Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ddd0b81

Browse files
committedApr 26, 2018
Create visual regression tests with niffy and nightmarejs
1 parent 870bbb6 commit ddd0b81

File tree

15 files changed

+221
-113
lines changed

15 files changed

+221
-113
lines changed
 

‎.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ module.exports = {
1313
'no-mixed-operators': [0],
1414
'default-case': [0],
1515
'import/no-unresolved': [0],
16+
'func-names': [0],
1617
},
1718
};

‎package.json

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"babel-runtime": "6.26.0",
1414
"case-sensitive-paths-webpack-plugin": "2.1.1",
1515
"chalk": "1.1.3",
16+
"co": "^4.6.0",
1617
"css-loader": "0.28.7",
1718
"dotenv": "^5.0.1",
1819
"dotenv-expand": "4.2.0",
@@ -55,9 +56,9 @@
5556
"build": "node scripts/build.js",
5657
"predeploy": "yarn build",
5758
"deploy": "node scripts/deploy.js",
58-
"test": "node scripts/test.js --env=jsdom",
59-
"test:coverage": "node scripts/test.js --env=jsdom --coverage",
60-
"test:e2e": "jest src/__tests__/e2e_tests/e2e.test.js",
59+
"test": "concurrently \"yarn start\" \"node scripts/test.js --env=jsdom\"",
60+
"test:coverage":
61+
"concurrently \"yarn start\" \"node scripts/test.js --env=jsdom --coverage",
6162
"lint": "eslint ./src/**/*.j*",
6263
"prettier": "prettier --write --config ./.prettierrc ./src/**/*.j*"
6364
},
@@ -74,13 +75,8 @@
7475
"stylelint-config-standard": "^18.2.0"
7576
},
7677
"jest": {
77-
"collectCoverageFrom": [
78-
"src/**/*.{js,jsx,mjs}"
79-
],
80-
"setupFiles": [
81-
"<rootDir>/config/polyfills.js",
82-
"<rootDir>/test-setup.js"
83-
],
78+
"collectCoverageFrom": ["src/**/*.{js,jsx,mjs}"],
79+
"setupFiles": ["<rootDir>/config/polyfills.js", "<rootDir>/test-setup.js"],
8480
"testMatch": [
8581
"<rootDir>/src/**/__tests__/**/*.{js,jsx,mjs}",
8682
"<rootDir>/src/**/?(*.)(spec|test).{js,jsx,mjs}"
@@ -90,11 +86,10 @@
9086
"transform": {
9187
"^.+\\.(js|jsx|mjs)$": "<rootDir>/node_modules/babel-jest",
9288
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
93-
"^(?!.*\\.(js|jsx|mjs|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
89+
"^(?!.*\\.(js|jsx|mjs|css|json)$)":
90+
"<rootDir>/config/jest/fileTransform.js"
9491
},
95-
"transformIgnorePatterns": [
96-
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$"
97-
],
92+
"transformIgnorePatterns": ["[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$"],
9893
"moduleNameMapper": {
9994
"^react-native$": "react-native-web"
10095
},
@@ -109,11 +104,7 @@
109104
]
110105
},
111106
"babel": {
112-
"presets": [
113-
"react-app"
114-
],
115-
"plugins": [
116-
"transform-decorators-legacy"
117-
]
107+
"presets": ["react-app"],
108+
"plugins": ["transform-decorators-legacy"]
118109
}
119110
}

‎screenshots/home_page.png

-127 KB
Loading

‎src/__tests__/e2e_tests/App.e2e.js

