This week I started adding Cypress testing to my blog (with some surprises too!). I insisted to use typescript with Cypress and my code looks now like this:
describe('SEO', () => {
beforeEach(() => {
cy.visit('/').waitForRouteChange()
})
it('Contains title tag', () => {
cy.get('head title').should('contain', 'Laur IVAN|PRO')
})
})
This is fine and it works.
Thing is that I have the text 'Laur IVAN|PRO" defined in another file and the site is getting it from that file.
I tried to import the file via:
import website from '../../config/website'
To my surprise, I got an error:
ParseError: 'import' and 'export' may appear only with 'sourceType: module'
Following this link, I found out that Cypress is executed directly in hte browser. Hence the modern import
syntax is not supported.
Solution
My solution (following the SO question above) is as follows:
-
Add the dependent packages:
yarn add -D ts-loader @cypress/webpack-preprocessor
-
Update the
cypress/tsconfig.json
file:{ "compilerOptions": { "strict": true, "baseUrl": "../node_modules", "target": "es6", "lib": ["es6", "dom"], "types": ["cypress"], "allowJs": true }, "include": ["**/*.ts"] }
-
Create a
cypress/webpack.config.js
file with the following:const path = require('path') module.exports = { entry: './src/index.ts', module: { rules: [ { test: /\.tsx?$/, use: 'ts-loader', exclude: /node_modules/ } ] }, resolve: { extensions: ['.tsx', '.ts', '.js'] }, output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') } }
-
Add the following to the
/cypress/plugins/index.js
file:const webpack = require('@cypress/webpack-preprocessor') module.exports = on => { const options = { // send in the options from your webpack.config.js, so it works the same // as your app's code webpackOptions: require('../webpack.config'), watchOptions: {} } on('file:preprocessor', webpack(options)) }
This will make sure the typescript will be processed before execution :)
Now my typescript file looks like this:
import website from '../../config/website-components'
describe('SEO', () => {
beforeEach(() => {
cy.visit('/').waitForRouteChange()
})
it('Contains title tag', () => {
cy.get('head title').should('contain', website.title)
})
})
Downsides
As with any hack, there are downsides. The ones I found are:
- Increased processing time (yes, the files need to be compiled into JS)
- If you're not careful, you may end up with webpack errors which I personally am not fond of.
Nevertheless, the convenience of having variables trumps these issues for the time being (the alternative would be to move to pure javascript).
HTH,
Member discussion: