@theforeman/test
v13.1.0
Published
Test utils for theforeman
Downloads
4,927
Readme
@theforeman/test
Adds theforeman testing tools to you project.
Installation
npm install --save-dev @theforeman/test
- Use
tfm-test
andtfm-publish-coverage
(for coverage) scripts undertest
andpublish-coverage
respectively inpackage.json
:
{
"test": "tfm-test --plugin",
"publish-coverage": "tfm-publish-coverage"
}
This script accepts all jest's arguments, including plugin
which is a flag indicator for plugins.
Configuration
In order to extend general settings or creating global mocks, create a test_setup.js
file under /webpack
directory
For example, some global mocks :
// test_setup.js
jest.mock("jed");
jest.mock("./assets/javascripts/react_app/common/I18n");
jest.mock("./assets/javascripts/foreman_tools", () => ({
foremanUrl: url => url
}));
Usage
This package gives an opiniated approach for test configurations and tools, including jest, enzyme, react-testing-library, and a test utils library.
These functions can be imported directly from @theforeman/test
:
mount
and shallow
- which are from enzyme
testComponentSnapshotsWithFixtures
testReducerSnapshotWithFixtures
,
testActionSnapshotWithFixtures
testSelectorsSnapshotWithFixtures
,
IntegrationTestHelper
- which are from react-redux-test-utils
MockAdapter
- which is from axios-mock-adapter
and also adding coveralls
for coverage.
Unit testing
You can use testComponentSnapshotsWithFixtures
for a unit testing without redux.
Keep in mind to import unconnected component (wrapped by connect
nor redux-hooks)
/* UserProfile.test.js */
import { testComponentSnapshotsWithFixtures } from "@theforeman/test";
import UserProfile from "../UserProfile"; // not redux connected
const fixtures = {
"should render UserProfile": {
user: "some-user"
},
"should render UserProfile with avatar": {
user: "some-user",
showAvatar: true
},
"should render UserProfile with posts and photos": {
user: "some-user",
showPosts: true,
showPhotos: true
}
};
describe("UserProfile - component", () =>
testComponentSnapshotsWithFixtures(UserProfile, fixtures));
Redux's Actions
This will create a snapshot for UserProfileActions.js
actions file:
/* UserProfileActions.test.js */
import { testActionSnapshotWithFixtures } from '@theforeman/test';
import {
updateShowAvatar,
updateShowPosts,
updateShowPhotos
} from "../UserProfileActions";
const fixtures = {
"should update-show-avatar": () => updateShowAvatar(true),
"should update-show-posts": () => updateShowPosts(true),
"should update-show-photos": () => updateShowPhotos(true)
};
describe("UserProfile - Actions", () =>
testActionSnapshotWithFixtures(fixtures));
For async actions and further explanation please look here
Redcuer's Testing
testReducerSnapshotWithFixtures
creates a snapshot of a given reducer and fixtures:
/* LoginFormReducer.test.js */
import { testReducerSnapshotWithFixtures } from '@theforeman/test';
import {
LOGIN_FORM_UPDATE_USERNAME,
LOGIN_FORM_UPDATE_PASSWORD,
LOGIN_FORM_TOGGLE_REMEMBER_ME,
} from '../LoginFormConstants';
import reducer from '../LoginFormReducer';
const fixtures = {
'it should update username': {
action: {
type: LOGIN_FORM_UPDATE_USERNAME,
payload: { username: 'some-username' }
}
},
'it should update password': {
action: {
type: LOGIN_FORM_UPDATE_PASSWORD,
payload: { password: 'some-password' }
}
},
'it should toggle remember-me': {
state: { rememberMe: false },
action: {
type: LOGIN_FORM_TOGGLE_REMEMBER_ME,
}
},
};
describe('LoginForm - Reducer', () =>
testReducerSnapshotWithFixtures(reducer, fixtures));
Integration testing
This test a full cycle of a component including redux (actions, reducers and store)
/* __tests__/integration.test.js */
import React from 'react';
import { IntegrationTestHelper } from '@theforeman/test';
import UserProfile, { reducers } from '../index'; // This is a connected component
describe('UserProfile - Integration Test', () => {
it('should flow', () => {
const integrationTestHelper = new IntegrationTestHelper(reducers);
const component = integrationTestHelper.mount(
<UserProfile user="some-user" />
);
// The user-avatar should not be shown
expect(component.exists('UserAvatar')).toEqual(false);
integrationTestHelper.takeStoreSnapshot('initial state');
// trigger checkbox change
component
.find('input#show-avatar-toggler')
.simulate('change', { target: { checked: true } });
// The user-avatar should be shown now
expect(component.exists('UserAvatar')).toEqual(true);
integrationTestHelper.takeStoreAndLastActionSnapshot(
'Update to show the user-avatar'
);
});
});
Functional Testing
The package react-testing-library
is included and is a way to test functionality in a React application from a user perspective rather than testing the implementation. To use this library, please see the official documentation. It can be imported directly from @testing-library/react
.
This approach is flexible and can be used to test smaller components as well as full pages made up of many components. For functional testing, it is recommended to test components connected to redux and mock the http calls, allowing the component to function as it does in the production application. These tests also tend to be less brittle than other approaches and can be good at catching regressions when refactoring.
For an example of how this is library is used within the Foreman ecosystem, please see Katello's react-testing-library-wrapper
Contributing
Please checkout the contributing.md
, the roadmap.md
and the open issues.