vue 프로젝트에 jest 추가하기

해피데빙·2023년 2월 16일
0

description

  1. eslint-plugin-jest
  • eslint 전역적으로 설정해서 eslint-plugin-jest도 전역적으로 설치해야 한다
  • jest를 .eslintrc 파일의 plugin으로 추가
  1. pino-pretty
  • @types/pino-pretty : typescript 4.3으로 update하면서 type 필요로 함
  • node_modules/@types/pino-pretty에 index.d.ts가 없어서 문제 : npm preinstall할 때 직접 생성하고 있음
    => 결국 삭제
  1. babel-eslint
    import 키워드를 eslint가 이해할 수 있게 babel 이용해서 최신 버전의 내용을 다운 버전에게 통역
  1. babel/core
    babel compiler core

package.json vs package-lock .json

  • major version.minor version.fetch version
    ex. 4.1.1

  • semantic versioning 확인하기
    semantic versioning

  • package.json : ^4.3.1처럼 ^를 써야 npm install할 때 최신 버전을 가져온다

  • package-lock.json : package.json에서 명시한 명령대로 install한 최종 버전
    => npm install할 때는 package-lock.json 기준으로 install하는데 만약 package.json이랑 다른 부분이 있으면 package.json 바탕으로 install

에러 해결

에러 1 dependency

  • ts-jest@28.0.1 설치
  • babel-jest@29.5.0 존재
  • ts-jest 파일에 있는 babel-jest와 버전 다름 : babel-jest@28.1.3

1차 시도 : root에 있는 babel-jest를 28.1.3으로 변경 시도
eslint@6.8.0이랑 충돌 => typescript-eslint/eslint-plugin@5.0.0
eslint-plugin-jest@27.2.1로 설치했는데 eslitn 7이상이어야 함
그러므로 eslint-plugin-jest@25로 버전 내리고 babel-jest도 27.0으로 내림

2차 시도 : ts-jest 폴더에 babel-jest@29.5.0로 설치
node_modules 삭제하고 설치하면 될일을 이렇게 할 필요가 없었음

3차 시도 : typescript 버전 업그레이드 (4.2.3 => 4.3)

4차 시도 : typescript 관련 eslint 에러 발생

suberror : typescript upgrade side effects

cf. parse5

  • provides nearly everything you may need when dealing with HTML.
  • It's the fastest spec-compliant HTML parser for Node to date.
  • It parses HTML the way the latest version of your browser does. It has proven itself reliable in such projects as jsdom, Angular, Lit, Cheerio, rehype and many more.
    -> html을 브라우저의 최신 버전에 맞게 파싱해주는 거

cf. tsc : 타입스크립트를 자바스크립트로 변환할 때 사용하는 명령어
cf. tsc --noEmit :
Do not emit compiler output files like JavaScript source code, source-maps or declarations.
This makes room for another tool like Babel, or swc to handle converting the TypeScript file to a file which can run inside a JavaScript environment.
You can then use TypeScript as a tool for providing editor integration, and as a source code type-checker

1차 시도 : tsc가 없어서 typescript install -g
2차 시도 : where tsc로 위치 확인, require()하고 있는 위치에 파일 존재 X 확인

  • typescript install 확인 / reinstall 또는 update typescript
  • tsconfig.json 파일 존재하는지 확인
  • This file specifies the configuration options for the TypeScript compiler, including the location of the tsc.js file. 해결 출처
  • tsc 명령어 돌린 결과 : cannot find type definition file for 'pino-pretty'

이유: node_modules/@types 안에 해당 패키지의 index.d.ts 파일이 존재하지 않아서

These errors occur when you have subdirectories of a typeRoots directory (in this case node_modules/@types) that do not contain index.d.ts files. I agree the error message is mysterious and should be improved.
The entry "@types/": "pino-pretty" caused it to be downloaded directly into the node_modules/@types folder, creating new files and subdirectories unrecognized by the TypeScript compiler alongside the existing valid subdirectories. I'm guessing you ran yarn add @types/@pino-pretty, trying to install the @types package for the scoped package @types/@pino-pretty, but that command is actually parsed as installing a package named @types/ at version reach/router. You probably meant @types/reach__router: that's the naming convention for @types packages for scoped packages. Consider filing a bug against Yarn for letting you install a package with the invalid name @types/. (I notice that NPM correctly catches this.)
  • downloaded directly into the node_modules/@types folder

  • create new files and subdirectories unrecognized by typescript compiler

  • 해결:
    1) mode_modules/@types/pino-pretty 안에 index.d.ts파일 만들기
    2) tsconfig.json 파일

{ 
///
 compilerOptions: { 
	types: ["pino-pretty"]
 }
///
}
  • es6 const, used before defined(no-use-before-defined)

  • subdmoule에 대한 es6 lint만 깨짐 ex. const,

에러

유의할 점

  • vue2 프로젝트
    : vue는 3까지 나와서 모든 관련 라이브러리들이 3을 기준으로 version을 update해놨다
    : npm install로 라이브러리를 설치하면 vue3을 기준으로 하는 최신 버전이 설치된다
    : vue2를 기준으로 하는 버전의 라이브러리 설치하기

  • 맨날 나는 에러들

  1. vue packages version mismatch vue@2.7.8 vue template-compiler@2.7.14

