diff --git a/Framework/Sources/MockHTTPRoute.swift b/Framework/Sources/MockHTTPRoute.swift index d1a2e65..62847ca 100644 --- a/Framework/Sources/MockHTTPRoute.swift +++ b/Framework/Sources/MockHTTPRoute.swift @@ -157,7 +157,7 @@ extension MockHTTPRoute: Equatable { if case MockHTTPRoute.custom(let lhsMethod, let lhsUrlPath, let lhsQuery, let lhsRequestHeaders, _, _, _) = lhs, case MockHTTPRoute.custom(let rhsMethod, let rhsUrlPath, let rhsQuery, let rhsRequestHeaders, _, _, _) = rhs { return lhsMethod == rhsMethod && lhsUrlPath.pathMatches(rhsUrlPath) - && lhsQuery == rhsQuery && headers(lhsRequestHeaders, contains: rhsRequestHeaders) + && queryParamsMatch(lhs: lhsQuery, rhs: rhsQuery) && headers(lhsRequestHeaders, contains: rhsRequestHeaders) } if case MockHTTPRoute.template(let lhsMethod, let lhsUrlPath, _, _, _) = lhs, case MockHTTPRoute.template(let rhsMethod, let rhsUrlPath, _, _, _) = rhs { @@ -198,6 +198,19 @@ extension MockHTTPRoute: Equatable { return false } + private static func queryParamsMatch(lhs: [String:String], rhs: [String:String]) -> Bool { + + if lhs.count != rhs.count { return false } + + for element in lhs { + let matches = rhs[element.key]?.pathMatches(element.value) ?? false + if !matches { + return false + } + } + return true + } + public func matches(method: MockHTTPMethod, path: String, params: [String:String], headers: [String:String]) -> Bool { guard !method.rawValue.isEmpty else { return false } guard !path.isEmpty else { return false } diff --git a/Tests/Sources/CustomRouteTests.swift b/Tests/Sources/CustomRouteTests.swift index a4cfff8..316fee3 100644 --- a/Tests/Sources/CustomRouteTests.swift +++ b/Tests/Sources/CustomRouteTests.swift @@ -136,6 +136,45 @@ class CustomRouteTests: ShockTestCase { self.waitForExpectations(timeout: timeout, handler: nil) } + func testCustomRouteWithDynamicQueryParameters() { + let query = "item1=value1&item2=value2" + let route: MockHTTPRoute = .custom( + method: .get, + urlPath: "/custom-with-query", + query: ["item1": ":placeHolder1", "item2": ":placeHolder2"], + requestHeaders: [:], + responseHeaders: [:], + code: 200, + filename: "testCustomRoute.txt" + ) + let query2 = "item3=value3&item4=value4" + let route2: MockHTTPRoute = .custom( + method: .get, + urlPath: "/custom-with-query", + query: ["item3": ":placeHolder3", "item4": ":placeHolder4"], + requestHeaders: [:], + responseHeaders: [:], + code: 200, + filename: "testCustomRoute2.txt" + ) + let routes: MockHTTPRoute = .collection(routes: [route, route2]) + server.setup(route: routes) + + let expectation = self.expectation(description: "Expect 200 response with response body") + HTTPClient.get(url: "\(server.hostURL)/custom-with-query?\(query)") { code, body, headers, error in + expectation.fulfill() + XCTAssertEqual(code, 200) + XCTAssertEqual(body, "testCustomRoute test fixture\n") + } + let expectation2 = self.expectation(description: "Expect 200 response with response body") + HTTPClient.get(url: "\(server.hostURL)/custom-with-query?\(query2)") { code, body, headers, error in + expectation2.fulfill() + XCTAssertEqual(code, 200) + XCTAssertEqual(body, "testCustomRoute2 test fixture\n") + } + self.waitForExpectations(timeout: timeout, handler: nil) + } + func testCustomRouteWithoutQueryParameters() { let route: MockHTTPRoute = .custom( method: .get,