In my Angular/Typescript/Webpack project, I was rewriting unit tests after code modifications.
The symptom of the issue was an error when running a very basic component test: "Error: Unexpected value 'undefined' declared by the module 'DynamicTestModule'"
In order to debug the issue, I wound up stripping out all dependencies from the constructor of the component and essentially all code. The component did nothing and yet I still got the error. It couldn't be a circular dependency because there were no dependencies.
The folder files were:
--profile
----profile.component.ts
----profile.component.spec.ts
----profile.component.html
----index.ts (barrel)
The component (with most meaningful code removed in order to figure out problem) is:
import { Component } from '#angular/core';
#Component({
selector: 'profile',
template: `<h1></h1>`
})
export class ProfileComponent {
title = 'Test Tour of Heroes';
constructor(){}
}
And the spec is:
import { NO_ERRORS_SCHEMA, DebugElement } from '#angular/core';
import { ComponentFixture, TestBed }
from '#angular/core/testing';
import { ProfileComponent } from './profile.component';
console.log(ProfileComponent);
fdescribe('Component: Jasmine Spy Test', () => {
console.log(ProfileComponent);
let fixture: ComponentFixture<ProfileComponent>;
let component: ProfileComponent;
let fixture2: ComponentFixture<ProfileComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ProfileComponent]
}).compileComponents();
fixture = TestBed.createComponent(ProfileComponent);
component = fixture.componentInstance;
});
it(`should create instance of objects`, () => {
expect(1).toBe(1);
});
});
Versions:
"#angular/core": "^4.0.0",
"karma": "~1.4.1"
"webpack": "^2.3.3"
There are lots of other packages but I don't think that was the issue.
I was using VisualCode 1.14.0 (1.14.0).
The Real Issue VisualCode identified that ProfileComponent was in ./profile.component but the console.log lines printing that out said 'undefined' and no compile/transpile error was thrown.
Notice that there is a separate .html file in the folder but the code doesn't reference it.
ProfileComponent began to have value (no longer undefined) when I renamed the profile.component.html file -- must have been something about the webpack build.
I don't know what is wrong with this particular set of files because there any many folders with this exact same naming convention/setup in this project that do run the tests correctly.
I'm leaving this here in case someone runs across this error.
I also faced this issue. The component I was testing was not declared in any module. I had commented out the code in the module, after removing the comments, the error was fixed.
Related
I encountered the module resolving issue in my testcafe(1.17.1) test.
I have a test
//test.e2e.ts in <root>/tests folder
import {MyComponent} from '../src/MyComponent';
...
...
fixture('Custom domain tests');
test('test 1', async () => {
...
...
});
the <root>/src/MyComponent.tsx looks like this
//MyComponent.tsx in <root>/src folder
import React, { FunctionComponent } from 'react';
import styles from '../scss/MyComponent.module.scss';
export const MyComponent: FunctionComponent = () => {
...
...
}
When I run testcafe ./tests/test.e2e.ts, I always got the error
Error: TypeScript compilation failed. Cannot find module '../scss/MyComponent.module.scss' or its corresponding type declarations.
My testcafe tsconfig specified the path config, the <root>/scss-module-for-tests.ts just exports a empty string
// .testcaferc.json in <root>/
{
"compilerOptions": {
"typescript": {
"options": {
"esModuleInterop": true,
"baseUrl": ".",
"paths": {
"../scss/MyComponent.module.scss": ["scss-module-for-tests.ts"],
"*.scss": ["scss-module-for-tests.ts"]
}
}
}
}
}
However, seems typescript path config doesn't resolve relative path nor accept a regex, but My project has a lot of those ../scss/*module.scss imports. Is there anyway to resolve the scss file directly for testcafe?
Thanks in advance!
Update on 12/02/2021
I tried add compiler for testcafe according to this doc , I put a .testcaferc.json at the root folder
//.testcaferc.json at <root>
{
"compilerOptions": {
"typescript": {
"options": {
"esModuleInterop": "true"
}
}
}
}
But seems the esModuleInterop=true config didn't reach to testcafe.
Update 12/13/2021:
Not easy to configure it correctly, I removed the *.scss file reference in the test code. Problem solved.
It looks like your TestCafe tests' code references your testing application code. However, TestCafe tests do not require testing application code. In fact, the code of the TestCafe tests and the application can be divided into two separate projects. Please try to separate your web application code and your TestCafe tests' code.
One of my Cypress tests fails to run when it tries to import from a file in the source code of a create-react-app src directory.
The test looks like:
// cypress/integration/this-fails.js
import { MY_CONSTANT } from '../../src/constants';
describe('Cypress', () => {
...
})
The imported source file looks like:
// src/constants.ts
export const MY_CONSTANT = 'foo';
The Cypress test failure is caused by a Jest test file in the source directory:
ERROR in /my-app/src/App.test.tsx(5,1)
Cannot find name 'test'. Do you need to install type definitions for a test runner? Try`npm i #types/jest`or`npm i #types/mocha`.
The Jest type definitions are installed. Additionally, to no avail, I have tried to exclude the problematic Jest test in the Cypress tsconfig.
// cypress/tsconfig.json
{
...
"exclude": [
"../src/App.test.tsx"
],
...
}
Here is a minimal repo that reproduces my problem.
Lastly, to clarify why I am importing things into Cypress tests from the source directory — the imported variable is intended to be a DOM selector or a function that returns a DOM selector so that selectors are not hardcoded in the tests.
I'm not sure why the message is TypeScript emitted no output for /my-app/src/constants.ts, this seems to indicate that the file is readable and typescript attempts to parse it, and does not recognize the syntax.
However my guess is that the code of the test is running in a browser process and can't access files outside of it's folder.
If constant.ts is in cypress/fixtures it works, so one easy way is to add a script to copy the file. A script called "precypress" will be automatically run when the "cypress" script is invoked.
This is kind of 90% there - you don't get hot-module reload when constants.ts changes.
package.json
"scripts": {
...
"precypress": "copyfiles ./src/constants.ts ./cypress/fixtures",
"cypress": "cypress open"
},
It also works with functions and handles typing,
test
import { MY_CONSTANT, getMyConstant } from '../fixtures/src/constants';
describe('Cypress', () => {
it('is working', () => {
cy.visit('/')
alert(MY_CONSTANT);
alert(getMyConstant());
expect(true).to.equal(true)
})
})
constant.ts
export const MY_CONSTANT: Number = 10;
export const getMyConstant: Function = () => 20;
While updating some deps (react-bootstrap) I ran into a react error
You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Compiling the same code with other setups (storybook, create react app, codesandbox, ...) doesn't show the issue.
Looks like the component we import (react-bootstrap/Dropdown), imports another component (react-overlays/Dropdown) which causes the problem.
I tracked the error down to this line which does NOT get outputted:
/* harmony import */ var react_overlays_Dropdown__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(react_overlays_Dropdown__WEBPACK_IMPORTED_MODULE_4__);
Instead, the non-working code uses the ..._MODULE_4__['default'] syntax, which fails and raises the error.
After hours of searches I found out the problem...
Changing this
module.exports = {
resolve: {
modules: [path.join(__dirname, 'node_modules')]
}
};
to this
module.exports = {
resolve: {
modules: ['node_modules']
}
};
solves the problem.
I am getting a webpack TypeError when I am trying to simplify an import. The following code works without any issues. Here I am importing a React Higher-Order-Component (HOC) called smartForm from core/components/form/index.js.
core/components/form/index.js (does a named export of smartForm)
export smartForm from './smart-form';
login-form.jsx (imports and uses smartForm)
import { smartForm } from 'core/components/form';
class LoginForm extends React.Component {
...
}
export default smartForm(LoginForm);
However, I want to simplify the import to just import { smartForm } from 'core'. So I re-exported smart-form in core/index.js and imported it from core. See the code below:
core/index.js (does a named export of smartForm)
export { smartForm } from './components/form';
// export smartForm from './components/form'; <--- Also tried this
login-form.jsx (imports and uses smartForm)
import { smartForm } from 'core';
class LoginForm extends React.Component {
...
}
export default smartForm(LoginForm); // <--- Runtime exception here
This code compiles without any issues, but I am getting the following runtime exception at the line export default smartForm(LoginForm);:
login-form.jsx:83 Uncaught TypeError: webpack_require.i(...) is not a function(…)
What am I missing?
P.S. Here are the Bable and plugin versions that I am using:
"babel-core": "^6.18.2",
"babel-preset-es2015-webpack": "^6.4.3",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-1": "^6.16.0",
tl;dr
For the questioner: Add this to your webpack.config.js:
resolve: {
alias: {
core: path.join(__dirname, 'core'),
},
},
For the general audience: Make sure the thing you try to import is indeed exists in that package.
Explanation
Questioner's problem: importing own code like npm modules
You try to import your module's exports in the same fashion how you import something from an npm package from the node_modules folder: import { something } from 'packagename';. The problem with this is that doesn't work out of the box. The Node.js docs give the answer on why:
Without a leading '/', './', or '../' to indicate a file, the module must either be a core module or is loaded from a node_modules folder.
So you either has to do what Waldo Jeffers and Spain Train suggested and write import { smartForm } from './core', or you can configure webpack so it can resolve your import path via its aliases which are created to solve this exact problem.
Debugging the error message in general
This error can arise if you try to import something from an existing npm package (in node_modules) but the imported thing doesn't exist in the exports. In this case, make sure there were no typos and that the given thing you try to import is indeed in that package. Nowadays it is trendy to break libraries into multiple npm packages, you might be trying to import from a wrong package.
So if you get something like this:
TypeError: __webpack_require__.i(...) is not a function
at /home/user/code/test/index.js:165080:81
at Layer.handle [as handle_request] (/home/user/code/test/index.js:49645:5)
To get more information on what import you should check, just open the output file generated by webpack and go to the line marked by the topmost line in the error stack (165080 in this case). You should see something like: __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_9_react_router_dom__["match"]). This tells us that there is no match export (or there is but it isn't a function) in react-router-dom, so we need to check our stuff around that import.
Since core is a folder of your app and not an npm module, Webpack can not understand which file you want to load. You must use a correct path pointing to a file. You have to replace import { smartForm } from 'core'; by import { smartForm } from './core/index.js
This error will occur by many reasons. Once I encountered this error when I add js in file-loader then when I removed it start to work correctly.
{
test: /\.(ttf|eot|svg|gif|jpg|png|js)(\?[\s\S]+)?$/,
use: 'file-loader'
},
When I remove |js it works
{
test: /\.(ttf|eot|svg|gif|jpg|png)(\?[\s\S]+)?$/,
use: 'file-loader'
},
Just remove these 2 line from config
const context = resolve.alias.context('./', true, /\.spec\.ts$/); context.keys().map(context);
I am making an exercise with ES2015, Jest, React and I get this error:
TypeError: Property description must be an object: undefined
at defineProperties (native)
at Object.eval (<PROJECT>/node_modules/event-emitter/index.js:127:8)
After digging into it, I think it is related to the import of the nodeModule EventEmitter or by extending the class by it.
This is the code of the script file:
import EventEmitter from 'event-emitter';
import AppDispatcher from '../dispatcher/app-dispatcher';
import {
ACTION_CURSOR_POSITION_CHANGED,
ACTION_IS_DRAGGING_CHANGED
} from '../constants/actions';
let _draggingStoreInstance = null;
/**
* DraggingStore class
*/
export default class DraggingStore extends EventEmitter
{
/**
* Constructor
*/
constructor () {
// ...
The source code of the test file looks like this:
import '../unmock/dragging-store.unmock.js';
import DraggingStore from '../../src/stores/dragging-store';
describe('Dragging Store', () => {
let draggingStoreInstance = null;
beforeEach(() => {
draggingStoreInstance = DraggingStore.getInstance();
});
it('should be defined', () => {
expect(DraggingStore).toBeDefined();
expect(draggingStoreInstance).toBeDefined();
});
});
I made an extra file for excluding mocks:
jest.dontMock('../../src/stores/dragging-store.js');
jest.dontMock('../../src/dispatcher/app-dispatcher.js');
jest.dontMock('../../src/constants/actions.js');
The code itself runs smoothly in the browser after compiling, but the test engine gives the error.
I added this in my package.json:
"scripts": {
"test": "jest"
},
"jest": {
"scriptPreprocessor": "./node_modules/babel-jest",
"unmockedModulePathPatterns": [
"./node_modules/react"
],
"collectCoverage": true,
"testDirectoryName": "spec",
"moduleFileExtensions": [
"js"
],
"collectCoverageOnlyFrom": {
// All files to test
}
}
Does anyone have a clue how to get around the problem?
Thanks in advance...
Update: full source code can be found here: https://github.com/dejakob/unlease-chess
I realize this is very late, but, a lot has changed in the time you have posted this question. With Jest v19+, and assuming you are using the latest version of Babel as well, you can follow the instructions here:
http://facebook.github.io/jest/docs/webpack.html#using-with-webpack-2
since you are using modules, you will need to tell Babel to transpile them to commonjs requires so that they can be run in the node environment, which is how Jest works.