Atlassian uses cookies to improve your browsing experience, perform analytics and research, and conduct advertising. Accept all cookies to indicate that you agree to our use of cookies on your device. Atlassian cookies and tracking notice, (opens new window)
When testing React and Angular OWA, we will create a mock webservice to test requests to the database. This is useful so that we can test our code without having to be connected to an online webservice. We see a mock webservice being created in an example test cases below. For React OWAs, in addition to testing database request, tests are usually made for proper rendering and state changes.
Choose your test type
Depending on what you selected when building your web app, you will either use React or Angular to test your OWA. Below are examples of each test type that you can use for your web app.
Your test file(s) should be stored as yourOWAfolder/test/exampleTest.js.
React (With Redux)
React OpenMRS Open Web Apps primarily use the framework Jest for its unit testing. Setting up Jest can be found here.
*All examples below are credited towards the Order Entry UIModule*
Testing Actions
When testing an action, the objective is to dispatch a function into a mock store and compare the action it dispatched to what action you expected. Your function will likely make request to a database and this can be tested by mocking a request. The example below uses moxios to mock axios request. The response of the request will determine what action is dispatched.
When testing a component, the objective is to check if the reducers change the application state as intended given a specific action. Your function will most likely compare two states. This example below creates an action and initial state then passes them to the reducer.
import createOrderReducer from '../../app/js/reducers/createOrderReducer';
describe('createOrder reducer test suite', () => {
const initialState = {
labOrderData: {},
errorMessage: '',
status: {
error: false,
added: true,
},
};
it(`sets status key error to true and sets key errorMessage to
error message from payload on action type SAVE_DRAFT_LAB_ORDER_FAILURE `, () => {
const action = {
type: 'SAVE_DRAFT_LAB_ORDER_FAILURE',
payload: 'Invalid data',
};
expect(createOrderReducer(initialState, action)).toEqual({
...initialState,
errorMessage: 'Invalid data',
status: {
added: false,
error: true,
},
});
});
it(`parses data from payload to key labOrderData and sets staus key
added to true on action type SAVE_DRAFT_LAB_ORDER_SUCCESS `, () => {
const data = {
id: 1,
name: 'Lab order',
description: 'amoxycillinn tests',
};
const action = {
type: 'SAVE_DRAFT_LAB_ORDER_SUCCESS',
data,
};
expect(createOrderReducer(initialState, action)).toEqual({
...initialState,
labOrderData: action.data,
status: {
error: false,
added: true,
},
});
});
it('returns initial state if action type is not handled', () => {
const action = {
type: 'SAVE_DRAFT_LAB_ORDER',
};
expect(createOrderReducer(initialState, action)).toEqual(initialState);
});
it('should handle SAVE_DRAFT_LAB_ORDER_LOADING', () => {
const action = {
type: 'SAVE_DRAFT_LAB_ORDER_LOADING',
};
const mockState = createOrderReducer(initialState, action)
expect(mockState.status.loading).toEqual(true);
});
});
Setup
OpenMRS React OWA typically have a setup file for test to handle import that will be used across all tests. This is to help abide by DRY and avoid repetitive code. An example of this is shown below:
Order Entry UI's test setup file
import expect from 'expect';
import thunk from 'redux-thunk';
import configureMockStore from 'redux-mock-store';
import { configure, shallow, render, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import sinon from 'sinon';
import moxios from 'moxios';
import axios from 'axios'
import promiseMiddleware from 'redux-promise-middleware'
import axiosInstance from '../app/js/config'
import mockData from '../__mocks__/mockData';
import locationMock from '../__mocks__/locationMock';
import store from '../app/js/redux-store';
process.env.NODE_ENV = 'test';
// React 16 Enzyme adapter
configure({ adapter: new Adapter() });
const promiseTypeSuffixes = ['LOADING', 'SUCCESS', 'FAILURE'];
const middlewares = [thunk, promiseMiddleware({promiseTypeSuffixes})];
const mockStore = configureMockStore(middlewares);
const reader = new FileReader();
moxios.install(axiosInstance)
const contextPath = window.location.href.split('/')[3];
const apiBaseUrl = `/${contextPath}/ws/rest/v1`;
require.extensions['.css'] = () => null;
require.extensions['.png'] = () => null;
require.extensions['.jpg'] = () => null;
global.expect = expect;
global.mockData = mockData;
global.locationMock = locationMock;
global.store = store;
global.apiBaseUrl = apiBaseUrl;
global.moxios = moxios;
global.mount = mount;
global.sinon = sinon;
global.shallow = shallow;
global.mockStore = mockStore;
global.navigator = {
userAgent: 'node.js'
};
global.document = document;
var documentRef = document;
In order to properly run tests and apply the setup file, Jest needs to be configured. An example configuration file is shown below:
Angular OpenMRS Open Web Apps also primarily use the framework Jasmine and the test runner Karma for its unit testing. To set up our mock backend, we use $httpbackend service. $httpbackend has the method whenGet that will create a new GET request. There needs to be enough whenGet calls that will receive all of the information that your controller expects. $rootScope needs to be created before each spec to observe model changes. $componentController creates an instance of a controller. Make sure you have the name of controller that you are testing in the parameters.
Example 1: Querying for an encounter
"use strict";
import '../app/js/home/home';
// The describe is a function that represents a test suite. This should encompasses tests that verify any behaviors of a component.
describe('component: encounterComponent', () => {
// The beforeEach is a function that is called before each spec ("it" function).
beforeEach(angular.mock.module('home'));
let component, scope, $componentController, $httpBackend;
// Defining mock data as encounterList
let encounterList = {
"results":[{
"uuid": "6ff4d871-a529-4b88-9cb9-761cf3c35136",
"display": "Vitals 31/12/2015",
"links": [
{
"rel": "self",
"uri": "http://localhost:8081/openmrs-standalone/ws/rest/v1/encounter/6ff4d871-a529-4b88-9cb9-761cf3c35136"
}
]
}]
};
let emptyResult = {
"results": []
}
beforeEach(inject((_$httpBackend_, $rootScope, _$componentController_) => {
$httpBackend = _$httpBackend_;
$httpBackend.whenGET(/translation.*/).respond();
$httpBackend.whenGET('manifest.webapp').respond(500, "");
$httpBackend.whenGET('/ws/rest/v1/encounter?includeAll=true&q=john&v=full').respond(encounterList);
$httpBackend.whenGET('/ws/rest/v1/encounter?q=john').respond(encounterList);
$httpBackend.whenGET('/ws/rest/v1/encounter?includeAll=true&q=Matt&v=full').respond(emptyResult);
scope = $rootScope.$new();
$componentController = _$componentController_;
}));
// The it function represent a spec.
it('Rest call should return the required json file', () => {
component = $componentController('encounterComponent',
{
$scope: scope
}
);
component.query = 'john';
component.onsearch();
$httpBackend.flush();
expect(component.encounters).toEqual(encounterList.results);
})
// Test case 2.
it('Rest call should return the required json file', () => {
component = $componentController('encounterComponent',
{
$scope: scope
}
);
component.query = 'Matt';
component.onsearch();
$httpBackend.flush();
expect(component.encounters).toEqual(emptyResult.results);
})
});
In the root of your project directory, run the command:
Run Tests Only
npm run test
Build Project and Run Tests
npm run build:prod
Troubleshooting
Angular Owa Fails to Run Tests and Build after Generating OWA
This is a potential fix for this error message:
component: encounterComponent Rest call should return the required json file FAILED
Error: [$injector:modulerr] Failed to instantiate module home due to:
Error: [$injector:modulerr] Failed to instantiate module openmrs-contrib-uicommons due to:
Error: [$injector:modulerr] Failed to instantiate module openmrs-contrib-uicommons.concept-autoComplete due to:
Error: [$injector:modulerr] Failed to instantiate module ngSanitize due to:
TypeError: a is not a function
1) Open package.json which is in your OWA's root folder, and under dependencies, remove the "^" before the version number of each following Angular dependency: angular, angular-route, and angular-mocks.
2) In the root of your project directory, run the command:
Install Correct Angular Dependencies
npm install
3) In home.js of your project remove this code:
.config(['$qProvider', function ($qProvider) {
$qProvider.errorOnUnhandledRejections(false);
}])