VIcon causing jest test to fail (Vue2/Vuetify3) - vue.js

This is a Vue 2 JavaScript application:
VIcon causing jest test to fail and present this error:
console.error node_modules/vue/dist/vue.runtime.common.dev.js:621
[Vue warn]: Error in render: "TypeError: Cannot read property 'component' of undefined"
found in
---> <VIcon>
<VCheckbox>
<Anonymous>
<Root>
I created this app with the Vue cli tool and used vue add to add the plugin for Vuetify. I'm also using PUG for vue template template, and SCSS instead of css (Node-sass). This might be due to the jest setup which will be provided below. I followed an online setup for ignoring some files and collecting coverage.
module.exports = {
preset: '#vue/cli-plugin-unit-jest',
setupFiles: ['./tests/setup.js'],
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/src/$1',
},
testMatch: [
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)',
'**/tests/int/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)',
],
transform: {
".+\\.(css|styl|less|sass|scss|png|jpg|jpeg|mp3|ttf|woff|woff2)$": "jest-transform-stub",
"^.+\\.jsx?$": "babel-jest",
"^.+\\.js?$": "babel-jest"
},
snapshotSerializers: ['jest-serializer-vue'],
collectCoverage: true,
collectCoverageFrom: [
'src/**/*.{js,vue}',
'!src/main.js',
'!src/App.vue',
'!src/plugins/*',
'!src/router/*',
// testing this later
'!src/store/*',
'!src/store/modules/*',
],
};
The jest inner setup file just adds vuetify:
import Vue from 'vue';
import Vuetify from 'vuetify';
Vue.use(Vuetify);
Here is the package.json to see what versions I'm using:
{
"name": "client2",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit --coverage --watchAll",
"test-ci": "vue-cli-service lint && vue-cli-service test:unit && vue-cli-service --mode development --headless",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.21.1",
"core-js": "^3.6.5",
"vue": "^2.6.11",
"vue-notification": "^1.3.20",
"vue-router": "^3.2.0",
"vuetify": "^2.2.11",
"vuex": "^3.4.0"
},
"devDependencies": {
"#vue/cli-plugin-babel": "~4.5.0",
"#vue/cli-plugin-eslint": "~4.5.0",
"#vue/cli-plugin-router": "~4.5.0",
"#vue/cli-plugin-unit-jest": "~4.5.0",
"#vue/cli-plugin-vuex": "~4.5.0",
"#vue/cli-service": "~4.5.0",
"#vue/eslint-config-prettier": "^6.0.0",
"#vue/test-utils": "^1.0.3",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-vue": "^6.2.2",
"node-sass": "^4.12.0",
"prettier": "^1.19.1",
"sass": "^1.19.0",
"sass-loader": "^8.0.2",
"vue-cli-plugin-pug": "~2.0.0",
"vue-cli-plugin-vuetify": "~2.0.9",
"vue-template-compiler": "^2.6.11",
"vuetify-loader": "^1.3.0"
}
}
and the test:
import TriBox from '../../src/components/UIContainers/TriBox.vue';
import { createLocalVue, mount } from '#vue/test-utils';
import Vuetify from 'vuetify';
describe('<TriBox /> Unit Tests', () => {
let wrapper;
const localVue = createLocalVue();
localVue.use(Vuetify);
beforeEach(() => {
wrapper = mount(TriBox, {
localVue,
});
});
it(`renders to screen`, () => {
expect(wrapper.exists).toBeTruthy();
});
});
and the component:
<template lang="pug">
.box-container
.left
v-checkbox
.middle
p hello
.right
v-icon mdi-trash-can
</template>
<script>
export default {};
</script>
<style lang="scss" scoped>
</style>
I can't find a specific document pertaining to this being a known bug with Vuetify and Vue2. Anyone have a clue as to how to solve this? I'm thinking it has to do with the jest setup file or how I'm setting the test up and adding vuetify to the local vue. But any suggestions would be helpful.

Based on Vuetify's Jest setup docs:
Don't use localVue.use(Vuetify) because you've already called Vue.use(Vuetify) in the Jest setup file.
Along with localVue, pass vuetify as a new instance of Vuetify to mount():
const localVue = createLocalVue()
let wrapper
beforeEach(() => {
wrapper = mount(TriBox, {
localVue,
vuetify: new Vuetify(),
})
})

Related

SyntaxError: Cannot use import statement outside a module in jest

