Testing svelte components with import.meta.env - jestjs

I'm struggeling now for a couple of days to get my testsetup running. Rough outline: Vite, Svelte (with ts), Jest.
I'm using import.meta.env.SOMENAME for my environment vars although this works fine for development as soon as a component uses import.meta.env the test will fail with:
SyntaxError: Cannot use 'import.meta' outside a module
I've tried different transformers, babel-plugins and configs but never succeeded...
My jest config:
"jest": {
"globals": {
"ts-jest": {
"isolatedModules": true
}
},
"verbose": true,
"transform": {
"^.+\\.svelte$": [
"svelte-jester",
{
"preprocess": true
}
],
"^.+\\.ts$": "ts-jest",
"^.+\\.js$": "babel-jest"
},
"setupFilesAfterEnv": ["<rootDir>/setupTests.ts"],
"moduleFileExtensions": ["js", "ts", "svelte"]
}
babel.config.js
module.exports = {
presets: [
[
"#babel/preset-env",
{
targets: {
node: "current"
}
}
]
]
};
svelte.config.cjs
const sveltePreprocess = require('svelte-preprocess')
module.exports = {
emitCss: true,
preprocess: sveltePreprocess()
};
Among other things I tried to use #babel/plugin-syntax-import-meta but ended up with the same error. Also vite-jest looked very promising but again I couldn't make it work.
I appreciate every hint I can get. If I can provide any additional info please let me know. Also my knowledge of vite and babel is very limited so REALLY appreciate any help IU can get on this topic.
Update (Solution)
So If you use babel you could use babel-preset-vite. The approach with esbuild-jest from Apu is also good solution that many people use. Unfortunately those things didn't work for me so I decided to use a workaround with vite's define.
This workaround consists of two steps.
replace import.meta.env with process.env (if this is a deal breaker for you then I hope you have luck with the solutions above) You only have to replace the instances in files you want to test with jest.
Update Vite config with define. This step is necessary or your build will break (dev will still work)
vite.config.js
const dotEnvConfig = dotenv.config();
export default defineConfig({
define: {
"process.env.NODE_ENV": `"${process.env.NODE_ENV}"`,
"process.env.VITE_APP_SOMENAME": `"${process.env.VITE_APP_SOMENAME}"`
},
...
)};
I know this is just a workaround but maybe this helps someone. Thanks & Good Luck.

A more recent alternative to Jest that understands import.meta.env is Vitest.
It should require almost no additional configuration to get started and it's highly compatible with Jest so it requires few changes to the actual tests.
The advantages of Vitest over Jest for this use case are:
It's designed specifically for Vite and will process tests on demand
It will reuse your existing Vite configuration:
Any define variables will be replaced as expected
Extensions that Vite adds to import.meta will be available as usual

I was having issues with svelte component testing as well using jest. babel is not good at resolving import.meta. I used esbuild-jest to transform both ts and js files. It solves the issue with the import.meta. Here is my jest.config.cjs.
npm i esbuild esbuild-jest -D
const { pathsToModuleNameMapper } = require('ts-jest/utils');
const { compilerOptions } = require('./tsconfig');
const config = {
"transform": {
"^.+\\.svelte$": [
"svelte-jester",
{
"preprocess": true
}
],
"^.+\\.(ts|tsx|js|jsx)$": ["esbuild-jest"]
},
"moduleFileExtensions": [
"js",
"ts",
"tsx",
"svelte"
],
"setupFilesAfterEnv": [
"#testing-library/jest-dom/extend-expect"
],
"collectCoverageFrom": [
"**/*.(t|j)s",
"**/*.svelte"
],
coverageProvider: 'v8',
"coverageDirectory": "./coverage",
"coveragePathIgnorePatterns": [
"/node_modules/",
"/.svelte-kit/"
],
"moduleNameMapper": pathsToModuleNameMapper(compilerOptions.paths, {prefix: '<rootDir>/'})
};
module.exports = config;

