Jest Configuration:
/** #type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
preset: 'ts-jest',
moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'vue'],
moduleNameMapper: {
'^~/(.*)$': '<rootDir>/src/$1',
},
testEnvironment: 'jsdom',
testMatch: ['**/tests/unit/**/*.[jt]s?(x)'],
transform: {
'^.+\\.vue$': 'vue-jest',
'^.+\\.ts$': 'ts-jest',
},
}
My test file (.ts file) :
import { render } from '#testing-library/vue'
import Kaki from '~/components/Kaki.vue'
test('Kaki.vue', () => {
const { getByText } = render(Kaki)
getByText('Tono')
})
Here's my directory structure:
When I run the test, it says Cannot find module '~/components/Kaki.vue' or its corresponding type declarations.
I think it has something to do with moduleNameMapper
Can you check if it works if you change your Index.spec.ts to a .js file? The error you're getting is because TypeScript doesn't know what type should .vue files have.
In a new Vue CLI project, the error you're getting is prevented with the shims.d.ts which tells TS to treat *.vue files as if their default export had the Vue type.
The "correct" solution here is to figure out why isn't shims.d.ts telling TypeScript the type for *.vue files (which is why you're getting the "Cannot find module [...] or its corresponding type declarations" error
Another thing is - this is not a real solution but a temporary fix:
// #ts-ignore
import Kaki from '~/components/Kaki.vue'
Another thing you could try is importing Kaki with a relative path (so without the ~ alias)? The ~ alias may be broken in some way - are you sure the alias is correctly defined in your tsconfig.json?
Related
Scenario
I'm using Vue2 with Vue CLI as the bundling tool, now I want to migrate Vue CLI to Vite to enhance the development experience, and the migration process is somewhat successful (thanks to this guide).
Problem
Due to a specific reason, I need to keep the production build accessible statically, without any local server required (the web app should run simply by opening up the index.html file on my machine). And with this, I encounter the problem due to the fact that Vite bundles my code in ESM format that has to be served through some server to resolve CORS policy (error screenshot below). And hence the question: Is it possible to configure Vite to build in plain JS rather than ESM?
Any help is appreciated. Thank you.
Attachments
My vite.config.js as below if it helps:
import path from "path";
import { defineConfig } from "vite";
import { createVuePlugin } from "vite-plugin-vue2";
export default defineConfig({
base: "",
css: {
preprocessorOptions: {
scss: {
additionalData: `
#use "sass:math";
#import "#/scss/utils.scss";`,
},
},
},
plugins: [createVuePlugin()],
resolve: {
extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"]
alias: {
"#": path.resolve(__dirname, "./src"),
},
},
});
I'm trying to compile a webcomponent based on the monaco editor (in a lit element context). Having tried a lot of options I now have got the result down to two files
rmx-monaco.abc123.js
style.css
My top priority is to get rid of the hash (abc123), but I would also like to get down to a single file with the js and css in. Thanks in advance
My config reads:
import { resolve } from "path";
export default defineConfig({
base: "/",
build: {
rollupOptions: {
input:
// main: resolve(__dirname, "index.html"),
resolve(__dirname, "src/rmx-monaco.ts"),
output: {
// Prevent vendor.js being created
manualChunks: undefined,
// chunkFileNames: "zzz-[name].js",
// this got rid of the hash on style.css
assetFileNames: "assets/[name].[ext]",
},
},
// Prevent vendor.css being created
cssCodeSplit: false,
// prevent some warnings
chunkSizeWarningLimit: 60000,
},
});
My js entry files has these lines
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
import { languages } from "monaco-editor/esm/vs/editor/editor.api";
import styles from "monaco-editor/min/vs/editor/editor.main.css";
(I can add more if it would help)
I needed to add output: {entryFileNames: "[name].js",...
Still working on getting a single file
add this:
export default defineConfig({
...
build: {
rollupOptions: {
output: {
entryFileNames: `assets/[name].js`,
chunkFileNames: `assets/[name].js`,
assetFileNames: `assets/[name].[ext]`
}
}
}
})
Long time passed but for future viewers who visit this thread, try this package for single bundled .html file using ViteJS:
https://github.com/richardtallent/vite-plugin-singlefile
I am trying to get my first Jest Test to pass with React and Babel.
I am getting the following error:
SyntaxError: /Users/manueldupont/test/avid-sibelius-publishing-viewer/src/components/TransportButton/TransportButton.less: Unexpected token
> 7 | #import '../variables.css';
| ^
My package.json config for jest look like this:
"babel": {
"presets": [
"es2015",
"react"
],
"plugins": [
"syntax-class-properties",
"transform-class-properties"
]
},
"jest": {
"moduleNameMapper": {
"^image![a-zA-Z0-9$_-]+$": "GlobalImageStub",
"^[./a-zA-Z0-9$_-]+\\.png$": "RelativeImageStub"
},
"testPathIgnorePatterns": [
"/node_modules/"
],
"collectCoverage": true,
"verbose": true,
"modulePathIgnorePatterns": [
"rpmbuild"
],
"unmockedModulePathPatterns": [
"<rootDir>/node_modules/react/",
"<rootDir>/node_modules/react-dom/",
"<rootDir>/node_modules/react-addons-test-utils/",
"<rootDir>/node_modules/fbjs",
"<rootDir>/node_modules/core-js"
]
},
So what am I missing?
moduleNameMapper is the setting that tells Jest how to interpret files with different extension. You need to tell it how to handle Less files.
Create a file like this in your project (you can use a different name or path if you’d like):
config/CSSStub.js
module.exports = {};
This stub is the module we will tell Jest to use instead of CSS or Less files. Then change moduleNameMapper setting and add this line to its object to use it:
'^.+\\.(css|less)$': '<rootDir>/config/CSSStub.js'
Now Jest will treat any CSS or Less file as a module exporting an empty object. You can do something else too—for example, if you use CSS Modules, you can use a Proxy so every import returns the imported property name.
Read more in this guide.
I solved this by using the moduleNameMapper key in the jest configurations in the package.json file
{
"jest":{
"moduleNameMapper":{
"\\.(css|less|sass|scss)$": "<rootDir>/__mocks__/styleMock.js",
"\\.(gif|ttf|eot|svg)$": "<rootDir>/__mocks__/fileMock.js"
}
}
}
After this you will need to create the two files as described below
__mocks__/styleMock.js
module.exports = {};
__mocks__/fileMock.js
module.exports = 'test-file-stub';
If you are using CSS Modules then it's better to mock a proxy to enable className lookups.
hence your configurations will change to:
{
"jest":{
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(css|less|scss|sass)$": "identity-obj-proxy"
},
}
}
But you will need to install identity-obj-proxy package as a dev dependancy i.e.
yarn add identity-obj-proxy -D
For more information. You can refer to the jest docs
UPDATE who use create-react-app from feb 2018.
You cannot override the moduleNameMapper in package.json but in jest.config.js it works, unfortunately i havent found any docs about this why it does.
So my jest.config.js look like this:
module.exports = {
...,
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(scss|sass|css)$": "identity-obj-proxy"
}
}
and it skips scss files and #import quite well.
Backing my answer i followed jest webpack
Similar situation, installing identity-object-proxy and adding it to my jest config for CSS is what worked for me.
//jest.config.js
module.exports = {
moduleNameMapper: {
"\\.(css|sass)$": "identity-obj-proxy",
},
};
The specific error I was seeing:
Jest encountered an unexpected token
/Users/foo/projects/crepl/components/atoms/button/styles.css:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){.button { }
^
SyntaxError: Unexpected token .
1 | import React from 'react';
> 2 | import styles from './styles.css';
If you're using ts-jest, none of the solutions above will work! You'll need to mock transform.
jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
roots: [
"<rootDir>/src"
],
transform: {
".(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/jest-config/file-mock.js",
'.(css|less)$': '<rootDir>/jest-config/style-mock.js'
},
};
file-mock.js
module.exports = {
process() {
return `module.exports = 'test-file-stub'`;
},
};
style-mock.js
module.exports = {
process() {
return 'module.exports = {};';
}
};
I found this working example if you want more details.
Solution of #import Unexpected token=:)
Install package:
npm i --save-dev identity-obj-proxy
Add in jest.config.js
module.exports = {
"moduleNameMapper": {
"\\.(css|less|scss)$": "identity-obj-proxy"
}
}
Update: Aug 2021
If you are using Next JS with TypeScript. Simply follow the examples repo.
Else you will be wasting days configuring the environment.
https://github.com/vercel/next.js/tree/canary/examples/with-jest
I added moduleNameMapper at the bottom of my package.json where I configured my jest just like this:
"jest": {
"verbose": true,
"moduleNameMapper": {
"\\.(scss|less)$": "<rootDir>/config/CSSStub.js"
}
}
My app used to work fine until I updated VueJS this morning. Now when I build, it shows the following error:
Error: Conflict: Multiple assets emit to the same filename img/default-contractor-logo.0346290f.svg
There's only one file like this in the repo.
Here's my vue.config.js:
module.exports = {
baseUrl: '/my/',
outputDir: 'dist/my',
css: {
loaderOptions: {
sass: {
data: `
#import "#/scss/_variables.scss";
#import "#/scss/_mixins.scss";
#import "#/scss/_fonts.scss";
`
}
}
},
devServer: {
disableHostCheck: true
}
};
I tried webpack fixes recommended in similar cases, but non helped.
I had the same error when importing SVG files using dynamically generated path in the require statement:
const url = require("../assets/svg/#{value}");
<img src={{url}} />
In this case file-loader processes all SVG files and saves them to the output path. My file-loader options were:
{
loader: "file-loader",
options: { name: "[name].[ext]" }
}
The folders structure has duplicate file names, something like this:
assets
|__ one
|____ file.svg
|__ two
|____ file.svg
In this case file-loader saves both file.svg files to the same output file: build/assets/file.svg - hence the warning.
I managed to fix it by adding [path] to the name option:
{
loader: "file-loader",
options: { name: "[path][name].[ext]" }
}
The answer by #ischenkodv is definitely correct, but because of my inexperience with webpack, I needed a little more context to use the information to fix the problem.
For the benefit of anyone else in the same situation, I'm adding the following details which I hope will be useful.
This section of the Vue.js documentation was particularly helpul:
VueJS - Modifying Options of a Loader
For the TL;DR fix, here is the relevant chunk of my vue.config.js:
// vue.config.js
module.exports = {
// ---snip---
chainWebpack: config =>
{
config.module
.rule('svg')
.test(/\.svg$/)
.use('file-loader')
.tap(options =>
{
return { name: "[path][name].[ext]" };
});
}
// ---snip---
};
In my project it was the flag-icon-css NPM package that was causing the Multiple assets emit to the same filename conflict errors. The above update to the vue.config.js file resolved the problem for me.
I suspect that the regular expression in the test could be tightened up to target just the items in the flag-icon-css package rather than matching all SVG files, but I haven't bothered since it's not causing any adverse effects so far.
I'm compiling my first angular library using rollupjs and I need your help :)
Currently I have a structure like this:
.src
--components
--component1
--component1.ts
--component1.scss
--component1.html
--common
--_variables.scss
And my component1.scss looks like this
#import "../../core/sass/variables";
:host {
.trigger {
&.clear_btn {
color: $color-grey;
}
}
}
My variables.sccs looks like:
$color-grey-light: #e3e3e3;
$color-grey: #bfbfbf;
and my rollup.config.js looks like:
export default {
input: 'build/index.js',
output: {
file: 'dist/common.js',
format: 'es',
},
plugins: [
angular({
preprocessors: {
template: template => minifyHtml(template, htmlminOpts),
style: scss => {
const css = sass.renderSync({data: scss}).css;
return cssmin.minify(css).styles;
},
}
})
],
external: [
'#angular/core',
'#angular/animations',
'#angular/router',
'#angular/platform-browser',
'#angular/forms'
]
};
but when I execute I get this error:
[!] (angular plugin) Error: File to import not found or unreadable: ../../core/sass/variables.
Parent style sheet: stdin
build/app/components/toggle/toggle.component.js
Error: File to import not found or unreadable: ../../core/sass/variables.
Parent style sheet: stdin...
I tried adding importer from node-sass but to be honest I have no idea how to use it to compile everything into css and then inject it to my js (I can actually inject the scss into my template by using rollup-plugin-angular but I don't know how to compile scss)
Any help, tips or suggestions will be really appreciated :)