Expo-Constants failing Jest since swap to app.config.json - react-native

As stated in the title, I've recently switched our project from app.json to app.config.json ready for EAS builds in Expo. Since then, my simple App.test.js has been failing
TypeError: Cannot read property 'environment' of undefined
const enableInExpoDevelopment = Constants.manifest.extra.environment !== 'Development'
This is the App.test.js
import React from 'react';
import renderer from 'react-test-renderer';
import App from '../App';
describe('<App />', () => {
it('has 1 child', () => {
const tree = renderer.create(<App />).toJSON();
expect(tree.children.length).toBe(1);
});
});
And this is the current jest.config.js
module.exports = {
preset: 'jest-expo',
transform: {
'^.+\\.js$': require.resolve('react-native/jest/preprocessor.js')
},
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/.*)'
],
reporters: [
'default'
],
setupFiles: [
'./__mocks__/#react-native-async-storage/async-storage.js'
]
}

Related

Load SVGs components in storybook VUE not working

Hello everyone I'm using vue 3 with storybook 6.5.16 and when i import the SVGs as a component using svg-inline-loader i get the following error in storybook app:
enter image description here
(Failed to execute 'createElement' on 'Document' svg is not a valid name)
Storybook main.js
const path = require('path');
module.exports = {
stories: [
'../src/**/*.stories.mdx',
'../src/**/*.stories.#(js|jsx|ts|tsx)',
],
addons: [
'#storybook/addon-links',
'#storybook/addon-essentials',
'#storybook/addon-interactions',
],
framework: '#storybook/vue3',
core: {
builder: '#storybook/builder-webpack5',
},
webpackFinal: async (config, { configType }) => {
// `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
config.module.rules.push({
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
{
loader: "sass-loader",
options: {
additionalData: `
#import "#/assets/scss/main.scss";
`,
implementation: require('sass'),
},
},
],
});
(() => {
const ruleSVG = config.module.rules.find(rule => {
if (rule.test) {
const test = rule.test.toString();
const regular = /\.(svg|ico|jpg|jpeg|png|apng|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/;
const regularString = regular.toString();
if (test === regularString) {
return rule;
}
}
});
ruleSVG.test = /\.(ico|jpg|jpeg|png|apng|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/;
})();
config.module.rules.push({
test: /\.svg$/,
use: ['svg-inline-loader'],
});
config.resolve.alias['#'] = path.resolve('src');
return config;
},
}
package.json file
enter image description here
SVG Vue components
<template>
<div
ref="icon"
class="v-icon"
#click="onClick"
>
<component
:is="iconName"
class="v-icon__svg"
/>
</div>
</template>
<script>
import Cards from '#/assets/icons/Cards.svg';
export default {
name: 'VIcon',
components: {
Cards,
},
props: {
iconName: {
type: String,
required: true,
},
},
};
</script>
.babelrc file
{
"presets": ["#babel/preset-env", "#babel/preset-react"]
}
i tried to use vue-svg-loader to replace svg-inline-loader but it didn't work and I got another error while building the app
ModuleBuildError: Module build failed: Error: Cannot find module './Block'
I also tried to use babel-loader in conjunction with vue-svg-loader but unfortunately I also got an error:
enter image description here
has anyone come across this or can you show your use cases of using SVGs components in Storybook and Vue 3?

Vuetify icons gives an error with storybook

Hello everyone I'm facing an issue When I use the storybook with vuetify framework and when I run the project it gives the following error multiple times.
Cannot read properties of undefined (reading 'component')
TypeError: Cannot read properties of undefined (reading 'component')
at remapInternalIcon (http://localhost:6006/vendors~main.f3adcb00877b75c26c76.bundle.js:267378:37)
at VueComponent.getIcon
and here is I'm using storybook v6.1.11 npm packages
"#storybook/addon-essentials": "^6.5.16",
"#storybook/addon-actions": "^6.1.11",
"#storybook/addon-controls": "^6.5.16",
"#storybook/addon-docs": "^6.1.11",
"#storybook/addon-links": "^6.1.11",
"#storybook/addons": "^6.1.11",
"#storybook/preset-scss": "^1.0.3",
"#storybook/vue": "^6.1.11",
"vuetify-loader": "^1.7.0",
"vuetify": "^2.6.0"
knowing that the my project is working fine and all of the components renders correctly even v-icon
main.js
const path = require('path');
module.exports = {
addons: [
'#storybook/addon-controls',
'#storybook/addon-docs',
'#storybook/addon-actions',
'#storybook/preset-scss',
],
webpackFinal: async (config, { configType }) => {
config.module.rules.push({
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
include: path.resolve(__dirname, '../'),
});
config.module.rules.push({
resolve: {
alias: {
'#': path.resolve(__dirname, '../src'),
vue: 'vue/dist/vue.js',
'vue$': 'vue/dist/vue.esm.js',
},
},
});
// Return the altered config
return config;
},
};
preview.js
import { configure, addDecorator } from "#storybook/vue";
import "!style-loader!css-loader!sass-loader!./scss-loader.scss";
import "vuetify/dist/vuetify.css";
import "#mdi/font/css/materialdesignicons.css";
import i18n from '../src/plugins/i18n';
import Vue from "vue";
import Vuetify from "vuetify";
Vue.use(Vuetify);
Vue.prototype.$t = function(...args){
return i18n.t(...args);
}
addDecorator(() => ({
i18n,
vuetify: new Vuetify({
rtl: true,
icons: {
iconfont: "mdi",
}
}),
template:
'<v-app style="background-color: white"><v-main><story/></v-main></v-app>',
}));
// automatically import all files ending in *.stories.js
configure(require.context("../stories", true, /\.stories\.js$/), module);
manager.js
import "#storybook/addon-actions/register";
import "#storybook/addon-links/register";
Here is an example of my stories
import Calendar from "../src/components/Calendar/calendar.vue";
export default {
title: "Components/Calendar",
component: Calendar,
};
const Template = (args, { argTypes }) => ({
components: { Calendar },
props: Object.keys(argTypes),
template: `<Calendar v-bind="$props" />`,
});
export const WithLabel = Template.bind({});
WithLabel.args = {
label: "Pick a date",
};
I don't know What is the issue.
Thanks in advance.

Cannot find module '#env' from 'src/store.ts' in react expo

I am trying to create an expo react app using typescript. The app works perfectly fine but when I am trying to write some tests using Jest, it always says it can not find the module '#env' from my store file.
Cannot find module '#env' from 'src/store.ts'
Require stack:
src/store.ts
src/screens/HomeScreen.tsx
src/tests/HomeScreen.test.tsx
> 1 | import { REACT_APP_API_URL } from '#env';
| ^
2 | import axios from 'axios';
3 | import { Alert } from 'react-native';
4 | import create from 'zustand';
at Resolver._throwModNotFoundError (node_modules/jest-resolve/build/resolver.js:425:11)
at Object.<anonymous> (src/store.ts:1:1)
at Object.<anonymous> (src/screens/HomeScreen.tsx:5:1)
at Object.<anonymous> (src/tests/HomeScreen.test.tsx:3:1)
HomeScreen.test.txt
import React from 'react';
import renderer from 'react-test-renderer';
import Home from '../screens/HomeScreen';
describe('<App />', () => {
it('has 1 child', () => {
const tree = renderer.create(<Home />).toJSON();
console.log('test', tree);
});
});
The #env is defined in a src/types and the file env.d.ts
declare module '#env' {
export const REACT_APP_API_URL: string;
}
jest.config.js
// jest.config.js
// Sync object
module.exports = {
preset: 'jest-expo',
transform: {
'^.+\\.tsx?$': [
'ts-jest',
{
tsconfig: {
jsx: 'react',
},
},
],
},
testMatch: ['**/?(*.)+(spec|test).ts?(x)'],
collectCoverageFrom: [
'**/*.{ts,tsx}',
'!**/coverage/**',
'!**/node_modules/**',
'!**/babel.config.js',
'!**/jest.setup.js',
],
moduleFileExtensions: ['js', 'ts', 'tsx'],
transformIgnorePatterns: [
'node_modules/(?!(jest-)?react-native|#react-native|react=native|react-clone-referenced-element|#react-native-community|expo(nent)?|#expo(nent)?/.*|react-navigation|#react-navigation/.*|#unimodules/.*|sentry-expo)',
],
coverageReporters: ['json-summary', 'text', 'lcov'],
rootDir: './',
modulePaths: ['<rootDir>'],
collectCoverage: false,
moduleNameMapper: {
'#(.*)': '<rootDir>/node_modules/$1',
},
};
tsconfig.json
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"jsx": "react-jsx",
"strict": true,
"typeRoots": ["./src/types"],
"types": ["jest", "node","#types/jest"],
"baseUrl": ".", // this must be specified if "paths" is specified.
"paths": {
"#env": ["node_modules/#env"] // this mapping is relative to "baseUrl"
},
},
}
babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: [
'react-native-reanimated/plugin',
[
'module:react-native-dotenv',
{
moduleName: '#env',
path: '.env',
blacklist: null,
whitelist: null,
safe: false,
allowUndefined: true,
},
],
],
};
};
I tried mostly everything e.g. Jest cannot find module #env React Native from here and also clear cache and reinstall all but nothing worked.
Can someone help me with this?
Create a types folder in your source folder.
Create a file named env.d.ts in the types folder.
Define your env variables as strings.
declare module '#env' {
export const REACT_APP_API_URL: string;
// other ones
}
first you create new folder under your src folder and you call it types, then you create a file named .env.d.js under types. finally you add your env variable
declare module '#env' {
export const REACT_APP_API_URL;
}

Test react-native app with 'jest-expo' preset trying to import a file after the Jest environment has been torn down

I'm trying to implement test for my react native app using expo.
I would like to test a simple component that import expo library (#expo/vector-icons) :
const Icon: FC<IconProps> = (props: IconProps) => {
const colors = useColors();
const IconComponent = createIconSetFromIcoMoon(
require("../../../../assets/icons/selection.json"),
'IcoMoon',
'icomoon.ttf'
);
return (
<IconComponent name={props.name} size={props.size || 20} color={props.color || colors.label}/>
);
};
Here is my test:
const iconProps = {
name: "alert-circle",
size: 20
}
describe("<Icon/>", () => {
describe("Rendering", () => {
it("render default as expected", () => {
const icon = create(<Icon {...iconProps}/>)
expect(icon.toJSON()).toMatchSnapshot();
})
})
})
But i got an error :
ReferenceError: You are trying to import a file after the Jest
environment has been torn down.
at Object.get Text [as Text] (node_modules/react-native/index.js:122:12)
at Object.get [as Text] (node_modules/#expo/vector-icons/build/vendor/react-native-vector-icons/lib/react-native.js:13:26)
at Icon.render (node_modules/#expo/vector-icons/build/vendor/react-native-vector-icons/lib/create-icon-set.js:120:58)
Here is my jest configuration :
preset: 'jest-expo',
setupFiles: [
"<rootDir>/jest/setupJestMock.ts"
],
testEnvironment: "node",
transform: {
'^.+\\.ts?$': 'ts-jest',
},
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/.*)"
],
I've tryed to add :
jest.useFakeTimers();
In my setupJestMock.ts file but nothing changed.
What i am doing wrong ?
Note that i'm using typescript.

Testing dynamic component using import() - TypeError: Path must be a string

Please help, I got this error when trying to create test for vue js dynamic component using jest.
I'm using babel-plugin-syntax-dynamic-import and babel-plugin-transform-dynamic-import with babel ver > 7.0.0
● Test suite failed to run
TypeError: Path must be a string. Received undefined
at TestExclude.shouldInstrument (node_modules/test-exclude/index.js:77:31)
at shouldSkip (node_modules/babel-plugin-istanbul/lib/index.js:59:21)
at PluginPass.enter (node_modules/babel-plugin-istanbul/lib/index.js:74:15)
at newFn (node_modules/#babel/core/node_modules/#babel/traverse/lib/visitors.js:193:21)
at NodePath._call (node_modules/#babel/core/node_modules/#babel/traverse/lib/path/context.js:53:20)
at NodePath.call (node_modules/#babel/core/node_modules/#babel/traverse/lib/path/context.js:40:17)
at NodePath.visit (node_modules/#babel/core/node_modules/#babel/traverse/lib/path/context.js:88:12)
at TraversalContext.visitQueue (node_modules/#babel/core/node_modules/#babel/traverse/lib/context.js:118:16)
Here's my my-page.js code:
const MyComponent = () => import('src/components/MyComponent')
...
components: {
MyComponent
},
...
myPage.spec.js code:
import { shallow } from 'vue-test-utils'
import MyPage from '#/pages/MyPage'
describe('MyPage.vue', () => {
let component
beforeEach(() => {
component = shallow(MyPage, {
...
})
jest.resetModules()
jest.clearAllMocks()
})
it('method#isEven', () => {
let result = component.vm.isEven(2)
expect(result).toBe(true)
})
})
jest.conf.js code:
const path = require('path')
module.exports = {
rootDir: path.resolve(__dirname, '../../'),
moduleFileExtensions: [
'js',
'json',
'vue'
],
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/src/$1'
},
transform: {
'^.+\\.js$': '<rootDir>/node_modules/babel-jest',
'.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
},
testPathIgnorePatterns: [
'<rootDir>/test/e2e'
],
snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
setupFiles: ['<rootDir>/test/unit/setup'],
coverageDirectory: '<rootDir>/test/unit/coverage',
collectCoverageFrom: [
'src/**/*.{js,vue}',
'!src/main.js',
'!src/router/index.js',
'!**/node_modules/**'
],
testURL: 'http://localhost/unit-test'
}
Do I need to add more configuration?
No need to use babel-plugin-syntax-dynamic-import, use babel-plugin-dynamic-import-node instead. Implementation can be seen at https://jestjs.io/docs/en/webpack.html#using-with-webpack-2
thanks to https://github.com/facebook/jest/issues/5920