RajKon
RajKon

Reputation: 470

Why do I get error `TypeError: fs.readdir is not a function` in Cypress

I wrote this code and it works fine that is written in TypeScript. When I use the same code in the test file in cypress I get error TypeError: fs.readdir is not a function

import * as fs from 'fs'

let inputPath: String = "C:\\Users\\rkon";
let replacementString = "/";
let newInputPath = inputPath.split('\\').join(replacementString)
console.log('path after replacement: ' + newInputPath);

fs.readdir(newInputPath as string, function (err: any, files: any[]) {
    //handling error
    if (err) {
        return console.log('Unable to scan directory: ' + err);
    }
    //listing all files using forEach
    files.forEach(function (file) {
        console.log('file: ' + file);
    });
});

I verified the above code by first doing:

>tsc temp.ts
>node temp.js

As I said it worked fine but why does the same code not work in Cypress giving the following error:

TypeError: fs.readdir is not a function

Upvotes: 11

Views: 17535

Answers (4)

Hamza Bouhelal
Hamza Bouhelal

Reputation: 69

You can also use the package cypress-fs (which I am the author of) which provides functionallities from the fs module directly in cypress like so:

cy.fsReadDir(path, options);

Steps to use it would be:

yarn install cypress-fs

Add import "cypress-fs"; to your cypress/support/e2e.ts file.

And add update your cypress.config.ts to look like so:

export default defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      return require("./node_modules/cypress-fs/plugins/index.js")(on, config);
    },
  },
});

Upvotes: 0

Roman Meyer
Roman Meyer

Reputation: 2872

Since Cypress v.10 plugin file is deprecated and no longer supported.

So now is it possible to use Node libraries by adding tasks into config:

const fs = require('fs')

module.exports = defineConfig({
  e2e: { // or components, if you are testing components
    setupNodeEvents(on, config) {
      on('task', {
        fileExists(path) { // there is a name and arguments for a task
          return fs.existsSync(path)
        },
      })
    }
  }
})

After definition you can use this task inside of the test:

it('test some stuff', () => {
  // run task with an argument
  cy.task('fileExists', { path: 'path/to/file' })
    .then(result => {
      // do what you need
    })
})

More info in the official docs.

Upvotes: 1

Josef Biehler
Josef Biehler

Reputation: 1041

you can not use node modules within cypress because cypress executes test code in the browser. To use node modules, you must use tasks (which are executed in the node process) that are defined in the plugins file (important, because the plugins file is executed in the node context).

So you have to tell cypress in the cypress.json that you are using a plugins file:

{
    ...
    "pluginsFile": "cypress/plugins/plugins.js",
    ...
  }

Then define a task in plugins.js:

on('task', {
    readdir({ path }) {
      return fs.readdir(path, .....);
    }
  });

Use the task like this:

cy.task("readdir", { path: "..." }, { timeout: 30000 });

Upvotes: 19

RajKon
RajKon

Reputation: 470

Surprisingly both the statements below work well in Windows machine to get the directory (Note that this solution is a workaround due to the fact that Cypress tests run in browser environment.)

        cy.exec('pwd').then((result) =>
            cy.log('pwd res:' + JSON.stringify(result))
        );

        cy.exec('cd').then( (result) =>
            cy.log('cd res:' + JSON.stringify(result))
        );

Upvotes: 0

Related Questions