diff --git a/Bender.xcodeproj/project.pbxproj b/Bender.xcodeproj/project.pbxproj index 855add0..ac8fbb7 100644 --- a/Bender.xcodeproj/project.pbxproj +++ b/Bender.xcodeproj/project.pbxproj @@ -7,7 +7,8 @@ objects = { /* Begin PBXBuildFile section */ - 45AB6AA5124B320B85642C6E /* Pods_BenderTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C08819D4FBCAAE3080F148B /* Pods_BenderTests.framework */; }; + 066065F19EDFC950FBE56C95 /* Pods_Bender.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 614618C363A461993C6EDB53 /* Pods_Bender.framework */; }; + 0B3413824AA52CD1BC67DF98 /* Pods_BenderTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72EA5682B17BC9F7E636C477 /* Pods_BenderTests.framework */; }; 5B05ABA91C54F71100339915 /* BenderOutputTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B05ABA81C54F71100339915 /* BenderOutputTests.swift */; }; 5B3C4B3E1C7A6A070032BA13 /* defaults_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 5B3C4B3D1C7A6A070032BA13 /* defaults_test.json */; }; 5B54EF0B1C3A90AE0072B2A8 /* Bender.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B54EF001C3A90AE0072B2A8 /* Bender.framework */; }; @@ -22,6 +23,8 @@ 5BAEB5121C47D0480044C0A7 /* recursive_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 5BAEB5111C47D0480044C0A7 /* recursive_test.json */; }; 5BCE65501C7F9BF6000603ED /* array_skip_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 5BCE654F1C7F9BF6000603ED /* array_skip_test.json */; }; 5BCE65551C8326EB000603ED /* path_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 5BCE65541C8326EB000603ED /* path_test.json */; }; + BE143A241CEA2BF10092CC2B /* ref_rules_test.json in Resources */ = {isa = PBXBuildFile; fileRef = BE143A231CEA2BF10092CC2B /* ref_rules_test.json */; }; + BE24B6581CECB454002AE950 /* advanced_ref_rules_test.json in Resources */ = {isa = PBXBuildFile; fileRef = BE24B6571CECB454002AE950 /* advanced_ref_rules_test.json */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -35,7 +38,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 1C08819D4FBCAAE3080F148B /* Pods_BenderTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_BenderTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 22EDECB62B0AD84C81D2E86A /* Pods-Bender.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Bender.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Bender/Pods-Bender.debug.xcconfig"; sourceTree = ""; }; 5B05ABA81C54F71100339915 /* BenderOutputTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BenderOutputTests.swift; sourceTree = ""; }; 5B3C4B3D1C7A6A070032BA13 /* defaults_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = defaults_test.json; sourceTree = ""; }; 5B54EF001C3A90AE0072B2A8 /* Bender.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Bender.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -53,8 +56,13 @@ 5BAEB5111C47D0480044C0A7 /* recursive_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = recursive_test.json; sourceTree = ""; }; 5BCE654F1C7F9BF6000603ED /* array_skip_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = array_skip_test.json; sourceTree = ""; }; 5BCE65541C8326EB000603ED /* path_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = path_test.json; sourceTree = ""; }; - 6B17FF595E1FE853707766E6 /* Pods-BenderTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BenderTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-BenderTests/Pods-BenderTests.debug.xcconfig"; sourceTree = ""; }; - FF38713AA0E03EF651054F86 /* Pods-BenderTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BenderTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-BenderTests/Pods-BenderTests.release.xcconfig"; sourceTree = ""; }; + 614618C363A461993C6EDB53 /* Pods_Bender.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Bender.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 71269F45DC1611C747FE40B1 /* Pods-Bender.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Bender.release.xcconfig"; path = "Pods/Target Support Files/Pods-Bender/Pods-Bender.release.xcconfig"; sourceTree = ""; }; + 72EA5682B17BC9F7E636C477 /* Pods_BenderTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_BenderTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + BE143A231CEA2BF10092CC2B /* ref_rules_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ref_rules_test.json; sourceTree = ""; }; + BE24B6571CECB454002AE950 /* advanced_ref_rules_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = advanced_ref_rules_test.json; sourceTree = ""; }; + F5B570F8D430305680560ACF /* Pods-BenderTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BenderTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-BenderTests/Pods-BenderTests.debug.xcconfig"; sourceTree = ""; }; + F7E362DC0AB1E40434C24AA0 /* Pods-BenderTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BenderTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-BenderTests/Pods-BenderTests.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -62,6 +70,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 066065F19EDFC950FBE56C95 /* Pods_Bender.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -70,29 +79,21 @@ buildActionMask = 2147483647; files = ( 5B54EF0B1C3A90AE0072B2A8 /* Bender.framework in Frameworks */, - 45AB6AA5124B320B85642C6E /* Pods_BenderTests.framework in Frameworks */, + 0B3413824AA52CD1BC67DF98 /* Pods_BenderTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 3BEC423E6E3202A33D3E3466 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 1C08819D4FBCAAE3080F148B /* Pods_BenderTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; 5B54EEF61C3A90AE0072B2A8 = { isa = PBXGroup; children = ( 5B54EF021C3A90AE0072B2A8 /* Bender */, 5B54EF0E1C3A90AE0072B2A8 /* BenderTests */, 5B54EF011C3A90AE0072B2A8 /* Products */, - CF84E480FC05BA072782574B /* Pods */, - 3BEC423E6E3202A33D3E3466 /* Frameworks */, + 70944CADEF49F7B36D2E3D6E /* Pods */, + 834A2B6F8B5F7E73001F6DB4 /* Frameworks */, ); sourceTree = ""; }; @@ -130,19 +131,32 @@ 5BAEB5111C47D0480044C0A7 /* recursive_test.json */, 5B3C4B3D1C7A6A070032BA13 /* defaults_test.json */, 5BCE65541C8326EB000603ED /* path_test.json */, + BE143A231CEA2BF10092CC2B /* ref_rules_test.json */, + BE24B6571CECB454002AE950 /* advanced_ref_rules_test.json */, ); path = BenderTests; sourceTree = ""; }; - CF84E480FC05BA072782574B /* Pods */ = { + 70944CADEF49F7B36D2E3D6E /* Pods */ = { isa = PBXGroup; children = ( - 6B17FF595E1FE853707766E6 /* Pods-BenderTests.debug.xcconfig */, - FF38713AA0E03EF651054F86 /* Pods-BenderTests.release.xcconfig */, + 22EDECB62B0AD84C81D2E86A /* Pods-Bender.debug.xcconfig */, + 71269F45DC1611C747FE40B1 /* Pods-Bender.release.xcconfig */, + F5B570F8D430305680560ACF /* Pods-BenderTests.debug.xcconfig */, + F7E362DC0AB1E40434C24AA0 /* Pods-BenderTests.release.xcconfig */, ); name = Pods; sourceTree = ""; }; + 834A2B6F8B5F7E73001F6DB4 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 614618C363A461993C6EDB53 /* Pods_Bender.framework */, + 72EA5682B17BC9F7E636C477 /* Pods_BenderTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -160,10 +174,12 @@ isa = PBXNativeTarget; buildConfigurationList = 5B54EF141C3A90AE0072B2A8 /* Build configuration list for PBXNativeTarget "Bender" */; buildPhases = ( + A98F253D5F94CD7E0A204B47 /* 📦 Check Pods Manifest.lock */, 5B54EEFB1C3A90AE0072B2A8 /* Sources */, 5B54EEFC1C3A90AE0072B2A8 /* Frameworks */, 5B54EEFD1C3A90AE0072B2A8 /* Headers */, 5B54EEFE1C3A90AE0072B2A8 /* Resources */, + 63EEED299EBADB90672D806D /* 📦 Copy Pods Resources */, ); buildRules = ( ); @@ -178,12 +194,12 @@ isa = PBXNativeTarget; buildConfigurationList = 5B54EF171C3A90AE0072B2A8 /* Build configuration list for PBXNativeTarget "BenderTests" */; buildPhases = ( - 55E055208F544A3EBEFD1F4F /* Check Pods Manifest.lock */, + 49DF39E8201EB44B10AF2B81 /* 📦 Check Pods Manifest.lock */, 5B54EF061C3A90AE0072B2A8 /* Sources */, 5B54EF071C3A90AE0072B2A8 /* Frameworks */, 5B54EF081C3A90AE0072B2A8 /* Resources */, - BC24E694DE6DFB71DAC88777 /* Embed Pods Frameworks */, - D2F4D159380FD54BB269E52F /* Copy Pods Resources */, + 833D4801C00DD31774D5A56C /* 📦 Embed Pods Frameworks */, + 7DEEE40E27C0442E9CFFABC3 /* 📦 Copy Pods Resources */, ); buildRules = ( ); @@ -248,7 +264,9 @@ 5B54EF1D1C3D38A60072B2A8 /* basic_test.json in Resources */, 5BCE65501C7F9BF6000603ED /* array_skip_test.json in Resources */, 5B54EF1F1C3D39DB0072B2A8 /* array_test.json in Resources */, + BE143A241CEA2BF10092CC2B /* ref_rules_test.json in Resources */, 5BAEB5121C47D0480044C0A7 /* recursive_test.json in Resources */, + BE24B6581CECB454002AE950 /* advanced_ref_rules_test.json in Resources */, 5B54EF231C3D4AD50072B2A8 /* enum_test.json in Resources */, 5B54EF211C3D46ED0072B2A8 /* natural_array_test.json in Resources */, 5BCE65551C8326EB000603ED /* path_test.json in Resources */, @@ -259,14 +277,14 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 55E055208F544A3EBEFD1F4F /* Check Pods Manifest.lock */ = { + 49DF39E8201EB44B10AF2B81 /* 📦 Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Check Pods Manifest.lock"; + name = "📦 Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -274,29 +292,29 @@ shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; - BC24E694DE6DFB71DAC88777 /* Embed Pods Frameworks */ = { + 63EEED299EBADB90672D806D /* 📦 Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Embed Pods Frameworks"; + name = "📦 Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-BenderTests/Pods-BenderTests-frameworks.sh\"\n"; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Bender/Pods-Bender-resources.sh\"\n"; showEnvVarsInLog = 0; }; - D2F4D159380FD54BB269E52F /* Copy Pods Resources */ = { + 7DEEE40E27C0442E9CFFABC3 /* 📦 Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Copy Pods Resources"; + name = "📦 Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -304,6 +322,36 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-BenderTests/Pods-BenderTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; + 833D4801C00DD31774D5A56C /* 📦 Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "📦 Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-BenderTests/Pods-BenderTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + A98F253D5F94CD7E0A204B47 /* 📦 Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "📦 Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -426,6 +474,7 @@ }; 5B54EF151C3A90AE0072B2A8 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 22EDECB62B0AD84C81D2E86A /* Pods-Bender.debug.xcconfig */; buildSettings = { CLANG_ENABLE_MODULES = YES; DEFINES_MODULE = YES; @@ -445,6 +494,7 @@ }; 5B54EF161C3A90AE0072B2A8 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 71269F45DC1611C747FE40B1 /* Pods-Bender.release.xcconfig */; buildSettings = { CLANG_ENABLE_MODULES = YES; DEFINES_MODULE = YES; @@ -463,7 +513,7 @@ }; 5B54EF181C3A90AE0072B2A8 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 6B17FF595E1FE853707766E6 /* Pods-BenderTests.debug.xcconfig */; + baseConfigurationReference = F5B570F8D430305680560ACF /* Pods-BenderTests.debug.xcconfig */; buildSettings = { INFOPLIST_FILE = BenderTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -474,7 +524,7 @@ }; 5B54EF191C3A90AE0072B2A8 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = FF38713AA0E03EF651054F86 /* Pods-BenderTests.release.xcconfig */; + baseConfigurationReference = F7E362DC0AB1E40434C24AA0 /* Pods-BenderTests.release.xcconfig */; buildSettings = { INFOPLIST_FILE = BenderTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; diff --git a/Bender/Bender.swift b/Bender/Bender.swift index e1ce0be..c9a31b1 100644 --- a/Bender/Bender.swift +++ b/Bender/Bender.swift @@ -986,3 +986,76 @@ public func /(path: JSONPath, right: String) -> JSONPath { return JSONPath(path.elements + [right]) } +/** + Insertes value instead of reference and validates value using hidden rule. + */ +public class RefRuleDecorator: Rule { + public typealias V = T + public typealias ReferenceRequest = (String) throws -> (AnyObject) + + private let nestedRule: R + + // Closure to request value by reference outside + var refRequest: ReferenceRequest? + + init(_ nestedRule: R, _ request: ReferenceRequest? = nil) { + self.nestedRule = nestedRule + self.refRequest = request + } + + public func validate(jsonValue: AnyObject) throws -> T { + guard let reference = jsonValue as? String else { + throw RuleError.ExpectedNotFound("Unable to validate \"\(jsonValue)\" as \(String.self). It is not a reference.", nil) + } + + guard let refRequest = refRequest else { + throw RuleError.ExpectedNotFound("Impossible to resolve references. Reference request is nil", nil) + } + + let resolvedValue = try refRequest(reference) + return try nestedRule.validate(resolvedValue) + } + + public func dump(value: V) throws -> AnyObject { + throw RuleError.InvalidDump("Not implemented yet: impossible to know reference key without json context", nil) + } +} + +/* + Provides interface to request values from map by stringified key and validates using hidden rule. + */ +public class RefRuleAdapter: Rule { + public typealias V = T + private let rootRule: R + private let path: JSONPath + private var references: [String: AnyObject]? + + init(_ refPath: JSONPath, _ rootRule: R) { + self.rootRule = rootRule + self.path = refPath + } + + // Allow to get value by ref + func resolve(ref: String) throws -> AnyObject { + guard let references = references else { + throw RuleError.ExpectedNotFound("Do not call this method before calling validate", nil) + } + + guard let value = references[ref] else { + throw RuleError.ExpectedNotFound("Reference \"\(ref)\" is not found", nil) + } + + return value + } + + public func validate(jsonValue: AnyObject) throws -> T { + references = objectIn(jsonValue, atPath: path) as? [String: AnyObject] + let result = try rootRule.validate(jsonValue) + references = nil + return result + } + + public func dump(value: V) throws -> AnyObject { + return try rootRule.dump(value) + } +} diff --git a/BenderTests/BenderInputTests.swift b/BenderTests/BenderInputTests.swift index efe138d..f71c9e5 100644 --- a/BenderTests/BenderInputTests.swift +++ b/BenderTests/BenderInputTests.swift @@ -261,6 +261,82 @@ class BenderInTests: QuickSpec { expect(user!.id).to(equal("123456")) expect(invisibleVar).to(equal("expected value")) } + + it("should support json references") { + let jsonObject = jsonFromFile("ref_rules_test") + + let nestedMessageRule = StructRule(ref("")) + .expect("message", StringRule, { $0.value = $1 }) + + let ruleDecorator = RefRuleDecorator(nestedMessageRule) + let contentRule = StructRule(ref("")) + .expect("content"/"reason"/"UUID", ruleDecorator, { $0.value = $1 }) + let refAdapterRule = RefRuleAdapter("content"/"refs", contentRule) + ruleDecorator.refRequest = refAdapterRule.resolve + + let value = try! refAdapterRule.validate(jsonObject) + + expect(value).to(equal("Message"), description: "Simple binding to the tuples") + + class Container { var user: User! } + let nestedUserRule = StructRule(ref(User(id: nil, name: nil))) + .expect("id", StringRule, { $0.value.id = $1 }) + .expect("name", StringRule, { $0.value.name = $1 }) + let refDecoratorUserRule = RefRuleDecorator(nestedUserRule) + let userRule = ClassRule(Container()) + .expect("content"/"userInfo", refDecoratorUserRule, { $0.user = $1 }) + let refAdapterUserRule = RefRuleAdapter("content"/"refs", userRule) + refDecoratorUserRule.refRequest = refAdapterUserRule.resolve + let userContainer = try! refAdapterUserRule.validate(jsonObject) + + expect(userContainer.user).toNot(beNil(), description: "Binding to the nested objects") + expect(userContainer.user.id).to(equal("296")) + expect(userContainer.user.name).to(equal("Innovator")) + + + let decorRule = RefRuleDecorator(nestedUserRule) + let contRule = ClassRule(Container()) + .expect("content"/"key", decorRule, { $0.user = $1 }) + let refAdapterContainerRule = RefRuleAdapter("content"/"refs", contRule) + decorRule.refRequest = refAdapterContainerRule.resolve + + let v = try? refAdapterContainerRule.validate(jsonObject) + expect(v).to(beNil(), description: "RefRule with unknown reference") + } + + it("should support references to any nested rules and a few reference rules at the same time"){ + let jsonObject = jsonFromFile("advanced_ref_rules_test") + + let nestedUserRule = StructRule(ref(User(id: nil, name: nil))) + .expect("id", StringRule, { $0.value.id = $1 }) + .expect("name", StringRule, { $0.value.name = $1 }) + let decorRule = RefRuleDecorator(nestedUserRule) + + class UserContainer { var user: User!; var isValid: Bool! } + let userContainer = ClassRule(UserContainer()) + .expect("isValid", BoolRule, { $0.isValid = $1 }) + .expect("path"/"url", decorRule, { $0.user = $1 }) + + class Content { var users: [UserContainer]! } + + let contentRule = ClassRule(Content()) + .expect("content", ArrayRule(itemRule: userContainer, invalidItemHandler: {_ in return } ), { $0.users = $1} ) + let adapter = RefRuleAdapter("refs", contentRule) + decorRule.refRequest = adapter.resolve + + let value = try! adapter.validate(jsonObject) + expect(value.users).toNot(beNil()) + expect(value.users.count).to(equal(2), description: "The last user item should not be validated because it contains unknown reference.") + expect(value.users[0].isValid).to(beTrue()) + expect(value.users[0].user).toNot(beNil()) + expect(value.users[0].user.id).to(equal("id1")) + expect(value.users[0].user.name).to(equal("name1")) + + expect(value.users[1].isValid).to(beFalse()) + expect(value.users[1].user).toNot(beNil()) + expect(value.users[1].user.id).to(equal("id2")) + expect(value.users[1].user.name).to(equal("name2")) + } } describe("Array validation") { diff --git a/BenderTests/advanced_ref_rules_test.json b/BenderTests/advanced_ref_rules_test.json new file mode 100644 index 0000000..6f31ad7 --- /dev/null +++ b/BenderTests/advanced_ref_rules_test.json @@ -0,0 +1,38 @@ +{ + "content": [ + { + "id": 1, + "path": { + "id": "test", + "url": "uuid1" + }, + "isValid": true + }, + { + "id": 2, + "path": { + "id": "test", + "url": "uuid2" + }, + "isValid": false + }, + { + "id": 3, + "path": { + "id": "test", + "url": "uuid" + }, + "isValid": true + }, + ], + "refs": { + "uuid1": { + "id": "id1", + "name": "name1" + }, + "uuid2": { + "id": "id2", + "name": "name2" + } + } +} \ No newline at end of file diff --git a/BenderTests/ref_rules_test.json b/BenderTests/ref_rules_test.json new file mode 100644 index 0000000..c63de14 --- /dev/null +++ b/BenderTests/ref_rules_test.json @@ -0,0 +1,20 @@ +{ + "content" : { + "userInfo": "https://host/959", + "reason": { + "id": "296", + "UUID": "UUID_UUID" + }, + "key": "unknownRef", + "refs": { + "https://host/959": { + "id": "296", + "name": "Innovator" + }, + "UUID_UUID": { + "id": "959", + "message": "Message" + } + } + } +} \ No newline at end of file diff --git a/Podfile b/Podfile index dee6ade..0ad9aab 100644 --- a/Podfile +++ b/Podfile @@ -7,8 +7,8 @@ target 'Bender' do end target 'BenderTests' do - pod 'Quick', '~> 0.9.1' - pod 'Nimble', '~> 3.2.0' + pod 'Quick', '~> 0.9.2' + pod 'Nimble', '~> 4.0.1' end diff --git a/Podfile.lock b/Podfile.lock index c00dbf7..67fb4f5 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,13 +1,15 @@ PODS: - - Nimble (3.2.0) - - Quick (0.9.1) + - Nimble (4.0.1) + - Quick (0.9.2) DEPENDENCIES: - - Nimble (~> 3.2.0) - - Quick (~> 0.9.1) + - Nimble (~> 4.0.1) + - Quick (~> 0.9.2) SPEC CHECKSUMS: - Nimble: 703854335d181df169bbca9c97117b5cf8c47c1d - Quick: a5221fc21788b6aeda934805e68b061839bc3165 + Nimble: 0f3c8b8b084cda391209c3c5efbb48bedeeb920a + Quick: 18d057bc66451eedd5d1c8dc99ba2a5db6e60226 -COCOAPODS: 0.39.0 +PODFILE CHECKSUM: 2b5003e932bccf343ef4e9d6fe97ece80d123896 + +COCOAPODS: 1.0.0