-
-
Notifications
You must be signed in to change notification settings - Fork 602
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New matcher: map, for running a function on a value and running a mat…
…cher against the return value of that function (#1112)
- Loading branch information
Showing
5 changed files
with
163 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/// `map` works by transforming the expression to a value that the given matcher uses. | ||
/// | ||
/// For example, you might only care that a particular property on a method equals some other value. | ||
/// So, you could write `expect(myObject).to(lens(\.someIntValue, equal(3))`. | ||
/// This is also useful in conjunction with ``satisfyAllOf`` to do a partial equality of an object. | ||
public func map<T, U>(_ transform: @escaping (T) throws -> U, _ matcher: Matcher<U>) -> Matcher<T> { | ||
Matcher { (received: Expression<T>) in | ||
try matcher.satisfies(received.cast { value in | ||
guard let value else { return nil } | ||
return try transform(value) | ||
}) | ||
} | ||
} | ||
|
||
/// `map` works by transforming the expression to a value that the given matcher uses. | ||
/// | ||
/// For example, you might only care that a particular property on a method equals some other value. | ||
/// So, you could write `expect(myObject).to(lens(\.someIntValue, equal(3))`. | ||
/// This is also useful in conjunction with ``satisfyAllOf`` to do a partial equality of an object. | ||
public func map<T, U>(_ transform: @escaping (T) async throws -> U, _ matcher: some AsyncableMatcher<U>) -> AsyncMatcher<T> { | ||
AsyncMatcher { (received: AsyncExpression<T>) in | ||
try await matcher.satisfies(received.cast { value in | ||
guard let value else { return nil } | ||
return try await transform(value) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import XCTest | ||
import Nimble | ||
#if SWIFT_PACKAGE | ||
import NimbleSharedTestHelpers | ||
#endif | ||
|
||
final class MapTest: XCTestCase { | ||
func testMap() { | ||
expect(1).to(map({ $0 }, equal(1))) | ||
|
||
struct Value { | ||
let int: Int | ||
let string: String? | ||
} | ||
|
||
expect(Value( | ||
int: 1, | ||
string: "hello" | ||
)).to(satisfyAllOf( | ||
map(\.int, equal(1)), | ||
map(\.string, equal("hello")) | ||
)) | ||
|
||
expect(Value( | ||
int: 1, | ||
string: "hello" | ||
)).to(satisfyAnyOf( | ||
map(\.int, equal(2)), | ||
map(\.string, equal("hello")) | ||
)) | ||
|
||
expect(Value( | ||
int: 1, | ||
string: "hello" | ||
)).toNot(satisfyAllOf( | ||
map(\.int, equal(2)), | ||
map(\.string, equal("hello")) | ||
)) | ||
} | ||
|
||
func testMapAsync() async { | ||
struct Value { | ||
let int: Int | ||
let string: String | ||
} | ||
|
||
await expect(Value( | ||
int: 1, | ||
string: "hello" | ||
)).to(map(\.int, asyncEqual(1))) | ||
|
||
await expect(Value( | ||
int: 1, | ||
string: "hello" | ||
)).toNot(map(\.int, asyncEqual(2))) | ||
} | ||
|
||
func testMapWithAsyncFunction() async { | ||
func someOperation(_ value: Int) async -> String { | ||
"\(value)" | ||
} | ||
await expect(1).to(map(someOperation, equal("1"))) | ||
} | ||
|
||
func testMapWithActor() { | ||
actor Box { | ||
let int: Int | ||
let string: String | ||
|
||
init(int: Int, string: String) { | ||
self.int = int | ||
self.string = string | ||
} | ||
} | ||
|
||
let box = Box(int: 3, string: "world") | ||
|
||
expect(box).to(satisfyAllOf( | ||
map(\.int, equal(3)), | ||
map(\.string, equal("world")) | ||
)) | ||
} | ||
} |