-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
implement window.fetch
capturing/mocking
#95
Comments
Per the It's on our radar to adding stubbing to these as well. We're a lot closer to being able to do it now. |
I would love to see this feature. I am very excited about stubbing. It will definitely solve a lot of problems when doing these tests. |
My team would love this too! |
Same here. We use fetch for it's simplicity in our react application. Until yet we use our own proxy that mocks the ajax requests, but your XHR approuch is much more readable. |
Maybe you could offer a way to use fetch outside the service-worker's context first and in a second phase you could add fetch in service-workers? |
There is now an example of using We have a bunch of examples of it here: https://github.com/cypress-io/cypress-example-recipes#controlling-behavior-with-spies-stubs-and-clocks |
As not all browsers support cy
.visit('<some url>', {
onBeforeLoad: (win) => {
win.fetch = null
}
}) After doing this, the polyfill will just use |
Thank you for the alternative approach. Will try that. |
@stigkj thx for the workaround/solution. |
@stigkj thanks for the work around, like @mvandebunt this has worked for me in Chromium 56 :) I find this a bit easier than the spy approach. I'm looking forward to Cypress getting better support for window.fetch :) |
While people are waiting for this, As long as your app falls back to XHR (polyfill or other) you can use this in Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
const opts = Object.assign({}, options, {
onBeforeLoad: (window, ...args) => {
window.fetch = null;
if (options.onBeforeLoad) {
return options.onBeforeLoad(window, ...args);
}
},
});
return originalFn(url, opts);
}); |
@Graham42 There is actually an easier way to do this and it will work not only for visits but all page transitions. https://docs.cypress.io/api/events/catalog-of-events.html#Window-Before-Load This event is called at the same time the You also won't have to overwrite the |
Supported natively in Cypress, but not yet for window.fetch See: cypress-io/cypress#95
@Graham42 the overwrite of the visit command does not call |
@vschoettke Do not use the visit overwrite - use what I suggested in my comment here: #95 (comment) There's nothing wrong per-se with overwriting visit but its unnecessary when you can use events which will apply to all page transitions. |
@brian-mann worked like a charm! I just put this in // use `Cypress` instead of `cy` so this persists across all tests
Cypress.on("window:before:load", win => {
win.fetch = null;
}); |
@nmchaves thanks! Your comment came just right in when I was about to ask if there was a way to make this global instead of inside the tests! You rock man! |
Thank your solution @nmchaves, but with it, i cant get response body by function |
Has anyone successfully getting the network stub to work with fetch requests made via a page within an iframe? |
For anyone looking for stub Apollo/GraphQL queries, I wrote one, as detailed here: https://siawyoung.com/stub-graphql-cypress. The simple (non-batched) version is pasted here for convenience: const responseStub = ({ payload, ok }) =>
Promise.resolve({
json() {
return Promise.resolve(payload)
},
text() {
return Promise.resolve(JSON.stringify(payload))
},
ok: ok === undefined ? true : ok,
})
Cypress.Commands.add('graphql', stubbedGQLResponses => {
cy.on('window:before:load', win => {
const originalFetch = win.fetch
const fetch = (path, options, ...rest) => {
if (options.body) {
try {
const body = JSON.parse(options.body)
if (body.operationName in stubbedGQLResponses) {
const stubbedResponse = stubbedGQLResponses[body.operationName]
return responseStub(stubbedResponse)
}
return originalFetch(path, options, ...rest)
} catch (e) {
return originalFetch(path, options, ...rest)
}
}
return originalFetch(path, options, ...rest)
}
cy.stub(win, 'fetch', fetch)
})
}) context('Accounts page', () => {
beforeEach(() => {
cy.graphql({
userAccount: {
payload: {
data: {
user: {
id: 1,
first_name: 'Bob',
last_name: 'Smith',
__typename: 'User',
},
},
},
},
})
cy.visit('/account')
})
it('should display user first and last name correctly', () => {
cy.get('.first-name').should('have.text', 'Bob')
cy.get('.last-name').should('have.text', 'Smith')
})
}) There's also a version that works with batched Apollo requests in the post itself. |
As @valentinogagliardi mentioned Mirage.js is a great tool. We are also using Mirage.js and there is also a guide for Cypress 🎉 (you can find it here) maybe it makes sense to join the forces and create a nice integration of Mirage.js into Cypress. I think @samselikoff would be happy about helping hands. This issue was opened more than 4 (!) years ago and it's still open. So maybe Mirage.js could be an option for some of use 🙂 |
We love Cypress and would absolutely love to collaborate here if there's an interest! |
We have experimental |
@bahmutov it's really nice, when it will be available in beta ? |
The You should be able to remove any of the following code: Cypress.on('window:before:load', (win) => {
delete win.fetch
}) or cy.visit('/', {
onBeforeLoad (win) {
delete win.fetch
},
}) And replace it with the below in your configuration file ( {
"experimentalFetchPolyfill": true
} You can see a full example of this in use here: https://github.com/cypress-io/cypress-example-recipes/tree/master/examples/stubbing-spying__window-fetch If you encounter any issues with the new |
In my case, the new |
Yeah, it doesn't work for me either. My login fetch gets a 415 (Unsupported Content-Type). |
@stefanoimperiale @stevenvachon we are also using MirageJs which works great for every type of mocking network requests. It works fine with |
Same here. We use a I think this happens because we utilize the This workaround (in our app code) works, although slightly awkward: fetch(url, {
...
- headers,
+ headers: Object.fromEntries(headers)
}) |
Is it valid to use fetch polyfill called |
@baeharam I did this for a project and it worked just fine. |
@mefechoel Thanks for your feedback! I'll try |
Is there a way to only replace window.fetch on stubbed routes? |
Released in This comment thread has been locked. If you are still experiencing this issue after upgrading to |
The features requested in this issue are now possible as part of
Please see the If you encounter any issues or unexpected behavior while using |
Many developers are migrating to
window.fetch
from XHRs due to the simplified async interface it exposes. I happen to be one of those developers.Cypress should support
window.fetch
with similar abilities to those of XHRs: I should be able to query the request and response, wait on them, and mock with data and fixtures.Cypress team edit
This feature will work seamlessly once Full network stubbing is implemented.
Workarounds
or do it yourself:
window.fetch
before visiting the page to force your application to polyfill it on top of XHR. If the application does not include a polyfill, you can load one from your tests.window.fetch
directly in JavaScriptSee these solutions in Stubbing
window.fetch
example recipeThe text was updated successfully, but these errors were encountered: