How to use onBeforeScreenshot method in Cypress

Best JavaScript code snippet using cypress

Run Cypress automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

screenshotCleaner.js

Source: screenshotCleaner.js Github

copy
1export function createScreenShots(screenshotName, viewPort, options = {}) {
2  console.log({ viewPort })
3
4  let onBeforeScreenshot = null
5
6  if (viewPort < 1023) {
7    console.log('mobile')
8    onBeforeScreenshot = ($el) => {
9      const $header = $el.find('[data-cy=header-mobile]')
10      console.log({ $header })
11      if ($header) {
12        $header.css('position', 'relative')
13      }
14    }
15  }
16  if (viewPort > 1023) {
17    console.log('desktop')
18    onBeforeScreenshot = ($el) => {
19      const $header = $el.find('[data-cy=header-desktop-sticky]')
20      console.log({ $header })
21      if ($header) {
22        $header.hide()
23        $header.css('position', 'relative')
24        $header.css('opacity', '0')
25      }
26    }
27    // cy.get('[data-cy=header-desktop-sticky]').invoke('css', 'opacity', '0')
28    // cy.get('[data-cy=header-desktop-sticky]').invoke('css', 'position', 'relative')
29    // cy.get('[data-cy=labelkey-toggle]').invoke('css', 'position', 'absolute')
30  }
31
32  options = {
33    onBeforeScreenshot,
34  }
35
36  cy.screenshot(screenshotName, options)
37}
38
Full Screen

screenshot_spec.js

Source: screenshot_spec.js Github

