Skip to content

Commit 89acf9c

Browse files
authored
chore: add types to screenshots (#22768)
* chore: add types to screenshots * remove wrong reference to event property and opt for Event
1 parent 0aebe4a commit 89acf9c

File tree

6 files changed

+73
-47
lines changed

6 files changed

+73
-47
lines changed

packages/driver/src/cy/commands/screenshot.ts

Lines changed: 63 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,50 @@ import $dom from '../../dom'
99
import $errUtils from '../../cypress/error_utils'
1010
import $utils from '../../cypress/utils'
1111
import type { Log } from '../../cypress/log'
12+
import type { StateFunc } from '../../cypress/state'
1213

13-
const getViewportHeight = (state) => {
14+
interface InternalScreenshotOptions extends Partial<Cypress.Loggable & Cypress.Timeoutable & Cypress.ScreenshotOptions> {
15+
_log?: Log
16+
}
17+
18+
type Scroll = {
19+
y: number
20+
clip?: Cypress.ScreenshotOptions['clip']
21+
afterScroll?: () => Cypress.Dimensions
22+
}
23+
24+
type TakeScreenshotOptions = {
25+
name?: string
26+
subject?: JQuery<HTMLElement>
27+
simple?: boolean
28+
testFailure?: boolean
29+
runnable: (Mocha.Test | Mocha.Hook) & {
30+
id: string
31+
}
32+
log?: Log
33+
timeout?: number
34+
}
35+
36+
type AutomationOptions = TakeScreenshotOptions & Omit<Cypress.ScreenshotOptions, 'onBeforeScreenshot'| 'onAfterScreenshot' | 'disableTimersAndAnimations' | 'scale' | 'padding'> & Partial<Cypress.ScreenshotOptions>
37+
38+
const getViewportHeight = (state: StateFunc) => {
1439
// TODO this doesn't seem correct
1540
return Math.min(state('viewportHeight'), window.innerHeight)
1641
}
1742

18-
const getViewportWidth = (state) => {
43+
const getViewportWidth = (state: StateFunc) => {
1944
return Math.min(state('viewportWidth'), window.innerWidth)
2045
}
2146

22-
const automateScreenshot = (state, options: TakeScreenshotOptions = {}) => {
47+
const automateScreenshot = (state: StateFunc, options: TakeScreenshotOptions) => {
2348
const { runnable, timeout } = options
2449

2550
const titles: string[] = []
2651

2752
// if this a hook then push both the current test title
2853
// and our own hook title
2954
if (runnable.type === 'hook') {
30-
let ct = runnable.ctx.currentTest
55+
let ct = runnable.ctx?.currentTest
3156

3257
if (runnable.ctx && ct) {
3358
titles.push(ct.title, runnable.title)
@@ -56,6 +81,7 @@ const automateScreenshot = (state, options: TakeScreenshotOptions = {}) => {
5681
titles,
5782
testId: runnable.id,
5883
takenPaths: state('screenshotPaths'),
84+
// @ts-ignore
5985
testAttemptIndex: $utils.getTestFromRunnable(runnable)._currentRetry,
6086
}, _.omit(options, 'runnable', 'timeout', 'log', 'subject'))
6187

@@ -84,7 +110,7 @@ const automateScreenshot = (state, options: TakeScreenshotOptions = {}) => {
84110
})
85111
}
86112

87-
const scrollOverrides = (win, doc) => {
113+
const scrollOverrides = (win: Window, doc: Document) => {
88114
const originalOverflow = doc.documentElement.style.overflow
89115
const originalBodyOverflowY = doc.body.style.overflowY
90116
const originalX = win.scrollX
@@ -108,7 +134,8 @@ const scrollOverrides = (win, doc) => {
108134
// since we scroll down the page in takeScrollingScreenshots
109135
// and don't want the page size to change once we start
110136
// https://github.com/cypress-io/cypress/issues/6099
111-
win.dispatchEvent(new win.Event('scroll'))
137+
138+
win.dispatchEvent(new Event('scroll'))
112139

113140
return () => {
114141
doc.documentElement.style.overflow = originalOverflow
@@ -122,16 +149,16 @@ const scrollOverrides = (win, doc) => {
122149
}
123150
}
124151

125-
const validateNumScreenshots = (numScreenshots, automationOptions) => {
152+
const validateNumScreenshots = (numScreenshots: number, automationOptions: AutomationOptions) => {
126153
if (numScreenshots < 1) {
127154
$errUtils.throwErrByPath('screenshot.invalid_height', {
128155
log: automationOptions.log,
129156
})
130157
}
131158
}
132159

133-
const takeScrollingScreenshots = (scrolls, win, state, automationOptions) => {
134-
const scrollAndTake = ({ y, clip, afterScroll }, index) => {
160+
const takeScrollingScreenshots = (scrolls: Scroll[], win: Window, state: StateFunc, automationOptions: AutomationOptions) => {
161+
const scrollAndTake = ({ y, clip, afterScroll }: Scroll, index) => {
135162
win.scrollTo(0, y)
136163
if (afterScroll) {
137164
clip = afterScroll()
@@ -151,7 +178,7 @@ const takeScrollingScreenshots = (scrolls, win, state, automationOptions) => {
151178
.then(_.last)
152179
}
153180

154-
const takeFullPageScreenshot = (state, automationOptions) => {
181+
const takeFullPageScreenshot = (state: StateFunc, automationOptions: AutomationOptions) => {
155182
const win = state('window')
156183
const doc = state('document')
157184

@@ -187,11 +214,12 @@ const takeFullPageScreenshot = (state, automationOptions) => {
187214
.finally(resetScrollOverrides)
188215
}
189216

190-
const applyPaddingToElementPositioning = (elPosition, automationOptions) => {
217+
const applyPaddingToElementPositioning = (elPosition: Cypress.ElementPositioning, automationOptions: AutomationOptions) => {
191218
if (!automationOptions.padding) {
192219
return elPosition
193220
}
194221

222+
// @ts-ignore
195223
const [paddingTop, paddingRight, paddingBottom, paddingLeft] = automationOptions.padding
196224

197225
return {
@@ -208,7 +236,7 @@ const applyPaddingToElementPositioning = (elPosition, automationOptions) => {
208236
}
209237
}
210238

211-
const takeElementScreenshot = ($el, state, automationOptions) => {
239+
const takeElementScreenshot = ($el: JQuery<HTMLElement>, state: StateFunc, automationOptions: AutomationOptions) => {
212240
const win = state('window')
213241
const doc = state('document')
214242

@@ -224,7 +252,7 @@ const takeElementScreenshot = ($el, state, automationOptions) => {
224252

225253
validateNumScreenshots(numScreenshots, automationOptions)
226254

227-
const scrolls = _.map(_.times(numScreenshots), (index) => {
255+
const scrolls: Scroll[] = _.map(_.times(numScreenshots), (index) => {
228256
const y = elPosition.fromElWindow.top + (viewportHeight * index)
229257

230258
const afterScroll = () => {
@@ -274,30 +302,30 @@ const takeElementScreenshot = ($el, state, automationOptions) => {
274302
}
275303

276304
// "app only" means we're hiding the runner UI
277-
const isAppOnly = ({ capture }) => {
305+
const isAppOnly = ({ capture }: { capture: Cypress.ScreenshotOptions['capture']}) => {
278306
return (capture === 'viewport') || (capture === 'fullPage')
279307
}
280308

281-
const getShouldScale = ({ capture, scale }) => {
309+
const getShouldScale = ({ capture, scale }: {
310+
capture: Cypress.ScreenshotOptions['capture']
311+
scale: Cypress.ScreenshotOptions['scale']
312+
}) => {
282313
return isAppOnly({ capture }) ? scale : true
283314
}
284315

285-
const getBlackout = ({ capture, blackout }) => {
316+
const getBlackout = ({ capture, blackout }: {
317+
capture: Cypress.ScreenshotOptions['capture']
318+
blackout: Cypress.ScreenshotOptions['blackout']
319+
}) => {
286320
return isAppOnly({ capture }) ? blackout : []
287321
}
288322

289-
// TODO: anys should be removed.
290-
type TakeScreenshotOptions = {
291-
name?: string
292-
subject?: any
293-
simple?: boolean
294-
testFailure?: boolean
295-
runnable?: any
296-
log?: any
297-
timeout?: number
298-
}
299-
300-
const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreenshotOptions = {}) => {
323+
const takeScreenshot = (
324+
Cypress: Cypress.Cypress,
325+
state: StateFunc,
326+
screenshotConfig: Partial<Cypress.ScreenshotOptions> & Pick<Cypress.ScreenshotOptions, 'capture' | 'scale' | 'blackout' | 'overwrite'>,
327+
options: TakeScreenshotOptions,
328+
) => {
301329
const {
302330
capture,
303331
padding,
@@ -326,7 +354,8 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho
326354
const getOptions = (isOpen) => {
327355
return {
328356
id: runnable.id,
329-
testAttemptIndex: $utils.getTestFromRunnable(runnable)._currentRetry,
357+
// @ts-ignore
358+
testAttemptIndex: $utils.getTestFromRunnable(runnable)?._currentRetry,
330359
isOpen,
331360
appOnly: isAppOnly(screenshotConfig),
332361
scale: getShouldScale(screenshotConfig),
@@ -337,7 +366,7 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho
337366
}
338367
}
339368

340-
const before = ($body, $container) => {
369+
const before = ($body: JQuery<HTMLBodyElement>, $container: JQuery<HTMLElement>) => {
341370
return Promise.try(() => {
342371
if (disableTimersAndAnimations) {
343372
return cy.pauseTimers(true)
@@ -366,7 +395,7 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho
366395
})
367396
}
368397

369-
const after = ($body) => {
398+
const after = ($body: JQuery<HTMLBodyElement>) => {
370399
// could fail if iframe is cross-origin, so fail gracefully
371400
try {
372401
if (disableTimersAndAnimations) {
@@ -392,7 +421,7 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho
392421
})
393422
}
394423

395-
const automationOptions = _.extend({}, options, {
424+
const automationOptions: AutomationOptions = _.extend({}, options, {
396425
capture,
397426
clip: {
398427
x: 0,
@@ -413,13 +442,13 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho
413442
})
414443

415444
// use the subject as $el or yield the wrapped documentElement
416-
const $el = $dom.isElement(subject)
445+
const $el: JQuery<HTMLElement> = $dom.isElement(subject)
417446
? subject
418447
: $dom.wrap(state('document').documentElement)
419448

420449
// get the current body of the AUT to accurately calculate screenshot blackouts
421450
// as well as properly enable/disable CSS animations while screenshotting is happening
422-
const $body = Cypress.$('body')
451+
const $body: JQuery<HTMLBodyElement> = Cypress.$('body')
423452

424453
return before($body, $el)
425454
.then(() => {
@@ -451,10 +480,6 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options: TakeScreensho
451480
.finally(() => after($body))
452481
}
453482

454-
interface InternalScreenshotOptions extends Partial<Cypress.Loggable & Cypress.Timeoutable & Cypress.ScreenshotOptions> {
455-
_log?: Log
456-
}
457-
458483
export default function (Commands, Cypress, cy, state, config) {
459484
// failure screenshot when not interactive
460485
Cypress.on('runnable:after:run:async', (test, runnable) => {

packages/driver/src/cypress/log.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ const defaults = function (state: StateFunc, config, obj) {
179179

180180
const t = $utils.getTestFromRunnable(runnable)
181181

182+
// @ts-ignore
182183
return t._currentRetry || 0
183184
}
184185

packages/driver/src/cypress/screenshot.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import _ from 'lodash'
33
import $utils from './utils'
44
import $errUtils from './error_utils'
55

6-
const _reset = () => {
6+
const _reset = (): Pick<Cypress.ScreenshotDefaultsOptions, 'capture' | 'scale' | 'disableTimersAndAnimations' | 'screenshotOnRunFailure' | 'blackout' | 'overwrite' | 'onBeforeScreenshot' | 'onAfterScreenshot'> => {
77
return {
88
capture: 'fullPage',
99
scale: false,

packages/driver/src/cypress/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,8 +312,8 @@ export default {
312312
return Math.sqrt((deltaX * deltaX) + (deltaY * deltaY))
313313
},
314314

315-
getTestFromRunnable (r) {
316-
return r.ctx.currentTest || r
315+
getTestFromRunnable (r: Mocha.Runnable) {
316+
return r.ctx?.currentTest || r
317317
},
318318

319319
memoize (func, cacheInstance = new Map()) {

packages/driver/src/dom/animation.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import $ from 'jquery'
22

3-
function addCssAnimationDisabler ($body) {
3+
function addCssAnimationDisabler ($body: JQuery<HTMLBodyElement>) {
44
$(`
55
<style id="__cypress-animation-disabler">
66
*, *:before, *:after {
@@ -11,7 +11,7 @@ function addCssAnimationDisabler ($body) {
1111
`).appendTo($body)
1212
}
1313

14-
function removeCssAnimationDisabler ($body) {
14+
function removeCssAnimationDisabler ($body: JQuery<HTMLBodyElement>) {
1515
$body.find('#__cypress-animation-disabler').remove()
1616
}
1717

packages/driver/src/dom/blackout.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const styles = (styleString) => {
1111
return styleString.replace(/\s*\n\s*/g, '')
1212
}
1313

14-
function addBlackoutForElement ($body, $el) {
14+
function addBlackoutForElement ($body: JQuery<HTMLBodyElement>, $el: JQuery<HTMLElement>) {
1515
const dimensions = $dimensions.getElementDimensions($el)
1616
const width = dimensions.widthWithBorder
1717
const height = dimensions.heightWithBorder
@@ -32,8 +32,8 @@ function addBlackoutForElement ($body, $el) {
3232
$(`<div class="__cypress-blackout" style="${style}">`).appendTo($body)
3333
}
3434

35-
function addBlackouts ($body, $container, selector) {
36-
let $el
35+
function addBlackouts ($body: JQuery<HTMLBodyElement>, $container: JQuery<HTMLElement>, selector: string) {
36+
let $el: JQuery<HTMLElement>
3737

3838
try {
3939
// only scope blacked out elements to to screenshotted element, not necessarily the whole body
@@ -49,7 +49,7 @@ function addBlackouts ($body, $container, selector) {
4949
})
5050
}
5151

52-
function removeBlackouts ($body) {
52+
function removeBlackouts ($body: JQuery<HTMLBodyElement>) {
5353
$body.find('.__cypress-blackout').remove()
5454
}
5555

0 commit comments

Comments
 (0)