Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Persist Debug Feature Flags #721

Merged
merged 6 commits into from
Jun 25, 2019
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ final class FeatureFlagToolsViewController: UITableViewController {

let updatedConfig = config |> \.features .~ features

AppEnvironment.updateDebugData(DebugData(config: updatedConfig))
AppEnvironment.updateConfig(updatedConfig)

self.viewModel.inputs.didUpdateConfig()
Expand Down
12 changes: 7 additions & 5 deletions Kickstarter.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,11 @@
77556F5720A0B41E008CEA57 /* ThanksViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77556F5520A0B408008CEA57 /* ThanksViewControllerTests.swift */; };
7758A8372097BADF0018B96D /* DiscoveryProjectCategoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7758A83120979BE50018B96D /* DiscoveryProjectCategoryView.swift */; };
7758A8382097BB090018B96D /* DiscoveryProjectCategoryView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7758A8352097A8180018B96D /* DiscoveryProjectCategoryView.xib */; };
775D922922BD7CFD00442301 /* DebugData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 775D922822BD7CFD00442301 /* DebugData.swift */; };
776B6F70215183A400AB0652 /* ChangeEmailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 776B6F6F215183A400AB0652 /* ChangeEmailViewController.swift */; };
77752F5E219B39EA00E7DA7D /* SettingsAccountWarningCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77752F5D219B39EA00E7DA7D /* SettingsAccountWarningCell.swift */; };
77752F97219B3D7300E7DA7D /* SettingsAccountWarningCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 77752F96219B3D7300E7DA7D /* SettingsAccountWarningCell.xib */; };
777B88E522BD911F0027640F /* CategoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6FB2A3C1FA27D0300B0D282 /* CategoryTests.swift */; };
777C67BB220A0FA5009F8D42 /* SettingsTableViewHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 777C67BA220A0FA5009F8D42 /* SettingsTableViewHeader.swift */; };
777C67F4220A22FD009F8D42 /* SettingsTableViewHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = 777C67F3220A22FD009F8D42 /* SettingsTableViewHeader.xib */; };
778215E820F6922100F3D09F /* HelpType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A707BAD31CFFAB9400653B2F /* HelpType.swift */; };
Expand Down Expand Up @@ -648,7 +650,6 @@
A7FA38A41D9068940041FC9C /* PledgeTitleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7FA38A31D9068940041FC9C /* PledgeTitleCell.swift */; };
A7FA38D91D9068AD0041FC9C /* RewardsTitleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7FA38D81D9068AD0041FC9C /* RewardsTitleCell.swift */; };
A7FC8C061C8F1DEA00C3B49B /* CircleAvatarImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7FC8C051C8F1DEA00C3B49B /* CircleAvatarImageView.swift */; };
D002CADF218CF8B7009783F2 /* CategoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01587801EEB2ED6006E7684 /* CategoryTests.swift */; };
D002CAE1218CF8F1009783F2 /* WatchProjectMutation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D002CAE0218CF8F1009783F2 /* WatchProjectMutation.swift */; };
D002CAE3218CF91D009783F2 /* WatchProjectInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = D002CAE2218CF91D009783F2 /* WatchProjectInput.swift */; };
D002CAE5218CF951009783F2 /* GraphMutationWatchProjectResponseEnvelope.swift in Sources */ = {isa = PBXBuildFile; fileRef = D002CAE4218CF951009783F2 /* GraphMutationWatchProjectResponseEnvelope.swift */; };
Expand Down Expand Up @@ -1456,6 +1457,7 @@
77556F5520A0B408008CEA57 /* ThanksViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThanksViewControllerTests.swift; sourceTree = "<group>"; };
7758A83120979BE50018B96D /* DiscoveryProjectCategoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscoveryProjectCategoryView.swift; sourceTree = "<group>"; };
7758A8352097A8180018B96D /* DiscoveryProjectCategoryView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DiscoveryProjectCategoryView.xib; sourceTree = "<group>"; };
775D922822BD7CFD00442301 /* DebugData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugData.swift; sourceTree = "<group>"; };
775DFA9C215E758400620CED /* GraphMutation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphMutation.swift; sourceTree = "<group>"; };
775DFAD4215EB2AB00620CED /* Service+RequestHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Service+RequestHelpers.swift"; sourceTree = "<group>"; };
776B6F6F215183A400AB0652 /* ChangeEmailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeEmailViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1951,7 +1953,6 @@
D015877B1EEB2ED6006E7684 /* ActivityTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivityTests.swift; sourceTree = "<group>"; };
D015877C1EEB2ED6006E7684 /* Backing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Backing.swift; sourceTree = "<group>"; };
D015877D1EEB2ED6006E7684 /* BackingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackingTests.swift; sourceTree = "<group>"; };
D01587801EEB2ED6006E7684 /* CategoryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CategoryTests.swift; sourceTree = "<group>"; };
D01587811EEB2ED6006E7684 /* ChangePaymentMethodEnvelope.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChangePaymentMethodEnvelope.swift; sourceTree = "<group>"; };
D01587821EEB2ED6006E7684 /* ChangePaymentMethodEnvelopeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChangePaymentMethodEnvelopeTests.swift; sourceTree = "<group>"; };
D01587831EEB2ED6006E7684 /* CheckoutEnvelope.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckoutEnvelope.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3483,8 +3484,8 @@
D015877C1EEB2ED6006E7684 /* Backing.swift */,
D015877D1EEB2ED6006E7684 /* BackingTests.swift */,
D6B9DF3E1F72E25A0064A4D8 /* Category.swift */,
D6FB2A3C1FA27D0300B0D282 /* CategoryTests.swift */,
D6AE52271FD1B4BA00BEC788 /* CategoryEnvelope.swift */,
D01587801EEB2ED6006E7684 /* CategoryTests.swift */,
D01587811EEB2ED6006E7684 /* ChangePaymentMethodEnvelope.swift */,
D01587821EEB2ED6006E7684 /* ChangePaymentMethodEnvelopeTests.swift */,
D01587831EEB2ED6006E7684 /* CheckoutEnvelope.swift */,
Expand All @@ -3500,6 +3501,7 @@
D79440562203A63300D0A747 /* CreatePaymentSourceEnvelope.swift */,
D015878A1EEB2ED6006E7684 /* CreatePledgeEnvelope.swift */,
D015878B1EEB2ED6006E7684 /* CreatePledgeEnvelopeTests.swift */,
775D922822BD7CFD00442301 /* DebugData.swift */,
D62B1476221216A000AC05C8 /* DeletePaymentMethodEnvelope.swift */,
D62B14AF2212184500AC05C8 /* DeletePaymentMethodEnvelopeTests.swift */,
D015878C1EEB2ED6006E7684 /* DiscoveryEnvelope.swift */,
Expand Down Expand Up @@ -3574,7 +3576,6 @@
D01588251EEB2ED7006E7684 /* VoidEnvelope.swift */,
D01587971EEB2ED6006E7684 /* lenses */,
D01587EE1EEB2ED7006E7684 /* templates */,
D6FB2A3C1FA27D0300B0D282 /* CategoryTests.swift */,
);
path = models;
sourceTree = "<group>";
Expand Down Expand Up @@ -5076,6 +5077,7 @@
D015891F1EEB2ED7006E7684 /* ShippingRulesEnvelope.swift in Sources */,
D01588831EEB2ED7006E7684 /* BackingLenses.swift in Sources */,
D01588C51EEB2ED7006E7684 /* Reward.ShippingLenses.swift in Sources */,
775D922922BD7CFD00442301 /* DebugData.swift in Sources */,
D01588D51EEB2ED7006E7684 /* UpdateDraftLenses.swift in Sources */,
D01589211EEB2ED7006E7684 /* StarEnvelope.swift in Sources */,
D01588EF1EEB2ED7006E7684 /* MessageThread.swift in Sources */,
Expand Down Expand Up @@ -5224,7 +5226,6 @@
D0D10C101EEB4550005EBAD0 /* MessageTests.swift in Sources */,
D0D10C151EEB4550005EBAD0 /* ProjectStatsEnvelopeTests.swift in Sources */,
D0D10C221EEB4550005EBAD0 /* UserTests.swift in Sources */,
D002CADF218CF8B7009783F2 /* CategoryTests.swift in Sources */,
D0D10C171EEB4550005EBAD0 /* PushEnvelopeTests.swift in Sources */,
D0D10C1D1EEB4550005EBAD0 /* UpdatePledgeEnvelopeTests.swift in Sources */,
D0D10C0E1EEB4550005EBAD0 /* ItemTests.swift in Sources */,
Expand All @@ -5236,6 +5237,7 @@
D0D10C111EEB4550005EBAD0 /* MessageThreadTests.swift in Sources */,
D0D10C161EEB4550005EBAD0 /* ProjectTests.swift in Sources */,
D0D10C1A1EEB4550005EBAD0 /* SubmitApplePayEnvelopeTests.swift in Sources */,
777B88E522BD911F0027640F /* CategoryTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
9 changes: 9 additions & 0 deletions KsApi/models/DebugData.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Foundation

public struct DebugData {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm just wondering if this should be a KsApi model... it's really just a wrapper type that we're using in the app, should perhaps just live in Library?

public let config: Config?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kept this as optional in case we want to add to the struct in the future.


public init(config: Config?) {
self.config = config
}
}
18 changes: 15 additions & 3 deletions Library/AppEnvironment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ public struct AppEnvironment: AppEnvironmentType {
)
}

public static func updateDebugData(_ debugData: DebugData) {
self.replaceCurrentEnvironment(
debugData: debugData
)
}

public static func updateServerConfig(_ config: ServerConfigType) {
let service = Service(serverConfig: config)

Expand All @@ -54,10 +60,12 @@ public struct AppEnvironment: AppEnvironmentType {
}

public static func updateConfig(_ config: Config) {
let debugConfigOrConfig = self.current.debugData?.config ?? config

self.replaceCurrentEnvironment(
config: config,
countryCode: config.countryCode,
koala: AppEnvironment.current.koala |> Koala.lens.config .~ config
config: debugConfigOrConfig,
countryCode: debugConfigOrConfig.countryCode,
koala: AppEnvironment.current.koala |> Koala.lens.config .~ debugConfigOrConfig
)
}

Expand Down Expand Up @@ -124,6 +132,7 @@ public struct AppEnvironment: AppEnvironmentType {
currentUser: User? = AppEnvironment.current.currentUser,
dateType: DateProtocol.Type = AppEnvironment.current.dateType,
debounceInterval: DispatchTimeInterval = AppEnvironment.current.debounceInterval,
debugData: DebugData? = AppEnvironment.current.debugData,
device: UIDeviceType = AppEnvironment.current.device,
isOSVersionAvailable: @escaping ((Double) -> Bool) = AppEnvironment.current.isOSVersionAvailable,
isVoiceOverRunning: @escaping (() -> Bool) = AppEnvironment.current.isVoiceOverRunning,
Expand Down Expand Up @@ -152,6 +161,7 @@ public struct AppEnvironment: AppEnvironmentType {
currentUser: currentUser,
dateType: dateType,
debounceInterval: debounceInterval,
debugData: debugData,
device: device,
isOSVersionAvailable: isOSVersionAvailable,
isVoiceOverRunning: isVoiceOverRunning,
Expand Down Expand Up @@ -184,6 +194,7 @@ public struct AppEnvironment: AppEnvironmentType {
currentUser: User? = AppEnvironment.current.currentUser,
dateType: DateProtocol.Type = AppEnvironment.current.dateType,
debounceInterval: DispatchTimeInterval = AppEnvironment.current.debounceInterval,
debugData: DebugData? = AppEnvironment.current.debugData,
device: UIDeviceType = AppEnvironment.current.device,
isOSVersionAvailable: @escaping ((Double) -> Bool) = AppEnvironment.current.isOSVersionAvailable,
isVoiceOverRunning: @escaping (() -> Bool) = AppEnvironment.current.isVoiceOverRunning,
Expand Down Expand Up @@ -212,6 +223,7 @@ public struct AppEnvironment: AppEnvironmentType {
currentUser: currentUser,
dateType: dateType,
debounceInterval: debounceInterval,
debugData: debugData,
device: device,
isOSVersionAvailable: isOSVersionAvailable,
isVoiceOverRunning: isVoiceOverRunning,
Expand Down
122 changes: 122 additions & 0 deletions Library/AppEnvironmentTests.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Foundation
@testable import KsApi
@testable import Library
import Prelude
import XCTest

final class AppEnvironmentTests: XCTestCase {
Expand Down Expand Up @@ -204,6 +205,7 @@ final class AppEnvironmentTests: XCTestCase {
ServerConfig.production.webBaseUrl.absoluteString,
env.apiService.serverConfig.webBaseUrl.absoluteString
)
XCTAssertEqual(EnvironmentType.production, env.apiService.serverConfig.environment)
XCTAssertEqual(currentUser, env.currentUser)
XCTAssertEqual(currentUser, env.koala.loggedInUser)
}
Expand Down Expand Up @@ -232,4 +234,124 @@ final class AppEnvironmentTests: XCTestCase {

AppEnvironment.popEnvironment()
}

func testUpdateServerConfig() {
AppEnvironment.pushEnvironment()

// Starts out as production environment
XCTAssertEqual(AppEnvironment.current.apiService.serverConfig.environment, .production)
XCTAssertEqual(
AppEnvironment.current.apiService.serverConfig.apiBaseUrl,
ServerConfig.production.apiBaseUrl
)
XCTAssertEqual(
AppEnvironment.current.apiService.serverConfig.webBaseUrl,
ServerConfig.production.webBaseUrl
)
XCTAssertEqual(
AppEnvironment.current.apiService.serverConfig.apiClientAuth.clientId,
ClientAuth.production.clientId
)
XCTAssertNil(AppEnvironment.current.apiService.serverConfig.basicHTTPAuth)
XCTAssertEqual(
AppEnvironment.current.apiService.serverConfig.graphQLEndpointUrl,
ServerConfig.production.graphQLEndpointUrl
)

let serverConfig = ServerConfig.staging

AppEnvironment.updateServerConfig(serverConfig)

// Updates all properties to staging environment
XCTAssertEqual(AppEnvironment.current.apiService.serverConfig.environment, .staging)
XCTAssertEqual(AppEnvironment.current.apiService.serverConfig.apiBaseUrl, ServerConfig.staging.apiBaseUrl)
XCTAssertEqual(AppEnvironment.current.apiService.serverConfig.webBaseUrl, ServerConfig.staging.webBaseUrl)
XCTAssertEqual(
AppEnvironment.current.apiService.serverConfig.apiClientAuth.clientId,
ClientAuth.development.clientId
)
XCTAssertEqual(
AppEnvironment.current.apiService.serverConfig.basicHTTPAuth?.username,
BasicHTTPAuth.development.username
)
XCTAssertEqual(
AppEnvironment.current.apiService.serverConfig.basicHTTPAuth?.password,
BasicHTTPAuth.development.password
)
XCTAssertEqual(
AppEnvironment.current.apiService.serverConfig.graphQLEndpointUrl,
ServerConfig.staging.graphQLEndpointUrl
)

AppEnvironment.popEnvironment()
}

func testUpdateDebugData() {
AppEnvironment.pushEnvironment()

XCTAssertNil(AppEnvironment.current.debugData)

let debugConfig = Config.template
|> \.features .~ ["hello": true]

AppEnvironment.updateDebugData(DebugData(config: debugConfig))

XCTAssertEqual(AppEnvironment.current.debugData?.config, debugConfig)

AppEnvironment.popEnvironment()
}

func testUpdateConfig_nilDebugData() {
AppEnvironment.pushEnvironment()

XCTAssertNil(AppEnvironment.current.debugData)
XCTAssertNil(AppEnvironment.current.config)
XCTAssertEqual(AppEnvironment.current.countryCode, "US")

let config = Config.template
|> \.countryCode .~ "CA"
|> \.features .~ ["hello": true]

AppEnvironment.updateConfig(config)

XCTAssertEqual(AppEnvironment.current.config, config)
XCTAssertEqual(AppEnvironment.current.countryCode, "CA")

AppEnvironment.popEnvironment()
}

func testUpdateConfig_nonNilDebugData() {
AppEnvironment.pushEnvironment()

XCTAssertNil(AppEnvironment.current.debugData)
XCTAssertNil(AppEnvironment.current.config)
XCTAssertEqual(AppEnvironment.current.countryCode, "US")

let debugConfig = Config.template
|> \.countryCode .~ "CA"
|> \.features .~ ["hello": true]

AppEnvironment.pushEnvironment(debugData: DebugData(config: debugConfig))

XCTAssertNotNil(AppEnvironment.current.debugData)

AppEnvironment.updateConfig(Config.template)

XCTAssertEqual(AppEnvironment.current.config, debugConfig)
XCTAssertEqual(AppEnvironment.current.countryCode, "CA")

AppEnvironment.popEnvironment()
}

func testUpdateLanguage() {
AppEnvironment.pushEnvironment()

XCTAssertEqual(AppEnvironment.current.language, .en)

AppEnvironment.updateLanguage(.fr)

XCTAssertEqual(AppEnvironment.current.language, .fr)

AppEnvironment.popEnvironment()
}
}
5 changes: 5 additions & 0 deletions Library/Environment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ public struct Environment {
/// The amount of time to debounce signals by. Default value is `0.3`.
public let debounceInterval: DispatchTimeInterval

/// Stored data used for debugging tools
public let debugData: DebugData?

/// The current device running the app.
public let device: UIDeviceType

Expand Down Expand Up @@ -106,6 +109,7 @@ public struct Environment {
currentUser: User? = nil,
dateType: DateProtocol.Type = Date.self,
debounceInterval: DispatchTimeInterval = .milliseconds(300),
debugData: DebugData? = nil,
device: UIDeviceType = UIDevice.current,
environmentVariables: EnvironmentVariables = EnvironmentVariables(),
isOSVersionAvailable: @escaping (Double) -> Bool = ksr_isOSVersionAvailable,
Expand Down Expand Up @@ -133,6 +137,7 @@ public struct Environment {
self.currentUser = currentUser
self.dateType = dateType
self.debounceInterval = debounceInterval
self.debugData = debugData
self.device = device
self.environmentVariables = environmentVariables
self.isOSVersionAvailable = isOSVersionAvailable
Expand Down