Add tests for Map components

This commit is contained in:
Stuart Taylor
2018-04-08 01:16:03 +01:00
committed by Mrugesh Mohapatra
parent bd285f8ee5
commit fc52d5ae3c
18 changed files with 1704 additions and 44 deletions

9
packages/learn/.babelrc Normal file
View File

@ -0,0 +1,9 @@
{
"presets": [
"es2015",
"react"
],
"plugins": [
"add-module-exports"
]
}

View File

@ -0,0 +1,13 @@
module.exports = {
moduleNameMapper: {
"\\.(jpg|jpeg|png|svg|woff|woff2)$": "<rootDir>/src/__mocks__/fileMock.js",
// Plain CSS - match css files that don't end with '.module.css' https://regex101.com/r/VzwrKH/4
"^(?!.*\\.module\\.css$).*\\.css$": "<rootDir>/src/__mocks__/styleMock.js",
// CSS Modules - match files that end with 'module.css'
"\\.module\\.css$": "identity-obj-proxy" // CSS modules
},
testPathIgnorePatterns: ["/node_modules/", "<rootDir>/.cache/"],
globals: {
__PATH_PREFIX__: ""
}
};

View File

@ -6,6 +6,7 @@
"dependencies": {
"adler32": "^0.1.7",
"babel-core": "^6.26.0",
"babel-jest": "^22.4.3",
"babel-standalone": "^6.26.0",
"brace": "^0.11.1",
"chai": "^4.1.2",
@ -22,11 +23,14 @@
"gatsby-source-filesystem": "^1.5.27",
"gatsby-source-mongodb": "^1.5.19",
"gatsby-transformer-json": "^1.0.16",
"jest": "^22.4.3",
"lodash": "^4.17.5",
"loop-protect": "^2.1.6",
"mongodb": "^3.0.5",
"react": "16",
"react-bootstrap": "^0.32.1",
"react-codemirror2": "^4.2.1",
"react-dom": "16",
"react-helmet": "^5.2.0",
"react-redux": "^5.0.7",
"react-reflex": "^2.2.1",
@ -54,15 +58,28 @@
"lint": "yarn lint:gatsby && yarn lint:src",
"lint:gatsby": "eslint ./gatsby*.js --fix",
"lint:src": "eslint ./src . --fix",
"test": "yarn format && yarn lint"
"pretty": "yarn format && yarn lint",
"test": "jest src",
"test:watch": "jest --watch src"
},
"jest": {
"verbose": true,
"transform": {
"^.+\\.js$": "babel-jest"
},
"moduleNameMapper": {
"^.+\\.(css|less)$": "<rootDir>/src/__mocks__/cssStub.js"
}
},
"devDependencies": {
"babel-eslint": "^8.2.2",
"enzyme-adapter-react-16": "^1.1.1",
"eslint": "^4.19.1",
"eslint-config-freecodecamp": "^1.1.1",
"eslint-plugin-import": "^2.9.0",
"eslint-plugin-prefer-object-spread": "^1.2.1",
"eslint-plugin-react": "^7.7.0",
"prettier": "^1.11.1"
"prettier": "^1.11.1",
"sinon": "^4.5.0"
}
}

View File

@ -0,0 +1,6 @@
import React from 'react';
const mockComponent = name => props =>
React.createElement(name, props, props.children);
export default mockComponent('MockedLink');

View File

