Skip to content

Commit

Permalink
fix: only adjust autoscrolling in interactive mode (#23053)
Browse files Browse the repository at this point in the history
Co-authored-by: Lachlan Miller <lachlan.miller.1990@outlook.com>
  • Loading branch information
marktnoonan and lmiller1990 committed Sep 13, 2022
1 parent 566a1a2 commit 25a47aa
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 23 deletions.
6 changes: 0 additions & 6 deletions packages/app/src/main.ts
Expand Up @@ -12,12 +12,6 @@ import Toast, { POSITION } from 'vue-toastification'
import 'vue-toastification/dist/index.css'
import { createWebsocket, getRunnerConfigFromWindow } from './runner'

// set a global so we can run
// conditional code in the vite branch
// so that the existing runner code
// @ts-ignore
window.__vite__ = true

const app = createApp(App)

const config = getRunnerConfigFromWindow()
Expand Down
39 changes: 36 additions & 3 deletions packages/reporter/cypress/e2e/runnables.cy.ts
Expand Up @@ -3,7 +3,9 @@ import { RootRunnable } from '../../src/runnables/runnables-store'
import { itHandlesFileOpening } from '../support/utils'
import type { BaseReporterProps } from '../../src/main'
import type { RunnablesErrorModel } from '../../src/runnables/runnable-error'
import appState from '../../src/lib/app-state'
import { MobxRunnerStore } from '@packages/app/src/store'
import scroller from '../../src/lib/scroller'

const runnerStore = new MobxRunnerStore('e2e')

Expand All @@ -16,7 +18,7 @@ runnerStore.setSpec({
describe('runnables', () => {
let runner: EventEmitter
let runnables: RootRunnable
let render: (renderProps?: Partial<BaseReporterProps>) => void
let render: (renderProps?: Partial<BaseReporterProps>, cypressMode?: 'run' | 'open') => void
let start: (renderProps?: Partial<BaseReporterProps>) => Cypress.Chainable

beforeEach(() => {
Expand All @@ -26,12 +28,15 @@ describe('runnables', () => {

runner = new EventEmitter()

render = (renderProps: Partial<BaseReporterProps> = {}) => {
render = (renderProps: Partial<BaseReporterProps> = {}, cypressMode = 'open') => {
cy.visit('/').then((win: Cypress.AUTWindow) => {
win.__CYPRESS_MODE__ = cypressMode
win.render({
runner,
studioEnabled: renderProps.studioEnabled || false,
runnerStore,
scroller,
appState,
...renderProps,
})
})
Expand Down Expand Up @@ -183,14 +188,21 @@ describe('runnables', () => {
})

describe('runnable-header (unified)', () => {
let spy: Cypress.Agent<sinon.SinonSpy>

beforeEach(() => {
cy.window().then((win) => win.__vite__ = true)
scroller.__setScrollThreholdMs(500)
spy = cy.spy(appState, 'temporarilySetAutoScrolling')

start({
runnerStore,
})
})

afterEach(() => {
scroller.__reset()
})

it('contains name of spec and emits when clicked', () => {
const selector = '.runnable-header a'

Expand All @@ -201,5 +213,26 @@ describe('runnables', () => {
expect(runner.emit).to.be.calledWith('open:file:unified')
})
})

it('adds a scroll listener in open mode', () => {
appState.startRunning()
cy.get('.container')
.trigger('scroll')
.trigger('scroll')
.trigger('scroll').then(() => {
expect(spy).to.have.been.calledWith(false)
})
})

it('does not add a scroll listener in run mode', () => {
render({}, 'run')
appState.startRunning()
cy.get('.container')
.trigger('scroll')
.trigger('scroll')
.trigger('scroll').then(() => {
expect(spy).not.to.have.been.calledWith(false)
})
})
})
})
28 changes: 20 additions & 8 deletions packages/reporter/src/lib/scroller.ts
Expand Up @@ -13,17 +13,17 @@
- element distance from top of container
*/

import { TimeoutID } from './types'

type UserScrollCallback = () => void
export type UserScrollCallback = () => void

const PADDING = 100
const SCROLL_THRESHOLD_MS = 50

export class Scroller {
private _container: Element | null = null
private _userScrollCount = 0
private _userScroll = true
private _countUserScrollsTimeout?: TimeoutID
private _countUserScrollsTimeout?: number
private _userScrollThresholdMs = SCROLL_THRESHOLD_MS

setContainer (container: Element, onUserScroll?: UserScrollCallback) {
this._container = container
Expand Down Expand Up @@ -53,7 +53,7 @@ export class Scroller {
onUserScroll()
}

clearTimeout(this._countUserScrollsTimeout as TimeoutID)
clearTimeout(this._countUserScrollsTimeout)
this._countUserScrollsTimeout = undefined
this._userScrollCount = 0

Expand All @@ -62,10 +62,10 @@ export class Scroller {

if (this._countUserScrollsTimeout) return

this._countUserScrollsTimeout = setTimeout(() => {
this._countUserScrollsTimeout = window.setTimeout(() => {
this._countUserScrollsTimeout = undefined
this._userScrollCount = 0
}, 50)
}, this._userScrollThresholdMs)
})
}

Expand Down Expand Up @@ -129,8 +129,20 @@ export class Scroller {
this._container = null
this._userScroll = true
this._userScrollCount = 0
clearTimeout(this._countUserScrollsTimeout as TimeoutID)
clearTimeout(this._countUserScrollsTimeout)
this._countUserScrollsTimeout = undefined
this._userScrollThresholdMs = SCROLL_THRESHOLD_MS
}

__setScrollThreholdMs (ms: number) {
const isCypressInCypress = document.defaultView !== top

// only allow this to be set in testing
if (!isCypressInCypress) {
return
}

this._userScrollThresholdMs = ms
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/reporter/src/main.tsx
Expand Up @@ -144,6 +144,7 @@ declare global {
Cypress: any
state: AppState
render: ((props: Partial<BaseReporterProps>) => void)
__CYPRESS_MODE__: 'run' | 'open'
}
}

Expand Down
23 changes: 17 additions & 6 deletions packages/reporter/src/runnables/runnables.tsx
Expand Up @@ -9,7 +9,7 @@ import Runnable from './runnable-and-suite'
import RunnableHeader from './runnable-header'
import { RunnablesStore, RunnableArray } from './runnables-store'
import statsStore, { StatsStore } from '../header/stats-store'
import { Scroller } from '../lib/scroller'
import { Scroller, UserScrollCallback } from '../lib/scroller'
import type { AppState } from '../lib/app-state'
import OpenFileInIDE from '../lib/open-file-in-ide'

Expand Down Expand Up @@ -176,11 +176,22 @@ class Runnables extends Component<RunnablesProps> {
componentDidMount () {
const { scroller, appState } = this.props

scroller.setContainer(this.refs.container as Element, action('user:scroll:detected', () => {
if (appState && appState.isRunning) {
appState.temporarilySetAutoScrolling(false)
}
}))
let maybeHandleScroll: UserScrollCallback | undefined = undefined

if (window.__CYPRESS_MODE__ === 'open') {
// in open mode, listen for scroll events so that users can pause the command log auto-scroll
// by manually scrolling the command log
maybeHandleScroll = action('user:scroll:detected', () => {
if (appState && appState.isRunning) {
appState.temporarilySetAutoScrolling(false)
}
})
}

// we need to always call scroller.setContainer, but the callback can be undefined
// so we pass maybeHandleScroll. If we don't, Cypress blows up with an error like
// `A container must be set on the scroller with scroller.setContainer(container)`
scroller.setContainer(this.refs.container as Element, maybeHandleScroll)
}
}

Expand Down

5 comments on commit 25a47aa

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 25a47aa Sep 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.8.0/linux-x64/develop-25a47aa5db4e7799322db830317401ec8107e6d5/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 25a47aa Sep 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux arm64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.8.0/linux-arm64/develop-25a47aa5db4e7799322db830317401ec8107e6d5/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 25a47aa Sep 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin arm64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.8.0/darwin-arm64/develop-25a47aa5db4e7799322db830317401ec8107e6d5/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 25a47aa Sep 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.8.0/darwin-x64/develop-25a47aa5db4e7799322db830317401ec8107e6d5/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 25a47aa Sep 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the win32 x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.8.0/win32-x64/develop-25a47aa5db4e7799322db830317401ec8107e6d5/cypress.tgz

Please sign in to comment.