Skip to content

Commit

Permalink
Replacing karma+mocha with jest+enzyme. (#4162)
Browse files Browse the repository at this point in the history
* Replacing karma+mocha with jest+enzyme.

This change is:

  * Replacing previously little used karma + mocha with jest + enzyme,
which allows us to do snapshot testing
  * Updating enzyme
  * Converting existing tests to work with jest
  * Making maven run jest for tests
  * Establishing consistent directory structure for tests (tests for
`src/foo/bar/Baz.jsx` are in `test/foo/bar/Baz.test.js`)

* Adding mocking helpers.

* Adding default rules parameter value, correcting condition.

* Putting tests next to components under test.

(cherry picked from commit 14218bc)
  • Loading branch information
dennisoelkers authored and Edmundo Alvarez committed Sep 29, 2017
1 parent 6db7ae3 commit e994dd2
Show file tree
Hide file tree
Showing 33 changed files with 826 additions and 5,435 deletions.
11 changes: 11 additions & 0 deletions graylog2-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,17 @@
<arguments>run build</arguments>
</configuration>
</execution>

<execution>
<id>npm test</id>
<goals>
<goal>npm</goal>
</goals>
<phase>test</phase>
<configuration>
<arguments>test</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
Expand Down
10 changes: 0 additions & 10 deletions graylog2-web-interface/karma.ci.conf.js

This file was deleted.

10 changes: 0 additions & 10 deletions graylog2-web-interface/karma.dev.conf.js

This file was deleted.

58 changes: 0 additions & 58 deletions graylog2-web-interface/karma.shared.js

This file was deleted.

47 changes: 36 additions & 11 deletions graylog2-web-interface/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,35 @@
"start": "webpack-dev-server --config webpack.bundled.js --history-api-fallback --hot --inline",
"start-nohmr": "webpack-dev-server --watch --history-api-fallback --config webpack.bundled.js",
"build": "disable_plugins=true webpack --config webpack.bundled.js",
"test": "webpack --config webpack.vendor.js && karma start karma.ci.conf.js",
"prepare-dev": "./tools/prepare-dev",
"lint": "eslint --ext js,jsx src"
"lint": "eslint --ext js,jsx src",
"test": "jest"
},
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx,ts,tsx}"
],
"setupFiles": [
"jest-localstorage-mock"
],
"setupTestFrameworkScriptFile": "./node_modules/jest-enzyme/lib/index.js",
"moduleDirectories": [
"src",
"test",
"node_modules"
],
"moduleFileExtensions": [
"js",
"jsx",
"ts"
],
"moduleNameMapper": {
"\\.(css|less)$": "identity-obj-proxy"
},
"transform": {
"^.+\\.jsx?$": "<rootDir>/node_modules/babel-jest",
"^.+\\.tsx?$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
}
},
"dependencies": {
"bluebird": "^3.4.0",
Expand Down Expand Up @@ -65,6 +91,7 @@
"@types/typeahead": "^0.11.29",
"assets-webpack-plugin": "^3.5.1",
"babel-core": "^6.22.1",
"babel-jest": "^21.0.2",
"babel-loader": "^7.0.0",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-polyfill": "^6.22.0",
Expand All @@ -73,29 +100,27 @@
"babel-preset-stage-0": "^6.22.0",
"clean-webpack-plugin": "^0.1.3",
"css-loader": "^0.28.4",
"enzyme": "^2.0.0",
"enzyme": "^2.9.0",
"eslint": "^4.3.0",
"eslint-loader": "^1.6.3",
"estraverse-fb": "^1.3.1",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^0.11.0",
"glob": "^7.0.0",
"jasmine-core": "*",
"identity-obj-proxy": "^3.0.0",
"jest": "^21.1.0",
"jest-enzyme": "^3.8.3",
"jest-localstorage-mock": "^2.0.0",
"json-loader": "^0.5.3",
"karma": "^1.1.2",
"karma-chrome-launcher": "*",
"karma-html2js-preprocessor": "*",
"karma-jasmine": "*",
"karma-phantomjs-launcher": "*",
"karma-webpack": "*",
"less": "^2.5.3",
"less-loader": "^4.0.5",
"mocha": "^2.3.4",
"phantomjs-prebuilt": ">=1.9",
"react-hot-loader": "^3.0.0-beta.6",
"react-proxy-loader": "^0.3.4",
"react-test-renderer": "^15.6.1",
"script-loader": "^0.7.0",
"style-loader": "^0.18.2",
"ts-jest": "^21.0.1",
"ts-loader": "^2.3.1",
"typescript": "^2.4.2",
"url-loader": "^0.5.6",
Expand Down
24 changes: 9 additions & 15 deletions graylog2-web-interface/src/components/common/Spinner.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
import PropTypes from 'prop-types';
import React from 'react';
import PropTypes from 'prop-types';

const Spinner = ({ text }) => <span><i className="fa fa-spin fa-spinner" /> {text}</span>;

const Spinner = React.createClass({
propTypes: {
text: PropTypes.string,
},
getDefaultProps() {
return { text: 'Loading...' };
},
getInitialState() {
return {};
},
render() {
return (<span><i className="fa fa-spin fa-spinner" /> {this.props.text}</span>);
},
});
Spinner.propTypes = {
text: PropTypes.string,
};
Spinner.defaultProps = {
text: 'Loading...',
};

export default Spinner;
18 changes: 18 additions & 0 deletions graylog2-web-interface/src/components/common/Spinner.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';
import renderer from 'react-test-renderer';

import Spinner from 'components/common/Spinner';

describe('<Spinner />', () => {
it('should render without props', () => {
const wrapper = renderer.create(<Spinner />);
expect(wrapper.toJSON()).toMatchSnapshot();
});

it('should render with a different text string', () => {
const text = 'Hello world!';
const wrapper = renderer.create(<Spinner text={text}/>);
expect(wrapper.toJSON()).toMatchSnapshot();
});

});
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<Spinner /> should render with a different text string 1`] = `
<span>
<i
className="fa fa-spin fa-spinner"
/>
Hello world!
</span>
`;

exports[`<Spinner /> should render without props 1`] = `
<span>
<i
className="fa fa-spin fa-spinner"
/>
Loading...
</span>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';

import { CombinedProviderMock, StoreMock } from 'helpers/mocking';

describe('UserPreferencesButton', function () {
beforeEach(() => {
jest.resetModules();
});

it('should load user data when user clicks edit button', function () {
const PreferencesStore = StoreMock('get', 'listen', 'loadUserPreferences');
const combinedProviderMock = new CombinedProviderMock({
Preferences: { PreferencesStore },
});

jest.doMock('injection/CombinedProvider', () => combinedProviderMock);

const UserPreferencesButton = require('components/users/UserPreferencesButton');
const userName = 'Full';
const instance = require('enzyme').mount(<UserPreferencesButton userName={userName} />);

expect(instance).toMatchSnapshot();
expect(instance.find('button')).toBeDefined();

instance.find('button').simulate('click');

expect(PreferencesStore.loadUserPreferences).toBeCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`UserPreferencesButton should load user data when user clicks edit button 1`] = `
<UserPreferencesButton
userName="Full"
>
<span>
<Button
active={false}
block={false}
bsClass="btn"
bsStyle="success"
disabled={false}
onClick={[Function]}
>
<button
className="btn btn-success"
disabled={false}
onClick={[Function]}
type="button"
>
User preferences
</button>
</Button>
<UserPreferencesModal
userName="Full"
>
<BootstrapModalForm
cancelButtonText="Cancel"
formProps={Object {}}
onSubmitForm={[Function]}
submitButtonDisabled={false}
submitButtonText="Save"
title="Preferences for user Full"
>
<BootstrapModalWrapper
onHide={[Function]}
>
<Modal
animation={true}
autoFocus={true}
backdrop={true}
bsClass="modal"
dialogComponentClass={[Function]}
enforceFocus={true}
keyboard={true}
manager={
ModalManager {
"containers": Array [],
"data": Array [],
"handleContainerOverflow": true,
"hideSiblingNodes": true,
"modals": Array [],
}
}
onHide={[Function]}
renderBackdrop={[Function]}
restoreFocus={true}
show={false}
>
<Modal
autoFocus={true}
backdrop={true}
backdropClassName="modal-backdrop"
backdropTransitionTimeout={150}
containerClassName="modal-open"
dialogTransitionTimeout={300}
enforceFocus={true}
keyboard={true}
manager={
ModalManager {
"containers": Array [],
"data": Array [],
"handleContainerOverflow": true,
"hideSiblingNodes": true,
"modals": Array [],
}
}
onEntering={[Function]}
onExited={[Function]}
onHide={[Function]}
renderBackdrop={[Function]}
restoreFocus={true}
show={false}
transition={[Function]}
/>
</Modal>
</BootstrapModalWrapper>
</BootstrapModalForm>
</UserPreferencesModal>
</span>
</UserPreferencesButton>
`;
Loading

0 comments on commit e994dd2

Please sign in to comment.