UNPKG

@revoloo/cypress6

Version:

Cypress.io end to end testing tool

257 lines (210 loc) 7.7 kB
import cs from 'classnames' import { observable } from 'mobx' import { observer } from 'mobx-react' import PropTypes from 'prop-types' import React, { Component } from 'react' import { findDOMNode } from 'react-dom' import { Reporter } from '@packages/reporter' import { $ } from '@packages/driver' import errorMessages from '../errors/error-messages' import util from '../lib/util' import State from '../lib/state' import Header from '../header/header' import Iframes from '../iframe/iframes' import Message from '../message/message' import Resizer from './resizer' import StudioModals from '../studio/studio-modals' @observer class App extends Component { @observable isReporterResizing = false render () { /** * @type {Cypress.Cypress['spec']} */ const spec = this.props.config.spec const NO_COMMAND_LOG = this.props.config.env && this.props.config.env.NO_COMMAND_LOG return ( <div className={cs({ 'is-reporter-resizing': this.isReporterResizing, 'is-reporter-sized': this.props.state.reporterWidth != null, })}> <div ref='reporterWrap' className='reporter-wrap' style={{ width: this.props.state.reporterWidth }} > {Boolean(NO_COMMAND_LOG) || <Reporter runner={this.props.eventManager.reporterBus} spec={spec} autoScrollingEnabled={this.props.config.state.autoScrollingEnabled} error={errorMessages.reporterError(this.props.state.scriptError, spec.relative)} firefoxGcInterval={this.props.config.firefoxGcInterval} experimentalStudioEnabled={this.props.config.experimentalStudio} />} </div> <div ref='container' className='runner container' style={{ left: this.props.state.absoluteReporterWidth }} > <Header ref='header' {...this.props} /> <Iframes ref='iframes' {...this.props} /> <Message ref='message' state={this.props.state} /> {this.props.children} </div> <Resizer style={{ left: this.props.state.absoluteReporterWidth }} state={this.props.state} onResizeStart={this._onReporterResizeStart} onResize={this._onReporterResize} onResizeEnd={this._onReporterResizeEnd} /> <StudioModals /> {/* these pixels help ensure the browser has painted when taking a screenshot */} <div ref='screenshotHelperPixels' className='screenshot-helper-pixels'> <div /><div /><div /><div /><div /><div /> </div> </div> ) } componentDidMount () { this._monitorWindowResize() this._handleScreenshots() } _monitorWindowResize () { const state = this.props.state const win = this.props.window const $header = $(findDOMNode(this.refs.header)) const $reporterWrap = $(this.refs.reporterWrap) this._onWindowResize = () => { state.updateWindowDimensions({ windowWidth: win.innerWidth, windowHeight: win.innerHeight, reporterWidth: $reporterWrap.outerWidth(), headerHeight: $header.outerHeight(), }) } $(win).on('resize', this._onWindowResize).trigger('resize') } _onReporterResizeStart = () => { this.isReporterResizing = true } _onReporterResize = (reporterWidth) => { this.props.state.reporterWidth = reporterWidth this.props.state.absoluteReporterWidth = reporterWidth const $header = $(findDOMNode(this.refs.header)) this.props.state.updateWindowDimensions({ headerHeight: $header.outerHeight(), }) } _onReporterResizeEnd = () => { this.isReporterResizing = false this.props.eventManager.saveState({ reporterWidth: this.props.state.reporterWidth, }) } _handleScreenshots () { const containerNode = findDOMNode(this.refs.container) const reporterNode = this.refs.reporterWrap const headerNode = findDOMNode(this.refs.header) const iframesNode = findDOMNode(this.refs.iframes) const iframesSizeNode = findDOMNode(this.refs.iframes.getSizeContainer()) const screenshotHelperPixels = this.refs.screenshotHelperPixels let prevAttrs = {} let screenshotting = false const { eventManager } = this.props eventManager.on('before:screenshot', (config) => { if (!config.appOnly) return screenshotting = true prevAttrs = { config, top: iframesNode.style.top, marginLeft: iframesSizeNode.style.marginLeft, width: iframesSizeNode.style.width, height: iframesSizeNode.style.height, transform: iframesSizeNode.style.transform, left: containerNode.style.left, } const messageNode = findDOMNode(this.refs.message) if (messageNode) { messageNode.style.display = 'none' } reporterNode.style.display = 'none' headerNode.style.display = 'none' iframesNode.style.top = 0 iframesNode.style.backgroundColor = 'black' iframesSizeNode.style.marginLeft = 0 containerNode.style.left = 0 iframesNode.style.left = 0 containerNode.className += ' screenshotting' if (!config.scale) { iframesSizeNode.style.width = `${Math.min(window.innerWidth, iframesSizeNode.offsetWidth)}px` iframesSizeNode.style.height = `${Math.min(window.innerHeight, iframesSizeNode.offsetHeight)}px` iframesSizeNode.style.transform = null } screenshotHelperPixels.style.display = 'none' }) const afterScreenshot = (config) => { if (!config.appOnly) return screenshotting = false screenshotHelperPixels.style.display = 'block' containerNode.className = containerNode.className.replace(' screenshotting', '') containerNode.style.left = prevAttrs.left iframesNode.style.left = prevAttrs.left iframesNode.style.top = prevAttrs.top iframesNode.style.backgroundColor = null iframesSizeNode.style.marginLeft = prevAttrs.marginLeft reporterNode.style.display = null headerNode.style.display = null const messageNode = findDOMNode(this.refs.message) if (messageNode) { messageNode.style.display = null } if (!config.scale) { iframesSizeNode.style.transform = prevAttrs.transform iframesSizeNode.style.width = prevAttrs.width iframesSizeNode.style.height = prevAttrs.height } prevAttrs = {} } eventManager.on('after:screenshot', afterScreenshot) eventManager.on('run:start', () => { if (screenshotting) { afterScreenshot(prevAttrs.config) } }) } componentWillUnmount () { $(this.props.window).off('resize', this._onWindowResize) } } App.defaultProps = { window, util, } App.propTypes = { config: PropTypes.shape({ browsers: PropTypes.arrayOf(PropTypes.shape({ name: PropTypes.string.isRequired, majorVersion: PropTypes.oneOfType([ PropTypes.string, PropTypes.number, ]), version: PropTypes.string.isRequired, })).isRequired, integrationFolder: PropTypes.string.isRequired, numTestsKeptInMemory: PropTypes.number.isRequired, projectName: PropTypes.string.isRequired, viewportHeight: PropTypes.number.isRequired, viewportWidth: PropTypes.number.isRequired, }).isRequired, eventManager: PropTypes.shape({ notifyRunningSpec: PropTypes.func.isRequired, reporterBus: PropTypes.shape({ emit: PropTypes.func.isRequired, on: PropTypes.func.isRequired, }).isRequired, }).isRequired, state: PropTypes.instanceOf(State).isRequired, } export default App