Gathering detailed insights and metrics for cypress-msw-interceptor
Gathering detailed insights and metrics for cypress-msw-interceptor
Gathering detailed insights and metrics for cypress-msw-interceptor
Gathering detailed insights and metrics for cypress-msw-interceptor
msw
Seamless REST/GraphQL API mocking library for browser and Node.js.
cypress
Cypress is a next generation front end testing tool built for the modern web
playwright-msw
A Mock Service Worker API for Playwright.
@pactflow/pact-msw-adapter
> Generate pact contracts from the recorded mock service worker interactions.
npm install cypress-msw-interceptor
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
42 Stars
53 Commits
10 Forks
3 Watching
4 Branches
4 Contributors
Updated on 10 Oct 2023
Minified
Minified + Gzipped
JavaScript (92.28%)
Shell (3.51%)
HTML (1.94%)
TypeScript (1.56%)
CSS (0.71%)
Cumulative downloads
Total Downloads
Last day
234.4%
1,602
Compared to previous day
Last week
100.5%
7,831
Compared to previous week
Last month
53.2%
28,782
Compared to previous month
Last year
28.5%
184,810
Compared to previous year
27
A networking layer for Cypress using MSW.
Both Cypress and MSW are amazing technologies, this plugin takes the features of
MSW and adapts its API to work with Cypress in a way that cy.route
works.
This plugin will start a MSW worker as part of the Cypress runner and intercept
fetch
requests made from the application being tested. MSW does not need to be
installed as part of application. This allows requests to be mocked using the
fantastic mocking ability of MSW and/or wait for requests to be completed before
continuing in a test.
To install the package run:
1$ npm install cypress-msw-interceptor msw --save-dev 2# or 3$ yarn add cypress-msw-interceptor msw --dev
Then in cypress/support/index.js
add:
1import 'cypress-msw-interceptor'
If you need to customize the MSW Worker start options. You can do so like:
1import { setMswWorkerOptions }, 'cypress-msw-interceptor' 2 3setMswWorkerOptions({ quiet: true, onUnhandledRequest: 'bypass' })
Next we need initialize msw. Follow the guide form MSW website.
You don't need to configure the worker or create handlers unless you want to use
it in your application too. The integration for cypress-msw-interceptor
will
happen automatically by importing cypress-msw-interceptor
.
Lastly, we need to set the baseUrl
for Cypress so that Cypress starts at the
same address as the application so that the service worker can be registered
correctly.
All examples use @testing-library/cypress. If you don't know it, check it out, it's the best way to write tests in Cypress in my opinion.
To intercept a request use the cy.interceptRequest
command:
1it('should be able to mock a request with msw', () => { 2 cy.interceptRequest( 3 'GET', 4 'https://jsonplaceholder.typicode.com/todos/1', 5 (req, res, ctx) => { 6 return res( 7 ctx.json({ 8 userId: 1, 9 id: 1, 10 title: 'Lord of the rings', 11 completed: false, 12 }), 13 ) 14 }, 15 ) 16 17 cy.visit('/') 18 cy.findByText(/lord of the rings/i).should('be.visible') 19})
This test will intercept a GET
(method) request to
https://jsonplaceholder.typicode.com/todos/1
(route) and respond with the
mocked payload returned from the response resolver.
This is very similar to cy.route
except it uses MSW to mock the response. To
learn more about the features of the response resolver, check out the
MSW documentation.
In Cypress to wait for a request to complete you would have to alias a request
and then use cy.wait('@alias)
(Cypress Route Documentation).
cypress-msw-interceptor
provides a similar API to achieve this:
1it('should be able to wait for a request to happen before it checks for the text', () => { 2 cy.interceptRequest( 3 'GET', 4 'https://jsonplaceholder.typicode.com/todos/1', 5 (req, res, ctx) => { 6 return res( 7 ctx.delay(1000), 8 ctx.json({ 9 userId: 1, 10 id: 1, 11 title: 'Lord of the rings', 12 completed: false, 13 }), 14 ) 15 }, 16 'todos', 17 ) 18 19 cy.visit('/') 20 cy.waitForRequest('@todos') 21 cy.findByText(/lord of the rings/i).should('be.visible') 22})
A request can be aliased using the third or forth (depending if a mock is
provided) argument to cy.interceptRequest
. The use cy.waitForRequest
with
the alias
with a preceding @
to wait for that request to complete before
finding the text on the page. To learn more about Cypress aliases check out the
Cypress Aliases Documentation.
cy.interceptRequest
will also work with the native .as('alias')
chainable
from Cypress, but that will not show the pretty badge in the test runner if you
do. It's recommended that you use the third or forth argument so you get the
best debugging experience.
This can also be done with a request that isn't mocked. This is particularly useful for end to end test:
1it("should be able to wait for a request to happen that isn't mocked before it checks for the text", () => { 2 cy.interceptRequest( 3 'GET', 4 'https://jsonplaceholder.typicode.com/todos/1', 5 'todos', 6 ) 7 cy.visit('/') 8 9 cy.waitForRequest('@todos') 10 cy.findByText(/some known text value/i).should('be.visible') 11})
By not providing a response resolver, the request executed as it normally but
will allow cypress-msw-interceptor
to track the request and wait for the
alias.
You could conditionally include the response resolver so the test sometimes runs as an integration test and sometimes as an end to end test:
1function shouldMockResponse(fn) { 2 return process.env.CYPRESS_E2E === 'true' ? fn : undefined 3} 4 5cy.interceptRequest( 6 'GET', 7 'https://jsonplaceholder.typicode.com/todos/1', 8 shouldMockResponse((req, res, ctx) => { 9 return res( 10 ctx.delay(1000), 11 ctx.json({ 12 userId: 1, 13 id: 1, 14 title: 'Lord of the rings', 15 completed: false, 16 }), 17 ) 18 }), 19 'todos', 20)
This way, you could choose to run some tests end to end in some environments and not others.
In order to be able to run a test both as integration and end to end, it's
important to be able to add assertions in your tests that are derived from the
response
:
1it('should be able to get the response and check that the correct text is displayed', () => { 2 cy.visit('/') 3 cy.interceptRequest( 4 'GET', 5 'https://jsonplaceholder.typicode.com/todos/1', 6 (req, res, ctx) => { 7 return res( 8 ctx.delay(1000), 9 ctx.json({ 10 userId: 1, 11 id: 1, 12 title: 'Lord of the rings', 13 completed: false, 14 }), 15 ) 16 }, 17 'todos', 18 ) 19 20 cy.waitForRequest('@todos').then(({ request, response }) => { 21 cy.findByText(new RegExp(response.body.title, 'i')).should('be.visible') 22 }) 23})
In the example above, cy.waitForRequest
will wait for the request to complete
and then return the request
and the response
which can be used in the
assertion.
Sometimes it's important to know how many times a request was made. This can be
checked by using the cy.getRequestCalls
:
1cy.visit('/') 2cy.interceptRequest( 3 'GET', 4 'https://jsonplaceholder.typicode.com/todos/1', 5 'todos', 6) 7 8cy.waitForRequest('@todos').then(({ request, response }) => { 9 cy.getRequestCalls('@todos').then(calls => { 10 expect(calls).to.have.length(1) 11 }) 12})
Sometimes the same request should respond with different values.
cypress-msw-interceptor
allows you to update a request by redefining an
interceptor definition:
1it('should be able to update the mock', () => { 2 cy.visit('/') 3 cy.interceptRequest( 4 'GET', 5 'https://jsonplaceholder.typicode.com/todos/1', 6 (req, res, ctx) => { 7 return res( 8 ctx.json({ 9 userId: 1, 10 id: 1, 11 title: 'Lord of the rings', 12 completed: false, 13 }), 14 ) 15 }, 16 'todos', 17 ) 18 19 cy.waitForRequest('@todos') 20 cy.getRequestCalls('@todos').then(calls => { 21 expect(calls).to.have.length(1) 22 }) 23 cy.findByText(/lord of the rings/i).should('be.visible') 24 25 cy.interceptRequest( 26 'GET', 27 'https://jsonplaceholder.typicode.com/todos/1', 28 (req, res, ctx) => { 29 return res( 30 ctx.json({ 31 userId: 1, 32 id: 1, 33 title: 'The outsider', 34 completed: false, 35 }), 36 ) 37 }, 38 'todos', 39 ) 40 cy.findByRole('button', { name: /refetch/i }).click() 41 cy.waitForRequest('@todos') 42 cy.getRequestCalls('@todos').then(calls => { 43 expect(calls).to.have.length(2) 44 }) 45 cy.findByText(/the outsider/i).should('be.visible') 46})
MSW provides an easy way to mock GraphQL queries. To make the same API available
cypress-msw-interceptor
has custom Cypress extensions to work with that API.
To mock a query with the name of CoursesQuery
:
1cy.interceptQuery( 2 'CoursesQuery', 3 (req, res, ctx) => { 4 return res( 5 ctx.delay(1000), 6 ctx.data({ 7 courses: [ 8 { 9 userId: 1, 10 id: 1, 11 title: 'GET me some data', 12 completed: false, 13 }, 14 ], 15 }), 16 ) 17 }, 18 'courses', 19) 20cy.visit('/') 21 22cy.findByRole('button', { name: /get graphql/i }).click() 23cy.waitForQuery('@courses').then(({ response }) => { 24 cy.getQueryCalls('@courses').then(calls => { 25 expect(calls).to.have.length(1) 26 }) 27 cy.findByText(new RegExp(response.body.data.courses[0].title, 'i')).should( 28 'be.visible', 29 ) 30})
This can also be done for a query that hasn't been mocked:
1cy.interceptQuery('CoursesQuery', 'courses') 2cy.visit('/') 3 4cy.findByRole('button', { name: /get graphql/i }).click() 5cy.waitForQuery('@courses').then(({ response }) => { 6 cy.getQueryCalls('@courses').then(calls => { 7 expect(calls).to.have.length(1) 8 }) 9 cy.findByText(new RegExp(response.body.data.courses[0].title, 'i')).should( 10 'be.visible', 11 ) 12})
In a similar way to queries, there is an extension for GraphQL Mutations:
1cy.interceptMutation( 2 'UpdateCourse', 3 (req, res, ctx) => { 4 return res( 5 ctx.delay(1000), 6 ctx.data({ 7 courses: [ 8 { 9 userId: 1, 10 id: 1, 11 title: 'GET me some data', 12 completed: false, 13 }, 14 ], 15 }), 16 ) 17 }, 18 'updateCourse', 19) 20cy.visit('/') 21 22cy.findByRole('button', { name: /mutate graphql/i }).click() 23cy.waitForMutation('@updateCourse').then(({ response }) => { 24 cy.getMutationCalls('@updateCourse').then(calls => { 25 expect(calls).to.have.length(1) 26 }) 27 cy.findByText(new RegExp(response.body.data.courses[0].title, 'i')).should( 28 'be.visible', 29 ) 30})
In a similar way, we can wait for requests that weren't mocked:
1cy.interceptMutation('UpdateCourse', 'updateCourse') 2cy.visit('/') 3 4cy.findByRole('button', { name: /mutate graphql/i }).click() 5cy.waitForMutation('@updateCourse').then(({ response }) => { 6 cy.getMutationCalls('@updateCourse').then(calls => { 7 expect(calls).to.have.length(1) 8 }) 9 cy.findByText(new RegExp(response.body.data.courses[0].title, 'i')).should( 10 'be.visible', 11 ) 12})
public
folder of the
application.To start the development environment run:
1yarn install 2yarn start
To run the Cypress tests run while the application is running in another terminal:
1yarn run cypress:open
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
Found 4/22 approved changesets -- score normalized to 1
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
59 existing vulnerabilities detected
Details
Score
Last Scanned on 2024-11-25
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More