Skip to content

Commit bc457ee

Browse files
authored
fight flake in select2 test (#521)
1 parent 70fe465 commit bc457ee

File tree

8 files changed

+115
-9
lines changed

8 files changed

+115
-9
lines changed

Development.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,16 @@ Simply commit an empty set of changes with `git commit --allow-empty` and set th
107107
and push to the branch. The CircleCI will install Cypress from the above links and then will go through the CI run, allowing you to confirm that the new recipes are working.
108108

109109
Once the new Cypress version is published, merge the branch.
110+
111+
## Fighting flake
112+
113+
If you notice a recipe test failing sometimes, run more of it! In [circle.yml](circle.yml) a job can take `repeat: N` parameter to run the recipe N times. Increase the number of times to run the recipe to flush out flaky tests and fix them.
114+
115+
Example recipe to run 5 times
116+
117+
```
118+
- testing-dom__select2:
119+
requires:
120+
- build
121+
repeat: 5
122+
```

circle.yml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ version: 2.1
22

33
# testing jobs are all the same, so just use a template
44
defaults: &defaults
5+
parameters:
6+
repeat:
7+
description: Number of times to run this particular example
8+
type: integer
9+
default: 1
510
parallelism: 1
611
working_directory: ~/app
712
docker:
@@ -26,11 +31,7 @@ defaults: &defaults
2631
# are not passed to the external PRs
2732
command: |
2833
cd examples/$CIRCLE_JOB
29-
if [ -z "$CYPRESS_RECORD_KEY" ]; then
30-
npm run cypress:run
31-
else
32-
npm run cypress:run -- --record --group $CIRCLE_JOB
33-
fi
34+
node ../../test-repeat -n << parameters.repeat >> --group $CIRCLE_JOB
3435
name: Cypress tests
3536

3637
jobs:
@@ -451,6 +452,7 @@ all_jobs: &all_jobs
451452
- testing-dom__select2:
452453
requires:
453454
- build
455+
repeat: 5
454456
- unit-testing__application-code:
455457
requires:
456458
- build
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
FOO=42
2+
BAR=baz
3+
CYPRESS_ping=123

examples/server-communication__env-variables/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
This recipe shows how to pass environment variables to your tests
44

5-
- See [package.json](package.json) which runs Cypress with environment variables set. The variables that start with `CYPRESS_` are extracted automatically. Other variables are copied from `process.env` in the script [cypress/plugins/index.js](cypress/plugins/index.js)
5+
- See [package.json](package.json) file which runs Cypress with environment variables set. The variables that start with `CYPRESS_` are extracted automatically. Other variables are copied from `process.env` in the script [cypress/plugins/index.js](cypress/plugins/index.js)
66
- Additional variables can be passed via `env` object in [cypress.json](cypress.json)
77
- Extract any other variable from `process.env` using `cypress/plugins/index.js` callback.
8+
9+
Note: for testing scripts, the same environment variables set in `package.json` are also set in [.env](.env) file

examples/server-communication__xhr-assertions/cypress/integration/spok-spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('network', () => {
2323
url: spok.endsWith('posts'),
2424
// network request takes at least 10ms
2525
// but should finish in less than 1 second
26-
duration: spok.range(10, 1000),
26+
duration: spok.range(10, 1500),
2727
statusMessage: spok.string,
2828
// check the request inside XHR object
2929
request: {

examples/testing-dom__select2/cypress/integration/spec.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,14 +237,31 @@ describe('select2', () => {
237237

238238
it('selects a value by typing and selecting', () => {
239239
cy.server()
240+
cy.route('https://jsonplaceholder.cypress.io/users?_type=query').as('query')
240241
cy.route('https://jsonplaceholder.cypress.io/users?term=clem&_type=query&q=clem').as('user_search')
241242

242243
// first open the container, which makes the initial ajax call
243244
cy.get('#select2-user-container').click()
244245

245-
// then type into the input element to trigger search, and wait for results
246-
cy.get('input[aria-controls="select2-user-results"]').type('clem{enter}')
246+
// let's wait for Select2 widget to finish its full query
247+
cy.wait('@query')
248+
249+
cy.get('.select2-results__option')
250+
.should('not.have.class', 'loading-results')
251+
252+
// then type into the input element to trigger search
253+
cy.get('input[aria-controls="select2-user-results"]')
254+
.type('clem', { delay: 150 })
255+
256+
// and wait for results from XHR "query=clem"
247257
cy.wait('@user_search')
258+
.its('responseBody.length').then((numberOfResults) => {
259+
// make sure the Select2 has updated to show just
260+
// the above number of items. Otherwise the next
261+
// step might fail since the widget suddenly re-renders
262+
// to show only the new results
263+
cy.get('.select2-results__option').should('have.length', numberOfResults)
264+
})
248265

249266
// select a value, again by retrying command
250267
// https://on.cypress.io/retry-ability

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
"cypress-react-unit-test": "4.9.0",
109109
"cypress-select-tests": "1.5.3",
110110
"cypress-wait-until": "1.7.1",
111+
"dotenv": "8.2.0",
111112
"eslint": "6.0.1",
112113
"eslint-plugin-json-format": "2.0.1",
113114
"eslint-plugin-mocha": "5.0.0",

test-repeat.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/* eslint-disable no-console */
2+
// a small utility script to run Cypress N times
3+
// use (from examples/X folder)
4+
// node ../../test-repeat.js -n 3
5+
// if you want to record, a good idea is to pass a group name
6+
// node ../../test-repeat.js -n 3 --group my-example
7+
8+
// if there is an .env file, lots it and add to process.env
9+
require('dotenv').config()
10+
11+
const arg = require('arg')
12+
const cypress = require('cypress')
13+
const Bluebird = require('bluebird')
14+
15+
const args = arg({
16+
'-n': Number,
17+
'--group': String,
18+
})
19+
20+
const repeatNtimes = args['-n'] ? args['-n'] : 1
21+
22+
console.log('will repeat Cypress run %d time(s)', repeatNtimes)
23+
24+
const allRunOptions = []
25+
26+
for (let k = 0; k < repeatNtimes; k += 1) {
27+
const runOptions = {}
28+
29+
if (process.env.CYPRESS_RECORD_KEY) {
30+
runOptions.record = true
31+
runOptions.group = args['--group']
32+
33+
if (runOptions.group && repeatNtimes > 1) {
34+
// make sure if we are repeating this example
35+
// then the recording has group names on the Dashboard
36+
// like "example-1-of-20", "example-2-of-20", ...
37+
runOptions.group += `-${k + 1}-of-${repeatNtimes}`
38+
}
39+
}
40+
41+
allRunOptions.push(runOptions)
42+
}
43+
44+
const onError = (err) => {
45+
console.error(err)
46+
process.exit(1)
47+
}
48+
49+
Bluebird.mapSeries(allRunOptions, (runOptions, k, n) => {
50+
console.log('***** %d of %d *****', k + 1, n)
51+
52+
const onTestResults = (testResults) => {
53+
if (testResults.failures) {
54+
console.error(testResults.message)
55+
process.exit(testResults.failures)
56+
}
57+
58+
if (testResults.totalFailed) {
59+
console.error('run %d of %d failed', k + 1, n)
60+
process.exit(testResults.totalFailed)
61+
}
62+
}
63+
64+
return cypress.run(runOptions).then(onTestResults)
65+
}).then(() => {
66+
console.log('***** finished %d run(s) successfully *****', repeatNtimes)
67+
})
68+
.catch(onError)

0 commit comments

Comments
 (0)