Karma and React, have warnings to cause errors - reactjs

I am using Karma with mocha to test my React components. I have some warnings displayed when the PropTypes are not matched. However it would be really interesting to have these warnings to cause an actual error, as to track down the test and fix it.
Do you know how this could be achieved?

You can replace the console.warn method with your own and throw when the message provided matches a certain pattern.
let warn = console.warn;
console.warn = function(warning) {
if (/(Invalid prop|Failed propType)/.test(warning)) {
throw new Error(warning);
}
warn.apply(console, arguments);
};

Small improvements to accepted answer: console.error instead of console.warn as spain-train mentioned, added 'Failed prop type' to regex, as only then it works with React 15.3.1, and made the code more strict eslint friendly.
const error = console.error;
console.error = function(warning, ...args) {
if (/(Invalid prop|Failed prop type)/.test(warning)) {
throw new Error(warning);
}
error.apply(console, [warning, ...args]);
};

2021 update:
const consoleError = console.error;
console.error = function (...args) {
if (/(Invalid prop|Failed propType|Failed .+ type)/.test(args[0])) {
const errorMessage = args.reduce((p, c) => p.replace(/%s/, c));
throw new Error(errorMessage);
}
consoleError.apply(console, args);
};
Failed prop type is now Failed %s type: %s%s. It uses string substitutions to write to console. Here is the code in React.

Related

Cannot use import statement outside a module in Jest Test module

I am new in Jest. I tried to write test for basic function which is
export const queryValidate = (query) => {
const str = query.replace(/\s+/g, "");
const conditionsArray = [
str === "",
str === "{",
str === "}",
str === "{}",
];
if (conditionsArray.includes(true)) {
return true;
} else {
return false;
}
};
In my Jest test file like that
import { queryValidate } from "./components/QueryValidate";
console.log(queryValidate("{"));
I am getting this error message :
import { queryValidate } from "./components/QueryValidate";
SyntaxError: Cannot use import statement outside a module
I cannot understand it is about Jest error or React module error. I try a write dummy test like :test("Fake test", () => {
expect(true).toBeTruthy();
});
Its work .
Can someone help me?
I don't have enough reputation to add a comment, therefore I'm adding an answer. I faced the same issues a while back.
As Estus has mentioned in the comment, you need to change the Jest config.
You can also have a look at babel-jest and then set a babel config file/ .babelrc, along with the preset env.

How to fix eslint failure when requiring a file with dynamic path inside a function?

I need to use react-int outside a component and particularly inside an util file. In order to accomplish that i'am using this code https://gist.github.com/genadyp/435f4e264cb6e377836cf63bee8987d8
But i am facing an issue with eslint that fails and it does not accept using require inside a function and using a dynamic file path too.
here is eslint output:
error Unexpected require() global-require
error Calls to require() should use string literals import/no-dynamic-require
Any advice and suggestions will be greatly appreciated.
//util.js
export function formatMessage(t, locale) {
if (t=== 0 || t === 2400) {
const translations
=require(`src/locales/${locale.toLowerCase()}.json`));
const intlProvider = new IntlProvider({ locale, messages:
translations }, {});
const mes = defineMessages({
morning: {
id: 'greeting.morning',
defaultMessage: 'hello',
},
evening: {
id: 'greeting.evening',
defaultMessage: 'good evening',
},
});
const { intl } = intlProvider.getChildContext();
return t === 0 ? intl.formatMessage(mes.morning) :
intl.formatMessage(mes.evening);
}
}
You can read more about the reasoning for this rule here: https://eslint.org/docs/rules/global-require
If you are pretty sure about what you are doing you can disable the rule adding this comment before the statement: // eslint-disable-next-line global-require

Apollo - React (Typescript) Invariant Error when building production build

I am creating a new react app with gatsby, typescript, and apollo (for graphql queries).
When testing in dev, the app compiles and runs with no errors thrown.
When I transpile the build, using 'gatsby build', it fails with an error.
I don't understand why or where this is being triggered. It seems to be something to do with the way webpack is checking as it's building, but I don't know how to pinpoint the issue and there doesn't seem to be any material out there with a clear answer for me.
It seems to be caused by the httplink module. The code that triggers the error when present in any .tsx file is:
import { HttpLink } from 'apollo-link-http'
const link = new HttpLink({
uri: 'http://localhost:3001/graphql'
})
The error shown is the following:
error Building static HTML failed
See our docs page on debugging HTML builds for help https://gatsby.dev/debug-html
10 | function InvariantError(message) {
11 | if (message === void 0) { message = genericMessage; }
> 12 | var _this = _super.call(this, typeof message === "number"
| ^
13 | ? genericMessage + ": " + message + " (see https://github.com/apollographql/invariant-packages)"
14 | : message) || this;
15 | _this.framesToPop = 1;
WebpackError: Invariant Violation: Invariant Violation: 1 (see https://github.com/apollographql/invariant-packages)
- invariant.esm.js:12 new InvariantError
[lib]/[apollo-link-http-common]/[ts-invariant]/lib/invariant.esm.js:12:1
- bundle.esm.js:64 checkFetcher
[lib]/[apollo-link-http-common]/lib/bundle.esm.js:64:52
- bundle.esm.js:8 createHttpLink
[lib]/[apollo-link-http]/lib/bundle.esm.js:8:17
- bundle.esm.js:139 new HttpLink
[lib]/[apollo-link-http]/lib/bundle.esm.js:139:1
- Strategy.tsx:6 Module../src/components/Strategy.tsx
lib/src/components/Strategy.tsx:6:14
- bootstrap:19 __webpack_require__
lib/webpack/bootstrap:19:1
- bootstrap:19 __webpack_require__
lib/webpack/bootstrap:19:1
- sync-requires.js:10 Object../.cache/sync-requires.js
lib/.cache/sync-requires.js:10:56
- bootstrap:19 __webpack_require__
lib/webpack/bootstrap:19:1
- static-entry.js:9 Module../.cache/static-entry.js
lib/.cache/static-entry.js:9:22
- bootstrap:19 __webpack_require__
lib/webpack/bootstrap:19:1
- bootstrap:83
lib/webpack/bootstrap:83:1
- universalModuleDefinition:3 webpackUniversalModuleDefinition
lib/webpack/universalModuleDefinition:3:1
- universalModuleDefinition:10 Object.<anonymous>
lib/webpack/universalModuleDefinition:10:2"
Is this typescript issue, gatsby issue, apollo issue, or a webpack issue? Or a combination?
Thank you for any help you can give! I'm struggling with my understanding of all the pieces here.
I understand that Invariant Violations are about an issue with the wrong types being referenced. Because this occurs in the module, I'm not sure if I'm doing something wrong, or if it's an issue inside the imported library. Maybe it's an issue that I'm forcing typescript checks on a basic javascript based library. I still didn't quite come to a conclusion on this.
I tried adding the following config to gatsby-node.js to ignore the module checks (as suggested here: https://gatsby.dev/debug-html), with no successful build, though the error did change, as it could not see the module.
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
if (stage === "build-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /apollo-link-http/,
use: loaders.null(),
},
],
},
})
}
}
To recap, this is the code designed to create the client object to enable queries to the graphql endpoint. When running 'gatsby build' the in variant error occurs (see above).
import * as React from 'react'
import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { HttpLink } from 'apollo-link-http'
const cache = new InMemoryCache()
const link = new HttpLink({
uri: 'http://localhost:3001/graphql'
})
const client = new ApolloClient({
cache,
link
})
I'm a newbie at this. After hours of looking I finally tracked down the error in the file. On closer inspection, when the environment is production (process.env.NODE_ENV === "production"), then the error is not detailed. So I looked at what the error would be if the environment was something else, and changed the file to output this to the console. What I got back was:
fetch is not found globally and no fetcher passed, to fix pass a fetch for
your environment like https://www.npmjs.com/package/node-fetch.
For example:
import fetch from 'node-fetch';
import { createHttpLink } from 'apollo-link-http';
const link = createHttpLink({ uri: '/graphql', fetch: fetch });
I added fetch to my code, and it built a production version with no errors.
I don't understand why this error was not thrown with the dev environment, but I guess it's something to do with the lazy loading.
Problem fixed.

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

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()

try-catch statement in React JSX

According to the JSX reference, this is what a try-catch statement must look like
try {
statement*
} [catch (varname : type) {
statement*
}]* [finally {
statement*
}]
I tried the following
try {
console.log(window.device.version)
} catch (e : TypeError) {
console.log('Error')
}
Which results in the error
Module build failed: SyntaxError: Unexpected token, expected ) (11:15)
9 | try {
10 | console.log(window.device.version)
11 | } catch (e : TypeError) {
| ^
12 | console.log('Error')
13 | }
14 | return (
What is the correct way to use a try-catch statement in JSX then ?
React JSX
It looks like a TypeScript style. Just use try{ } catch(e) { console.error(e); } would be fine.
Take a look at MDN, and don't forget that JSX is just a syntax sugar for React.createElement.
JSX - a faster, safer, easier JavaScript
The link you mentioned is not react React JSX, but a whole new thing call DeNA JSX.
Take a look at this issue in DeNA JSX, and this PR.
In JSX or JavaScript you can write it like this
try {
console.log(window.device.version)
} catch (e) {
console.log('Error')
}
If you are using TypeScript your previous code should work
Hope that helps
The try statement lets you test a block of code for errors.
The catch statement lets you handle the error.
The throw statement lets you create custom errors.
The final statement lets you execute code, after try and catch, regardless of the result.
The basic concept goes like this:
try {
// Block of code to try
}
catch(err) {
// Block of code to handle errors
}
So, let's now make a scenario where an error would occur:
// It will try to run the task, but it will fail
try {
eval(console.log("Hello world)); // Just add the missing quote at the end of 'world' word and it will pass :)
}
// So, here is where we catch the error and display it to the user
catch(error) {
console.error(error);
// expected output:
// "message": "Uncaught SyntaxError: Invalid or unexpected token"
// Note - error messages will vary depending on browser
}
Exception handling has the following syntax..
try {
// code...
} catch (err) {
// error handling
}
See this: https://javascript.info/try-catch
But try-catch will not catch all the errors in React.js code. Try-catch will detect errors in an imperative code whereas React is declarative in nature
Use error boundaries as defined in React 16 and above..
Create a component using componentDidCatch
Surround your component to be tested using the error boundary.
See this-(official react docs):https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html
try{
// code for error testing
}
catch (e) {
// code for error handeling
console.log(e)
}

Resources