diff --git a/Hippolyte.xcodeproj/project.pbxproj b/Hippolyte.xcodeproj/project.pbxproj index 0bcc152..e628d3b 100644 --- a/Hippolyte.xcodeproj/project.pbxproj +++ b/Hippolyte.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ 77A2EA9F1F6561A30051E45A /* HippolyteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77A2EA9E1F6561A30051E45A /* HippolyteTests.swift */; }; 77B806641F63E33A0077A365 /* HTTPStubURLProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77B806631F63E33A0077A365 /* HTTPStubURLProtocol.swift */; }; 77B806661F63E5670077A365 /* HTTPRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77B806651F63E5670077A365 /* HTTPRequest.swift */; }; + ABD79AD622CD5F24003C9D8B /* JSONMatcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABD79AD522CD5F24003C9D8B /* JSONMatcherTests.swift */; }; E64B0ED3223ACCF900FB35E4 /* Hippolyte.h in Headers */ = {isa = PBXBuildFile; fileRef = 77A290D11F62EADF001E70FA /* Hippolyte.h */; settings = {ATTRIBUTES = (Public, ); }; }; E64B0ED4223ACD0D00FB35E4 /* Hippolyte.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77A290E81F62EDF5001E70FA /* Hippolyte.swift */; }; E64B0ED5223ACD0D00FB35E4 /* StubRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77A290EA1F62EE40001E70FA /* StubRequest.swift */; }; @@ -67,7 +68,7 @@ /* Begin PBXFileReference section */ 7706E6651F822F2C00734A1D /* StubResponseBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubResponseBuilderTests.swift; sourceTree = ""; }; 7766CF9D1F652D8F00B717B2 /* URLHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLHook.swift; sourceTree = ""; }; - 7766CF9F1F652FD100B717B2 /* Matcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Matcher.swift; sourceTree = ""; }; + 7766CF9F1F652FD100B717B2 /* Matcher.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = Matcher.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 7766CFA11F65311200B717B2 /* URL+HippolyteAdditions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+HippolyteAdditions.swift"; sourceTree = ""; }; 7766CFA31F654F1800B717B2 /* DataMatcherTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataMatcherTests.swift; sourceTree = ""; }; 7766CFA51F65515000B717B2 /* StringMatcherTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringMatcherTests.swift; sourceTree = ""; }; @@ -87,6 +88,7 @@ 77A2EA9E1F6561A30051E45A /* HippolyteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HippolyteTests.swift; sourceTree = ""; }; 77B806631F63E33A0077A365 /* HTTPStubURLProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPStubURLProtocol.swift; sourceTree = ""; }; 77B806651F63E5670077A365 /* HTTPRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPRequest.swift; sourceTree = ""; }; + ABD79AD522CD5F24003C9D8B /* JSONMatcherTests.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = JSONMatcherTests.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; E64B0ECB223ACB6300FB35E4 /* Hippolyte.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Hippolyte.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E64B0EE3223ACE8400FB35E4 /* HippolyteTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HippolyteTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -171,6 +173,7 @@ 7766CFA31F654F1800B717B2 /* DataMatcherTests.swift */, 7766CFA51F65515000B717B2 /* StringMatcherTests.swift */, 7766CFA71F6552B100B717B2 /* RegexMatcherTests.swift */, + ABD79AD522CD5F24003C9D8B /* JSONMatcherTests.swift */, 7766CFAB1F65571800B717B2 /* StubRequestTests.swift */, 7706E6651F822F2C00734A1D /* StubResponseBuilderTests.swift */, 77A2EA9C1F65589C0051E45A /* TestRequest.swift */, @@ -416,6 +419,7 @@ files = ( 77A2EA9F1F6561A30051E45A /* HippolyteTests.swift in Sources */, 7706E6661F822F2C00734A1D /* StubResponseBuilderTests.swift in Sources */, + ABD79AD622CD5F24003C9D8B /* JSONMatcherTests.swift in Sources */, 7766CFA81F6552B100B717B2 /* RegexMatcherTests.swift in Sources */, 7766CFA41F654F1800B717B2 /* DataMatcherTests.swift in Sources */, 7766CFA61F65515000B717B2 /* StringMatcherTests.swift in Sources */, diff --git a/Hippolyte/Matcher.swift b/Hippolyte/Matcher.swift index 24a5eba..b90cc00 100644 --- a/Hippolyte/Matcher.swift +++ b/Hippolyte/Matcher.swift @@ -112,3 +112,34 @@ public class DataMatcher: Matcher { } } + +public class JsonMatcher: Matcher { + + let decoder: JSONDecoder + let object: T + + public init(object: T) { + self.decoder = JSONDecoder() + self.object = object + } + + public override func matches(data: Data?) -> Bool { + guard let data = data, let decodedObject = try? self.decoder.decode(T.self, from: data) else { + return false + } + + return object == decodedObject + } + + public override func hash(into hasher: inout Hasher) { + hasher.combine(object) + } + + override func isEqual(to other: Matcher) -> Bool { + if let theOther = other as? JsonMatcher { + return theOther.object == object + } + return false + } + +} diff --git a/HippolyteTests/JSONMatcherTests.swift b/HippolyteTests/JSONMatcherTests.swift new file mode 100644 index 0000000..b9cd8c0 --- /dev/null +++ b/HippolyteTests/JSONMatcherTests.swift @@ -0,0 +1,61 @@ +// +// JSONMatcherTests.swift +// HippolyteTests_iOS +// +// Created by Clemens on 04.07.19. +// Copyright © 2019 Clemens Schulz. All rights reserved. +// + +import XCTest +import Hippolyte + +class JSONMatcherTests: XCTestCase { + + private struct TestObject: Codable, Hashable { + + let id: Int + let name: String? + let foo: Bool + } + + func testMatchingObjectMatches() throws { + let object = TestObject(id: 1, name: "name", foo: false) + let matcher = JsonMatcher(object: object) + + let encoder = JSONEncoder() + let data = try encoder.encode(object) + + XCTAssertTrue(matcher.matches(data: data)) + } + + func testMismatchingObjectDoesNotMatch() throws { + let object = TestObject(id: 1, name: "name", foo: false) + let matcher = JsonMatcher(object: object) + + let otherObject = TestObject(id: 1, name: "other", foo: true) + + let encoder = JSONEncoder() + let data = try encoder.encode(otherObject) + + XCTAssertFalse(matcher.matches(data: data)) + } + + func testInstancesWithSameObjectMatch() { + let object = TestObject(id: 1, name: "name", foo: false) + let matcher1 = JsonMatcher(object: object) + let matcher2 = JsonMatcher(object: object) + + XCTAssertEqual(matcher1, matcher2) + } + + func testInstancesWithDifferentObjectDoNotMatch() { + let object1 = TestObject(id: 1, name: "name", foo: false) + let matcher1 = JsonMatcher(object: object1) + + let object2 = TestObject(id: 2, name: "other", foo: true) + let matcher2 = JsonMatcher(object: object2) + + XCTAssertNotEqual(matcher1, matcher2) + } + +}