Jest throwing ReferenceError to default exports - javascript

Jest is unable to find functions which are export default but IS able to find export const. I can go through and redefine how all of my functions are exported/imported, but I feel this is likely just a config issue but have been unable to find any solution on the docs or github issues to solve it.
Does anyone know of some jest config which can be used to resolve this?
GOOD
file:
export const MyFunction = () => {..
spec:
import { MyFunction } from "src/MyFunction";
=> ● Pass
BAD
file:
export default MyFunction = () => {..
spec:
import MyFunction from "src/MyFunction";
=> ● Test suite failed to run
ReferenceError: MyFunction is not defined
My jest.config.js:
/*
* For a detailed explanation regarding each configuration property, visit:
* https://jestjs.io/docs/en/configuration.html
*/
module.exports = {
// All imported modules in your tests should be mocked automatically
// automock: false,
// Automatically restore mock state between every test
restoreMocks: true,
// Make calling deprecated APIs throw helpful error messages
errorOnDeprecated: true,
// An array of directory names to be searched recursively up from the requiring module's location
moduleDirectories: ["node_modules", "src", "test/unit"],
// The test environment that will be used for testing
testEnvironment: "node",
// The glob patterns Jest uses to detect test files
testMatch: ["**/test/**/**/*.spec.(js|jsx|ts|tsx)"],
transformIgnorePatterns: [
"node_modules/(?!(jest-)?react-native|react-clone-referenced-element|#react-native-community|expo(nent)?|#expo(nent)?/.*|react-navigation|#react-navigation/.*|#unimodules/.*|unimodules|sentry-expo|native-base|#sentry/.*)",
],
transform: {
"\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js",
},
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
testPathIgnorePatterns: ["/node_modules/"],
reporters: ["default", "jest-junit"],
collectCoverage: true,
coverageReporters: ["lcov", "text-summary"],
coveragePathIgnorePatterns: [
"/node_modules/",
"src/img/",
"src/styles/",
"test/factories/",
"test/fixtures/",
],
// Whether to use watchman for file crawling
watchman: true,
setupFilesAfterEnv: ["#testing-library/jest-native/extend-expect"],
preset: "jest-expo",
globals: {
__DEV__: true,
THEME: true,
SEGMENT_KEY_STORE_INFO: true,
INITIAL_STATE: true,
EMPTY_MESSAGE: true,
},
};

export default MyFunction = () => {..
Change this to
export default const MyFunction = () => {..

Ok guys stupid one here, but the solution is to change the default export to:
MyFunction.js:
export default () => {..
Ie drop the name in the export default function declaration. Hope this helps someone having this issue.

Related

How to Polyfill node core modules using vite

It seems that vite does not do automatic polyfills anymore - vite 4.0.0
How do you guys go about this? I have tried multiple variations of what I could find over the internet and none of them seems to be solid.
✘ [ERROR] The injected path "/Users/marian/code/OzoneV2/app-web/node_modules/#esbuild-plugins/node-globals-polyfill/_buffer.js" cannot be marked as external
✘ [ERROR] The injected path "/Users/marian/code/OzoneV2/app-web/node_modules/#esbuild-plugins/node-globals-polyfill/_virtual-process-polyfill_.js" cannot be marked as external
Build failed with 2 errors:
error: The injected path "/Users/marian/code/OzoneV2/app-web/node_modules/#esbuild-plugins/node-globals-polyfill/_buffer.js" cannot be marked as external
error: The injected path "/Users/marian/code/OzoneV2/app-web/node_modules/#esbuild-plugins/node-globals-polyfill/_virtual-process-polyfill_.js" cannot be marked as external
my config
// yarn add --dev #esbuild-plugins/node-globals-polyfill
import { NodeGlobalsPolyfillPlugin } from "#esbuild-plugins/node-globals-polyfill";
// yarn add --dev #esbuild-plugins/node-modules-polyfill
import { NodeModulesPolyfillPlugin } from "#esbuild-plugins/node-modules-polyfill";
// You don't need to add this to deps, it's included by #esbuild-plugins/node-modules-polyfill
import rollupNodePolyFill from "rollup-plugin-node-polyfills";
export default {
resolve: {
alias: {
// This Rollup aliases are extracted from #esbuild-plugins/node-modules-polyfill,
// see https://github.com/remorses/esbuild-plugins/blob/master/node-modules-polyfill/src/polyfills.ts
// process and buffer are excluded because already managed
// by node-globals-polyfill
util: "rollup-plugin-node-polyfills/polyfills/util",
sys: "util",
events: "rollup-plugin-node-polyfills/polyfills/events",
stream: "rollup-plugin-node-polyfills/polyfills/stream",
path: "rollup-plugin-node-polyfills/polyfills/path",
querystring: "rollup-plugin-node-polyfills/polyfills/qs",
punycode: "rollup-plugin-node-polyfills/polyfills/punycode",
url: "rollup-plugin-node-polyfills/polyfills/url",
string_decoder: "rollup-plugin-node-polyfills/polyfills/string-decoder",
http: "rollup-plugin-node-polyfills/polyfills/http",
https: "rollup-plugin-node-polyfills/polyfills/http",
os: "rollup-plugin-node-polyfills/polyfills/os",
assert: "rollup-plugin-node-polyfills/polyfills/assert",
constants: "rollup-plugin-node-polyfills/polyfills/constants",
_stream_duplex: "rollup-plugin-node-polyfills/polyfills/readable-stream/duplex",
_stream_passthrough: "rollup-plugin-node-polyfills/polyfills/readable-stream/passthrough",
_stream_readable: "rollup-plugin-node-polyfills/polyfills/readable-stream/readable",
_stream_writable: "rollup-plugin-node-polyfills/polyfills/readable-stream/writable",
_stream_transform: "rollup-plugin-node-polyfills/polyfills/readable-stream/transform",
timers: "rollup-plugin-node-polyfills/polyfills/timers",
console: "rollup-plugin-node-polyfills/polyfills/console",
vm: "rollup-plugin-node-polyfills/polyfills/vm",
zlib: "rollup-plugin-node-polyfills/polyfills/zlib",
tty: "rollup-plugin-node-polyfills/polyfills/tty",
domain: "rollup-plugin-node-polyfills/polyfills/domain",
},
},
optimizeDeps: {
esbuildOptions: {
// Node.js global to browser globalThis
define: {
global: "globalThis",
},
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
process: true,
buffer: true,
}),
NodeModulesPolyfillPlugin(),
],
},
},
build: {
rollupOptions: {
plugins: [
// Enable rollup polyfills plugin
// used during production bundling
rollupNodePolyFill(),
],
},
},
};
I encountered the same issue "cannot be marked as external" when working with the bip39 package and getting error because of buffer not defined. I tried many stuffs so not sure how what I solved, but here is my configuration (working with svelteKit):
In vite.config.js:
import { sveltekit } from '#sveltejs/kit/vite';
import type { UserConfig } from 'vite';
const config: UserConfig = {
plugins: [sveltekit()],
resolve: {
alias: {
// polyfills
Buffer: 'vite-compatible-readable-buffer',
stream: 'vite-compatible-readable-stream',
util: 'rollup-plugin-node-polyfills/polyfills/util',
}
}
};
export default config;
In layout.ts:
import { Buffer as BufferPolyfill } from 'buffer'
declare var Buffer: typeof BufferPolyfill;
globalThis.Buffer = BufferPolyfill
In app.html:
<script>
/**
* this is a hack for error: global is not defined
*/
var global = global || window
</script>
I hope it helps. I'm new to svelte and I don't 100% know what I'm doing :p

Next.js Cannot use import statement outside a module in third party library

Summary
I'm using Next.js to create both API and and Frontend app. Frontend uses react. To unit testing I'm using next/jest preset and jest as an unit testing library. I'm using #tenstack/react-query to state management and when I want to test page, it throws an error. In tests where I'm using jsdom environment I add
/**
* #jest-environment jsdom
*/
in tests to API I'm using babel-jest that is default and no need anything
error that throws
/path/to/project/node_modules/#tanstack/react-query/src/QueryClientProvider.tsx:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import * as React from 'react'
^^^^^^
SyntaxError: Cannot use import statement outside a module
The error appers in test where I want to render page that uses react-query
jest.config.js
// jest.config.js
const nextJest = require('next/jest');
const createJestConfig = nextJest({
dir: './'
});
const customJestConfig = {
moduleDirectories: ['node_modules', '<rootDir>/'],
transform: {
'^.+\\.[t|j]sx?$': 'ts-jest'
}
};
module.exports = createJestConfig(customJestConfig);
.babelrc
{
"presets": ["next/babel","#babel/preset-env", "#babel/preset-typescript"],
"plugins": [
"babel-plugin-transform-typescript-metadata",
["#babel/plugin-proposal-decorators", { "legacy": true }],
"babel-plugin-parameter-decorator"
]
}
I've tried these answers but unfortunatelly it didn't help.
I solved myself an issue by mocking library #tenstack/react-query. Here is an sample code
jest.mock('#tanstack/react-query/src/QueryClientProvider', () => ({
QueryClientProvider: ({ children }) => children
}));
jest.mock('#tanstack/react-query', () => ({
QueryClient: jest.fn(),
useQueryClient: jest.fn(),
useQuery: jest.fn(),
useMutation: jest.fn().mockReturnValue({
mutate: jest.fn(),
isLoading: false
})
}));

Vue linting errors for defineEmits function

I'm having an issue with the linting for my Vue SPA. I'm using the defineEmits function from the script setup syntactic sugar (https://v3.vuejs.org/api/sfc-script-setup.html). The errors just do not make any sense, does anyone know how to fix this (without disabling these rules for the affected files, because it happens to every usage of defineEmits). The weird thing is that the defineProps function works without errors, which follows the same syntax. Can anyone help me out here?
My linter complains about these errors:
22:14 error Unexpected space between function name and paren no-spaced-func
22:27 error Unexpected whitespace between function name and paren func-call-spacing
23:3 error 'e' is defined but never used no-unused-vars
23:27 error 'value' is defined but never used no-unused-vars
Code that is generating these errors (the defineEmits is the source of all the errors:
<script lang="ts" setup>
const emit = defineEmits<{
(e: 'update:modelValue', value: string): void
}>()
defineProps<{
modelValue: string
name: string
items: string[]
}>()
const onInput = (e: Event) => {
emit('update:modelValue', (e.target as HTMLInputElement).value)
}
</script>
My linting eslintrs.js file (the imported shared rules do not modify the rules eslint is complaining about):
const path = require('path')
const prettierSharedConfig = require(path.join(__dirname, '../prettier-shared-config.json'))
module.exports = {
settings: {
'import/resolver': {
typescript: {},
node: {
extensions: ['.js', '.ts', '.vue'],
},
},
},
env: {
browser: true,
es2021: true,
'vue/setup-compiler-macros': true,
},
extends: ['plugin:vue/essential', 'airbnb-base'],
parserOptions: {
ecmaVersion: 13,
parser: '#typescript-eslint/parser',
sourceType: 'module',
},
plugins: ['vue', '#typescript-eslint'],
rules: {
...prettierSharedConfig.rules.shared,
'vue/multi-word-component-names': 'off',
'vue/no-multiple-template-root': 'off',
},
}
Update:
I did some further digging and saw this happening:
type EmitsType = {
(e: 'update:modelValue', value: string): void
}
const emit = defineEmits<EmitsType>()
With the following linting output:
23:3 error 'e' is defined but never used no-unused-vars
23:27 error 'value' is defined but never used no-unused-vars
It seems that the linter cannot properly process these types.
I had the same issue, I've found 2 solutions, it fixes this problem but I'm not pretty sure if I was doing it wrong.
Add '#typescript-eslint/recommended' to your eslintrc
plugins: [
...,
'#typescript-eslint/recommended',
],
or
Add 'func-call-spacing' rule
rules: {
...
'func-call-spacing': 'off', // Fix for 'defineEmits'
}
Here's the additional details about the no-unused-vars.
https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/no-unused-vars.md
You should use #typescript-eslint/no-unused-vars for your eslint rule. It will show the correct result.
"rules": {
"#typescript-eslint/no-unused-vars": "error",
}

Jest tests not working after moving to TypeScript

Recently I've moved a project from plain old JavaScript to TypeScript. Previously every test was running fine. Right after the change some test cases just broke and I can not understand why. I'm using Vue.js alongside vue-test-utils and jest.
jest.config.js
module.exports = {
collectCoverageFrom: [
'/src/**/*.{js,jsx,vue}',
'!**/node_modules/**',
'!**/vendor/**',
],
moduleFileExtensions: [
'ts',
'js',
'json',
'vue',
],
transform: {
'.*\\.(vue)$': 'vue-jest',
'^.+\\.js$': 'babel-jest',
'^.+\\.ts$': 'ts-jest',
},
transformIgnorePatterns: [
'<rootDir>/node_modules/(?!vuex-class-modules).+\\.js$',
],
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/src/$1',
},
setupFilesAfterEnv: [
'#testing-library/jest-dom/extend-expect',
],
};
A snippet of an example test that's failing right now, which has been working fine previously.
some.test.js
function mountStore(loggedInState) {
const store = new Vuex.Store({
modules: {
customer: {
namespaced: true,
state: {
isLoggedIn: loggedInState,
},
actions,
},
},
});
return shallowMount(Component, {
localVue,
store,
router,
stubs: { 'router-link': RouterLinkStub },
});
}
describe('Test with customer logged in at beginning', () => {
let wrapper;
beforeEach(() => {
wrapper = mountStore(true);
});
it('should redirect to home if user is logged in on init', () => {
expect(wrapper.vm.$route.name).toBe('Home');
});
});
Regarding this specific test case, the result is as following.
expect(received).toBe(expected) // Object.is equality
Expected: "Home"
Received: null
I also noticed upgrading all dependencies (including some Jest dependencies) leads to even more failing tests. So I expect that to (probably) be the reason, since I just added TypeScript support later on. However, I don't know what dependency combination would lead to a faulty behavior.
Relevant dependencies I've updated, which eventually would lead to even more failing tests.
jest
ts-jest
babel-jest
Add
preset: 'ts-jest/presets/js-with-babel',
to jest.config.js since you use ts-jest with babel-jest. Source.
Did you try adding #types/jest? And adding it in your tsconfig.json:
"types": ["#types/node", "#nuxt/types", "#types/jest", "nuxt-i18n"]
I was having a similar issue. #winwiz1's answer worked for me, but I needed to put it inside the project definition as I'm using the projects syntax. I would just leave this as a comment on #winwiz1's answer, but StackOverflow mangles the format.
projects: [
{
"displayName": "test-unit",
"preset": "ts-jest",
"testMatch": ["<rootDir>/test-unit/**/*\\.tests\\.[t|j]s"]
}
],

Systemjs-Builder - Cannot configure properly - Bundling Typescript into a package

I want to build a quick nodejs script to package a Typescript app as SystemJS modules, a lot like what Angular2 bundles look like.
I tried different configurations but I can't seem to put my finger on it, and haven't found clear enough documentation as of yet.
Note that for this "test", I am not using Gulp or Jspm at all, just systemjs-builder for the time being (and don't plan on using jspm at all either)
Here's what my "project" looks like:
---- Project's Root
-------- index.ts // export * from './modules/index' and eventually more
-------- modules
------------ index.ts // export * from './menu/index'
------------ menu
---------------- menu.component.ts // export class
---------------- menu.service.ts // export class
I want to package this under a single file, where I will have multiple SystemRegister modules that can be consumed in an app thereafter
I tried the following without success:
var Builder = require('systemjs-builder');
// optional constructor options
// sets the baseURL and loads the configuration file
var builder = new Builder('./modules');
builder.bundle('./modules/index.ts', {
/* SystemJS Configuration Here */
baseURL: './modules',
transpiler: 'typescript',
typescriptOptions: {
"module": "system",
"emitDecoratorMetadata": true,
"experimentalDecorators": true
},
defaultExtension: 'ts',
packages: {
'modules': {
defaultExtension: 'ts'
}
}
}, 'infrastructure.js')
.then(function() {
console.log('Build complete');
})
.catch(function(err) {
console.error(err);
})
First of all, the defaultExtension options doesn't seem to work at all
So when I do import {something} from 'filePath'; (without extension), it tries to load filePath, instead of filePath.ts;
Second, if I try adding the .ts extension in my imports (which I don't want to do), it complains that the code is invalid (unexpected token #, unexpected token menuItem and so forth)
Anyone have a good example or some explanations on how this is supposed to work?
Thank you
here you have an example: angular typescript skeleton
build task looks like this:
const path = require('path');
const Builder = require('jspm').Builder;
const builder = new Builder();
const packageJson = require(path.join(config.projectDir, 'package.json'));
return beginBuild()
.then(buildSFX)
.catch((err) => console.log('Build Failed', err));
function beginBuild() {
builder.reset();
return builder.loadConfig(path.join(config.projectDir, packageJson.jspm.configFile))
}
function buildSFX() {
const appName = packageJson.name;
const distFileName = `${appName}.min.js`;
const outFile = path.join(config.distDir, distFileName);
const moduleName = 'app';
const buildConfig = {
format: 'global',
minify: true,
sourceMaps: true
};
return builder.buildStatic(moduleName, outFile, buildConfig);
}
and jspm conf looks like this:
System.config({
defaultJSExtensions: true,
transpiler: "typescript",
typescriptOptions: {
"tsconfig": "src/tsconfig.json"
},
paths: {
"github:*": "vendor/jspm_packages/github/*",
"npm:*": "vendor/jspm_packages/npm/*",
"app": "src/index"
}
/// ...
}
Why do you want to bundle typescript? Bundling is a method used for optimizing the delivery of source code to the browser. The browser doesn't know typescript, it only knows javascript (unless you do on the fly transpiling).

Categories