Granularize app features (#671)
Split .networkSettings and add .sharing for #668
This commit is contained in:
parent
63b0199a39
commit
0917e47ea3
|
@ -71,6 +71,7 @@
|
|||
/* Begin PBXFileReference section */
|
||||
0E06D18F2B87629100176E1D /* Passepartout.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Passepartout.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0E7C3CCC2C9AF44600B72E69 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
0E7D0EAD2CAEA47700A2F28D /* Passepartout.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = Passepartout.xctestplan; sourceTree = "<group>"; };
|
||||
0E7E3D5B2B9345FD002BBDB4 /* App.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = "<group>"; };
|
||||
0E7E3D5C2B9345FD002BBDB4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
0E7E3D5F2B9345FD002BBDB4 /* PassepartoutApp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PassepartoutApp.swift; sourceTree = "<group>"; };
|
||||
|
@ -152,6 +153,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
0E8D852F2C328CA1005493DE /* Config.xcconfig */,
|
||||
0E7D0EAD2CAEA47700A2F28D /* Passepartout.xctestplan */,
|
||||
0E7E3D5A2B9345FD002BBDB4 /* App */,
|
||||
0EDE56E82CABE40D0082D21C /* Intents */,
|
||||
0E7E3D612B9345FD002BBDB4 /* Shared */,
|
||||
|
|
|
@ -26,8 +26,13 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<TestPlans>
|
||||
<TestPlanReference
|
||||
reference = "container:Passepartout/Passepartout.xctestplan"
|
||||
default = "YES">
|
||||
</TestPlanReference>
|
||||
</TestPlans>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
|
|
|
@ -25,24 +25,33 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
public enum AppFeature: String, CaseIterable {
|
||||
public enum AppFeature: String {
|
||||
case appleTV
|
||||
|
||||
case interactiveLogin
|
||||
case dns
|
||||
|
||||
case networkSettings
|
||||
case httpProxy
|
||||
|
||||
case interactiveLogin
|
||||
|
||||
case onDemand
|
||||
|
||||
case providers
|
||||
|
||||
case routing
|
||||
|
||||
case sharing
|
||||
|
||||
case siri
|
||||
|
||||
public static let allCases: [AppFeature] = [
|
||||
public static let fullVersionFeaturesV2: [AppFeature] = [
|
||||
.dns,
|
||||
.httpProxy,
|
||||
.interactiveLogin,
|
||||
.networkSettings,
|
||||
.onDemand,
|
||||
.providers,
|
||||
.routing,
|
||||
.sharing,
|
||||
.siri
|
||||
]
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ extension AppProduct: AppFeatureProviding {
|
|||
return [.appleTV]
|
||||
|
||||
case .Features.networkSettings:
|
||||
return [.networkSettings]
|
||||
return [.dns, .httpProxy, .routing]
|
||||
|
||||
case .Features.siriShortcuts:
|
||||
return [.siri]
|
||||
|
@ -90,18 +90,18 @@ extension AppProduct: AppFeatureProviding {
|
|||
return [.onDemand]
|
||||
|
||||
case .Full.allPlatforms:
|
||||
return AppFeature.allCases
|
||||
return AppFeature.fullVersionFeaturesV2
|
||||
|
||||
case .Full.iOS:
|
||||
#if os(iOS)
|
||||
return AppFeature.allCases
|
||||
return AppFeature.fullVersionFeaturesV2
|
||||
#else
|
||||
return []
|
||||
#endif
|
||||
|
||||
case .Full.macOS:
|
||||
#if os(macOS)
|
||||
return AppFeature.allCases
|
||||
return AppFeature.fullVersionFeaturesV2
|
||||
#else
|
||||
return []
|
||||
#endif
|
||||
|
|
|
@ -29,10 +29,10 @@ extension AppUserLevel: AppFeatureProviding {
|
|||
var features: [AppFeature] {
|
||||
switch self {
|
||||
case .fullVersion:
|
||||
return AppFeature.allCases
|
||||
return AppFeature.fullVersionFeaturesV2
|
||||
|
||||
case .fullVersionPlusTV:
|
||||
var list = AppFeature.allCases
|
||||
var list = AppFeature.fullVersionFeaturesV2
|
||||
list.append(.appleTV)
|
||||
return list
|
||||
|
||||
|
|
|
@ -103,11 +103,17 @@ private extension ProfileCoordinator {
|
|||
private extension ProfileCoordinator {
|
||||
func onNewModule(_ moduleType: ModuleType) {
|
||||
switch moduleType {
|
||||
case .onDemand:
|
||||
break
|
||||
case .dns:
|
||||
paywallReason = iapManager.paywallReason(forFeature: .dns)
|
||||
|
||||
default:
|
||||
paywallReason = iapManager.paywallReason(forFeature: .networkSettings)
|
||||
case .httpProxy:
|
||||
paywallReason = iapManager.paywallReason(forFeature: .httpProxy)
|
||||
|
||||
case .ip:
|
||||
paywallReason = iapManager.paywallReason(forFeature: .routing)
|
||||
|
||||
case .onDemand, .openVPN, .wireGuard:
|
||||
break
|
||||
}
|
||||
guard paywallReason == nil else {
|
||||
return
|
||||
|
|
|
@ -62,7 +62,7 @@ extension ConnectionObserverTests {
|
|||
XCTAssertEqual(sut.dataCount, nil)
|
||||
|
||||
try await tunnel.install(profile, connect: true, title: \.name)
|
||||
try await Task.sleep(for: .milliseconds(200))
|
||||
try await Task.sleep(for: .milliseconds(300))
|
||||
XCTAssertEqual(sut.dataCount, dataCount)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ extension IAPManagerTests {
|
|||
return []
|
||||
}
|
||||
await sut.reloadReceipt()
|
||||
XCTAssertTrue(sut.isEligible(for: AppFeature.allCases))
|
||||
XCTAssertTrue(sut.isEligible(for: AppFeature.fullVersionFeaturesV2))
|
||||
}
|
||||
|
||||
func test_givenBuildProducts_whenNewer_thenFreeVersion() async {
|
||||
|
@ -65,7 +65,7 @@ extension IAPManagerTests {
|
|||
return []
|
||||
}
|
||||
await sut.reloadReceipt()
|
||||
XCTAssertFalse(sut.isEligible(for: AppFeature.allCases))
|
||||
XCTAssertFalse(sut.isEligible(for: AppFeature.fullVersionFeaturesV2))
|
||||
}
|
||||
|
||||
// MARK: Eligibility
|
||||
|
@ -74,13 +74,13 @@ extension IAPManagerTests {
|
|||
let reader = MockReceiptReader()
|
||||
let sut = IAPManager(receiptReader: reader)
|
||||
|
||||
XCTAssertFalse(sut.isEligible(for: AppFeature.allCases))
|
||||
XCTAssertFalse(sut.isEligible(for: AppFeature.fullVersionFeaturesV2))
|
||||
|
||||
await reader.setReceipt(withBuild: defaultBuildNumber, products: [.Full.allPlatforms])
|
||||
XCTAssertFalse(sut.isEligible(for: AppFeature.allCases))
|
||||
XCTAssertFalse(sut.isEligible(for: AppFeature.fullVersionFeaturesV2))
|
||||
|
||||
await sut.reloadReceipt()
|
||||
XCTAssertTrue(sut.isEligible(for: AppFeature.allCases))
|
||||
XCTAssertTrue(sut.isEligible(for: AppFeature.fullVersionFeaturesV2))
|
||||
}
|
||||
|
||||
func test_givenPurchasedFeatures_thenIsOnlyEligibleForFeatures() async {
|
||||
|
@ -92,10 +92,13 @@ extension IAPManagerTests {
|
|||
let sut = IAPManager(receiptReader: reader)
|
||||
|
||||
await sut.reloadReceipt()
|
||||
XCTAssertTrue(sut.isEligible(for: .siri))
|
||||
XCTAssertTrue(sut.isEligible(for: .networkSettings))
|
||||
XCTAssertTrue(sut.isEligible(for: .dns))
|
||||
XCTAssertTrue(sut.isEligible(for: .httpProxy))
|
||||
XCTAssertFalse(sut.isEligible(for: .onDemand))
|
||||
XCTAssertFalse(sut.isEligible(for: AppFeature.allCases))
|
||||
XCTAssertTrue(sut.isEligible(for: .routing))
|
||||
XCTAssertFalse(sut.isEligible(for: .sharing))
|
||||
XCTAssertTrue(sut.isEligible(for: .siri))
|
||||
XCTAssertFalse(sut.isEligible(for: AppFeature.fullVersionFeaturesV2))
|
||||
}
|
||||
|
||||
func test_givenPurchasedAndCancelledFeature_thenIsNotEligible() async {
|
||||
|
@ -108,7 +111,7 @@ extension IAPManagerTests {
|
|||
let sut = IAPManager(receiptReader: reader)
|
||||
|
||||
await sut.reloadReceipt()
|
||||
XCTAssertFalse(sut.isEligible(for: AppFeature.allCases))
|
||||
XCTAssertFalse(sut.isEligible(for: AppFeature.fullVersionFeaturesV2))
|
||||
}
|
||||
|
||||
func test_givenFreeVersion_thenIsNotEligibleForAnyFeature() async {
|
||||
|
@ -118,7 +121,7 @@ extension IAPManagerTests {
|
|||
|
||||
await sut.reloadReceipt()
|
||||
XCTAssertFalse(sut.userLevel.isFullVersion)
|
||||
AppFeature.allCases.forEach {
|
||||
AppFeature.fullVersionFeaturesV2.forEach {
|
||||
XCTAssertFalse(sut.isEligible(for: $0))
|
||||
}
|
||||
}
|
||||
|
@ -138,7 +141,7 @@ extension IAPManagerTests {
|
|||
let sut = IAPManager(receiptReader: reader)
|
||||
|
||||
await sut.reloadReceipt()
|
||||
AppFeature.allCases.forEach {
|
||||
AppFeature.fullVersionFeaturesV2.forEach {
|
||||
XCTAssertTrue(sut.isEligible(for: $0))
|
||||
}
|
||||
XCTAssertFalse(sut.isEligible(for: .appleTV))
|
||||
|
@ -160,11 +163,11 @@ extension IAPManagerTests {
|
|||
#if os(macOS)
|
||||
await reader.setReceipt(withBuild: defaultBuildNumber, products: [.Full.macOS, .Features.networkSettings])
|
||||
await sut.reloadReceipt()
|
||||
XCTAssertTrue(sut.isEligible(for: AppFeature.allCases))
|
||||
XCTAssertTrue(sut.isEligible(for: AppFeature.fullVersionFeaturesV2))
|
||||
#else
|
||||
await reader.setReceipt(withBuild: defaultBuildNumber, products: [.Full.iOS, .Features.networkSettings])
|
||||
await sut.reloadReceipt()
|
||||
XCTAssertTrue(sut.isEligible(for: AppFeature.allCases))
|
||||
XCTAssertTrue(sut.isEligible(for: AppFeature.fullVersionFeaturesV2))
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -175,11 +178,11 @@ extension IAPManagerTests {
|
|||
#if os(macOS)
|
||||
await reader.setReceipt(withBuild: defaultBuildNumber, products: [.Full.iOS, .Features.networkSettings])
|
||||
await sut.reloadReceipt()
|
||||
XCTAssertFalse(sut.isEligible(for: AppFeature.allCases))
|
||||
XCTAssertFalse(sut.isEligible(for: AppFeature.fullVersionFeaturesV2))
|
||||
#else
|
||||
await reader.setReceipt(withBuild: defaultBuildNumber, products: [.Full.macOS, .Features.networkSettings])
|
||||
await sut.reloadReceipt()
|
||||
XCTAssertFalse(sut.isEligible(for: AppFeature.allCases))
|
||||
XCTAssertFalse(sut.isEligible(for: AppFeature.fullVersionFeaturesV2))
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -264,7 +267,7 @@ extension IAPManagerTests {
|
|||
let sut = IAPManager(customUserLevel: .beta, receiptReader: reader)
|
||||
|
||||
await sut.reloadReceipt()
|
||||
XCTAssertFalse(sut.isEligible(for: AppFeature.allCases))
|
||||
XCTAssertFalse(sut.isEligible(for: AppFeature.fullVersionFeaturesV2))
|
||||
}
|
||||
|
||||
func test_givenBetaApp_thenIsEligibleForUnrestrictedFeature() async {
|
||||
|
@ -272,7 +275,7 @@ extension IAPManagerTests {
|
|||
let sut = IAPManager(customUserLevel: .beta, receiptReader: reader, unrestrictedFeatures: [.onDemand])
|
||||
|
||||
await sut.reloadReceipt()
|
||||
AppFeature.allCases.forEach {
|
||||
AppFeature.fullVersionFeaturesV2.forEach {
|
||||
if $0 == .onDemand {
|
||||
XCTAssertTrue(sut.isEligible(for: $0))
|
||||
} else {
|
||||
|
@ -302,7 +305,7 @@ extension IAPManagerTests {
|
|||
let sut = IAPManager(customUserLevel: .fullVersion, receiptReader: reader)
|
||||
|
||||
await sut.reloadReceipt()
|
||||
AppFeature.allCases.forEach {
|
||||
AppFeature.fullVersionFeaturesV2.forEach {
|
||||
XCTAssertTrue(sut.isEligible(for: $0))
|
||||
}
|
||||
XCTAssertFalse(sut.isEligible(for: .appleTV))
|
||||
|
@ -313,7 +316,7 @@ extension IAPManagerTests {
|
|||
let sut = IAPManager(customUserLevel: .fullVersionPlusTV, receiptReader: reader)
|
||||
|
||||
await sut.reloadReceipt()
|
||||
AppFeature.allCases.forEach {
|
||||
AppFeature.fullVersionFeaturesV2.forEach {
|
||||
XCTAssertTrue(sut.isEligible(for: $0))
|
||||
}
|
||||
XCTAssertTrue(sut.isEligible(for: .appleTV))
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"configurations" : [
|
||||
{
|
||||
"id" : "880EB747-73AE-45F8-B6D3-95D06B161AB1",
|
||||
"name" : "Configuration 1",
|
||||
"options" : {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
"defaultOptions" : {
|
||||
"testTimeoutsEnabled" : true
|
||||
},
|
||||
"testTargets" : [
|
||||
{
|
||||
"target" : {
|
||||
"containerPath" : "container:Passepartout\/Library",
|
||||
"identifier" : "AppLibraryTests",
|
||||
"name" : "AppLibraryTests"
|
||||
}
|
||||
},
|
||||
{
|
||||
"target" : {
|
||||
"containerPath" : "container:Passepartout\/Library",
|
||||
"identifier" : "AppUITests",
|
||||
"name" : "AppUITests"
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 1
|
||||
}
|
|
@ -44,7 +44,7 @@ extension IAPManager {
|
|||
customUserLevel: customUserLevel,
|
||||
receiptReader: KvittoReceiptReader(),
|
||||
// FIXME: #662, omit unrestrictedFeatures on release!
|
||||
unrestrictedFeatures: [.interactiveLogin],
|
||||
unrestrictedFeatures: [.interactiveLogin, .sharing],
|
||||
productsAtBuild: productsAtBuild
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue