React (Native) setup Jest to test Context component - javascript

The React Context API allows me to place the logic for the app state in one place (and avoid redux). Right now it looks like this
// Using the Context API used in react 16.3 - https://www.youtube.com/watch?v=XLJN4JfniH4
const { Provider, Consumer: ContextConsumer } = React.createContext()
class ContextProvider extends Component {
...// lot of functions ...
render() {
return (
<Provider
value={{
...this.state,
getDose: this.getDose,
getDoseRange: this.getDoseRange,
setDose: this.setDose,
checkIN: this.checkIN,
checkOUT: this.checkOUT,
getFalsifiedDrug: this.getDefaultproductData,
updatePrescriptionDose: this.updatePrescriptionDose,
}}
>
{this.props.children}
</Provider>
)
}
}
module.exports = { ContextConsumer, ContextProvider }
Entire code can be found here.
What's the best practice to build jest tests that allows me to test the functions and don't mess up the state?
(Would like to avoid using Enzyme (developed by AirBnB) - since AirBnB officially gave up using React Native)
Example
How do I make a test that confirms that when I call setDose(2) that the productData.dose was changed from "5 mg" and now equals "2 mg. But then set the state back to "5 mg" for the other test.
BONUS INFO
I'm having some trouble getting jest to work with me (so I can try out the suggested solutions)
package.json
{
"main": "node_modules/expo/AppEntry.js",
"private": true,
"scripts": {
"test": "jest --watchAll"
},
"dependencies": {
"#expo/samples": "2.1.1",
"crypto-js": "^3.1.9-1",
"date-fns": "^1.29.0",
"expo": "^28.0.0",
"invert-color": "^1.2.3",
"lodash": "^4.17.10",
"react": "16.3.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-28.0.0.tar.gz",
"react-native-qrcode": "^0.2.6",
"react-native-slider": "^0.11.0",
"react-native-switch": "^1.5.0",
"react-navigation": "2.3.1",
"whatwg-fetch": "^2.0.4"
},
"devDependencies": {
"babel-eslint": "^10.0.1",
"babel-preset-expo": "^5.0.0",
"eslint": "^5.16.0",
"eslint-config-codingitwrong": "^0.1.4",
"eslint-plugin-import": "^2.17.2",
"eslint-plugin-jest": "^22.5.1",
"eslint-plugin-jsx-a11y": "^6.2.1",
"eslint-plugin-react": "^7.13.0",
"jest-expo": "^32.0.0",
"react-native-testing-library": "^1.7.0",
"react-test-renderer": "^16.8.6"
},
"jest": {
"preset": "jest-expo"
}
}
It just throws this at me
> # test /Users/norfeldt/Desktop/React-Native/MedBlockChain
> jest --watchAll
● Validation Error:
Module react-native/jest/hasteImpl.js in the haste.hasteImplModulePath option was not found.
<rootDir> is: /Users/norfeldt/Desktop/React-Native/MedBlockChain
Configuration Documentation:
https://jestjs.io/docs/configuration.html
npm ERR! Test failed. See above for more details.
I have tried things like
rm -rf node_modules/ yarn.lock package-lock.json && npm install

You could make use of react-test-renderer which you're already using in your project specs. What you need is to call testRenderer.getInstance() => check current state => invoke some methods you need to test => check updated state:
import React from "react";
import { create } from "react-test-renderer";
import { ContextProvider } from "../Context";
describe("ContextProvider", () => {
test("it updates dose correctly", () => {
const component = create(<ContextProvider />);
const instance = component.getInstance();
expect(instance.getDose()).toBe(5);
expect(instance.state.productData.dose).toBe("5 mg");
instance.setDose(2);
expect(instance.getDose()).toBe(2);
expect(instance.state.productData.dose).toBe("2 mg");
});
test("it updates something else correctly", () => {
// ...
});
});
State for other tests won't be affected.
The only thing I needed to make this work with your repo is to npm install whatwg-fetch#2.0.4 --save as described here. Hope this helps.
UPDATE
Even though this is supposed to be another question and the obvious solution is to create a new rn project and copy you code in it, but here is what I've done to fix jest errors on your code:
1) Make versions match (as described in the comments...):
"expo": "^32.0.0",
"jest-expo": "^32.0.0",
// and maybe even
"react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz",
2) To fix an error
api.caller is not a function
use babel.config.js as described here:
module.exports = function(api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
env: {
development: {
plugins: ["transform-react-jsx-source"]
}
}
};
};
3) Use yarn due to this

If you are looking for a replacement for Enzyme, I think you should look here: https://callstack.github.io/react-native-testing-library/
That library will allow you to use the update function provided to change the values you are testing, then change them back.
Great library for React Native - the getting started page says it all. If you are interested in some code to help you get started I can work something up as well.

I suggest that you only unit-test your logic and consider avoiding component tests altogether in this case.
You can extract your methods into a "Presenter" to process your data and only test this logic. With this approach it's easy to test the presenter which has a pure input/output logic.
The presenter, for example, can look like this:
// DosePresenter.js
const processDose = (value, productData) => {
productData.dose = value.toFixed(0) + productData.dose.replace(/[\d\.]*/g, '')
productData.productionTime = Conventions.datetimeStr();
productData.hashSalt = this.makeHashSalt();
return {productData, productDataHash: getHashOfproductData(productData)};
};
module.exports = {
processDose
};
The usage:
// Context.js
import * as DosePresenter from './DosePresenter';
const setDose = (value) => this.setState(DosePresenter.processDose(value, {...this.state}));
Now it should be easier to test the logic:
// DosePresenter.test.js
describe('DosePresenter tests', () => {
let uut;
beforeEach(() => {
uut = require('./DosePresenter');
});
it('should process a dose', () => {
const value = 10;
const productData = {};
expect(uut.processDose(value, productData)).toEqual(...);
});
};

Related

Angular, could someone please explain the Typescript peerDependencies, tslib 1.* vs 2.3.*

I am creating a new angular project but I don't know how to import the localStorage?
i looking to a existing project using localStorage like this
import { Injectable } from '#angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Router } from '#angular/router';
import { AuthenticationService, LoginModel } from '../_libraries/card-system-core';
export class AuthenticationHelper {
//...
constructor(private authService: AuthenticationService, private router: Router) {
this.currentUserSubject = new BehaviorSubject<AuthInfo>(JSON.parse(localStorage.getItem(this.STORAGE_NAME)));
this.currentUserRouteSubject = new BehaviorSubject<RouteInfo[]>(JSON.parse(localStorage.getItem(this.STORAGE_ROUTES_NAME)));
this.currentUser = this.currentUserSubject.asObservable();
this.currentUserRoute = this.currentUserRouteSubject.asObservable();
}
//...
the old project was written in typescript, however when I want to use localStroage in my new project, I having the below error
I expect it will be linked and allow "go to definition" to here
i manage to find there was a line "peerDependencies" in old package.json
"dependencies": {
"tslib": "1.10.0"
},
"devDependencies": {
"ts-node": "~5.0.1",
"tslint": "~6.1.0",
"typescript": "~4.2.4"
},
"peerDependencies": {
"tslib": "1.10.0"
}
but it will not get works in my new project if I use
"peerDependencies": {
"tslib": "2.3.0"
}
until i use 1.10.0 under peerDependencies in my project,
my new project setup as below
"dependencies": {
"tslib": "^2.3.0",
},
"devDependencies": {
"ts-node": "^10.9.1",
"typescript": "~4.7.2"
}
My question is why?
i don't know the relationship between Typescript, peerDependencies and tslib
Why i have to config "tslib": "1.10.0" in peerDependencies to get localStorage work?
Is it not a propper way to call/use localStorage by peerDependencies for "tslib": "2.3.0"?
final i revamp my code as below, thanks bro
let storagedName = localStorage.getItem(this.STORAGE_NAME);
let storagedRouteName = localStorage.getItem(this.STORAGE_ROUTES_NAME);
let emptyUser:AuthInfo = {
accessToken: "",
routes: [],
twoFA: false,
forgotPassword: false,
errorMessage: ""}
this.currentUserSubject = new BehaviorSubject<AuthInfo>(emptyUser);
if(storagedName)
this.currentUserSubject = new BehaviorSubject<AuthInfo>(JSON.parse(storagedName));
this.currentUserRouteSubject = new BehaviorSubject<RouteInfo[]>([]);
if(storagedRouteName)
this.currentUserRouteSubject = new BehaviorSubject<RouteInfo[]>(JSON.parse(storagedRouteName));
The reason is not the package in the peerDependencies.
When you see the error message in vs code it describe you the problem.
The key you use to get the value can be string or null.
But for localstorage is must be string
You can try something like this:
if(this.STORAGES_ROUTES_NAME) {
localStorage.getItem(this.STORAGES_ROUTES_NAME)
}
Or if the variable can't be null then you have to change your declaration of the variable.
Maybe the older version of tslib don't control the variable type and that's why it's working.

Weird console error when vuex action return false

Hy there,
I try to make a custom navigation guard with vue using vuex actions.
The code for the router guard is looking like this:
router.js
{
path: '/authusersonly',
name: 'authusersonly',
component: loadView('authusersonly'),
async beforeEnter (to, from, next) {
try {
let authStatus = await store.dispatch('pingAuth', 'checkAuth')
if (authStatus) next()
else next('/login')
} catch (error) {
console.log(error)
next('/')
}
}
}
The code from store.js file is looking like this
actions: {
async pingAuth ({ commit, state, getters, dispatch }, action) {
let pingStatus = getters.pingStatus
if (!pingStatus) {
// here i do the user check using axios with await axios.......
}
// here i return the results true or false
return false
}
}
The code work perfect but when the pingAuth action return false i get weird console error the user is redirected correctly even when the error appear.
If the pingAuth return true no error is present in the console.
The error is different in firefox and chrome.
Firefox Error
Chrome Error
I have tried to reproduce the issue in a codesandbox but the error doesn't apper. I have also tried the code with a new clean vue project (all dependencies to latest versions) and have the same error.
Can anyone explain why i get this error ?
Thanks a lot in advance.
#vue/cli 4.0.5 on ubuntu 19
package.js
"dependencies": {
"axios": "^0.19.0",
"core-js": "^2.6.5",
"date-fns": "1.29.0",
"register-service-worker": "^1.6.2",
"vue": "^2.6.10",
"vue-i18n": "^8.14.1",
"vue-router": "^3.0.3",
"vuex": "^3.0.1"
},
"devDependencies": {
"#vue/cli-plugin-babel": "^3.12.0",
"#vue/cli-plugin-eslint": "^3.12.0",
"#vue/cli-plugin-pwa": "^3.12.0",
"#vue/cli-service": "^3.12.0",
"#vue/eslint-config-standard": "^4.0.0",
"babel-eslint": "^10.0.1",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0",
"node-sass": "^4.12.0",
"sass-loader": "^8.0.0",
"vue-cli-plugin-vueth": "file:../plugin/",
"vue-template-compiler": "^2.6.10"
}
Edit:
I tried to isolate the problem.
The problem came from router navigation.
I have created a repo for my problem.
git clone https://github.com/thenutz/vue-router-error.git
yarn install
yarn serve
Another interesting thing is if i'm using router-link for navigation no error is present.
I found a fix for this error.
If i use #click="$router.push({ path: '/protected' }).catch((err) => {})" instead of #click="$router.push({ path: '/protected' })" no error is present.
Please check if it's the case. You are visiting the 'login' page and you use next('login') to the same page. So need to determine whether the same page, if so just use 'next()'.

Importing async functions in Javascript

I'm a beginner with Node and Javascript and Puppeteer. Given the following code, in which I'm simply trying to use one function from a different file:
const waitForFrame = require ("../../lib/frames");
const screenshotFolder = 'test/screenshots';
module.exports = async(page) => {
try {
const iframe = await waitForFrame(page);
await iframe.waitForSelector('.competition-response__copy');
await page.waitForSelector({
visible: '.competition-response__copy'
});
const confirmationMessageText = await frame.$eval('.competition-response__copy > p', e => e.textContent);
return confirmationMessageText;
} catch (err) {
await page.screenshot({
path: screenshotFolder + '/saveYourEntryButton.png',
fullPage: true
});
}
And a helper file called:
module.exports = async function waitForFrame(page) { export async
function waitForFrame(page) {
let fulfill;
const promise = new Promise(x => fulfill = x);
checkFrame();
return promise;
function checkFrame() {
const frame = page.frames().find(f => f.name() === 'iframe');
if (frame) {
fulfill(frame)
} else
page.once('frameattached', checkFrame);
}
};
And my package json is as follows:
"engines": {
"node": ">=6"
},
"dependencies": {
"chai": "^4.1.2",
"chai-as-promised": "^7.1.1",
"lodash": "^4.17.10",
"mocha": "^5.2.0",
"puppeteer": "^1.6.2",
"yargs": "^12.0.1",
"express": "^4.16.4",
"supertest": "^3.3.0"
},
"devDependencies": {
"chai": "^4.2.0",
"chai-dom": "^1.8.1",
"mocha": "^5.2.0",
"js-comments": "^0.5.4",
"chai-as-promised": "^7.1.1",
"express": "^4.16.4",
"supertest": "^3.3.0",
}
}
I am receving an error as follows:
import {waitForFrame} from "../../lib/frames";
^
SyntaxError: Unexpected token {
at new Script (vm.js:79:7)
I'm sure this has a beginners error but grateful for a quick pointer. I'm aware there are a number of different methods to import depending on which standards of Javascript you are adhering too.
Thanks
You're trying to use import as native, but this's no still supported on ES6, the problem is not related with async functions but import as an unexpected token, you have some alternatives:
Don't use import orexport and instead use:
const waitForFrame = require("../../lib/frames");
This works very well and is supported in Node 6.
Migrate to Node 10, in that version is supported and you can use it.
Use a Compiler, like babel or any other that works for you, this involve include more dependencies, but then you can use modern APIs on oldest Node versions.
All depends on what you prefer.
Hope this helps you!

Testing React Native apps with Jest

I've been trying to get Jest working with my react native project without much luck. Seems most threads are hacked solutions to get things up and running and I can't seem to get over the last hurdle I'm facing.
Problem
I'm getting the following error when trying to run the following piece of code. If I mock react-native inside of the jestSupport/env.js file I can get past the error but obviously I cannot use any of the structures such as AsyncStorage to actually test my code (as I'll only have the mocked functionality).
Question
Does anyone have any suggestions on how to solve this problem?
At this stage I'm willing to try anything up to and including scrapping everything test related that I have and trying again. If that were the case, I'd need some set of guidelines to follow as the React Native docs are horribly out of date regarding Jest and I'm relatively new to the React scene.
Error
Runtime Error
Error: Cannot find module 'ReactNative' from 'react-native.js'
at Runtime._resolveNodeModule (/Users/Yulfy/Downloads/COMPANY-Mobile/node_modules/jest-cli/src/Runtime/Runtime.js:451:11)
at Object.<anonymous> (/Users/Yulfy/Downloads/COMPANY-Mobile/node_modules/react-native/Libraries/react-native/react-native.js:181:25)
at Object.<anonymous> (/Users/Yulfy/Downloads/COMPANY-Mobile/network/connections.js:8:18)
Test Code
jest.unmock('../network/connections');
import Authorisation from '../network/connections';
describe('connections', () => {
it('Should store and retrieve a mocked user object', () => {
Auth = new Authorisation();
const TEST_STRING = "CONNECTION TEST PASS";
var userObj = {
test_string: TEST_STRING
};
Auth._localStore(userObj, (storeRes) => {
Auth._localRetrieve((retRes) => {
expect(retRes.test_string).toEqual(TEST_STRING);
});
});
});
});
connection.js
/*
* All returns should give the following structure:
* {isSuccess: boolean, data: object}
*/
import React, { Component } from 'react';
import { AsyncStorage } from 'react-native';
const Firebase = require('firebase');
const FIREBASE_URL = 'https://COMPANY-test.firebaseio.com';
const STORAGE_KEY = 'USER_DATA';
class Authorisation{
_ref = null;
user = null;
constructor(){
}
getOne(){return 1;}
_setSystemUser(userObj, authObj, callback){
var ref = this.connect();
if(ref === null){
callback({isSuccess:false, data:{message:"Could not connect to the server"}});
}
ref = ref.child('users').child(authObj.uid);
ref.once("value", function(snapshot){
if(snapshot.exists()){
callback({isSuccess:false, data:{message:"Email is currently in use"}});
return;
}
ref.set(userObj, function(error){
if(error){
callback({isSuccess:false, data:error});
}else{
callback({isSuccess:true, data:authObj});
}
});
});
}
_localStore(userObj, callback){
AsyncStorage.setItem(STORAGE_KEY, userObj, (error) => {
console.log("_localStore::setItem -> ", error);
if(error){
callback({
isSuccess:false,
data:'Failed to store user object in storage.'
});
}else{
callback({
isSuccess:true,
data: userObj
});
}
});
}
_localRetrieve(callback){
AsyncStorage.getItem(STORAGE_KEY, (error, res) => {
console.log("_localStore::getItem:error -> ", error);
console.log("_localStore::getItem:result -> ", res);
if(error){
callback({
isSuccess:false,
data:error
});
}else{
callback({
isSuccess: true,
data: res
});
}
});
}
connect(){
if(this._ref === null){
_ref = new Firebase(FIREBASE_URL);
}
return _ref;
}
getUser(){
}
isLoggedIn(){
}
registerUser(userObj, callback){
var ref = this.connect();
if(ref === null){
callback({isSuccess:false, data:{message:"Could not connect to the server"}});
}
var that = this;
ref.createUser({
email: userObj.username,
password: userObj.password
}, function(error, userData){
if(error){
callback({isSuccess:false, data:error});
return;
}
var parseObj = {
email: userObj.username,
fullName: userObj.fullName
};
that.loginUser(parseObj, function(res){
if(res.isSuccess){
that._setSystemUser(parseObj, res.data, callback);
}else{
callback(res);//Fail
}
});
});
}
loginUser(userObj, callback){
var ref = this.connect();
if(ref === null){
callback({isSuccess:false, data:{message:"Could not connect to the server"}});
}
ref.authWithPassword({
email: userObj.email,
password: userObj.password
}, function(error, authData){
if(error){
callback({isSuccess:false, data:error.message});
}else{
callback({isSuccess:true, data:authData});
}
});
}
}
export default Authorisation;
If you've read this far, thanks for your time!
-Yulfy
TL;DR
I have a working example of Jest running with the latest version React Native (v0.28.0) in this GitHub Repo.
-
After investigating this problem for quite some time, I finally found the solution.
There are a few online examples of React Native applications that are integrated with Jest, but you can't simply copy and paste the code into your codebase and expect it to work, unfortunately. This is because of RN version differences.
Versions of React Native prior to v0.20.0 contained a .babelrc file in the packager (node_modules/react-native/packager/react-packager/.babelrc) that some online examples directly include it in their package.json. However, versions v0.20.0 and up changed to no longer include this file which means that you can no longer attempt to include it. Because of this, I recommend using your own .babelrc file and definte your own presets and plugins.
I don't know what your package.json file looks like, but it's an incredibly important piece to solving this problem.
{
"name": "ReactNativeJest",
"version": "0.0.1",
"jest": {
"scriptPreprocessor": "<rootDir>/node_modules/babel-jest",
"unmockedModulePathPatterns": [
"node_modules"
],
"verbose": true,
"collectCoverage": true
},
"scripts": {
"test": "jest"
},
"dependencies": {
"react": "^15.1.0",
"react-native": "^0.27.2"
},
"devDependencies": {
"babel-core": "^6.4.5",
"babel-jest": "^12.1.0",
"babel-plugin-transform-regenerator": "^6.0.18",
"babel-polyfill": "^6.0.16",
"babel-preset-react-native": "^1.9.0",
"babel-types": "^6.1.2",
"chai": "^3.5.0",
"enzyme": "^2.3.0",
"jest-cli": "^12.1.1",
"react-addons-test-utils": "^15.1.0",
"react-dom": "^15.1.0"
}
}
The other important piece is mocking React Native. I created a __mocks__/react-native.js file that looks like this:
'use strict';
var React = require('react');
var ReactNative = React;
ReactNative.StyleSheet = {
create: function(styles) {
return styles;
}
};
class View extends React.Component {}
class Text extends React.Component {}
class TouchableHighlight extends React.Component {}
// Continue to patch other components as you need them
ReactNative.View = View;
ReactNative.Text = Text;
ReactNative.TouchableHighlight = TouchableHighlight;
module.exports = ReactNative;
By monkey patching the React Native functions like this, you can successfully avoid the weird Jest errors you get when trying to run your tests.
Finally, make sure you create a .babelrc file in your project's root directory that has, at the very least, these following lines:
{
"presets": ["react-native"],
"plugins": [
"transform-regenerator"
]
}
This file will be used to tell babel how to correctly transform your ES6 code.
After following this setup, you should have no problems running Jest with React Native. I am confident that a future version of React Native will make it easier to integrate the two frameworks together, but this technique will work perfectly for the current version :)
EDIT
Instead of manually mocking the ReactNative elements in your __mocks__/react-native.js file, you can use the react-native-mock library to do the mocking for you (make sure to add the library to your package.json file):
// __mocks__/react-native.js
module.exports = require('react-native-mock');
I updated my GitHub Repo example to demonstrate this method.
Did you tried to mock react-native inside of test file?
It works fine for my test case:
jest.dontMock(`../my-module-that-uses React-native.AsyncStorage`);
jest.setMock(`react-native`, {
AsyncStorage: {
multiGet: jest.fn(),
},
});
const ReactNative = require(`react-native`);
const {AsyncStorage, } = ReactNative;
const myModule = require(`../my-module-that-uses React-native.AsyncStorage`);
// Do some tests and assert ReactNative.AsyncStorage.multiGet calls

How to unit test React JSX ES6 code with KARMA?

I've written my React app with ES6. Now I would like to write my tests also with ES6. So the challenge here is to configure karma.
Together with google I came this far with karma.config.js (I've omitted parts of the config file which are the same!):
...
files: [
'../node_modules/karma-babel-preprocessor/node_modules/babel-core/browser-polyfill.js',
'../app/**/*.jsx',
'../test/**/*.jsx'],
preprocessors: {
'app/**/*.jsx': ['react-jsx', 'babel'],
'test/**/*.jsx': ['react-jsx', 'babel']
},
'babelPreprocessor': {
options: {
sourceMap: 'inline'
},
filename: function(file) {
return file.originalPath.replace(/\.jsx$/, '.es5.js');
},
sourceFileName: function(file) {
return file.originalPath;
}
},
....
What I think this setup should do: 1) compile the JSX to JS and next babel should transform ES6 to ES5. This together with the polyfill I expected it should run in phantomjs for example. But no, here is the output from karma when I run it:
PhantomJS 1.9.8 (Mac OS X) ERROR
SyntaxError: Parse error
at Projects/ES6/app/js/app.jsx:35
PhantomJS 1.9.8 (Mac OS X): Executed 0 of 0 ERROR (0.027 secs / 0 secs)
[20:36:59] Karma has exited with 1
Line 35 of app.jsx contains the actual JSX part. So, for some reason the preprocessors seems to do not so much. Any help with the preprocessors would be appreciated ?
UPDATE: I have this almost working nog. Turns out that the preprocessors I had should be swapped like this
'../app/**/*.jsx': ['babel', 'react'],
'../test/**/*.jsx': ['babel', 'react']
Now, when I run this, I get:
Uncaught ReferenceError: require is not defined
I thought I had a polyfill for that :(
I use ES6 with Browserify and JSX. For compilation I use Babel. The following configuration works for me.
karma.conf.js
...
frameworks: ['browserify', 'jasmine'],
files: [
'Component.js', // replace with your component
'__tests__/Component-test.js'
],
preprocessors: {
'Component.js': 'browserify',
'./__tests__/Component-test.js': 'browserify'
},
browserify : {
transform : ['babelify']
},
...
__tests__/Component-test.js
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
var Component = require('../Component.js');
describe('Component', () => {
it('should work', () => {
var component = <Component />;
TestUtils.renderIntoDocument(component);
expect(component).toBeTruthy();
});
});
If you have any questions let me know.
#zemirico answer did not work for me and is slightly outdated.
Here is my own setup that you can use for karma.conf.js:
...
frameworks: ['jasmine', 'browserify'],
files: [
'src/*',
'tests/*'
],
preprocessors: {
'src/*': ['browserify'],
'tests/*': ['browserify']
},
browserify: {
debug: true,
transform: ['babelify']
}
...
It uses babelify instead of reactify, and has other dependencies. Thus, .babelrc in the project root is also needed:
{
presets: ['es2015', 'react']
}
The setup also requires the dependencies below to be included in package.json file:
"devDependencies": {
"babel-preset-react": "^6.5.0",
"babelify": "^7.2.0",
"browserify": "^13.0.0",
"jasmine-core": "^2.4.1",
"karma": "^0.13.22",
"karma-browserify": "^5.0.3",
"karma-chrome-launcher": "^0.2.3",
"karma-jasmine": "^0.3.8",
"watchify": "^3.7.0",
"babel-preset-es2015": "^6.6.0",
"react": "^15.0.1",
"react-addons-test-utils": "^15.0.1",
"react-dom": "^15.0.1"
}
Usage
Create a new React component in src/my-element.jsx:
import React from 'react';
export default class MyElement extends React.Component {
constructor(props) {
super(props);
this.state = {isActive: false};
this.onClick = this.onClick.bind(this);
}
onClick() {
this.setState({isActive: !this.state.isActive});
}
render() {
return (
<div onClick={this.onClick}>{this.state.isActive ? "I am active!" : "I am not active :("}</div>
);
}
}
Then, test it as such by creating spec in tests/my-element-spec.js:
import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-addons-test-utils';
import MyElement from '../src/my-element.jsx';
describe('MyElement', () => {
// Render a checkbox with label in the document
const element = TestUtils.renderIntoDocument(<MyElement />);
const elementNode = ReactDOM.findDOMNode(element);
it('verity correct default text', () => {
expect(elementNode.textContent).toEqual('I am not active :(');
});
it ('verify text has been changed successfuly after click', () => {
// Simulate a click and verify that it is now On
TestUtils.Simulate.click(elementNode);
// Verify text has been changed successfully
expect(elementNode.textContent).toEqual('I am active!');
});
});
Demo
Working example on GitHub.

Categories