Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ReferenceError: exports is not defined in ES module scope #26167

Closed
billy-reify opened this issue Mar 21, 2023 · 8 comments
Closed

ReferenceError: exports is not defined in ES module scope #26167

billy-reify opened this issue Mar 21, 2023 · 8 comments
Assignees

Comments

@billy-reify
Copy link

billy-reify commented Mar 21, 2023

Current behavior

Unable to start cypress with standard command line getting error at startup.
I have "type": "module", within my package.json file

ReferenceError: exports is not defined in ES module scope at file:///Users/williamowens/Documents/GitHub/sponsor-test-automation-cypress/cypress.config.ts:2:23 at ModuleJob.run (node:internal/modules/esm/module_job:175:25) at async Loader.import (node:internal/modules/esm/loader:178:24) at async importModuleDynamicallyWrapper (node:internal/vm/module:437:15) at async loadFile (/Users/williamowens/Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/packages/server/lib/plugins/child/run_require_async_child.js:106:14) at async EventEmitter.<anonymous> (/Users/williamowens/Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/packages/server/lib/plugins/child/run_require_async_child.js:116:32

Desired behavior

I would like for Cypress to start without the error

Test code to reproduce

This is my cypress.config.ts file

Screenshot 2023-03-21 at 11 21 14 AM

Cypress Version

v11.2.0

Node version

v18.15.0

Operating System

Ventura 13.2.1 (22D68)

Debug Logs

No response

Other

No response

@billy-reify
Copy link
Author

If I remove "type" : "module" and attempt to start cypress with npx cypress open --env configFile=testing
I get this error instead
Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/.../Documents/GitHub/sponsor-test-automation-cypress/node_modules/lighthouse/core/index.js from /Users/.../Documents/GitHub/sponsor-test-automation-cypress/node_modules/@cypress-audit/lighthouse/src/task.js not supported. Instead change the require of index.js in /Users/.../Documents/GitHub/sponsor-test-automation-cypress/node_modules/@cypress-audit/lighthouse/src/task.js to a dynamic import() which is available in all CommonJS modules. at require.extensions. [as .js] (/Users/.../Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/node_modules/ts-node/dist/index.js:851:20) at Object. (/Users/.../Documents/GitHub/sponsor-test-automation-cypress/node_modules/@cypress-audit/lighthouse/src/task.js:1:23) at require.extensions. [as .js] (/Users/.../Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/node_modules/ts-node/dist/index.js:851:20) at Object. (/Users/.../Documents/GitHub/sponsor-test-automation-cypress/node_modules/@cypress-audit/lighthouse/index.js:2:24) at require.extensions. [as .js] (/Users/.../Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/node_modules/ts-node/dist/index.js:851:20) at Object. (/Users/.../Documents/GitHub/sponsor-test-automation-cypress/cypress/plugins/index.js:23:38) at require.extensions. [as .js] (/Users/.../Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/node_modules/ts-node/dist/index.js:851:20) at setupNodeEvents (/Users/.../Documents/GitHub/sponsor-test-automation-cypress/cypress.config.ts:12:20) at /Users/.../Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/packages/server/lib/plugins/child/run_plugins.js:118:14 at tryCatcher (/Users/.../Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/node_modules/bluebird/js/release/util.js:16:23) at Promise.attempt.Promise.try (/Users/.../Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/node_modules/bluebird/js/release/method.js:39:29) at RunPlugins.load (/Users/.../Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/packages/server/lib/plugins/child/run_plugins.js:115:9) at RunPlugins.runSetupNodeEvents (/Users/.../Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/packages/server/lib/plugins/child/run_plugins.js:276:10) at EventEmitter. (/Users/.../Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/packages/server/lib/plugins/child/run_require_async_child.js:185:22) at EventEmitter.emit (node:events:512:28) at EventEmitter.emit (node:domain:489:12) at process. (/Users/.../Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/packages/server/lib/plugins/util.js:33:22) at process.emit (node:events:512:28) at process.emit (node:domain:489:12) at process.emit.sharedData.processEmitHook.installedValue [as emit] (/Users/.../Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/node_modules/@cspotcode/source-map-support/source-map-support.js:745:40)

@lmiller1990
Copy link
Contributor

lmiller1990 commented Mar 21, 2023

Can you please share a minimal reproduction? It's most likely relating to your tsconfig.json, I suspect.

Related:

You might need to change the tsconfig.json value compilerOptions.module. It defaults to CommonJS (module: "commonjs"), but you are using ES module syntax (all this module stuff is confusing...)

Alternatively, if you want to use CommonJS, you can remove type: module and change import to require and export default to module.exports. Basically, there are two module systems conflicting here (by not fault of your own, the tools have different defaults - TS defaults to CommonJS, but most people generally want to use ES module syntax and/or target ES modules).

