I have installed the Vue Test tools, installed Jest and have a test case just to verify that the vue instance works.
My test looks like the following
/* global describe, test, expect */
/* eslint no-undef: "error" */
import { mount } from '#vue/test-utils';
import Logo from '#/components/Logo';
describe('Logo', ()=> {
test('is a vue instance', () => {
const wrapper = mount(Logo)
expect(wrapper.vm).toBeTruthy()
});
});
I run it using npm run test and get the following error
import { mount } from '#vue/test-utils'
Syntax error: Unexpected token {
(with an carrot pointing to the { in front of { mount }
Any ideas?
***** Editing to add my jest.config.js ****
module.exports = {
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/$1',
'^~/(.*)$': '<rootDir>/$1',
'^vue$': 'vue/dist/vue.common.js'
},
moduleFileExtentions: ['js', 'vue', 'json'],
testPathIgnorePatterns: ['/dist/', '/node_modules/'],
transform: {
'^.+\\.js$' : 'babel-jest',
'.*\\.(vue)$' : 'vue-jest'
},
collectCoverage: true,
collectCoverageFrom: [
'<rootDir>/components/**/*.vue',
'<rootDir>/pages/**/*.vue'
]
}
I figured out the issue. I needed to add '#babel/preset-env' to my presets in my babel.config
I'm now getting errors related to Vuetify but for this issue that fixed the problem. Ill create a new question for the other issue.
Related
Hello everyone I'm using vue 3 with storybook 6.5.16 and when i import the SVGs as a component using svg-inline-loader i get the following error in storybook app:
enter image description here
(Failed to execute 'createElement' on 'Document' svg is not a valid name)
Storybook main.js
const path = require('path');
module.exports = {
stories: [
'../src/**/*.stories.mdx',
'../src/**/*.stories.#(js|jsx|ts|tsx)',
],
addons: [
'#storybook/addon-links',
'#storybook/addon-essentials',
'#storybook/addon-interactions',
],
framework: '#storybook/vue3',
core: {
builder: '#storybook/builder-webpack5',
},
webpackFinal: async (config, { configType }) => {
// `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
config.module.rules.push({
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
{
loader: "sass-loader",
options: {
additionalData: `
#import "#/assets/scss/main.scss";
`,
implementation: require('sass'),
},
},
],
});
(() => {
const ruleSVG = config.module.rules.find(rule => {
if (rule.test) {
const test = rule.test.toString();
const regular = /\.(svg|ico|jpg|jpeg|png|apng|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/;
const regularString = regular.toString();
if (test === regularString) {
return rule;
}
}
});
ruleSVG.test = /\.(ico|jpg|jpeg|png|apng|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/;
})();
config.module.rules.push({
test: /\.svg$/,
use: ['svg-inline-loader'],
});
config.resolve.alias['#'] = path.resolve('src');
return config;
},
}
package.json file
enter image description here
SVG Vue components
<template>
<div
ref="icon"
class="v-icon"
#click="onClick"
>
<component
:is="iconName"
class="v-icon__svg"
/>
</div>
</template>
<script>
import Cards from '#/assets/icons/Cards.svg';
export default {
name: 'VIcon',
components: {
Cards,
},
props: {
iconName: {
type: String,
required: true,
},
},
};
</script>
.babelrc file
{
"presets": ["#babel/preset-env", "#babel/preset-react"]
}
i tried to use vue-svg-loader to replace svg-inline-loader but it didn't work and I got another error while building the app
ModuleBuildError: Module build failed: Error: Cannot find module './Block'
I also tried to use babel-loader in conjunction with vue-svg-loader but unfortunately I also got an error:
enter image description here
has anyone come across this or can you show your use cases of using SVGs components in Storybook and Vue 3?
I am trying to create an expo react app using typescript. The app works perfectly fine but when I am trying to write some tests using Jest, it always says it can not find the module '#env' from my store file.
Cannot find module '#env' from 'src/store.ts'
Require stack:
src/store.ts
src/screens/HomeScreen.tsx
src/tests/HomeScreen.test.tsx
> 1 | import { REACT_APP_API_URL } from '#env';
| ^
2 | import axios from 'axios';
3 | import { Alert } from 'react-native';
4 | import create from 'zustand';
at Resolver._throwModNotFoundError (node_modules/jest-resolve/build/resolver.js:425:11)
at Object.<anonymous> (src/store.ts:1:1)
at Object.<anonymous> (src/screens/HomeScreen.tsx:5:1)
at Object.<anonymous> (src/tests/HomeScreen.test.tsx:3:1)
HomeScreen.test.txt
import React from 'react';
import renderer from 'react-test-renderer';
import Home from '../screens/HomeScreen';
describe('<App />', () => {
it('has 1 child', () => {
const tree = renderer.create(<Home />).toJSON();
console.log('test', tree);
});
});
The #env is defined in a src/types and the file env.d.ts
declare module '#env' {
export const REACT_APP_API_URL: string;
}
jest.config.js
// jest.config.js
// Sync object
module.exports = {
preset: 'jest-expo',
transform: {
'^.+\\.tsx?$': [
'ts-jest',
{
tsconfig: {
jsx: 'react',
},
},
],
},
testMatch: ['**/?(*.)+(spec|test).ts?(x)'],
collectCoverageFrom: [
'**/*.{ts,tsx}',
'!**/coverage/**',
'!**/node_modules/**',
'!**/babel.config.js',
'!**/jest.setup.js',
],
moduleFileExtensions: ['js', 'ts', 'tsx'],
transformIgnorePatterns: [
'node_modules/(?!(jest-)?react-native|#react-native|react=native|react-clone-referenced-element|#react-native-community|expo(nent)?|#expo(nent)?/.*|react-navigation|#react-navigation/.*|#unimodules/.*|sentry-expo)',
],
coverageReporters: ['json-summary', 'text', 'lcov'],
rootDir: './',
modulePaths: ['<rootDir>'],
collectCoverage: false,
moduleNameMapper: {
'#(.*)': '<rootDir>/node_modules/$1',
},
};
tsconfig.json
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"jsx": "react-jsx",
"strict": true,
"typeRoots": ["./src/types"],
"types": ["jest", "node","#types/jest"],
"baseUrl": ".", // this must be specified if "paths" is specified.
"paths": {
"#env": ["node_modules/#env"] // this mapping is relative to "baseUrl"
},
},
}
babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: [
'react-native-reanimated/plugin',
[
'module:react-native-dotenv',
{
moduleName: '#env',
path: '.env',
blacklist: null,
whitelist: null,
safe: false,
allowUndefined: true,
},
],
],
};
};
I tried mostly everything e.g. Jest cannot find module #env React Native from here and also clear cache and reinstall all but nothing worked.
Can someone help me with this?
Create a types folder in your source folder.
Create a file named env.d.ts in the types folder.
Define your env variables as strings.
declare module '#env' {
export const REACT_APP_API_URL: string;
// other ones
}
first you create new folder under your src folder and you call it types, then you create a file named .env.d.js under types. finally you add your env variable
declare module '#env' {
export const REACT_APP_API_URL;
}
I am creating a Vue component library with Rollup, but when I use slots it gives me the following error:
Uncaught (in promise) TypeError: currentRenderingInstance is null
I made a very simple component in my library:
<script setup></script>
<template>
<button>
<slot></slot>
</button>
</template>
<style scoped></style>
Then I simply use it like this:
<ExampleComponent>
Text
</ExampleComponent>
If I remove the slot and replace it with a prop or hard-coded text, everything works fine.
This is my rollup.config.js:
import { defineConfig } from 'rollup';
import path from 'path';
import resolve from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import postcss from 'rollup-plugin-postcss';
import vue from 'rollup-plugin-vue';
// the base configuration
const baseConfig = {
input: 'src/entry.js',
};
// plugins
const plugins = [
vue(),
resolve({
extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue'],
}),
// process only `<style module>` blocks.
postcss({
modules: {
generateScopedName: '[local]___[hash:base64:5]',
},
include: /&module=.*\.css$/,
}),
// process all `<style>` blocks except `<style module>`.
postcss({ include: /(?<!&module=.*)\.css$/ }),
commonjs(),
];
const external = ['vue'];
const globals = {
vue: 'Vue',
};
export default [
// esm
defineConfig({
...baseConfig,
input: 'src/entry.esm.js',
external,
output: {
file: 'dist/vue-my-lib.esm.js',
format: 'esm',
exports: 'named',
},
plugins,
}),
// cjs
defineConfig({
...baseConfig,
external,
output: {
compact: true,
file: 'dist/vue-my-lib.ssr.js',
format: 'cjs',
name: 'VueMyLib',
exports: 'auto',
globals,
},
plugins,
}),
// iife
defineConfig({
...baseConfig,
external,
output: {
compact: true,
file: 'dist/vue-my-lib.min.js',
format: 'iife',
name: 'VueMyLib',
exports: 'auto',
globals,
},
plugins,
}),
];
Any idea about the problem?
After a whole day of searching, I found the solution (here and here). It's a problem with using a library locally (e.g., through npm link) where it seems there are two instances of Vue at the same time (one of the project and one of the library). So, the solution is to tell the project to use specifically its own vue through webpack.
In my case, I use Jetstream + Inertia, so I edited webpack.mix.js:
const path = require('path');
// ...
mix.webpackConfig({
resolve: {
symlinks: false,
alias: {
vue: path.resolve("./node_modules/vue"),
},
},
});
Or if you used vue-cli to create your project, edit the vue.config.js:
const { defineConfig } = require("#vue/cli-service");
const path = require("path");
module.exports = defineConfig({
// ...
chainWebpack(config) {
config.resolve.symlinks(false);
config.resolve.alias.set("vue", path.resolve("./node_modules/vue"));
},
});
Thanks to #mikelplhts
On vite + esbuild I used:
export default defineConfig({
...
resolve: {
alias: [
...
{
find: 'vue',
replacement: path.resolve("./node_modules/vue"),
},
],
},
...
With this simple vue page:
<template>
<div class="home">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
import HelloWorld from '#/components/HelloWorld.vue'
import { ipcRenderer } from 'electron'
export default {
name: 'Home',
components: {
HelloWorld
},
data() {
return {
dato: null
}
},
methods: {
rendererFunct () {
//ipcRenderer.on('setting', (event, arg) => {
//console.log(arg);
//})
}
}
}
</script>
The only presence of import { ipcRenderer } from 'electron' produces the error __dirname is not defined :
Is this problem is something related to webpack configuration or it is due to something else?
This is my webpack.config.js :
import 'script-loader!./script.js';
import webpack from 'webpack';
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
target: ['electron-renderer', 'electron-main', 'electron-preload'],
pluginOptions: {
electronBuilder: {
chainWebpackMainProcess: config => {
config.resolve.alias.set('jsbi', path.join(__dirname, 'node_modules/jsbi/dist/jsbi-cjs.js'));
}
},
},
};
module.exports = {
entry: './src/background.js',
target: 'node',
output: {
path: path.join(__dirname, 'build'),
filename: 'backend.js'
}
}
module.exports = config => {
config.target = "electron-renderer";
return config;
};
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{ from: 'source', to: 'dest' },
{ from: 'other', to: 'public' },
],
options: {
concurrency: 100,
},
}),
],
};
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
// Creates `style` nodes from JS strings
'style-loader',
// Translates CSS into CommonJS
'css-loader',
// Compiles Sass to CSS
'sass-loader',
],
},
],
},
};
const supportedLocales = ['en-US', 'it'];
export default const config = {
plugins: [
new webpack.ContextReplacementPlugin(
/date\-fns[\/\\]/,
new RegExp(`[/\\\\\](${supportedLocales.join('|')})[/\\\\\]index\.js$`)
)
]
}
This is vue.config.js :
module.exports = {
configureWebpack: {
// Configuration applied to all builds
},
pluginOptions: {
electronBuilder: {
chainWebpackMainProcess: (config) => {
// Chain webpack config for electron main process only
},
chainWebpackRendererProcess: (config) => {
config.plugin('define').tap((args) => {
args[0]['IS_ELECTRON'] = true
return args
})
},
mainProcessFile: 'src/background.js',
mainProcessWatch: ['src/preload.js'],
}
}
}
module.exports = {
pluginOptions: {
electronBuilder: {
disableMainProcessTypescript: false,
mainProcessTypeChecking: false
}
}
}
Electron: version 9.0.0
webpack: version 4.44.1
System:
OS: Linux 5.4 Ubuntu 18.04.4 LTS (Bionic Beaver)
CPU: (8) x64 Intel(R) Core(TM) i7-4790K CPU # 4.00GHz
Binaries:
Node: 14.5.0 - ~/.nvm/versions/node/v14.5.0/bin/node
Yarn: 1.22.4 - /usr/bin/yarn
npm: 6.14.5 - ~/.nvm/versions/node/v14.5.0/bin/npm
Browsers:
Chrome: 84.0.4147.105
Firefox: 79.0
Looking forward to your kind help.
Marco
__dirname is a NodeJS variable, in recent electron versions, node integration is disabled by default. When opening your BrowserWindow, you should add the following to the options:
webpreferences:{
nodeIntegration: true
}
This is however STRONGLY DISCOURAGED as this opens up security issues.
this seems to solve it for most people (for me sadly enough i now get the next error:
fs.existsSync is not a function)
a better solution i to change your bundler to the correct build mode. You should not be building for node but for web, so target:esnext or something.
if something requires node access, this should be solved by running it in the background thread or the preload scripts.
You can apply the solution described on this post
How to import ipcRenderer in vue.js ? __dirname is not defined
In this way you can call this method from vue files:
window.ipcRenderer.send(channel, args...)
Just make sure you configure preload.js on vue.config.js:
// vue.config.js - project root
module.exports = {
pluginOptions: {
electronBuilder: {
preload: 'src/preload.js' //make sure you have this line added
}
}
}
Please help, I got this error when trying to create test for vue js dynamic component using jest.
I'm using babel-plugin-syntax-dynamic-import and babel-plugin-transform-dynamic-import with babel ver > 7.0.0
● Test suite failed to run
TypeError: Path must be a string. Received undefined
at TestExclude.shouldInstrument (node_modules/test-exclude/index.js:77:31)
at shouldSkip (node_modules/babel-plugin-istanbul/lib/index.js:59:21)
at PluginPass.enter (node_modules/babel-plugin-istanbul/lib/index.js:74:15)
at newFn (node_modules/#babel/core/node_modules/#babel/traverse/lib/visitors.js:193:21)
at NodePath._call (node_modules/#babel/core/node_modules/#babel/traverse/lib/path/context.js:53:20)
at NodePath.call (node_modules/#babel/core/node_modules/#babel/traverse/lib/path/context.js:40:17)
at NodePath.visit (node_modules/#babel/core/node_modules/#babel/traverse/lib/path/context.js:88:12)
at TraversalContext.visitQueue (node_modules/#babel/core/node_modules/#babel/traverse/lib/context.js:118:16)
Here's my my-page.js code:
const MyComponent = () => import('src/components/MyComponent')
...
components: {
MyComponent
},
...
myPage.spec.js code:
import { shallow } from 'vue-test-utils'
import MyPage from '#/pages/MyPage'
describe('MyPage.vue', () => {
let component
beforeEach(() => {
component = shallow(MyPage, {
...
})
jest.resetModules()
jest.clearAllMocks()
})
it('method#isEven', () => {
let result = component.vm.isEven(2)
expect(result).toBe(true)
})
})
jest.conf.js code:
const path = require('path')
module.exports = {
rootDir: path.resolve(__dirname, '../../'),
moduleFileExtensions: [
'js',
'json',
'vue'
],
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/src/$1'
},
transform: {
'^.+\\.js$': '<rootDir>/node_modules/babel-jest',
'.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
},
testPathIgnorePatterns: [
'<rootDir>/test/e2e'
],
snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
setupFiles: ['<rootDir>/test/unit/setup'],
coverageDirectory: '<rootDir>/test/unit/coverage',
collectCoverageFrom: [
'src/**/*.{js,vue}',
'!src/main.js',
'!src/router/index.js',
'!**/node_modules/**'
],
testURL: 'http://localhost/unit-test'
}
Do I need to add more configuration?
No need to use babel-plugin-syntax-dynamic-import, use babel-plugin-dynamic-import-node instead. Implementation can be seen at https://jestjs.io/docs/en/webpack.html#using-with-webpack-2
thanks to https://github.com/facebook/jest/issues/5920