copy
1const { Screenshot } = Cypress
2
3const DEFAULTS = {
4  capture: 'fullPage',
5  scale: false,
6  disableTimersAndAnimations: true,
7  screenshotOnRunFailure: true,
8  blackout: [],
9}
10
11describe('src/cypress/screenshot', () => {
12  beforeEach(() => {
13    // reset state since this is a singleton
14    Screenshot.reset()
15  })
16
17  it('has defaults', () => {
18    expect(Screenshot.getConfig()).to.deep.eq(DEFAULTS)
19    expect(() => {
20      Screenshot.onBeforeScreenshot()
21    }).not.to.throw()
22
23    expect(() => {
24      Screenshot.onAfterScreenshot()
25    }).not.to.throw()
26  })
27
28  context('.getConfig', () => {
29    it('returns copy of config', () => {
30      const config = Screenshot.getConfig()
31
32      config.blackout.push('.foo')
33
34      expect(Screenshot.getConfig().blackout).to.deep.eq(DEFAULTS.blackout)
35    })
36  })
37
38  context('.defaults', () => {
39    it('is noop if not called with any valid properties', () => {
40      Screenshot.defaults({})
41      expect(Screenshot.getConfig()).to.deep.eq(DEFAULTS)
42      expect(() => {
43        Screenshot.onBeforeScreenshot()
44      }).not.to.throw()
45
46      expect(() => {
47        Screenshot.onAfterScreenshot()
48      }).not.to.throw()
49    })
50
51    it('sets capture if specified', () => {
52      Screenshot.defaults({
53        capture: 'runner',
54      })
55
56      expect(Screenshot.getConfig().capture).to.eql('runner')
57    })
58
59    it('sets scale if specified', () => {
60      Screenshot.defaults({
61        scale: true,
62      })
63
64      expect(Screenshot.getConfig().scale).to.equal(true)
65    })
66
67    it('sets disableTimersAndAnimations if specified', () => {
68      Screenshot.defaults({
69        disableTimersAndAnimations: false,
70      })
71
72      expect(Screenshot.getConfig().disableTimersAndAnimations).to.equal(false)
73    })
74
75    it('sets screenshotOnRunFailure if specified', () => {
76      Screenshot.defaults({
77        screenshotOnRunFailure: false,
78      })
79
80      expect(Screenshot.getConfig().screenshotOnRunFailure).to.equal(false)
81    })
82
83    it('sets clip if specified', () => {
84      Screenshot.defaults({
85        clip: { width: 200, height: 100, x: 0, y: 0 },
86      })
87
88      expect(
89        Screenshot.getConfig().clip,
90      ).to.eql(
91        { width: 200, height: 100, x: 0, y: 0 },
92      )
93    })
94
95    it('sets and normalizes padding if specified', () => {
96      const tests = [
97        [50, [50, 50, 50, 50]],
98        [[15], [15, 15, 15, 15]],
99        [[30, 20], [30, 20, 30, 20]],
100        [[10, 20, 30], [10, 20, 30, 20]],
101        [[20, 10, 20, 10], [20, 10, 20, 10]],
102      ]
103
104      for (let test of tests) {
105        const [input, expected] = test
106
107        Screenshot.defaults({
108          padding: input,
109        })
110
111        expect(Screenshot.getConfig().padding).to.eql(expected)
112      }
113    })
114
115    it('sets onBeforeScreenshot if specified', () => {
116      const onBeforeScreenshot = cy.stub()
117
118      Screenshot.defaults({ onBeforeScreenshot })
119      Screenshot.onBeforeScreenshot()
120
121      expect(onBeforeScreenshot).to.be.called
122    })
123
124    it('sets onAfterScreenshot if specified', () => {
125      const onAfterScreenshot = cy.stub()
126
127      Screenshot.defaults({ onAfterScreenshot })
128      Screenshot.onAfterScreenshot()
129
130      expect(onAfterScreenshot).to.be.called
131    })
132
133    describe('errors', () => {
134      it('throws if not passed an object', () => {
135        const fn = () => {
136          Screenshot.defaults()
137        }
138
139        expect(fn).to.throw()
140        .with.property('message')
141        .and.include('`Cypress.Screenshot.defaults()` must be called with an object. You passed: ``')
142
143        expect(fn).to.throw()
144        .with.property('docsUrl')
145        .and.include('https://on.cypress.io/screenshot-api')
146      })
147
148      it('throws if capture is not a string', () => {
149        const fn = () => {
150          Screenshot.defaults({ capture: true })
151        }
152
153        expect(fn).to.throw()
154        .with.property('message')
155        .and.include('`Cypress.Screenshot.defaults()` `capture` option must be one of the following: `fullPage`, `viewport`, or `runner`. You passed: `true`')
156
157        expect(fn).to.throw()
158        .with.property('docsUrl')
159        .and.eq('https://on.cypress.io/screenshot-api')
160      })
161
162      it('throws if capture is not a valid option', () => {
163        const fn = () => {
164          Screenshot.defaults({ capture: 'foo' })
165        }
166
167        expect(fn).to.throw()
168        .with.property('message')
169        .and.include('`Cypress.Screenshot.defaults()` `capture` option must be one of the following: `fullPage`, `viewport`, or `runner`. You passed: `foo`')
170
171        expect(fn).to.throw()
172        .with.property('docsUrl')
173        .and.eq('https://on.cypress.io/screenshot-api')
174      })
175
176      it('throws if scale is not a boolean', () => {
177        const fn = () => {
178          Screenshot.defaults({ scale: 'foo' })
179        }
180
181        expect(fn).to.throw()
182        .with.property('message')
183        .and.include('`Cypress.Screenshot.defaults()` `scale` option must be a boolean. You passed: `foo`')
184
185        expect(fn).to.throw()
186        .with.property('docsUrl')
187        .and.eq('https://on.cypress.io/screenshot-api')
188      })
189
190      it('throws if disableTimersAndAnimations is not a boolean', () => {
191        const fn = () => {
192          Screenshot.defaults({ disableTimersAndAnimations: 'foo' })
193        }
194
195        expect(fn).to.throw()
196        .with.property('message')
197        .and.include('`Cypress.Screenshot.defaults()` `disableTimersAndAnimations` option must be a boolean. You passed: `foo`')
198
199        expect(fn).to.throw()
200        .with.property('docsUrl')
201        .and.eq('https://on.cypress.io/screenshot-api')
202      })
203
204      it('throws if screenshotOnRunFailure is not a boolean', () => {
205        const fn = () => {
206          Screenshot.defaults({ screenshotOnRunFailure: 'foo' })
207        }
208
209        expect(fn).to.throw()
210        .with.property('message')
211        .and.include('`Cypress.Screenshot.defaults()` `screenshotOnRunFailure` option must be a boolean. You passed: `foo`')
212
213        expect(fn).to.throw()
214        .with.property('docsUrl')
215        .and.include('https://on.cypress.io/screenshot-api')
216      })
217
218      it('throws if blackout is not an array', () => {
219        const fn = () => {
220          Screenshot.defaults({ blackout: 'foo' })
221        }
222
223        expect(fn).to.throw()
224        .with.property('message')
225        .and.include('`Cypress.Screenshot.defaults()` `blackout` option must be an array of strings. You passed: `foo`')
226
227        expect(fn).to.throw()
228        .with.property('docsUrl')
229        .and.include('https://on.cypress.io/screenshot-api')
230      })
231
232      it('throws if blackout is not an array of strings', () => {
233        const fn = () => {
234          Screenshot.defaults({ blackout: [true] })
235        }
236
237        expect(fn).to.throw()
238        .with.property('message')
239        .and.include('`Cypress.Screenshot.defaults()` `blackout` option must be an array of strings. You passed: `true`')
240
241        expect(fn).to.throw()
242        .with.property('docsUrl')
243        .and.include('https://on.cypress.io/screenshot-api')
244      })
245
246      it('throws if padding is not a number or an array of numbers with a length between 1 and 4', () => {
247        expect(() => {
248          Screenshot.defaults({ padding: '50px' })
249        }).to.throw('`Cypress.Screenshot.defaults()` `padding` option must be either a number or an array of numbers with a maximum length of 4. You passed: `50px`')
250
251        expect(() => {
252          Screenshot.defaults({ padding: ['bad', 'bad', 'bad', 'bad'] })
253        }).to.throw('`Cypress.Screenshot.defaults()` `padding` option must be either a number or an array of numbers with a maximum length of 4. You passed: `bad, bad, bad, bad`')
254
255        expect(() => {
256          Screenshot.defaults({ padding: [20, 10, 20, 10, 50] })
257        }).to.throw('`Cypress.Screenshot.defaults()` `padding` option must be either a number or an array of numbers with a maximum length of 4. You passed: `20, 10, 20, 10, 50`')
258      })
259
260      it('throws if clip is lacking proper keys', () => {
261        expect(() => {
262          Screenshot.defaults({ clip: { x: 5 } })
263        }).to.throw('`Cypress.Screenshot.defaults()` `clip` option must be an object with the keys `{ width, height, x, y }` and number values. You passed: `{x: 5}`')
264      })
265
266      it('throws if clip has extraneous keys', () => {
267        expect(() => {
268          Screenshot.defaults({ clip: { width: 100, height: 100, x: 5, y: 5, foo: 10 } })
269        }).to.throw('`Cypress.Screenshot.defaults()` `clip` option must be an object with the keys `{ width, height, x, y }` and number values. You passed: `Object{5}`')
270      })
271
272      it('throws if clip has non-number values', () => {
273        expect(() => {
274          Screenshot.defaults({ clip: { width: 100, height: 100, x: 5, y: '5' } })
275        }).to.throw('`Cypress.Screenshot.defaults()` `clip` option must be an object with the keys `{ width, height, x, y }` and number values. You passed: `Object{4}`')
276      })
277
278      it('throws if onBeforeScreenshot is not a function', () => {
279        const fn = () => {
280          Screenshot.defaults({ onBeforeScreenshot: 'foo' })
281        }
282
283        expect(fn)
284        .to.throw()
285        .with.property('message')
286        .and.include('`Cypress.Screenshot.defaults()` `onBeforeScreenshot` option must be a function. You passed: `foo`')
287
288        expect(fn).to.throw()
289        .with.property('docsUrl')
290        .and.include('https://on.cypress.io/screenshot-api')
291      })
292
293      it('throws if onAfterScreenshot is not a function', () => {
294        const fn = () => {
295          Screenshot.defaults({ onAfterScreenshot: 'foo' })
296        }
297
298        expect(fn)
299        .to.throw()
300        .with.property('message')
301        .and.include('`Cypress.Screenshot.defaults()` `onAfterScreenshot` option must be a function. You passed: `foo`')
302
303        expect(fn).to.throw()
304        .with.property('docsUrl')
305        .and.include('https://on.cypress.io/screenshot-api')
306      })
307    })
308  })
309})
310
Full Screen

