Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: dashboard orchestration #14925

Merged
merged 30 commits into from
Mar 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0c4b8bb
test orchestration
kuceb Feb 4, 2021
7b1ce3b
bump json-schemas
kuceb Feb 4, 2021
a7e6433
fix unit
kuceb Feb 4, 2021
62daf26
Merge remote-tracking branch 'origin/develop' into test-orchestration
kuceb Feb 5, 2021
a492451
Merge branch 'develop' into test-orchestration
kuceb Feb 9, 2021
709bd85
fix server-ct build
kuceb Feb 9, 2021
9e9ddf0
Merge branch 'develop' into test-orchestration
kuceb Feb 10, 2021
a18c7e7
add @types/node
kuceb Feb 10, 2021
d221ad8
add runtime to resolved config, send resolved config to postInstanceT…
kuceb Feb 11, 2021
9aba5a2
add missing fixture spec, support sending test config for skipped and…
kuceb Feb 12, 2021
274c3e1
spec prior., refactor recording tests, update specs
kuceb Feb 18, 2021
5beb096
remove unneded utils, fix e2e_record_spec, rename testConfig, fix unit
kuceb Feb 23, 2021
6c19ef8
Merge branch 'develop' into test-orchestration
kuceb Feb 25, 2021
980e884
fix bug with spec SKIP not stopping test execution
kuceb Mar 2, 2021
10fe66c
Merge remote-tracking branch 'origin/develop' into test-orchestration
kuceb Mar 3, 2021
6e1e1ee
bump json-schemas
kuceb Mar 3, 2021
423d6f0
Merge remote-tracking branch 'origin/develop' into test-orchestration
kuceb Mar 3, 2021
70d5f28
bump json schemas 2
kuceb Mar 3, 2021
c1655f5
Merge branch 'develop' into test-orchestration
kuceb Mar 4, 2021
450d7f1
refactor exit early and error logic, add runnerCapabilities + bump js…
kuceb Mar 8, 2021
8abf2f1
Merge remote-tracking branch 'origin/develop' into test-orchestration
kuceb Mar 8, 2021
5322128
update yarn.lock
kuceb Mar 8, 2021
e8cdf0c
Merge remote-tracking branch 'origin/test-orchestration' into test-or…
kuceb Mar 8, 2021
27758ca
fix referenceError
kuceb Mar 8, 2021
caddeb8
fix: skipAction -> skipSpecAction, muteAction -> muteTestAction
kuceb Mar 8, 2021
6d28e32
exit with non-zero for canceled runs, improve messaging for canceled …
kuceb Mar 9, 2021
65dd097
fixup unit tests
kuceb Mar 9, 2021
bc6076f
Merge branch 'develop' into test-orchestration
kuceb Mar 10, 2021
917973f
colorize run cancelation messages
kuceb Mar 11, 2021
6699d9f
Merge remote-tracking branch 'origin/develop' into test-orchestration
kuceb Mar 11, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe('src/cy/commands/angular', () => {
cy.state('window').angular = this.angular
})