Related

JEST with Handlebars configuration

I am trying to add Jest to existing project and i have problem with configuration.
To solve problem with modules and es6 i added rollup-jest package (we are using rollup on our project)
To solve problem with handlebars i tried to use jest-handlebars package but i got problem
Code transformer's `process` method must return an object containing `code` key
with processed string. If `processAsync` method is implemented it must return
a Promise resolving to an object containing `code` key with processed string.
Code Transformation Documentation:
https://jestjs.io/docs/code-transformation```
Has anybody aby similar problem with jest plus handlebars configuration or can anybody help me with code transformator?
EDIT:
i added preprocessor.js file with:
module.exports = {
process(src) {
const code = `
const Handlebars = require('handlebars');
module.exports = Handlebars.compile(\`${src}\`);
`
return {
code: code
};
},
};
and change my packaged.json to:
``` "jest": {
"preset": "rollup-jest",
"collectCoverage": true,
"modulePaths": [
"./",
"./node_modules"
],
"moduleFileExtensions": [
"js",
"hbs",
"ts"
],
"transform": {
"\\.js$": "rollup-jest",
"^.+\\.hbs$": "<rootDir>/jestHbsTransformer.js",
"^.+\\.ts?$": "ts-jest"
}
}
}```
and it is still not working ;)
enter code here

How can I get ESLint to recognize aggregate export namespaces?

The Situation
I have a NodeJS project that uses Babel and ESLint (6.8).
I'm using the relatively new syntax for aggregate exports (export * as name1 from …;).
The Code
constants.js
export const x = 5
export const y = 6
index.js
export * as constants from './constants'
sandbox.js
import { constants } from './index'
console.log(constants.x)
When I run babel-node sandbox.js everything works just fine, and the value for x (5) is rendered.
.eslintrc
{
"extends": "airbnb-base",
"parser": "babel-eslint",
"env": {
"es6": true,
"node": true,
"jest": true
}
}
.babelrc
{
"presets": [
[
"#babel/preset-env",
{
"targets": {
"node": "13.10"
}
}
]
],
"plugins": [
"#babel/plugin-proposal-export-namespace-from"
]
}
The Problem
ESLint seems to be confused by my aggregate export, rendering the following error when I lint:
sandbox.js
1:10 error constants not found in './index' import/named
The Question
How do I get ESLint to recognize that the named aggregate does in fact exist? I would like to be able to still benefit from the import/named checks overall.

ESLint conflicts with eslint-plugin-import and typescript-eslint