Lines changed: 0 additions & 24 deletions
This file was deleted.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import Nightmare from 'nightmare';
2+
import Niffy from 'niffy';
3+
import co from 'co';
4+
import {
5+
NIFFY_BASE_HOST,
6+
NIFFY_TEST_HOST,
7+
NIFFY_OPTIONS,
8+
ASYNC_CALLBACK_TIMEOUT,
9+
} from '../../../test-setup';
10+
11+
describe('Image Gallery', () => {
12+
it(
13+
'show open a modal window, if user clicks on an image',
14+
async () => {
15+
const nightmare = Nightmare(NIFFY_OPTIONS);
16+
await nightmare
17+
.goto(NIFFY_TEST_HOST)
18+
.wait(5000)
19+
.click('img')
20+
.wait('#preview-modal')
21+
.exists('#preview-modal')
22+
.visible('#preview-modal')
23+
.evaluate(() => document.querySelector('#preview-modal img'))
24+
.end()
25+
.then((image) => {
26+
expect(image).toHaveProperty('src');
27+
expect(image).toHaveProperty('complete', true);
28+
})
29+
.catch((error) => {
30+
console.error(`An error has occurred: ${error}`);
31+
});
32+
},
33+
ASYNC_CALLBACK_TIMEOUT,
34+
);
35+
36+
describe('Image Gallery perceptual diff test', () => {
37+
let niffy;
38+
beforeAll(() => {
39+
niffy = new Niffy(NIFFY_BASE_HOST, NIFFY_TEST_HOST, NIFFY_OPTIONS);
40+
});
41+
42+
afterAll(async () => {
43+
await co(function* () {
44+
return yield niffy.end();
45+
});
46+
});
47+
48+
it('should open a modal window with an image', async () => {
49+
await co(function* () {
50+
return yield niffy.test('/', async (nightmare) => {
51+
await co(function* () {
52+
return yield nightmare.click('img').wait('#preview-modal');
53+
});
54+
});
55+
});
56+
});
57+
});
58+
});

‎src/__tests__/e2e_tests/Home.e2e.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import Niffy from 'niffy';
2+
import co from 'co';
3+
import {
4+
NIFFY_BASE_HOST,
5+
NIFFY_TEST_HOST,
6+
NIFFY_OPTIONS,
7+
ASYNC_CALLBACK_TIMEOUT,
8+
} from '../../../test-setup';
9+
10+
describe('Visual Regression Tests', () => {
11+
let niffy;
12+
describe('Home Page', () => {
13+
beforeAll(() => {
14+
niffy = new Niffy(NIFFY_BASE_HOST, NIFFY_TEST_HOST, NIFFY_OPTIONS);
15+
});
16+
17+
afterAll(async () => {
18+
await co(function* () {
19+
return yield niffy.end();
20+
});
21+
});
22+
23+
describe('Home Page perceptual diff test', () => {
24+
it(
25+
'should display search header, content body and footer',
26+
async () => {
27+
await co(function* () {
28+
return yield niffy.test('/');
29+
});
30+
},
31+
ASYNC_CALLBACK_TIMEOUT,
32+
);
33+
});
34+
});
35+
});
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import Nightmare from 'nightmare';
2+
import {
3+
NIFFY_TEST_HOST,
4+
NIFFY_OPTIONS,
5+
ASYNC_CALLBACK_TIMEOUT,
6+
} from '../../../test-setup';
7+
8+
describe('Scroll To Top', () => {
9+
it(
10+
'should show scroll to top component, if user scrolls down a little bit',
11+
async () => {
12+
const nightmare = Nightmare(NIFFY_OPTIONS);
13+
await nightmare
14+
.goto(NIFFY_TEST_HOST)
15+
.wait(5000)
16+
.scrollTo(500, 0)
17+
.wait('#scroll-to-top')
18+
.exists('#scroll-to-top')
19+
.visible('#scroll-to-top')
20+
.end()
21+
.then((result) => {
22+
console.log(result);
23+
})
24+
.catch((error) => {
25+
console.error(`An error has occurred: ${error}`);
26+
});
27+
},
28+
ASYNC_CALLBACK_TIMEOUT,
29+
);
30+
31+
it(
32+
'should return to top, if clicked on scroll to top component',
33+
async () => {
34+
const nightmare = new Nightmare(NIFFY_OPTIONS);
35+
36+
await nightmare
37+
.goto(NIFFY_TEST_HOST)
38+
.wait(5000)
39+
.scrollTo(500, 0)
40+
.wait('#scroll-to-top')
41+
.click('#scroll-to-top')
42+
.wait(200)
43+
.evaluate(() => document.documentElement.scrollTop)
44+
.end()
45+
.then((currentScollPosition) => {
46+
expect(currentScollPosition).toEqual(0);
47+
})
48+
.catch(error => console.log(error));
49+
},
50+
ASYNC_CALLBACK_TIMEOUT,
51+
);
52+
});
Lines changed: 36 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,42 @@
1-
import Nightmare from 'nightmare';
2-
// import Niffy from 'niffy';
1+
import Niffy from 'niffy';
2+
import co from 'co';
3+
import {
4+
NIFFY_BASE_HOST,
5+
NIFFY_TEST_HOST,
6+
NIFFY_OPTIONS,
7+
ASYNC_CALLBACK_TIMEOUT,
8+
} from '../../../test-setup';
39

