Import HTML as string and test with Jest - node.js

I'm using sveltekit and I can't use the files api to import html templates. So I decided to import by writing a module that imports the content of the document as a string (described here).
// src/global.d.ts
/// <reference types="#sveltejs/kit" />
declare module '*.html' {
const content: string
export default content
}
So far so good, but now I need to test the code and jest can't interpret the code.
● Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.
By default "node_modules" folder is ignored by transformers.
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
• If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation
Details:
/home/developer/workspace/src/assets/html/confirm_email.html:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){<!DOCTYPE html>
^
SyntaxError: Unexpected token '<'
I don't understand how jest understands the .d.ts files... How do I get to test the code?

Do you install #babel/plugin-transform-runtime"?
I share my config for jest/svelte-jester..
I have:
jsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"$lib": ["src/lib"],
"$lib/*": ["src/lib/*"]
}
},
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"],
}
svelte.config.js
import vercel from '#sveltejs/adapter-vercel'
/** #type {import('#sveltejs/kit').Config} */
const config = {
kit: {
adapter: vercel(),
vite: {
define: {
'process.env': process.env,
},
},
},
transform: {
"^.+\\.svelte$": ["svelte-jester", { "preprocess": true }]
}
};
export default config;
babel.config.json
{
"presets": [
["#babel/preset-env", { "modules": "auto" }]
],
"plugins": ["babel-plugin-transform-vite-meta-env","#babel/plugin-transform-runtime"]
}
jest.config.js
export default {
"transform": {
"^.+\\.js$": "babel-jest",
"^.+\\.svelte$": "svelte-jester",
},
"moduleFileExtensions": ["svelte", "js"],
"testEnvironment": "jsdom",
"setupFilesAfterEnv": ["#testing-library/jest-dom/extend-expect"]
}
and whole package.json
{
"name": "sveltekit",
"version": "0.0.1",
"scripts": {
"dev": "svelte-kit dev",
"build": "svelte-kit build",
"package": "svelte-kit package",
"preview": "svelte-kit preview",
"test": "jest src",
"test:watch": "npm run test -- --watch"
},
"devDependencies": {
"#babel/core": "^7.16.12",
"#babel/plugin-transform-modules-commonjs": "^7.16.8",
"#babel/plugin-transform-runtime": "^7.17.0",
"#babel/preset-env": "^7.16.11",
"#supabase/supabase-js": "^1.29.1",
"#sveltejs/adapter-auto": "^1.0.0-next.7",
"#sveltejs/kit": "^1.0.0-next.215",
"#sveltejs/svelte-virtual-list": "^3.0.1",
"#testing-library/svelte": "^3.0.3",
"autoprefixer": "^10.4.1",
"babel-jest": "^27.4.6",
"babel-plugin-transform-vite-meta-env": "^1.0.3",
"jest": "^27.4.7",
"postcss-load-config": "^3.1.1",
"prettier": "^2.5.1",
"prettier-plugin-svelte": "^2.5.1",
"svelte": "^3.44.0",
"svelte-jester": "^2.1.5",
"svelte-lazy": "^1.0.12",
"tailwindcss": "^3.0.8",
"ts-jest": "^27.1.3"
},
"type": "module",
"dependencies": {
"#fontsource/fira-mono": "^4.5.0",
"#lukeed/uuid": "^2.0.0",
"#testing-library/jest-dom": "^5.16.1",
"cookie": "^0.4.1",
"svelte-lazy-image": "^0.2.0",
"swiper": "^8.0.3"
},
"testEnvironment": "jsdom"
}
I hope it will help you.I had a lot of troubles too with setting up jest..