I would like to do vue util test using jest, but since i used import statement, it keeps making errors.
it says "SyntaxError: Cannot use import statement outside a module "
" at ScriptTransformer._transformAndBuildScript (node_modules/#jest/transform/build/ScriptTransformer.js:537:17)"
i've tried adding type:module to my package.json, transformIgnorePatterns to jest.config.js , and module to my script tag. none of them worked. i think it is related to version, as i am using vue 2 to get track of lessons im listening to. please take a look at my code
this is my package.json
{
"name": "jest-test",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^1.2.3",
"core-js": "^3.6.5",
"vue": "^2.6.11",
"vuex": "^3.4.0"
},
"devDependencies": {
"#babel/preset-env": "^7.20.2",
"#vue/cli-plugin-babel": "^4.1.2",
"#vue/cli-plugin-eslint": "^4.1.2",
"#vue/cli-plugin-unit-jest": "^4.1.2",
"#vue/cli-plugin-vuex": "^4.1.2",
"#vue/cli-service": "^4.1.2",
"#vue/eslint-config-standard": "^5.1.2",
"#vue/test-utils": "^1.0.3",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^6.2.2",
"node-sass": "^4.12.0",
"sass-loader": "^8.0.2",
"vue-template-compiler": "^2.6.11"
}
}
this is my error code to test
<template>
<div>
{{ todo.title }}
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
todo: {},
};
},
created() {
this.fetchTodo();
},
methods: {
async fetchTodo() {
const { data } = await axios.get(
"https://jsonplaceholder.typicode.com/todos/1"
);
this.todo = data;
},
},
};
</script>
and this is testing code
import { shallowMount } from "#vue/test-utils";
import TodoTitle from "#/components/TodoTitle";
describe("TodoTitle Component", () =\> {
test("rendering", () =\> {
const wrapper = shallowMount(TodoTitle);
console.log(wrapper);
expect(wrapper.text()).toBe("");
});
});

How to handle `process.env` in client-side javascript files when running E2E tests in Cypress?

