I try to write test for my Vue 3 app and I try to test my component.
In this post I will use my simple component to show my case.
So I have my simple component with button and when the button is clicked my method "testFun" should be called. Inside this method I have a console.log and I can see this console.log is displayed in consol after run my test but when I want to use assertion :
"expect(testCall).toHaveBeenCalled();"
then i have this error:
expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
15 | wrapper.find("button").trigger("click");
16 |
> 17 | expect(testCall).toHaveBeenCalled();
| ^
18 | });
19 | });
I tried to use also
toHaveBeenCalledWith()
toBeCalled()
Below I will paste my component, spec file and set up.
COPOMENT:
<template>
<button data-test="data-test" @click="testFun">TEST</button>
</template>
<script setup lang="ts">
const testFun = () => {
console.log("TESTTEST");
};
</script>
SPEC FILE:
import HelloWorld from "./HelloWorld.vue";
import { mount } from "@vue/test-utils";
describe("HelloWorld", () => {
it("renders properly", () => {
const wrapper = mount(HelloWorld);
const testCall = jest.spyOn(wrapper.vm, "testFun");
wrapper.find("button").trigger("click");
expect(testCall).toHaveBeenCalled();
});
});
JEST CONFIG:
module.exports = {
testEnvironment: "jsdom",
transform: {
'^.+\\.ts$': 'babel-jest',
'^.+\\.js$': 'babel-jest',
'^.+\\.vue$': '@vue/vue3-jest',
},
testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(js|ts)$",
moduleFileExtensions: ['js', 'json', 'vue', 'ts'],
moduleNameMapper: {
"^@/(.*)$": "<rootDir>/src/$1",
},
coveragePathIgnorePatterns: ["/node_modules/", "/tests/"],
coverageReporters: ["text", "json-summary"],
setupFiles: ['<rootDir>/jest-setup.ts'],
testEnvironmentOptions: {
customExportConditions: ["node"],
},
}
JEST SETUP
import { config } from "@vue/test-utils"; import { createTestingPinia } from "@pinia/testing"; import ElementPlus from "element-plus";
config.global = {
...config.global,
plugins: [createTestingPinia({ stubActions: false }), ElementPlus],
};
if (!window.global.activeFeatureTogglz) {
window.global.activeFeatureTogglz = [];
}
WEBPACK CONFIG
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers');
module.exports = {
// ... other configurations
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
},
// ... other rules for JS, CSS, etc.
],
},
plugins: [
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
};
TS CONFIG
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"useDefineForClassFields": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env",
"jest",
"element-plus/global"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}
PACKAGE JSON
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test": "jest",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"axios": "^1.5.0",
"element-plus": "^2.5.1",
"pinia": "^2.1.7",
"vue": "^3.2.13",
"vue-router": "^4.2.4"
},
"devDependencies": {
"@babel/preset-env": "^7.23.8",
"@babel/preset-typescript": "^7.23.3",
"@pinia/testing": "^0.1.3",
"@types/jest": "^27.0.1",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"@typescript-eslint/parser": "^5.4.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-plugin-typescript": "~5.0.0",
"@vue/cli-plugin-unit-jest": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"@vue/eslint-config-typescript": "^9.1.0",
"@vue/test-utils": "^2.4.3",
"@vue/vue3-jest": "^29.2.6",
"babel-jest": "^29.7.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"flush-promises": "^1.0.2",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"sass": "^1.69.7",
"sass-loader": "^13.3.3",
"ts-jest": "^27.0.4",
"typescript": "^5.3.3"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended",
"@vue/typescript/recommended"
],
"parserOptions": {
"ecmaVersion": 2020
},
"rules": {},
"overrides": [
{
"files": [
"**/__tests__/*.{j,t}s?(x)",
"**/tests/unit/**/*.spec.{j,t}s?(x)"
],
"env": {
"jest": true
}
}
]
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead",
"not ie 11"
]
}
I tried also jest.fc(() => {}) But i had same results
I just want to see if my method was called WITH assertion, I also can change the HTML results, but want to understand my mistake.