mirror of
https://github.com/cypress-io/cypress.git
synced 2026-01-28 18:08:47 -06:00
chore: migrate mochaEvents integration tests from runner to app (#20678)
* mocha-events * wip * work on snapshots tests * update * lint * remove unused code * revert some changes * remove old code * migrate retries tests to app * reduce duplication * remove old code * rename method * use disparity
This commit is contained in:
136
packages/app/cypress/e2e/runner/retries.mochaEvents.cy.ts
Normal file
136
packages/app/cypress/e2e/runner/retries.mochaEvents.cy.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
import { runSpec } from './support/spec-loader'
|
||||
import { runCypressInCypressMochaEventsTest } from './support/mochaEventsUtils'
|
||||
import { snapshots } from './retries.mochaEvents.snapshots'
|
||||
|
||||
describe('src/cypress/runner retries mochaEvents', { retries: 0 }, () => {
|
||||
// NOTE: for test-retries
|
||||
|
||||
it('simple retry', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner retries mochaEvents simple retry #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'simple-fail.retries.mochaEvents.cy.js',
|
||||
}).then((win) => {
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
|
||||
it('test retry with hooks', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner retries mochaEvents test retry with hooks #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'test-retry-with-hooks.retries.mochaEvents.cy.js',
|
||||
}).then((win) => {
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
|
||||
it('test retry with hooks', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner retries mochaEvents test retry with hooks #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'test-retry-with-hooks.retries.mochaEvents.cy.js',
|
||||
}).then((win) => {
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
|
||||
it('test retry with [only]', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner retries mochaEvents test retry with [only] #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'test-retry-with-only.retries.mochaEvents.cy.js',
|
||||
}).then((win) => {
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
|
||||
it('can retry from [beforeEach]', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner retries mochaEvents can retry from [beforeEach] #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'can-retry-from-beforeEach.retries.mochaEvents.cy.js',
|
||||
}).then((win) => {
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
|
||||
it('can retry from [afterEach]', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner retries mochaEvents can retry from [afterEach] #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'can-retry-from-afterEach.retries.mochaEvents.cy.js',
|
||||
}).then((win) => {
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
|
||||
it('cant retry from [before]', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner retries mochaEvents cant retry from [before] #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'cant-retry-from-before.retries.mochaEvents.cy.js',
|
||||
}).then((win) => {
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
|
||||
it('three tests with retry', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner retries mochaEvents three tests with retry #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'three-tests-with-retry.retries.mochaEvents.cy.js',
|
||||
}).then((win) => {
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
|
||||
describe('cleanses errors before emitting', () => {
|
||||
it('does not try to serialize error with err.actual as DOM node', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner retries mochaEvents cleanses errors before emitting does not try to serialize error with err.actual as DOM node #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'does-not-serialize-dom-error.cy.js',
|
||||
}).then((win) => {
|
||||
// should not have err.actual, expected properties since the subject is a DOM element
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
7120
packages/app/cypress/e2e/runner/retries.mochaEvents.snapshots.ts
Normal file
7120
packages/app/cypress/e2e/runner/retries.mochaEvents.snapshots.ts
Normal file
File diff suppressed because it is too large
Load Diff
125
packages/app/cypress/e2e/runner/runner.mochaEvents.cy.ts
Normal file
125
packages/app/cypress/e2e/runner/runner.mochaEvents.cy.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
import { runSpec } from './support/spec-loader'
|
||||
import { runCypressInCypressMochaEventsTest } from './support/mochaEventsUtils'
|
||||
import { snapshots } from './runner.mochaEvents.snapshots'
|
||||
|
||||
describe('src/cypress/runner', { retries: 0 }, () => {
|
||||
describe('tests finish with correct state', () => {
|
||||
describe('hook failures', () => {
|
||||
it('fail in [before]', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner tests finish with correct state hook failures fail in [before] #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'fail-with-before.mochaEvents.cy.js',
|
||||
}).then((win) => {
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
|
||||
it('fail in [beforeEach]', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner tests finish with correct state hook failures fail in [beforeEach] #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'fail-with-beforeEach.mochaEvents.cy.js',
|
||||
}).then((win) => {
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
|
||||
it('fail in [after]', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner tests finish with correct state hook failures fail in [after] #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'fail-with-after.mochaEvents.cy.js',
|
||||
}).then((win) => {
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
|
||||
it('fail in [afterEach]', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner tests finish with correct state hook failures fail in [afterEach] #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'fail-with-afterEach.mochaEvents.cy.js',
|
||||
}).then((win) => {
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('mocha grep', () => {
|
||||
it('fail with [only]', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner tests finish with correct state mocha grep fail with [only] #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'fail-with-only.mochaEvents.cy.js',
|
||||
}).then((win) => {
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
|
||||
it('pass with [only]', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner tests finish with correct state mocha grep pass with [only] #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'pass-with-only.mochaEvents.cy.js',
|
||||
}).then((win) => {
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('mocha events', () => {
|
||||
it('simple single test', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner mocha events simple single test #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'simple-single-test.mochaEvents.cy.js',
|
||||
}).then((win) => {
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
|
||||
it('simple three tests', (done) => {
|
||||
const { assertMatchingSnapshot } = runCypressInCypressMochaEventsTest(
|
||||
snapshots,
|
||||
'src/cypress/runner mocha events simple three tests #1',
|
||||
done,
|
||||
)
|
||||
|
||||
runSpec({
|
||||
fileName: 'three-tests-with-hooks.mochaEvents.cy.js',
|
||||
}).then((win) => {
|
||||
assertMatchingSnapshot(win)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
3110
packages/app/cypress/e2e/runner/runner.mochaEvents.snapshots.ts
Normal file
3110
packages/app/cypress/e2e/runner/runner.mochaEvents.snapshots.ts
Normal file
File diff suppressed because it is too large
Load Diff
189
packages/app/cypress/e2e/runner/support/mochaEventsUtils.ts
Normal file
189
packages/app/cypress/e2e/runner/support/mochaEventsUtils.ts
Normal file
@@ -0,0 +1,189 @@
|
||||
import type { CypressInCypressMochaEvent } from '../../../../src/runner/event-manager'
|
||||
import _ from 'lodash'
|
||||
import type { MochaLifecycleData, SanitizedMochaLifecycleData } from './mochaTypes'
|
||||
import EventEmitter from 'events'
|
||||
import disparity from 'disparity'
|
||||
|
||||
const hooks = {
|
||||
before: ['before all', 'before each'],
|
||||
after: ['after each', 'after all'],
|
||||
} as const
|
||||
|
||||
const stringifyShort = (obj: Record<string, any>) => {
|
||||
const constructorName = _.get(obj, 'constructor.name')
|
||||
|
||||
if (constructorName && !_.includes(['Object', 'Array'], constructorName)) {
|
||||
return `{${constructorName}}`
|
||||
}
|
||||
|
||||
if (_.isArray(obj)) {
|
||||
return `[Array ${obj.length}]`
|
||||
}
|
||||
|
||||
if (_.isObject(obj)) {
|
||||
return `{Object ${Object.keys(obj).length}}`
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
const eventCleanseMap = {
|
||||
snapshots: stringifyShort,
|
||||
parent: stringifyShort,
|
||||
tests: stringifyShort,
|
||||
commands: stringifyShort,
|
||||
invocationDetails: stringifyShort,
|
||||
body: () => '[body]',
|
||||
wallClockStartedAt: () => 'match.date',
|
||||
lifecycle: () => 'match.number',
|
||||
fnDuration: () => 'match.number',
|
||||
duration: () => 'match.number',
|
||||
afterFnDuration: () => 'match.number',
|
||||
wallClockDuration: () => 'match.number',
|
||||
stack: () => 'match.string',
|
||||
file: (arg: string) => arg ? 'relative/path/to/spec.js' : undefined,
|
||||
message: () => '[error message]',
|
||||
sourceMappedStack: () => 'match.string',
|
||||
parsedStack: () => 'match.array',
|
||||
name: (n: string) => n === 'Error' ? 'AssertionError' : n,
|
||||
err: () => {
|
||||
return {
|
||||
message: '[error message]',
|
||||
name: 'AssertionError',
|
||||
stack: 'match.string',
|
||||
sourceMappedStack: 'match.string',
|
||||
parsedStack: 'match.array',
|
||||
}
|
||||
},
|
||||
startTime: new Date(0),
|
||||
start: () => 'match.date',
|
||||
end: () => 'match.date',
|
||||
timings: (arg: MochaLifecycleData): SanitizedMochaLifecycleData => {
|
||||
let sanitizedLifecycleData: SanitizedMochaLifecycleData = {
|
||||
lifecycle: 'match.number',
|
||||
}
|
||||
|
||||
for (const hook of hooks.before) {
|
||||
const hooksToSanitize = arg[hook]
|
||||
|
||||
if (!hooksToSanitize) {
|
||||
continue
|
||||
}
|
||||
|
||||
sanitizedLifecycleData[hook] = hooksToSanitize.map((oldHook) => {
|
||||
return {
|
||||
hookId: oldHook.hookId,
|
||||
fnDuration: 'match.number',
|
||||
afterFnDuration: 'match.number',
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (arg.test) {
|
||||
sanitizedLifecycleData.test = {
|
||||
fnDuration: 'match.number',
|
||||
afterFnDuration: 'match.number',
|
||||
}
|
||||
}
|
||||
|
||||
for (const hook of hooks.after) {
|
||||
const hooksToSanitize = arg[hook]
|
||||
|
||||
if (!hooksToSanitize) {
|
||||
continue
|
||||
}
|
||||
|
||||
sanitizedLifecycleData[hook] = hooksToSanitize.map((oldHook) => {
|
||||
return {
|
||||
hookId: oldHook.hookId,
|
||||
fnDuration: 'match.number',
|
||||
afterFnDuration: 'match.number',
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return sanitizedLifecycleData
|
||||
},
|
||||
}
|
||||
|
||||
const keysToEliminate = ['codeFrame', '_testConfig'] as const
|
||||
|
||||
function removeUnusedKeysForTestSnapshot<T> (obj: T): T {
|
||||
for (const key of keysToEliminate) {
|
||||
delete obj[key]
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
if (key in obj) {
|
||||
const transform = eventCleanseMap[key]?.(value)
|
||||
|
||||
if (!transform) {
|
||||
continue
|
||||
}
|
||||
|
||||
obj[key] = transform
|
||||
} else {
|
||||
delete obj[key]
|
||||
}
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
bus: EventEmitter
|
||||
}
|
||||
}
|
||||
|
||||
class SnapshotError extends Error {
|
||||
constructor (message: string) {
|
||||
super()
|
||||
this.message = `\n${message}`
|
||||
}
|
||||
}
|
||||
|
||||
export function runCypressInCypressMochaEventsTest<T> (snapshots: T, snapToCompare: keyof T, done: Mocha.Done) {
|
||||
const bus = new EventEmitter()
|
||||
const outerRunner = window.top!.window
|
||||
|
||||
outerRunner.bus = bus
|
||||
|
||||
// TODO: Can we automate writing the snapshots to disk?
|
||||
// For some reason `cy.task('getSnapshot')` has problems when executed in
|
||||
// "cypress in cypress"
|
||||
bus.on('assert:cypress:in:cypress', (snapshot: CypressInCypressMochaEvent[]) => {
|
||||
const expected = snapshots[snapToCompare]
|
||||
const diff = disparity.unifiedNoColor(JSON.stringify(snapshot, null, 2), JSON.stringify(expected, null, 2), {})
|
||||
|
||||
if (diff !== '') {
|
||||
/* eslint-disable no-console */
|
||||
console.info('Received snapshot:', JSON.stringify(snapshot, null, 2))
|
||||
throw new SnapshotError(diff)
|
||||
}
|
||||
|
||||
done()
|
||||
})
|
||||
|
||||
const assertMatchingSnapshot = (win: Cypress.AUTWindow) => {
|
||||
win.getEventManager().on('cypress:in:cypress:run:complete', (args: CypressInCypressMochaEvent[]) => {
|
||||
const data = sanitizeMochaEvents(args)
|
||||
|
||||
bus.emit('assert:cypress:in:cypress', data)
|
||||
})
|
||||
}
|
||||
|
||||
return { assertMatchingSnapshot }
|
||||
}
|
||||
|
||||
function sanitizeMochaEvents (args: CypressInCypressMochaEvent[]) {
|
||||
return args.map((mochaEvent) => {
|
||||
return mochaEvent.map((payload) => {
|
||||
if (typeof payload === 'string') {
|
||||
return payload
|
||||
}
|
||||
|
||||
return removeUnusedKeysForTestSnapshot(payload)
|
||||
})
|
||||
})
|
||||
}
|
||||
23
packages/app/cypress/e2e/runner/support/mochaTypes.ts
Normal file
23
packages/app/cypress/e2e/runner/support/mochaTypes.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
export type Timing = {
|
||||
hookId: `h${number}`
|
||||
fnDuration: number
|
||||
afterFnDuration: number
|
||||
}
|
||||
|
||||
export type SanitizedTiming = {
|
||||
hookId?: `h${number}`
|
||||
fnDuration: 'match.number'
|
||||
afterFnDuration: 'match.number'
|
||||
}
|
||||
|
||||
export type MochaLifecycleBase<T> = {
|
||||
'test'?: T
|
||||
'before each'?: T[]
|
||||
'after each'?: T[]
|
||||
'before all'?: T[]
|
||||
'after all'?: T[]
|
||||
}
|
||||
|
||||
export type MochaLifecycleData = MochaLifecycleBase<Timing> & { lifecycle: number }
|
||||
|
||||
export type SanitizedMochaLifecycleData = MochaLifecycleBase<SanitizedTiming> & { lifecycle: string }
|
||||
@@ -21,7 +21,7 @@ export type LoadSpecOptions = {
|
||||
hasPreferredIde?: boolean
|
||||
}
|
||||
|
||||
export function loadSpec (options: LoadSpecOptions): void {
|
||||
export function loadSpec (options: LoadSpecOptions) {
|
||||
const {
|
||||
fileName,
|
||||
setup,
|
||||
@@ -78,3 +78,23 @@ export function loadSpec (options: LoadSpecOptions): void {
|
||||
// Wait for specs to complete
|
||||
shouldHaveTestResults({ passCount, failCount, pendingCount })
|
||||
}
|
||||
|
||||
export function runSpec ({ fileName }: { fileName: string }) {
|
||||
cy.scaffoldProject('runner-e2e-specs')
|
||||
cy.openProject('runner-e2e-specs')
|
||||
cy.startAppServer()
|
||||
|
||||
cy.__incorrectlyVisitAppWithIntercept()
|
||||
|
||||
cy.findByLabelText('Search Specs').type(fileName)
|
||||
// wait for virtualized spec list to update, there is a chance
|
||||
// of disconnection otherwise
|
||||
cy.wait(500)
|
||||
cy.contains('[data-cy=spec-item]', fileName).click()
|
||||
|
||||
cy.location().should((location) => {
|
||||
expect(location.hash).to.contain(fileName)
|
||||
})
|
||||
|
||||
return cy.window()
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
"concurrently": "^6.2.0",
|
||||
"cross-env": "6.0.3",
|
||||
"cypress-real-events": "1.6.0",
|
||||
"disparity": "^3.0.0",
|
||||
"faker": "5.5.3",
|
||||
"fuzzysort": "^1.1.4",
|
||||
"graphql": "^15.5.1",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { FileDetails } from '@packages/types'
|
||||
import type { ScriptError } from '../store'
|
||||
import type { CypressInCypressMochaEvent } from './event-manager'
|
||||
|
||||
interface BeforeScreenshot {
|
||||
appOnly: boolean
|
||||
@@ -21,6 +22,7 @@ export type LocalBusEventMap = {
|
||||
|
||||
export type LocalBusEmitsMap = {
|
||||
'open:file': FileDetails
|
||||
'cypress:in:cypress:run:complete': CypressInCypressMochaEvent[]
|
||||
}
|
||||
|
||||
export type SocketToDriverMap = {
|
||||
|
||||
@@ -11,6 +11,8 @@ import { logger } from './logger'
|
||||
import type { Socket } from '@packages/socket/lib/browser'
|
||||
import { useRunnerUiStore } from '../store'
|
||||
|
||||
export type CypressInCypressMochaEvent = Array<Array<string | Record<string, any>>>
|
||||
|
||||
// type is default export of '@packages/driver'
|
||||
// cannot import because it's not type safe and tsc throw many type errors.
|
||||
type $Cypress = any
|
||||
@@ -26,7 +28,7 @@ const driverToReporterEvents = 'paused session:add'.split(' ')
|
||||
const driverToLocalAndReporterEvents = 'run:start run:end'.split(' ')
|
||||
const driverToSocketEvents = 'backend:request automation:request mocha recorder:frame'.split(' ')
|
||||
const driverTestEvents = 'test:before:run:async test:after:run'.split(' ')
|
||||
const driverToLocalEvents = 'viewport:changed config stop url:changed page:loading visit:failed visit:blank'.split(' ')
|
||||
const driverToLocalEvents = 'viewport:changed config stop url:changed page:loading visit:failed visit:blank cypress:in:cypress:runner:event'.split(' ')
|
||||
const socketRerunEvents = 'runner:restart watched:file:changed'.split(' ')
|
||||
const socketToDriverEvents = 'net:stubbing:event request:event script:error'.split(' ')
|
||||
const localToReporterEvents = 'reporter:log:add reporter:log:state:changed reporter:log:remove'.split(' ')
|
||||
@@ -42,6 +44,7 @@ export class EventManager {
|
||||
Cypress?: $Cypress
|
||||
studioRecorder: any
|
||||
selectorPlaygroundModel: any
|
||||
cypressInCypressMochaEvents: CypressInCypressMochaEvent[] = []
|
||||
|
||||
constructor (
|
||||
// import '@packages/driver'
|
||||
@@ -531,6 +534,22 @@ export class EventManager {
|
||||
|
||||
driverToLocalEvents.forEach((event) => {
|
||||
Cypress.on(event, (...args: unknown[]) => {
|
||||
// special case for asserting the correct mocha events + payload
|
||||
// is emitted from cypress/driver when running e2e tests using
|
||||
// "cypress in cypress"
|
||||
if (event === 'cypress:in:cypress:runner:event') {
|
||||
this.cypressInCypressMochaEvents.push(args as CypressInCypressMochaEvent[])
|
||||
|
||||
if (args[0] === 'mocha' && args[1] === 'end') {
|
||||
this.emit('cypress:in:cypress:run:complete', this.cypressInCypressMochaEvents)
|
||||
|
||||
// reset
|
||||
this.cypressInCypressMochaEvents = []
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
// TODO: UNIFY-1318 - strongly typed event emitter.
|
||||
return this.emit(event, ...args)
|
||||
|
||||
@@ -72,6 +72,9 @@ interface AutomationError extends Error {
|
||||
automation: boolean
|
||||
}
|
||||
|
||||
// Are we running Cypress in Cypress? (Used for E2E Testing for Cypress in Cypress only)
|
||||
const isCypressInCypress = document.defaultView !== top
|
||||
|
||||
class $Cypress {
|
||||
cy: any
|
||||
chai: any
|
||||
@@ -372,6 +375,17 @@ class $Cypress {
|
||||
})
|
||||
}
|
||||
|
||||
maybeEmitCypressInCypress (...args: unknown[]) {
|
||||
// emit an event if we are running a Cypress in Cypress E2E Test.
|
||||
// used to assert the runner (mocha) is emitting the expected
|
||||
// events/payload.
|
||||
if (!isCypressInCypress) {
|
||||
return
|
||||
}
|
||||
|
||||
this.emit('cypress:in:cypress:runner:event', ...args)
|
||||
}
|
||||
|
||||
action (eventName, ...args) {
|
||||
// normalizes all the various ways
|
||||
// other objects communicate intent
|
||||
@@ -397,6 +411,8 @@ class $Cypress {
|
||||
return
|
||||
}
|
||||
|
||||
this.maybeEmitCypressInCypress('mocha', 'start', args[0])
|
||||
|
||||
if (this.config('isTextTerminal')) {
|
||||
return this.emit('mocha', 'start', args[0])
|
||||
}
|
||||
@@ -415,6 +431,8 @@ class $Cypress {
|
||||
// test:after:run events ourselves
|
||||
this.emit('run:end')
|
||||
|
||||
this.maybeEmitCypressInCypress('mocha', 'end', args[0])
|
||||
|
||||
if (this.config('isTextTerminal')) {
|
||||
return this.emit('mocha', 'end', args[0])
|
||||
}
|
||||
@@ -423,6 +441,8 @@ class $Cypress {
|
||||
|
||||
case 'runner:suite:start':
|
||||
// mocha runner started processing a suite
|
||||
this.maybeEmitCypressInCypress('mocha', 'suite', ...args)
|
||||
|
||||
if (this.config('isTextTerminal')) {
|
||||
return this.emit('mocha', 'suite', ...args)
|
||||
}
|
||||
@@ -431,6 +451,8 @@ class $Cypress {
|
||||
|
||||
case 'runner:suite:end':
|
||||
// mocha runner finished processing a suite
|
||||
this.maybeEmitCypressInCypress('mocha', 'suite end', ...args)
|
||||
|
||||
if (this.config('isTextTerminal')) {
|
||||
return this.emit('mocha', 'suite end', ...args)
|
||||
}
|
||||
@@ -439,6 +461,9 @@ class $Cypress {
|
||||
|
||||
case 'runner:hook:start':
|
||||
// mocha runner started processing a hook
|
||||
|
||||
this.maybeEmitCypressInCypress('mocha', 'hook', ...args)
|
||||
|
||||
if (this.config('isTextTerminal')) {
|
||||
return this.emit('mocha', 'hook', ...args)
|
||||
}
|
||||
@@ -447,6 +472,8 @@ class $Cypress {
|
||||
|
||||
case 'runner:hook:end':
|
||||
// mocha runner finished processing a hook
|
||||
this.maybeEmitCypressInCypress('mocha', 'hook end', ...args)
|
||||
|
||||
if (this.config('isTextTerminal')) {
|
||||
return this.emit('mocha', 'hook end', ...args)
|
||||
}
|
||||
@@ -455,6 +482,8 @@ class $Cypress {
|
||||
|
||||
case 'runner:test:start':
|
||||
// mocha runner started processing a hook
|
||||
this.maybeEmitCypressInCypress('mocha', 'test', ...args)
|
||||
|
||||
if (this.config('isTextTerminal')) {
|
||||
return this.emit('mocha', 'test', ...args)
|
||||
}
|
||||
@@ -462,6 +491,8 @@ class $Cypress {
|
||||
break
|
||||
|
||||
case 'runner:test:end':
|
||||
this.maybeEmitCypressInCypress('mocha', 'test end', ...args)
|
||||
|
||||
if (this.config('isTextTerminal')) {
|
||||
return this.emit('mocha', 'test end', ...args)
|
||||
}
|
||||
@@ -472,6 +503,8 @@ class $Cypress {
|
||||
// mocha runner calculated a pass
|
||||
// this is delayed from when mocha would normally fire it
|
||||
// since we fire it after all afterEach hooks have ran
|
||||
this.maybeEmitCypressInCypress('mocha', 'pass', ...args)
|
||||
|
||||
if (this.config('isTextTerminal')) {
|
||||
return this.emit('mocha', 'pass', ...args)
|
||||
}
|
||||
@@ -480,6 +513,8 @@ class $Cypress {
|
||||
|
||||
case 'runner:pending':
|
||||
// mocha runner calculated a pending test
|
||||
this.maybeEmitCypressInCypress('mocha', 'pending', ...args)
|
||||
|
||||
if (this.config('isTextTerminal')) {
|
||||
return this.emit('mocha', 'pending', ...args)
|
||||
}
|
||||
@@ -487,6 +522,8 @@ class $Cypress {
|
||||
break
|
||||
|
||||
case 'runner:fail': {
|
||||
this.maybeEmitCypressInCypress('mocha', 'fail', ...args)
|
||||
|
||||
if (this.config('isTextTerminal')) {
|
||||
return this.emit('mocha', 'fail', ...args)
|
||||
}
|
||||
@@ -497,6 +534,8 @@ class $Cypress {
|
||||
// https://github.com/mochajs/mocha/commit/2a76dd7589e4a1ed14dd2a33ab89f182e4c4a050
|
||||
case 'runner:retry': {
|
||||
// mocha runner calculated a pass
|
||||
this.maybeEmitCypressInCypress('mocha', 'retry', ...args)
|
||||
|
||||
if (this.config('isTextTerminal')) {
|
||||
this.emit('mocha', 'retry', ...args)
|
||||
}
|
||||
@@ -508,6 +547,8 @@ class $Cypress {
|
||||
return this.runner.onRunnableRun(...args)
|
||||
|
||||
case 'runner:test:before:run':
|
||||
this.maybeEmitCypressInCypress('mocha', 'test:before:run', args[0])
|
||||
|
||||
if (this.config('isTextTerminal')) {
|
||||
// needed for handling test retries
|
||||
this.emit('mocha', 'test:before:run', args[0])
|
||||
@@ -529,6 +570,7 @@ class $Cypress {
|
||||
// this event is how the reporter knows how to display
|
||||
// stats and runnable properties such as errors
|
||||
this.emit('test:after:run', ...args)
|
||||
this.maybeEmitCypressInCypress('mocha', 'test:after:run', args[0])
|
||||
|
||||
if (this.config('isTextTerminal')) {
|
||||
// needed for calculating wallClockDuration
|
||||
|
||||
@@ -158,6 +158,7 @@ export const e2eProjectDirs = [
|
||||
'vueclivue3-configured',
|
||||
'vueclivue3-custom-index-html',
|
||||
'vueclivue3-unconfigured',
|
||||
'webpack-dev-server',
|
||||
'webpack-preprocessor',
|
||||
'webpack-preprocessor-awesome-typescript-loader',
|
||||
'webpack-preprocessor-ts-loader',
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,23 +1,10 @@
|
||||
const helpers = require('../support/helpers')
|
||||
|
||||
const { shouldHaveTestResults, getRunState, cleanseRunStateMap } = helpers
|
||||
const { runIsolatedCypress, snapshotMochaEvents, getAutCypress } = helpers.createCypress({ config: { retries: 2, isTextTerminal: true } })
|
||||
const { runIsolatedCypress, getAutCypress } = helpers.createCypress({ config: { retries: 2, isTextTerminal: true } })
|
||||
const { sinon } = Cypress
|
||||
const match = Cypress.sinon.match
|
||||
|
||||
const threeTestsWithRetry = {
|
||||
suites: {
|
||||
'suite 1': {
|
||||
hooks: ['before', 'beforeEach', 'afterEach', 'after'],
|
||||
tests: [
|
||||
'test 1',
|
||||
{ name: 'test 2', fail: 2 },
|
||||
'test 3',
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
describe('src/cypress/runner retries mochaEvents', { retries: 0 }, () => {
|
||||
// NOTE: for test-retries
|
||||
it('can set retry config', () => {
|
||||
@@ -27,142 +14,6 @@ describe('src/cypress/runner retries mochaEvents', { retries: 0 }, () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('simple retry', () => {
|
||||
runIsolatedCypress({
|
||||
suites: {
|
||||
'suite 1': {
|
||||
tests: [
|
||||
{ name: 'test 1',
|
||||
fail: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}, { config: { retries: 1 } })
|
||||
.then(snapshotMochaEvents)
|
||||
})
|
||||
|
||||
it('test retry with hooks', () => {
|
||||
runIsolatedCypress({
|
||||
suites: {
|
||||
'suite 1': {
|
||||
hooks: ['before', 'beforeEach', 'afterEach', 'after'],
|
||||
tests: [{ name: 'test 1', fail: 1 }],
|
||||
},
|
||||
},
|
||||
}, { config: { retries: 1 } })
|
||||
.then(snapshotMochaEvents)
|
||||
})
|
||||
|
||||
it('test retry with [only]', () => {
|
||||
runIsolatedCypress({
|
||||
suites: {
|
||||
'suite 1': {
|
||||
hooks: ['before', 'beforeEach', 'afterEach', 'after'],
|
||||
tests: [
|
||||
{ name: 'test 1' },
|
||||
{ name: 'test 2', fail: 1, only: true },
|
||||
{ name: 'test 3' },
|
||||
],
|
||||
},
|
||||
},
|
||||
}, { config: { retries: 1 } })
|
||||
.then(snapshotMochaEvents)
|
||||
})
|
||||
|
||||
it('can retry from [beforeEach]', () => {
|
||||
runIsolatedCypress({
|
||||
suites: {
|
||||
'suite 1': {
|
||||
hooks: [
|
||||
'before',
|
||||
'beforeEach',
|
||||
{ type: 'beforeEach', fail: 1 },
|
||||
'beforeEach',
|
||||
'afterEach',
|
||||
'after',
|
||||
],
|
||||
tests: [{ name: 'test 1' }],
|
||||
},
|
||||
},
|
||||
}, { config: { retries: 1 } })
|
||||
.then(snapshotMochaEvents)
|
||||
})
|
||||
|
||||
it('can retry from [afterEach]', () => {
|
||||
runIsolatedCypress({
|
||||
hooks: [{ type: 'afterEach', fail: 1 }],
|
||||
suites: {
|
||||
'suite 1': {
|
||||
hooks: [
|
||||
'before',
|
||||
'beforeEach',
|
||||
'beforeEach',
|
||||
'afterEach',
|
||||
'after',
|
||||
],
|
||||
tests: [{ name: 'test 1' }, 'test 2', 'test 3'],
|
||||
},
|
||||
'suite 2': {
|
||||
hooks: [{ type: 'afterEach', fail: 2 }],
|
||||
tests: ['test 1'],
|
||||
},
|
||||
'suite 3': {
|
||||
tests: ['test 1'],
|
||||
},
|
||||
},
|
||||
}, { config: { retries: 2, isTextTerminal: true } })
|
||||
|
||||
.then(snapshotMochaEvents)
|
||||
})
|
||||
|
||||
it('cant retry from [before]', () => {
|
||||
runIsolatedCypress({
|
||||
suites: {
|
||||
'suite 1': {
|
||||
hooks: [
|
||||
{ type: 'before', fail: 1 },
|
||||
'beforeEach',
|
||||
'beforeEach',
|
||||
'afterEach',
|
||||
'afterEach',
|
||||
'after',
|
||||
],
|
||||
tests: [{ name: 'test 1' }],
|
||||
},
|
||||
},
|
||||
}, { config: { retries: 1 } })
|
||||
.then(snapshotMochaEvents)
|
||||
})
|
||||
|
||||
it('cant retry from [after]', () => {
|
||||
runIsolatedCypress({
|
||||
suites: {
|
||||
'suite 1': {
|
||||
hooks: [
|
||||
'before',
|
||||
'beforeEach',
|
||||
'beforeEach',
|
||||
'afterEach',
|
||||
'afterEach',
|
||||
{ type: 'after', fail: 1 },
|
||||
],
|
||||
tests: [{ name: 'test 1' }],
|
||||
},
|
||||
},
|
||||
}, { config: { retries: 1 } })
|
||||
.then(snapshotMochaEvents)
|
||||
})
|
||||
|
||||
it('three tests with retry', () => {
|
||||
runIsolatedCypress(threeTestsWithRetry, {
|
||||
config: {
|
||||
retries: 2,
|
||||
},
|
||||
})
|
||||
.then(snapshotMochaEvents)
|
||||
})
|
||||
|
||||
describe('screenshots', () => {
|
||||
it('retry screenshot in test body', () => {
|
||||
let onAfterScreenshot
|
||||
@@ -249,20 +100,6 @@ describe('src/cypress/runner retries mochaEvents', { retries: 0 }, () => {
|
||||
})
|
||||
})
|
||||
|
||||
// https://github.com/cypress-io/cypress/issues/8363
|
||||
describe('cleanses errors before emitting', () => {
|
||||
it('does not try to serialize error with err.actual as DOM node', () => {
|
||||
runIsolatedCypress(() => {
|
||||
it('visits', () => {
|
||||
cy.visit('/fixtures/dom.html')
|
||||
cy.get('#button').should('not.be.visible')
|
||||
})
|
||||
}, { config: { defaultCommandTimeout: 200 } })
|
||||
// should not have err.actual, expected properties since the subject is a DOM element
|
||||
.then(snapshotMochaEvents)
|
||||
})
|
||||
})
|
||||
|
||||
describe('save/reload state', () => {
|
||||
const serializeState = () => {
|
||||
return getRunState(getAutCypress())
|
||||
|
||||
@@ -3,148 +3,9 @@ const sinon = require('sinon')
|
||||
const helpers = require('../support/helpers')
|
||||
|
||||
const { cleanseRunStateMap, shouldHaveTestResults, getRunState } = helpers
|
||||
const { runIsolatedCypress, snapshotMochaEvents, getAutCypress } = helpers.createCypress({ config: { isTextTerminal: true, retries: 0 } })
|
||||
|
||||
const simpleSingleTest = {
|
||||
suites: { 'suite 1': { tests: [{ name: 'test 1' }] } },
|
||||
}
|
||||
|
||||
const threeTestsWithHooks = {
|
||||
suites: { 'suite 1': { hooks: ['before', 'beforeEach', 'afterEach', 'after'], tests: ['test 1', 'test 2', 'test 3'] } },
|
||||
}
|
||||
const { runIsolatedCypress, getAutCypress } = helpers.createCypress({ config: { isTextTerminal: true, retries: 0 } })
|
||||
|
||||
describe('src/cypress/runner', { retries: 0 }, () => {
|
||||
describe('tests finish with correct state', () => {
|
||||
describe('hook failures', () => {
|
||||
it('fail in [before]', () => {
|
||||
runIsolatedCypress({
|
||||
suites: {
|
||||
'suite 1': {
|
||||
hooks: [
|
||||
{
|
||||
type: 'before',
|
||||
fail: true,
|
||||
},
|
||||
],
|
||||
tests: [{ name: 'test 1' }],
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(shouldHaveTestResults(0, 1))
|
||||
.then(() => {
|
||||
cy.get('.runnable-err:visible').invoke('text').should('contain', 'Because this error occurred during a before all hook')
|
||||
})
|
||||
.then(() => {
|
||||
snapshotMochaEvents()
|
||||
})
|
||||
})
|
||||
|
||||
it('fail in [beforeEach]', () => {
|
||||
runIsolatedCypress({
|
||||
suites: {
|
||||
'suite 1': {
|
||||
hooks: [
|
||||
{
|
||||
type: 'beforeEach',
|
||||
fail: true,
|
||||
},
|
||||
],
|
||||
tests: [{ name: 'test 1' }],
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(shouldHaveTestResults(0, 1))
|
||||
.then(() => {
|
||||
snapshotMochaEvents()
|
||||
})
|
||||
})
|
||||
|
||||
it('fail in [afterEach]', () => {
|
||||
runIsolatedCypress({
|
||||
suites: {
|
||||
'suite 1': {
|
||||
hooks: [
|
||||
{
|
||||
type: 'afterEach',
|
||||
fail: true,
|
||||
},
|
||||
],
|
||||
tests: [{ name: 'test 1' }],
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(shouldHaveTestResults(0, 1))
|
||||
.then(() => {
|
||||
snapshotMochaEvents()
|
||||
})
|
||||
})
|
||||
|
||||
it('fail in [after]', () => {
|
||||
runIsolatedCypress({
|
||||
suites: {
|
||||
'suite 1': {
|
||||
hooks: [
|
||||
{
|
||||
type: 'after',
|
||||
fail: true,
|
||||
},
|
||||
],
|
||||
tests: ['test 1', 'test 2'],
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(shouldHaveTestResults(1, 1))
|
||||
.then(() => {
|
||||
expect('foo').contain('f')
|
||||
cy.get('.runnable-err:visible').invoke('text').should('contain', 'Because this error occurred during a after all hook')
|
||||
})
|
||||
.then(() => {
|
||||
snapshotMochaEvents()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('mocha grep', () => {
|
||||
it('fail with [only]', () => {
|
||||
runIsolatedCypress({
|
||||
suites: {
|
||||
'suite 1': {
|
||||
hooks: ['before', 'beforeEach', 'afterEach', 'after'],
|
||||
tests: [
|
||||
{ name: 'test 1', fail: true },
|
||||
{ name: 'test 2', fail: true, only: true },
|
||||
{ name: 'test 3', fail: true },
|
||||
],
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(shouldHaveTestResults(0, 1))
|
||||
.then(() => {
|
||||
snapshotMochaEvents()
|
||||
})
|
||||
})
|
||||
|
||||
it('pass with [only]', () => {
|
||||
runIsolatedCypress({
|
||||
suites: {
|
||||
'suite 1': {
|
||||
hooks: ['before', 'beforeEach', 'afterEach', 'after'],
|
||||
tests: [
|
||||
{ name: 'test 1' },
|
||||
{ name: 'test 2', only: true },
|
||||
{ name: 'test 3' },
|
||||
],
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(shouldHaveTestResults(1, 0))
|
||||
.then(() => {
|
||||
snapshotMochaEvents()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('save/reload state on top navigation', () => {
|
||||
describe('serialize / load from state', () => {
|
||||
const serializeState = () => {
|
||||
@@ -291,22 +152,6 @@ describe('src/cypress/runner', { retries: 0 }, () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('mocha events', () => {
|
||||
it('simple single test', () => {
|
||||
runIsolatedCypress(simpleSingleTest)
|
||||
.then(() => {
|
||||
snapshotMochaEvents()
|
||||
})
|
||||
})
|
||||
|
||||
it('simple three tests', () => {
|
||||
runIsolatedCypress(threeTestsWithHooks)
|
||||
.then(() => {
|
||||
snapshotMochaEvents()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('event listeners', () => {
|
||||
// https://github.com/cypress-io/cypress/issues/8701
|
||||
it('does not hang when error thrown in test:after:run', () => {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
let i = 0
|
||||
|
||||
afterEach(() => {
|
||||
if (i === 0) {
|
||||
i++
|
||||
throw new Error('')
|
||||
}
|
||||
})
|
||||
|
||||
describe('suite 1', { retries: 2 }, () => {
|
||||
before(() => {})
|
||||
beforeEach(() => {})
|
||||
beforeEach(() => {})
|
||||
afterEach(() => {})
|
||||
after(() => {})
|
||||
|
||||
it('test 1', () => {})
|
||||
it('test 2', () => {})
|
||||
it('test 3', () => {})
|
||||
})
|
||||
|
||||
describe('suite 2', { retries: 2 }, () => {
|
||||
let j = 0
|
||||
|
||||
afterEach(() => {
|
||||
if (j === 0 || j === 1) {
|
||||
j++
|
||||
throw new Error('')
|
||||
}
|
||||
})
|
||||
|
||||
it('test 1', () => {})
|
||||
})
|
||||
|
||||
describe('suite 3', { retries: 2 }, () => {
|
||||
it('test 1', () => {})
|
||||
})
|
||||
@@ -0,0 +1,20 @@
|
||||
describe('suite 1', { retries: 1 }, () => {
|
||||
before(() => {})
|
||||
beforeEach(() => {})
|
||||
|
||||
let i = 0
|
||||
|
||||
beforeEach(() => {
|
||||
if (i === 0) {
|
||||
i++
|
||||
throw new Error('')
|
||||
}
|
||||
})
|
||||
|
||||
beforeEach(() => {})
|
||||
|
||||
afterEach(() => {})
|
||||
after(() => {})
|
||||
|
||||
it('test 1', () => {})
|
||||
})
|
||||
@@ -0,0 +1,17 @@
|
||||
describe('suite 1', { retries: 1 }, () => {
|
||||
before(() => {})
|
||||
beforeEach(() => {})
|
||||
beforeEach(() => {})
|
||||
afterEach(() => {})
|
||||
afterEach(() => {})
|
||||
let i = 0
|
||||
|
||||
after(() => {
|
||||
if (i === 0) {
|
||||
i++
|
||||
throw new Error('')
|
||||
}
|
||||
})
|
||||
|
||||
it('test 1', () => {})
|
||||
})
|
||||
@@ -0,0 +1,17 @@
|
||||
describe('suite 1', { retries: 1 }, () => {
|
||||
let i = 0
|
||||
|
||||
before(() => {
|
||||
if (i === 0) {
|
||||
i++
|
||||
throw new Error('')
|
||||
}
|
||||
})
|
||||
|
||||
beforeEach(() => {})
|
||||
beforeEach(() => {})
|
||||
afterEach(() => {})
|
||||
afterEach(() => {})
|
||||
after(() => {})
|
||||
it('test 1', () => {})
|
||||
})
|
||||
@@ -0,0 +1,4 @@
|
||||
it('visits', { defaultCommandTimeout: 200, retries: 2 }, () => {
|
||||
cy.visit('cypress/fixtures/dom.html')
|
||||
cy.get('#button').should('not.be.visible')
|
||||
})
|
||||
@@ -0,0 +1,8 @@
|
||||
describe('suite 1', () => {
|
||||
after(() => {
|
||||
throw new Error('Error!')
|
||||
})
|
||||
|
||||
it('test 1', () => {})
|
||||
it('test 2', () => {})
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
describe('suite 1', () => {
|
||||
afterEach(() => {
|
||||
throw new Error('After each error')
|
||||
})
|
||||
|
||||
it('test 1', () => {})
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
describe('suite 1', () => {
|
||||
before(() => {
|
||||
throw new Error('before')
|
||||
})
|
||||
|
||||
it('test 1', () => {})
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
describe('suite 1', () => {
|
||||
beforeEach(() => {
|
||||
throw new Error('beforeEach')
|
||||
})
|
||||
|
||||
it('test 1', () => {})
|
||||
})
|
||||
@@ -0,0 +1,19 @@
|
||||
describe('suite 1', () => {
|
||||
before(() => {})
|
||||
beforeEach(() => {})
|
||||
after(() => {})
|
||||
afterEach(() => {})
|
||||
|
||||
it('test 1', () => {
|
||||
throw new Error('T1 fail')
|
||||
})
|
||||
|
||||
// eslint-disable-next-line mocha/no-exclusive-tests
|
||||
it.only('test 2', () => {
|
||||
throw new Error('T2 fail')
|
||||
})
|
||||
|
||||
it('test 3', () => {
|
||||
throw new Error('T3 fail')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,11 @@
|
||||
describe('suite 1', () => {
|
||||
before(() => {})
|
||||
beforeEach(() => {})
|
||||
after(() => {})
|
||||
afterEach(() => {})
|
||||
|
||||
it('test 1', () => {})
|
||||
// eslint-disable-next-line mocha/no-exclusive-tests
|
||||
it.only('test 2', () => {})
|
||||
it('test 3', () => {})
|
||||
})
|
||||
@@ -0,0 +1,10 @@
|
||||
describe('suite 1', { retries: 1 }, () => {
|
||||
let i = 0
|
||||
|
||||
it('test 1', () => {
|
||||
if (i === 0) {
|
||||
i++
|
||||
throw new Error('test 1')
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
describe('suite 1', () => {
|
||||
it('test 1', () => {})
|
||||
})
|
||||
@@ -0,0 +1,15 @@
|
||||
describe('suite 1', { retries: 1 }, () => {
|
||||
before(() => {})
|
||||
beforeEach(() => {})
|
||||
after(() => {})
|
||||
afterEach(() => {})
|
||||
|
||||
let i = 0
|
||||
|
||||
it('test 1', () => {
|
||||
if (i === 0) {
|
||||
i++
|
||||
throw new Error('test 1')
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,20 @@
|
||||
describe('suite 1', { retries: 1 }, () => {
|
||||
before(() => {})
|
||||
beforeEach(() => {})
|
||||
after(() => {})
|
||||
afterEach(() => {})
|
||||
|
||||
it('test 1', () => {})
|
||||
|
||||
let i = 0
|
||||
|
||||
// eslint-disable-next-line mocha/no-exclusive-tests
|
||||
it.only('test 2', () => {
|
||||
if (i === 0) {
|
||||
i++
|
||||
throw new Error('test 2')
|
||||
}
|
||||
})
|
||||
|
||||
it('test 3', () => {})
|
||||
})
|
||||
@@ -0,0 +1,10 @@
|
||||
describe('suite 1', () => {
|
||||
before(() => {})
|
||||
beforeEach(() => {})
|
||||
after(() => {})
|
||||
afterEach(() => {})
|
||||
|
||||
it('test 1', () => {})
|
||||
it('test 2', () => {})
|
||||
it('test 3', () => {})
|
||||
})
|
||||
@@ -0,0 +1,19 @@
|
||||
describe('suite 1', { retries: 2 }, () => {
|
||||
before(() => {})
|
||||
beforeEach(() => {})
|
||||
afterEach(() => {})
|
||||
after(() => {})
|
||||
|
||||
it('test 1', () => {})
|
||||
|
||||
let i = 0
|
||||
|
||||
it('test 2', () => {
|
||||
if (i <= 1) {
|
||||
i++
|
||||
throw new Error('')
|
||||
}
|
||||
})
|
||||
|
||||
it('test 3', () => {})
|
||||
})
|
||||
675
system-tests/projects/runner-e2e-specs/cypress/fixtures/dom.html
Normal file
675
system-tests/projects/runner-e2e-specs/cypress/fixtures/dom.html
Normal file
@@ -0,0 +1,675 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>DOM Fixture</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="dom">
|
||||
<style>
|
||||
|
||||
/* a small css reset stylesheet */
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 2px 0;
|
||||
/* border: 0px outset; */
|
||||
border: 2px outset;
|
||||
padding:0
|
||||
}
|
||||
|
||||
|
||||
button,
|
||||
input { /* 1 */
|
||||
overflow: visible;
|
||||
}
|
||||
button {
|
||||
padding: 1px 6px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
button,
|
||||
select { /* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
|
||||
button,
|
||||
[type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
body {
|
||||
display: block;
|
||||
padding: 0;
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
:focus {
|
||||
background-color: red;
|
||||
}
|
||||
#overflow-auto-container {
|
||||
width: 100px;
|
||||
height: 50px;
|
||||
border: 1px solid #999;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#overflow-auto-container li {
|
||||
line-height: 33px;
|
||||
}
|
||||
|
||||
#animation-container {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.slidein {
|
||||
background-color: yellow;
|
||||
border: 1px solid red;
|
||||
width: 100px;
|
||||
float: left;
|
||||
margin: 0;
|
||||
animation-timing-function: linear;
|
||||
animation-name: slidein;
|
||||
}
|
||||
|
||||
@keyframes slidein {
|
||||
from {
|
||||
margin-left: 100%;
|
||||
}
|
||||
|
||||
to {
|
||||
margin-left: 0%;
|
||||
}
|
||||
}
|
||||
|
||||
[contenteditable] p {
|
||||
display: block
|
||||
}
|
||||
|
||||
#contenteditable {
|
||||
min-height: 20px;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.content-box {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
#button {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
DOM Fixture
|
||||
|
||||
<div id="nested-find">
|
||||
Nested Find
|
||||
</div>
|
||||
|
||||
<div id="animation-container">
|
||||
</div>
|
||||
|
||||
<div id="specific-contains">
|
||||
<span>foo</span>
|
||||
<div id="nested-div">
|
||||
<span>foo</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="edge-case-contains">
|
||||
<div class="badge">5</div>
|
||||
<div class="badge-multi">1</div>
|
||||
<div class="badge-multi">2</div>
|
||||
<div class="badge-multi">3</div>
|
||||
<div class="badge-multi">4</div>
|
||||
<span class="count">
|
||||
<i class="fa fa-icon"></i>
|
||||
1
|
||||
</span>
|
||||
<span class="count">
|
||||
<i class="fa fa-icon"></i>
|
||||
2
|
||||
</span>
|
||||
<span class="count">
|
||||
<i class="fa fa-icon"></i>
|
||||
3
|
||||
</span>
|
||||
<span>
|
||||
<i>25</i>
|
||||
</span>
|
||||
<span>25</span>
|
||||
</div>
|
||||
|
||||
<div id="fixed-nav-test">
|
||||
|
||||
</div>
|
||||
|
||||
<div id="wrapper">
|
||||
<div id="upper">
|
||||
<div class="item"><em>New</em> York</div>
|
||||
</div>
|
||||
<div id="lower">
|
||||
<div class="item"><em>New</em> York</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul id="list">
|
||||
<li class="item">li 0</li>
|
||||
<li class="item">li 1</li>
|
||||
<li class="item">li 2</li>
|
||||
</ul>
|
||||
|
||||
<ul id="asdf">
|
||||
<li>asdf 1</li>
|
||||
<li>asdf 2</li>
|
||||
<li>asdf 3</li>
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
<li><span>jkl 1</span></li>
|
||||
<li><span>jkl 2</span></li>
|
||||
<li><span>jkl 3</span></li>
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
<li><span>jkl 4</span></li>
|
||||
<li><span>jkl 5</span></li>
|
||||
<li><span>jkl 6</span></li>
|
||||
</ul>
|
||||
|
||||
<div id="tabindex" tabindex="1" style="height: 50px">
|
||||
el with tabindex
|
||||
</div>
|
||||
|
||||
<button id="button">button</button>
|
||||
|
||||
<form id="by-id">
|
||||
<input id="input" />
|
||||
<input id="name" />
|
||||
<input id="age" />
|
||||
</form>
|
||||
|
||||
<form id="by-name">
|
||||
<input name="name" />
|
||||
<input name="age" />
|
||||
<input type="radio" name="gender" value="male" />
|
||||
<input type="radio" name="gender" value="female" />
|
||||
<input type="checkbox" name="colors" value="blue" />
|
||||
<input type="checkbox" name="colors" value="green" />
|
||||
<input type="checkbox" name="colors" value="red" />
|
||||
<input type="checkbox" name="dogs" value="husky" />
|
||||
<input type="checkbox" name="dogs" value="poodle" />
|
||||
<input type="checkbox" name="dogs" value="on" />
|
||||
<input type="checkbox" name="dogs" data-no-value="true" />
|
||||
<input type="tel">
|
||||
</form>
|
||||
|
||||
<form>
|
||||
<textarea id="comments"></textarea>
|
||||
</form>
|
||||
|
||||
<form id="checkboxes">
|
||||
<input type="checkbox" name="birds" value="cockatoo" checked="true" />
|
||||
<input type="checkbox" name="birds" value="amazon" checked="true" />
|
||||
</form>
|
||||
|
||||
<input type="submit" value="input contains submit" />
|
||||
|
||||
<form id="input-type-submit">
|
||||
<a href="#">
|
||||
<input type="submit" value="click me" />
|
||||
</a>
|
||||
</form>
|
||||
|
||||
<form id="button-inside-a">
|
||||
<button>
|
||||
<span>click button</span>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<form action="/timeout?ms=2000" id="click-me">
|
||||
<input type="hidden" name="ms" value="100" />
|
||||
<a href="#">
|
||||
<span>click me 1</span>
|
||||
</a>
|
||||
<button>
|
||||
<span>click me 2</span>
|
||||
</button>
|
||||
<input type="submit" value="click me" />
|
||||
</form>
|
||||
|
||||
<form id="complex-contains">
|
||||
<button>
|
||||
<a href="#">
|
||||
<label>nested contains</label>
|
||||
</a>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<form id="button-text">
|
||||
<a href="#">
|
||||
<span>click button 1</span>
|
||||
</a>
|
||||
<button>
|
||||
<span>click button 2</span>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<form id="anchor-text">
|
||||
<a href="#">
|
||||
<span>Home Page</span>
|
||||
</a>
|
||||
</form>
|
||||
|
||||
<form id="focus">
|
||||
<div>
|
||||
<span>
|
||||
<input type="text" />
|
||||
<button>focusable button</button>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div id="form-submits">
|
||||
<form id="single-input">
|
||||
<div>
|
||||
<input name="fname" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form id="no-buttons-more-than-one-input-allowing-implicit-submission">
|
||||
<input /> <!-- default is type='text' -->
|
||||
<input /> <!-- default is type='text' -->
|
||||
</form>
|
||||
|
||||
<!-- https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#implicit-submission -->
|
||||
<form id="no-buttons-and-only-one-input-allowing-implicit-submission">
|
||||
<input type="text" />
|
||||
<input type="hidden" />
|
||||
</form>
|
||||
|
||||
<form id="one-button-type-button">
|
||||
<input name="fname" />
|
||||
<input name="lname" />
|
||||
<button type="button">submit me</button>
|
||||
</form>
|
||||
|
||||
<form id="multiple-inputs-and-input-submit">
|
||||
<input name="fname" />
|
||||
<input name="lname" />
|
||||
<input type="submit" value="submit me" />
|
||||
</form>
|
||||
|
||||
<form id="multiple-inputs-and-button-submit">
|
||||
<input name="fname" />
|
||||
<input name="lname" />
|
||||
<button type="button">button</button>
|
||||
<button type="submit">submit me</button>
|
||||
</form>
|
||||
|
||||
<form id="multiple-inputs-and-reset-and-submit-buttons">
|
||||
<input name="fname" />
|
||||
<input name="lname" />
|
||||
<button type="reset">reset</button>
|
||||
<button type="submit">submit me</button>
|
||||
</form>
|
||||
|
||||
<form id="multiple-inputs-and-button-with-no-type">
|
||||
<input name="fname" />
|
||||
<input name="lname" />
|
||||
<button>submit me</button>
|
||||
</form>
|
||||
|
||||
<form id="multiple-inputs-and-other-type-buttons-and-button-with-no-type">
|
||||
<input name="fname" />
|
||||
<input name="lname" />
|
||||
<button type='button'>button</button>
|
||||
<button type='reset'>reset</button>
|
||||
<button>submit me</button>
|
||||
</form>
|
||||
|
||||
<form id="multiple-inputs-and-multiple-submits">
|
||||
<input name="fname" />
|
||||
<input name="lname" />
|
||||
<button>submit me</button>
|
||||
<input type="submit" value ="submit me2" />
|
||||
</form>
|
||||
|
||||
<form id="readonly">
|
||||
<!-- All values are valid readonly -->
|
||||
<input id="readonly-attr" readonly />
|
||||
<input id="readonly-readonly" readonly="readonly" />
|
||||
<input id="readonly-empty-str" readonly="" />
|
||||
|
||||
<!-- Although not strictly part of spec, Chrome respects any string -->
|
||||
<input id="readonly-str" readonly="abc" />
|
||||
|
||||
<!-- readonly doesn't enforce on non typeable inputs -->
|
||||
<input type="checkbox" id="readonly-checkbox" readonly />
|
||||
<input type="submit" id="readonly-submit" value="readonly click" readonly />
|
||||
<select name="hunter" readonly>
|
||||
<option value="gon-val" readonly>gon</option>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="input-types">
|
||||
<input id="input-with-value" value="foo" />
|
||||
<input id="input-without-value" />
|
||||
|
||||
<input id="number-with-value" type="number" value="12" />
|
||||
<input id="number-without-value" type="number" />
|
||||
|
||||
<input id="email-with-value" type="email" value="brian@foo.c" />
|
||||
<input id="email-without-value" type="email" />
|
||||
|
||||
<input id="password-with-value" type="password" value="pass" />
|
||||
<input id="password-without-value" type="password" />
|
||||
|
||||
<input id="date-with-value" type="date" value="2016-01-01" />
|
||||
<input id="date-without-value" type="date" />
|
||||
|
||||
<input id="month-with-value" type="month" value="2017-05" />
|
||||
<input id="month-without-value" type="month" />
|
||||
|
||||
<input id="week-with-value" type="week" value="2017-W05" />
|
||||
<input id="week-without-value" type="week" />
|
||||
|
||||
<input id="time-with-value" type="time" value="01:23:45" />
|
||||
<input id="time-without-value" type="time" />
|
||||
|
||||
<input id="tel-with-value" type="tel" value="678-999-8212" />
|
||||
<input id="text-with-value" type="text" value="foo" />
|
||||
<input id="datetime-with-value" type="datetime" value="2018-01-01T01:00" />
|
||||
<input id="datetime-local-with-value" type="datetime-local" value="2018-01-01T01:00" />
|
||||
<input id="search-with-value" type="search" value="query" />
|
||||
<input id="url-with-value" type="url" value="cool.biz" />
|
||||
|
||||
<div contenteditable="true"><br></div>
|
||||
<textarea></textarea>
|
||||
<input id="bad-type" type="asdf" />
|
||||
</div>
|
||||
|
||||
<table id="table">
|
||||
<thead>
|
||||
header
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>cell</td>
|
||||
</tr>
|
||||
<tbody>
|
||||
</table>
|
||||
|
||||
<div id="sequential-clicks">
|
||||
<a href="#">1</a>
|
||||
<a href="#">2</a>
|
||||
<a href="#">3</a>
|
||||
<a href="#">4</a>
|
||||
<a href="#">5</a>
|
||||
</div>
|
||||
|
||||
<select id="select-maps" name="maps">
|
||||
<option value="de_dust2">dust2</option>
|
||||
<option value="de_aztec">inferno</option>
|
||||
<option value="de_nuke">nuke</option>
|
||||
<option value="de_train">train</option>
|
||||
<option value="cs_italy">
|
||||
italy
|
||||
<br>
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<select name="foods">
|
||||
<option value="Japanese">Ramen</option>
|
||||
<option value="Ramen">Japanese</option>
|
||||
</select>
|
||||
|
||||
<select name="names">
|
||||
<option value="bm">brian m</option>
|
||||
<option value="ss">sam s</option>
|
||||
<option value="bm">bryan m</option>
|
||||
</select>
|
||||
|
||||
<select name="movies" multiple="multiple">
|
||||
<option value="apoc">Apocalypse Now</option>
|
||||
<option value="thc">The Human Condition</option>
|
||||
<option value="br">Blade Runner</option>
|
||||
<option value="2001">2001: A Space Odyssey</option>
|
||||
<option value="co">Clockwork Orange</option>
|
||||
<option value="twbb">There Will Be Blood</option>
|
||||
<option value="gone with the wind">Gone with the Wind</option>
|
||||
</select>
|
||||
|
||||
<select name="disabled" disabled>
|
||||
<option value="foo">foo</option>
|
||||
<option value="bar">bar</option>
|
||||
</select>
|
||||
|
||||
<fieldset disabled>
|
||||
<select name="fielset-disabled">
|
||||
<option value="foo">foo</option>
|
||||
<option value="bar">bar</option>
|
||||
</select>
|
||||
</fieldset>
|
||||
|
||||
<select name="optgroup-disabled">
|
||||
<optgroup label="foobar" disabled>
|
||||
<option value="foo">foo</option>
|
||||
<option value="bar">bar</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
|
||||
<select name="opt-disabled">
|
||||
<option value="foo">foo</option>
|
||||
<option disabled value="bar">bar</option>
|
||||
</select>
|
||||
|
||||
<select name="starwars">
|
||||
<optgroup label="Light Side">
|
||||
<option value="luke">Luke</option>
|
||||
<option value="leia">Leia</option>
|
||||
<option value="rey">Rey</option>
|
||||
</optgroup>
|
||||
<optgroup label="Dark Side">
|
||||
<option value="vader">Vader</option>
|
||||
<option value="palpatine">Palpatine</option>
|
||||
<option value="jarjar">Jar Jar</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
|
||||
<select name="startrek-same">
|
||||
<option value="same">Kirk</option>
|
||||
<option value="same">Spock</option>
|
||||
<option value="same">Uhura</option>
|
||||
<option value="same">Sulu</option>
|
||||
</select>
|
||||
|
||||
<select name="startrek-some-same">
|
||||
<option value="different">Kirk</option>
|
||||
<option value="same">Spock</option>
|
||||
<option value="same">Uhura</option>
|
||||
<option value="same">Sulu</option>
|
||||
</select>
|
||||
|
||||
<div id="contenteditable" contenteditable="true">
|
||||
content should be editable
|
||||
</div>
|
||||
|
||||
<div id="invisible" style="display: none;">i am not visible</div>
|
||||
|
||||
<button class="content-box">content-box</button>
|
||||
|
||||
<div id="svgs">
|
||||
<svg data-cy="line" width="300" height="200">
|
||||
<line x1="50" y1="50" x2="250" y2="150" style="stroke:red; stroke-width:20;" />
|
||||
</svg>
|
||||
<svg tabindex="0" data-cy="rect" width="300" height="200">
|
||||
<rect x="50" y="50" width="200" height="100" style="fill:orange; stroke:black; stroke-width:3;" />
|
||||
</svg>
|
||||
<svg data-cy="circle" width="300" height="200">
|
||||
<circle cx="150" cy="100" r="70" style="fill:lime; stroke:black; stroke-width:3;" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<canvas id="canvas"></canvas>
|
||||
|
||||
<div id="contains-multiple-filter-match">
|
||||
<ul class="k-group k-treeview-lines" role="group">
|
||||
<li role="treeitem" class="k-item k-first" data-uid="82e99592-f200-4ae3-b96d-cbbd53cfd1a1">
|
||||
<div class="k-top treeview-parent-wrapper">
|
||||
<span class="k-icon k-minus" role="presentation"></span>
|
||||
<span class="k-in">
|
||||
<div class="treeview-parent pull-left">
|
||||
Assessments
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
1 Folder Type
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
<ul class="k-group" role="group" style="display: block;">
|
||||
<li role="treeitem" class="k-item k-last" data-uid="d0fd09f6-b1fd-4155-b4aa-bee3890f0029">
|
||||
<div class="k-bot">
|
||||
<span class="k-in">
|
||||
<span class="square-small" style="background-color: #589d46;"></span>
|
||||
Inspection
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li role="treeitem" class="k-item k-last" data-uid="8a691b97-98b9-475b-b54f-50d8441e3a78">
|
||||
<div class="k-bot treeview-parent-wrapper">
|
||||
<span class="k-icon k-minus" role="presentation"></span>
|
||||
<span class="k-in">
|
||||
<div class="treeview-parent pull-left">
|
||||
Folders
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
2 Folder Types
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
<ul class="k-group" role="group" style="display: block;">
|
||||
<li role="treeitem" class="k-item active" data-uid="bfc39753-ff6b-4237-a53c-e62c4161ba99" aria-selected="true" id="treeview_tv_active">
|
||||
<div class="k-top">
|
||||
<span class="k-state-selected k-in">
|
||||
<span class="square-small" style="background-color: #705092;"></span>
|
||||
Maintenance
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<li role="treeitem" class="k-item k-last" data-uid="27acc697-71da-4c19-a755-78f93931303b">
|
||||
<div class="k-bot">
|
||||
<span class="k-in">
|
||||
<span class="square-small" style="background-color: #000000;"></span>
|
||||
Quality Control
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<foobarbazquux>custom element</foobarbazquux>
|
||||
<div id="ajax-get-container">
|
||||
<button id="get-json">get ajax</button>
|
||||
</div>
|
||||
<span id="not-hidden">my hidden content</span>
|
||||
<div id="three-buttons">
|
||||
<button>1</button>
|
||||
<button>2</button>
|
||||
<button>3</button>
|
||||
</div>
|
||||
<ul id="overflow-auto-container">
|
||||
<li>foo</li>
|
||||
<li>bar</li>
|
||||
<li>baz</li>
|
||||
<li>quux</li>
|
||||
</ul>
|
||||
|
||||
<div id="overflow-link" style="width:260px"><p>
|
||||
|
||||
this is some text that will <span class="wrapped" style="color:rgb(0, 0, 192)">wrap to a newline</span>
|
||||
and cause the click to miss
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style="width: 30px; line-height: 2;">
|
||||
<a href="#" id="overflow-link-width">
|
||||
<i style="display: inline-block;"></i>
|
||||
foofoofoofoofoo bar
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<span id="opacity-0" style="opacity: 0;">opacity 0</span>
|
||||
<input type="checkbox" style="opacity: 0;" name="opacity" value="val" />
|
||||
<div style="opacity: 0;">
|
||||
<span id="opacity-0-parent">parent opacity 0</span>
|
||||
</div>
|
||||
<div style="height:25px; width:25px; overflow: hidden;">
|
||||
<span id="opacity-0-hidden" style="opacity: 0; margin-left: 30px;">opacity 0</span>
|
||||
</div>
|
||||
|
||||
<div id="massively-long-div" style="height: 500px; width: 200px; background-color: gray;"></div>
|
||||
<div id="form-header-region">
|
||||
<div>
|
||||
<div id="header" class="navbar navbar-green">
|
||||
<div class="navbar-header">
|
||||
<ul>
|
||||
<li>
|
||||
<span id="homebutton" data-js="done" class="btn btn-no-bg full-screen-btn pull-left navbar-btn" style="display: block;"><i class="fa fa-arrow-circle-o-left"></i> Done</span>
|
||||
</li>
|
||||
<li>
|
||||
<span id="backbutton" data-js="back" class="btn btn-no-bg full-screen-btn pull-left navbar-btn" style="display: none;"><i class="fa fa-caret-left"></i> Back</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="form-template-name-wrapper">
|
||||
<div class="form-template-name">
|
||||
EyeProtection -
|
||||
129083
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="diff-els-1">
|
||||
<a href="">Sakura</a>
|
||||
<a href="">Naruto</a>
|
||||
<button>Sarada</button>
|
||||
<button>Boruto</button>
|
||||
</div>
|
||||
<div>
|
||||
iframe:<br>
|
||||
<iframe id="iframe" src="/fixtures/generic.html"></iframe>
|
||||
</div>
|
||||
<div id="does-not-wrap-input">Text</div>
|
||||
<div id="input-wrap">
|
||||
<input style="width:100%" />
|
||||
</div>
|
||||
<div>
|
||||
Cross domain iframe:<br>
|
||||
<iframe id="iframe-cross-domain" src="http://localhost:3501/fixtures/generic.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
10
yarn.lock
10
yarn.lock
@@ -12212,7 +12212,7 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1:
|
||||
dependencies:
|
||||
color-convert "^1.9.0"
|
||||
|
||||
ansi-styles@^4.0.0, ansi-styles@^4.1.0:
|
||||
ansi-styles@^4.0.0, ansi-styles@^4.1.0, ansi-styles@^4.2.1:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
|
||||
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
|
||||
@@ -19311,6 +19311,14 @@ disparity@3.0.0:
|
||||
ansi-styles "^4.1.0"
|
||||
diff "^4.0.1"
|
||||
|
||||
disparity@^3.0.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/disparity/-/disparity-3.2.0.tgz#7198eaf7a873a130f8098c93061c1df8934500f2"
|
||||
integrity sha512-8cl9ouncFYE7OQsYwJNiy2e15S0xN80X1Jj/N/YkoiM+VGWSyg1YzPToecKyYx2DQiJapt5IC8yi43GW23TUHQ==
|
||||
dependencies:
|
||||
ansi-styles "^4.2.1"
|
||||
diff "^4.0.2"
|
||||
|
||||
dmg-builder@22.13.1:
|
||||
version "22.13.1"
|
||||
resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-22.13.1.tgz#5a77655e691ad7e5d28fbf008c68e819e0e2bd69"
|
||||
|
||||
Reference in New Issue
Block a user