/* * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import FirebaseRemoteConfig import FirebaseRemoteConfigSwift import XCTest #if compiler(>=5.5.2) && canImport(_Concurrency) @available(iOS 14.0, macOS 11.0, macCatalyst 14.0, tvOS 14.0, watchOS 7.0, *) class PropertyWrapperTests: APITestBase { // MARK: - Test fetching Remote Config JSON values into struct property struct Recipe: Decodable { var recipeName: String var ingredients: [String] var cookTime: Int } static let fallbackString = "fallback" static let fallbackInt = 50 static let fallbackFloat: Float = 50.2 static let fallbackDouble: Double = 16_777_216.333921 static let fallbackDecimal: Decimal = 235 static let fallbackData = "hello".data(using: .utf8)! static let fallbackArray = ["mango", "pineapple", "papaya"] static let fallbackDict = [ "session 0": "breakfast", "session 1": "keynote", "session 2": "state of union", ] static let fallbackJSON = Recipe( recipeName: "muffin", ingredients: ["flour", "sugar"], cookTime: 45 ) struct PropertyWrapperTester { @RemoteConfigProperty(key: Constants.stringKey, fallback: "") var stringValue: String! var stringKeyName: String { return _stringValue.key } @RemoteConfigProperty(key: Constants.intKey, fallback: 0) var intValue: Int! var intKeyName: String { return _intValue.key } @RemoteConfigProperty(key: Constants.floatKey, fallback: 0) var floatValue: Float! var floatKeyName: String { return _floatValue.key } @RemoteConfigProperty(key: Constants.floatKey, fallback: 0) var doubleValue: Double! var doubleKeyName: String { return _doubleValue.key } @RemoteConfigProperty(key: Constants.decimalKey, fallback: 0) var decimalValue: Decimal! var decimalKeyName: String { return _decimalValue.key } @RemoteConfigProperty(key: Constants.trueKey, fallback: false) var trueValue: Bool! var trueKeyName: String { return _trueValue.key } @RemoteConfigProperty(key: Constants.falseKey, fallback: false) var falseValue: Bool! var falseKeyName: String { return _falseValue.key } @RemoteConfigProperty(key: Constants.dataKey, fallback: Data()) var dataValue: Data! var dataKeyName: String { return _dataValue.key } @RemoteConfigProperty(key: Constants.jsonKey, fallback: nil) var recipeValue: Recipe! var recipeKeyName: String { _recipeValue.key } @RemoteConfigProperty(key: Constants.arrayKey, fallback: []) var arrayValue: [String]! var arrayKeyName: String { _arrayValue.key } @RemoteConfigProperty(key: Constants.dictKey, fallback: [:]) var dictValue: [String: String]! var dictKeyName: String { _dictValue.key } } struct PlaceholderValueTester { @RemoteConfigProperty(key: "NewKeyNotInSystem", fallback: fallbackString) var stringValue: String @RemoteConfigProperty(key: "NewIntKeyNotInSystem", fallback: fallbackInt) var intValue: Int! @RemoteConfigProperty(key: "NewZeroKey", fallback: 0) var zeroIntValue: Int! @RemoteConfigProperty(key: "newFloatKey", fallback: fallbackFloat) var floatValue: Float! @RemoteConfigProperty(key: "newDoubleKey", fallback: fallbackDouble) var doubleValue: Double! @RemoteConfigProperty(key: "newDecimalKey", fallback: fallbackDecimal) var decimalValue: Decimal! @RemoteConfigProperty(key: "newTrueKey", fallback: false) var trueKeyFalseValue: Bool! @RemoteConfigProperty(key: "newTrueKey2", fallback: true) var trueKeyTrueValue: Bool! @RemoteConfigProperty(key: "newFalseKey", fallback: true) var falseKeyTrueValue: Bool! @RemoteConfigProperty(key: "newFalseKey2", fallback: false) var falseKeyFalseValue: Bool! @RemoteConfigProperty(key: "newDataKey", fallback: fallbackData) var dataValue: Data @RemoteConfigProperty(key: "newJSONKey", fallback: fallbackJSON) var recipeValue: Recipe! @RemoteConfigProperty(key: "newArrayKey", fallback: fallbackArray) var arrayValue: [String]! @RemoteConfigProperty(key: "newDictKey", fallback: fallbackDict) var dictValue: [String: String]! } func testFetchAndActivateWithPropertyWrapper() async throws { let status = try await config.fetchAndActivate() XCTAssertEqual(status, .successFetchedFromRemote) let tester = await PropertyWrapperTester() let stringValue = await tester.stringValue XCTAssertEqual(stringValue, Constants.stringValue) let intValue = await tester.intValue XCTAssertEqual(intValue, Constants.intValue) let floatValue = await tester.floatValue XCTAssertEqual(floatValue, Constants.floatValue) let doubleValue = await tester.doubleValue XCTAssertEqual(doubleValue, Constants.doubleValue) let decimalValue = await tester.decimalValue XCTAssertEqual(decimalValue, Constants.decimalValue) let trueValue = await tester.trueValue XCTAssertEqual(trueValue, true) let falseValue = await tester.falseValue XCTAssertEqual(falseValue, false) let dataValue = await tester.dataValue XCTAssertEqual(dataValue, Constants.dataValue) let recipe = try XCTUnwrap(config[Constants.jsonKey].decoded(asType: Recipe.self)) let recipeValue = await tester.recipeValue XCTAssertEqual(recipeValue?.recipeName, recipe.recipeName) XCTAssertEqual(recipeValue?.ingredients, recipe.ingredients) XCTAssertEqual(recipeValue?.cookTime, recipe.cookTime) let arrayValue = await tester.arrayValue XCTAssertEqual(arrayValue, Constants.arrayValue) let dictValue = await tester.dictValue XCTAssertEqual(dictValue, Constants.dictValue) } func testPropertyWrapperInstanceValues() async { let tester = await PropertyWrapperTester() let stringKeyName = await tester.stringKeyName XCTAssertEqual(Constants.stringKey, stringKeyName) let intKeyName = await tester.intKeyName XCTAssertEqual(Constants.intKey, intKeyName) let floatKeyName = await tester.floatKeyName XCTAssertEqual(Constants.floatKey, floatKeyName) let doubleKeyName = await tester.doubleKeyName XCTAssertEqual(Constants.floatKey, doubleKeyName) let decimalKeyName = await tester.decimalKeyName XCTAssertEqual(Constants.decimalKey, decimalKeyName) let trueKeyName = await tester.trueKeyName XCTAssertEqual(Constants.trueKey, trueKeyName) let falseKeyName = await tester.falseKeyName XCTAssertEqual(Constants.falseKey, falseKeyName) let dataKeyName = await tester.dataKeyName XCTAssertEqual(Constants.dataKey, dataKeyName) let recipeKeyName = await tester.recipeKeyName XCTAssertEqual(Constants.jsonKey, recipeKeyName) let arrayKeyName = await tester.arrayKeyName XCTAssertEqual(Constants.arrayKey, arrayKeyName) let dictKeyName = await tester.dictKeyName XCTAssertEqual(Constants.dictKey, dictKeyName) } func testPlaceHolderValues() async throws { // Make sure the values below are consistent with the property wrapper // in PlaceholderValueTester let tester = await PlaceholderValueTester() let stringValue = await tester.stringValue XCTAssertEqual(stringValue, PropertyWrapperTests.fallbackString) let intValue = await tester.intValue XCTAssertEqual(intValue, PropertyWrapperTests.fallbackInt) let zeroValue = await tester.zeroIntValue XCTAssertEqual(zeroValue, 0) let floatValue = await tester.floatValue XCTAssertEqual(floatValue, PropertyWrapperTests.fallbackFloat) let doubleValue = await tester.doubleValue XCTAssertEqual(doubleValue, PropertyWrapperTests.fallbackDouble) let decimalValue = await tester.decimalValue XCTAssertEqual(decimalValue, PropertyWrapperTests.fallbackDecimal) let trueKeyFalseValue = await tester.trueKeyFalseValue XCTAssertEqual(trueKeyFalseValue, false) let trueKeyTrueValue = await tester.trueKeyTrueValue XCTAssertEqual(trueKeyTrueValue, true) let falseKeyTrueValue = await tester.falseKeyTrueValue XCTAssertEqual(falseKeyTrueValue, true) let falseKeyFalseValue = await tester.falseKeyFalseValue XCTAssertEqual(falseKeyFalseValue, false) let dataValue = await tester.dataValue XCTAssertEqual(dataValue, PropertyWrapperTests.fallbackData) let arrayValue = await tester.arrayValue XCTAssertEqual(arrayValue, PropertyWrapperTests.fallbackArray) let dictValue = await tester.dictValue XCTAssertEqual(dictValue, PropertyWrapperTests.fallbackDict) let recipeValue = await tester.recipeValue XCTAssertEqual(recipeValue?.recipeName, "muffin") XCTAssertEqual(recipeValue?.ingredients, ["flour", "sugar"]) XCTAssertEqual(recipeValue?.cookTime, 45) } } #endif