UNPKG

@revoloo/cypress6

Version:

Cypress.io end to end testing tool

244 lines (182 loc) 6.37 kB
import _ from 'lodash' import { action } from 'mobx' import eventManager from '../lib/event-manager' import selectorPlaygroundModel from '../selector-playground/selector-playground-model' import studioRecorder from '../studio/studio-recorder' export default class IframeModel { constructor ({ state, detachDom, removeHeadStyles, restoreDom, highlightEl, snapshotControls }) { this.state = state this.detachDom = detachDom this.removeHeadStyles = removeHeadStyles this.restoreDom = restoreDom this.highlightEl = highlightEl this.snapshotControls = snapshotControls this._reset() } listen () { eventManager.on('run:start', action('run:start', this._beforeRun)) eventManager.on('run:end', action('run:end', this._afterRun)) eventManager.on('viewport:changed', action('viewport:changed', this._updateViewport)) eventManager.on('config', action('config', (config) => { this._updateViewport(_.map(config, 'viewportHeight', 'viewportWidth')) })) eventManager.on('url:changed', action('url:changed', this._updateUrl)) eventManager.on('page:loading', action('page:loading', this._updateLoadingUrl)) eventManager.on('show:snapshot', action('show:snapshot', this._setSnapshots)) eventManager.on('hide:snapshot', action('hide:snapshot', this._clearSnapshots)) eventManager.on('pin:snapshot', action('pin:snapshot', this._pinSnapshot)) eventManager.on('unpin:snapshot', action('unpin:snapshot', this._unpinSnapshot)) } _beforeRun = () => { this.state.isLoading = false this.state.isRunning = true this.state.resetUrl() selectorPlaygroundModel.setEnabled(false) this._reset() this._clearMessage() } _afterRun = () => { this.state.isRunning = false } _updateViewport = ({ viewportWidth, viewportHeight }, cb) => { this.state.updateDimensions(viewportWidth, viewportHeight) if (cb) { this.state.setCallbackAfterUpdate(cb) } } _updateUrl = (url) => { this.state.url = url } _updateLoadingUrl = (isLoadingUrl) => { this.state.isLoadingUrl = isLoadingUrl } _clearMessage = () => { this.state.clearMessage() } _setSnapshots = (snapshotProps) => { if (this.isSnapshotPinned) return if (this.state.isRunning) { return this._testsRunningError() } if (studioRecorder.isOpen) { return this._studioOpenError() } const { snapshots } = snapshotProps if (!snapshots || !snapshots.length) { this._clearSnapshots() this._setMissingSnapshotMessage() return } this.state.highlightUrl = true if (!this.originalState) { this._storeOriginalState() } this.detachedId = snapshotProps.id this._updateViewport(snapshotProps) this._updateUrl(snapshotProps.url) clearInterval(this.intervalId) const revert = action('revert:snapshot', this._showSnapshot) if (snapshots.length > 1) { let i = 0 this.intervalId = setInterval(() => { if (this.isSnapshotPinned) return i += 1 if (!snapshots[i]) { i = 0 } revert(snapshots[i], snapshotProps) }, 800) } revert(snapshots[0], snapshotProps) } _showSnapshot = (snapshot, snapshotProps) => { this.state.messageTitle = 'DOM Snapshot' this.state.messageDescription = snapshot.name this.state.messageType = '' this._restoreDom(snapshot, snapshotProps) } _restoreDom (snapshot, snapshotProps) { this.restoreDom(snapshot) if (snapshotProps.$el) { this.highlightEl(snapshot, snapshotProps) } } _clearSnapshots = () => { if (this.isSnapshotPinned) return clearInterval(this.intervalId) this.state.highlightUrl = false if (!this.originalState || !this.originalState.body) { return this._clearMessage() } const previousDetachedId = this.detachedId // process on next tick so we don't restore the dom if we're // about to receive another 'show:snapshot' event, else that would // be a huge waste setTimeout(action('clear:snapshots:next:tick', () => { // we want to only restore the dom if we haven't received // another snapshot by the time this function runs if (previousDetachedId !== this.detachedId) return this._updateViewport(this.originalState) this._updateUrl(this.originalState.url) this.restoreDom(this.originalState.snapshot) this._clearMessage() this.originalState = null this.detachedId = null })) } _pinSnapshot = (snapshotProps) => { const { snapshots } = snapshotProps if (!snapshots || !snapshots.length) { eventManager.snapshotUnpinned() this._setMissingSnapshotMessage() return } clearInterval(this.intervalId) this.isSnapshotPinned = true this.state.snapshot.showingHighlights = true this.state.snapshot.stateIndex = 0 this.state.messageTitle = 'DOM Snapshot' this.state.messageDescription = 'pinned' this.state.messageType = 'info' this.state.messageControls = this.snapshotControls(snapshotProps) this._restoreDom(snapshots[0], snapshotProps) } _setMissingSnapshotMessage () { this.state.messageTitle = 'The snapshot is missing. Displaying current state of the DOM.' this.state.messageDescription = '' this.state.messageType = 'warning' } _unpinSnapshot = () => { this.isSnapshotPinned = false this.state.messageTitle = 'DOM Snapshot' this.state.messageDescription = '' this.state.messageControls = null } _testsRunningError () { this.state.messageTitle = 'Cannot show Snapshot while tests are running' this.state.messageType = 'warning' } _studioOpenError () { this.state.messageTitle = 'Cannot show Snapshot while creating commands in Studio' this.state.messageType = 'warning' } _storeOriginalState () { const finalSnapshot = this.detachDom() if (!finalSnapshot) return const { body, htmlAttrs } = finalSnapshot this.originalState = { body, htmlAttrs, snapshot: finalSnapshot, url: this.state.url, viewportWidth: this.state.width, viewportHeight: this.state.height, } } _reset () { this.detachedId = null this.intervalId = null this.originalState = null this.isSnapshotPinned = false } }