Robin Reiche
Robin Reiche

Reputation: 75

Cypress: import modules via alias

in my project i am using cypress with plain javascript. i am facing the challenge of importing the modules (page objects) via aliases instead of spaghetti code like ../../../../folder/page.js. I don't use typescript or react.js and don't have a src folder/directory.

my tests run locally in the browser or via a docker image (pipeline).

I would like to transform from this:

import { LoginPage } from "../../pages/loginPage.js";

to something like this:

import { LoginPage } from "@Pages/loginPage.js";

but I always get an error:

Error: Webpack Compilation Error
./cypress/e2e/accountOverview/accountOverviewPageTest.spec.js
Module not found: Error: Can't resolve 'Pages/loginPage.js' in 'C:\Users\User\automated_frontend_tests\automated_frontend_tests\cypress\e2e\accountOverview'
resolve 'Pages/loginPage.js' in 'C:\Users\User\automated_frontend_tests\automated_frontend_tests\cypress\e2e\accountOverview'
  Parsed request is a module
  using description file: C:\Users\User\automated_frontend_tests\automated_frontend_tests\package.json (relative path: ./cypress/e2e/accountOverview)
    Field 'browser' doesn't contain a valid alias configuration
    Looked for and couldn't find the file at the following paths:
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\cypress\e2e\accountOverview\node_modules]
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\cypress\e2e\node_modules]
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\cypress\node_modules]
[C:\Users\node_modules]
[C:\node_modules]
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\node_modules\Pages\loginPage.js]
[C:\Users\User\automated_frontend_tests\node_modules\Pages\loginPage.js]
[C:\Users\User\node_modules\Pages\loginPage.js]
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\node_modules\Pages\loginPage.js.js]
[C:\Users\User\automated_frontend_tests\node_modules\Pages\loginPage.js.js]
[C:\Users\User\node_modules\Pages\loginPage.js.js]
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\node_modules\Pages\loginPage.js.json]
[C:\Users\User\automated_frontend_tests\node_modules\Pages\loginPage.js.json]
[C:\Users\User\node_modules\Pages\loginPage.js.json]
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\node_modules\Pages\loginPage.js.jsx]
[C:\Users\User\automated_frontend_tests\node_modules\Pages\loginPage.js.jsx]
[C:\Users\User\node_modules\Pages\loginPage.js.jsx]
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\node_modules\Pages\loginPage.js.mjs]
[C:\Users\User\automated_frontend_tests\node_modules\Pages\loginPage.js.mjs]
[C:\Users\User\node_modules\Pages\loginPage.js.mjs]
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\node_modules\Pages\loginPage.js.coffee]
[C:\Users\User\automated_frontend_tests\node_modules\Pages\loginPage.js.coffee]
[C:\Users\User\node_modules\Pages\loginPage.js.coffee]
 @ ./cypress/e2e/accountOverview/accountOverviewPageTest.spec.js 5:17-46

I have tried several solutions, including:

//webpack.config.js

module.exports = {
  resolve: {
    alias: {
      "@pages": path.resolve(__dirname, "cypress/pages/*"),
    },
  },
};



//testspec file
import { LoginPage } from "@pages/loginPage.js";
const loginPage = new LoginPage();

@Uzair Khan: I tried your solution, but it still didn't work. The error message remains the same. It seems that the IDE does not search in the correct folder, but only in ...\node_modules\@page\loginPage.js which makes no sense. If I enter const loginPage = new LoginPage(), the module LoginPage() cannot be found by the IDE either. Something is wrong with the solution. Do I still have to install any packages via NPM?

Upvotes: 1

Views: 6177

Answers (2)

TesterDick
TesterDick

Reputation: 10580

I think both answers are nearly there, this is what I have for src files:

const webpack = require('@cypress/webpack-preprocessor')
...
module.exports = defineConfig({
  ...
  e2e: {
    setupNodeEvents(on, config) {
      ...
      // @src alias
      const options = {
        webpackOptions: {             
          resolve: {                 
            alias: {                     
              '@src': path.resolve(__dirname, './src')              
            },             
          },         
        },     
        watchOptions: {},
      }
      on('file:preprocessor', webpack(options))
      ...

path.resolve() resolves a relative path into an absolute one, so you need to start the 2nd param with ./ or ../.

Also, don't use wildcard * in the path, you just need a single folder that will be substituted for the alias in the import statement.

If in doubt, check the folder returned (in the terminal)

module.exports = defineConfig({
  ...
  e2e: {
    setupNodeEvents(on, config) {
      const pagesFolder = path.resolve(__dirname, './cypress/pages')
      console.log('pagesFolder', pagesFolder)

Upvotes: 5

Uzair Khan
Uzair Khan

Reputation: 105

In your webpack.config.js file add resolve.alias which you want to make alias. It looks like something this below:

 resolve: {
  alias: {
    '@page': path.resolve(__dirname, '{path you want to make alias}')
  }
}

Since you are using cypress, you have to update the resolve path in cypress.config.js. Here is mine cypress.config.js

import { defineConfig } from 'cypress'
import webpack from '@cypress/webpack-preprocessor'
import preprocessor from '@badeball/cypress-cucumber-preprocessor'
import path from 'path'

export async function setupNodeEvents (on, config) {
  // This is required for the preprocessor to be able to generate JSON reports after each run, and more,
  await preprocessor.addCucumberPreprocessorPlugin(on, config)

  on(
    'file:preprocessor',
    webpack({
      webpackOptions: {
        resolve: {
          extensions: ['.ts', '.js', '.mjs'],
          alias: {
            '@page': path.resolve('cypress/support/pages/')
          }
        },
        module: {
          rules: [
            {
              test: /\.feature$/,
              use: [
                {
                  loader: '@badeball/cypress-cucumber-preprocessor/webpack',
                  options: config
                }
              ]
            }
          ]
        }
      }
    })
  )

  // Make sure to return the config object as it might have been modified by the plugin.
  return config
}

And import in other file via that alias you set in cypress.config.js. Here is mine for example:

import page from '@page/visit.js'

const visit = new page()

When('I visit duckduckgo.com', () => {
 visit.page()
})

Upvotes: 2

Related Questions