I have a server.get set up to listen to a request url but whenever I am running the tests, I seem to end up with undefined in my response
msw": "^0.19.3nodejs: 12.13.0npm: 6.12.0Steps to reproduce the behavior:
I should be able to intercept the request and consume the payload I give ctx
``const server = setupServer(
rest.get('*', req => console.log(req.url.href)),
rest.get(/api/portfolioCalls`, (req, res, ctx) => {
return res(ctx.status(200), ctx.json(propertiesData))
}),
)
describe('PortfolioReport', () => {
beforeAll(() => server.listen())
afterAll(() => server.close())
afterEach(() => server.resetHandlers())
const checkForUserActivity = jest.fn()
const switchToPropertyView = jest.fn()
const setDateRange = jest.fn()
beforeEach(() => {})
it('should render component', async () => {
act(() => {
render(
switchToPropertyView={switchToPropertyView}
setDateRange={setDateRange}
/>
)
})
const { getByText } = screen
expect(getByText('Portfolio')).toBeInTheDocument()
await wait(() => {
expect(getByText('Total Calls')).toBeInTheDocument()
})
screen.debug()
})
})
this is the axios call i am trying to listen to
try {
const result = await axios.get(
${HOSTNAME}/api/portfolioCalls?startDate=${startDate}&endDate=${endDate}
)
if (result?.status === 200 && result?.data) {
const formattedData = formatData(result.data)
dispatch({
type: FETCH_PORTFOLIO_SUCCESS,
payload: formattedData.properties,
status: SUCCESS,
})
setData(formattedData)
} else setData({})
} catch (error) {
dispatch({ type: FETCH_PORTFOLIO_ERROR, status: ERROR })
console.log(error)
}
}
```
Hey, @lammypham. Thanks for transferring this issue to the repo!
Could you please show me what is the value of HOSTNAME you use to compose a request URL for axios?
When running request matching in Node, considered jsdom (browser-like) environment, when you given a relative URL in your request handler (rest.get('/login')), it appends a location origin from the window to make an absolute URL out of it. I have a feeling that jsdom location and your custom HOSTNAME may differ, that's why the request matching may not capture your request.
Interesting. I was wondering about that so i was hoping the pattern matching would help
export const HOSTNAME = window.location.hostname === 'localhost' ? 'http://web101.levelone.com' : ''
Does it help if you prepend the HOSTNAME to the request handler?
rest.get(`${HOSTNAME}/medsapi/api/answerautomation/portfolioCalls`, ...)
By the way, you are doing the right thing by not including the query parameters in the request handler's URL! Those matter not during capturing, and must not be included.
That's _not_ a solution, but may help us to figure out if the hostname is the problematic part.
This was actually what I was doing before and didn't find success. Then I realized that the url does pattern matching there.
I even hardcoded the url just for kicks and giggles.
Whenever I do,
rest.get('*', req => console.log(req.url.href)),
am I expected to see a log in my terminal, because currently when I run this I do not. I wonder if the msw is intercepting the request at all.
The scenario of using intercepting relative URLs is not directly covered by MSW tests yet. Since our tests run in Node (or Node-like) environments, we are using node-fetch, which cannot be called with a relative URL as a part of a test.
There is a unit test in the REST API example that handles a relative URL request from the Login component. That test passes, but it has a few deviations from your scenario:
window.fetch instead of axios.HOSTNAME in the request URL. I still think this is the biggest factor influencing this issue. @lammypham, may I please ask you to put down a minimum reproduction repo? You can use the existing REST API example, just modifying the necessary parts (using axios and configuring the actual request URL the same way you do in your app). That would be the most helpful in resolving this issue. Thanks!
I haven't done this before but I hope this is helpful!
https://github.com/lammypham/msw-lammypham
Hi @lammypham,
I have tried with your example to reproduce the issue but it didn't happen to me. The code below is the result of the axios get.
data: { userName: 'John' },
status: 200,
statusText: 'OK',
headers: { 'x-powered-by': 'msw', 'content-type': 'application/json' },
config: {
adapter: [Function: xhrAdapter],
transformRequest: { '0': [Function: transformRequest] },
transformResponse: { '0': [Function: transformResponse] },
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
headers: { Accept: 'application/json, text/plain, */*' },
method: 'get',
url: '/login',
data: undefined
},
As you can see I received an object containing the information returned from the mock. Which kind of problem did you have?
Hey @marcosvega91 thanks for taking a look.
I wasn't able to mimic the same current situation. The application i am working on is a SPA app that gets baked into a monolithic application. so the HOSTNAME is handled by determined whether it is local or in a staging environment.
As long as you use the same request URL, you are going to get the request match and mocked response. Most likely due to the HOSTNAME being env-specific, something goes off, and your actual request's URL doesn't match the one declared in the request handler.
Hm. Sorry im not quite sure what the next steps are here.
Should i change anything in my reproduction repo for me to make it anything as similar as to the issue i am having?
Hey, @lammypham.
I've issued a pull request to your reproduction repository. The test passed even without my changes, but since the App component was not performing an async request properly, I've decided to update the example so you can see the changes.
As I've written above, the next step is for you to ensure your request URL is the same between environments. Depending on your setup this may mean you need to reflect your conditional URL in mock definition as well (i.e. bring in the HOSTNAME environmental variable). I don't see an unexpected behavior from MSW here, so I'm closing the issue. Still, feel free to update us here with your findings. Thanks.
So i've implemented this MSW again on another endpoint which seemed to worked and i've been comparing the two to see why i haven't been able to receive a response from this current one.
One thing i noticed is that the endpoint i am testing here when i pass the endpoint on the browser is that its an XML response
<ArrayOfPropertyOverviewData xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/MedsAPI.Models">
Could be a stretch, but wanted to see if this is the cause?
ok so i fixed it. i forgot when i was switching from jest.mock('axios') to msw i forgot to remove the jest.mock('axios') in my setUpTest.js
one question, if i wanted to test the same endpoint for a 400 or an error, how would i go about doing that?
Glad to hear the issue if fixed for you, @lammypham!
You can make a single endpoint behave differently on a per-test basis using server.use() method. It allows to modify an endpoint's behavior on runtime. Combine it with server.resetHandlers() in the afterEach hook of your tests, and now each test can teardown its own breakpoints and override existing ones.