Skip to content

Commit

Permalink
Unit testing with Jest
Browse files Browse the repository at this point in the history
Current global test coverage:
- Statements: 59.29%
- Branches: 60.61%
- Functions: 64.55%
- Lines: 63.26%
  • Loading branch information
birdofpreyru committed Mar 29, 2017
1 parent 97e205f commit 49dd259
Show file tree
Hide file tree
Showing 55 changed files with 2,204 additions and 55 deletions.
4 changes: 3 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
"containers": "./containers",
"reducers": "./reducers",
"routes": "./routes",
"server": "./server",
"services": "./services",
"utils": "./utils"
},
"extensions": [".js", ".jsx"],
"root": [
"./src/shared"
"./src/shared",
"./src"
]
}],
["react-css-modules", {
Expand Down
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
__coverage__
build
node_modules
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pids
lib-cov

# Coverage directory used by tools like istanbul
__coverage__
coverage

# nyc test coverage
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ To control code quality we have set up ESLint for .js/.jsx (AirBnB style), and S

StyleFmt is installed as dev dependency of the project. This tool can automatically fix many lint errors in `.scss` files, to fit them into our Stylelint rules. It can help when you move styling from other projects into this repo. Run the tool with `$ npm run fix:styles`.

To run unit tests use `$ npm run jest`, also you can `$ npm test` to run both the linter and the unit-tests.

To run development build of the App against development Topcoder backend do `$ npm run dev` and access website as `local.topcoder-dev.com:3000`. Prior doing this you should add into your `/etc/hosts` the line `127.0.0.1 local.topcoder-dev.com:3000`. In this case you'll have all development bells and whistles enabled, like Redux DevTools, hot module reloading, etc. To access pages which need Topcoder authentication use `accounts.topcoder-dev.com/members` to login, and just wipe out your cookies for the page to log out.

To run production build of the App against production Topcoder backend do `$ npm run build` to build the bundle, then `$ PORT=80 npm start` to run the server at port #80. In this case you should access the site as `local.topcoder.com`. Prior doing this you should add into your `/etc/hosts` the line `127.0.0.1 local.topcoder.com`. You should also allow the App to listen on the port 80. The easiest way to do it on Ubuntu 16.04 is (no guarantees, how safe is it):
Expand Down
11 changes: 11 additions & 0 deletions __tests__/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"env": {
"jest/globals": true
},
"plugins": [
"jest"
],
"rules": {
"global-require": 0
}
}
34 changes: 34 additions & 0 deletions __tests__/client/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* eslint-env browser */

/* eslint-disable import/no-dynamic-require */
const MODULE = '../../src/client';

window.CONFIG = {
ACCOUNTS_APP_CONNECT_URL: 'https://dummy.url',
COOKIES: {
MAXAGE: 7,
SECURE: false,
},
};

jest.setMock('browser-cookies', {
erase: () => {},
get: () => 'Dummy cookie',
set: () => {},
});

jest.setMock('tc-accounts', {
configureConnector: () => undefined,
decodeToken: () => 'Decoded user object',
getFreshToken: () => Promise.resolve('Dummy token'),
});

test('should not start without process.env.FRONT_END evaluating true', () => {
expect(() => require(MODULE)).toThrow();
});

test('should start whit process.env.FRONT_END evaluating true', () => {
jest.resetModules();
process.env.FRONT_END = true;
require(MODULE);
});
12 changes: 12 additions & 0 deletions __tests__/server/renderer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
jest.setMock('react-dom/server', {
renderToString: () => 'RENDER',
});

const renderer = require('server/renderer').default;

test('should not throw errors', () => {
const res = {
send: () => {},
};
expect(() => renderer(undefined, res)).not.toThrow();
});
22 changes: 22 additions & 0 deletions __tests__/shared/actions/examples/data-fetch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import actions from 'actions/examples/data-fetch';

global.fetch = jest.fn(() =>
new Promise(resolve =>
setTimeout(() => resolve({
json: () => ({ data: 'DUMMY DATA' }),
}), 1),
),
);

describe('examples.dataFetch.fetchDataDone', () => {
const a = actions.examples.dataFetch.fetchDataDone();

test('has expected type', () => {
expect(a.type).toBe('EXAMPLES/DATA_FETCH/FETCH_DATA_DONE');
});

/* NOTE: Starting from Jest 20.x.x you should use the more elegant way:
* expect(a.payload).resolves.toEqual({ data: 'DUMMY DATA' }); */
test('payload is a promise which resolves to the expected object', () =>
a.payload.then(res => expect(res).toEqual('DUMMY DATA')));
});
10 changes: 10 additions & 0 deletions __tests__/shared/components/Button.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Button from 'components/Button';
import React from 'react';
import renderer from 'react-test-renderer';

test('renders correctly', () => {
const button = renderer.create((
<Button className="testClassName">Test Button</Button>
)).toJSON();
expect(button).toMatchSnapshot();
});
29 changes: 29 additions & 0 deletions __tests__/shared/components/Error404.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Error404 from 'components/Error404';
import React from 'react';
import { BrowserRouter, StaticRouter } from 'react-router-dom';
import renderer from 'react-test-renderer';

function render(context) {
return renderer.create((
<StaticRouter location="/" context={context}>
<Error404 />
</StaticRouter>
)).toJSON();
}

test('renders correctly with context', () =>
expect(render({})).toMatchSnapshot());

test('renders correctly without context', () =>
expect(renderer.create((
<BrowserRouter>
<Error404 />
</BrowserRouter>
)).toJSON()).toMatchSnapshot(),
);

test('writes error to the context, if provided', () => {
const context = {};
render(context);
expect(context.status).toBe(404);
});
9 changes: 9 additions & 0 deletions __tests__/shared/components/Modal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';
import renderer from 'react-test-renderer';

import Modal from 'components/Modal';

test('matches snapshots', () => {
const cmp = renderer.create(<Modal />);
expect(cmp.toJSON()).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import renderer from 'react-test-renderer';

import ScreeningDetails from 'components/SubmissionManagement/ScreeningDetails';
import mockScreeningObject from './__mocks__/screening-object.json';

test('renders correctly', () => {
const html = renderer.create((
<ScreeningDetails
screeningObject={mockScreeningObject}
submissionId="12345"
/>
)).toJSON();
expect(html).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import renderer from 'react-test-renderer';

import ScreeningStatus from 'components/SubmissionManagement/ScreeningStatus';
import mockScreeningObject from './__mocks__/screening-object.json';

test('renders correctly', () => {
const html = renderer.create((
<ScreeningStatus
screeningObject={mockScreeningObject}
submissionId="12345"
/>
)).toJSON();
expect(html).toMatchSnapshot();
});
11 changes: 11 additions & 0 deletions __tests__/shared/components/SubmissionManagement/Submission.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import renderer from 'react-test-renderer';

import Submission from 'components/SubmissionManagement/Submission';

test('matches snapshots', () => {
const html = renderer.create((
<Submission />
)).toJSON();
expect(html).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import renderer from 'react-test-renderer';

import SubmissionManagement from 'components/SubmissionManagement/SubmissionManagement';

import mockDesignSubmissionsObject from './__mocks__/design-submissions.json';
import mockDevSubmissionsObject from
'./__mocks__/dev-submissions.json';

test('matches snapshots for design submissions', () => {
const html = renderer.create((
<SubmissionManagement
mockObject={mockDesignSubmissionsObject}
/>
)).toJSON();
expect(html).toMatchSnapshot();
});

test('matches snapshots for development submissions', () => {
const html = renderer.create((
<SubmissionManagement
mockObject={mockDevSubmissionsObject}
/>
)).toJSON();
expect(html).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"challenge": {
"allowSubmit": true,
"name": "GET - Rapid UX - Positive Train Control Design Concepts Challenge",
"phase": "Round 2",
"phaseEnd": "1489679594883",
"type": "design"
},
"submissions": [{
"id": "0253653",
"preview": "http://placehold.it/90/ff0000",
"screening": {
"status": "pending"
},
"submitted": "1488470630291",
"type": "Final"
}, {
"id": "0253614",
"preview": "http://placehold.it/90/f0ff0f",
"screening": {
"status": "passed",
"warnings": [{
"brief": "Incomplete Source Files",
"details": "The provided source files don't match the JPEGs from the submission .zip archive. Sources for files 14..25 are missing."
}, {
"brief": "Stock Art is Not Allowed",
"details": "This challenge doesn't allow you to use any istockphoto, others than the files provided by client. The submitter violated this rule and used 3 images from istockphoto.com. Please check challenge's specifications carefully."
}]
},
"submitted": "1488480630291",
"type": "Checkpoint"
}, {
"id": "0253145",
"preview": "http://placehold.it/90/0660ff",
"screening": {
"status": "passed"
},
"submitted": "1488570630291",
"type": "Checkpoint"
}, {
"id": "0253144",
"preview": "http://placehold.it/90/ff0ff0",
"screening": {
"status": "failed",
"warnings": [{
"brief": "You Have Made a Fatal Mistake",
"details": "Sorry, you have totally lost this challenge. Don't be too upset though, those who never fail, never rise up singing either."
}]
},
"submitted": "1488670630291",
"type": "Checkpoint"
}, {
"id": "0253188",
"preview": "http://placehold.it/90/0f00f0",
"screening": {
"status": "failed"
},
"submitted": "1488670630291",
"type": "Checkpoint"
}, {
"id": "0253199",
"preview": "http://placehold.it/90/00ff00",
"submitted": "1488670630291",
"type": "Checkpoint"
}]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"challenge": {
"name": "John Hancock - Project Coesus Database Upgrade",
"phase": "Submission",
"phaseEnd": "1489679594883",
"type": "develop"
},
"submissions": [{
"id": "0253653",
"preview": "http://placehold.it/40/ff0ff0",
"submitted": "1488470630291",
"type": "Final"
}]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"status": "Dummy Status",
"warnings": [{
"brief": "Dummy Brief #1",
"details": "Dummy Details #1"
}, {
"brief": "Dummy Brief #2",
"details": "Dummy Details #2"
}]
}
Loading

0 comments on commit 49dd259

Please sign in to comment.