From 89acf9c8a5e6220f645eb4b2a72a27b056d010e0 Mon Sep 17 00:00:00 2001 From: Bill Glesias Date: Mon, 18 Jul 2022 18:24:01 -0400 Subject: [PATCH 1/3] chore: add types to screenshots (#22768) * chore: add types to screenshots * remove wrong reference to event property and opt for Event --- packages/driver/src/cy/commands/screenshot.ts | 101 +++++++++++------- packages/driver/src/cypress/log.ts | 1 + packages/driver/src/cypress/screenshot.ts | 2 +- packages/driver/src/cypress/utils.ts | 4 +- packages/driver/src/dom/animation.ts | 4 +- packages/driver/src/dom/blackout.ts | 8 +- 6 files changed, 73 insertions(+), 47 deletions(-) diff --git a/packages/driver/src/cy/commands/screenshot.ts b/packages/driver/src/cy/commands/screenshot.ts index c0c392ab23ec..b04ffdff1292 100644 --- a/packages/driver/src/cy/commands/screenshot.ts +++ b/packages/driver/src/cy/commands/screenshot.ts @@ -9,17 +9,42 @@ import $dom from '../../dom' import $errUtils from '../../cypress/error_utils' import $utils from '../../cypress/utils' import type { Log } from '../../cypress/log' +import type { StateFunc } from '../../cypress/state' -const getViewportHeight = (state) => { +interface InternalScreenshotOptions extends Partial { + _log?: Log +} + +type Scroll = { + y: number + clip?: Cypress.ScreenshotOptions['clip'] + afterScroll?: () => Cypress.Dimensions +} + +type TakeScreenshotOptions = { + name?: string + subject?: JQuery + simple?: boolean + testFailure?: boolean + runnable: (Mocha.Test | Mocha.Hook) & { + id: string + } + log?: Log + timeout?: number +} + +type AutomationOptions = TakeScreenshotOptions & Omit & Partial + +const getViewportHeight = (state: StateFunc) => { // TODO this doesn't seem correct return Math.min(state('viewportHeight'), window.innerHeight) } -const getViewportWidth = (state) => { +const getViewportWidth = (state: StateFunc) => { return Math.min(state('viewportWidth'), window.innerWidth) } -const automateScreenshot = (state, options: TakeScreenshotOptions = {}) => { +const automateScreenshot = (state: StateFunc, options: TakeScreenshotOptions) => { const { runnable, timeout } = options const titles: string[] = [] @@ -27,7 +52,7 @@ const automateScreenshot = (state, options: TakeScreenshotOptions = {}) => { // if this a hook then push both the current test title // and our own hook title if (runnable.type === 'hook') { - let ct = runnable.ctx.currentTest + let ct = runnable.ctx?.currentTest if (runnable.ctx && ct) { titles.push(ct.title, runnable.title) @@ -56,6 +81,7 @@ const automateScreenshot = (state, options: TakeScreenshotOptions = {}) => { titles, testId: runnable.id, takenPaths: state('screenshotPaths'), + // @ts-ignore testAttemptIndex: $utils.getTestFromRunnable(runnable)._currentRetry, }, _.omit(options, 'runnable', 'timeout', 'log', 'subject')) @@ -84,7 +110,7 @@ const automateScreenshot = (state, options: TakeScreenshotOptions = {}) => { }) } -const scrollOverrides = (win, doc) => { +const scrollOverrides = (win: Window, doc: Document) => { const originalOverflow = doc.documentElement.style.overflow const originalBodyOverflowY = doc.body.style.overflowY const originalX = win.scrollX @@ -108,7 +134,8 @@ const scrollOverrides = (win, doc) => { // since we scroll down the page in takeScrollingScreenshots // and don't want the page size to change once we start // https://github.com/cypress-io/cypress/issues/6099 - win.dispatchEvent(new win.Event('scroll')) + + win.dispatchEvent(new Event('scroll')) return () => { doc.documentElement.style.overflow = originalOverflow @@ -122,7 +149,7 @@ const scrollOverrides = (win, doc) => { } } -const validateNumScreenshots = (numScreenshots, automationOptions) => { +const validateNumScreenshots = (numScreenshots: number, automationOptions: AutomationOptions) => { if (numScreenshots < 1) { $errUtils.throwErrByPath('screenshot.invalid_height', { log: automationOptions.log, @@ -130,8 +157,8 @@ const validateNumScreenshots = (numScreenshots, automationOptions) => { } } -const takeScrollingScreenshots = (scrolls, win, state, automationOptions) => { - const scrollAndTake = ({ y, clip, afterScroll }, index) => { +const takeScrollingScreenshots = (scrolls: Scroll[], win: Window, state: StateFunc, automationOptions: AutomationOptions) => { + const scrollAndTake = ({ y, clip, afterScroll }: Scroll, index) => { win.scrollTo(0, y) if (afterScroll) { clip = afterScroll() @@ -151,7 +178,7 @@ const takeScrollingScreenshots = (scrolls, win, state, automationOptions) => { .then(_.last) } -const takeFullPageScreenshot = (state, automationOptions) => { +const takeFullPageScreenshot = (state: StateFunc, automationOptions: AutomationOptions) => { const win = state('window') const doc = state('document') @@ -187,11 +214,12 @@ const takeFullPageScreenshot = (state, automationOptions) => { .finally(resetScrollOverrides) } -const applyPaddingToElementPositioning = (elPosition, automationOptions) => { +const applyPaddingToElementPositioning = (elPosition: Cypress.ElementPositioning, automationOptions: AutomationOptions) => { if (!automationOptions.padding) { return elPosition } + // @ts-ignore const [paddingTop, paddingRight, paddingBottom, paddingLeft] = automationOptions.padding return { @@ -208,7 +236,7 @@ const applyPaddingToElementPositioning = (elPosition, automationOptions) => { } } -const takeElementScreenshot = ($el, state, automationOptions) => { +const takeElementScreenshot = ($el: JQuery, state: StateFunc, automationOptions: AutomationOptions) => { const win = state('window') const doc = state('document') @@ -224,7 +252,7 @@ const takeElementScreenshot = ($el, state, automationOptions) => { validateNumScreenshots(numScreenshots, automationOptions) - const scrolls = _.map(_.times(numScreenshots), (index) => { + const scrolls: Scroll[] = _.map(_.times(numScreenshots), (index) => { const y = elPosition.fromElWindow.top + (viewportHeight * index) const afterScroll = () => { @@ -274,30 +302,30 @@ const takeElementScreenshot = ($el, state, automationOptions) => { } // "app only" means we're hiding the runner UI -const isAppOnly = ({ capture }) => { +const isAppOnly = ({ capture }: { capture: Cypress.ScreenshotOptions['capture']}) => { return (capture === 'viewport') || (capture === 'fullPage') } -const getShouldScale = ({ capture, scale }) => { +const getShouldScale = ({ capture, scale }: { + capture: Cypress.ScreenshotOptions['capture'] + scale: Cypress.ScreenshotOptions['scale'] +}) => { return isAppOnly({ capture }) ? scale : true } -const getBlackout = ({ capture, blackout }) => { +const getBlackout = ({ capture, blackout }: { + capture: Cypress.ScreenshotOptions['capture'] + blackout: Cypress.ScreenshotOptions['blackout'] +}) => { return isAppOnly({ capture }) ? blackout : [] } -// TODO: anys should be removed. -type TakeScreenshotOptions = { - name?: string - subject?: any - simple?: boolean - testFailure?: boolean - runnable?: any - log?: any - timeout?: number -} - -const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreenshotOptions = {}) => { +const takeScreenshot = ( + Cypress: Cypress.Cypress, + state: StateFunc, + screenshotConfig: Partial & Pick, + options: TakeScreenshotOptions, +) => { const { capture, padding, @@ -326,7 +354,8 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho const getOptions = (isOpen) => { return { id: runnable.id, - testAttemptIndex: $utils.getTestFromRunnable(runnable)._currentRetry, + // @ts-ignore + testAttemptIndex: $utils.getTestFromRunnable(runnable)?._currentRetry, isOpen, appOnly: isAppOnly(screenshotConfig), scale: getShouldScale(screenshotConfig), @@ -337,7 +366,7 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho } } - const before = ($body, $container) => { + const before = ($body: JQuery, $container: JQuery) => { return Promise.try(() => { if (disableTimersAndAnimations) { return cy.pauseTimers(true) @@ -366,7 +395,7 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho }) } - const after = ($body) => { + const after = ($body: JQuery) => { // could fail if iframe is cross-origin, so fail gracefully try { if (disableTimersAndAnimations) { @@ -392,7 +421,7 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho }) } - const automationOptions = _.extend({}, options, { + const automationOptions: AutomationOptions = _.extend({}, options, { capture, clip: { x: 0, @@ -413,13 +442,13 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho }) // use the subject as $el or yield the wrapped documentElement - const $el = $dom.isElement(subject) + const $el: JQuery = $dom.isElement(subject) ? subject : $dom.wrap(state('document').documentElement) // get the current body of the AUT to accurately calculate screenshot blackouts // as well as properly enable/disable CSS animations while screenshotting is happening - const $body = Cypress.$('body') + const $body: JQuery = Cypress.$('body') return before($body, $el) .then(() => { @@ -451,10 +480,6 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho .finally(() => after($body)) } -interface InternalScreenshotOptions extends Partial { - _log?: Log -} - export default function (Commands, Cypress, cy, state, config) { // failure screenshot when not interactive Cypress.on('runnable:after:run:async', (test, runnable) => { diff --git a/packages/driver/src/cypress/log.ts b/packages/driver/src/cypress/log.ts index a2869227d462..6bec5bf54100 100644 --- a/packages/driver/src/cypress/log.ts +++ b/packages/driver/src/cypress/log.ts @@ -179,6 +179,7 @@ const defaults = function (state: StateFunc, config, obj) { const t = $utils.getTestFromRunnable(runnable) + // @ts-ignore return t._currentRetry || 0 } diff --git a/packages/driver/src/cypress/screenshot.ts b/packages/driver/src/cypress/screenshot.ts index d9648a232db8..e24bb6f627ad 100644 --- a/packages/driver/src/cypress/screenshot.ts +++ b/packages/driver/src/cypress/screenshot.ts @@ -3,7 +3,7 @@ import _ from 'lodash' import $utils from './utils' import $errUtils from './error_utils' -const _reset = () => { +const _reset = (): Pick => { return { capture: 'fullPage', scale: false, diff --git a/packages/driver/src/cypress/utils.ts b/packages/driver/src/cypress/utils.ts index ef4f7d0f576e..bce7d4df618c 100644 --- a/packages/driver/src/cypress/utils.ts +++ b/packages/driver/src/cypress/utils.ts @@ -312,8 +312,8 @@ export default { return Math.sqrt((deltaX * deltaX) + (deltaY * deltaY)) }, - getTestFromRunnable (r) { - return r.ctx.currentTest || r + getTestFromRunnable (r: Mocha.Runnable) { + return r.ctx?.currentTest || r }, memoize (func, cacheInstance = new Map()) { diff --git a/packages/driver/src/dom/animation.ts b/packages/driver/src/dom/animation.ts index e18c2b2c2a31..42282d04a570 100644 --- a/packages/driver/src/dom/animation.ts +++ b/packages/driver/src/dom/animation.ts @@ -1,6 +1,6 @@ import $ from 'jquery' -function addCssAnimationDisabler ($body) { +function addCssAnimationDisabler ($body: JQuery) { $(`