skip to Main Content

I am trying the code found in the cypress document which allows cypress user to modify screenshot path.

I tried the examples they have given but i am having an issue with the permission.

Error: EPERM: operation not permitted, rename ‘c:mydocuments/cypress/example/dist.cypress/app/screemshots/login.cy.ts — my first test (failed).png’ -> ‘c:/myscreenshots/screenshot.png

https://docs.cypress.io/api/plugins/after-screenshot-api#Usage

system: windows 10 and 11
ide: visual studio code
using NX workspace

// cypress.config.js

{ defineConfig } from 'cypress'
import fs from 'fs'

export default defineConfig({
  // setupNodeEvents can be defined in either
  // the e2e or component configuration
  e2e: {
    setupNodeEvents(on, config) {`your text`
      on('after:screenshot', (details) => {
        console.log(details) // print all details to terminal

        const newPath = '/new/path/to/screenshot.png'

        return new Promise((resolve, reject) => {
          // fs.rename moves the file to the existing directory 'new/path/to'
          // and renames the image to 'screenshot.png'
          fs.rename(details.path, newPath, (err) => {
            if (err) return reject(err)

            // because we renamed and moved the image, resolve with the new path
            // so it is accurate in the test results
            resolve({ path: newPath })
          })
        })
      })
    },
  },
})`

My code

const { defineConfig } = require('cypress')
const fs = require('fs')
const { Runnable } = require('mocha')

module.exports = defineConfig({
e2e: {
    setupNodeEvents(on, config) {
        on('after:screenshot', (details) => {
            console.log(details) // print all details to terminal
       const testNmae=Cypress.spec.name.replace(/.|/|s/g,'_')
       const timeStamp = newDate().toISOString().replace(/:/g,'_')
       const filename = '${testname}--${timeStamp} (failed).png'
       const newPath = 'cypress/myscreenshots/${filename}'
    if (!fs.existsSync(newPath)) {fs.mkdirSync(newPath, {recursive: true });}
    return new Promise((resolve, reject) => {
    fs.rename(details.path, newPath, (err) => {if (err) return reject(err)
resolve({ path: newPath })
          })
        })
      })
    },
  },
})

result:

  1. template spec
    passes:
    Error: EPERM: operation not permitted, rename ‘D:Cypressprojectsexamplecypressscreenshotsspec.cy.jstemplate spec — passes (failed).png’ -> ‘D:Cypressprojectsexamplecypressmyscreenshots’

2

Answers


  1. You can set the screenshots folder in configuration and save yourself a lot of hassle.

    In cypress.config.js

    const { defineConfig } = require('cypress')
    
    module.exports = defineConfig({
      e2e: {
        baseUrl: 'http://localhost:1234',
      },
      screenshotsFolder: 'cypressmyscreenshots',
    })
    

    That way you keep the spec/test sub-path and don’t get any nasty surprises when one screenshot over-rides the other.

    Login or Signup to reply.
  2. The error message is due to your call to fs.mkdirSync which is not necessary.

    But with that code, you would not even get that far – the Cypress.spec.name call will give you a different error – so I’m a little confused about inconsistencies in the question.

    In any case

    • Cypress.spec.name can only be used in tests, not in plugin events.
    • the details parameter has a specName property, but it’s not passing anything. I assume that’s a bug in the Cypress code, since the property exists, it should have the spec name in it.
    • to get around that, add a task to send the spec name into the plugin from the test. After Cypress remedies the issue, you can revert.

    Here is the code entire:

    const { defineConfig } = require("cypress");
    const fs = require('fs')
    
    let specName;   // temporary until bug fix
    
    module.exports = defineConfig({
      e2e: {
        setupNodeEvents(on, config) {
          on('task', {
            sendSpecNameToPlugin: (name) => specName = name 
          })
          on('after:screenshot', (details) => {
            const testname = (details.specName || specName)  // temporary until bug fix
              .replace(/.|/|s/g,'_')
            const timeStamp = new Date().toISOString().replace(/:/g,'_')
            const filename = `${testname}--${timeStamp} (failed).png`
            const newPath = `cypress/myscreenshots/${filename}`
    
            return new Promise((resolve, reject) => {
              fs.rename(details.path, newPath, (err) => {
                if (err) return reject(err)
                resolve({ path: newPath })
              })
            })
          })
        },
      },
    })
    

    The test:

    cy.task('sendSpecNameToPlugin', Cypress.spec.name)
    cy.screenshot()
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search