fix(component-testing): Video recording (#15140)

This commit is contained in:
Dmitriy Kovalenko
2021-02-19 16:52:15 +02:00
committed by GitHub
parent c1c27a0c99
commit 02aec1eb62
8 changed files with 94 additions and 67 deletions

View File

@@ -210,7 +210,7 @@ commands:
- store_test_results:
path: /tmp/cypress
- store_artifacts:
path: /tmp/artifacts
path: ./packages/runner-ct/cypress/videos
- store-npm-logs
run-e2e-tests:

1
packages/runner-ct/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
cypress/videos/*

View File

@@ -1,4 +1,4 @@
{
"testFiles": "**/*spec.{ts,tsx}",
"video": false
"video": true
}

View File

@@ -1,7 +1,7 @@
/// <reference types="@percy/cypress" />
import React from 'react'
import { mount } from '@cypress/react'
import App from '../../src/app/RunnerCt'
import RunnerCt from '../../src/app/RunnerCt'
import State from '../../src/lib/state'
import '@packages/runner/src/main.scss'
@@ -12,18 +12,23 @@ class FakeEventManager {
notifyRunningSpec = () => { }
}
const fakeConfig = { projectName: 'Project', env: {}, isTextTerminal: false } as any as Cypress.RuntimeConfigOptions
describe('RunnerCt', () => {
beforeEach(() => {
cy.viewport(1000, 500)
})
function assertSpecsListIs (state: 'closed' | 'open') {
// for some reason should("not.be.visible") doesn't work here so ensure that specs list was outside of screen
cy.get('[data-cy=specs-list]').then(([el]) => {
const { x } = el.getBoundingClientRect()
cy.get('[data-cy=specs-list]').then(($el) => {
const { x } = $el[0].getBoundingClientRect()
state === 'closed' ? expect(x).to.be.lessThan(0) : expect(x).to.be.lessThan(0)
})
}
it('renders App', () => {
cy.viewport(1000, 500)
it('renders RunnerCt', () => {
const state = new State({
reporterWidth: 500,
spec: null,
@@ -31,11 +36,30 @@ describe('RunnerCt', () => {
})
mount(
<App
<RunnerCt
state={state}
// @ts-ignore - this is difficult to stub. Real one breaks things.
eventManager={new FakeEventManager()}
config={{ projectName: 'Project', env: {} }}
config={fakeConfig}
/>,
)
cy.percySnapshot()
})
it('renders RunnerCt for video recording', () => {
const state = new State({
reporterWidth: 500,
spec: null,
specs: [{ relative: '/test.js', absolute: 'root/test.js', name: 'test.js' }],
})
mount(
<RunnerCt
state={state}
// @ts-ignore - this is difficult to stub. Real one breaks things.
eventManager={new FakeEventManager()}
config={{ ...fakeConfig, isTextTerminal: true }}
/>,
)
@@ -44,7 +68,6 @@ describe('RunnerCt', () => {
context('keyboard shortcuts', () => {
beforeEach(() => {
cy.viewport(1000, 500)
const state = new State({
reporterWidth: 500,
spec: null,
@@ -52,11 +75,11 @@ describe('RunnerCt', () => {
})
mount(
<App
<RunnerCt
state={state}
// @ts-ignore - this is difficult to stub. Real one breaks things.
eventManager={new FakeEventManager()}
config={{ projectName: 'Project', env: {} }}
config={fakeConfig}
/>,
)
@@ -80,7 +103,6 @@ describe('RunnerCt', () => {
context('specs-list resizing', () => {
beforeEach(() => {
cy.viewport(1000, 500)
const state = new State({
reporterWidth: 500,
spec: null,
@@ -88,11 +110,11 @@ describe('RunnerCt', () => {
})
mount(
<App
<RunnerCt
state={state}
// @ts-ignore - this is difficult to stub. Real one breaks things.
eventManager={new FakeEventManager()}
config={{ projectName: 'Project', env: {} }}
config={fakeConfig}
/>,
)
})

View File

@@ -69,9 +69,12 @@ main.app-ct {
.app-wrapper {
position: relative;
width: calc(100vw - #{$specs-list-offset});
height: 100vh;
margin-inline: $specs-list-offset;
&.with-specs-drawer {
width: calc(100vw - #{$specs-list-offset});
margin-inline: $specs-list-offset;
}
}
.app-wrapper-screenshotting {

View File

@@ -24,17 +24,10 @@ import './RunnerCt.scss'
import { KeyboardHelper, NoSpecSelected } from './NoSpecSelected'
import { useScreenshotHandler } from './useScreenshotHandler'
// Cypress.ConfigOptions only appears to have internal options.
// TODO: figure out where the "source of truth" should be for
// an internal options interface.
export interface ExtendedConfigOptions extends Cypress.ConfigOptions {
projectName: string
}
interface AppProps {
state: State
eventManager: typeof EventManager
config: ExtendedConfigOptions
config: Cypress.RuntimeConfigOptions
}
const DEFAULT_LEFT_SIDE_OF_SPLITPANE_WIDTH = 355
@@ -48,10 +41,11 @@ const App: React.FC<AppProps> = observer(
const pluginRootContainer = React.useRef<null | HTMLDivElement>(null)
const { state, eventManager, config } = props
const isOpenMode = !config.isTextTerminal
const [pluginsHeight, setPluginsHeight] = React.useState(500)
const [isResizing, setIsResizing] = React.useState(false)
const [isSpecsListOpen, setIsSpecsListOpen] = React.useState(true)
const [isSpecsListOpen, setIsSpecsListOpen] = React.useState(isOpenMode)
const [drawerWidth, setDrawerWidth] = React.useState(300)
const windowSize = useWindowSize()
const [leftSideOfSplitPaneWidth, setLeftSideOfSplitPaneWidth] = React.useState(DEFAULT_LEFT_SIDE_OF_SPLITPANE_WIDTH)
@@ -124,47 +118,53 @@ const App: React.FC<AppProps> = observer(
return (
<>
<main className="app-ct">
<div
className={cs(
'specs-list-drawer',
{
'display-none': state.screenshotting,
},
)}
style={{
transform: isSpecsListOpen ? `translateX(0)` : `translateX(-${drawerWidth - 20}px)`,
}}
>
<ResizableBox
disabled={!isSpecsListOpen}
width={drawerWidth}
onIsResizingChange={setIsResizing}
onWidthChange={setDrawerWidth}
className="specs-list-container"
data-cy="specs-list-resize-box"
minWidth={200}
maxWidth={windowSize.width / 100 * 80} // 80vw
{isOpenMode && (
<div
className={cs(
'specs-list-drawer',
{
'display-none': state.screenshotting,
},
)}
style={{
transform: isSpecsListOpen ? `translateX(0)` : `translateX(-${drawerWidth - 20}px)`,
}}
>
<nav>
<a
id="menu-toggle"
onClick={() => setIsSpecsListOpen(!isSpecsListOpen)}
className="menu-toggle"
aria-label="Open the menu"
>
<Burger />
</a>
</nav>
<SpecList
specs={state.specs}
inputRef={searchRef}
disableTextSelection={isResizing}
selectedSpecs={state.spec ? [state.spec.absolute] : []}
onSelectSpec={runSpec}
/>
</ResizableBox>
</div>
<div className={cs('app-wrapper', { 'app-wrapper-screenshotting': state.screenshotting })}>
<ResizableBox
disabled={!isSpecsListOpen}
width={drawerWidth}
onIsResizingChange={setIsResizing}
onWidthChange={setDrawerWidth}
className="specs-list-container"
data-cy="specs-list-resize-box"
minWidth={200}
maxWidth={windowSize.width / 100 * 80} // 80vw
>
<nav>
<a
id="menu-toggle"
onClick={() => setIsSpecsListOpen(!isSpecsListOpen)}
className="menu-toggle"
aria-label="Open the menu"
>
<Burger />
</a>
</nav>
<SpecList
specs={state.specs}
inputRef={searchRef}
disableTextSelection={isResizing}
selectedSpecs={state.spec ? [state.spec.absolute] : []}
onSelectSpec={runSpec}
/>
</ResizableBox>
</div>
)}
<div className={cs('app-wrapper', {
'with-specs-drawer': isOpenMode,
'app-wrapper-screenshotting': state.screenshotting,
})}>
<SplitPane
split="vertical"
primary="first"

View File

@@ -280,7 +280,7 @@ export default class State {
}
@action
initializePlugins = (config: Cypress.ConfigOptions, rootElement: HTMLElement) => {
initializePlugins = (config: Cypress.RuntimeConfigOptions, rootElement: HTMLElement) => {
if (config.env.reactDevtools) {
this.loadReactDevTools(rootElement)
.then(action(() => {

View File

@@ -1,4 +1,5 @@
const run = (options) => {
// TODO make sure if we need to run this in electron by default to match e2e behavior?
options.browser = options.browser || 'chrome'
// if we're in run mode with component