Cypress 테스트 코드 작성 중 SSR에서 호출하는 API는 intercept가 안되는 현상이 있어서 해결하는데 고생좀 했다.
결론은 Cypress 전용 NextJS 서버를 하나 더 만들어주고 nock 라이브러리를 통해 api를 mock data로 바꿔주면 된다.
cypress/plugins/index.js 에 다음과 같이 작성해주자.
const nock = require('nock');
const next = require('next');
const express = require('express');
const CYPRESS_SERVER_PORT = 3000;
// start the Next.js server when Cypress starts
module.exports = async (on, config) => {
const app = next({ dev: true });
const handle = app.getRequestHandler();
app
.prepare()
.then(() => {
const server = express();
server.get('*', (req, res) => {
return handle(req, res);
});
server.listen(CYPRESS_SERVER_PORT, () => {
console.warn(`SSR server running, client path is http://localhost:${CYPRESS_SERVER_PORT}`);
});
})
.catch(ex => {
console.error('ex', ex.stack);
process.exit(1);
});
// register handlers for cy.task command
// https://on.cypress.io/task
on('task', {
clearNock() {
nock.restore();
nock.cleanAll();
return null;
},
async nock({ hostname, method, path, statusCode, body }) {
nock.activate();
console.log(
'nock will: %s %s%s respond with %d %o',
method,
hostname,
path,
statusCode,
body,
);
// add one-time network stub like
// nock('https://icanhazdadjoke.com').get('/').reply(200, ...)
method = method.toLowerCase();
nock(hostname)
[method](path)
.reply(statusCode, body);
return null;
},
});
return config;
};
사용법은 다음과 같다. body에 mock data를 넣어주자.
import projectDetail from '../../fixtures/project/projectDetail';
describe('상세페이지', () => {
beforeEach(() => {
cy.task('clearNock');
});
context('기본', () => {
before('', () => {});
it('랜더 체크', () => {
cy.task('nock', {
hostname: Cypress.env('API_URL'),
method: 'GET',
path: '/api/v2/projects/2000',
statusCode: 200,
body: projectDetail,
});
cy.visit('/projects/2000');
});
});
});
cypress 버전은 다음과 같다.
"cypress": "^9.1.1",