Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cli/types/cypress.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2992,6 +2992,7 @@ declare namespace Cypress {
disableTimersAndAnimations: boolean
padding: Padding
scale: boolean
overwrite: boolean
onBeforeScreenshot: ($el: JQuery) => void
onAfterScreenshot: ($el: JQuery, props: {
path: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ describe('src/cy/commands/screenshot', () => {
capture: 'viewport',
screenshotOnRunFailure: true,
disableTimersAndAnimations: true,
overwrite: false,
scale: true,
blackout: ['.foo'],
}
Expand Down Expand Up @@ -135,6 +136,7 @@ describe('src/cy/commands/screenshot', () => {
isOpen: true,
appOnly: false,
scale: true,
overwrite: false,
waitForCommandSynchronization: true,
disableTimersAndAnimations: true,
blackout: [],
Expand All @@ -146,6 +148,7 @@ describe('src/cy/commands/screenshot', () => {
isOpen: false,
appOnly: false,
scale: true,
overwrite: false,
waitForCommandSynchronization: true,
disableTimersAndAnimations: true,
blackout: [],
Expand Down Expand Up @@ -276,7 +279,7 @@ describe('src/cy/commands/screenshot', () => {
})
})

it('takes screenshot of hook title with test', () => {})
it('takes screenshot of hook title with test', () => { })
})

context('#screenshot', () => {
Expand Down Expand Up @@ -411,6 +414,7 @@ describe('src/cy/commands/screenshot', () => {
isOpen: true,
appOnly: true,
scale: true,
overwrite: false,
waitForCommandSynchronization: false,
disableTimersAndAnimations: true,
blackout: ['.foo'],
Expand All @@ -431,6 +435,7 @@ describe('src/cy/commands/screenshot', () => {
isOpen: false,
appOnly: true,
scale: true,
overwrite: false,
waitForCommandSynchronization: false,
disableTimersAndAnimations: true,
blackout: ['.foo'],
Expand All @@ -453,6 +458,7 @@ describe('src/cy/commands/screenshot', () => {
isOpen: true,
appOnly: false,
scale: true,
overwrite: false,
waitForCommandSynchronization: true,
disableTimersAndAnimations: true,
blackout: [],
Expand All @@ -474,6 +480,7 @@ describe('src/cy/commands/screenshot', () => {
isOpen: true,
appOnly: true,
scale: true,
overwrite: false,
waitForCommandSynchronization: false,
disableTimersAndAnimations: true,
blackout: ['.foo'],
Expand Down
5 changes: 4 additions & 1 deletion packages/driver/src/cy/commands/screenshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options = {}) => {
capture,
padding,
clip,
overwrite,
disableTimersAndAnimations,
onBeforeScreenshot,
onAfterScreenshot,
Expand Down Expand Up @@ -313,6 +314,7 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options = {}) => {
waitForCommandSynchronization: !isAppOnly(screenshotConfig),
disableTimersAndAnimations,
blackout: getBlackout(screenshotConfig),
overwrite,
}
}

Expand Down Expand Up @@ -353,6 +355,7 @@ const takeScreenshot = (Cypress, state, screenshotConfig, options = {}) => {
},
scaled: getShouldScale(screenshotConfig),
blackout: getBlackout(screenshotConfig),
overwrite,
startTime: startTime.toISOString(),
})

Expand Down Expand Up @@ -450,7 +453,7 @@ export default function (Commands, Cypress, cy, state, config) {

const isWin = $dom.isWindow(subject)

let screenshotConfig = _.pick(options, 'capture', 'scale', 'disableTimersAndAnimations', 'blackout', 'waitForCommandSynchronization', 'padding', 'clip', 'onBeforeScreenshot', 'onAfterScreenshot')
let screenshotConfig = _.pick(options, 'capture', 'scale', 'disableTimersAndAnimations', 'overwrite', 'blackout', 'waitForCommandSynchronization', 'padding', 'clip', 'onBeforeScreenshot', 'onAfterScreenshot')

screenshotConfig = $Screenshot.validate(screenshotConfig, 'screenshot', options._log)
screenshotConfig = _.extend($Screenshot.getConfig(), screenshotConfig)
Expand Down
6 changes: 3 additions & 3 deletions packages/driver/src/cypress/screenshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,9 @@ const validate = (props, cmd, log) => {
values.capture = capture
}

validateAndSetBoolean(props, values, cmd, log, 'scale')
validateAndSetBoolean(props, values, cmd, log, 'disableTimersAndAnimations')
validateAndSetBoolean(props, values, cmd, log, 'screenshotOnRunFailure')
['scale', 'disableTimersAndAnimations', 'screenshotOnRunFailure', 'overwrite'].forEach((key) => {
validateAndSetBoolean(props, values, cmd, log, key)
})

if (blackout) {
const existsNonString = _.some(blackout, (selector) => {
Expand Down
20 changes: 10 additions & 10 deletions packages/server/lib/screenshots.js
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,9 @@ const getDimensions = function (details) {
return pick(details.image.bitmap)
}

const ensureSafePath = function (withoutExt, extension, num = 0) {
const suffix = `${num ? ` (${num})` : ''}.${extension}`
const ensureSafePath = function (withoutExt, extension, overwrite, num = 0) {
const suffix = `${(num && !overwrite) ? ` (${num})` : ''}.${extension}`

const maxSafePrefixBytes = maxSafeBytes - suffix.length
const filenameBuf = Buffer.from(path.basename(withoutExt))

Expand All @@ -315,8 +316,8 @@ const ensureSafePath = function (withoutExt, extension, num = 0) {

return fs.pathExists(fullPath)
.then((found) => {
if (found) {
return ensureSafePath(withoutExt, extension, num + 1)
if (found && !overwrite) {
return ensureSafePath(withoutExt, extension, overwrite, num + 1)
}

// path does not exist, attempt to create it to check for an ENAMETOOLONG error
Expand All @@ -328,7 +329,7 @@ const ensureSafePath = function (withoutExt, extension, num = 0) {
if (err.code === 'ENAMETOOLONG' && maxSafePrefixBytes >= MIN_PREFIX_BYTES) {
maxSafeBytes -= 1

return ensureSafePath(withoutExt, extension, num)
return ensureSafePath(withoutExt, extension, overwrite, num)
}

throw err
Expand All @@ -342,7 +343,7 @@ const sanitizeToString = (title) => {
return sanitize(_.toString(title))
}

const getPath = function (data, ext, screenshotsFolder) {
const getPath = function (data, ext, screenshotsFolder, overwrite) {
let names
const specNames = (data.specName || '')
.split(pathSeparatorRe)
Expand Down Expand Up @@ -371,13 +372,13 @@ const getPath = function (data, ext, screenshotsFolder) {

const withoutExt = path.join(screenshotsFolder, ...specNames, ...names)

return ensureSafePath(withoutExt, ext)
return ensureSafePath(withoutExt, ext, overwrite)
}

const getPathToScreenshot = function (data, details, screenshotsFolder) {
const ext = mime.getExtension(getType(details))

return getPath(data, ext, screenshotsFolder)
return getPath(data, ext, screenshotsFolder, data.overwrite)
}

module.exports = {
Expand All @@ -392,9 +393,8 @@ module.exports = {
copy (src, dest) {
return fs
.copyAsync(src, dest, { overwrite: true })
.catch({ code: 'ENOENT' }, () => {})
.catch({ code: 'ENOENT' }, () => { })
},
// dont yell about ENOENT errors

get (screenshotsFolder) {
// find all files in all nested dirs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,13 +302,44 @@ describe('taking screenshots', () => {
})
})

// @see https://github.com/cypress-io/cypress/issues/7955
it('can pass overwrite option to replace existing filename', () => {
cy.viewport(600, 200)
cy.visit('http://localhost:3322/color/yellow')
cy.screenshot('overwrite-test', {
overwrite: false,
clip: { x: 10, y: 10, width: 160, height: 80 },
})

cy.task('check:screenshot:size', {
name: `${path.basename(__filename)}/overwrite-test.png`,
width: 160,
height: 80,
devicePixelRatio,
})

cy.screenshot('overwrite-test', {
overwrite: true,
clip: { x: 10, y: 10, width: 100, height: 50 },
})

cy.readFile(`cypress/screenshots/${path.basename(__filename)}/overwrite-test (1).png`).should('not.exist')

cy.task('check:screenshot:size', {
name: `${path.basename(__filename)}/overwrite-test.png`,
width: 100,
height: 50,
devicePixelRatio,
})
})

context('before hooks', () => {
before(() => {
// failure 2
throw new Error('before hook failing')
})

it('empty test 1', () => {})
it('empty test 1', () => { })
})

context('each hooks', () => {
Expand All @@ -322,7 +353,7 @@ describe('taking screenshots', () => {
throw new Error('after each hook failed')
})

it('empty test 2', () => {})
it('empty test 2', () => { })
})

context(`really long test title ${Cypress._.repeat('a', 255)}`, () => {
Expand Down