screenshot.js

Source: screenshot.js Github

copy
1const _ = require('lodash')
2
3const $utils = require('./utils')
4const $errUtils = require('./error_utils')
5
6const reset = () => {
7  return {
8    capture: 'fullPage',
9    scale: false,
10    disableTimersAndAnimations: true,
11    screenshotOnRunFailure: true,
12    blackout: [],
13    onBeforeScreenshot () {},
14    onAfterScreenshot () {},
15  }
16}
17
18let defaults = reset()
19
20const validCaptures = ['fullPage', 'viewport', 'runner']
21
22const normalizePadding = (padding) => {
23  let top
24  let right
25  let bottom
26  let left
27
28  if (!padding) {
29    padding = 0
30  }
31
32  if (_.isArray(padding)) {
33    // CSS shorthand
34    // See: https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties#Tricky_edge_cases
35    switch (padding.length) {
36      case 1:
37        top = right = bottom = left = padding[0]
38        break
39      case 2:
40        top = (bottom = padding[0])
41        right = (left = padding[1])
42        break
43      case 3:
44        top = padding[0]
45        right = (left = padding[1])
46        bottom = padding[2]
47        break
48      case 4:
49        top = padding[0]
50        right = padding[1]
51        bottom = padding[2]
52        left = padding[3]
53        break
54      default:
55        break
56    }
57  } else {
58    top = right = bottom = left = padding
59  }
60
61  return [
62    top,
63    right,
64    bottom,
65    left,
66  ]
67}
68
69const validateAndSetBoolean = (props, values, cmd, log, option) => {
70  const value = props[option]
71
72  if (value == null) {
73    return
74  }
75
76  if (!_.isBoolean(value)) {
77    $errUtils.throwErrByPath('screenshot.invalid_boolean', {
78      log,
79      args: {
80        cmd,
81        option,
82        arg: $utils.stringify(value),
83      },
84    })
85  }
86
87  values[option] = value
88}
89
90const validateAndSetCallback = (props, values, cmd, log, option) => {
91  const value = props[option]
92
93  if (value == null) {
94    return
95  }
96
97  if (!_.isFunction(value)) {
98    $errUtils.throwErrByPath('screenshot.invalid_callback', {
99      log,
100      args: {
101        cmd,
102        callback: option,
103        arg: $utils.stringify(value),
104      },
105    })
106  }
107
108  values[option] = value
109}
110
111const validate = (props, cmd, log) => {
112  const values = {}
113
114  if (!_.isPlainObject(props)) {
115    $errUtils.throwErrByPath('screenshot.invalid_arg', {
116      log,
117      args: { cmd, arg: $utils.stringify(props) },
118    })
119  }
120
121  const { capture, blackout, clip, padding } = props
122
123  if (capture) {
124    if (!validCaptures.includes(capture)) {
125      $errUtils.throwErrByPath('screenshot.invalid_capture', {
126        log,
127        args: { cmd, arg: $utils.stringify(capture) },
128      })
129    }
130
131    values.capture = capture
132  }
133
134  validateAndSetBoolean(props, values, cmd, log, 'scale')
135  validateAndSetBoolean(props, values, cmd, log, 'disableTimersAndAnimations')
136  validateAndSetBoolean(props, values, cmd, log, 'screenshotOnRunFailure')
137
138  if (blackout) {
139    const existsNonString = _.some(blackout, (selector) => {
140      return !_.isString(selector)
141    })
142
143    if (!_.isArray(blackout) || existsNonString) {
144      $errUtils.throwErrByPath('screenshot.invalid_blackout', {
145        log,
146        args: { cmd, arg: $utils.stringify(blackout) },
147      })
148    }
149
150    values.blackout = blackout
151  }
152
153  if (clip) {
154    const existsNonNumber = _.some(clip, (value) => {
155      return !_.isNumber(value)
156    })
157
158    if (
159      !_.isPlainObject(clip) || existsNonNumber ||
160      (_.sortBy(_.keys(clip)).join(',') !== 'height,width,x,y')
161    ) {
162      $errUtils.throwErrByPath('screenshot.invalid_clip', {
163        log,
164        args: { cmd, arg: $utils.stringify(clip) },
165      })
166    }
167
168    values.clip = clip
169  }
170
171  if (padding) {
172    const isShorthandPadding = (value) => {
173      return _.isArray(value) &&
174        (value.length >= 1) &&
175        (value.length <= 4) &&
176        _.every(value, _.isFinite)
177    }
178
179    if (!(_.isFinite(padding) || isShorthandPadding(padding))) {
180      $errUtils.throwErrByPath('screenshot.invalid_padding', {
181        log,
182        args: { cmd, arg: $utils.stringify(padding) },
183      })
184    }
185
186    values.padding = normalizePadding(padding)
187  }
188
189  validateAndSetCallback(props, values, cmd, log, 'onBeforeScreenshot')
190  validateAndSetCallback(props, values, cmd, log, 'onAfterScreenshot')
191
192  return values
193}
194
195module.exports = {
196  reset () {
197    defaults = reset()
198  },
199
200  getConfig () {
201    return _.cloneDeep(_.omit(defaults, 'onBeforeScreenshot', 'onAfterScreenshot'))
202  },
203
204  onBeforeScreenshot ($el) {
205    return defaults.onBeforeScreenshot($el)
206  },
207
208  onAfterScreenshot ($el, results) {
209    return defaults.onAfterScreenshot($el, results)
210  },
211
212  defaults (props) {
213    const values = validate(props, 'Cypress.Screenshot.defaults')
214
215    return _.extend(defaults, values)
216  },
217
218  validate,
219}
220
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Cypress on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)