npm list vue
npm list vue-template-compiler
npm install vue-template-compiler@<version> --save-dev
  1. Test suite failed to run ReferenceError: Vue is not defined
    또는 SecurityError: localStorage is not available for opaque origins

  • jest-environment-jsdom 설치
  • jest.config.js에서 testEnvironment: jest-environment-jsdom 넣어주기
  • 이외의 문제: 프로젝트에서 Vue를 직접 import Vue해서 쓰는 게 아니라
    new webpack.ProvidePlugin({
      Vue: ["vue/dist/vue.runtime.esm.js", "default"]
    }),
    new VueLoaderPlugin()

이렇게 사용하고 있다
ProvidePlugin은 import, require할 필요 없이 자동으로 로드할 수 있게 해준다

이런 경우에 jsdom이 바로 vue에 접근할 수 없다

//jest.setup.js
window.Vue = require('vue');
//window.Vue는 Vue를 전역에서 사용할 수 있도록 만들어준다
//jest.config.js
"setupFiles": [ "<rootDir>/jest.setup.js" ],

이렇게 window에 Vue를 넣어두고
config에서 setup을 해주면 된다

  1. SyntaxError: Cannot use import statement outside a module

this error message occurs when you try to use the import statement in a JavaScript file that is not being treated as a module.
Starting from ES6, JavaScript introduced a new module system, which allows developers to organize their code into modules, making it more maintainable and easier to share. To use this module system, you need to specify that a file should be treated as a module.

you can use a transform module ex.Babe(ES6+ -> older, node.js) to convert your ES6 modules into CommonJS modules that Jest can understand.

해결방법

npm install --save-dev @babel/core @babel/preset-env babel-jest

.babelrc(서브셋 디렉토리 또는 파일에서 특정한 플러그인이나 변형 시 사용) 또는
babel.config.json (여러 패키지 디렉토리를 가진 프로젝트에서 하나의 바벨 설정 가져갈 때, 보편적)
babel.config,js (바벨 구성 api가 노출된다)

{
  "presets": ["@babel/preset-env"]
  //babel의 preset-env를 사용해서 transform
}

cf.
@babel/preset-env is a smart preset that allows you to use the latest JavaScript without needing to micromanage which syntax transforms (and optionally, browser polyfills) are needed by your target environment(s). This both makes your life easier and JavaScript bundles smaller!

jest.config.js

module.exports = {
  transform: {
    '^.+\\.js?$': 'babel-jest',
  },
};

//babel에게 어떤 Js파일이든 babel을 이용해 변경하도록 (ES6 : import -> commonJS :require로)

babel로 다른 버전의 js를 이전 버전 호환 가능하게 만들어주는 과정이 필요하다

"core-js": "^3.8.3",
"ts-jest": "^29.0.5",

cf.

jest.setup.js

  • 모든 테스트 케이스 전 자동 실행 파일
  • 글로벌 test environment configuration
    test environment variables, setting up test fixtures, and configuring mock modules.
    jest.init.js
  • runs once, before running any test suites or jest.setup.js
  • typicaly used to set up Jest's runtime configuration (text reporter, custom matcher)
  • typically used to set up Jest's runtime configuration, such as configuring test reporters or setting up custom matchers. This file is often used to configure Jest's behavior globally, across all test suites in a project.

jest.config.js

module.exports = {
    // 파일 확장자를 지정하지 않은 경우, Jest가 검색할 확장자 목록입니다.
    // 일반적으로 많이 사용되는 모듈의 확장자를 지정합니다.
    moduleFileExtensions: [
      'js',
      'json',
      'vue'
    ],
    // `@`나 `~` 같은 경로 별칭을 매핑합니다.
    // E.g. `import HelloWorld from '~/components/HelloWorld.vue';`
    // `<rootDir>` 토큰을 사용해 루트 경로를 참조할 수 있습니다.
    // TODO: 프로젝트에 맞는 경로로 수정하세요!
    moduleNameMapper: {
      '^~/(.*)$': '<rootDir>/src/$1',
      '^@/(.*)$': '<rootDir>/src/$1'
    },
    // 일치하는 경로에서는 모듈을 가져오지 않습니다.
    // `<rootDir>` 토큰을 사용해 루트 경로를 참조할 수 있습니다.
    // TODO: 프로젝트에 맞는 경로로 수정하세요!
    modulePathIgnorePatterns: [
      '<rootDir>/node_modules',
      '<rootDir>/build',
      '<rootDir>/dist'
    ],
    // 정규식과 일치하는 파일의 변환 모듈을 지정합니다.
    transform: {
      '^.+\\.vue$': 'vue-jest',
      '^.+\\.jsx?$': 'babel-jest'
    },
    // Jest Snapshot 테스트에 필요한 모듈을 지정합니다.
    setupFiles: [
      '<rootDir>/jest.setup.js', 
    ], 
    testEnvironment: 'jest-environment-jsdom', 
    verbose: true,
    testEnvironmentOptions:{ 
      "url": "http://localhost/"
    } 
  }

ts-jest : https://bobbyhadz.com/blog/typescript-jest-cannot-use-import-statement-outside-module

vue router test

  • express로 ssr
  • router('경로') => return res.vue()
  • res.vue() : middleware에서 정의한 함수
  • handler.js의 render함수: res.send(html), html : initialState 등으로 데이터 전송
  • router를 어떻게 넣은거지? vueRotuer에서는 hash 붙이는 거만 하고 있던데
profile
노션 : https://garrulous-gander-3f2.notion.site/c488d337791c4c4cb6d93cb9fcc26f17

0개의 댓글