4-
describe('Visual Tests', () => {
5-
// const basehost = 'https://github.com/synthetiquely/collections';
6-
// const testhost = 'http://127.0.0.1:3000';
7-
// let niffy;
10+
describe('Visual Regression Tests', () => {
11+
let niffy;
812
describe('Search Form', () => {
9-
it(
10-
'should go to the page, type something into the search form and then make a screenshot',
11-
async () => {
12-
const nightmare = Nightmare({ show: false });
13-
await nightmare
14-
.goto('http://127.0.0.1:3000')
15-
.wait(200)
16-
.type('input', 'cats')
17-
.click('button')
18-
.wait(5000)
19-
.screenshot('./screenshots/search_results.png')
20-
.end()
21-
.then((result) => {
22-
console.log(result);
23-
})
24-
.catch((error) => {
25-
console.error(`An error has occurred: ${error}`);
26-
});
27-
},
28-
30000,
29-
);
30-
31-
// beforeAll(() => {
32-
// niffy = new Niffy(basehost, testhost, { show: true });
33-
// });
13+
beforeAll(() => {
14+
niffy = new Niffy(NIFFY_BASE_HOST, NIFFY_TEST_HOST, NIFFY_OPTIONS);
15+
});
3416

35-
// afterAll(async () => {
36-
// await niffy.end();
37-
// });
17+
afterAll(async () => {
18+
await co(function* () {
19+
return yield niffy.end();
20+
});
21+
});
3822

39-
// describe('Search form', () => {
40-
// beforeEach(async () => {
41-
// await niffy.goto('/', async (nightmare) => {
42-
// await nightmare
43-
// .type('input', 'dogs')
44-
// .click('button[type="submit"]')
45-
// .wait(5000);
46-
// });
47-
// });
48-
49-
// it(
50-
// 'should find cats',
51-
// async () => {
52-
// await niffy.test('/');
53-
// },
54-
// 30000,
55-
// );
56-
// });
23+
describe('Search form perceptual diff test', () => {
24+
it(
25+
'should display cats',
26+
async () => {
27+
await co(function* () {
28+
return yield niffy.test('/', async (nightmare) => {
29+
await co(function* () {
30+
return yield nightmare
31+
.type('input', 'cats')
32+
.click('button[type="submit"]')
33+
.wait(3000);
34+
});
35+
});
36+
});
37+
},
38+
ASYNC_CALLBACK_TIMEOUT,
39+
);
40+
});
5741
});
5842
});

‎src/components/Modal/Modal.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import Icon from '../styled/Icon';
99

1010
const Modal = props => (
1111
<Backdrop>
12-
<ModalWindow>
13-
<CloseButton onClick={props.onClose}>
12+
<ModalWindow id="preview-modal">
13+
<CloseButton id="preview-close-button" onClick={props.onClose}>
1414
<Icon size="lg">&times;</Icon>
1515
</CloseButton>
1616
<ArrowButton
17+
id="preview-right-arrow"
1718
direction="right"
1819
onClick={() => props.onChangeSelected(DESTINATION_NEXT)}
1920
>
@@ -22,6 +23,7 @@ const Modal = props => (
2223
</Icon>
2324
</ArrowButton>
2425
<ArrowButton
26+
id="preview-left-arrow"
2527
direction="left"
2628
onClick={() => props.onChangeSelected(DESTINATION_PREVIOUS)}
2729
>

‎src/components/Modal/__snapshots__/Modal.test.js.snap

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ exports[`Modal Component should render and match its own snapshot 1`] = `
66
>
77
<div
88
className="css-13la5a5"
9+
id="preview-modal"
910
>
1011
<button
1112
className="css-hcjupp"
13+
id="preview-close-button"
1214
onClick={undefined}
1315
>
1416
<span
@@ -19,6 +21,7 @@ exports[`Modal Component should render and match its own snapshot 1`] = `
1921
</button>
2022
<button
2123
className="css-10e1v19"
24+
id="preview-right-arrow"
2225
onClick={[Function]}
2326
>
2427
<span
@@ -29,6 +32,7 @@ exports[`Modal Component should render and match its own snapshot 1`] = `
2932
</button>
3033
<button
3134
className="css-1cvb4bz"
35+
id="preview-left-arrow"
3236
onClick={[Function]}
3337
>
3438
<span

‎src/components/Preview/Preview.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,13 @@ class Preview extends Component {
116116
onMouseEnter={this.onMouseMove}
117117
onMouseLeave={this.onMouseMove}
118118
/>
119-
<Tooltip showTooltip={showTooltip && loaded}>
120-
<TooltipText>
121-
{this.props.collections.selectedPhoto.user.username}
122-
</TooltipText>
123-
</Tooltip>
119+
{loaded && (
120+
<Tooltip id="preview-tooltip" showTooltip={showTooltip && loaded}>
121+
<TooltipText>
122+
{this.props.collections.selectedPhoto.user.username}
123+
</TooltipText>
124+
</Tooltip>
125+
)}
124126
</a>
125127
</Swipe>
126128
</Modal>

‎src/components/Preview/Preview.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ describe('Preview Component', () => {
3535

3636
it('should render an image, if there is a seleted photo in the store', () => {
3737
const wrapper = mount(<Preview {...props} />);
38+
wrapper.setState({ loaded: true, showTooltip: true });
3839

3940
expect(wrapper.find(Modal)).toHaveLength(1);
4041
expect(wrapper.find(Image)).toHaveLength(1);

‎src/components/Preview/__snapshots__/Preview.test.js.snap

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ exports[`Preview Component should render and match its own snapshot 1`] = `
66
>
77
<div
88
className="css-13la5a5"
9+
id="preview-modal"
910
>
1011
<button
1112
className="css-hcjupp"
13+
id="preview-close-button"
1214
onClick={[Function]}
1315
>
1416
<span
@@ -19,6 +21,7 @@ exports[`Preview Component should render and match its own snapshot 1`] = `
1921
</button>
2022
<button
2123
className="css-10e1v19"
24+
id="preview-right-arrow"
2225
onClick={[Function]}
2326
>
2427
<span
@@ -29,6 +32,7 @@ exports[`Preview Component should render and match its own snapshot 1`] = `
2932
</button>
3033
<button
3134
className="css-1cvb4bz"
35+
id="preview-left-arrow"
3236
onClick={[Function]}
3337
>
3438
<span
@@ -66,15 +70,6 @@ exports[`Preview Component should render and match its own snapshot 1`] = `
6670
}
6771
}
6872
/>
69-
<div
70-
className="css-1sz2gg8"
71-
>
72-
<h1
73-
className="css-1yb2agg"
74-
>
75-
test user
76-
</h1>
77-
</div>
7873
</a>
7974
</div>
8075
</div>

‎src/components/ScrollToTop/ScrollToTop.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class ScrollToTop extends Component {
6060
const { show } = this.state;
6161
if (show && this.props.show) {
6262
return (
63-
<div className={styles} title="Вернуться наверх">
63+
<div id="scroll-to-top" className={styles} title="Вернуться наверх">
6464
<Button bordered inverted type="button" onClick={this.onClick}>
6565
<Icon size="md">&uarr;</Icon>
6666
</Button>

‎test-setup.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,10 @@ import { configure } from 'enzyme';
22
import Adapter from 'enzyme-adapter-react-16';
33

44
configure({ adapter: new Adapter() });
5+
6+
export const NIFFY_BASE_HOST = 'https://synthetiquely.github.io/collections/';
7+
export const NIFFY_TEST_HOST = 'http://127.0.0.1:3000';
8+
export const NIFFY_OPTIONS = {
9+
show: false,
10+
};
11+
export const ASYNC_CALLBACK_TIMEOUT = 200000;

0 commit comments

Comments
 (0)
Please sign in to comment.