Svelte 3: не удалось импортировать модули при модульном тестировании - PullRequest
2 голосов
/ 20 февраля 2020

Я пытаюсь протестировать компонент Svelte с помощью Jest. Этот компонент прекрасно работает в браузере, но модульное тестирование завершается неудачно с импортом модулей.

Например, при запуске Jest import uuid from 'uuid', скомпилированном как const { default: uuid } = require("uuid");, и вызов uuid.v4() вызывает TypeError: Cannot read property 'v4' of undefined. Когда я использую import * as uuid from 'uuid' или const uuid = require('uuid'), юнит-тест Jest проходит, но он не работает в браузере.

Как я могу решить эту проблему? Любая информация очень поможет. Спасибо.

пакет. json:

{
  "name": "svelte-app",
  "version": "1.0.0",
  "scripts": {
    "build": "rollup -c",
    "dev": "rollup -c -w",
    "start": "firebase serve --only hosting"
  },
  "devDependencies": {
    "@rollup/plugin-json": "^4.0.0",
    "@testing-library/jest-dom": "^5.1.1",
    "@testing-library/svelte": "^1.11.0",
    "bulma": "^0.8.0",
    "eslint": "^6.7.0",
    "eslint-config-standard": "^14.1.0",
    "eslint-plugin-import": "^2.18.2",
    "eslint-plugin-jest": "^23.0.4",
    "eslint-plugin-node": "^10.0.0",
    "eslint-plugin-promise": "^4.2.1",
    "eslint-plugin-standard": "^4.0.1",
    "eslint-plugin-svelte3": "^2.7.3",
    "jest-transform-svelte": "^2.1.1",
    "node-sass": "^4.13.1",
    "rollup": "^1.12.0",
    "rollup-jest": "0.0.2",
    "rollup-plugin-commonjs": "^10.0.0",
    "rollup-plugin-livereload": "^1.0.0",
    "rollup-plugin-node-builtins": "^2.1.2",
    "rollup-plugin-node-globals": "^1.4.0",
    "rollup-plugin-node-resolve": "^5.2.0",
    "rollup-plugin-svelte": "^5.0.3",
    "rollup-plugin-terser": "^5.1.2",
    "sirv-cli": "^0.4.5",
    "svelma": "^0.3.2",
    "svelte": "^3.18.2",
    "svelte-preprocess": "^3.4.0"
  },
  "dependencies": {
    "firebase": "^7.8.2"
  },
  "private": true
}

rollup.config. js

import json from '@rollup/plugin-json'
import commonjs from 'rollup-plugin-commonjs'
import builtins from 'rollup-plugin-node-builtins'
import globals from 'rollup-plugin-node-globals'
import livereload from 'rollup-plugin-livereload'
import resolve from 'rollup-plugin-node-resolve'
import svelte from 'rollup-plugin-svelte'
import { terser } from 'rollup-plugin-terser'
import preprocess from 'svelte-preprocess'

const production = !process.env.ROLLUP_WATCH

export default {
  input: 'src/main.js',
  output: {
    sourcemap: true,
    format: 'iife',
    name: 'app',
    file: 'public/build/bundle.js',
  },
  plugins: [
    // https://github.com/rollup/plugins/tree/master/packages/json
    json(),

    svelte({
      // enable run-time checks when not in production
      dev: !production,
      // we'll extract any component CSS out into
      // a separate file — better for performance
      css: css => {
        css.write('public/build/bundle.css')
      },
      preprocess: preprocess(),
    }),

    // If you have external dependencies installed from
    // npm, you'll most likely need these plugins. In
    // some cases you'll need additional configuration —
    // consult the documentation for details:
    // https://github.com/rollup/rollup-plugin-commonjs
    resolve({
      browser: true,
      dedupe: importee => importee === 'svelte' || importee.startsWith('svelte/'),
    }),
    commonjs(),
    globals(),
    builtins(),

    // In dev mode, call `npm run start` once
    // the bundle has been generated
    !production && serve(),

    // Watch the `public` directory and refresh the
    // browser on changes when not in production
    !production && livereload('public'),

    // If we're building for production (npm run build
    // instead of npm run dev), minify
    production && terser(),
  ],
  watch: {
    clearScreen: false,
  },
}

function serve () {
  let started = false

  return {
    writeBundle () {
      if (!started) {
        started = true

        require('child_process').spawn('npm', ['run', 'start'], {
          stdio: ['ignore', 'inherit', 'inherit'],
          shell: true,
        })
      }
    },
  }
}

jest.config. js

const sveltePreprocess = require('svelte-preprocess')

module.exports = {
  displayName: { name: 'web', color: 'magentaBright' },
  moduleFileExtensions: [
    'js',
    'json',
    'svelte',
  ],
  preset: 'rollup-jest',
  transform: {
    '\\.js$': 'rollup-jest',
    '\\.svelte$': ['jest-transform-svelte', { preprocess: sveltePreprocess(), debug: true }],
  },
  setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'],
}

Ответы [ 2 ]

0 голосов
/ 05 апреля 2020

Это сработало для меня.

Эта проблема, похоже, не позволяет решить uuid при создании кода во время выполнения. Что вполне очевидно, потому что по умолчанию игнорирует пакеты node_modules .

Я столкнулся с похожими проблемами и решил их. Подход заключается в конфигурации, информирующей JEST о том, что он должен также включать пакеты node_modules. В моем проекте я использовал rollup-plugin-babel. Это конфигурация плагина babel

...
...
babel({
    extensions: [ '.js', '.mjs', '.html', '.svelte' ],
    runtimeHelpers: true,
    exclude: [ 'node_modules/@babel/**', 'node_modules/core-js/**' ],
    presets: [
      [
        '@babel/preset-env',
        {
          targets: '> 0.25%, not dead',
          useBuiltIns: 'usage',
          corejs: 3 
        }
      ]
    ]
  })

И я добавил babel-jest для преобразования jest.config. js

module.exports = {
  preset: 'jest-puppeteer', //ignore the preset part, I used for puppeteer
  transform: {
    '^.+\\.js?$': require.resolve('babel-jest'),
    "^.+\\.ts?$": "ts-jest" // this part is only required if you have typescript project
  }
};

Не забудьте установить такие пакеты как babel-jest, rollup-plugin-babel перед его использованием.

0 голосов
/ 18 марта 2020

Я столкнулся с этой же проблемой, и мне удалось обойти эту проблему, высмеивая модуль в тестовом файле и назначая ему ключ по умолчанию.

jest.mock('uuid', () => ({
  default: {
    v4: jest.fn(),
  },
}))

Другой способ, который, похоже, работает, - это деструктурировать импорт в файле компонента.

import { v4 as uuidv4 } from 'uuid'
...