@ -0,0 +1,110 @@
export default [
{
fields: {
slug: '/super-block-one/block-a/challenge-one',
blockName: 'Block A'
},
block: 'block-a',
title: 'Challenge One',
isRequired: false,
isPrivate: false,
superBlock: 'Super Block One',
dashedName: 'challenge-one'
},
{
fields: {
slug: '/super-block-one/block-a/challenge-two',
blockName: 'Block A'
},
block: 'block-a',
title: 'Challenge Two',
isRequired: false,
isPrivate: false,
superBlock: 'Super Block One',
dashedName: 'challenge-two'
},
{
fields: {
slug: '/super-block-one/block-b/challenge-one',
blockName: 'Block B'
},
block: 'block-b',
title: 'Challenge One',
isRequired: false,
isPrivate: false,
superBlock: 'Super Block One',
dashedName: 'challenge-one'
},
{
fields: {
slug: '/super-block-one/block-b/challenge-two',
blockName: 'Block B'
},
block: 'block-b',
title: 'Challenge Two',
isRequired: false,
isPrivate: false,
superBlock: 'Super Block One',
dashedName: 'challenge-two'
},
{
fields: {
slug: '/super-block-one/block-c/challenge-one',
blockName: 'Block C'
},
block: 'block-c',
title: 'Challenge One',
isRequired: false,
isPrivate: true,
superBlock: 'Super Block One',
dashedName: 'challenge-one'
},
{
fields: {
slug: '/super-block-one/block-a/challenge-one',
blockName: 'Block A'
},
block: 'block-a',
title: 'Challenge One',
isRequired: false,
isPrivate: false,
superBlock: 'Super Block Two',
dashedName: 'challenge-one'
},
{
fields: {
slug: '/super-block-one/block-a/challenge-two',
blockName: 'Block A'
},
block: 'block-a',
title: 'Challenge Two',
isRequired: false,
isPrivate: false,
superBlock: 'Super Block Two',
dashedName: 'challenge-two'
},
{
fields: {
slug: '/super-block-one/block-b/challenge-one',
blockName: 'Block B'
},
block: 'block-b',
title: 'Challenge One',
isRequired: false,
isPrivate: false,
superBlock: 'Super Block Two',
dashedName: 'challenge-one'
},
{
fields: {
slug: '/super-block-one/block-b/challenge-two',
blockName: 'Block B'
},
block: 'block-b',
title: 'Challenge Two',
isRequired: false,
isPrivate: false,
superBlock: 'Super Block Two',
dashedName: 'challenge-two'
}
];

View File

@ -0,0 +1 @@
module.exports = {};

View File

