-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature Request: Support asynchronous matchers #3874
Comments
Whoa, I like the idea. |
Shouldn't the new resolves matchers handle this since async functions just return promises? |
@probablyup I've not used the My real motivation behind this is for testing action creators in Redux. When a component calls an action creator, it doesn't (and shouldn't) really know if the action creator returns an action object or a thunk. As such, I'd like to be able to write tests that look something like this: // actions.js
export function someAction () {
return async function (dispatch) {
dispatch({ type: 'START_OF_ASYNC_THING' })
await new Promise(res => setTimeout(res, 0))
dispatch({ type: 'END_OF_ASYNC_THING' })
}
}
// actions-test.js
import * as actions from './actions'
test('some action creator', () => {
let action = actions.someAction()
mockStore.dispatch(action)
expect(mockStore).toHaveDispatched({ type: 'START_OF_ASYNC_THING' })
expect(mockStore).toHaveDispatched({ type: 'END_OF_ASYNC_THING' })
}) With asynchronous support on the matcher side, the matcher itself could |
I think |
I have a group of tests for an async function that replaces content in strings. In some test cases, I need to ensure that a given string changes or does not change after running the function. It would be great to be able to extract this testing behavior into a custom matcher, but I can't because the behavior has to be asynchronous through a Promise (it's making network requests through a third party library). If I used the Beforeconst expectToUpdate = url => () => expect(cdnm.update(url)).resolves.toBe(replaceVersion(url))
const expectNotToUpdate = url => () => expect(cdnm.update(url)).resolves.toBe(url)
test('empty string', expectNotToUpdate(''))
test('complete html document', expectToUpdate(html)) Aftertest('empty string', () => expect('').not.toUpdate())
test('complete html document', () => expect(html).toUpdate()) |
Can't you use I haven't read through this issue, so might be missing something |
Unfortunately no, because I want the matcher's internal logic to be asynchronous while passing a synchronous value to the matcher. In this case, I would be passing a String (not wrapped in a Promise) to a |
Does the // toMatchTextContent.js
const toMatchTextContent = async (received, expected) => {
const isElementHandle = testUtils.isPuppeteerConstructor(received, 'ElementHandle');
if (!isElementHandle) {
return { actual: received, message: testUtils.constructorError('ElementHandle').message, pass: false };
}
const textContentProperty = await received.getProperty('textContent');
const textJson = await textContentProperty.jsonValue();
const pass = textJson.match(expected);
// rest of matcher and message logic
....
}
// toMatchTextContent.test.js
// The test now requires that you use `await` on the expect
it('should match text from an ElementHandle', async () => {
await page.goto('http://www.example.com/');
const header = await page.$('h1');
await expect(header).toMatchTextContent('Example Domain');
}); Using I haven't personally had success with |
I don't think so, that's the issue I'm having. In my opinion |
Agreed on I poking around in the Do you have any thoughts or ideas on implementation details? Follow UpI think here is where we'd want to "copy"/make similar. It is the promise resolution of the matcher function itself that is the tricky part. |
@therynamo I really want this feature to be able to write some custom matchers to DRY our test suite. At the moment I have a working version that lets you create async matchers but only works in combination with Would love some feedback and any ideas on how to support this without having to use promises inside the |
Hey @bilby91, nice PR! Seems to make sense.
This was the one thing I was trying to solve when I was working on this issue. I didn't like the idea of having to write tests like this #3874 (comment). However, incremental changes towards not having to do that are great. So it seems like what you have is a step in the right direction. 👍 |
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Do you want to request a feature or report a bug?
Feature
What is the current behavior?
Custom matchers must return an object of the form:
{ pass: [boolean], message: [string|function] }
.It would be helpful to support matchers that return a Promise, thereby allowing custom matchers that can utilize
async/await
to flush pending Promises.This may be of use for folks waiting on #2157.
I'd like to be able to have a matcher something of the form (though this is a contrived example):
The text was updated successfully, but these errors were encountered: