How to use react-native-i18n in detox[react-native] - reactjs

I want to test the alert message in detox,and the message use i18n.
const i18n = require("react-native-i18n");
describe("Example", () => {
beforeEach(async () => {
await device.reloadReactNative();
});
it("should show hello screen after tap", async () => {
await element(by.id("btnLogin")).tap();
I18n.t(LocaleKeys.errorMsg_invalidUsername);
await expect(element(by.text(I18n.t(LocaleKeys.errorMsg_invalidUsername)))).toBeVisible();
// await expect(element(by.text("Please input the email and password."))).toBeVisible();
});
});
Run test and get the following error.
Test suite failed to run
/Users/leogeng/Desktop/studentREP/student-app/node_modules/react-native-i18n/index.js:14
export const getLanguages = () => RNI18n.getLanguages();
^^^^^^
SyntaxError: Unexpected token export
at ScriptTransformer._transformAndBuildScript (../node_modules/jest-runtime/build/script_transformer.js:305:17)
at Object.<anonymous> (firstTest.spec.js:1:114)
at Generator.next (<anonymous>)
Then I add the following code for jest:
{
"preset": "react-native",
"transformIgnorePatterns": [
"/node_modules/(?!(react-native(.*)?/|native-base(.*)?/|react-navigation/))"
]
}
and get error again:
Validation Error:
Module <rootDir>/node_modules/react-native/jest/setup.js in the setupFiles option was not found.
Actually i confirm 'setup,js' exist in node_modules/react-native/jest.
I do not know why the error happens, anybody can help me?
Thanks

Most likely it's because you're using an old version of node, try to update and see if it solves the issue. Also, it's completely unrelated to Jest and you should probably revert your attempts to modify Jest settings if you don't have any issues with Jest unit tests; in anyway, it will not fix the detox issues.
In case you have some requirement or reason which forces you to keep node at a specific old version, you can bypass it by performing the test differently: have a demo screen only for the e2e tests (or even create a whole demo project just for e2e), in the demo screen you can have a button which performs what you need with i18n (changing locale or whatever), and in the detox test you tap this "demo" button before testing what you actually want.

I've had the same problem. I resolve it by importing i18n-js instead of react-native-i18n.
Because react-native-i18n is not a plain javascript framework, Detox can't import it.
But react-native-i18n is using i18n-js, so you can access your translations without any problem
const I18n = require('i18n-js')
// and then you can use it for your tests
...
await element(by.text( I18n.t('hello') )).tap()

Related

Unit Tests Failing After Updating React Scripts from v.3.4.4 to v.4.0.3

I'm working on a new project for a client and have been asked to update create-react-app (react-scripts) from v.2.0.5 to v.4.0.3. I did that, and a bunch of unit tests failed. I went back through the project and isolated the breaking change to be the update from react-scripts 3.4.4 to 4.0.0.
Basically, the main error I'm seeing seems to apply to any tests running against async/await methods. Jest reports that the test times out but these tests are only timing out because they are failing. They all pass without issue on an earlier version of react-scripts (and by extension an earlier version of Jest I'd guess).
thrown: "Exceeded timeout of 5000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."
The timeout seems to be relating to an issue with promises as it's preceeded by this error:
TypeError: Cannot read property 'then' of undefined
Along with a fairly indecipherable stack trace that lists a load of node modules.
Here's an example of the test that's failing:
test('dispatching fetchPublishedArticlesAuthors action causes an API GET and updates the store', async (done) => {
const options = { page: 0, size: 20, sort: 'createdBy.firstName,asc' };
store.dispatch(fetchPublishedArticlesAuthors(options));
const state = await stateChange(store);
expect(fetch).toHaveBeenCalledWith(
`https://content.onehub.test/articles/authors?page=0&size=20&sort=createdBy.firstName%2Casc`,
expect.objectContaining({ method: 'GET' }),
);
expect(getPublishedArticlesAuthors(state)).toMatchSnapshot();
done();
});
The await stateChange(store) references this method:
export function stateChange(store) {
return new Promise((resolve) => {
let currentState = store.getState();
store.subscribe(() => {
const newState = store.getState();
if (newState !== currentState) {
resolve(newState);
}
currentState = newState;
});
});
}
This method works without issue on another project running react-scripts 4.0.3 so I don't think that it's the issue per se but it is failing to return anything if I'm not mistaken.
Store is mocked as follows:
beforeEach(() => {
store = mockStore({ initialState, reducers, rootSaga: sagas });
fetch.mockClear();
});
Any tips on where to start? Confused as to why it fails on a more recent version but passes on an earlier one.
The solution was to set resetMocks to false. I tried doing this in Jest config but couldn't get it working so just added it directly to package.json:
"jest": {
"resetMocks": false
}
It wasn't obvious from the failing tests but having read the release notes you can see that the version of Jest used by Create React App changed from v24 to v26. In the process, resetMocks is set to true which was breaking the implementation in the test above, causing them all to time out.

why importing CSSRulePlugin in Next.js results in error?

I am trying to use GSAP library in my Next.js project i downloaded the npm version of the library
from react jsap.
but when i import it like this:
import { gsap } from "gsap";
import { CSSRulePlugin } from "gsap/CSSRulePlugin";
it throws an error, the error seems to be caused by CSSRulePlugIn since when i remove it from imports everything is fine.
the error:
apparently this error occurs because GSAP tries to access the window element of the client browser but since i was using it in Next.js (SSR) so it would result in that error since there was no window to get a hold of.
so i ended up solving the problem by importing CSSRulePlugin only after making sure that the code runs in the client side, and for that i imported it inside useEffect method and it worked.
here is the code in my case:
useEffect(() => {
const GSAP = require("gsap/CSSRulePlugin");
const { CSSRulePlugin } = GSAP;
gsap.registerPlugin(CSSRulePlugin);
// do whatever you want to do with the plugin, its Working now...
// for example
let imageReveal = CSSRulePlugin.getRule(".container:after");
}, []);

Cypress test fails to run when importing from source code of CRA+TS app

One of my Cypress tests fails to run when it tries to import from a file in the source code of a create-react-app src directory.
The test looks like:
// cypress/integration/this-fails.js
import { MY_CONSTANT } from '../../src/constants';
describe('Cypress', () => {
...
})
The imported source file looks like:
// src/constants.ts
export const MY_CONSTANT = 'foo';
The Cypress test failure is caused by a Jest test file in the source directory:
ERROR in /my-app/src/App.test.tsx(5,1)
Cannot find name 'test'. Do you need to install type definitions for a test runner? Try`npm i #types/jest`or`npm i #types/mocha`.
The Jest type definitions are installed. Additionally, to no avail, I have tried to exclude the problematic Jest test in the Cypress tsconfig.
// cypress/tsconfig.json
{
...
"exclude": [
"../src/App.test.tsx"
],
...
}
Here is a minimal repo that reproduces my problem.
Lastly, to clarify why I am importing things into Cypress tests from the source directory — the imported variable is intended to be a DOM selector or a function that returns a DOM selector so that selectors are not hardcoded in the tests.
I'm not sure why the message is TypeScript emitted no output for /my-app/src/constants.ts, this seems to indicate that the file is readable and typescript attempts to parse it, and does not recognize the syntax.
However my guess is that the code of the test is running in a browser process and can't access files outside of it's folder.
If constant.ts is in cypress/fixtures it works, so one easy way is to add a script to copy the file. A script called "precypress" will be automatically run when the "cypress" script is invoked.
This is kind of 90% there - you don't get hot-module reload when constants.ts changes.
package.json
"scripts": {
...
"precypress": "copyfiles ./src/constants.ts ./cypress/fixtures",
"cypress": "cypress open"
},
It also works with functions and handles typing,
test
import { MY_CONSTANT, getMyConstant } from '../fixtures/src/constants';
describe('Cypress', () => {
it('is working', () => {
cy.visit('/')
alert(MY_CONSTANT);
alert(getMyConstant());
expect(true).to.equal(true)
})
})
constant.ts
export const MY_CONSTANT: Number = 10;
export const getMyConstant: Function = () => 20;

Jest Testing Electron/React Component using window.require

I'm currently creating an Electron application that uses React to create the interface. In order to get access the fs, I have been using:
const fs = window.require('fs');
Which works fine when in an Electron window.
The issue is that when I write jest tests for any components that use the window.require('fs'), I get the following error when running the test.
TypeError: window.require is not a function
I have looked through the documentation for Jest and it seems the solution is to generate a mock of window using a manual mock (see "Mocking methods which are not implemented in JSDOM" at https://jestjs.io/docs/en/manual-mocks). However, when I tried to mock window.require by adding at the top of my test file
window.require = jest.fn();
I still get the same TypeError.
I'm very new to create Jest mocks so any help with this would be much appreciated.
My current test file (Component.test.js) looks like
window.require = jest.fn();
import React from 'react';
import renderer from 'react-test-renderer';
import Component from '../index';
describe('Testing', () => {
it('Component renders correctly', () => {
const component = renderer.create(<Component />);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
});
Add this line at the beginning of your test (or in a setupFilesAfterEnv setup file):
window.require = require;
Details
electron supplies window.require but it isn't defined when running unit tests with Jest.
By default Jest provides a browser-like environment using jsdom that includes a window object.
The above line mocks window.require by setting it equal to the current value of require.
I once faced this issue and below was what solved it for me:
I had to leverage on the module react-app-rewired. this module Tweaks the webpack config(s), even for those using create-react-app(CRA) without using 'eject' and without creating a fork of the react-scripts.
all you need is to add a config-overrides.js file in the root of your project, and populate it with the snippet below:
module.exports = function override (config) {
config.target = 'electron-renderer'
return config;
}
then you proceed to your package.json and replace your start script with
"start": "react-app-rewired start" . and you are done. you can thereafter rebuild and run your test script without getting the window.require is not a function error.
I hope I have been able to help.
cheers!

React testing through jest gives an unexpected error

I'm using JEST to test my react app.
I get the error and some text as in the image below.
Also, the code for my test case(named: TodoApp.test.jsx) is as :
it("should add todo ...", () => {
// const text = "Suzal is trying react";
// I commented out the other lines because the test
// only gave error when this line was included.
const todoApp = TestUtils.renderIntoDocument(<TodoApp />);
// todoApp.state = {
// todos: []
// }
// todoApp.handleAddTodo(text);
// expect(todoApp.state.todos[0].text).toBe(text);
});
If extra code/description is needed then please do ask. The complete file is on Github : TodoApp.test.jsx
Links that I already have gone through
https://github.com/facebook/react/issues/11098
https://github.com/facebook/jest/issues/4597
I cloned your repo and started commenting things out and found that there seems to be something going on with TodoApi.getTodos() on line 15 of TodoApp.jsx in the constructor when setting your initial state. If you remove the call to TodoApi.getTodos and replace with with an empty array the test errors disappear. You may need to create a mock function for TodoApi.getTodos to get your tests to pass.
https://facebook.github.io/jest/docs/en/mock-functions.html

Resources