Jest return error when using "import * as .." - jestjs

I have problems to run my test suite when I used import * as './filename.js' with Jest.
All the others imports run without problems so I don't think is a problem with babel configuration.
I use Nextjs 10(so react17), Jest, Typescript and babel-jest.
Here is my babel.config.js
{
"env": {
"development": {
"presets": ["next/babel"]
},
"production": {
"presets": ["next/babel"]
},
"test": {
"presets": [
[
"next/babel",
{
"preset-env": {
"modules": "commonjs"
}
}
]
]
}
}
}
And here an example of the test that gives the error:
import React, { FC, useEffect } from 'react'
import Head from 'next/head'
import Header from '../Header/Header'
import HeaderHome from '../HeaderHome/HeaderHome'
import Footer from '../Footer/Footer'
import styles from './Layout.module.css'
import * as settingsHelper from '../../helpers/_settingsHelper'
// .... normal react component here.
And inside the _seetingsHelper.js I call my cookieHelper like so:
import * as cookieHelper from './_cookies'
function initialise () {
// body of function here
}
error:
.../helpers/_settingsHelper.js:2
import * as cookieHelper from './_cookies'
^^^^^^
SyntaxError: Cannot use import statement outside a module
6 | import styles from './Layout.module.css'
7 |
> 8 | import * as settingsHelper from '../../helpers/_settingsHelper'
| ^
9 |
10 | // prettier-ignore
11 | interface LayoutProps {
Someone already encountered this issue?

Related

Jest test gives me "Cannot find module" when running tests, but the code compiles fine outside of tests. Whats up?

I am writing my first test for a large application using NestJS and TypeScript. I want to import an entity which imports an interface from a module in another folder. This is proving challenging.
The project has a structure like
apps
..apis
--..web-api
----..src
----..package.json
----..jest.config.js
------..app
--------..profiles
----------.._entities
------------..profile.entity.spec.ts <--- the test
------------..profile.entity.ts
libs
--app-interfaces
----src
------lib
--------profile
----------index.ts <--- the files the test is trying to import and test
----------gender.enum.ts
----------profile.interface.ts
In profile.entity.spec.ts I have:
import { ProfileEntity } from "./profile.entity";
import { GenderEnum, ProfileTypeEnum } from '../../../../../../../libs/app-interfaces/src/lib/profile';
// all that ../../ is what I have to do to get to the import and have it recognized in this .spec file
// it doesn't recognize the # symbol taking us to the root of the project
describe('Profile class', () => {
it('should make a profile with no fields', () => {
const profile = new ProfileEntity();
expect(profile).toBeTruthy();
});
});
and in profile.entity.ts:
import { Column, CreateDateColumn, DeleteDateColumn, Entity, PrimaryColumn, UpdateDateColumn } from 'typeorm';
import { GenderEnum, IProfile, ProfileTypeEnum } from '#ourProject/app-interfaces';
#Entity({ name: 'profile' })
export class ProfileEntity implements IProfile {
#PrimaryColumn({ nullable: false, unique: true })
id: string;
The profile.entity.ts file works fine when the app is compiled by Docker. However when I run my profile.entity.spec.ts file in Jest, I get:
Cannot find module '#ourProject/app-interfaces' from 'src/app/profiles/_entities/profile.entity.ts' // <--- this is a big clue
Require stack:
src/app/profiles/_entities/profile.entity.ts
src/app/profiles/_entities/profile.entity.spec.ts
1 | import { Column, CreateDateColumn, DeleteDateColumn, Entity, PrimaryColumn, UpdateDateColumn } from 'typeorm';
> 2 | import { GenderEnum, IProfile, ProfileTypeEnum } from '#ourProject/app-interfaces';
| ^
3 |
4 |
5 | #Entity({ name: 'profile' })
at Resolver.resolveModule (node_modules/jest-resolve/build/resolver.js:324:11)
at Object.<anonymous> (src/app/profiles/_entities/profile.entity.ts:2:1)
Is there some special configuration I need to use in jest.config.js to give jest testing access to files outside of the top lvl of the package.json?
here is jest.config.js
module.exports = {
displayName: 'web-api',
globals: {
'ts-jest': {
tsconfig: '<rootDir>/tsconfig.spec.json',
},
},
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/apps/web-api',
roots: ['../../'],
};
The line Cannot find module '#ourProject/app-interfaces' from 'src/app/profiles/_entities/profile.entity.ts' does not occur when the file runs normally.
Let's say your tsconfig.json alias configuration looks like this:
"paths": {
"#ourProject/*": ["./libs/*"],
}
Then you would need to add a moduleNameMapper line in jest.config.js:
{
moduleNameMapper: {
'^#ourProject/(.*)$': ['<rootDir>/libs/$1'],
},
}
I didn't have an issue with aliased imports being in a different folder, but jest didn't recognize aliases defined in tsconfig.json.

Vite with Jest: cannot find module start with alias '#'

I'm using Jest in Vite. It works until I import a module from node_module.
import { defineComponent } from 'vue'
import { useCookies } from '#vueuse/integrations/useCookies'
I got this error.
FAIL src/components/MyComponent/index.test.ts
● Test suite failed to run
Cannot find module '#vueuse/integrations/useCookies' from 'src/components/MyComponent/index.vue'
Require stack:
src/components/MyComponent/index.vue
src/components/MyComponent/index.test.ts
16 | <script lang="ts">
17 | import { defineComponent } from 'vue'
> 18 | import { useCookies } from '#vueuse/integrations/useCookies'
| ^
19 |
20 | export default defineComponent({
at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:306:11)
I guess somehow Jest cannot resolve the module starts with '#'. Maybe I should write a moduleNameMapper? I also tried to install vite-jest, but somehow my app just crash, maybe I mess up something.
Anyway, thanks for your time, and if you need more information like my jest.config.js or vite.config.ts, please let me know.
Thank you.
Use moduleNameMapper in your jest.config.js file like following:
module.exports = {
//...
moduleNameMapper: {
"^#/(.*)$": "<rootDir>/src/$1",
},
};
Also, if you are using TypeScript, you should add the following to your tsconfig.json file as well:
{
"compilerOptions": {
"paths": {
"#/*": ["./src"]
}
}
}

Adding nguniversal/express-engine to Angular proj: "Cannot find BrowserModule import in /src/app/app.module.ts"

First question
Goal
I'm trying to add SSR to my Angular project with ng add #nguniversal/express-engine --clientProject [name] (so I can dynamically prerender meta tags)
Expected Result
I expected the command to execute successfully with all the scaffolding and necessary updates to my existing files, as demonstrated in this YouTube tutorial.
Actual Result
Instead, the console says this:
Installing packages for tooling via npm.
Installed packages for tooling via npm.
Cannot find BrowserModule import in /src/app/app.module.ts
But BrowserModule is imported in app.module.ts.
What I've Tried
Reinstalling package
I've tried uninstalling the package with npm uninstall #nguniversal/express-engineand re-running the ng add above, same issue.
Other posted questions about ng adding #nguniversal/express-server don't seem to apply here, as those guys actually got as far as creating some of the scaffolding and generating the new files - no files are created for me at all, but the module does get added to my node-modules folder.
Could it be an issue with simply reading the typescript in app.module.ts? The BrowserModule import is there, and in the imports array. This is the output for npm ls typescript:
+-- #angular-devkit/build-angular#0.901.8
| `-- #angular-devkit/build-optimizer#0.901.8
| `-- typescript#3.6.5
+-- #ng-toolkit/universal#1.1.21
| +-- #ng-toolkit/_utils#1.1.51
| | `-- #schematics/angular#7.3.10
| | `-- typescript#3.2.4
| `-- #schematics/angular#0.6.8
| `-- typescript#2.7.2
`-- typescript#3.8.3
Additional Info (for David)
app.module.ts
import { BrowserModule, Meta, Title } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HeaderComponent } from './header/header.component';
import { FooterComponent } from './footer/footer.component';
import { HomeComponent } from './home/home.component';
import { FontAwesomeModule } from '#fortawesome/angular-fontawesome';
import { SoftwareComponent } from './software/software.component';
import { MediaComponent } from './media/media.component';
import { ShopComponent } from './shop/shop.component';
import { FilmDetailsComponent } from './film-details/film-details.component';
import { ShareModalComponent } from './share-modal/share-modal.component';
import { ShareModule } from 'ngx-sharebuttons';
import { ShareButtonModule } from 'ngx-sharebuttons/button';
import { ShareIconsModule } from 'ngx-sharebuttons/icons';
#NgModule({
imports: [
ShareButtonModule,
ShareIconsModule // Optional if you want the default share icons
]
})
#NgModule({
declarations: [
AppComponent,
HeaderComponent,
FooterComponent,
HomeComponent,
SoftwareComponent,
MediaComponent,
ShopComponent,
FilmDetailsComponent,
ShareModalComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FontAwesomeModule,
ShareModule,
ShareButtonModule,
ShareIconsModule
],
providers: [Meta, Title],
bootstrap: [AppComponent]
})
export class AppModule { }
main.ts
import { enableProdMode } from '#angular/core';
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
This error is caused by multiple NgModules in the app.module, as the first NgModule imports doesn't contain BrowserModule.
app would still work fine if you remove first NgModule since the modules in the imports are already imported in the second one

Cannot test jest with monaco editor - unexpected token

Running jest on the application fails with:
Details:
/home/**/node_modules/monaco-editor/esm/vs/editor/editor.api.js:5
import { EDITOR_DEFAULTS } from './common/config/editorOptions.js';
^
SyntaxError: Unexpected token {
> 1 | import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";
| ^
2 |
3 | /**
4 | * Get create function for the editor.
at ScriptTransformer._transformAndBuildScript (node_modules/#jest/transform/build/ScriptTransformer.js:537:17)
at ScriptTransformer.transform (node_modules/#jest/transform/build/ScriptTransformer.js:579:25)
at Object.<anonymous> (src/utils/editor-actions.js:1:1)
Application has installed packages for jest and babel-jest.
Babel config:
const presets = [
[
"#babel/env",
{
targets: {
edge: "17",
firefox: "60",
chrome: "67",
safari: "11.1"
},
useBuiltIns: "usage",
corejs: 3,
}
],
"#babel/preset-react"
];
const plugins = [
"#babel/plugin-proposal-object-rest-spread",
"#babel/plugin-proposal-class-properties",
"babel-plugin-styled-components"
];
module.exports = { presets, plugins };
The import statement as suggested in the docs for lazy loading modules from monaco leads to the esm folder, which jest is not familiar with.
import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";
By default, babel-jest would not transform node_modules and hence anything referencing the monaco-editor would error out. A possible solution is to include monaco-editor package into the compilation step by transformIgnorePatterns as mentioned in the docs
Add these to the jest config:
{
"transformIgnorePatterns": [
"node_modules\/(?!(monaco-editor)\/)"
]
}
PS: If you are using jest-dom, it might start complaining on not implmenting certain features from monaco-editor, you can mock it out with:
jest.mock("monaco-editor/esm/vs/editor/editor.api.js");
The only workaround that helped me in that issue (from here):
In folder __mocks__ create file react-monaco-editor.js with content:
import * as React from 'react';
export default function MonacoEditor() {
return <div />;
}
I have the same issue with Jest and Monaco and to make the tests pass I had to:
Add a moduleNameMapper for monaco-editor: #133 (comment)
Configure a setupTests.js like explained here: stackOverflow
I'm using:
"jest": "^24.9.0"
"babel-jest": "24.9",
"monaco-editor": "^0.20.0"
"react-monaco-editor": "0.33.0",
"monaco-editor-webpack-plugin": "^1.8.2",

unexpected token import when use localize-router in Angular 4 Universal app

I try to build Angular 4 app with server rendering side and language route path. All this base on Angular CLI in 1.5.0-rc1 version.
Everything work OK but I can't solve a problem with language in route.
I have two idea - one to make it like a parameter :lang in URL, but everywhere people advice me to use localize-router plugin. It look very good, but my npm run server can't start properly. In console I get an error:
/home/xxx/Projects/private/angular4-cli-seed/node_modules/localize-router/src/localize-router.config.js:1
(function (exports, require, module, __filename, __dirname) { import { Inject, OpaqueToken } from '#angular/core';
Here is my app-routing.module.ts:
import {NgModule, PLATFORM_ID, Inject, OpaqueToken} from '#angular/core';
import 'zone.js';
import 'reflect-metadata';
import { Routes, RouterModule } from '#angular/router';
import {AboutComponent} from './about/about.component';
import {HomeComponent} from './home/home.component';
import {LocalizeParser, LocalizeRouterModule, LocalizeRouterSettings, ManualParserLoader} from 'localize-router';
import {HttpClientModule, HttpClient} from '#angular/common/http';
import {TranslateService} from '#ngx-translate/core';
import { Observable } from 'rxjs/Observable';
import { Location } from '#angular/common';
const routes: Routes = [
{
path: '',
component: HomeComponent
},
{
path: 'about',
component: AboutComponent
}
];
export function localizeFactory(translate: TranslateService, location: Location, settings: LocalizeRouterSettings): LocalizeParser {
const browserLocalizeLoader = new ManualParserLoader(translate, location, settings, ['en', 'pl'], 'pl');
return browserLocalizeLoader;
}
#NgModule({
imports: [
RouterModule.forRoot(routes),
LocalizeRouterModule.forRoot(routes, {
parser: {
provide: LocalizeParser,
useFactory: (localizeFactory),
deps: [TranslateService, Location, LocalizeRouterSettings, HttpClient]
}
}),
],
exports: [RouterModule]
})
export class AppRoutingModule {
private static TranslateService: any;
}
Do you have any tips how can I solve it? I found some tips for Webpack (to use exclude list), but I want to use CLI because I don't know Webpack too well.
This problem is connected with library type - it's not a commonjs type, but ES6. More about this problem you can read here on GitHub.
To solve it you can contact the author of library what you want to use in Angular 4 Universal (with Angular CLI). They should recompile it in a proper way.
Another solution (more quick to realize) give me a #sjogren on GitHub. You can use babel.js to recompile library during a building process. To do this you should run:
npm install babel-cli --save
npm install babel-preset-env --save
npm install babel-preset-es2015 --save
and add this code in package.json:
"babel": {
"presets": [
"es2015"
]
},
Finally in package.json you should add to your scripts prestart script with code to recompile the library. In my example:
"scripts": {
"prestart": "node node_modules/babel-cli/bin/babel.js node_modules/localize-router --out-dir node_modules/localize-router --presets es2015"
"start": "......"
}
This worked fine for me, and I don't have an Unexpected Token Import error.

Resources