vue-componentvue-test-utilsvue-jest

Cannot call trigger on an empty DOMWrapper


I am upgrading a Vue 2 component library to Vue 3. I have upgraded all the packages in the project, and made some necessary changes to get the code to compile. The components work as expected in a demo application.

Unfortunately, when I run the jest unit tests, I get a bunch of Cannot call [something] on an empty DOMWrapper. I found that jest does not seem to recognize the template definition in the <template></template> tag in the .vue file. However, if I define the template as a component property like:

export default {
  template: `<div class="component__wrapper">
              ...
            </div>`,
  name: 'Component',
  ...

the tests run fine and all pass.

Am I missing some crucial tidbit in the jest.config.json?

These are my relevant package versions:

    "@types/jest": "^29.5.10",
    "@vue/test-utils": "^2.4.3",
    "@vue/vue3-jest": "^29.2.6",
    "babel-jest": "^29.7.0",
    "babel-loader": "^9.1.3",
    "babel-preset-vue": "^2.0.2",
    "ts-jest": "^29.1.1",
    "typescript": "^5.3.2",
    "vue": "^3.3.9",
    "vue-loader": "^17.3.1",
    "vue-style-loader": "^4.1.3",

and my jest.config.json looks like:

{
  "preset": "ts-jest",
  "testEnvironment": "jsdom",
  "testEnvironmentOptions": {
    "customExportConditions": ["node", "node-addons"]
  },
  "rootDir": "..",
  "setupFiles": [
    "<rootDir>/jest/setup.js"
  ],
  "transform": {
    "^.+\\.jsx?$": "babel-jest",
    "^.+\\.tsx?$": "ts-jest",
    "^.*\\.vue$": "@vue/vue3-jest"
  },
  "transformIgnorePatterns": [
    "/node_modules/(?!(@storybook/.*\\.vue$))"
  ],
  "testRegex": "/__tests__/.*\\.spec\\.(ts|js)$",
  "moduleFileExtensions": [
    "ts",
    "tsx",
    "js",
    "jsx",
    "vue",
    "json"
  ],
  "moduleNameMapper": {
    "\\.(jpg|png|gif|svg)$": "<rootDir>/jest/image-mocks.js"
  },
  "snapshotSerializers": [
    "jest-serializer-vue"
  ],
  "collectCoverage": true,
  "collectCoverageFrom": [
    "src/**/*.ts"
  ],
  "coveragePathIgnorePatterns": [
    ".d.ts$",
    ".stories.ts$",
    "index.ts$",
    "/__tests__/",
    "/stories/",
    "/types/"
  ],
  "coverageReporters": [
    "json",
    "lcov",
    "text",
    "html"
  ],
  "coverageThreshold": {
    "global": {
      "branches": 100,
      "functions": 100,
      "lines": 100,
      "statements": 100
    }
  },
  "clearMocks": true
}

Been pulling my hair out - if anyone has any ideas, I would appreciate it.


Solution

  • In case anyone else comes to this question, the answer came from a coworker of mine. The solution was to change the script in the .vue file from:

    <script>module.exports = require('./RadioButton.ts')</script>
    

    to

    <script lang="ts">
      import RadioButton from "./RadioButton";
      export default RadioButton;
    </script>
    

    Unfortunately, not really sure why that worked. If anyone has thoughts, feel free to comment.