Vue/Jest unit testing Cannot read property 'shallowMount' of undefined - javascript

I have been following the Vue school guides on implementing Jest with Vue in order to start writing some unit tests.
So far I've installed jest, jest-serializer-vue, vue-template-compiler.
module.exports = {
verbose: true,
roots: [
"<rootDir>/src/",
"<rootDir>/src/specs/"
],
moduleFileExtensions: ['js', 'vue'],
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/src/$1',
},
transform: {
"^.+\\.js$": "babel-jest",
"^.+\\.vue$": "vue-jest",
},
snapshotSerializers: [
"<rootDir>/node_modules/jest-serializer-vue"
]
}
When writing my first test it is building successfully.
import TestComponent from '../src/components/test';
test('mount a vue component', () => {
console.log(TestComponent);
});
But when I try mounting Vue component it starts failing with the following error:
FAIL src/specs/test.spec.js
● Test suite failed to run
TypeError: Cannot read property 'shallowMount' of undefined
The actual test file looks like this:
import TestComponent from '../src/components/test';
import { shallowMount } from '#vue/test-utils';
test('mount a vue component', () => {
const wrapper = shallowMount(TestComponent);
console.log(wrapper);
});
I don't understand why this is happening, and there is no info (at least I could not find some) as why this is failing. Can someone help me?
PS: My project is NOT using vue-cli.

Related

How to make jest ignore type which is not js keyword and used in #react-native?

I am setting up jest for React Native 0.68 with jest 29.0. Here is the my jest config in package.json:
"jest": {
"preset": "react-native",
"cacheDirectory": "./cache",
"moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"],
"coveragePathIgnorePatterns": [
"./app/utils/vendor"
],
"coverageThreshold": {
"global": {
"statements": 80
}},
"transformIgnorePatterns": [
"node_modules/(?!#react-native|react-native)",
"node_modules/(?!#react-native/polyfills/)",
"node_modules/(?!(jest-)?#react-navigation|#react-native-community|#react-navigation-redux-helpers)",
"node_modules/(?!(jest-runtime))"
]
}
There is only one simple test case for the project. Here is the test case:
/**
* #format
*/
import 'react-native';
import React from 'react';
import App from '../App';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
it('renders correctly', () => {
renderer.create(<App />);
});
However yarn jest throws error below:
/Users/macair/Documents/code/js/xyz_app6/node_modules/#react-native/polyfills/error-guard.js:14
type ErrorHandler = (error: mixed, isFatal: boolean) => void;
^^^^^^^^^^^^
SyntaxError: Unexpected identifier
This is a common error but the solutions posted didn't work in my case. I think the problem is type which is not a javascript keyword but a Flow definition. The type is used in #react-native/polyfills/error-guard.js and #react-native is being ignored in jest config. However somehow ignore of #react-native does not work here.

How to configure Relay.JS in Vite?

I'm trying to migrate my React project from CRA to Vite, this is my vite.config.js:
import { defineConfig } from 'vite'
import react from '#vitejs/plugin-react'
import envCompatible from 'vite-plugin-env-compatible'
import relay from "vite-plugin-relay"
import macrosPlugin from "vite-plugin-babel-macros"
import path from 'path';
import fs from 'fs/promises';
export default defineConfig({
resolve: {
alias: {
'~': path.resolve(__dirname, 'src'),
'#material-ui/core': path.resolve(__dirname, 'node_modules/#material-ui/core')
}
},
esbuild: {
loader: "tsx",
include: /src\/.*\.[tj]sx?$/,
exclude: [],
},
optimizeDeps: {
esbuildOptions: {
plugins: [
{
name: "load-js-files-as-jsx",
setup(build) {
build.onLoad({ filter: /src\/.*\.js$/ }, async (args) => ({
loader: "tsx",
contents: await fs.readFile(args.path, "utf8"),
}));
},
},
],
},
},
define: {
global: {},
},
plugins: [
envCompatible(),
react(),
relay,
//macrosPlugin(),
],
})
My GraphQL query files are like this:
import graphql from 'babel-plugin-relay/macro'
const getQuery = () => graphql`
query UserQuery($id: ID!) {
user(id: $id) {
id
fullName
}
}
`
export default getQuery
When I tried to run the project in dev mode (command $ vite), I got this error:
So I did some search and replaced vite-plugin-relay to vite-plugin-babel-macros like this:
// others import
import relay from "vite-plugin-relay"
import macrosPlugin from "vite-plugin-babel-macros"
export default defineConfig({
// configs like bellow
plugins: [
envCompatible(),
react(),
//relay,
macrosPlugin(),
],
})
So I started to get a new error:
How can I configure Relay to work on Vite.JS?
Might be a bit late, but the issue has been fixed in Relay#13 and you can find some workarounds in this thread for older versions of Relay :
https://github.com/facebook/relay/issues/3354
You can also try adding the option eagerEsModules: true to your relay babel plugin configuration.
Unless you have some specific usecase that requires the use of babel-plugin-relay, your issue should be resolved if you change your imports from
import graphql from 'babel-plugin-relay/macro'
to
import { graphql } from "react-relay";
You should only need the relay vite plugin at that point, and can remove vite-plugin-babel-macros
There's a few things wrong with your setup.
1. Don't use vite-plugin-babel-macros:
Use #vitejs/plugin-react instead.
import { defineConfig } from "vite";
import react from "#vitejs/plugin-react";
import relay from "vite-plugin-relay";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [relay, react({
babel: {
plugins: ['babel-plugin-macros']
},
})],
});
You can probably get it to work with vite-plugin-babel-macros, but the later is an official plugin.
2. Don't use 'babel-plugin-relay/macro':
Use the following instead:
import { graphql } from "react-relay";
It's unclear to me why the official docs suggest using babel-plugin-relay/macro, but that just doesn't work.
3. Configure relay.config.js correctly:
{
"src": "./src",
"language": "typescript",
// Change this to the location of your graphql schema
"schema": "./src/graphql/schema.graphql",
"exclude": [
"**/node_modules/**",
"**/__mocks__/**",
"**/__generated__/**"
],
"eagerEsModules": true
}
In particular, make sure you use language: typescript and eagerEsModules.
4. Sample repository
I wrote a sample repository showing how to properly configure React Relay with Vite.js and TypeScript, you can find it here.

