Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Master

* Added `hasJsonBody(_:)` matcher.
[@pimnijman](https://github.com/pimnijman)
* Added `onStubMissing` to report missing stubs.
[@c1ira](https://github.com/c1ira)
[#264](https://github.com/AliSoftware/OHHTTPStubs/pull/264)
Expand Down
20 changes: 20 additions & 0 deletions OHHTTPStubs/Sources/Swift/OHHTTPStubsSwift.swift
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,26 @@ public func hasHeaderNamed(_ name: String, value: String) -> OHHTTPStubsTestBloc
}
#endif

/**
* Matcher testing that the `NSURLRequest` body contains a JSON object with the same keys and values
* - Parameter jsonObject: the JSON object to expect
*
* - Returns: a matcher that returns true if the `NSURLRequest`'s body contains a JSON object with the same keys and values as the parameter value
*/
#if swift(>=3.0)
public func hasJsonBody(_ jsonObject: [AnyHashable : Any]) -> OHHTTPStubsTestBlock {
return { req in
guard
let httpBody = req.ohhttpStubs_httpBody,
let jsonBody = (try? JSONSerialization.jsonObject(with: httpBody, options: [])) as? [AnyHashable : Any]
else {
return false
}
return NSDictionary(dictionary: jsonBody).isEqual(to: jsonObject)
}
}
#endif

// MARK: Operators on OHHTTPStubsTestBlock

/**
Expand Down
63 changes: 63 additions & 0 deletions OHHTTPStubs/UnitTests/Test Suites/SwiftHelpersTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,69 @@ class SwiftHelpersTests : XCTestCase {
#endif
}

#if swift(>=3.0)
func testHasJsonBodyIsTrue() {
let jsonStringsAndObjects = [
Copy link
Copy Markdown
Owner

@AliSoftware AliSoftware Oct 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking, but just realized: why make that an array of tuples, instead of a Dictionary?

Wouldn't change a thing in your for loop below, but would be more common Swift and would make it order-independent.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I agree. Of course I could convert this array to a dictionary but this would mean I can use each JSON sting only once. Unless I've misinterpreted your comment.

let dict = [ "{ \"foo\": \"bar\" }", ["foo": "bar" ] ]

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I didn't realize you used some test input strings multiple times, good point

// Exact match
("{ \"foo\": \"bar\", \"baz\": 42, \"qux\": true }",
["foo": "bar", "baz": 42, "qux": true]),
// Changed attribute order
("{ \"qux\": true, \"foo\": \"bar\", \"baz\": 42 }",
["foo": "bar", "baz": 42, "qux": true]),
// Newlines and indentations
("{ \"foo\": \"bar\", \n\"baz\": 42, \"qux\": true }",
["foo": "bar", "baz": 42, "qux": true]),
// Nested objects
("{ \"foo\": \"bar\", \"baz\": { \"qux\": true, \"quux\": [\"spam\", \"ham\", \"eggs\"] } }",
["foo": "bar", "baz": ["qux": true, "quux": ["spam", "ham", "eggs"]]]),
// Nested objects with changed attribute order
("{ \"foo\": \"bar\", \"baz\": { \"quux\": [\"spam\", \"ham\", \"eggs\"], \"qux\": true } }",
["foo": "bar", "baz": ["qux": true, "quux": ["spam", "ham", "eggs"]]]),
]

for (jsonString, expectedJsonObject) in jsonStringsAndObjects {
var req = URLRequest(url: URL(string: "foo://bar")!)
req.httpBody = jsonString.data(using: .utf8)
let matchesJsonBody = hasJsonBody(expectedJsonObject)(req)

XCTAssertTrue(matchesJsonBody)
}
}
#endif

#if swift(>=3.0)
func testHasJsonBodyIsFalse() {
let jsonStringsAndObjects = [
// Changed value
("{ \"foo\": \"bar\" }",
["foo": "qux"]),
// Changed key
("{ \"foo\": \"bar\" }",
["baz": "bar"]),
// Missing attribute
("{ \"foo\": \"bar\", \"baz\": 42 }",
["foo": "bar"]),
// Extraneous attribute
("{ \"foo\": \"bar\" }",
["foo": "bar", "baz": 42]),
// Changed order in array
("{ \"foo\": [\"spam\", \"ham\", \"eggs\"] }",
["foo": ["spam", "eggs", "ham"]]),
// Nested objects with changed value
("{ \"foo\": \"bar\", \"baz\": { \"qux\": true } }",
["foo": "bar", "baz": ["qux": false]])
]

for (jsonString, expectedJsonObject) in jsonStringsAndObjects {
var req = URLRequest(url: URL(string: "foo://bar")!)
req.httpBody = jsonString.data(using: .utf8)
let matchesJsonBody = hasJsonBody(expectedJsonObject)(req)

XCTAssertFalse(matchesJsonBody)
}
}
#endif

let sampleURLs = [
// Absolute URLs
"scheme:",
Expand Down