Unexpected string error in Jest with './environment/validate.fx'; - react-native

In my React Native app, I'm just starting to write a test file, which runs fine like this:
// #flow
import type {
Location,
LocationAction
} from "../src/redux/reducers/locationReducer";
// import { getLocationSaga } from "../src/redux/actions/locationActions";
import SagaTester from "redux-saga-tester";
import recordSaga from "../recordSaga";
describe("getLocationAsync", () => {
const calculatedSimulatorLocation: Location = {
latitude: 37.33233141,
latitudeDelta: 0.0004491555874955085,
longitude: -122.0312186,
longitudeDelta: -0.05737702242408729
};
const startAction: LocationAction = { type: "USER_LOCATION_START" };
const successAction: LocationAction = {
type: "USER_LOCATION_SUCCESS",
region: calculatedSimulatorLocation
};
describe("userLocationSaga", () => {
it("gets the user's location", async () => {
const dispatched = await recordSaga(getLocationSaga, startAction);
expect(dispatched).toContainEqual(successAction);
});
});
});
The test, of course, fails because getLocationSaga is not defined. I've stubbed the function in my actions file:
// #flow
import { Location } from "expo";
import type { LocationAction } from "../reducers/locationReducer";
import type { Saga } from "redux-saga";
export function getLocationAsync(): LocationAction {
return { type: "USER_LOCATION_START" };
}
export function* getLocationSaga(): Saga<void> {
return console.log("hello from saga");
}
But when I uncomment the line in the tests that imports this method, I get this error:
● Test suite failed to run
/Users/TuzMacbookPro2017/Development/QMG-local/APPS/QMGTrago/node_modules/expo/build/Expo.fx.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import './environment/validate.fx';
^^^^^^^^^^^^^^^^^^^^^^^^^^^
SyntaxError: Unexpected string
at ScriptTransformer._transformAndBuildScript (node_modules/#jest/transform/build/ScriptTransformer.js:471:17)
at ScriptTransformer.transform (node_modules/#jest/transform/build/ScriptTransformer.js:513:25)
at Object.<anonymous> (node_modules/expo/src/Expo.ts:1:1)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 7.506s
Ran all test suites.
Watch Usage: Press w to show more.
How do I fix this? Below are some config files:
package.json
...
"jest": {
"preset": "react-native"
},
...
.eslintrc
{
"parser": "babel-eslint",
"extends": "airbnb",
"plugins": ["react", "jsx-ally", "import"]
}
babel.config.js
module.exports = function(api) {
api.cache(true);
return {
presets: ["babel-preset-expo", "#babel/preset-flow"]
};
};

I had this same issue today on a react-native/ expo app that is using jest. I referenced their guide at https://docs.expo.io/versions/latest/guides/testing-with-jest/. I looked at the following section listing the transform patterns to ignore:
"transformIgnorePatterns": [
"node_modules/(?!(jest-)?react-native|react-clone-referenced-element|#react-native-community|expo(nent)?|#expo(nent)?/.*|react-navigation|#react-navigation/.*|#unimodules/.*|sentry-expo|native-base)"
]
This is found in jest config file (mine is jest.config.js). I noticed mine was missing the following: |#unimodules/.*|sentry-expo|expo(nent)?|#expo(nent)?/.*|
I included those to fix that specific error.
However, I then got the following errors :
The Expo SDK requires Expo to run. It appears the native Expo modules are unavailable and this code is not running on Expo.
I discovered that I needed to configure my jest to work with jest-expo according to the docs.

Related

Testing Angular 14 Standalone Components with Spectator

Our test runner is Jest.
Our component is marked as standalone: true,
If try to set up spectator like this:
describe('OurComponent', () => {
let spectator: Spectator<OurComponent>;
const fakeActivatedRoute: ActivatedRoute = {
snapshot: {data: {}},
} as ActivatedRoute;
const componentFactory: SpectatorFactory<OurComponent> = createComponentFactory({
component: OurComponent,
imports: [
// some imports
],
providers: [
// some providers
],
detectChanges: false,
shallow: true,
});
beforeEach(async () => {
spectator = componentFactory();
});
it('should be created', () => {
expect(spectator).toBeDefined();
});
});
Then we run into the following error:
"Error: Unexpected "OurComponent" found in the "declarations" array of the "TestBed.configureTestingModule" call, "OurComponent" is marked as standalone and can't be declared in any NgModule - did you intend to import it instead (by adding it to the "imports" array)?"
Using the Angular-CLI in order to generate resulted in a component with a test file which is built upon ComponentFixture.
How can we make it possible to test a standalone component using Spectator?
Depends on your spectator version (mine is 10.0.0) but you can use the declareComponent property :
const componentFactory: SpectatorFactory<OurComponent> = createComponentFactory({
component: OurComponent,
declareComponent: false,
});

Module parse failed: Unexpected token in Storybook when working with pdfjs-dist

I am working with a package that uses the pdfjs-dist package, and when trying to load the component that uses it in my Storybook, I get the following error
ERROR in ./node_modules/pdfjs-dist/build/pdf.js 2267:39
Module parse failed: Unexpected token (2267:39)
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
|
| async getXfa() {
> return this._transport._htmlForXfa?.children[this._pageIndex] || null;
| }
|
My guess, it is about handling XFA files, which are PDF files.
This is my main.js file in .storybook
const path = require('path');
module.exports = {
stories: ['../components/**/*.stories.js', '../components/**/*.stories.mdx'],
addons: [
'#storybook/addon-links',
'#storybook/addon-essentials',
'storybook-dark-mode',
'storybook-addon-next-router',
],
webpackFinal: async (config, { isServer }) => {
config.resolve.modules = [path.resolve(__dirname, '..'), 'node_modules'];
config.resolve.alias = {
...config.resolve.alias,
'#': path.resolve(__dirname, '../components'),
store: path.resolve(__dirname, '../utils/stores'),
dummy: path.resolve(__dirname, '../utils/dummy'),
};
if (!isServer) {
config.node = {
fs: 'empty',
};
}
return config;
},
};
pdfjs-dist: https://github.com/mozilla/pdf.js
react-pdf-viewer: https://github.com/react-pdf-viewer/react-pdf-viewer
The component works swimmingly in my development server, the issue is only in Storybook. Because of that issue, it is unable to even start the storybook server. If I remove the component that uses the package, storybook loads.
The error tells me to use proper webpack configs, but I just cannot figure that one out. This is what I tried, and it didn't work. (in webpackFInal: async () => { ... )
config.module.entry['pdf.worker'] = 'pdfjs-dist/build/pdf.worker.entry';
and
config.module.rules.push({
test: /pdf\.worker\.js$/,
type: 'asset/inline',
generator: {
dataUrl: (content) => content.toString(),
},
});
Found them here: https://github.com/mozilla/pdf.js/issues/14172

Jest with Vue 3 - ReferenceError: define is not defined

I would like to test my component with Jest and inside component, I imported #vue/apollo-composable library and when I run test I get the error:
ReferenceError: define is not defined
2 | // libraries
3 | import { defineComponent, ref, watch } from '#vue/composition-api'
> 4 | import { useLazyQuery, useResult } from '#vue/apollo-composable'
| ^
5 | import gql from 'graphql-tag'
In the jest test I don't use apollo-composable and I don't plan to. Code:
import '#/plugins/composition-api'
import App from '#/components/App.vue'
import Vue from 'vue'
import { Wrapper, createLocalVue, mount } from '#vue/test-utils'
Vue.use(Vuetify)
describe('SelectMediaProcess.vue', () => {
let wrapper: Wrapper<Vue>
const localVue = createLocalVue()
beforeEach(() => {
wrapper = mount(SelectMediaProcess, { localVue })
})
it('render', () => {
expect(wrapper.exists()).toBe(true)
})
})
I read on the internet what I can use:
jest.mock('#vue/apollo-composable', () => {
// mock implementation
})
But when I use this piece of code in my test. I get error: (useLazyQuery is a function from #vue/apollo-composable library)
TypeError: Cannot read property 'useLazyQuery' of undefined
19 |
20 | // get default media process
> 21 | const { onResult, load: loadDefaultMP } = useLazyQuery<
| ^
22 | getDefaultMediaProcess,
23 | getDefaultMediaProcessVariables
24 | >(
Does anyone know what can I do please?
EDIT
I added these lines to my jest.config.js. It helped others but not me.
transformIgnorePatterns: ['<rootDir>/node_modules/(?!#vue/apollo-composable).+\\.js$']
moduleNameMapper: { '#vue/apollo-composable': '#vue/apollo-composable/dist/index.js' }
Full jest.config.js:
module.exports = {
preset: '#vue/cli-plugin-unit-jest/presets/typescript-and-babel',
moduleFileExtensions: ['js', 'ts', 'json', 'vue'],
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/src/$1',
'vuetify/lib(.*)': '<rootDir>/node_modules/vuetify/es5$1',
'#vue/apollo-composable': '#vue/apollo-composable/dist/index.js'
},
modulePaths: ['<rootDir>/src', '<rootDir>/node_modules'],
transform: {
'.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$':
'jest-transform-stub',
'^.+\\.ts?$': 'ts-jest',
'.*\\.(vue)$': 'vue-jest'
},
transformIgnorePatterns: [
'<rootDir>/node_modules/(?!(vuetify)/)',
'<rootDir>/node_modules/(?!#vue/apollo-composable).+\\.js$'
]
}
and I get these new errors:
FAIL tests/unit/selectMediaProcess.spec.ts
● Test suite failed to run
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:
C:\Users\u112200\Documents\deposit-frontend\node_modules\#vue\apollo-composable\dist\index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){export { useQuery, } from './useQuery';
^^^^^^
SyntaxError: Unexpected token 'export'
2 | // libraries
3 | import { defineComponent, ref, watch } from '#vue/composition-api'
> 4 | import { useLazyQuery, useResult } from '#vue/apollo-composable'
| ^
5 | import gql from 'graphql-tag'
6 | // models
7 | import { allMediaProcesses } from '../models/__generated__/allMediaProcesses'
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 src/components/SelectMediaProcess.vue:4:1
at Object.<anonymous> (src/components/SelectMediaProcess.vue:89:3)
Does anyone know what can I do next please?
You'll need to define the functions inside the mock statement.
Currently, you've said that rather than using the real thing a mock should be used. The reason you're then getting undefine is because the mock is empty (you've not defined any functions in it).
So, the next thing to do is to specify how that mocked library should interact. You're importing two functions, so you'll need to define those functions inside the mock statement:
jest.mock('#vue/apollo-composable', () => {
return {
__esModule: true,
useLazyQuery: jest.fn(() => 42), // Replace 42 with whatever result you'd expect
useResult: jest.fn(() => 43), // Replace 43 with whatever result you'd expect
};
})
There's some more detail about this in the jest documentation.
Do you have a .babelrc file in your project? If so, you will need to change it to a babel.config.js (don't ask me why, only worked for me this way).
Also, you will need to add the following line to your jest.config.js
transformIgnorePatterns: ['node_modules/(?!#vue/apollo-composable)/']
In your case, you are already using a jest.config.js file, but in case you were using the package.json to define your testing config, you would need to create the jest config file.
This issue on GitHub helped me a lot on solving this issue:
https://github.com/facebook/jest/issues/9395
If you wanna mock using jest, you use the following approach
jest.mock("apollo-client", () => ({
__esModule: true,
useQuery: (query: any) => {
//other mocks if needed
},
useLazyQuery: jest.fn().mockReturnValue([
jest.fn(),
{
data: {
yourProperties: "Add Here",
},
loading: false,
},
]),
}));
As you see, this approach even returns the mock function that is called in the code to be tested.

Angular 8 testing error Unexpected value 'DecoratorFactory' imported by the module 'DynamicTestModule'

I am trying to make Jasmine & Karma framework into the current angular application running in ver 8.2. But i am coming across this weird error inside the Karma test running window:
Failed: Unexpected value 'DecoratorFactory' imported by the module 'DynamicTestModule'. Please add a #NgModule annotation.
What is the problem?
My componenent.spec.ts looks like this:
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { HomeComponent } from './home.component';
import { NO_ERRORS_SCHEMA} from '#angular/core';
import {RouterTestingModule} from '#angular/router/testing';
import {HttpClientTestingModule} from '#angular/common/http/testing';
import { MsalService } from '#azure/msal-angular';
import { Store } from '#ngrx/store';
import { Pipe } from '#angular/core';
describe('HomeComponent', () => {
let component: HomeComponent;
let fixture: ComponentFixture<HomeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule, HttpClientTestingModule, Pipe]
,declarations: [HomeComponent]
,schemas:[NO_ERRORS_SCHEMA]
,providers: [
{provide: MsalService, useFactory: '' },
{provide: Store, useFactory: '' }
]
})
.compileComponents();
}));
it('should have header text', async(() => {
const fixture = TestBed.createComponent(HomeComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
//expect(compiled.querySelector('.header-txt').textContent).toContain('Tax');
}));
});
I found the cause :-
export class MockStore<T> {
private state: BehaviorSubject<T> = new BehaviorSubject(undefined);
setState(data: T) { this.state.next(data); }
select(selector?: any): Observable<T> {
return this.state.asObservable();
}
pipe() {}
dispatch(action: any) { }
}
========================================================================
TestBed.configureTestingModule({
{provide: Store, useFactory: 'MockStore' }
..............
The useFactory property must be some custom class name. Now i mocked the store class.

Difference between import and require in jest

I am writing my first test for a react-native project using react-native-router-flux and react-redux
My code is something like
jest.autoMockOff();
jest.setMock('react-native', {
NativeModules: {}
});
jest.setMock('react-native-router-flux', {
Actions: {}
});
const mockStore = require('../../mock/Store');
const actions = require('../myActions');
...
// Some tests that test if the right actions are dispatched.
The above works, However when I use ES6 import instead of require I have a problem.
If I replace
const actions = require('../myActions');
with
import * as actions from "../myActions"
I get the below error.
Runtime Error
- Error: Cannot find module 'ReactNative' from 'react-native.js'
at Resolver.resolveModule (node_modules/jest-cli/node_modules/jest-resolve/src/index.js:117:17)
at Object.<anonymous> (node_modules/react-native/Libraries/react-native/react-native.js:175:25)
at Object.<anonymous> (node_modules/react-native-router-flux/src/Scene.js:10:18)
While I can work with this, I am curious to understand the reason for failure,
Also note that I am just not able to transpile react-native-router-flux with es2015 presets in .bablerc file and I think I will have to live with that limitation (of not being able to transpile react-native-router-flux).
myActions.js looks like
import {Actions} from 'react-native-router-flux';
export function searchRequest() {
return {
type: "search_request"
}
}
export function searchRequestFailure(error) {
return {
type: "search_request_failure",
error: error.toString()
}
}
export function searchRequestSuccess(payload) {
return {
type: "search_request_success",
payload: payload
}
}
export function search(nameOrAddress) {
return dispatch => {
dispatch(searchRequest())
return fetch("http://localhost:8080/search", {
method: "GET"
}).then((response) => {
return response.json()
}).then((responseData) => {
dispatch(searchRequestSuccess(responseData))
Actions.list() //react-native-router-flux dependency
}).catch(error => {
dispatch(searchRequestFailure(error))
})
}
}
Using react-native 0.26 and jest 12.1.1
That is not the correct ES6 conversion.
const actions = require('../myActions'); // requires the defaultMember of the exported module and
//ES6 (ES2015) equivalent is
import actions from '../myActions';
https://developer.mozilla.org/en/docs/web/javascript/reference/statements/import