@revoloo/cypress6
Version:
Cypress.io end to end testing tool
219 lines (179 loc) • 6.54 kB
JSX
import cs from 'classnames'
import { action, autorun } from 'mobx'
import { observer } from 'mobx-react'
import React, { Component } from 'react'
import { $ } from '@packages/driver'
import AutIframe from './aut-iframe'
import ScriptError from '../errors/script-error'
import SnapshotControls from './snapshot-controls'
import IframeModel from './iframe-model'
import logger from '../lib/logger'
import selectorPlaygroundModel from '../selector-playground/selector-playground-model'
import studioRecorder from '../studio/studio-recorder'
import util from '../lib/util'
export default class Iframes extends Component {
_disposers = []
render () {
const { width, height, scale, marginLeft, headerHeight, scriptError } = this.props.state
return (
<div
className={cs(
'iframes-container',
{
'has-error': !!scriptError,
'studio-is-open': studioRecorder.isOpen,
'studio-is-loading': studioRecorder.isLoading,
'studio-is-ready': studioRecorder.isReady,
'studio-is-failed': studioRecorder.isFailed,
},
)}
style={{
top: headerHeight,
left: this.props.state.absoluteReporterWidth,
}}
>
<div
ref='container'
className='size-container'
style={{
marginLeft,
height,
transform: `scale(${scale})`,
width,
}}
/>
<ScriptError error={scriptError} />
<div className='cover' />
{studioRecorder.isLoading && (
<div
className='studio-loading-cover'
style={{
marginLeft,
height,
transform: `scale(${scale})`,
width,
}}
>
<div><i className='fa fa-spinner fa-spin' /></div>
</div>
)}
</div>
)
}
componentDidMount () {
this.autIframe = new AutIframe(this.props.config)
this.props.eventManager.on('visit:failed', this.autIframe.showVisitFailure)
this.props.eventManager.on('before:screenshot', this.autIframe.beforeScreenshot)
this.props.eventManager.on('after:screenshot', this.autIframe.afterScreenshot)
this.props.eventManager.on('script:error', this._setScriptError)
this.props.eventManager.on('run:end', this.autIframe.startStudio)
this.props.eventManager.on('page:loading', (isLoading) => {
if (!isLoading) {
this.autIframe.reattachStudio()
}
})
// TODO: need to take headless mode into account
// may need to not display reporter if more than 200 tests
this.props.eventManager.on('restart', () => {
this._run(this.props.config)
})
this.props.eventManager.on('print:selector:elements:to:console', this._printSelectorElementsToConsole)
this._disposers.push(autorun(() => {
this.autIframe.toggleSelectorPlayground(selectorPlaygroundModel.isEnabled)
}))
this._disposers.push(autorun(() => {
this.autIframe.toggleSelectorHighlight(selectorPlaygroundModel.isShowingHighlight)
}))
this.props.eventManager.start(this.props.config)
this.iframeModel = new IframeModel({
state: this.props.state,
removeHeadStyles: this.autIframe.removeHeadStyles,
restoreDom: this.autIframe.restoreDom,
highlightEl: this.autIframe.highlightEl,
detachDom: this.autIframe.detachDom,
snapshotControls: (snapshotProps) => (
<SnapshotControls
eventManager={this.props.eventManager}
snapshotProps={snapshotProps}
state={this.props.state}
onToggleHighlights={this._toggleSnapshotHighlights}
onStateChange={this._changeSnapshotState}
/>
),
})
this.iframeModel.listen()
this._run(this.props.config)
}
_setScriptError = (err) => {
this.props.state.scriptError = err
}
_run = (config) => {
const specPath = util.specPath()
this.props.eventManager.notifyRunningSpec(specPath)
logger.clearLog()
this._setScriptError(null)
this.props.eventManager.setup(config)
const $autIframe = this._loadIframes(specPath)
this.props.eventManager.initialize($autIframe, config)
}
// jQuery is a better fit for managing these iframes, since they need to get
// wiped out and reset on re-runs and the snapshots are from dom we don't control
_loadIframes (specPath) {
const specSrc = `/${this.props.config.namespace}/iframes/${specPath}`
const $container = $(this.refs.container).empty()
const $autIframe = this.autIframe.create(this.props.config).appendTo($container)
this.autIframe.showBlankContents()
// specs with type "component" can only arrive if the server has "componentTesting" experiment on
if (this.props.config.spec.specType === 'component') {
// In mount mode we need to render something right from spec file
// So load application tests to the aut frame
$autIframe.prop('src', specSrc)
return $autIframe
}
const $specIframe = $('<iframe />', {
id: `Your Spec: '${specSrc}'`,
class: 'spec-iframe',
}).appendTo($container)
$specIframe.prop('src', specSrc)
return $autIframe
}
_toggleSnapshotHighlights = (snapshotProps) => {
this.props.state.snapshot.showingHighlights = !this.props.state.snapshot.showingHighlights
if (this.props.state.snapshot.showingHighlights) {
const snapshot = snapshotProps.snapshots[this.props.state.snapshot.stateIndex]
this.autIframe.highlightEl(snapshot, snapshotProps)
} else {
this.autIframe.removeHighlights()
}
}
_changeSnapshotState = (snapshotProps, index) => {
const snapshot = snapshotProps.snapshots[index]
this.props.state.snapshot.stateIndex = index
this.autIframe.restoreDom(snapshot)
if (this.props.state.snapshot.showingHighlights && snapshotProps.$el) {
this.autIframe.highlightEl(snapshot, snapshotProps)
} else {
this.autIframe.removeHighlights()
}
}
componentDidUpdate () {
const cb = this.props.state.callbackAfterUpdate
if (cb) {
cb()
}
}
_printSelectorElementsToConsole = () => {
this.autIframe.printSelectorElementsToConsole()
}
componentWillUnmount () {
this.props.eventManager.notifyRunningSpec(null)
this.props.eventManager.stop()
this._disposers.forEach((dispose) => {
dispose()
})
}
getSizeContainer () {
return this.refs.container
}
}