@lmiller1990 lmiller1990 self-assigned this Mar 21, 2023
@billy-reify
Copy link
Author

billy-reify commented Mar 22, 2023

So here is my current situation:
My project is actually "working" now, except for graphql-requests once again, with the following setup
No "type" : "module" within the package.json
No tsconfig.json file at all
I'm using this configuration within my cypress.config.ts
Screenshot 2023-03-22 at 8 02 51 AM

All of the files within PO, Actions and Tests utilize imports versus require within them

This is my plugins/index.js file -

/// <reference types="cypress" />
/// <reference types="@shelex/cypress-allure-plugin" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
require("dotenv").config();

// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)

// promisified fs module
const allureWriter = require("@shelex/cypress-allure-plugin/writer");
const fs = require("fs-extra");
const path = require("path");
const tagify = require("cypress-tags");
const pg = require("pg");
//const { lighthouse, prepareAudit } = require("@cypress-audit/lighthouse");
//const { pa11y } = require("@cypress-audit/pa11y");
const { rmdir } = require("fs");

function getConfigurationByFile(file) {
  const pathToConfigFile = path.resolve("config", `${file}.json`);

  return fs.readJson(pathToConfigFile);
}

/**
 * @type {Cypress.PluginConfig}
 */
// eslint-disable-next-line no-unused-vars
module.exports = (on, config) => {
  // `on` is used to hook into various events Cypress emits
  // `config` is the resolved Cypress config
  on("file:preprocessor", tagify(config));

  /***************************************************
   * Prepare Audit (Lighthouse) - Frontend Performance
   ***************************************************/
  on("before:browser:launch", (browser = {}, launchOptions) => {
    //prepareAudit(launchOptions);
  });

  // on("task", {
  //   lighthouse: lighthouse(),
  //   pa11y: pa11y(console.log.bind(console)),
  // });

  /***************************************************
   * Connects to an env db and fetches query result
   ***************************************************/
  on("task", {
    DATABASE({ dbConfig, sql }) {
      const pool = new pg.Pool(dbConfig);
      try {
        // return pool.query(sql, values)
        return new Promise(function (resolve, reject) {
          pool.query(sql, (err, res) => {
            if (err) {
              console.log("Error quering DB: " + err);
              reject(err);
            } else {
              resolve(res.rows);
            }
            pool.end();
          });
        });
      } catch (e) {
        console.log("Failed to query DB: " + e);
      }
    },
  });

  on("task", {
    createFolder(folderName) {
      if (!fs.existsSync(folderName)) {
        return new Promise((resolve, reject) => {
          fs.mkdir(folderName, { recursive: true }, (err) => {
            if (err) {
              console.error(err);
              return reject(err);
            }
            resolve(null);
          });
        });
      } else {
        return new Promise((resolve, reject) => {
          console.log("Folder %s already available", folderName);
          resolve(null);
        });
      }
    },
  });

  on("task", {
    deleteFolder(folderName) {
      if (fs.existsSync(folderName)) {
        console.log("deleting folder %s", folderName);

        return new Promise((resolve, reject) => {
          rmdir(folderName, { maxRetries: 10, recursive: true }, (err) => {
            if (err) {
              console.error(err);
              return reject(err);
            }
            resolve(null);
          });
        });
      } else {
        return new Promise((resolve, reject) => {
          console.log("Folder %s already not available", folderName);
          resolve(null);
        });
      }
    },
  });

  on("task", {
    downloads: (downloadspath) => {
      if (fs.existsSync(downloadspath)) {
        return new Promise((resolve, reject) => {
          resolve(fs.readdirSync(downloadspath));
        });
      } else {
        return new Promise((resolve, reject) => {
          console.log("Folder %s  not available", downloadspath);
          resolve([]);
        });
      }
    },
  });

  on("task", {
    compareImages({ image1, image2, imageType }) {
      const Jimp = require("jimp");
      const PNG = require("pngjs").PNG;
      const JPEG = require("jpeg-js");
      const pixelmatch = require("pixelmatch");

      function adjust_image(path, imageType) {
        let type = "image/png";
        if (imageType == "JPG" || imageType.toLowerCase() == "jpeg") {
          type = "image/jpeg";
        }
        const buffer = fs.readFileSync(path);
        const imageData = Jimp.decoders[type](buffer);
        const baseImage = new Jimp(imageData);
        baseImage.resize(1920, 1198);
        baseImage.crop(0, 0, 1919, 1197);
        return baseImage;
      }

      try {
        if (!fs.existsSync(image1)) {
          return new Promise((resolve, reject) => {
            reject(new Error("Error: Invalid path " + String(image1)));
          });
        }

        if (!fs.existsSync(image2)) {
          return new Promise((resolve, reject) => {
            reject(new Error("Error: Invalid path " + String(image2)));
          });
        }
        const img1 = adjust_image(image1, imageType);
        const img2 = adjust_image(image2, imageType);

        const pixels = Jimp.diff(img1, img2, 0.2);
        return new Promise((resolve, reject) => {
          resolve(1 - pixels.percent);
        });
      } catch (error) {
        return new Promise((resolve, reject) => {
          reject(error);
        });
      }
    },
  });

  on("task", {
    extractCSV({ csvPath }) {
      try {
        if (!fs.existsSync(csvPath)) {
          return new Promise((resolve, reject) => {
            reject(new Error("Error: Invalid path"));
          });
        }
        const csv = require("csv-parser");
        const results = [];
        return new Promise((resolve, reject) => {
          fs.createReadStream(csvPath)
            .pipe(csv())
            .on("data", (data) => results.push(data))
            .on("end", () => {
              resolve(results);
            });
        });
      } catch (error) {
        return new Promise((resolve, reject) => {
          reject(error);
        });
      }
    },
  });

  /***********************************************************
   * accept a configFile value or use testing by default
   ***********************************************************/
  if (!process.env.CIRCLECI) {
    const file = config.env.configFile || "testing";
    return getConfigurationByFile(file);
  }
  allureWriter(on, config);
  return config;
};