@ -13,12 +13,13 @@ const propTypes = {
};
class ShowMap extends PureComponent {
renderSuperBlocks = superBlocks => {
renderSuperBlocks(superBlocks) {
const { nodes } = this.props;
return superBlocks.map(superBlock => (
<SuperBlock key={superBlock} nodes={nodes} superBlock={superBlock} />
));
};
}
render() {
const { nodes } = this.props;

View File

@ -0,0 +1,19 @@
/* global expect */
import React from 'react';
import ShallowRenderer from 'react-test-renderer/shallow';
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import Map from './Map';
import mockNodes from '../../__mocks__/map-nodes';
Enzyme.configure({ adapter: new Adapter() });
const renderer = new ShallowRenderer();
test('<Map /> snapshot', () => {
const component = renderer.render(
<Map nodes={mockNodes} />,
);
expect(component).toMatchSnapshot('Map');
});

View File

@ -0,0 +1,237 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<Map /> snapshot: Map 1`] = `
<ul>
<Connect(SuperBlock)
nodes={
Array [
Object {
"block": "block-a",
"dashedName": "challenge-one",
"fields": Object {
"blockName": "Block A",
"slug": "/super-block-one/block-a/challenge-one",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block One",
"title": "Challenge One",
},
Object {
"block": "block-a",
"dashedName": "challenge-two",
"fields": Object {
"blockName": "Block A",
"slug": "/super-block-one/block-a/challenge-two",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block One",
"title": "Challenge Two",
},
Object {
"block": "block-b",
"dashedName": "challenge-one",
"fields": Object {
"blockName": "Block B",
"slug": "/super-block-one/block-b/challenge-one",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block One",
"title": "Challenge One",
},
Object {
"block": "block-b",
"dashedName": "challenge-two",
"fields": Object {
"blockName": "Block B",
"slug": "/super-block-one/block-b/challenge-two",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block One",
"title": "Challenge Two",
},
Object {
"block": "block-c",
"dashedName": "challenge-one",
"fields": Object {
"blockName": "Block C",
"slug": "/super-block-one/block-c/challenge-one",
},
"isPrivate": true,
"isRequired": false,
"superBlock": "Super Block One",
"title": "Challenge One",
},
Object {
"block": "block-a",
"dashedName": "challenge-one",
"fields": Object {
"blockName": "Block A",
"slug": "/super-block-one/block-a/challenge-one",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block Two",
"title": "Challenge One",
},
Object {
"block": "block-a",
"dashedName": "challenge-two",
"fields": Object {
"blockName": "Block A",
"slug": "/super-block-one/block-a/challenge-two",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block Two",
"title": "Challenge Two",
},
Object {
"block": "block-b",
"dashedName": "challenge-one",
"fields": Object {
"blockName": "Block B",
"slug": "/super-block-one/block-b/challenge-one",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block Two",
"title": "Challenge One",
},
Object {
"block": "block-b",
"dashedName": "challenge-two",
"fields": Object {
"blockName": "Block B",
"slug": "/super-block-one/block-b/challenge-two",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block Two",
"title": "Challenge Two",
},
]
}
superBlock="Super Block One"
/>
<Connect(SuperBlock)
nodes={
Array [
Object {
"block": "block-a",
"dashedName": "challenge-one",
"fields": Object {
"blockName": "Block A",
"slug": "/super-block-one/block-a/challenge-one",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block One",
"title": "Challenge One",
},
Object {
"block": "block-a",
"dashedName": "challenge-two",
"fields": Object {
"blockName": "Block A",
"slug": "/super-block-one/block-a/challenge-two",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block One",
"title": "Challenge Two",
},
Object {
"block": "block-b",
"dashedName": "challenge-one",
"fields": Object {
"blockName": "Block B",
"slug": "/super-block-one/block-b/challenge-one",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block One",
"title": "Challenge One",
},
Object {
"block": "block-b",
"dashedName": "challenge-two",
"fields": Object {
"blockName": "Block B",
"slug": "/super-block-one/block-b/challenge-two",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block One",
"title": "Challenge Two",
},
Object {
"block": "block-c",
"dashedName": "challenge-one",
"fields": Object {
"blockName": "Block C",
"slug": "/super-block-one/block-c/challenge-one",
},
"isPrivate": true,
"isRequired": false,
"superBlock": "Super Block One",
"title": "Challenge One",
},
Object {
"block": "block-a",
"dashedName": "challenge-one",
"fields": Object {
"blockName": "Block A",
"slug": "/super-block-one/block-a/challenge-one",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block Two",
"title": "Challenge One",
},
Object {
"block": "block-a",
"dashedName": "challenge-two",
"fields": Object {
"blockName": "Block A",
"slug": "/super-block-one/block-a/challenge-two",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block Two",
"title": "Challenge Two",
},
Object {
"block": "block-b",
"dashedName": "challenge-one",
"fields": Object {
"blockName": "Block B",
"slug": "/super-block-one/block-b/challenge-one",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block Two",
"title": "Challenge One",
},
Object {
"block": "block-b",
"dashedName": "challenge-two",
"fields": Object {
"blockName": "Block B",
"slug": "/super-block-one/block-b/challenge-two",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block Two",
"title": "Challenge Two",
},
]
}
superBlock="Super Block Two"
/>
<Spacer />
</ul>
`;

View File

@ -26,13 +26,15 @@ const propTypes = {
toggleBlock: PropTypes.func.isRequired
};
class Block extends PureComponent {
renderChallenges = challenges =>
challenges.map(challenge => (
export class Block extends PureComponent {
renderChallenges(challenges) {
// TODO: Split this into a Challenge Component and add tests
return challenges.map(challenge => (
<li className='map-challenge-title' key={challenge.dashedName}>
<Link to={challenge.fields.slug}>{challenge.title}</Link>
</li>
));
}
render() {
const { blockDashedName, challenges, isExpanded, toggleBlock } = this.props;

View File

@ -0,0 +1,92 @@
/* global expect */
import React from 'react';
import ShallowRenderer from 'react-test-renderer/shallow';
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import sinon from 'sinon';
import { Block } from './Block';
import mockNodes from '../../../__mocks__/map-nodes';
Enzyme.configure({ adapter: new Adapter() });
const renderer = new ShallowRenderer();
test('<Block /> not expanded snapshot', () => {
const toggleSpy = sinon.spy();
const componentToRender = (
<Block
blockDashedName='block-a'
challenges={
mockNodes.filter(
node => node.block === 'block-a'
)
}
isExpanded={false}
toggleBlock={toggleSpy}
/>
);
const component = renderer.render(componentToRender);
expect(component).toMatchSnapshot('block-not-expanded');
});
test('<Block expanded snapshot', () => {
const toggleSpy = sinon.spy();
const componentToRender = (
<Block
blockDashedName='block-a'
challenges={
mockNodes.filter(
node => node.block === 'block-a'
)
}
isExpanded={true}
toggleBlock={toggleSpy}
/>
);
const component = renderer.render(componentToRender);
expect(component).toMatchSnapshot('block-expanded');
});
test('<Block /> should handle toggle clicks correctly', () => {
const toggleSpy = sinon.spy();
const props = {
blockDashedName: 'block-a',
challenges: mockNodes.filter(
node => node.block === 'block-a'
),
isExpanded: false,
toggleBlock: toggleSpy
};
const componentToRender = (
<Block { ...props } />
);
const enzymeWrapper = Enzyme.shallow(componentToRender);
expect(toggleSpy.called).toBe(false);
expect(
enzymeWrapper.find('.map-title').find('h5').text()
).toBe('Block A');
enzymeWrapper.find('.map-title').simulate('click');
expect(toggleSpy.called).toBe(true);
expect(toggleSpy.calledWithExactly('block-a')).toBe(true);
enzymeWrapper.setProps({ ...props, isExpanded: true });
expect(
enzymeWrapper.find('.map-title').find('h5').text()
).toBe('Block A');
expect(
enzymeWrapper.find('ul').length
).toBe(1);
});

View File

@ -35,8 +35,8 @@ const propTypes = {
toggleSuperBlock: PropTypes.func.isRequired
};
class SuperBlock extends PureComponent {
renderBlock = superBlock => {
export class SuperBlock extends PureComponent {
renderBlock(superBlock) {
const { nodes } = this.props;
const blocksForSuperBlock = nodes.filter(
node => node.superBlock === superBlock
@ -58,7 +58,8 @@ class SuperBlock extends PureComponent {
))}
</ul>
);
};
}
render() {
const { superBlock, isExpanded, toggleSuperBlock } = this.props;
return (

View File

@ -0,0 +1,82 @@
/* global expect */
import React from 'react';
import ShallowRenderer from 'react-test-renderer/shallow';
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import sinon from 'sinon';
import { SuperBlock } from './SuperBlock';
import mockNodes from '../../../__mocks__/map-nodes';
Enzyme.configure({ adapter: new Adapter() });
const renderer = new ShallowRenderer();
test('<SuperBlock /> not expanded snapshot', () => {
const toggleSpy = sinon.spy();
const props = {
isExpanded: false,
nodes: mockNodes,
superBlock: 'Super Block One',
toggleSuperBlock: toggleSpy
};
const componentToRender = (
<SuperBlock { ...props } />
);
const component = renderer.render(componentToRender);
expect(component).toMatchSnapshot('superBlock-not-expanded');
});
test('<SuperBlock /> expanded snapshot', () => {
const toggleSpy = sinon.spy();
const props = {
isExpanded: true,
nodes: mockNodes,
superBlock: 'Super Block One',
toggleSuperBlock: toggleSpy
};
const componentToRender = (
<SuperBlock { ...props } />
);
const component = renderer.render(componentToRender);
expect(component).toMatchSnapshot('superBlock-expanded');
});
test('<SuperBlock should handle toggle clicks correctly', () => {
const toggleSpy = sinon.spy();
const props = {
isExpanded: false,
nodes: mockNodes,
superBlock: 'Super Block One',
toggleSuperBlock: toggleSpy
};
const componentToRender = (
<SuperBlock { ...props } />
);
const enzymeWrapper = Enzyme.shallow(componentToRender);
expect(toggleSpy.called).toBe(false);
expect(
enzymeWrapper.find('.map-title').find('h4').text()
).toBe('Super Block One');
expect(
enzymeWrapper.find('ul').length
).toBe(0);
enzymeWrapper.find('.map-title').simulate('click');
expect(toggleSpy.called).toBe(true);
expect(toggleSpy.calledWithExactly('Super Block One')).toBe(true);
enzymeWrapper.setProps({ ...props, isExpanded: true });
expect(
enzymeWrapper.find('.map-title').find('h4').text()
).toBe('Super Block One');
expect(
enzymeWrapper.find('ul').length
).toBe(1);
});

View File

@ -0,0 +1,72 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<Block /> not expanded snapshot: block-not-expanded 1`] = `
<li
className="block "
>
<div
className="map-title"
onClick={[Function]}
>
<Caret />
<h5>
Block A
</h5>
</div>
<ul />
</li>
`;
exports[`<Block expanded snapshot: block-expanded 1`] = `
<li
className="block open"
>
<div
className="map-title"
onClick={[Function]}
>
<Caret />
<h5>
Block A
</h5>
</div>
<ul>
<li
className="map-challenge-title"
>
<Unknown
to="/super-block-one/block-a/challenge-one"
>
Challenge One
</Unknown>
</li>
<li
className="map-challenge-title"
>
<Unknown
to="/super-block-one/block-a/challenge-two"
>
Challenge Two
</Unknown>
</li>
<li
className="map-challenge-title"
>
<Unknown
to="/super-block-one/block-a/challenge-one"
>
Challenge One
</Unknown>
</li>
<li
className="map-challenge-title"
>
<Unknown
to="/super-block-one/block-a/challenge-two"
>
Challenge Two
</Unknown>
</li>
</ul>
</li>
`;

View File

@ -0,0 +1,116 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<SuperBlock /> expanded snapshot: superBlock-expanded 1`] = `
<li
className="superblock open"
>
<div
className="map-title"
onClick={[Function]}
>
<Caret />
<h4>
Super Block One
</h4>
</div>
<ul>
<Connect(Block)
blockDashedName="block-a"
challenges={
Array [
Object {
"block": "block-a",
"dashedName": "challenge-one",
"fields": Object {
"blockName": "Block A",
"slug": "/super-block-one/block-a/challenge-one",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block One",
"title": "Challenge One",
},
Object {
"block": "block-a",
"dashedName": "challenge-two",
"fields": Object {
"blockName": "Block A",
"slug": "/super-block-one/block-a/challenge-two",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block One",
"title": "Challenge Two",
},
]
}
/>
<Connect(Block)
blockDashedName="block-b"
challenges={
Array [
Object {
"block": "block-b",
"dashedName": "challenge-one",
"fields": Object {
"blockName": "Block B",
"slug": "/super-block-one/block-b/challenge-one",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block One",
"title": "Challenge One",
},
Object {
"block": "block-b",
"dashedName": "challenge-two",
"fields": Object {
"blockName": "Block B",
"slug": "/super-block-one/block-b/challenge-two",
},
"isPrivate": false,
"isRequired": false,
"superBlock": "Super Block One",
"title": "Challenge Two",
},
]
}
/>
<Connect(Block)
blockDashedName="block-c"
challenges={
Array [
Object {
"block": "block-c",
"dashedName": "challenge-one",
"fields": Object {
"blockName": "Block C",
"slug": "/super-block-one/block-c/challenge-one",
},
"isPrivate": true,
"isRequired": false,
"superBlock": "Super Block One",
"title": "Challenge One",
},
]
}
/>
</ul>
</li>
`;
exports[`<SuperBlock /> not expanded snapshot: superBlock-not-expanded 1`] = `
<li
className="superblock "
>
<div
className="map-title"
onClick={[Function]}
>
<Caret />
<h4>
Super Block One
</h4>
</div>
</li>
`;

View File

@ -0,0 +1,19 @@
/* global expect */
import React from 'react';
import renderer from 'react-test-renderer';
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import Spacer from './Spacer';
Enzyme.configure({ adapter: new Adapter() });
test('<Spacer /> snapshot', () => {
const component = renderer.create(
<Spacer />,
);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
});

View File

@ -0,0 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<Spacer /> snapshot 1`] = `
<div
className="util-spacer"
/>
`;

File diff suppressed because it is too large Load Diff