it('throws when cannot find angular', (done) => {
it('throws when cannot find angular', { retries: 2 }, (done) => {
delete cy.state('window').angular

cy.on('fail', (err) => {
Expand Down
14 changes: 8 additions & 6 deletions packages/driver/src/cy/testConfigOverrides.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,28 +44,30 @@ function mutateConfiguration (testConfigOverride, config, env) {
return restoreConfigFn
}

function getResolvedTestConfigOverride (test) {
// this is called during test onRunnable time
// in order to resolve the test config upfront before test runs
export function getResolvedTestConfigOverride (test) {
let curParent = test.parent

const cfgs = [test.cfg]
const testConfig = [test._testConfig]

while (curParent) {
if (curParent.cfg) {
cfgs.push(curParent.cfg)
if (curParent._testConfig) {
testConfig.push(curParent._testConfig)
}

curParent = curParent.parent
}

return _.reduceRight(cfgs, (acc, cfg) => _.extend(acc, cfg), {})
return _.reduceRight(testConfig, (acc, opts) => _.extend(acc, opts), {})
}

class TestConfigOverride {
private restoreTestConfigFn: Nullable<() => void> = null
restoreAndSetTestConfigOverrides (test, config, env) {
if (this.restoreTestConfigFn) this.restoreTestConfigFn()

const resolvedTestConfig = getResolvedTestConfigOverride(test)
const resolvedTestConfig = test._testConfig || {}

this.restoreTestConfigFn = mutateConfiguration(resolvedTestConfig, config, env)
}
Expand Down
1 change: 1 addition & 0 deletions packages/driver/src/cypress.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ class $Cypress {
_.extend(this, browserInfo(config))

this.state = $SetterGetter.create({})
this.originalConfig = _.cloneDeep(config)
this.config = $SetterGetter.create(config)
this.env = $SetterGetter.create(env)
this.getFirefoxGcInterval = $FirefoxForcedGc.createIntervalGetter(this)
Expand Down
17 changes: 8 additions & 9 deletions packages/driver/src/cypress/mocha.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ const suiteAfterEach = Suite.prototype.afterEach
delete window.mocha
delete window.Mocha

function invokeFnWithOriginalTitle (ctx, originalTitle, mochaArgs, fn) {
function invokeFnWithOriginalTitle (ctx, originalTitle, mochaArgs, fn, _testConfig) {
const ret = fn.apply(ctx, mochaArgs)

ret._testConfig = _testConfig
ret.originalTitle = originalTitle

return ret
Expand Down Expand Up @@ -64,13 +65,11 @@ function overloadMochaFnForConfig (fnName, specWindow) {
const origFn = subFn ? _fn[subFn] : _fn

if (args.length > 2 && _.isObject(args[1])) {
const opts = _.defaults({}, args[1], {
browser: null,
})
const _testConfig = _.extend({}, args[1])

const mochaArgs = [args[0], args[2]]

const configMatchesBrowser = opts.browser == null || Cypress.isBrowser(opts.browser, `${fnType} config value \`{ browser }\``)
const configMatchesBrowser = _testConfig.browser == null || Cypress.isBrowser(_testConfig.browser, `${fnType} config value \`{ browser }\``)

if (!configMatchesBrowser) {
// TODO: this would mess up the dashboard since it would be registered as a new test
Expand All @@ -84,15 +83,15 @@ function overloadMochaFnForConfig (fnName, specWindow) {
this.skip()
}

return invokeFnWithOriginalTitle(this, originalTitle, mochaArgs, origFn)
return invokeFnWithOriginalTitle(this, originalTitle, mochaArgs, origFn, _testConfig)
}

return invokeFnWithOriginalTitle(this, originalTitle, mochaArgs, _fn['skip'])
return invokeFnWithOriginalTitle(this, originalTitle, mochaArgs, _fn['skip'], _testConfig)
}

const ret = origFn.apply(this, mochaArgs)

ret.cfg = opts
ret._testConfig = _testConfig

return ret
}
Expand Down Expand Up @@ -327,7 +326,7 @@ function patchTestClone () {
const ret = testClone.apply(this, arguments)

// carry over testConfigOverrides
ret.cfg = this.cfg
ret._testConfig = this._testConfig

// carry over test.id
ret.id = this.id
Expand Down
26 changes: 24 additions & 2 deletions packages/driver/src/cypress/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const $Log = require('./log')
const $utils = require('./utils')
const $errUtils = require('./error_utils')
const $stackUtils = require('./stack_utils')
const { getResolvedTestConfigOverride } = require('../cy/testConfigOverrides')

const mochaCtxKeysRe = /^(_runnable|test)$/
const betweenQuotesRe = /\"(.+?)\"/
Expand All @@ -18,8 +19,7 @@ const TEST_BEFORE_RUN_EVENT = 'runner:test:before:run'
const TEST_AFTER_RUN_EVENT = 'runner:test:after:run'

const RUNNABLE_LOGS = 'routes agents commands hooks'.split(' ')
const RUNNABLE_PROPS = 'id order title root hookName hookId err state failedFromHookId body speed type duration wallClockStartedAt wallClockDuration timings file originalTitle invocationDetails final currentRetry retries'.split(' ')

const RUNNABLE_PROPS = '_testConfig id order title _titlePath root hookName hookId err state failedFromHookId body speed type duration wallClockStartedAt wallClockDuration timings file originalTitle invocationDetails final currentRetry retries'.split(' ')
const debug = require('debug')('cypress:driver:runner')

const fire = (event, runnable, Cypress) => {
Expand Down Expand Up @@ -493,6 +493,17 @@ const normalizeAll = (suite, initialTests = {}, setTestsById, setTests, onRunnab
setTests(testsArr)
}

// generate the diff of the config after spec has been executed
// e.g. config changes via Cypress.config('...')
normalizedSuite.runtimeConfig = {}
_.map(Cypress.config(), (v, key) => {
if (_.isEqual(v, Cypress.originalConfig[key])) {
return null
}

normalizedSuite.runtimeConfig[key] = v
})

return normalizedSuite
}

Expand Down Expand Up @@ -548,6 +559,17 @@ const normalize = (runnable, tests, initialTests, onRunnable, onLogsById, getRun
// and collections
const wrappedRunnable = wrapAll(runnable)

if (runnable.type === 'test') {
const cfg = getResolvedTestConfigOverride(runnable)

if (_.size(cfg)) {
runnable._testConfig = cfg
wrappedRunnable._testConfig = cfg
}

wrappedRunnable._titlePath = runnable.titlePath()
}

if (prevAttempts) {
wrappedRunnable.prevAttempts = prevAttempts
}
Expand Down
1 change: 1 addition & 0 deletions packages/runner-ct/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"@babel/preset-env": "^7.12.1",
"@packages/driver": "0.0.0-development",
"@percy/cypress": "2.3.4",
"@types/node": "12.12.50",
"@types/sockjs-client": "1.1.0",
"babel-loader": "8.1.0",
"clean-webpack-plugin": "^3.0.0",
Expand Down
12 changes: 7 additions & 5 deletions packages/runner-ct/src/lib/event-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,18 +269,20 @@ const eventManager = {
Cypress.runner.setStartTime(state.startTime)
}

if (config.isTextTerminal && !state.currentId) {
// we are in run mode and it's the first load
// store runnables in backend and maybe send to dashboard
return ws.emit('set:runnables:and:maybe:record:tests', runnables, run)
}

if (state.currentId) {
// if we have a currentId it means
// we need to tell the Cypress to skip
// ahead to that test
Cypress.runner.resumeAtTest(state.currentId, state.emissions)
}

if (config.isTextTerminal && !state.currentId) {
ws.emit('set:runnables', runnables, run)
} else {
run()
}
run()
})
},
})
Expand Down
2 changes: 1 addition & 1 deletion packages/runner/cypress/support/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ function createCypress (defaultOptions = {}) {
url: opts.visitUrl,
} })

.withArgs('set:runnables')
.withArgs('set:runnables:and:maybe:record:tests')
.callsFake((...args) => {
setRunnablesStub(...args)
_.last(args)()
Expand Down
12 changes: 7 additions & 5 deletions packages/runner/src/lib/event-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -340,18 +340,20 @@ const eventManager = {
Cypress.runner.setStartTime(state.startTime)
}

if (config.isTextTerminal && !state.currentId) {
// we are in run mode and it's the first load
// store runnables in backend and maybe send to dashboard
return ws.emit('set:runnables:and:maybe:record:tests', runnables, run)
}

if (state.currentId) {
// if we have a currentId it means
// we need to tell the Cypress to skip
// ahead to that test
Cypress.runner.resumeAtTest(state.currentId, state.emissions)
}

if (config.isTextTerminal && !state.currentId) {
ws.emit('set:runnables', runnables, run)
} else {
run()
}
run()
})
},
})
Expand Down
Loading