Summer Sale! All accounts are 50% off this week.

CrasyHorse's avatar

Using Cypress for component tests

Hi everyone,

I'm working on a project using Laravel 7.24, VueJs 2.6.12 and Vuetify 2.3. E2e testing is done with Cypress. Now I have to write some component tests for a custom VueJs component. In the past I've used vue-test-utils but now I want to use Cypress with @cypress/vue plugin. The problem is that I have to provide a complete webpack configuration to make @cypress/vue plugin work but because I'm using Laravel-Mix I can see only my custom part of the webpack config from webpack.mix.js. Is there a way to make laravel-mix dump its complete webpack config or has anybody ever done something like this?

Thanks in advance

0 likes
6 replies
jimclimb's avatar

I also have this problem, did you find a solution?

CrasyHorse's avatar

Hi Jimclimb,

sorry for answering late. Yes, I've found a solution for this problem. In short words, use your webpack.mix.js together with @cypress/webpack-preprocessor. Next week I'll be back in my office again and then I can give you a more complete and useful answer. Maybe I can send you a sample configuration.

LexLloyd's avatar

@CrasyHorse Hi! Can we get an update? I'm having the same issue and you seem to be the only one with solution.

CrasyHorse's avatar

@LexLloyd Hi! Sorry for this late answer but I had a lot of work to do in the last few days. I will try to give you an overview about how I've solved using Cypress for component testing with Laravel Mix.

My Setup

  • Laravel Framework ^8.70
  • VueJs 2.6.12
  • Cypress 9.3.1
  • @cypress/vue ^2.2.4
  • @cypress/webpack-dev-server ^1.8.1
  • @cypress/webpack-preprocessor ^5.11.1
  • laravel-mix ^5.0.6
  • Webpack 4.46.0
  • pug ^3.0.2
  • pug-plain-loader ^1.1.0

For the next steps I assume that you have a completely installed and configure (Laravel) project. I will concentrate on Cypress and component testing only.

Install Cypress

Cypress should be installed as project dependency

npm install --save-dev [email protected]

If you are behind a corporate firewall, you have to find an alternative (legal :-) )way to download Cypress an to bring it into your network.

Open a shell and set CYPRESS_INSTALL_BINARY

For Linux:

export CYPRESS_INSTALL_BINARY=/local/path/to/the/cypress/zip/file/cypress-9.3.1-linux-x64.zip
npm install --save-dev [email protected]

For Windows:

set CYPRESS_INSTALL_BINARY=X:\local\path\to\the\cypress\zip\file\cypress-9.3.1-windows-x64.zip
npm install --save-dev [email protected]

Install @cypress/webpack-dev-server and @cypress/preprocessor

npm install --save-dev @cypress/webpack-dev-serve@^1.8.1
npm install --save-dev @cypress/webpack-preprocessor@^5.11.1

Configure Cypress to use both packages

cypress/plugins/index.js

/// <reference types="cypress" />
const webpackPreprocessor = require('@cypress/webpack-preprocessor');
const { startDevServer } = require('@cypress/webpack-dev-server');
const webpackConfig = require('laravel-mix/setup/webpack.config.js');
...
    // start webpack-dev-server for component testing only
    if(config.testingType === 'component') {
        on('dev-server:start', options =>
            startDevServer({
                options,
                webpackConfig
            })
        );
    }

    on('task', require('./templating'));

    const options = {
        webpackOptions: require('laravel-mix/setup/webpack.config.js'),
        watchOptions  : {},
    };

    // use webpack-preprocessor for e2e testing only
    if(config.testingType === 'e2e') {
        on('file:preprocessor', webpackPreprocessor(options));
    }

Create cypress/plugins/templating.js (optional step)

cypress/plugins/templating.js

const pug = require('pug');

const layout = `
<v-app id='app' v-cloak><v-main><v-container fill-height fluid class='align-start'><v-row justify='center'>!{content}</v-row></v-container></v-main></v-app>`;

module.exports = {
    generateTemplate(templateString) {
        return pug.render(layout, { content: templateString });
    }
};

This is some kind of default (Vuetify) template that I use in nearly every component test. You could also write a template for each single test.

Now you should be ready to create your first component test.

This is an example of a test I use in one of my applications:

import { vuetify } from '../../../setup';
import { mount } from '@cypress/vue';
import BookingHistoryComponent from '@js/views/BookingHistoryComponent';
import { Ziggy } from '@js/Ziggy';
import route from 'ziggy-js';
import '@ts/config/veevalidate/config';
import{ VDataTable } from 'vuetify/lib';

const stylesheets = '../../../../../css/app.css';

const component = {
    components: {
        'booking-history': BookingHistoryComponent
    }
};

describe('@js/views/BookingHistoryComponent', function() {
    beforeEach(() => {
        cy.window().then((win) => {
            win.sessionStorage.clear();
        });
    });
    
    afterEach(() => {
        cy.window().then((win) => {
            win.sessionStorage.clear();
        });
    });
    
    context('renders without data', function(){
        beforeEach(()=>{
            cy.server();
            cy.route({
                method  : 'GET',
                url     : route('history.index', undefined, false, Ziggy),
                delay   : 2000,
                response: 'fixture:empty.json'
            }).as('GETHistoryEmpty');
            cy.task('generateTemplate', `
                <booking-history></booking-history>
            `)
                .then((template) => {
                    Object.assign(component, { template: template });
                    mount(component, {
                        stylesheets: stylesheets,
                        vuetify,
                    });
                });
        });
    });
});

I know that cy.server and cy.route are deprecated since Cypress 7.x but this test is rather old and I didn't had the time to refactor it.

Hope this helps.

1 like
Co00olCat's avatar

Install preprocessor

npm install --save-dev @cypress/webpack-preprocessor --legacy-peer-deps

In cypress/plugins/index.js add

const webpackPreprocessor = require('@cypress/webpack-preprocessor');

module.exports = (on, config) => {   

...

    // For Component testing
   const options = {
        webpackOptions: require('laravel-mix/setup/webpack.config.js'),
        watchOptions  : {},
    };

    if(config.testingType === 'component') {
        on('file:preprocessor', webpackPreprocessor(options));
    }

...

};

In cypress.config.js add

...

module.exports = defineConfig({  

...

    component: {
        devServer: {
            framework: "vue",
            bundler: "webpack",
            webpackConfig: require('laravel-mix/setup/webpack.config.js')
        },
    },

...

});

Note: When running tests in batch - make sure --component is present!

1 like

Please or to participate in this conversation.