React Native - Jest - Enzyme throws an Jest cannot parse Error

i'm facing an error when i want to add Jest and Enzyme as a testing library to my React Native project. This is my codes :
//Button.spec.js
import React from 'react';
import { View } from 'react-native';
import { shallow } from 'enzyme';
const Test = () => <View />;
describe('SomeComponent component', () => {
it('Shallow rendering', () => {
const wrapper = shallow(<Test />);
});
});
//jest/setup.js
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
//babel.config.js
module.exports = () => ({
presets: ['module:metro-react-native-babel-preset'],
plugins: ['transform-flow-strip-types']
});
//jest.config.json
{
"preset": "react-native",
"collectCoverage": true,
"moduleDirectories": [
"node_modules",
"src"
],
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
},
"setupFiles": [
"<rootDir>/jest/setup.js"
],
"transformIgnorePatterns": [
"/node_modules/(?!react-native|).+\\.js$"
],
"coveragePathIgnorePatterns": [
"/node_modules/",
"/jest"
]
}
When I run npm test. It will throws an error like this :
/src/components/common/__test__/Button.spec.js: Unexpected token (5:19)
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
Details:
3 | import { shallow } from 'enzyme';
4 |
> 5 | const Test = () => <View />;
| ^
6 |
7 | describe('SomeComponent component', () => {
8 | it('Shallow rendering', () => {
Do you guys have any suggestions to fix this? Should I add any library I used inside node_modules to transformIgnorePatterns? Or is there any missing step to setup?

Svelte Component Testing with Jest, Unable to load Svelte files recursively

I am working on a Svelte Project with Typescript and want to use Jest to test UI components using the #testing-library/svelte module . I am not able to properly import all my svelte files like my sub-components and Jest just hangs trying to load the application.
There are some typescript errors in the svelte components and by these errors printing, I can see which files actually loaded. After loading App.svelte, the program just freezes and doesn't load any of the submodules.
I am not exactly sure where the error is, because before this error I was getting an import error similar to jest: Test suite failed to run, SyntaxError: Unexpected token import, I "solved" this by adding the configuration to the .babelrc file and adding the preprocessor.
All the relevant files are below and are also on Github here
The actual test case file, there is a data-testid element called dropzone in dropzone.svelte
// app.spec.js
import App from "../src/App.svelte";
import { render, fireEvent } from "#testing-library/svelte";
describe("UI Load Test", () => {
it("Check Dropzone Loaded", () => {
const { getByText, getByTestId } = render(App);
const dropzone = getByTestId("dropzone");
expect(dropzone).toBeDefined();
});
});
// App.svelte
<script lang="ts">
...
// Static Svelte Components
import HeaderContent from "./components/header.svelte";
import Loader from "./components/loader.svelte";
import Footer from "./components/footer.svelte";
// Dynamic Svelte Modules
import Terminal from "./modules/terminal/terminal.svelte";
import Dropzone from "./modules/dropzone/dropzone.svelte";
import Configure from "./modules/configure/configure.svelte";
import Video from "./modules/video/video.svelte";
import Progress from "./modules/progress/progress.svelte";
let loaded = $loadedStore;
...
let fileState = $fileUploaded;
...
let processedState = $processed;
...
let progressState = $progressStore;
...
let configState = $showConfig;
...
</script>
...
// jest.config.js
const {
preprocess: makeTsPreprocess,
createEnv,
readConfigFile,
} = require("#pyoner/svelte-ts-preprocess");
const env = createEnv();
const compilerOptions = readConfigFile(env);
const preprocessOptions = {
env,
compilerOptions: {
...compilerOptions,
allowNonTsExtensions: true,
},
};
const preprocess = makeTsPreprocess(preprocessOptions);
module.exports = {
transform: {
"^.+\\.svelte$": [
"jest-transform-svelte",
{ preprocess: preprocess, debug: true },
],
"^.+\\.ts$": "ts-jest",
"^.+\\.js$": "babel-jest",
},
moduleDirectories: ["node_modules", "src"],
testPathIgnorePatterns: ["node_modules"],
bail: false,
verbose: true,
transformIgnorePatterns: ["node_modules"],
moduleFileExtensions: ["js", "svelte", "ts"],
setupFilesAfterEnv: [
"./jest.setup.js",
"#testing-library/jest-dom/extend-expect",
],
};
// babel.config.js
module.exports = {
presets: [
[
"#babel/preset-env",
{
targets: {
node: "current",
},
},
],
],
};
//.babelrc
{
"plugins": [
"#babel/plugin-syntax-dynamic-import"
],
"env": {
"test": {
"plugins": ["dynamic-import-node"]
}
}
}
You have not imported these variables yet from your store.ts file "$loadedStore, $fileUploaded, $processed, $progressStore, $showConfig"
Basically, you can put this on a store.ts like this.
// store.ts
export const loadedStore= writable([]) // for arrays
export const fileUploaded= writable({}) // for objects
export const processed = writable("") // for strings
export const progressStore = writable("")
export const showConfig= writable({})
Then add this line on top of your App.svelte file
// App.svelte
import { loadedStore, fileUploaded, processed, progressStore, showConfig } from 'store.ts'

Babel React transform : Property value expected type of string but got null

I have an application that is working great client side (transpiled and compiled with Webpack/Babel).
I'm trying to render this app server side with Node, but I'm getting this error :
TypeError: C:/[PROJECT_PATH]/src/_base/common/components/general/AComponent.js: Property value expected type of string but got null
at Object.validate (C:\[PROJECT_PATH]\node_modules\babel-types\lib\definitions\index.js:153:13)
at validate (C:\[PROJECT_PATH]\node_modules\babel-types\lib\index.js:269:9)
at Object.builder (C:\[PROJECT_PATH]\node_modules\babel-types\lib\index.js:222:7)
at File.<anonymous> (C:\[PROJECT_PATH]\node_modules\babel-core\lib\transformation\file\index.js:329:56)
at File.addImport (C:\[PROJECT_PATH]\node_modules\babel-core\lib\transformation\file\index.js:336:8)
at C:\[PROJECT_PATH]\node_modules\babel-plugin-react-transform\lib\index.js:257:46
at Array.map (native)
at ReactTransformBuilder.initTransformers (C:\[PROJECT_PATH]\node_modules\babel-plugin-react-transform\lib\index.js:255:40)
at ReactTransformBuilder.build (C:\[PROJECT_PATH]\node_modules\babel-plugin-react-transform\lib\index.js:164:41)
at PluginPass.Program (C:\[PROJECT_PATH]\node_modules\babel-plugin-react-transform\lib\index.js:331:17)
It happens on any component imported.
I know the components themselves work because they do in client mode.
Here is my index.js (same babel config as in client side app) :
require('babel-register')({
presets:["es2015", "stage-0",'react'],
highlightCode: false,
sourceMaps: "both",
env: {
development: {
plugins: [
'transform-decorators-legacy',
["react-transform", {
transforms: [{
imports: ['react'],
locals: ['module']
}]
}]
]
}
}
});
require('./renderer.js');
Here is my renderer.js :
import React, { Component } from 'react'
import Router, {match, RoutingContext } from 'react-router'
// this works :
import AnyActions from 'path/to/actions/AnyActions'
// this don't
import AnyComponent from 'path/to/any/component'
Everything else is commented out !
I tried to import this simple AComponent :
import React, { Component, PropTypes } from 'react'
export default class AComponent extends Component {
render () { return (<p>Hello</p>)}
}
Same error !
I must miss something obvious ... but I don't see it !
Problem was with my Babel's React-Transform incorrect configuration : I was specifiying import and locals without any transform name ...
Removing this part solved my problem.
Here is my new index.js :
require('babel-register')({
presets:["es2015", "stage-0",'react'],
highlightCode: false,
sourceMaps: "both",
env: {
development: {
plugins: [
'transform-decorators-legacy'
]
}
}
});
require('./renderer.js');

Categories

Resources