require() of ES Module gulpfile.js not supported n gulp node js - node.js

gulpfile.js
'use strict';
const gulp = require("gulp");
const imagemin = require("gulp-imagemin");
const webp = require("imagemin-webp");
const extReplace = require("gulp-ext-replace");
gulp.task("exportWebP", function() {
let src = "artists/**/*.jpg"; // Where your PNGs are coming from.
let dest = "dist/images"; // Where your WebPs are going.
return gulp.src(src)
.pipe(imagemin([
webp({
quality: 75
})
]))
.pipe(extReplace(".webp"))
.pipe(gulp.dest(dest));
});
package.json
{
"type": "module",
"main": "gulpfile.js",
"dependencies": {
"gulp-ext-replace": "^0.3.0",
"gulp-imagemin": "^8.0.0",
"imagemin-webp": "^7.0.0"
},
"devDependencies": {
"gulp": "^4.0.2"
}
}
here i run gulp js file it show the error
Error [ERR_REQUIRE_ESM]: require() of ES Module index.js from gulpfile.js not supported.
Instead change the require of index.js in gulpfile.js to a dynamic import() which is available in all CommonJS modules.
at Object. (gulpfile.js:3:18)
at async Promise.all (index 0) {
code: 'ERR_REQUIRE_ESM'
}
how to solve this problem.

Many packages moved to esm modules and can no longer be imported using require
Change require to import
import gulp from "gulp";
import imagemin from "gulp-imagemin";
import webp from "imagemin-webp";
import extReplace from "gulp-ext-replace";

Related

Testing with NPM three mocha+typescript

I try to add test for my code use three according to Testing-with-NPM
Use typescript + mocha. it works great with following code
const THREE = require('three');
// const ConvexHull = require('three/examples/jsm/math/ConvexHull');
const assert = require('assert');
describe('The THREE object', function() {
it('should have a defined BasicShadowMap constant', function() {
assert.notEqual('undefined', THREE.BasicShadowMap);
}),
it('should be able to construct a Vector3 with default of x=0', function() {
const vec3 = new THREE.Vector3();
assert.equal(0, vec3.x);
// let cc = new ConvexHull();
})
})
but when i uncomment following code and use ConvexHull
const ConvexHull = require('three/examples/jsm/math/ConvexHull');
let cc = new ConvexHull();
I got a error
Error: Cannot find module 'D:\xxx\node_modules\three\examples\jsm\math\ConvexHull'
Use typescript load it with import does not work either.
import * as THREE from 'three';
import { ConvexHull } from 'three/examples/jsm/math/ConvexHull';
And I can't use any class under node_modules\three\examples\jsm.
All of them give a Error: Cannot find module error.
Want to use classes provided under node_modules\three\examples\jsm folder
part of package.json
"scripts": {
"test": "mocha -r ts-node/register test/*.ts --reporter list"
},
"devDependencies": {
"#types/mocha": "^10.0.1",
"#types/node": "^18.11.18",
"#types/three": "^0.148.0",
"mocha": "^10.2.0",
"three": "^0.148.0",
"ts-node": "^10.9.1",
"typescript": "^4.9.4"
}
Don't know how to solve it. any ideas would be appreciated, thanks.
The extension for the file you want to import may be needed.
Node likely struggles to solve the path without it for various reasons.
EDIT:
I tried their code on my PC and added a test case against a "convexHull" object. I have also used the .mjs extension instead of .js to avoid modifying the package.json.
All test cases are okay.
Here is the code:
JAVASCRIPT
unit-test-2.specs.mjs
import * as THREE from 'three';
import assert from "assert";
import {ConvexHull} from 'three/examples/jsm/math/ConvexHull.js';
describe('The THREE object', function ()
{
it('should have a defined BasicShadowMap constant', function ()
{
assert.notEqual('undefined', THREE.BasicShadowMap);
}),
it('should be able to construct a Vector3 with default of x=0', function ()
{
const vec3 = new THREE.Vector3();
assert.equal(0, vec3.x);
})
it("should have the convexHull tolerance set to -1", function ()
{
let cc = new ConvexHull();
assert.equal(cc.tolerance, -1);
})
})
To run the test:
npm test
I am adding the package.json, so you can compare the dependency versions:
package.json
{
"scripts": {
"test": "mocha --reporter list"
},
"devDependencies": {
"mocha": "^10.2.0",
"three": "^0.148.0"
}
}
TYPESCRIPT
The "Three" module contains a type declaration file "index.d.ts". However, it does not expose the class ConvexHull as it's not part of Three core codes.
Because of this, copy the example folder in your root directory (outside the node_modules, at least).
Create a tsconfig.json within your test directory so it does not affect your main tsconfig:
📝 test/tsconfig.json ↴
{
"compilerOptions": {
"allowJs": true,
"checkJs": false // <- Optional
}
}
Create .mocharc.json to make Mocha aware of how to run the tests
📝 .mocharc.json ↴
{
"extensions": ["ts"],
"require": [
"test/register-test.js"
],
"spec": [
"test/**/*.spec.ts"
]
}
Create the file the .mocharc is referring to:
📝 register.js ↴
require("ts-node").register({
project: "test/tsconfig.json"
});
package.json to compare versions
📝 package.json ↴
{
"scripts": {
"test": "mocha --config test/.mocharc.json"
},
"devDependencies": {
"#types/mocha": "^7.0.2",
"#types/node": "^18.11.18",
"mocha": "^10.2.0",
"ts-node": "^8.9.0",
"typescript": "^3.8.3"
},
"dependencies": {
"#types/three": "^0.148.0",
"three": "^0.148.0"
},
"type": "commonjs"
}
Update the tests:
📝 test/unit/unit-test.js ↴
import { strict as assert } from 'node:assert';
import * as THREE from 'three';
import {ConvexHull} from '../../examples/jsm/math/ConvexHull';
describe('The THREE object', function ()
{
it('should have a defined BasicShadowMap constant', function ()
{
console.log(THREE.BasicShadowMap);
assert.notEqual(undefined, THREE.BasicShadowMap);
})
it('should be able to construct a Vector3 with default of x=0', function ()
{
const vec3 = new THREE.Vector3();
assert.equal(0, vec3.x);
})
it("should have the convexHull tolerance set to -1", function ()
{
let cc = new ConvexHull();
assert.equal(cc.tolerance, -1);
})
})
I have a structure like that:
📁 root
│
└───📁 examples
│ └───📁 jsm
│ └───📁 math
│ 📝 ConvexHull.js
└───📁 test
│ │─ 📝 .mocharc.json
│ │─ 📝 .register-test.js
│ │─ 📝 .tsconfig.json
│ └───📁 unit
│ 📝 unit-test.ts
│
│─ 📝 package.json
Run the test
npm test
All test cases will pass.
Note: I might update this post

MakeCallback DeprecationWarning error when running Foundation for Emails build process

I'm using Foundation for Emails Sass Version to generate HTML emails. I have made a few small changes to the gulpfile and package.json, but for the most part it is exactly what is given on the Foundation for Emails repo.
I'm getting an error when I try to run npm run build. It seems to be something I have added to my template code but I am not sure what it could be.
Here is the error:
[13:48:22] Using gulpfile ~/Development/Work/foundation-email-stack-sass-workflow/gulpfile.babel.js
[13:48:22] Starting 'default'...
[13:48:22] Starting 'build'...
[13:48:22] Starting 'clean'...
[13:48:22] Finished 'clean' after 11 ms
[13:48:22] Starting 'pages'...
[13:48:23] Finished 'pages' after 525 ms
[13:48:23] Starting 'sass'...
[13:48:35] Finished 'sass' after 12 s
[13:48:35] Starting 'images'...
[13:48:39] gulp-imagemin: Minified 27 images (saved 46.34 kB - 1.1%)
[13:48:39] Finished 'images' after 4.04 s
[13:48:39] Starting 'inline'...
(node:35425) [DEP0097] DeprecationWarning: Using a domain property in MakeCallback is deprecated. Use the async_context variant of MakeCallback or the AsyncResource class instead.
[13:48:41] The following tasks did not complete: default, build, inline
[13:48:41] Did you forget to signal async completion?
Here is my gulpfile:
import gulp from 'gulp';
import plugins from 'gulp-load-plugins';
import browser from 'browser-sync';
import rimraf from 'rimraf';
import panini from 'panini';
import yargs from 'yargs';
import lazypipe from 'lazypipe';
import inky from 'inky';
import fs from 'fs';
import siphon from 'siphon-media-query';
import path from 'path';
import merge from 'merge-stream';
import beep from 'beepbeep';
import colors from 'colors';
var helpers = require('handlebars-helpers')();
var ext_replace = require('gulp-ext-replace');
const $ = plugins();
// Look for the --production flag
const PRODUCTION = !!(yargs.argv.production);
const EMAIL = yargs.argv.to;
// Declar var so that both AWS and Litmus task can use it.
var CONFIG;
// Build the "dist" folder by running all of the below tasks
gulp.task('build',
gulp.series(clean, pages, sass, images, inline));
// Build emails, run the server, and watch for file changes
gulp.task('default',
gulp.series('build', server, watch));
// Build emails, then send to litmus
gulp.task('litmus',
gulp.series('build', creds, aws, litmus));
// Build emails, then send to EMAIL
gulp.task('mail',
gulp.series('build', creds, aws, mail));
// Build emails, then zip
gulp.task('zip',
gulp.series('build', zip));
// Delete the "dist" folder
// This happens every time a build starts
function clean(done) {
rimraf('dist', done);
}
// Compile layouts, pages, and partials into flat HTML files
// Then parse using Inky templates
function pages() {
return gulp.src(['src/pages/**/*.{html,hbs,handlebars}', '!src/pages/archive/**/*.{html,hbs,handlebars}'])
.pipe(panini({
root: 'src/pages',
layouts: 'src/layouts',
partials: 'src/partials',
helpers: 'src/helpers'
}))
.pipe(inky())
.pipe(ext_replace('.html'))
.pipe(gulp.dest('dist'));
}
// Reset Panini's cache of layouts and partials
function resetPages(done) {
panini.refresh();
done();
}
// Compile Sass into CSS
function sass() {
return gulp.src('src/assets/scss/**/*.scss')
.pipe($.if(!PRODUCTION, $.sourcemaps.init()))
.pipe($.sass({
includePaths: ['node_modules/foundation-emails/scss']
}).on('error', $.sass.logError))
.pipe($.if(PRODUCTION, $.uncss(
{
html: ['dist/**/*.html']
})))
.pipe($.if(!PRODUCTION, $.sourcemaps.write()))
.pipe(gulp.dest('dist/css'));
}
// Copy and compress images
function images() {
return gulp.src(['src/assets/img/**/*', '!src/assets/img/archive/**/*'])
.pipe($.imagemin())
.pipe(gulp.dest('./dist/assets/img'));
}
// Inline CSS and minify HTML
function inline() {
return gulp.src('dist/**/*.html')
.pipe($.if(PRODUCTION, inliner('dist/css/app.css')))
.pipe(gulp.dest('dist'));
}
// Start a server with LiveReload to preview the site in
function server(done) {
browser.init({
server: 'dist'
});
done();
}
// Watch for file changes
function watch() {
gulp.watch('src/pages/**/*.{html,hbs,handlebars}').on('all', gulp.series(pages, inline, browser.reload));
gulp.watch(['src/layouts/**/*', 'src/partials/**/*']).on('all', gulp.series(resetPages, pages, inline, browser.reload));
gulp.watch(['../scss/**/*.scss', 'src/assets/scss/**/*.scss']).on('all', gulp.series(resetPages, sass, pages, inline, browser.reload));
gulp.watch('src/assets/img/**/*').on('all', gulp.series(images, browser.reload));
}
// Inlines CSS into HTML, adds media query CSS into the <style> tag of the email, and compresses the HTML
function inliner(css) {
var css = fs.readFileSync(css).toString();
var mqCss = siphon(css);
var pipe = lazypipe()
.pipe($.inlineCss, {
applyStyleTags: false,
removeStyleTags: true,
preserveMediaQueries: true,
removeLinkTags: false
})
.pipe($.replace, '<!-- <style> -->', `<style>${mqCss}</style>`)
.pipe($.replace, '<link rel="stylesheet" type="text/css" href="css/app.css">', '')
.pipe($.htmlmin, {
collapseWhitespace: true,
minifyCSS: true
});
return pipe();
}
// Ensure creds for Litmus are at least there.
function creds(done) {
var configPath = './config.json';
try { CONFIG = JSON.parse(fs.readFileSync(configPath)); }
catch(e) {
beep();
console.log('[AWS]'.bold.red + ' Sorry, there was an issue locating your config.json. Please see README.md');
process.exit();
}
done();
}
// Post images to AWS S3 so they are accessible to Litmus and manual test
function aws() {
var publisher = !!CONFIG.aws ? $.awspublish.create(CONFIG.aws) : $.awspublish.create();
var headers = {
'Cache-Control': 'max-age=315360000, no-transform, public'
};
return gulp.src('./dist/assets/img/*')
// publisher will add Content-Length, Content-Type and headers specified above
// If not specified it will set x-amz-acl to public-read by default
.pipe(publisher.publish(headers))
// create a cache file to speed up consecutive uploads
//.pipe(publisher.cache())
// print upload updates to console
.pipe($.awspublish.reporter());
}
// Send email to Litmus for testing. If no AWS creds then do not replace img urls.
function litmus() {
var awsURL = !!CONFIG && !!CONFIG.aws && !!CONFIG.aws.url ? CONFIG.aws.url : false;
return gulp.src('dist/**/*.html')
.pipe($.if(!!awsURL, $.replace(/=('|")(\/?assets\/img)/g, "=$1"+ awsURL)))
.pipe($.litmus(CONFIG.litmus))
.pipe(gulp.dest('dist'));
}
// Send email to specified email for testing. If no AWS creds then do not replace img urls.
function mail() {
var awsURL = !!CONFIG && !!CONFIG.aws && !!CONFIG.aws.url ? CONFIG.aws.url : false;
if (EMAIL) {
CONFIG.mail.to = [EMAIL];
}
return gulp.src('dist/**/*.html')
.pipe($.if(!!awsURL, $.replace(/=('|")(\/?assets\/img)/g, "=$1"+ awsURL)))
.pipe($.mail(CONFIG.mail))
.pipe(gulp.dest('dist'));
}
// Copy and compress into Zip
function zip() {
var dist = 'dist';
var ext = '.html';
function getHtmlFiles(dir) {
return fs.readdirSync(dir)
.filter(function(file) {
var fileExt = path.join(dir, file);
var isHtml = path.extname(fileExt) == ext;
return fs.statSync(fileExt).isFile() && isHtml;
});
}
var htmlFiles = getHtmlFiles(dist);
var moveTasks = htmlFiles.map(function(file){
var sourcePath = path.join(dist, file);
var fileName = path.basename(sourcePath, ext);
var moveHTML = gulp.src(sourcePath)
.pipe($.rename(function (path) {
path.dirname = fileName;
return path;
}));
var moveImages = gulp.src(sourcePath)
.pipe($.htmlSrc({ selector: 'img'}))
.pipe($.rename(function (path) {
path.dirname = fileName + path.dirname.replace('dist', '');
return path;
}));
return merge(moveHTML, moveImages)
.pipe($.zip(fileName+ '.zip'))
.pipe(gulp.dest('dist'));
});
return merge(moveTasks);
}
And my package.json:
{
"name": "foundation-emails-template",
"version": "1.0.0",
"description": "Basic template for a Foundation for Emails project.",
"repository": "zurb/foundation-emails-template",
"main": "gulpfile.babel.js",
"scripts": {
"start": "gulp",
"build": "gulp --production",
"zip": "gulp zip --production",
"litmus": "gulp litmus --production",
"mail": "gulp mail --production"
},
"author": "ZURB <foundation#zurb.com>",
"license": "MIT",
"dependencies": {
"foundation-emails": "^2.2.1",
"handlebars-helpers": "^0.10.0"
},
"devDependencies": {
"babel-core": "^6.3.26",
"babel-preset-es2015": "^6.3.13",
"babel-register": "^6.7.2",
"beepbeep": "^1.2.0",
"browser-sync": "^2.11.0",
"colors": "^1.1.2",
"gulp": ">=4.0",
"gulp-awspublish": "^3.0.1",
"gulp-cli": "^1.1.0",
"gulp-ext-replace": "^0.3.0",
"gulp-html-src": "^1.0.0",
"gulp-htmlmin": "^1.1.1",
"gulp-if": "^2.0.0",
"gulp-imagemin": "^2.4.0",
"gulp-inline-css": "^3.0.0",
"gulp-litmus": "0.0.7",
"gulp-load-plugins": "^1.1.0",
"gulp-mail": "^0.1.1",
"gulp-rename": "^1.2.2",
"gulp-replace": "^0.5.4",
"gulp-sass": "^2.1.0",
"gulp-sourcemaps": "^1.6.0",
"gulp-uncss": "^1.0.1",
"gulp-zip": "^3.2.0",
"inky": "^1.3.6",
"lazypipe": "^1.0.1",
"merge-stream": "^1.0.0",
"panini": "^1.3.0",
"rimraf": "^2.3.3",
"siphon-media-query": "^1.0.0",
"yargs": "^4.1.0"
},
"babel": {
"presets": [
"es2015"
]
}
}
Suggestions?
so, I added a custom helper:
module.exports = function( content ) {
var devmode = content;
if( devmode === true ) {
return "/";
} else {
return "http:*****";
}
}
which used a value in the pages front matter to change URLs:
---
devmode: true
devmode: false
---
to insert a value into pages:
{{#remoteurl devmode}}{{/remoteurl}}
The build process did not like that I was passing an unquoted true/false value. Quoting the devmode value in front matter fixed the problem:
---
devmode: "true"
---

os.networkInterfaces is not a function

var os = require('os');
var ifaces = os.networkInterfaces();
var lib = {};
lib.networkInterfaces = function () {
return os.networkInterfaces();
};
Above code has to return networkInterfaces but it through error "os.networkInterfaces is not a function", above code is inside a node module that i have installed in my angular project
{
"name": "#braj1996/tiny",
"version": "1.0.1",
"main": "index.js",
"dependencies": {
"os":"0.1.1"
}
}
And this is the package.json file detail inside the node module
ngOnInit() {
console.log(TinyJS.networkInterfaces());
}
And this is code that i used in my component.ts file to get the output
NOTE:- The above node module is my custom node module i build it and packaged it.But i don't get it what is wrong in my packaging.

Migrate Node.js project to TypeScript from plain ES6

Is started migrating a Node.js project from plain ES6 to TypeScript.
What I did:
npm install -g typescript
npm install #types/node --save-dev
Setup tsconfig.json:
{
"compilerOptions": {
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"module": "commonjs",
"target": "es6",
"sourceMap": true,
"outDir": "dist",
"allowJs": true,
"forceConsistentCasingInFileNames": true
},
"exclude": [
"node_modules",
"dist",
"docs"
]
}
Change all file extensions from .js to .ts (except in node_modules):
find . -not \( -path node_modules -prune \) -iname "*.js" -exec bash -c 'mv "$1" "${1%.js}".ts' - '{}' \;
Running tsc now leads to a ton of errors like these:
server.ts:13:7 - error TS2451: Cannot redeclare block-scoped variable 'async'.
13 const async = require('async');
~~~~~
Or these:
bootstrap/index.ts:8:7
8 const async = require('async');
~~~~~
'async' was also declared here.
Update:
The same happens for retry and other npm packages:
const retry = require('retry');
Changing require statements to ES6 import statements mostly fixed these but having to migrate a few thousands files at once is not feasable so I need a way to stick with require for a while. Is this possible?
It's possible, but you'll still have to edit those files.
Either of those methods will be enough.
Replace const ... = require() with import ... = require():
import async = require('async');
...
Add export {} to the top of the file:
export {};
const async = require('async');
...
The reason of initial issue is that in TS different files are not modules unless they explicitly declared as modules, thus they are compiled/executed in the same global scope, and that's why tsc is reporting you that async variable can't be redeclared.
From documentation:
In TypeScript, just as in ECMAScript 2015, any file containing a top-level import or export is considered a module. Conversely, a file without any top-level import or export declarations is treated as a script whose contents are available in the global scope (and therefore to modules as well).
This is the same problem as this one.
In order to be treated as ES module, a file should contain either import or export statement, otherwise a variable is considered to be declared in global scope by TypeScript compiler (even if this is not so at runtime).
The solution is same as in linked question, to add dummy export {}. This could be done in batch with regex replacement but in case CommonJS , module.exports = ... exports are already in use, there may be a conflict between them.
The use of CommonJS require() imports results in untyped code. All major libraries already have according #types/... or built-in typings. Existing NPM packages can be matched with a regex from code base in order to install relevant #types/... packages in batch, imports like const async = require('async') can be replaced in batch with import async from 'async'. This requires esModuleInterop and allowSyntheticDefaultImports options to be set.
async is a protected keyword. When you use async/await you might skip the 'async' package. If you made ES6+ properly with ECMAScript modules (ESM) you also renamed all your files *.mjs, for example index.mjs. If you have the filename index.js it is most often assumed NOT to be ESM. You have to add types / interfaces to all your ES6 code, so depending on your case it might not be feasible to make all at once, that's why I give the example in ES2015+ ESM notation.
For TypeScript you should be able to use ESM because I guess you want more up to date notation. In order to use async at top level, the async function exist for doing that. Example code for index.mjs that include ES2015+ import from ES5/CommonJS *.js with module.exports and ESM import/export and finally dynamic import:
import { createRequireFromPath } from 'module'; // ESM import
import { fileURLToPath } from 'url';
const require = createRequireFromPath(fileURLToPath(import.meta.url));
// const untypedAsync = require('async');
class Index {
constructor() {
this._server = null;
this.host = `localhost`;
this.port = 8080;
}
set server(value) { this._server = value; }
get server() { return this._server; }
async start() {
const http = await import(`http`); // dynamic import
this.server = http.createServer(this.handleRequest);
this.server.on(`error`, (err) => {
console.error(`start error:`, err);
});
this.server.on(`clientError`, (err, socket) => {
console.error(`start clientError:`, err);
if (socket.writable) {
return socket.end(`HTTP/1.1 400 Bad Request\r\n\r\n`);
}
socket.destroy();
});
this.server.on(`connection`, (socket) => {
const arrival = new Date().toJSON();
const ip = socket.remoteAddress;
const port = socket.localPort;
console.log(`Request from IP-Address ${ip} and source port ${port} at ${arrival}`);
});
this.server.listen(this.port, this.host, () => {
console.log(`http server listening at ${this.host}:${this.port}`);
});
}
handleRequest(req, res) {
console.log(`url:`, req.url);
res.setHeader(`Content-Type`, `application/json`);
res.writeHead(200);
res.end(JSON.stringify({ url: req.url }));
}
}
export default Index; // ESM export
export const randomName = new Index(); // Usage: import { randomName } from './index.mjs';
async function main() {
const index = new Index();
const cjs = require(`./otherfile.js`); // ES5/CommonJS import
console.log(`otherfile:`, cjs);
// 'async' can be used by using: cjs.untypedAsync
await index.start();
}
main();
// in otherfile.js
const untypedAsync = require('async');
const test = {
url: "url test",
title: "title test",
};
module.exports = { test, untypedAsync }; // ES5/CommonJS export.
However, to use .mjs with typescript currently have some issues. Please look at the related typescript issues that are still open: .mjs input files and .mjs output files. You should at least transpile your .ts to .mjs to solve your problems. The scripts might look like (es6 to ts source):
// in package.json
"files": [ "dist" ],
"main": "dist/index",
"types": "dist/index.d.ts",
"scripts": {
"mjs": "tsc -d && mv dist/index.js dist/index.mjs",
"cjs": "tsc -m commonjs",
"start": "node --no-warnings --experimental-modules ./dist/index.mjs"
"build": "npm run mjs && npm run cjs"
},
"devDependencies": {
"typescript": "^3.2.2"
}
// in tsconfig.json
"compilerOptions": {
"module": "es2015",
"target": "ES2017",
"rootDir": "src",
"outDir": "dist",
"sourceMap": false,
"strict": true
}
Since you are migrating a large project to TypeScript, I would suggest using some tool like this package (https://www.npmjs.com/package/javascript-to-typescript) which could automate some of the work.
You can write a script to open each file in the project and add export {} at the top as suggested by #Styx in his answer.

How can I ignore "-!svg-react-loader!./path/to/my.svg" when testing with Jest without bundling everything with webpack

We're using svg-react-loader for some of the SVG files in our application. We're trying to setup jest to run with a babel-jest and the following .babelrc:
{
"presets": [
"es2015",
"react"
],
"plugins": [
"transform-decorators-legacy",
"transform-class-properties",
"transform-object-rest-spread"
]
}
The following test fails:
/* global it, document */
import React from 'react'
import ReactDOM from 'react-dom'
import Comp from './Icon'
it('renders without crashing', () => {
const div = document.createElement('div')
ReactDOM.render(<Comp><div /></Comp>, div)
})
With error:
Cannot find module '-!svg-react-loader!../../assets/grid.svg' from 'Icon.js'
How could I ignore imports that start with like import grid from '-!svg-react-loader!../../assets/grid.svg' in jest?
The way I solved this was by adding a jest mock for any import that contains -!svg-react-loader! at the beginning of the module.
"moduleNameMapper": {
"^-!svg-react-loader.*$": "<rootDir>/config/jest/svgImportMock.js"
}
Where svgImportMock.js is:
'use strict';
module.exports = 'div';
It's not ideal, because the file could simple not exists, but the assumption is that we see the missing module when bundling with webpack.
I resolved this by installing jest-svg-transformer, then adding this config:
{
"jest": {
"transform": {
"^.+\\.svg$": "jest-svg-transformer"
}
}
}
I was able to solve this by correctly handling static assets in Jest (https://jestjs.io/docs/en/webpack#handling-static-assets):
// package.json
{
"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)$": "<rootDir>/__mocks__/styleMock.js"
}
}
}
// __mocks__/styleMock.js
module.exports = {};
// __mocks__/fileMock.js
module.exports = 'test-file-stub';

Resources