diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ceff0b3..9b36ca9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # OHHTTPStubs — CHANGELOG +## [Future release] + +* Added `containsQueryParamsMatching(...)` matcher. + [@mcarti](https://github.com/mcarti) + [#309](https://github.com/AliSoftware/OHHTTPStubs/issues/309) ## [9.0.0](https://github.com/AliSoftware/OHHTTPStubs/releases/tag/9.0.0) diff --git a/Sources/OHHTTPStubsSwift/OHHTTPStubsSwift.swift b/Sources/OHHTTPStubsSwift/OHHTTPStubsSwift.swift index 07069daa..6b7b684a 100644 --- a/Sources/OHHTTPStubsSwift/OHHTTPStubsSwift.swift +++ b/Sources/OHHTTPStubsSwift/OHHTTPStubsSwift.swift @@ -363,6 +363,40 @@ public func containsQueryParams(_ params: [String:String?]) -> HTTPStubsTestBloc } } +/** + * Matcher for testing an `NSURLRequest`'s **query parameters** that matches a RegEx. + * + * - Parameter params: The dictionary of the Regular Expressions matching the query parameters we want to check the presence for + * + * - Returns: a matcher (HTTPStubsTestBlock) that succeeds if the request contains + * the given query parameters matching the given list of RegExs. + */ +@available(iOS 8.0, OSX 10.10, *) +public func containsQueryParamsMatching(_ params: [String:String?]) -> HTTPStubsTestBlock { + return { req in + if let url = req.url { + let comps = NSURLComponents(url: url, resolvingAgainstBaseURL: true) + if let queryItems = comps?.queryItems { + for (k,v) in params { + guard let regexString = v, let regex = try? NSRegularExpression(pattern: regexString, options: []) else { return false } + if queryItems.filter({ qi in + guard let paramValue = qi.value else { return false} + let range = NSRange(location: 0, length: paramValue.utf16.count) +#if swift(>=3.0) + let paramMatchesRegex: Bool = regex.firstMatch(in: paramValue, options: [], range: range) != nil +#else + let paramMatchesRegex: Bool = regex.firstMatchInString(paramValue, options: [], range: range) != nil +#endif + return qi.name == k && paramMatchesRegex + }).count == 0 { return false } + } + return true + } + } + return false + } +} + /** * Matcher testing that the `NSURLRequest` headers contain a specific key * - Parameter name: the name of the key to search for in the `NSURLRequest`'s **allHTTPHeaderFields** property diff --git a/Tests/OHHTTPStubsSwiftTests/SwiftHelpersTests.swift b/Tests/OHHTTPStubsSwiftTests/SwiftHelpersTests.swift index 9541e9cf..48f485e3 100644 --- a/Tests/OHHTTPStubsSwiftTests/SwiftHelpersTests.swift +++ b/Tests/OHHTTPStubsSwiftTests/SwiftHelpersTests.swift @@ -381,6 +381,35 @@ class SwiftHelpersTests : XCTestCase { XCTAssert(matcher(req) == result, "containsQueryParams(\"\(params)\") matcher failed when testing url \(url)") } } + + @available(iOS 8.0, OSX 10.10, *) + func testContainsQueryParamsMatching() { + let regEx1: String = "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$" + let regEx2: String = "en|fr|ru" + let params: [String: String?] = ["q":regEx1, "lang": regEx2] + let matcher = containsQueryParamsMatching(params) + + let urls = [ + "foo://bar": false, + "foo://bar?q=1994-11-05T08:15:30.000Z": false, + "foo://bar?lang=en": false, + "foo://bar?q=1994-11-05T08:15:30.000Z&lang=en": true, + "foo://bar?q=2019-05-21T13:22:45.000Z&lang=fr": true, + "foo://bar?q=9999-99-99T99:99:99.999Z&lang=ru": true, + "foo://bar?q=1994-11-05T08:15:30.000Z&lang=ro": false, + "foo://bar?q=1994-11-05T08:15:30.000&lang=en": false + ] + + for (url, result) in urls { +#if swift(>=3.0) + let req = URLRequest(url: URL(string: url)!) +#else + let req = NSURLRequest(URL: NSURL(string: url)!) +#endif + + XCTAssert(matcher(req) == result, "containsQueryParamsMatching(\"\(params)\") matcher failed when testing url \(url)") + } + } func testHasHeaderNamedIsTrue() { #if swift(>=3.0)