Note that lighthouse, prepareAudit and pa11y are disabled. Enabling these will cause this error:

Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/williamowens/Documents/GitHub/sponsor-test-automation-cypress/node_modules/lighthouse/core/index.js from /Users/williamowens/Documents/GitHub/sponsor-test-automation-cypress/node_modules/@cypress-audit/lighthouse/src/task.js not supported.
Instead change the require of index.js in /Users/williamowens/Documents/GitHub/sponsor-test-automation-cypress/node_modules/@cypress-audit/lighthouse/src/task.js to a dynamic import() which is available in all CommonJS modules.
    at require.extensions. [as .js] (/Users/williamowens/Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/node_modules/ts-node/dist/index.js:851:20)
    at Object. (/Users/williamowens/Documents/GitHub/sponsor-test-automation-cypress/node_modules/@cypress-audit/lighthouse/src/task.js:1:23)
    at require.extensions. [as .js] (/Users/williamowens/Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/node_modules/ts-node/dist/index.js:851:20)
    at Object. (/Users/williamowens/Documents/GitHub/sponsor-test-automation-cypress/node_modules/@cypress-audit/lighthouse/index.js:2:24)
    at require.extensions. [as .js] (/Users/williamowens/Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/node_modules/ts-node/dist/index.js:851:20)
    at Object. (/Users/williamowens/Documents/GitHub/sponsor-test-automation-cypress/cypress/plugins/index.js:23:38)
    at require.extensions. [as .js] (/Users/williamowens/Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/node_modules/ts-node/dist/index.js:851:20)
    at setupNodeEvents (/Users/williamowens/Documents/GitHub/sponsor-test-automation-cypress/cypress.config.ts:12:20)
    at /Users/williamowens/Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/packages/server/lib/plugins/child/run_plugins.js:118:14
    at tryCatcher (/Users/williamowens/Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/node_modules/bluebird/js/release/util.js:16:23)
    at Promise.attempt.Promise.try (/Users/williamowens/Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/node_modules/bluebird/js/release/method.js:39:29)
    at RunPlugins.load (/Users/williamowens/Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/packages/server/lib/plugins/child/run_plugins.js:115:9)
    at RunPlugins.runSetupNodeEvents (/Users/williamowens/Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/packages/server/lib/plugins/child/run_plugins.js:276:10)
    at EventEmitter. (/Users/williamowens/Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/packages/server/lib/plugins/child/run_require_async_child.js:185:22)
    at EventEmitter.emit (node:events:512:28)
    at EventEmitter.emit (node:domain:489:12)
    at process. (/Users/williamowens/Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/packages/server/lib/plugins/util.js:33:22)
    at process.emit (node:events:512:28)
    at process.emit (node:domain:489:12)
    at process.emit.sharedData.processEmitHook.installedValue [as emit] (/Users/williamowens/Library/Caches/Cypress/11.2.0/Cypress.app/Contents/Resources/app/node_modules/@cspotcode/source-map-support/source-map-support.js:745:40)

Here is my package.json

