본문 바로가기

cypress를 써보자! (2)

< cypress를 써보자! (1)                                                    

> cypress를 써보자! (3)

 

목차


1. Webpack resolve.alias

2. Settig up CI

3. One intercept, multiple responses


 

 

1. Webpack resolve.alias

1주차에서 jsconfig.json에 alias 설정을 추가했다.

그러나 cypress:open 시 절대 경로를 못찾는 에러가 발생했다.

 

cypress 웹팩 설정에서 resolve.alias를 해주지 않아 발생한 이슈였다.

따라서 cypress/plugins/index.js에 webpack resolve.alias 또한 추가했다.

// ./cypress/plugins/index.js

// ... 중략 ...

module.exports = (on, config) => {
  const webpackOptions = findWebpack.getWebpackOptions()
  
  // ... 중략 ...
  
  const options = {
    webpackOptions: merge(webpackOptions, {
      resolve: {
        alias: {
          $components: path.resolve('src/components'),
          $cypress: path.resolve('cypress/')
        }
      }
    }),
    watchOptions: {}
  }
  
  on('file:preprocessor', webpackPreprocessor(options))
  
  config.env.host = getHostByProfiles(process.env.REACT_APP_PROFILES) 
  
  return config
}

 

2. Settig up CI

저번 주에 설정한 npm script에서는 수동으로 서버 부팅 후 cypress를 실행해야만 테스트가 가능했다.

서버를 부팅하는 데 시간이 오래 걸리기 때문에 완전히 실행되기 전에 cypress 테스트를 run하면 테스트에 실패한다.

 

따라서 서버가 완전히 켜질 때까지 기다렸다가 cypress를 open하는 스크립트로 변경하였다.

 

가이드에서는 wait-on 모듈을 사용하는 방법과 start-server-and-test module을 사용하는 방법 두 가지를 안내하였는데 이 중에 start-server-and-test module을 사용하였다.

 

 

If the server takes a very long time to start,

we recommend trying the start-server-and-test module.

 

 

start-server-and-test 라이브러리는 첫번째 npm script를 실행 후 {URL}이 HttpStatus 200으로 정상 응답할 때까지 기다렸다가 다음 script를 실행한다.

"test:ci:local": "cross-env REACT_APP_PROFILES=local start-server-and-test start http://localhost:3000 cypress:open",
"test:ci:real": "cross-env REACT_APP_PROFILES=real start-server-and-test real http://localhost:5000 cypress:open",

 

3. One intercept, multiple responses

테스트 코드를 작성하다가 한번 intercept한 HttpRequest에 대해 각각 다른 Response를 응답해야 하는 경우가 있었다.

다음은 내 예시이다.

 

사용자가 서비스에서 조회한 쇼핑몰 매출액 내역을 GET하는 /api/list/exist XHR에 대해,

 

1. 첫번째 호출 시, 약관동의내역 없음 응답을 받는다.

{
  isAgree: false
}

2. 약관동의 후 두번째 호출 시, 빈 값 응답을 받는다.

{
  isExist: false,
  list: []
}

3. 매출액을 조회하는 /api/sales API 응답을 받은 후 세번째 호출 시, 조회한 값이 들어있는 응답을 받는다.

{
  isExist: true,
  list: [
    {
      module: 'coupang',
      revenue: 2000000
    }
  ]
}

 

이렇게 프로세스에 따라 같은 XHR에 대해 각각 다른 값을 응답으로 주어야 하는 경우에는 어떻게 intercept를 작성할까.

나같은 경우, request가 없는 XHR이기 때문에 routeHandler의 req.body 값으로 구분하기도 어려웠다.

 

따라서 isAgree, isGettingSales 외부 변수를 두어 아래처럼 작성하였다.

변경이 필요한 위치에서 isAgree, isGettingSales를 true로 함으로써 다른 response를 응답하도록 작성했다.

let isAgree = false
let isGettingSales = false

cy.intercept('GET', '/api/list/exist', (req) => {
  if (isGettingSales) { // 세번째 호출
    req.reply({
      fixture: `${fixturePath}/exist_after_sales.json`,
    })
    return
  }

  if (isAgree) { // 두번째 호출
    req.reply({
      fixture: `${fixturePath}/exist_init.json`,
    })
    return
  }

  /* 첫번째 호출 */
  isAgree = true
  req.reply({
    fixture: `${fixturePath}/exist_need_agree.json`,
  })
}).as('getExist')

cy.intercept('POST', '/api/sales', (req) => {
  isGettingSales = true
  req.reply({
    fixture: `${fixturePath}/sales_coupang.json`,
  })
}).as('getSales')

 

만약, request에 따라 구분이 가능하다면 아래처럼 작성할 수 있다.

cy.intercept('POST', '/api/login', (req) => {
  if (!req.body.is2Pass) {
    req.reply({
      fixture: `${fixturePath}/login_need_2pass.json`
    })
    return
  }
  
  req.reply({
    fixure: `${fixturePath}/login_success.json`
  })
})