Embarrassingly, this problem has been holding me up for days, and I must, must get on with my task for work, so I'm reaching out for help.
When running Cypress, I get said error: process is not defined and it points to a JavaScript file in the client portion of my project (shown below). I understand process is a nodeJS property, but I can obviously call this on the FE of my application, and must, so I don't understand why Cypress is throwing an error here. Any help would be much appreciated. I'm running node v14.x.x.
vue.config.js
const { defineConfig } = require('#vue/cli-service')
// const { VueLoaderPlugin } = require('vue-loader')
module.exports = defineConfig({
css: {
loaderOptions: {
sass: {
additionalData: '#import src/styles/base/entry.scss',
},
},
},
lintOnSave: false,
publicPath: '/',
transpileDependencies: true,
})
Package.json
{
"name": "test2",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"test:e2e": "vue-cli-service test:e2e",
"lint": "vue-cli-service lint"
},
"dependencies": {
"#sentry/apm": "^5.27.1",
"#sentry/browser": "^7.28.1",
"#sentry/integrations": "^7.28.1",
"auth0-js": "^9.20.0",
"axios": "^1.2.2",
"axios-retry": "^3.3.1",
"big.js": "^6.2.1",
"core-js": "^3.8.3",
"css-loader": "^6.7.3",
"moment": "^2.29.4",
"moment-timezone": "^0.5.40",
"style-loader": "^3.3.1",
"toastr": "^2.1.4",
"uuid": "^9.0.0",
"vue": "^2.6.14",
"vue-router": "^3.5.2"
},
"devDependencies": {
"#babel/core": "^7.20.7",
"#babel/eslint-parser": "^7.19.1",
"#babel/preset-env": "^7.20.2",
"#cypress/webpack-preprocessor": "^5.16.1",
"#vue/cli-plugin-babel": "~5.0.0",
"#vue/cli-plugin-e2e-cypress": "~5.0.0",
"#vue/cli-plugin-eslint": "~5.0.0",
"#vue/cli-plugin-unit-jest": "~5.0.0",
"#vue/cli-service": "~5.0.0",
"#vue/test-utils": "^1.1.3",
"#vue/vue2-jest": "^27.0.0-alpha.2",
"babel-jest": "^27.0.6",
"babel-loader": "^8.0.2",
"cypress": "^9.7.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"jest": "^27.0.5",
"node-sass": "^4.14.0",
"sass-loader": "^12.6.0",
"ts-jest": "^27.0.4",
"vue-loader": "^15.0.1",
"vue-template-compiler": "^2.6.14",
"webpack": "^5.75.0"
}
}
Cypress webpack config
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
const { VueLoaderPlugin } = require('vue-loader')
const webpackPreprocessor = require('#cypress/webpack-preprocessor')
/**
* #type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
const defaults = webpackPreprocessor.defaultOptions
// Add to existing rules
defaults.webpackOptions.module.rules.push(
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.sass$/i,
use: [
// creates 'style' nodes from JS strings
"vue-style-loader",
// Translates CSS into CommonJS
"css-loader",
// Compiles Sass to CSS
{
loader: "sass-loader",
options: {
additionalData: '#import src/styles/base/entry.scss',
// sass-loader >= 8
sassOptions: {
indentedSyntax: true,
},
},
},
],
}
)
// Add first plugin
defaults.webpackOptions.plugins = [ new VueLoaderPlugin() ]
console.log(defaults)
on('file:preprocessor', webpackPreprocessor(defaults))
}
sentryMixin.js
...
const environment = process.env.VUE_APP_ENV
^ this is where it points to the error
...

Having issues with vue-svg-loader - missing template or render function

I am getting issues trying to get vue-svg-loader to work. I posted this in the issues part of the plugin, but I am not sure if it is, or just that I have implemented it wrong.
I am pretty new to Vue, so apologies if I am making a really stupid mistake when implementing it.
When I run vue --version it says I am on #vue/cli 4.5.9
This is the code inside of my component:
<template>
<div>
<SampleSvg />
</div>
</template>
<script>
import SampleSvg from "#/assets/sample.svg"
export default {
name: "HelloWorld",
components: {
SampleSvg
},
};
</script>
This is my vue.config.js file:
module.exports = {
chainWebpack: (config) => {
const svgRule = config.module.rule('svg');
svgRule.uses.clear();
svgRule
.use('babel-loader')
.loader('babel-loader')
.end()
.use('vue-svg-loader')
.loader('vue-svg-loader');
},
css: {
loaderOptions: {
sass: {
prependData:
`#import "#/assets/scss/globals/_variables.scss";
#import "#/assets/scss/globals/_variables-font-sizes.scss";
#import "#/assets/scss/globals/_colours.scss";
#import "#/assets/scss/globals/_mixins.scss";
`
},
},
},
};
This is my package.json file
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.21.1",
"core-js": "^3.6.5",
"postcss": "^8.3.6",
"vue": "^3.0.0",
"vue-router": "^4.0.0-0"
},
"devDependencies": {
"#vue/cli-plugin-babel": "~4.5.0",
"#vue/cli-plugin-eslint": "~4.5.0",
"#vue/cli-plugin-router": "~4.5.0",
"#vue/cli-service": "~4.5.0",
"#vue/compiler-sfc": "^3.0.0",
"#vue/eslint-config-prettier": "^6.0.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-vue": "^7.0.0",
"prettier": "^2.2.1",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"style-resources-loader": "^1.4.1",
"vue-svg-loader": "^0.17.0-beta.2",
"vue-template-compiler": "^2.6.14"
}
}
The error I get is:
[Vue warn]: Component is missing template or render function.
at <SampleSvg>
at <HelloWorld onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< null > >
at <RouterView>
at <App>
If I open up the sample.svg file, I have this code:
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="40" stroke="deeppink" stroke-width="2" fill="#ffe6ee" />
</svg>
I am pretty new to Vue, so apologies if this is down to how I have installed it.
My setup is as follows - but since I want to reference both internal and external SVGs (meaning that I want to be able to import an SVG as a Vue Component OR to be able to put it in the SRC of an IMG tag) I use the ?int modifier to signal when I want to receive a component. Without this modifier the import will be the image itself.
const svgRule = config.module.rule('svg');
svgRule.uses.clear();
svgRule
.oneOf('inline')
.resourceQuery(/int/) // internal SVGs must be in the form - import svgComponent from "#/images/example.svg?int" !!!!!
.use('babel-loader')
.loader('babel-loader')
.end()
.use('vue-svg-loader')
.loader('vue-svg-loader')
.options({
svgo:
{
plugins: [
{ inlineStyles: { onlyMatchedOnce: false } },
{ removeXMLNS: true },
{ removeViewBox: false },
{ removeDimensions: true },
]
}
})
.end()
.end()
.oneOf('external')
.use('url-loader')
.loader('url-loader')
.options({
limit: 4096,
fallback:
{
loader: 'file-loader',
options:
{
name: 'img/[name].[hash:8].[ext]',
}
}
});

BootstrapVue Components Not Being Converted into HTML

My components are rendering to the client page exactly as written in BootstrapVue, so I'm seeing <b-button> literally rendered to the client page:
<b-button data-v-3d7e72245 id="myBtn" variant="outline-primary">Click Me</b-button>
Shouldn't this be converted into standard HTML during the Vue render process and have the bootstrap classes added automatically?
I'm new to Vue, so I could be missing something obvious - but I'm not seeing any errors when running 'npm run build' in the command line, or in the web console/Vue dev tools.
Header.vue:
<template>
<header id="Header">
<ApplyBtn btnText="Click Me" />
</header>
</template>
<script>
import ApplyBtn from './header/ApplyBtn.vue'
export default {
name: 'Header',
components: {
ApplyBtn
}
}
</script>
Main.js:
import 'core-js/stable'
import 'regenerator-runtime/runtime'
import 'intersection-observer'
import Vue from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify';
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import '/scss/global/duo-theme.scss'
new Vue({
vuetify,
render: h => h(App)
}).$mount('#App')
Vue.config.devtools = true
Vue.config.productionTip = false
// Custom widgets
Vue.component('applybtn', require('./components/global/header/ApplyBtn.vue').default);
window.Vue = Vue;
Vue.use(BootstrapVue);
Vue.use(IconsPlugin);
Package.json:
{
"name": "VueBS",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"acorn": "^8.1.0",
"axios": "^0.21.1",
"bootstrap": "^4.6.0",
"bootstrap-scss": "^4.6.0",
"bootstrap-vue": "^2.21.2",
"core-js": "^3.10.0",
"css-loader": "^5.2.0",
"extract-text-webpack-plugin": "^3.0.2",
"intersection-observer": "^0.12.0",
"jquery": "^1.12.4",
"mini-css-extract-plugin": "^0.9.0",
"popper.js": "^1.16.1",
"regenerator-runtime": "^0.13.7",
"rxjs": "^6.6.7",
"rxjs-compat": "^6.6.7",
"typescript": "^4.2.3",
"vue": "^2.6.11",
"vue-style-loader": "^4.1.3",
"vuetify": "^2.4.9"
},
"devDependencies": {
"#vue/cli-plugin-babel": "^4.5.12",
"#vue/cli-plugin-eslint": "^4.5.12",
"#vue/cli-service": "^4.5.12",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"html-webpack-plugin": "^5.3.1",
"sass": "^1.32.0",
"sass-loader": "^10.0.0",
"vue-cli-plugin-vuetify": "~2.3.1",
"vue-template-compiler": "^2.6.11",
"vuetify-loader": "^1.7.0",
"webpack": "^4.46.0"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
Try placing your Vue.use before you create your Vue instance.
Change this
new Vue({
vuetify,
render: h => h(App)
}).$mount('#App')
Vue.use(BootstrapVue);
Vue.use(IconsPlugin);
To this
Vue.use(BootstrapVue);
Vue.use(IconsPlugin);
new Vue({
vuetify,
render: h => h(App)
}).$mount('#App');

Use BootstrapVue on every component in Vue.js

I am making a Vue.js Webapp. I am using raw Vue.js with BootstrapVue and SCSS. The scss styles work globally after I imported them in the app entry point, which in my case is the main.js file in the src folder of the project. But the BootstrapVue styles do not work anymore when I use them in any other .vue file except the main file "App.vue".
This is my vue.config.js file:
module.exports = {
css: {
sourceMap: true,
loaderOptions: {
sass: {
prependData: `
#import "src/scss/_variables.scss";
#import "node_modules/bootstrap/scss/bootstrap";
#import "node_modules/bootstrap-vue/src/index.scss";
`,
}
}
}
};
And this is my main.js file and therefore the entry point of the app:
import Vue from "vue";
import App from "./App.vue";
import { BootstrapVue, IconsPlugin } from "bootstrap-vue";
import "./scss/global.scss";
Vue.config.productionTip = false;
Vue.use(BootstrapVue);
Vue.use(IconsPlugin);
new Vue({
render: (h) => h(App),
}).$mount("#app");
I imported BootstrapVue in my global.scss additionally. I did try to import my global.scss file in the component's style tag, I tried to import BootstrapVue directly in my component's style tag but that didn't work either.
So I am basically asking you for a solution to use BootstrapVue globally in any Vue.js Component. Maybe I made some mistake I did not notice. The error message in the console didn't really help me solve the problem.
EDIT:
This is my package.json file:
{
"name": "portfolio",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"bootstrap": "^4.5.0",
"bootstrap-vue": "^2.14.0",
"core-js": "^3.6.4",
"vue": "^2.6.11"
},
"devDependencies": {
"#vue/cli-plugin-babel": "~4.3.0",
"#vue/cli-plugin-eslint": "~4.3.0",
"#vue/cli-service": "~4.3.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
You're missing .scss on #import "node_modules/bootstrap/scss/bootstrap";. Should be #import "node_modules/bootstrap/scss/bootstrap.scss";