Skip to content

Commit 16e963b

Browse files
committed
cleanup code, add better e2e tests
1 parent 6c7ba0f commit 16e963b

File tree

10 files changed

+321
-8
lines changed

10 files changed

+321
-8
lines changed

packages/driver/src/cypress/runner.js

+31-7
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,16 @@ const create = function (specWindow, mocha, Cypress, cy) {
889889
return _testsById[id]
890890
}
891891

892+
function hasTestAlreadyRun (test) {
893+
if (Cypress._RESUMED_AT_TEST) {
894+
if (+test.id.slice(1) < +Cypress._RESUMED_AT_TEST.slice(1)) {
895+
return true
896+
}
897+
}
898+
899+
return false
900+
}
901+
892902
overrideRunnerHook(Cypress, _runner, getTestById, getTest, setTest, getTests)
893903

894904
return {
@@ -962,6 +972,27 @@ const create = function (specWindow, mocha, Cypress, cy) {
962972
break
963973
}
964974

975+
// if this isnt a hook, then the name is 'test'
976+
const hookName = runnable.type === 'hook' ? getHookName(runnable) : 'test'
977+
978+
// extract out the next(fn) which mocha uses to
979+
// move to the next runnable - this will be our async seam
980+
const _next = args[0]
981+
982+
if (hasTestAlreadyRun(test)) {
983+
// NOTE: this is a hack to work around another cypress bug
984+
// where the currentTest of a global after hook
985+
// can be the wrong test after top navigation occurs
986+
// (no open issue since it isn't user-facing for the most part)
987+
988+
// A failing after hook will also not show up as a failing test in open mode
989+
// (only a visual bug - does not affect run mode)
990+
// https://github.com/cypress-io/cypress/issues/2296
991+
if (!(hookName === 'after all' && runnable.parent.root)) {
992+
return _next()
993+
}
994+
}
995+
965996
// closure for calculating the actual
966997
// runtime of a runnables fn exection duration
967998
// and also the run of the runnable:after:run:async event
@@ -986,9 +1017,6 @@ const create = function (specWindow, mocha, Cypress, cy) {
9861017
test.wallClockStartedAt = wallClockStartedAt
9871018
}
9881019

989-
// if this isnt a hook, then the name is 'test'
990-
const hookName = runnable.type === 'hook' ? getHookName(runnable) : 'test'
991-
9921020
// if we haven't yet fired this event for this test
9931021
// that means that we need to reset the previous state
9941022
// of cy - since we now have a new 'test' and all of the
@@ -997,10 +1025,6 @@ const create = function (specWindow, mocha, Cypress, cy) {
9971025
fire(TEST_BEFORE_RUN_EVENT, test, Cypress)
9981026
}
9991027

1000-
// extract out the next(fn) which mocha uses to
1001-
// move to the next runnable - this will be our async seam
1002-
const _next = args[0]
1003-
10041028
const next = function (err) {
10051029
// now set the duration of the after runnable run async event
10061030
afterFnDurationEnd = (wallClockEnd = new Date())
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
exports['e2e issue 1987 / can reload during spec run'] = `
2+
3+
====================================================================================================
4+
5+
(Run Starting)
6+
7+
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
8+
│ Cypress: 1.2.3 │
9+
│ Browser: FooBrowser 88 │
10+
│ Specs: 1 found (beforehook-and-test-navigation.js) │
11+
│ Searched: cypress/integration/beforehook-and-test-navigation.js │
12+
└────────────────────────────────────────────────────────────────────────────────────────────────┘
13+
14+
15+
────────────────────────────────────────────────────────────────────────────────────────────────────
16+
17+
Running: beforehook-and-test-navigation.js (1 of 1)
18+
19+
20+
suite
21+
✓ test
22+
✓ causes domain navigation
23+
24+
25+
2 passing
26+
27+
28+
(Results)
29+
30+
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
31+
│ Tests: 2 │
32+
│ Passing: 2 │
33+
│ Failing: 0 │
34+
│ Pending: 0 │
35+
│ Skipped: 0 │
36+
│ Screenshots: 0 │
37+
│ Video: true │
38+
│ Duration: X seconds │
39+
│ Spec Ran: beforehook-and-test-navigation.js │
40+
└────────────────────────────────────────────────────────────────────────────────────────────────┘
41+
42+
43+
(Video)
44+
45+
- Started processing: Compressing to 32 CRF
46+
- Finished processing: /XXX/XXX/XXX/cypress/videos/beforehook-and-test-navigation. (X second)
47+
js.mp4
48+
49+
50+
====================================================================================================
51+
52+
(Run Finished)
53+
54+
55+
Spec Tests Passing Failing Pending Skipped
56+
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
57+
│ ✔ beforehook-and-test-navigation.js XX:XX 2 2 - - - │
58+
└────────────────────────────────────────────────────────────────────────────────────────────────┘
59+
✔ All specs passed! XX:XX 2 2 - - -
60+
61+
62+
`
63+
64+
exports['e2e issue 1987 / can run proper amount of hooks'] = `
65+
66+
====================================================================================================
67+
68+
(Run Starting)
69+
70+
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
71+
│ Cypress: 1.2.3 │
72+
│ Browser: FooBrowser 88 │
73+
│ Specs: 1 found (afterhooks.spec.js) │
74+
│ Searched: cypress/integration/afterhooks.spec.js │
75+
└────────────────────────────────────────────────────────────────────────────────────────────────┘
76+
77+
78+
────────────────────────────────────────────────────────────────────────────────────────────────────
79+
80+
Running: afterhooks.spec.js (1 of 1)
81+
82+
83+
suite 1
84+
✓ test 1
85+
✓ test 2
86+
87+
suite 2
88+
✓ s2t1
89+
90+
91+
3 passing
92+
93+
94+
(Results)
95+
96+
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
97+
│ Tests: 3 │
98+
│ Passing: 3 │
99+
│ Failing: 0 │
100+
│ Pending: 0 │
101+
│ Skipped: 0 │
102+
│ Screenshots: 0 │
103+
│ Video: true │
104+
│ Duration: X seconds │
105+
│ Spec Ran: afterhooks.spec.js │
106+
└────────────────────────────────────────────────────────────────────────────────────────────────┘
107+
108+
109+
(Video)
110+
111+
- Started processing: Compressing to 32 CRF
112+
- Finished processing: /XXX/XXX/XXX/cypress/videos/afterhooks.spec.js.mp4 (X second)
113+
114+
115+
====================================================================================================
116+
117+
(Run Finished)
118+
119+
120+
Spec Tests Passing Failing Pending Skipped
121+
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
122+
│ ✔ afterhooks.spec.js XX:XX 3 3 - - - │
123+
└────────────────────────────────────────────────────────────────────────────────────────────────┘
124+
✔ All specs passed! XX:XX 3 3 - - -
125+
126+
127+
`
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const e2e = require('../support/helpers/e2e')
2+
const Fixtures = require('../support/helpers/fixtures')
3+
4+
describe('e2e issue 1987', () => {
5+
e2e.setup({
6+
servers: [{
7+
port: 3434,
8+
static: true,
9+
},
10+
{
11+
port: 4545,
12+
static: true,
13+
}],
14+
})
15+
16+
// https://github.com/cypress-io/cypress/issues/1987
17+
// before/after hooks should not be rerun on top navigation
18+
e2e.it('can reload during spec run', {
19+
project: Fixtures.projectPath('hooks-after-rerun'),
20+
spec: 'beforehook-and-test-navigation.js',
21+
snapshot: true,
22+
})
23+
24+
e2e.it('can run proper amount of hooks', {
25+
project: Fixtures.projectPath('hooks-after-rerun'),
26+
spec: 'afterhooks.spec.js',
27+
snapshot: true,
28+
})
29+
})

packages/server/test/integration/cypress_spec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ describe('lib/cypress', () => {
105105
require('mocha-banner').register()
106106

107107
beforeEach(function () {
108-
this.timeout(5000)
108+
this.timeout(8000)
109109

110110
cache.__removeSync()
111111

Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
describe('suite 1', () => {
2+
before(() => {
3+
cy.task('incrState', 'b1')
4+
})
5+
6+
it('test 1', () => {
7+
cy.task('incrState', 't1')
8+
cy.visit('http://localhost:3434')
9+
})
10+
11+
it('test 2', () => {
12+
cy.task('incrState', 't2')
13+
})
14+
15+
after(() => {
16+
cy.task('incrState', 'a1')
17+
})
18+
})
19+
20+
describe('suite 2', () => {
21+
it('s2t1', () => {
22+
cy.task('incrState', 's2t1')
23+
cy.visit('http://localhost:4545')
24+
})
25+
})
26+
27+
after(() => {
28+
cy.task('incrState', 'a2')
29+
cy.task('getState').then((state) => {
30+
expect(state).deep.eq({
31+
// initial domain change causes 2 runs
32+
'b1': 2,
33+
't1': 2,
34+
't2': 1,
35+
'a1': 1,
36+
// domain change causes 2 runs
37+
's2t1': 2,
38+
'a2': 1,
39+
})
40+
})
41+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
describe('suite', () => {
2+
before(() => {
3+
// will cause infinite top navigation
4+
cy.visit('http://localhost:3434')
5+
})
6+
7+
it('test', () => {
8+
})
9+
10+
it('causes domain navigation', () => {
11+
cy.visit('http://localhost:4545')
12+
})
13+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/// <reference types="cypress" />
2+
// ***********************************************************
3+
// This example plugins/index.js can be used to load plugins
4+
//
5+
// You can change the location of this file or turn off loading
6+
// the plugins file with the 'pluginsFile' configuration option.
7+
//
8+
// You can read more here:
9+
// https://on.cypress.io/plugins-guide
10+
// ***********************************************************
11+
12+
// This function is called when a project is opened or re-opened (e.g. due to
13+
// the project's config changing)
14+
15+
const state = {}
16+
17+
/**
18+
* @type {Cypress.PluginConfig}
19+
*/
20+
module.exports = (on, config) => {
21+
on('task', {
22+
incrState (arg) {
23+
state[arg] = state[arg] + 1 || 1
24+
25+
return null
26+
},
27+
getState () {
28+
return state
29+
} })
30+
31+
// `on` is used to hook into various events Cypress emits
32+
// `config` is the resolved Cypress config
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// ***********************************************
2+
// This example commands.js shows you how to
3+
// create various custom commands and overwrite
4+
// existing commands.
5+
//
6+
// For more comprehensive examples of custom
7+
// commands please read more here:
8+
// https://on.cypress.io/custom-commands
9+
// ***********************************************
10+
//
11+
//
12+
// -- This is a parent command --
13+
// Cypress.Commands.add("login", (email, password) => { ... })
14+
//
15+
//
16+
// -- This is a child command --
17+
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
18+
//
19+
//
20+
// -- This is a dual command --
21+
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
22+
//
23+
//
24+
// -- This will overwrite an existing command --
25+
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
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')

0 commit comments

Comments
 (0)