Skip to content

Commit 1e48a2a

Browse files
author
Yannick Croissant
authored
test(cypress): add integration tests with Cypress (#428)
1 parent f9603f5 commit 1e48a2a

22 files changed

+1617
-207
lines changed

.circleci/config.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ defaults: &defaults
4444
docker:
4545
- image: circleci/node:14.15.0
4646

47+
cypress: &cypress
48+
working_directory: ~/autocomplete
49+
docker:
50+
- image: cypress/browsers:node14.15.0-chrome86-ff82
51+
environment:
52+
## this enables colors in the output
53+
TERM: xterm
54+
4755
references:
4856
workspace_root: &workspace_root /tmp/workspace
4957
attach_workspace: &attach_workspace
@@ -147,6 +155,23 @@ jobs:
147155
- run:
148156
name: Test packages size
149157
command: yarn run test:size
158+
test_cypress:
159+
<<: *cypress
160+
steps:
161+
- checkout
162+
- run: *install_yarn_version
163+
- restore_cache: *restore_yarn_cache
164+
- run: *run_yarn_install
165+
- save_cache: *save_yarn_cache
166+
- run:
167+
name: Cypress test Actions
168+
command: yarn run cy:run
169+
- store_test_results:
170+
path: cypress-results
171+
- store_artifacts:
172+
path: cypress\screenshots
173+
- store_artifacts:
174+
path: cypress\videos
150175
release:
151176
<<: *defaults
152177
steps:
@@ -177,12 +202,16 @@ workflows:
177202
- test_size:
178203
requires:
179204
- build
205+
- test_cypress:
206+
requires:
207+
- build
180208
- release:
181209
requires:
182210
- test_unit
183211
- test_lint
184212
- test_types
185213
- test_size
214+
- test_cypress
186215
- build
187216
filters:
188217
branches:

cypress.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"projectId": "8iv7jf",
3+
"baseUrl": "http://localhost:1234"
4+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
context('Start', () => {
2+
beforeEach(() => {
3+
cy.visit(Cypress.config().baseUrl!);
4+
});
5+
6+
it('Open Panel on Search Input click', () => {
7+
cy.get('.aa-Input').click();
8+
cy.get('.aa-Panel').should('be.visible');
9+
cy.get('.aa-Input').should('be.focus');
10+
cy.percySnapshot('panel-opened');
11+
});
12+
});
13+
14+
context('End', () => {
15+
beforeEach(() => {
16+
cy.visit(Cypress.config().baseUrl!);
17+
cy.get('.aa-Input').click();
18+
});
19+
20+
it('Close Panel with Esc key', () => {
21+
cy.get('body').type('{esc}');
22+
cy.get('.aa-Panel').should('not.to.exist');
23+
cy.percySnapshot('panel-closed');
24+
});
25+
});
26+
27+
context('Search', () => {
28+
beforeEach(() => {
29+
cy.visit(Cypress.config().baseUrl!);
30+
cy.get('.aa-Input').click();
31+
});
32+
33+
it('Results are displayed after a Query', () => {
34+
cy.get('.aa-Input').type('apple');
35+
cy.get('.aa-SourceHeader').should('be.visible');
36+
cy.percySnapshot('search-results');
37+
});
38+
39+
it('Query can be cleared', () => {
40+
cy.get('.aa-Input').type('apple');
41+
cy.get('.aa-ClearButton').click();
42+
cy.get('.aa-Input').should('be.empty');
43+
});
44+
45+
it("No Results are displayed if query doesn't match", () => {
46+
cy.get('.aa-Input').type('zzzzz');
47+
cy.contains('No products for this query.').should('be.visible');
48+
cy.percySnapshot('no-results');
49+
});
50+
});
51+
52+
context('Recent searches', () => {
53+
beforeEach(() => {
54+
cy.visit(Cypress.config().baseUrl!);
55+
cy.get('.aa-Input').click();
56+
cy.get('.aa-Input').type('apple');
57+
cy.get('.aa-Item').first().click({ force: true });
58+
});
59+
60+
it('Recent search is displayed after visiting a result', () => {
61+
cy.get('.aa-Input').click();
62+
cy.get('.aa-Item')
63+
.first()
64+
.find('[title="Remove this search"]')
65+
.should('be.visible');
66+
cy.percySnapshot('recent-search');
67+
});
68+
69+
it('Recent search can be deleted', () => {
70+
cy.get('.aa-Input').click();
71+
cy.get('.aa-Item')
72+
.first()
73+
.find('[title="Remove this search"]')
74+
.trigger('click');
75+
cy.get('.aa-Item')
76+
.first()
77+
.find('[title="Remove this search"]')
78+
.should('not.to.exist');
79+
});
80+
});
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/// <reference path="../../support/commands.d.ts" />
2+
3+
describe('Screenshots', () => {
4+
before(() => {
5+
cy.exec('yarn cy:clean');
6+
});
7+
8+
beforeEach(() => {
9+
cy.visit(Cypress.config().baseUrl!);
10+
});
11+
12+
const sizes: Cypress.ViewportPreset[] = ['iphone-x', 'ipad-2', 'macbook-11'];
13+
const modes = ['light', 'dark'];
14+
15+
modes.forEach((mode) => {
16+
context(mode, () => {
17+
sizes.forEach((size) => {
18+
context(size, () => {
19+
it('Open Panel', () => {
20+
if (mode === 'dark') {
21+
cy.darkmode();
22+
}
23+
cy.viewport(size);
24+
cy.openPanel();
25+
cy.screenshot('panel-opened__' + size + '__' + mode, {
26+
capture: 'viewport',
27+
});
28+
});
29+
30+
it('Close Panel', () => {
31+
if (mode === 'dark') {
32+
cy.darkmode();
33+
}
34+
cy.viewport(size);
35+
cy.closePanel();
36+
cy.screenshot('panel-closed__' + size + '__' + mode, {
37+
capture: 'viewport',
38+
});
39+
});
40+
41+
it('Results after Query', () => {
42+
if (mode === 'dark') {
43+
cy.darkmode();
44+
}
45+
cy.viewport(size);
46+
cy.openPanel();
47+
cy.typeQueryMatching();
48+
cy.screenshot('search-results__' + size + '__' + mode, {
49+
capture: 'viewport',
50+
});
51+
});
52+
53+
it('No Results', () => {
54+
if (mode === 'dark') {
55+
cy.darkmode();
56+
}
57+
cy.viewport(size);
58+
cy.openPanel();
59+
cy.typeQueryNotMatching();
60+
cy.contains('No products for this query.').should('be.visible');
61+
cy.screenshot('no-results__' + size + '__' + mode, {
62+
capture: 'viewport',
63+
});
64+
});
65+
66+
it('Recent searches', () => {
67+
if (mode === 'dark') {
68+
cy.darkmode();
69+
}
70+
cy.viewport(size);
71+
cy.openPanel();
72+
cy.typeQueryMatching();
73+
cy.get('.aa-Item').first().click({
74+
force: true,
75+
});
76+
cy.wait(1000);
77+
cy.openPanel();
78+
cy.get('.aa-Item')
79+
.first()
80+
.find('[title="Remove this search"]')
81+
.should('be.visible');
82+
cy.screenshot('recent-search__' + size + '__' + mode, {
83+
capture: 'viewport',
84+
});
85+
});
86+
});
87+
});
88+
});
89+
});
90+
});

cypress/plugins/index.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/* eslint-disable import/no-commonjs */
2+
const percyHealthCheck = require('@percy/cypress/task');
3+
4+
module.exports = (on) => {
5+
on('task', percyHealthCheck);
6+
};

cypress/support/commands.d.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/// <reference types="cypress" />
2+
3+
declare namespace Cypress {
4+
interface Chainable {
5+
/**
6+
* Toggles the dark mode on the preview website.
7+
*/
8+
darkmode(): Chainable<Element>;
9+
/**
10+
* Opens the DocSearch modal.
11+
*/
12+
openPanel(): Chainable<Element>;
13+
/**
14+
* Closes the DocSearch modal.
15+
*/
16+
closePanel(): Chainable<Element>;
17+
/**
18+
* Types a query that returns results.
19+
*/
20+
typeQueryMatching(): Chainable<Element>;
21+
/**
22+
* Types a query that returns no results.
23+
*/
24+
typeQueryNotMatching(): Chainable<Element>;
25+
}
26+
}

cypress/support/commands.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import '@percy/cypress';
2+
3+
Cypress.Commands.add('darkmode', () => {
4+
cy.openPanel();
5+
cy.get('.aa-Input').type('/');
6+
cy.contains('Toggle dark mode').click({ force: true });
7+
cy.get('.aa-ClearButton').click();
8+
});
9+
10+
Cypress.Commands.add('openPanel', () => {
11+
cy.get('body')
12+
.then((body) => {
13+
const input = body.find('.aa-Input').length;
14+
return input ? '.aa-Input' : '.aa-DetachedSearchButton';
15+
})
16+
.then((selector) => {
17+
cy.get(selector).click();
18+
});
19+
});
20+
21+
Cypress.Commands.add('closePanel', () => {
22+
cy.get('body').type('{esc}');
23+
});
24+
25+
Cypress.Commands.add('typeQueryMatching', () => {
26+
cy.wait(1000);
27+
cy.openPanel();
28+
cy.get('.aa-Input').type('apple');
29+
});
30+
31+
Cypress.Commands.add('typeQueryNotMatching', () => {
32+
cy.wait(1000);
33+
cy.openPanel();
34+
cy.get('.aa-Input').type('zzzzz');
35+
});

cypress/support/index.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// ***********************************************************
2+
// This example support/index.js is processed and
3+
// loaded automatically before your test files.
4+
//
5+
// This is a great place to put global configuration and
6+
// behavior that modifies Cypress.
7+
//
8+
// You can change the location of this file or turn off
9+
// automatically serving support files with the
10+
// 'supportFile' configuration option.
11+
//
12+
// You can read more here:
13+
// https://on.cypress.io/configuration
14+
// ***********************************************************
15+
16+
// Import commands.js using ES2015 syntax:
17+
import './commands';
18+
19+
// Alternatively you can use CommonJS syntax:
20+
// require('./commands')

cypress/test-apps/js/README.md

Whitespace-only changes.

0 commit comments

Comments
 (0)