Fetch API Support Beta #1464
Replies: 38 comments 174 replies
-
Greetings, I started a fresh NextJs application, applied the new syntax to my handler, ran a simple test that checked for data after a GET request, and Jest blew up. If I switch back to the latest msw version and apply the old syntax, everything works as usual.
Handler:
Error:
|
Beta Was this translation helpful? Give feedback.
-
It's probably worth mentioning the new |
Beta Was this translation helpful? Give feedback.
-
From the migration guide:
This is possible with an array of entries instead of a plain object: new Headers([
["Set-Cookie", "sessionId=123"],
["Set-Cookie", "name=world"],
]); |
Beta Was this translation helpful? Give feedback.
-
With all the breaking changes towards the standards, may I also suggest renaming |
Beta Was this translation helpful? Give feedback.
-
@kettanaito this is what I found implementing some tests -> https://codesandbox.io/p/sandbox/msw-standard-api-9z1f0h?file=%2Frest.spec.ts Seems the Note: I expected the same behavior as |
Beta Was this translation helpful? Give feedback.
-
❤️ the new API. I tried it out in 3 projects and found myself just knowing what to do thanks to already knowing Request, Response, etc. rather than having to go look at MSW docs when I couldn't remember some context utility or whatever. Great job, looking forward to this being released! The only frustration was not being able to use Node 18, but that applies to the current version of MSW as well so nothing new to report there. |
Beta Was this translation helpful? Give feedback.
-
I am testing with vitest here: https://github.com/xmlking/svelte-starter-kit/tree/main/src/mocks env: node v18.11.0 , "cross-fetch": "3.1.5", "msw": "0.49.0" <--- Works looking for any workaround or fix |
Beta Was this translation helpful? Give feedback.
-
Love the upcoming changes! As already mentioned in #1436, I noticed a TypeScript bug when passing a predefined object to |
Beta Was this translation helpful? Give feedback.
-
I'll repost my question regarding the new Beta and generics here:
Would the proper way be like the above replies? Using Or maybe using something like |
Beta Was this translation helpful? Give feedback.
-
Looks like with the latest version:
|
Beta Was this translation helpful? Give feedback.
-
Hi folks! I've been using the Fetch API support to set up mocking for a mature codebase for the last week or so and it's been great. Use cases include a lightweight E2E testing suite that catches the most egregious errors, as well as a light weight development environment for our designers. It's a lot more intuitive than the previous iteration and it works really well. Two things that stood out to me and I wanted to point out to you:
|
Beta Was this translation helpful? Give feedback.
-
The Fetch API spec explicitly bans body on GET requests, despite this being quite common in the wild (and not explicitly banned by the HTTP spec). Stripe, Elasticsearch and many others all have API designs that require body in GET requests. node-fetch, axios also allows this. |
Beta Was this translation helpful? Give feedback.
-
Hi, 🐛 I noticed an incompatibility between BugThe bug is that response headers won't be added to the Response ReproYou can see the repro case here : https://codesandbox.io/s/mystifying-haze-selkxr?file=/src/index.js (try to comment out the ExplanationsThe logic inside the Here is how rc3 version is creating the Here is how Here is how Here is a little something to help understand (maybe :D) SolutionsWhat do you think we should do here ? Few suggestions I had in mind, feel free to suggest a better alternative:
What do you think ? Thank you for maintaining this great project. We are using it quite a lot at Datadog 💌 . |
Beta Was this translation helpful? Give feedback.
-
Hi! I have to admit I'm a bit surprised having the 1.0.0 released 5 days ago without this change. I thought we were going to have this new API in the next major version. It seems like a concern for consumers that they will have to upgrade to 1.0.0 and then probably a 2.0.0 with this Fetch API-like feat in a few weeks? Curious what's your reasoning around that :) |
Beta Was this translation helpful? Give feedback.
-
Somehow I'm encountering a curious situation. Did anybody else notice something similar? I'm using a framework exposing a wrapper around Axios for doing external calls. Also running Node 18 right now. When using In case somebody encountered something similar I'd be curious what happened. |
Beta Was this translation helpful? Give feedback.
-
I'm having difficulty running the mockServer with jest (on node). I've tried importing Response from 'msw', but it's not being exported. And then again, I'm using HttpResponse, but still getting the error.
Traceback is pointing to HttpResponse.js line 25.
don't see any import happening in this file. happening on rc-14 |
Beta Was this translation helpful? Give feedback.
-
Hi I started a fresh NextJS project (
Thanks a lot for this great piece of software 👍 |
Beta Was this translation helpful? Give feedback.
-
We're also successfully using rc14 in a Vue 3 / Vite project. Is there a plan to merge it into the main branch? |
Beta Was this translation helpful? Give feedback.
-
Hi. I am trying to implement MSW with fetch on my project but I get this error when I run it: It is a basic implementation of MSW: import { setupServer } from 'msw/node';
import { handlers } from './handlers.js';
export const server = setupServer(...handlers); I tried with This is what I am using:
|
Beta Was this translation helpful? Give feedback.
-
Not sure there's anything you can actually do about this at the moment, but there's an issue with using
They can also import the interface from
I just started using |
Beta Was this translation helpful? Give feedback.
-
Hello! I am trying to use MSW and Playwright and I am following the migration guide for it to work with nodejs 18. I updated the
|
Beta Was this translation helpful? Give feedback.
-
Hey there, I'm getting console error
browser error
src/mocks/server.ts
environment
Please let me know if there are any other solutions or improvements. |
Beta Was this translation helpful? Give feedback.
-
UPDATE: never mind -- already fixed! Don't you love when just updating a dependency resolves an issue for you? jestjs/jest#13868 Original text was: I have one smallish new piece of feedback. I might be using it wrong, but if I accidentally write a handler-function that throws, I'm not seeing the content of the error in my test console. Example: const testUrl = 'http://handled/url';
const handlers = [
rest.get(testUrl, () => {
// Oops, Infinity is a bad status, this throws
return HttpResponse.text('OK': {status: 20/0})
});
];
// Set up server.listen etc here
it('shouldn't fail here', async () => {
const resp = await fetch(testUrl);
expect(await resp.text()).toBe('OK');
}) This logs "TypeError: Failed to fetch", pointing at the I see that the interceptor does attach the root-cause in the |
Beta Was this translation helpful? Give feedback.
-
I'm currently receiving |
Beta Was this translation helpful? Give feedback.
-
I started a fresh node.js project and discovered msw. I thought it would be perfect for my scenario. At first I was disappointed at its inability to use |
Beta Was this translation helpful? Give feedback.
-
Run into an issue on rc-20.
Not sure if anyone else has this error. Lemme know if any more info needed. |
Beta Was this translation helpful? Give feedback.
-
Not sure if this is related to my previous issue or jsdom/jest environment, I can move this to a my previous post if necessary. In jsdom my server seems to send different responses that are not usable. As I'm testing react, I need to be in jsdom. I've made a pretty lightweight setup const server = setupServer();
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
beforeEach(() => {
server.use(
http.get<any>('http://localhost/jobs', () => {
return HttpResponse.json({ success: true });
}),
);
});
it.only('should show the issue', async () => {
const response = await fetch('http://localhost/jobs', {
headers: { 'Content-Type': 'application/json' },
signal: new AbortController().signal,
});
const result = await response.json();
expect(result).toBeDefined();
}); Two things I've noticed - i have to give it a signal, otherwise I get a "TypeError: Cannot read properties of undefined (reading 'addEventListener')" Once I've given it a signal, I simply get a
only in jsdom! If i swap out the test environment for node, works fine. Same with the signal, funnily enough. Apologies for the bombardment, appreciate the work you guys do. Not sure if this is the fault of jsdom or not. |
Beta Was this translation helpful? Give feedback.
-
I looked through the changes in the migration guide, and I'm really looking forward to the standardization on the fetch spec! This is fantastic work. I've really loved msw for the past two years. It really makes integration testing so much easier! What's the current status for releasing v2? What is lacking prior to cutting a production release? |
Beta Was this translation helpful? Give feedback.
-
Hello everyone, I'm trying to write simple app and some tests for it with jest. In my app I'm using redux-toolkit-query and tried to use msw for mocking as docs suggest and with regular version of msw everything worked fine untill form that sends Formdata to server. To fix it I installed msw@next and did all migrations as required, but now I only get TypeError: Failed to fetch error in response to all attempts to make fetch request Node versionv18.18.2 Packages versions"react-redux": "^8.1.2", API reducerconst specificEndPoints = [
'register',
'postArticle',
'updateArticle',
'getArticleContent'
]
export const blogApi = createApi({
reducerPath: 'blogApi',
tagTypes: ['Articles', 'ArticlesDetail', 'ArticlesContent', 'Comments'],
baseQuery: fetchBaseQuery({
baseUrl: '/api/',
prepareHeaders: (headers, { getState, endpoint }) => {
const token = (getState() as RootState)?.user?.token
if (token !== '') {
headers.set('Authorization', `Token ${token}`)
}
if (!specificEndPoints.includes(endpoint)) {
// headers.set('Content-Type', 'multipart/form-data')
// } else {
headers.set('Content-Type', 'application/json;charset=UTF-8')
}
return headers
}
}),
endpoints: () => ({})
}) Tested endpointsexport type ILoginResponse = {
token: string
userId: string
name: string
picture: string
isAdmin: boolean
}
export const userApi = blogApi.injectEndpoints({
endpoints: build => ({
login: build.mutation<ILoginResponse, ILoginData>({
query: body => ({
url: 'auth/login',
method: 'POST',
body
})
}),
checkAuth: build.query({
query: () => ({
url: 'auth/check',
method: 'GET'
})
}),
register: build.mutation<IFetchSuccess, FormData>({
query: body => {
return {
url: 'auth/registration',
method: 'POST',
credentials: 'include',
body
}
}
})
})
})
export const { useLoginMutation, useRegisterMutation, useCheckAuthQuery } =
userApi One of failed testsconst handlers = [
http.post('/api/auth/login', () => {
return Response.json(
{
userId: 1,
name: 'Kovalev Aleksandr',
token: 'fsafsefaefaewf',
picture: null,
isAdmin: false
},
{ status: 200 }
)
})
]
const server = setupServer(...handlers)
// console.log(server.listHandlers())
describe('Login page', () => {
beforeAll(() => server.listen())
// Reset any runtime request handlers we may add during the tests.
afterEach(() => server.resetHandlers())
// Disable API mocking after the tests are done.
afterAll(() => server.close())
test('Login work', () => {
renderWithProviders(<Login />, { router: 'browser' })
const emailField = screen.getByLabelText('Email')
expect(emailField).toBeInTheDocument()
const passwordField = screen.getByLabelText('Пароль')
expect(passwordField).toBeInTheDocument()
const button = screen.getByRole('button')
expect(button).toBeInTheDocument()
})
test('Login use', async () => {
const { store } = renderWithProviders(<App />, {
router: 'memory',
routerProps: { initialEntries: ['/login'] }
})
const emailField = screen.getByLabelText('Email')
fireEvent.input(emailField, { target: { value: '[email protected]' } })
const passwordField = screen.getByLabelText('Password')
fireEvent.input(passwordField, { target: { value: '123456789' } })
const button = screen.getByTestId('login-submit')
fireEvent.click(button)
const avatar = await screen.findByTestId('logged-avatar')
expect(avatar).toBeInTheDocument()
const articleTitle = await screen.findByText('Articles')
expect(articleTitle).toBeInTheDocument()
const unloginButtons = await screen.findAllByText(/Logout/i)
expect(unloginButtons).toHaveLength(2)
const state = store.getState()
expect(state.user).toMatchObject({
userId: 1,
name: 'Kovalev Aleksandr',
token: 'fsafsefaefaewf',
picture: null,
isAdmin: false
})
fireEvent.click(unloginButtons[0])
const loginButtons = await screen.findAllByText(/Войти/i)
expect(loginButtons).toHaveLength(2)
})
}) Componentexport type ILoginData = {
email: string
password: string
}
const Login: FC = () => {
const [sendLogin, { data, error }] = useLoginMutation()
console.log({ data, error })
const dispatch = useAppDispatch()
const { handleSubmit, control } = useFetchForm<ILoginData>(error)
const onSubmit = async (data: ILoginData): Promise<void> => {
await sendLogin(data)
}
useEffect(() => {
if (data !== undefined) {
localStorage.setItem('auth', JSON.stringify(data))
dispatch(login(data))
}
}, [data, dispatch])
return (
<CenterContainer>
<StyledFormBox component='form' onSubmit={handleSubmit(onSubmit)}>
<Typography variant='h4'>Login</Typography>
<HookedTextField
control={control}
defaultValue=''
label='Email'
name='email'
required
autoFocus
fullWidth
variant='standard'
type='email'
sx={{
color: 'inherit'
}}
/>
<HookedTextField
label='Password'
variant='standard'
control={control}
defaultValue=''
name='password'
required
fullWidth
type='password'
sx={{
color: 'inherit'
}}
/>
<Button type='submit' variant='contained' data-testid='login-submit'>
Login
</Button>
</StyledFormBox>
</CenterContainer>
)
}
export default Login |
Beta Was this translation helpful? Give feedback.
-
MSW 2.0 is out! 🎉As of today, I would like to say a huge thank you to everybody who's contributed to that release in this discussion. You are incredible. I did my best to go through all the comments and mention you all in the announcement blog post. If I missed someone, pull requests are welcome! I will lock this thread. I encourage you to report the issues with 2.0 as you normally would (by creating a new Issue in this repository). Thanks. |
Beta Was this translation helpful? Give feedback.
-
Hey! Thank you for taking the time to help us with the next library release. We’re approaching this one as a release candidate because it contains quite a number of breaking changes.
Motivation
The main motivation behind this release is to rework the public API to respect and use the Fetch API standard. This means handling intercepted requests as
Request
instances and expecting the mocked responses to be declared asResponse
instances. While this may sound simple, it requires a significant change to how MSW is used by each of you.This is also the biggest API change we’ve had since the day I pushed the
req, res, ctx
API. With this release, that era is gone and so is that API. The next era begins and it looks fantastic.Before you begin
The purpose of this beta release is to gather your feedback on the changes. We kindly ask you to share such feedback in the comments under this discussion, following these rules:
Getting started
👉 Please follow the Migration guide to learn more about how to install this beta release and the migration instructions for every feature we’ve changed or deprecated.
Expect breaking changes. It will require some effort to migrate any existing MSW setup to the new API but it’s going to be worth it.
What is expected from the participants?
Frequently asked questions
Are these changes backward-compatible?
No. Backward compatibility is beneficial when you want to have the advantage of the change while remaining on the previous API. This change, however, is about the API, so maintaining backward compatibility is not feasible for it. If you wish to use the previous API you can do so by staying on the previous version. However, you will update to these changes eventually as this is the public API we’re going forward with.
Are these changes “production” ready?
No. Be mindful that you’re trying out a beta release of the library. Things may and likely will change as we iterate through your feedback.
That being said, the API changes proposed in this release will end up in the public release, eventually. This is the direction we’re taking, so migrating to it may ease any additional changes you need to do in your setup once this release becomes public.
When is this release going to be public?
As soon as we gather enough feedback to be certain people can migrate to the new version without issues. We will then release the changes under the
latest
tag, updating the documentation respectively.Beta Was this translation helpful? Give feedback.
All reactions