I want to include the rule no-unpublished-import from eslint-plugin-node, however, it is conflicting with my current .eslintrc because I am using typescript-eslint and eslint-import-resolver-typescript.
It is my current configuration:
{
"parser": "#typescript-eslint/parser", // Specifies the ESLint parser
"extends": [
"airbnb-base",
"plugin:#typescript-eslint/recommended", // Uses the recommended rules from the #typescript-eslint/eslint-plugin
"prettier", // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array
"prettier/#typescript-eslint" // Uses eslint-config-prettier to disable ESLint rules from #typescript-eslint/eslint-plugin that would conflict with prettier
],
"parserOptions": {
"project": "./tsconfig.json",
"ecmaVersion": 6, // Allows for the parsing of modern ECMAScript features
"sourceType": "module" // Allows for the use of imports
},
"rules": {
},
"settings": {
"import/resolver": {
"node": {
"extensions": [".js", ".ts"]
},
// use <root>/tsconfig.json
"typescript": {
"alwaysTryTypes": true // always try to resolve types under `<root>#types` directory even it doesn't contain any source code, like `#types/unist`
}
}
},
"root": true
}
The code compiles correctly, however, if I add to the extends option the plugin:node/recommended the compilation process will fail:
1:1 error Import and export declarations are not supported yet node/no-unsupported-features/es-syntax
1:43 error "express" is not found node/no-missing-import
2:1 error Import and export declarations are not supported yet node/no-unsupported-features/es-syntax
My package.json includes the node": ">=12.0.0. Also, this rule should be ignored because I am using typescript. On the other hand, I am just exporting types from express because the module don't use it.
According to this issue the conflict should be resolved by eslint-plugin-node.
How can I accomplish the merge of both plugins? Do I have to go disabling rules one by one?
UPDATED:
It seems it was asked in this issue on the eslint-plugin-node repository. It works for no-unsupported-features and no-missing-import, however, it is still failing with the import definition of express with no-extraneous-import.
UPDATED 2:
It seems eslint-plugin-node is working on a enhancement to accomplish it. Issue here
Firstly, you have to add the option tryExtension to include TS files:
"settings": {
"node": {
"tryExtensions": [".js", ".json", ".node", ".ts", ".d.ts"]
},
To solve the no-unsupported-features/es-syntax, according to this issue about adding information to works with TypeScript, if you work with transpilers you will have to ignore it under rules:
"node/no-unsupported-features/es-syntax": ["error", { "ignores": ["modules"] }],
On the other hand, use just types and not the code is not supported yet by the eslint-plugin-node. They are working on a enhancement to solve it. However,, to solve the no-missing-import, you have to add to the resolvePath the node_modules/#types:
"node": {
"resolvePaths": ["node_modules/#types"],
"tryExtensions": [".js", ".json", ".node", ".ts", ".d.ts"]
},
Even so, it will generate a no-extraneous-import because it doesn't detect the module, because it is just a type. Meanwhile they are working on this enhancement, you can use allowModules under that rule for workaround:
"node/no-extraneous-import": ["error", {
"allowModules": ["express"]
}]

Trying to build Jest is throwing "Caching was left unconfigured."

I have the following .babelrc.js in the root folder:
{
"plugins": [
"#babel/plugin-transform-flow-strip-types",
"#babel/plugin-transform-modules-commonjs",
"#babel/plugin-transform-async-to-generator",
"#babel/plugin-transform-strict-mode",
"#babel/plugin-transform-runtime"
],
"cache": "true"
}
but when it tries to run node ./packages/jest-cli/bin/jest.js I see:
Caching was left unconfigured. Babel's plugins, presets, and .babelrc.js files can be configured
for various types of caching, using the first param of their handler functions:
What am I missing?
Use new babel.config.js
https://new.babeljs.io/docs/en/next/babelconfigjs.html
module.exports = function(api) {
api.cache(true)
return {
plugins: [
"#babel/plugin-transform-flow-strip-types",
"#babel/plugin-transform-modules-commonjs",
"#babel/plugin-transform-async-to-generator",
"#babel/plugin-transform-strict-mode",
"#babel/plugin-transform-runtime"
]
}
}

Jest, Typescript, ts-jest: Coverage is slightly incorrect

I am wrtiting a project using TypeScript, Jest and the ts-jest NPM module.
When I run my test, I do get some amount of coverage, but the HTML report is not quite right:
Furthermore, some functions are being marked as untested even though they are certainly being called.
My package.json is set as follows:
{
"jest": {
"transform": {
".(ts|tsx)": "<rootDir>/node_modules/ts-jest/preprocessor.js"
},
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
"moduleFileExtensions": [
"ts",
"tsx",
"js"
],
"testResultsProcessor": "<rootDir>/node_modules/ts-jest/coverageprocessor.js",
"collectCoverage": true,
"collectCoverageFrom": [
"src/**/*.{ts,tsx}"
],
"coverageReporters": [
"html",
"json"
]
}
}
Is something wrong with my configuration?
UPDATE
Starting from jest#20 you can pass mapCoverage option and use coverage/lcov-report/index.html file.
OLD
I also have been struggling with this problem, but then I notice that line.
Long story short - coverage reports goes to coverage/remapped/html/index.html file.

Resources