1.Import html as string
I solved the problem using another approach...
I'm using a resource of vite to import the html file as an asset, as can be seen here in the documentation
import confirm_email_template from '../../../assets/html/confirm_email.html?raw'
2.Test using Jest
For production it works perfectly, but for unit testing the code breaks because Jest can't import the asset as a module.
So the second part of the problem was fixed (I don't know if this is the best practice) using asset mocks.
// jest.config.cjs
{
⋮
moduleNameMapper: {
⋮
'([a-zA-Z_ ]+\\.html)\\?raw$': '<rootDir>/__mocks/$1.cjs'
}
⋮
}
To make it work, I created the following folder structure:
__mocks
|
confirm_email.html.cjs
another_asset_mocked.html.cjs
The confirm_email.html.cjs looks like this:
// __mocks/confirm_email.html.cjs
module.exports = '<html>content<html>'

Related

I cant import with jest in vue

im trying to learn testing but i get this problem. It seem that jest can not import modules. I have tried a lot of configurations but i couldn't solve it
Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.
By default "node_modules" folder is ignored by transformers.
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
• If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation
Details:
/home/alain-maza/Documentos/entrenamiento/vue/04-pokemon/node_modules/axios/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import axios from './lib/axios.js';
^^^^^^
SyntaxError: Cannot use import statement outside a module
> 1 | import axios from "axios";
| ^
2 |
3 | const pokemonApi = axios.create({
4 | baseURL: 'https://pokeapi.co/api/v2/pokemon'
this is my jest.config
module.exports = {
preset: '#vue/cli-plugin-unit-jest',
}
this is my babel.config
module.exports = {
presets: [
'#vue/cli-plugin-babel/preset'
]
}
and my package.json
{
"name": "04-pokemon",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit"
},
"dependencies": {
"axios": "^1.0.0",
"core-js": "^3.8.3",
"vue": "^3.2.13"
},
"devDependencies": {
"#babel/core": "^7.19.3",
"#babel/preset-env": "^7.19.4",
"#vue/cli-plugin-babel": "~5.0.0",
"#vue/cli-plugin-unit-jest": "~5.0.0",
"#vue/cli-service": "~5.0.0",
"#vue/test-utils": "^2.0.0-0",
"#vue/vue3-jest": "^27.0.0-alpha.1",
"babel-jest": "^27.5.1",
"jest": "^27.0.5"
}
}
heklpme please! i have trried a lot of things

How to import d3.js in a node and typescript project? [ERR_REQUIRE_ESM]

I'm working on a node project using typescript, oclif and d3.js, among other things. Typescript was configured by npx when creating the project with oclif so I didn't control all aspects of it (especially regarding TS, and I'm not an expert. TS is great, but configuration wise, meh).
Anyway, everything was working fine, but I recently added d3 as a dependency and tried to build a document, and I get this error when running it:
(node:22554) [ERR_REQUIRE_ESM] Error Plugin: dbacl [ERR_REQUIRE_ESM]: require() of ES Module /dbacl/node_modules/d3/src/index.js from /dbacl/src/tree/graph-tree.ts not supported.
Instead change the require of index.js in /Users/nico/Furo/Dev/dbacl/src/tree/graph-tree.ts to a dynamic import() which is available in all CommonJS modules.
In the file where I'm using d3 I import it as per documentation:
import * as d3 from 'd3'
I suspect it might be a problem after compiling, so here is tsconfig.json. I didn't change anything since generation by npx.
{
"compilerOptions": {
"declaration": true,
"importHelpers": true,
"module": "commonjs",
"outDir": "dist",
"rootDir": "src",
"strict": true,
"target": "es2019",
},
"include": [
"src/**/*"
]
}
And in case it's more relevant, here is my package.json file as well (didn't change anything either):
{
"name": "dbacl",
"version": "0.0.0",
"description": "",
"author": "",
"bin": {
"dbacl": "./bin/run"
},
"license": "MIT",
"main": "dist/index.js",
"repository": "*****/dbacl",
"files": [
"/bin",
"/dist",
"/npm-shrinkwrap.json",
"/oclif.manifest.json"
],
"dependencies": {
"#oclif/core": "^1",
"#oclif/plugin-help": "^5",
"#oclif/plugin-plugins": "^2.0.1",
"#types/d3": "^7.4.0",
"#types/jsdom": "^16.2.14",
"d3": "^7.6.1",
"directory-tree": "^3.3.0",
"jsdom": "^20.0.0",
"lodash": "^4.17.21"
},
"devDependencies": {
"#oclif/test": "^2",
"#types/chai": "^4",
"#types/mocha": "^9.0.0",
"#types/node": "^16.9.4",
"chai": "^4",
"eslint": "^7.32.0",
"eslint-config-oclif": "^4",
"eslint-config-oclif-typescript": "^1.0.2",
"globby": "^11",
"mocha": "^9",
"oclif": "^3",
"shx": "^0.3.3",
"ts-node": "^10.2.1",
"tslib": "^2.3.1",
"typescript": "^4.4.3"
},
"oclif": {
"bin": "dbacl",
"dirname": "dbacl",
"commands": "./dist/commands",
"plugins": [
"#oclif/plugin-help",
"#oclif/plugin-plugins"
],
"topicSeparator": " ",
"topics": {
"hello": {
"description": "Say hello to the world and others"
}
}
},
"scripts": {
"build": "shx rm -rf dist && tsc -b",
"lint": "eslint . --ext .ts --config .eslintrc",
"postpack": "shx rm -f oclif.manifest.json",
"posttest": "yarn lint",
"prepack": "yarn build && oclif manifest && oclif readme",
"test": "mocha --forbid-only \"test/**/*.test.ts\"",
"version": "oclif readme && git add README.md"
},
"engines": {
"node": ">=12.0.0"
},
"keywords": [
"oclif"
],
"types": "dist/index.d.ts"
}
I find this problem quite confusing because everywhere I've been searching about this problem, it seems I'm doing the right thing. I assume the problem might be between my screen and my chair, but really I don't get it. Also, should I use the dynamic import like this?
const d3 = await import('d3')
I tried, it didn't work. I made the function that generates the document async and added that line at the start but nope. Anyway, if I believe the error, that would be the way to go but I didn't see this solution anywhere when looking for a solution to my problem. What do you guys think?
Thanks
So thanks to the input from a colleague and this article, the problem is that d3 now supports ESM only. So when the compiler turns the import into
// index.ts
import * as d3 from 'd3'
// compiled index.js
const d3 = require('d3')
it just doesn't work. I was using d3 version 7, and a quick fix to it was to downgrade to version 6.7.0, when it did support commonJS.
Now, I have to move on with this project, but I'll keep looking into it and into how I can use a recent version of d3 in my project. If I do, I'll edit that answer!
Cheers

ESLint linting my Typescript files correctly

I have .js files ( src/client/...) and .ts files ( src/server/.. )
I installed the following packages :
package.json
"eslint": "^5.11.1",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-config-typescript": "^1.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-typescript": "^0.14.0",
....
"typescript": "^3.0.3",
"typescript-eslint-parser": "^21.0.2",
And I defined the following aslant config in package.json
"eslintConfig": {
"extends": ["airbnb-base", "eslint:recommended", "typescript"],
"env": { "es6": true, "browser": true },
"parserOptions": { "parser": "typescript-eslint-parser" },
"plugins": ["typescript"],
"rules": {
"no-unused-vars": ["error", { "vars": "all", "args": "after-used", "ignoreRestSiblings": false }],
"no-var": ["off"],
"one-var": ["off"],
"prefer-destructuring": ["error", { "object": false, "array": false } ],
"no-underscore-dangle": ["error", { "allow": ["__blogPostData"] }]
}
}
Then I set the lint script :
"lint": "eslint src --fix",
It's listing correctly all my .js files , but I don't see any warnings/errors in my .ts files ( I doubt they are all well written...)
Am I wrong or missing anything in my eslint setup for typescript ?
parser is a root-level config item, not a field of parserOptions:
"eslintConfig": {
"parser": "typescript-eslint-parser"
"parserOptions": { ...options },
"plugins": ["typescript"]
}
Also, the parser and plugin you are using are deprecated. The newer/maintained projects are both available at https://github.com/typescript-eslint/typescript-eslint. (Config is the same, just with updated names). Here is an nice step-by-step walk-through on how to set this up - https://dev.to/robertcoopercode/using-eslint-and-prettier-in-a-typescript-project-53jb
Note that rather than defining your eslint config in package.json, you could instead use a separate.eslintrc.{js,yaml}. One in the root directory would setup your standard rules for JavaScript and another one in ./src/server could setup the TypeScript parser & plugin only for the relevant directory (but still pick up all your standard root rules).
You should use tslint for TypeScript, not eslint:
npm i tslint --save
after that, create a tslint.json in your project root (or pick one from the web with the rules you like). Just a link I found on Google: ts lint setup

TypeScript: Could not find a declaration file for module in unit tests, only

I'm using TypeScript with Visual Studio Code on Windows 10 to develop an NPM module. I use mocha/chai combined with nyc (istanbul) for unit testing and code coverage.
For some of my tests I would like to use chai-bytes to compare buffers more easily. Unfortunately, there is no type definition file in the chai-bytes module and there is no definition at #types/chai-bytes available.
Therefore, I have written my own type definition file for the chai-bytes plugin (which is very simple), but during execution of npm test I get the following error:
TSError: ⨯ Unable to compile TypeScript:
test/utls/BitArray-test.ts(3,23): error TS7016: Could not find a declaration file for module 'chai-bytes'. 'C:/Users/<user>/Source/Repos/velux-api/node_modules/chai-bytes/index.js' implicitly has an 'any' type.
Try `npm install #types/chai-bytes` if it exists or add a new declaration (.d.ts) file containing `declare module 'chai-bytes';`
test/utls/BitArray-test.ts(48,38): error TS2339: Property 'equalBytes' does not exist on type 'Assertion'.
VS Code provides me with full Intellisense, so I think my type definition file works and is found at least by VS Code.
This is my directory structure:
dist\ <-- My compiled code goes here
utils\
BitArray.d.ts
BitArray.js
BitArray.js.map
index.d.ts
index.js
index.js.map
...
src\
utils\
BitArray.ts
index.ts
...
test\
utils\
BitArray-test.ts
... (other test files)
mocha.opts
types\
chai-bytes\
index.d.ts <-- Type definition file for 'chai-bytes'
I have tried to move the type definition file to the source tree (several places), but with no effect, besides, that sometimes it got even worse, so that even VS Code haven't found it anymore.
These are my config files:
package.json:
{
"name": "klf-200-api",
"version": "3.0.0",
"description": "This module provides a wrapper to the socket API of a Velux KLF-200 interface. You will need at least firmware 0.2.0.0.71 on your KLF interface for this library to work.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"author": {
"name": "Michael Schroeder"
},
"dependencies": {
"#types/promise-timeout": "^1.3.0",
"promise-timeout": "^1.3.0"
},
"devDependencies": {
"#types/chai": "^4.1.6",
"#types/chai-as-promised": "^7.1.0",
"#types/mitm": "^1.3.2",
"#types/mocha": "^5.2.5",
"#types/node": "^10.11.7",
"#types/sinon": "^5.0.7",
"#types/sleep": "0.0.7",
"babel-eslint": "^8.0.0",
"chai": "^4.1.0",
"chai-as-promised": "^7.1.1",
"chai-bytes": "^0.1.1",
"chai-sinon": "^2.8.1",
"cross-env": "^5.2.0",
"eslint": "^4.7.1",
"eslint-config-defaults": "^9.0.0",
"eslint-plugin-react": "^7.3.0",
"gulp": "^4.0.0",
"gulp-release-it": "^2.0.14",
"gulp-typescript": "^5.0.0-alpha.3",
"gulp-uglify": "^3.0.1",
"istanbul": "^0.4.5",
"mitm": "^1.4.0",
"mocha": "^3.4.2",
"nock": "^9.0.14",
"nyc": "^13.1.0",
"sinon": "^7.1.1",
"sleep": "^5.2.3",
"source-map-support": "^0.5.9",
"ts-mocha": "^2.0.0",
"ts-node": "^7.0.1",
"typescript": "^3.1.2",
"uglify-es": "^3.3.9"
},
"scripts": {
"test": "cross-env TS_NODE_FILES=true nyc mocha",
"document": "jsdoc src -r -c ./.jsdoc.json -d docs"
},
"nyc": {
"include": [
"src/**/*.ts",
"src/**/*.tsx"
],
"extension": [
".ts",
".tsx"
],
"exclude": [
"**/*.d.ts"
],
"reporter": [
"text-summary",
"html"
],
"all": true
},
"repository": {
"type": "git",
"url": "https://github.com/MiSchroe/klf-200-api"
},
"keywords": [
"klf-200",
"IoT"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/MiSchroe/klf-200-api/issues"
},
"homepage": "https://mischroe.github.io/klf-200-api/"
}
tsconfig.json:
{
"compilerOptions": {
/* Basic Options */
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"declaration": true, /* Generates corresponding '.d.ts' file. */
"sourceMap": true, /* Generates corresponding '.map' file. */
"outDir": "./dist", /* Redirect output structure to the directory. */
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
/* Module Resolution Options */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
},
"include": [
"./src/**/*"
]
}
mocha.opts:
--require ts-node/register
--require source-map-support/register
--recursive
--full-trace
--bail
test/**/*.ts
types\chai-bytes\index.d.ts:
/// <reference types="chai" />
declare module "chai-bytes" {
function chaiBytes(chai: any, utils: any): void;
export = chaiBytes;
}
declare namespace Chai {
// For BDD API
interface Assertion extends LanguageChains, NumericComparison, TypeComparison {
equalBytes(expected: string | Array<number> | ArrayLike<number>): void;
}
}
BitArray-test.ts (only the relevant test):
import { expect } from "chai";
import { bitArrayToArray, arrayToBitArray } from "../../src/utils/BitArray";
import chaibytes from "chai-bytes";
'use strict';
chai.use(chaibytes);
describe("...", function() {
it("should return an the correctly filled buffer", function() {
const nums: number[] = [0, 2, 4, 6, 8, 10, 12, 14];
const result = arrayToBitArray(nums, 2);
expect(result).to.be.an.instanceof(Buffer);
expect(result).to.be.equalBytes([0x55, 0x55]);
});
});
npm --version:
3.10.10
node --version:
v6.11.1
I could use Buffer.compare as work-around instead, but then I wouldn't see the buffers' content in the error message but only a -1, 0 or 1. (And it wouldn't solve the problem.)
Currently, I'm stuck at that point and any help is much appreciated.
At tsconfig.json add:
"typeRoots": [
"./node_modules/#types",
"./types"
] /* List of folders to include type definitions from. */
to the compilerOptions list.
Change the header of the BitArray-test.ts file:
import { bitArrayToArray, arrayToBitArray } from "../../src/utils/BitArray";
import chaibytes from "chai-bytes";
import { expect, use } from "chai";
'use strict';
use(chaibytes);

unexpected token import in ES2017 with babel and Jest

I try to use Jest with bablejs and ES2017 in my project, according to the Jest Getting Started page and also Bablejs config for ES2017 this is my .babelrc file :
{
"presets": ["es2017"],
"env": {
"test": {
"presets": ["es2017"]
}
}
}
And my package.json is:
{
"name": "",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "jest"
},
"repository": {
"type": "git",
"url": ""
},
"author": "",
"license": "ISC",
"bugs": {
"url": ""
},
"homepage": "",
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-jest": "^21.2.0",
"babel-polyfill": "^6.26.0",
"babel-preset-es2017": "^6.24.1",
"jest": "^21.2.1"
}
}
When I type npm test to run all my test with jest i get these error :
){import StateList from './StateList';
^^^^^^
SyntaxError: Unexpected token import
It means it doesn't know import.
babel-preset-es2017 does not transform import statements, because it only includes the plugins: syntax-trailing-function-commas and
transform-async-to-generator.
When installing babel-preset-es2017 you also get a warning that it has been deprecated in favour of babel-preset-env, which contains everything that the es201x presets contained and more.
warning babel-preset-es2017#6.24.1: 🙌 Thanks for using Babel: we recommend using babel-preset-env now: please read babeljs.io/env to update!
As shown in the Migration guide from es2015 to env, it is a drop-in replacement.
npm install --save-dev babel-preset-env
And change your .babelrc to:
{
"presets": ["env"]
}
Do not confuse babel-preset-env with Babel's env option, which I have removed from your current config, since you are using the exact same presets for the test environment as for any other, so it doesn't have any effect.
You can configure babel-preset-env to only transform features that are not supported by the platform you target, for example { "targets": { "node": "current" } } will only transform features that aren't supported by the Node version you are running. If no targets are specified, it will transform everything. For details see the Env preset documentation.
Note: With the upcoming version 7 of Babel, the official packages will be published under the namespace #babel, which means that babel-preset-env will be #babel/preset-env.

Resources