I'm adding unit tests to a legacy php project that has a lot of older javascript classes. Specially I'm trying to write tests on a file that is located in ./public/scripts/ directory.
The Javascript looks like it's es4 or 5.
I've added npm package.json babel, mocah, and chai to the project.
I keep getting the following error when I run tests.
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '~/Development/web/OHB/dev/public/script/world' imported from ~/Development/web/OHB/dev/tests/js/world.test.js
My package.json looks like this.
{
"name": "ohb",
"version": "0.0.0",
"type": "module",
"main": "./public/script/main.js",
"description": "package management for the javascript application that configures the building configurator",
"scripts": {
"test": "npx mocha \"./tests/js/*.test.js\" --recursive --require @babel/register"
},
"devDependencies": {
"@babel/core": "^7.15.5",
"@babel/preset-env": "^7.15.6",
"@babel/register": "^7.15.3",
"chai": "^4.3.4",
"mocha": "^9.1.2"
}
}
The javascript file I'm trying to test is in /public/scripts/world.js and looks like this.
import * as THREE from "../../../build/three.module.js";
import {OHBBuilding, focuspoint} from "/script/bap/building.js";
import {OrbitControls} from "/assets/js/OrbitControls.js";
export var container;
export var camera, scene, renderer;
export var groundMaterial, barn, controls;
export var loaded3d = false;
var canexpand=true;
var builder;
export var objects = [], plane;
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2(),
SELECTED= new THREE.Vector3();
function myTestFunction() {
return {};
}
///lots of other functions below here
module.exports = { myTestFunction };
my test looks like this
import { expect } from "chai";
import { myTestFunction } from "../../public/script/world";
describe('myTestFunction - does it return an object', () => {
it('returns an empty object', () => {
const expected = {};
const actual = myTestFunction();
expect(expected).to.deep.equal(actual);
});
});
this one is a little tricky, so let me split that into two parts:
There's an message that the module cannot be found, because you haven't specified the extension. If you replace second line in your test to:
import { myTestFunction } from "../../public/script/world.js";
the module will be found. It's happening because node.js does not infer the file extension. This can be easily changed by adding an argument --es-module-specifier-resolution=node to your mocha command:
npx mocha \"./tests/js/*.test.js\" --recursive --require @babel/register --es-module-specifier-resolution=node
There's node.js documentation about it, although it's quite a long read.
After you've got your world.js file visible from the test file you'll get another error:
ReferenceError: module is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and '/root/stack-overflow/mocha-help/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
You've got two ways of dealing with that:
world.js file to the new ES module syntax:export { myTestFunction };
world.cjs and refer to that extension in the test file.There's really no difference in both, so it boils down to which option will be easier to implement.