DEV Community

Vien Nguyen
Vien Nguyen

Posted on • Edited on

Jest unit tests in Shopware Plugin's administration

Table of Contents


What is Shopware?

Shopware 6 is an open commerce platform based on Symfony Framework and Vue and is supported by a worldwide community and more than 1.500 community extensions.

Folder structure

The test folder structure should match the source folder structure. You add a test for a file in the same path as the source path.

└── <pluginRoot>/src/Resources/app/administration
    ├── src
    │   └── module
    │       └── custom-cms
    │          └── component
    │              └── custom-cms-sidebar
    │                  ├── index.js
    │                  └── custom-cms-sidebar.html.twig
    ├── test
    │   ├── _mocks_
    │   │   └── entity-schema.json
    │   │ 
    │   └── module
    │       └── custom-cms
    │           └── component
    │               └── custom-cms-sidebar.spec.js
    │
    ├── babel.config.json
    ├── jest.config.js
    └── package.json
Enter fullscreen mode Exit fullscreen mode

Installation

Let’s grab all the dependencies we will need for the setup in package.json

{
    // ...
    "devDependencies": {
        "@babel/plugin-proposal-class-properties": "^7.16.7",
        "@babel/plugin-transform-runtime": "7.13.15",
        "@babel/preset-env": "7.13.15",
        "@shopware-ag/jest-preset-sw6-admin": "^2.0.1",
        "@vue/test-utils": "1.1.0",
        "jest": "26.4.2"
    }
}
Enter fullscreen mode Exit fullscreen mode

@shopware-ag/jest-preset-sw6-admin

Default Jest preset for Shopware 6 administration development.

@vue/test-utils

We are using the Vue Test Utils for easier testing of Vue components. It provides some methods to mount and interact with Vue components in an isolated manner.

Setup

After installing the required dependency packages, please create a file called babel.config.json right next to your own package.json with the following content:

{
    "presets": ["@babel/preset-env"],
    "plugins": [
        "@babel/plugin-transform-runtime",
        "@babel/plugin-proposal-class-properties"
    ]
}
Enter fullscreen mode Exit fullscreen mode

Next up, create a file jest.config.js which should contain the following content:

const { resolve, join } = require('path');

const ADMIN_PATH = resolve('../../../../vendor/shopware/administration/Resources/app/administration');
process.env.ADMIN_PATH = process.env.ADMIN_PATH || ADMIN_PATH;

module.exports = {
    preset: '@shopware-ag/jest-preset-sw6-admin',

    globals: {
        adminPath: process.env.ADMIN_PATH,
    },

    collectCoverageFrom: [
        'src/**/*.js',
    ],

    moduleNameMapper: {
        '^plugin-admin(.*)$': '<rootDir>$1',
        '\@vue/test-utils': '<rootDir>/node_modules/@vue/test-utils',
        '../../_mocks_/entity-schema.json': '<rootDir>/test/_mocks_/entity-schema.json',
    },

    setupFilesAfterEnv: [
        resolve(join(process.env.ADMIN_PATH, 'test/_setup/prepare_environment.js')),
    ],
};
Enter fullscreen mode Exit fullscreen mode

The file entity-schema.json could be generated by running this command:

bin/console framework:schema -s 'entity-schema' custom/plugins/<your_plugin>/src/Resources/app/administration/test/_mocks_/entity-schema.json
Enter fullscreen mode Exit fullscreen mode

Writing Test

We are using a global object as an interface for the whole administration. Every component gets registered to this object, e.g. Shopware.Component.register(). Therefore, we have access to Component with the Shopware.Component.build() method. This creates a native Vue component with a working template. Every override and extension from another component are resolved in the built component.

Your component might look like this:

// src/module/custom-cms/component/custom-cms-sidebar/index.js
Component.extend('custom-cms-sidebar', 'sw-cms-sidebar', {
    // The vue component
});
Enter fullscreen mode Exit fullscreen mode

Create test file custom-cms-sidebar.spec.js for custom-cms-sidebar component.

When you want to mount your component it needs to be imported first:

import 'plugin-admin/src/module/custom-cms/component/custom-cms-sidebar';
Enter fullscreen mode Exit fullscreen mode

Then import it's related components:

import 'src/module/sw-cms/mixin/sw-cms-state.mixin';
import 'src/module/sw-cms/component/sw-cms-sidebar';
import 'src/app/component/base/sw-button';
Enter fullscreen mode Exit fullscreen mode

In the next step we can mount our Vue component which we get from the global Shopware object:

shallowMount(Shopware.Component.build('custom-cms-sidebar'));
Enter fullscreen mode Exit fullscreen mode

Now you can test the component like any other component. Let's try to write our first test:

import { shallowMount } from '@vue/test-utils';
import 'src/module/sw-cms/mixin/sw-cms-state.mixin';
import 'src/module/sw-cms/component/sw-cms-sidebar';
import 'src/app/component/base/sw-button';

import 'plugin-admin/src/module/custom-cms/component/custom-cms-sidebar';

function createWrapper() {
    return shallowMount(Shopware.Component.build('custom-cms-sidebar'), {
        propsData: {
            page: {
                sections: []
            }
        },
        stubs: {
            'sw-button': Shopware.Component.build('sw-button'),
            'sw-sidebar': true,
            'sw-sidebar-item': true,
            'sw-sidebar-collapse': true,
            'sw-text-field': true,
            'sw-select-field': true,
            'sw-cms-block-config': true,
            'sw-cms-block-layout-config': true,
            'sw-cms-section-config': true,
            'sw-context-button': true,
            'sw-context-menu-item': true,
            'sw-cms-sidebar-nav-element': true,
            'sw-entity-single-select': true,
            'sw-modal': true,
            'sw-checkbox-field': true
        },
        provide: {
            repositoryFactory: {
                create: () => ({
                    create: () => ({
                        id: null,
                        slots: []
                    }),
                    save: () => {}
                })
            },
            cmsService: {
                getCmsBlockRegistry: () => ({
                    'foo-bar': {}
                })
            }
        }
    });
}

describe('module/custom-cms/component/custom-cms-sidebar', () => {
    beforeAll(() => {
        Shopware.State.registerModule('cmsPageState', {
            namespaced: true,
            state: {
                isSystemDefaultLanguage: true
            }
        });
    });

    it('should be a Vue.js component', async () => {
        const wrapper = createWrapper();

        expect(wrapper.vm).toBeTruthy();
    });
});
Enter fullscreen mode Exit fullscreen mode

Running Test

Create a script in package.json

"scripts": {
    "jest": "jest --config=jest.config.js",
}
Enter fullscreen mode Exit fullscreen mode

Open a terminal and run this command:

npm run jest
Enter fullscreen mode Exit fullscreen mode

I hope this post helps you with the config testing environment for your plugin. I am really happy to receive your feedback on this article. Thanks for your precious time reading this.

Source: https://viennt.me/jest-unit-tests-in-shopware-plugins-administration

Top comments (0)