{
  "name": "cypress_tutorial",
  "version": "1.0.0",
  "description": "cypress tutorial",
  "main": "index.js",
  "scripts": {
    "testing": "npx cypress open --env configFile=testing",
    "testing_smoke": "npx cypress run --env configFile=testing,grepTags=smoke",
    "staging": "npx cypress open --env configFile=staging",
    "cy:run": "npx cypress run --env allure=true,allureResultsPath=allure-results,configFile=testing",
    "allure:report": "allure generate allure_results --clean -o allure-report",
    "allure:clear": "if [ -e allure-results ]; then rm -rf allure_results; fi; mkdir allure_results; if [ -e cypress/screenshots ]; then rm -rf cypress/screenshots; fi; if [ -e cypress/videos ]; then rm -rf cypress/videos; fi",
    "pretest": "npm run allure:clear",
    "test": "npm run cy:run || npm run posttest",
    "posttest": "npm run allure:report",
    "cypress:run": "cypress run --spec 'tests/ui/Sponsor/Demo.js' --reporter mochawesome",
    "cypress:verify": "cypress verify"
  },
  "dependencies": {
    "@cypress-audit/lighthouse": "^1.3.1",
    "@cypress-audit/pa11y": "^1.3.1",
    "@cypress/grep": "^3.1.5",
    "@cypress/webpack-preprocessor": "^5.17.0",
    "@faker-js/faker": "^7.6.0",
    "@shelex/cypress-allure-plugin": "^2.26.5",
    "@types/fs-extra": "^9.0.13",
    "allure": "^0.0.0",
    "allure-commandline": "^2.17.2",
    "aws-sdk": "^2.1110.0",
    "csv-parser": "^3.0.0",
    "cypress-grep": "^2.14.0",
    "cypress-iframe": "^1.0.1",
    "cypress-postgresql": "^1.0.8",
    "cypress-real-events": "^1.7.6",
    "cypress-tags": "^0.3.0",
    "cypress-xpath": "^1.8.0",
    "dotenv": "^16.0.3",
    "fs-extra": "^10.0.1",
    "graphql": "^16.6.0",
    "graphql-request": "^5.2.1-next.1",  <--- Tried this after 5.2.0 was still throwing cannot find module errors
    "jimp": "^0.22.7",
    "loglevel": "^1.8.0",
    "moment": "^2.29.3",
    "node": "^19.8.1",
    "node-fetch": "^3.2.5",
    "node-xlsx": "^0.21.0",
    "npx": "^3.0.0",
    "path": "^0.12.7",
    "pg": "^8.7.3",
    "sqlstring": "^2.3.3",
    "transit-js": "^0.8.874",
    "typescript": "^4.6.3",
    "uuid": "^8.3.2",
    "write-excel-file": "^1.4.21",
    "yarn": "^1.22.18"
  },
  "devDependencies": {
    "cypress": "^11.2.0",
    "mocha": "^10.2.0",
    "mocha-allure-reporter": "^1.4.0",
    "mochawesome": "^7.1.3",
    "mochawesome-merge": "^4.2.1",
    "mochawesome-report-generator": "^6.2.0"
  }
}

@lmiller1990
Copy link
Contributor

lmiller1990 commented Mar 23, 2023

The whole module system is quite messy... sorry you are running into this.

Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/williamowens/Documents/GitHub/sponsor-test-automation-cypress/node_modules/lighthouse/core/index.js from /Users/williamowens/Documents/GitHub/sponsor-test-automation-cypress/node_modules/@cypress-audit/lighthouse/src/task.js not supported.

Not sure about this one - I'll help with graphql-requests issue first.

I found the problem. In cypress.config.js you do

on('file:preprocessor', preprocessor())

Which was the original fix.

But later on, it's overridden in cypress/plugins/index.js:

on("file:preprocessor", tagify(config));

Seems combining preprocessors is not supported right now... following this issue leads to this feature request. #5832

@lmiller1990
Copy link
Contributor

lmiller1990 commented Mar 23, 2023

In fact, your exact feature request is here: #5832 (comment)

I think there are some cypress-tagify alternatives, have a look around - I can't remember off the top of my head, but I think there's a non-preprocessor based alternative.

@billy-reify
Copy link
Author

Thanks for the help on this.. I didn't know you couldn't have multiple preprocessors..
As soon as I comment out "//on("file:preprocessor", tagify(config));" within the index.js
I get this error, which just started to appear when I was debugging the graphql-requests error
Screenshot 2023-03-23 at 8 17 24 AM

Can you please offer a "safe" alternative to cypress-tagify I don't want to install something else and make things worse

@billy-reify
Copy link
Author

I added a comment about the cypress-tags issue on this thread -> infosum/cypress-tags#217

@lmiller1990
Copy link
Contributor

Not sure about a direct alteranative to cypress-tags. Maybe something like https://github.com/bahmutov/cy-grep?

Happy to advise more, but since the original issue is resolved (via latest webpack preprocessor) I'll close it to indicate we don't need a patch in Cypress immediately to fix a bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants