Do you want to request a _feature_ or report a _bug_?
feature
What is the current behavior?
expect({ foo: new Error("failure") }).toEqual({
foo: expect.any(Error).objectContaining({ message: "failure" }),
})
outputs
TypeError: expect.any(...).objectContaining is not a function
548 | foo: new Error("failure"),
549 | }).toEqual({
> 550 | foo: expect.any(Error).objectContaining({ message: "failure" }),
551 | })
552 | })
553 |
What is the expected behavior?
The syntax above should not throw.
The following test should throw a descriptive error message:
expect({ foo: new Error("failure") }).toEqual({
foo: expect.any(Error).objectContaining({ message: "success" }),
})
Please provide your exact Jest configuration
{
"testMatch": [
"<rootDir>/imports/**/*.test.js"
],
"testPathIgnorePatterns": [
"/node_modules/",
"/.meteor"
],
"setupTestFrameworkScriptFile": "./imports/test-helpers/setup.js",
"coverageDirectory": "imports/coverage"
}
Run npx envinfo --preset jest in your project directory and paste the
results here
System:
OS: macOS High Sierra 10.13.3
CPU: x64 Intel(R) Core(TM) i7-5557U CPU @ 3.10GHz
Binaries:
Node: 8.9.1
Yarn: 1.5.1
npm: 5.5.1
npmPackages:
jest:
wanted: ^22.4.2
installed: 22.4.2
I am willing to do a PR if someone tells me the feature would be approved!
I like it :) @cpojer thoughts?
Yeah sounds pretty cool! Wanna work on a PR? :)
Nice! I'll have a look at it on Thursday next week.
@cpojer I know this has been touched on before in other issues, how would you feel about also making normal matchers chainable too?
expect('hello').toBe('hello').toContain('h').etc()
I've played around with this locally and got it working it wasn't much work, but does increase the surface area of expect - in that all matchers need to make sure they return the matchers object.
That's a separate conversation entirely. I don't think it provides a lot of value for the added complexity and it can make assertions harder to read rather than easier.
The nice thing about the extension to asymmetric matchers here is that it allows to create a richer description of what you'd like to match. However, I think we need to be careful if we add this to Jest: expect.arrayContaining(…).stringMatching() and similar combinations do not make any sense.
A few things I would like to confirm before coding:
In order to have a nice implementation, I suggest:
1/ creating a "combine" operation for asymmetric matchers:
expect("Hello World").toEqual(combinedAssertions([
expect.stringContaining("Hello"),
expect.stringContaining("World!"),
]))
2/ adding the chaining API itself
I imagined printing the first failing assertion : what do you think?
@aymericbouzy I think it would be cool to collect all failures but probably too messy to print? So fail fast is probably better.
With the combinedAssertions suggestion would that be a public API or something used under the hood to implement the chaining?
I'd like to actually go back to the drawing board first. Which asymmetric matchers should we chain and why? The example you just gave can be accomplished using a regex, for example. I'd like to see a number of examples of where this could be useful, consider alternatives and then figure out if it makes sense to add something to Jest or not.
Hi,
let latLng = {lat: 1.000001, lng: 2.000001}
expect(latLng).toBeCloseToLatLng( {lat: 1, lng: 2})
I like hamcrest style in java ❤️ and I want to combine matchers to use predicate expect.toBeCloseTo() with hardcoded accuracy?
it seems to me it's an unrelated issue. I would suggest defining a custom matcher.
The example you just gave can be accomplished using a regex, for example.
What do you mean? can you validate that a given object is an instance of Error and that it has a key message with value "failure" using a regex? I don't get it.
I'd like to see a number of examples of where this could be useful
I use Mongoose in my code. I often find myself wanting to write such code :
expect(await getSomeUsersFromDatabase()).toEqual([
expect.someUserWithId(user.id)
])
Except I have dozens of different models. Also, sometimes, I don't want to check the id matches, but some other information.
Writing this would be much more convenient:
expect(await getSomeUsersFromDatabase()).toEqual([
expect.any(User).objectContaining({ id: user.id })
])
Whenever I find another use case, I'll post it here.
This is something we have had in the popular matching libraries for Java in many years and I would expect all test systems to have:
https://junit.org/junit4/javadoc/latest/org/hamcrest/CoreMatchers.html#allOf(org.hamcrest.Matcher...)
https://junit.org/junit4/javadoc/latest/org/hamcrest/CoreMatchers.html#anyOf(org.hamcrest.Matcher...)
Most helpful comment
A few things I would like to confirm before coding:
Implementation
In order to have a nice implementation, I suggest:
1/ creating a "combine" operation for asymmetric matchers:
2/ adding the chaining API itself
Descriptive error message
I imagined printing the first failing assertion : what do you think?