Jest problem with flow types of AsyncStorage class - react-native

I believe this is a setup bug, but I don't know what to do anymore, I tried a lot of stuff. We have an app setup and tests are failing with error:
src/__tests__/App.spec.tsx
● Test suite failed to run
SyntaxError: .../react-native/Libraries/Storage/AsyncStorage.js: Unexpected token, expected "," (31:19)
29 | */
30 | const AsyncStorage = {
> 31 | _getRequests: ([]: Array<any>),
| ^
32 | _getKeys: ([]: Array<string>),
33 | _immediate: (null: ?number),
34 |
at Parser.raise (node_modules/#babel/core/node_modules/babylon/lib/index.js:776:15)
at Parser.unexpected (node_modules/#babel/core/node_modules/babylon/lib/index.js:2079:16)
at Parser.expect (node_modules/#babel/core/node_modules/babylon/lib/index.js:2067:28)
at Parser.parseParenAndDistinguishExpression (node_modules/#babel/core/node_modules/babylon/lib/index.js:3283:14)
at Parser.parseExprAtom (node_modules/#babel/core/node_modules/babylon/lib/index.js:3113:21)
at Parser.parseExprSubscripts (node_modules/#babel/core/node_modules/babylon/lib/index.js:2757:21)
at Parser.parseMaybeUnary (node_modules/#babel/core/node_modules/babylon/lib/index.js:2736:21)
at Parser.parseExprOps (node_modules/#babel/core/node_modules/babylon/lib/index.js:2643:21)
at Parser.parseMaybeConditional (node_modules/#babel/core/node_modules/babylon/lib/index.js:2615:21)
at Parser.parseMaybeAssign (node_modules/#babel/core/node_modules/babylon/lib/index.js:2562:21)
This is the App.spec.tsx code:
import React from 'react';
import renderer from 'react-test-renderer';
import { App } from '../app';
it('renders correctly with defaults', () => {
const app = renderer.create(<App />).toJSON();
expect(app).toMatchSnapshot();
});
My jest.json:
{
"preset": "react-native",
"cacheDirectory": ".jest/cache",
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
"moduleFileExtensions": [
"ts",
"tsx",
"js"
],
"transform": {
"^.+\\.(js)$": "<rootDir>/node_modules/babel-jest",
"\\.(ts|tsx)$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
},
"transformIgnorePatterns": [
"node_modules/(?!(jest-)?react-native|react-navigation)"
],
"testPathIgnorePatterns": [
"\\.snap$",
"<rootDir>/node_modules/",
"<rootDir>/lib/",
"./build"
],
"globals": {
"window": true
}
}
Is there any helpful information that I can provide? Is this an issue with flow-types, babel...? My .babelrc is really simple.

Related

Jest: Must use import to load ES Module

I'm trying to configure jest/babel to do react component testing in my app. So far I'm facing some difficulties, in imports.
It throws this error:
Here is my babel.config.json:
{
"plugins": [
"#babel/plugin-proposal-class-properties",
"#babel/plugin-transform-runtime"
],
"presets": [
[
"#babel/preset-env",
{
"targets": {
"node": "current"
}
}
],
"#babel/preset-react"
]
}
I've trying adding "type": "module" in the package.json and it brings different problems upon itself. I would appreciate any help!

How to use jsx in vuepress?

Config
// ./docs/.vuepress/config.js
module.exports = {
...
chainWebpack: (config, isServer) => {
config.module
.rule("js") // Find the rule.
.use("babel-loader") // Find the loader
.tap(options =>
merge(options, {
presets: [
["#babel/preset-env"],
["#vue/babel-preset-jsx", { injectH: false }]
],
plugins: [
[
"import",
{
libraryName: "ant-design-vue",
libraryDirectory: "es",
style: "css"
}
],
"#babel/plugin-proposal-optional-chaining"
]
})
);
}
}
The config didn't work, when I ran the code I met the following error.
Error
Uncaught Error: Module parse failed: Unexpected token (87:11)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| },
| render(h) {
return <a-tree></a-tree>;
| }
| };
Could someone give me the right config?

Why does Jest throw an error on dynamic import() when calculating coverage for a Vue.js app?

I have a Vue.js application that is covered by unit tests written in Jest.
When I run Jest, my unit tests work and pass green but then Jest breaks when collecting coverage data - with the below error:
Failed to collect coverage from C:\...\router.js
ERROR: C:/.../router.js: Unexpected token (7:19)
STACK: SyntaxError: C:/.../router.js: Unexpected token (7:19)
5 | Vue.use(Router);
6 |
> 7 | const feed = () => import(/* webpackChunkName: "foo" */'~/components/pages/feed/FeedPage').then(cmp => cmp.default || cmp);
| ^
8 | const lobby = () => import(/* webpackChunkName: "foo" */'~/components/pages/lobby/LobbyPage').then(cmp => cmp.default || cmp);
9 | const home = () => import(/* webpackChunkName: "foo" */'~/components/pages/home/Home').then(cmp => cmp.default || cmp);
10 | const wip = () => import(/* webpackChunkName: "global" */'~/components/pages/wip/WorkInProgressPage').then(cmp => cmp.default || cmp);
at Parser.pp$5.raise (C:\...\tests\unit\node_modules\babylon\lib\index.js:4454:13)
at Parser.pp.unexpected (C:\...\tests\unit\node_modules\babylon\lib\index.js:1761:8)
at Parser.pp$3.parseExprAtom (C:\...\tests\unit\node_modules\babylon\lib\index.js:3627:50)
at Parser.pp$3.parseExprSubscripts (C:\...\tests\unit\node_modules\babylon\lib\index.js:3494:19)
at Parser.pp$3.parseMaybeUnary (C:\...\tests\unit\node_modules\babylon\lib\index.js:3474:19)
at Parser.pp$3.parseExprOps (C:\...\tests\unit\node_modules\babylon\lib\index.js:3404:19)
at Parser.pp$3.parseMaybeConditional (C:\...\tests\unit\node_modules\babylon\lib\index.js:3381:19)
at Parser.pp$3.parseMaybeAssign (C:\...\tests\unit\node_modules\babylon\lib\index.js:3344:19)
at Parser.pp$3.parseFunctionBody (C:\...\tests\unit\node_modules\babylon\lib\index.js:4226:22)
at Parser.pp$3.parseArrowExpression (C:\...\tests\unit\node_modules\babylon\lib\index.js:4190:8)
=============================== Coverage summary ===============================
Statements : 3.22% ( 840/26062 )
Branches : 0.67% ( 123/18349 )
Functions : 1.2% ( 96/7986 )
Lines : 5.19% ( 828/15961 )
================================================================================
Here is my Jest configuration as part of package.json.
"jest": {
"rootDir": "../",
"moduleFileExtensions": [
"js",
"vue"
],
"transform": {
"^.+\\.vue$": "<rootDir>/tests/unit/node_modules/jest-vue-preprocessor",
"^.+\\.js$": "<rootDir>/tests/unit/node_modules/babel-jest"
},
"moduleNameMapper": {
"^~/(.*)$": "<rootDir>/$1"
},
"collectCoverage": true,
"collectCoverageFrom": [
"**/*.{js,vue}",
"!**/node_modules/**"
],
"coverageReporters": [
"html",
"text-summary"
],
"coverageDirectory": "coverage",
"notify": true,
"setupTestFrameworkScriptFile": "<rootDir>/tests/setup.js"
}
As you can see, Jest complains about the use of the import() function in my router.js file. Why do I get the above error and how can I fix it?
The issue stemmed from a Babel configuration that did not support dynamic imports.
Resolved by:
Installing #babel/plugin-syntax-dynamic-import
npm i #babel/plugin-syntax-dynamic-import
Adding it to .babelrc like so:
{
...
"plugins": [
"#babel/plugin-syntax-dynamic-import",
],
...
}

Proper Jest configuration with React-native 0.56

After upgrading to react-native 0.56 I'm experiencing tons of babel reated errors on jest specs that used to run just fine.
I realize that react-native 0.56 requires babel7 and that's probably related but I don't have enough experience/understaanding in babel to figure out what I'm missing.
Some error examples:
/xxx/spec/Bootstrap.test.js:6
import thunk from 'redux-thunk';
^^^^^
SyntaxError: Unexpected identifier
at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:403:17)
another:
import { rootReducer } from '../store';
^
SyntaxError: Unexpected token {
at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:403:17)
My package.json jest config is as follows:
"jest": {
"preset": "react-native",
"collectCoverage": true,
"coverageReporters": [
"cobertura",
"lcov"
],
"coverageDirectory": "coverage",
"globals": {
"__TEST__": true
},
"moduleNameMapper": {
"styled-components": "<rootDir>/node_modules/styled-components/dist/styled-components.native.cjs.js"
},
"moduleDirectories": [
"node_modules",
"/"
],
"transformIgnorePatterns": [
"node_modules/(?!react-native|react-navigation)/"
],
"setupFiles": [
"jest-localstorage-mock",
"./node_modules/appcenter/test/AppCenterMock.js",
"./node_modules/appcenter-analytics/test/AppCenterAnalyticsMock.js",
"./node_modules/appcenter-crashes/test/AppCenterCrashesMock.js"
]
},
.babelrc is defined as follows:
{
"presets": ["react-native"],
"env": {
"development": {
"plugins": ["transform-class-properties"]
},
"test": {
"plugins": ["transform-class-properties"]
}
}
}
I also have the following devdependencies:
"#babel/core": "^7.0.0-beta.52",
"babel-core": "^7.0.0-beta.52",
"babel-eslint": "~8.2.5",
"babel-plugin-module-resolver": "^3.1.1",
"babel-plugin-transform-class-properties": "~6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.5",
"babel-preset-expo": "~4.0.0",
"babel-preset-react-native": "^5.0.1",
"babel-preset-react-native-stage-0": "^1.0.1",
"babel-preset-stage-0": "^6.24.1",
I've tried several approaches but couldn't progress much.
Besides the jest environment, the application runs fine.
Details of the workaround I did to move on, while 0.57 wasn't ready:
Basically I had to create 2 config files:
jest-acceptance.config (with the following relevant snippets)
"preset": "react-native",
"transform": {
"^.+\\.js$": "<rootDir>/custom_b7_processor.js"
},
"testRegex": "(/test/.*|(\\.|/)spec)\\.js$",
jest-unit.config (with the following relevant snippets)
"preset": "react-native",
"testRegex": "(/test/.*|(\\.|/)test)\\.js$",
That custom_b7_processor, is some sort of internal code from react-native:
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* #format
* #flow
*/
/* eslint-disable */
'use strict';
const {transformSync: babelTransformSync} = require('#babel/core');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const babelRegisterOnly = require('metro-babel-register');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const createCacheKeyFunction = require('fbjs-scripts/jest/createCacheKeyFunction');
const generate = require('#babel/generator').default;
const nodeFiles = RegExp(
[
'/local-cli/',
'/metro(?:-[^/]*)?/', // metro, metro-core, metro-source-map, metro-etc
].join('|'),
);
const nodeOptions = babelRegisterOnly.config([nodeFiles]);
babelRegisterOnly([]);
/* $FlowFixMe(site=react_native_oss) */
const transformer = require('metro/src/reactNativeTransformer');
module.exports = {
process(src /*: string */, file /*: string */) {
if (nodeFiles.test(file)) {
// node specific transforms only
return babelTransformSync(
src,
Object.assign(
{filename: file},
{sourceType: 'script', ...nodeOptions, ast: false},
),
).code;
}
const {ast} = transformer.transform({
filename: file,
localPath: file,
options: {
ast: true, // needed for open source (?) https://github.com/facebook/react-native/commit/f8d6b97140cffe8d18b2558f94570c8d1b410d5c#r28647044
dev: true,
inlineRequires: true,
platform: '',
projectRoot: '',
retainLines: true,
sourceType: 'unambiguous', // b7 required. detects module vs script mode
},
src,
plugins: [
[require('#babel/plugin-transform-block-scoping')],
// the flow strip types plugin must go BEFORE class properties!
// there'll be a test case that fails if you don't.
[require('#babel/plugin-transform-flow-strip-types')],
[
require('#babel/plugin-proposal-class-properties'),
// use `this.foo = bar` instead of `this.defineProperty('foo', ...)`
{loose: true},
],
[require('#babel/plugin-transform-computed-properties')],
[require('#babel/plugin-transform-destructuring')],
[require('#babel/plugin-transform-function-name')],
[require('#babel/plugin-transform-literals')],
[require('#babel/plugin-transform-parameters')],
[require('#babel/plugin-transform-shorthand-properties')],
[require('#babel/plugin-transform-react-jsx')],
[require('#babel/plugin-transform-regenerator')],
[require('#babel/plugin-transform-sticky-regex')],
[require('#babel/plugin-transform-unicode-regex')],
[
require('#babel/plugin-transform-modules-commonjs'),
{strict: false, allowTopLevelThis: true},
],
[require('#babel/plugin-transform-classes')],
[require('#babel/plugin-transform-arrow-functions')],
[require('#babel/plugin-transform-spread')],
[require('#babel/plugin-proposal-object-rest-spread')],
[
require('#babel/plugin-transform-template-literals'),
{loose: true}, // dont 'a'.concat('b'), just use 'a'+'b'
],
[require('#babel/plugin-transform-exponentiation-operator')],
[require('#babel/plugin-transform-object-assign')],
[require('#babel/plugin-transform-for-of'), {loose: true}],
[require('#babel/plugin-transform-react-display-name')],
[require('#babel/plugin-transform-react-jsx-source')],
],
});
return generate(
ast,
{
code: true,
comments: false,
compact: false,
filename: file,
retainLines: true,
sourceFileName: file,
sourceMaps: true,
},
src,
).code;
},
getCacheKey: createCacheKeyFunction([
__filename,
require.resolve('metro/src/reactNativeTransformer'),
require.resolve('#babel/core/package.json'),
]),
};
At my .babelrc I had to include the following:
"presets": ["./node_modules/babel-preset-react-native-b6"],
That is pointing to a fork I made of the babel preset that React-native was using at 0.56-
https://github.com/lhrolim/babel-preset-react-native.
At my package.json I had te following babel dependencies
"babel-preset-react-native": "~5.0.2",
"babel-preset-react-native-b6": "github:lhrolim/babel-preset-react-native",
The test scripts I used then:
"test": "npm run test-acc && npm run test-unit",
"test-acc": "jest --config=jest_acceptance-config.json",
"test-unit": "jest --config=jest_unit-config.json",
I believe there might be some redundancies here and there, but that's what worked for me.

Aurelia using featherjs dependency failing to properly import

How do you import featherjs using the style common in Aurelia projects. This is what I have:
in the build file aurelia.json
"dependencies": [
{
"name": "socket.io-client",
"path": "../node_modules/socket.io-client/dist/socket.io.min"
},
{
"name": "feathers",
"path": "../node_modules/feathers",
"main": "client",
"env": "dev"
},
"aurelia-binding",
In the app.js
import io from 'socket.io-client';
import feathers from 'feathers';
//import socketio from 'feathers-socketio';
export class App {
constructor() {
this.message = 'Hello World!';
console.log("startup");
const socket = io('http://localhost:3030');
const app = feathers();
// .configure(socketio(socket));
}
}
The error looks like this:
Starting 'readProjectConfiguration'...
Finished 'readProjectConfiguration'
Starting 'processMarkup'...
Starting 'processCSS'...
Starting 'configureEnvironment'...
Finished 'processCSS'
Finished 'processMarkup'
Finished 'configureEnvironment'
Starting 'buildJavaScript'...
Finished 'buildJavaScript'
Starting 'writeBundles'...
Tracing app...
{ uid: 8,
name: 'writeBundles',
branch: false,
error:
{ [Error: ENOENT: no such file or directory, open '/Users/steve/project/src/uberproto.js']
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: '/Users/steve/project/src/uberproto.js',
moduleTree: [ 'feathers/lib/feathers' ],
fileName: '/Users/steve/project/node_modules/feathers/lib/feathers.js' },
duration: [ 0, 161365129 ],
time: 1484844203606 }
Once it gets into processing the dependency it seems to be having path confusion looking for dependencies in featherjs. I'm pretty new with this stuff, so it is likely something simple, but I haven't figured out the correct way to include this dependency.
I believe what you want to install is feathers-client not feathers.
npm i -S feathers-client
aurelia.json:
{
"name": "socket.io-client",
"path": "../node_modules/socket.io-client/dist/socket.io.min"
},
{
"name": "feathers-client",
"path": "../node_modules/feathers-client/dist",
"main": "feathers"
}
app.js:
import io from 'socket.io-client';
import feathers from 'feathers-client';
export class App {
constructor() {
const socket = io('http://localhost:3030');
const app = feathers().configure(feathers.socketio(socket));
}
}
You're missing the main property. The configuration should be like this:
{
"name": "socket.io-client",
"path": "../node_modules/socket.io-client/dist",
"main": "socket.io.min"
}