---
title: >-
  Best practices for Running End-to-End Tests with Playwright | Shopware
  Community Hub
description: Learn how to write and run end-to-end tests in Shopware using Playwright.
canonical_url: 'https://hub.shopware.com/learn/unit/playwright-end-to-end-tests'
---

# Best practices for Running End-to-End Tests with Playwright

<LearningObjectives>

- Understand the role of **Playwright** in Shopware as the new E2E testing framework since Shopware 6.7.
- Learn how to write and run Playwright E2E tests.
- Learn how to run an E2E test locally and in a CI environment.

</LearningObjectives>

# Best practices for Running End-to-End Tests with Playwright

Starting with **Shopware 6.7**, **Playwright** replaces Cypress as the default **end-to-end testing framework**. It provides faster execution, better cross-browser support, new features and improvements, and a more robust developer experience.

You can also use other testing frameworks, but since the [acceptance test suite](https://github.com/shopware/acceptance-test-suite) created by Shopware already covers a lot of the functionality, it is highly recommended to use it.

In this learning unit, you will learn how to write an end-to-end test in Shopware with Playwright.

## Real-World Example

Fortunately, we already have an example for our test. In our [AcademyStorefrontController](https://github.com/ShopwareAcademy/AcademyStorefrontController) plugin, we have a custom controller that opens a modal window when clicking on a link. We want to make sure that the link with the class `open-image-modal` exists.

## Getting Started

<Callout title="Missing documentation" type="warning">

This is a very new feature and not fully released yet in the official documentation.

</Callout>

As always, you can start from [scratch](https://github.com/shopware/acceptance-test-suite) or check out the Academy [repository](https://github.com/ShopwareAcademy/AcademyStorefrontController).

Clone it in the `custom/plugins` directory of your local Shopware installation. If you have done the [backend development essentials course](/learn/course/basic-plugin-development), you should already have a running Shopware installation and the plugin installed.

```shell
git clone git@github.com:ShopwareAcademy/AcademyStorefrontController.git
```

## Folder Structure

The new Playwright folder structure is **simpler** and **less nested** than the old Cypress structure. You can find the tests in the `tests/acceptance` folder.

```txt
Pluginroot
└── tests
    └── acceptance
        ├── tests
        │   ├── product-buy-widget.spec.ts
        │   └── BaseTestFile.ts
        .env
        .env.dist
        .gitignore
        package.json
        package-lock.json
        playwright.config.ts
```

### Key Files

#### The **`.env.dist`** File

Contains your default environment variables. You can copy it to .env and adjust it to your needs.

```dotenv
APP_URL=http://localhost:8000

# Authentication via integration
SHOPWARE_ACCESS_KEY_ID=SWIAA29PA0W0UWZVDDE2EWHZDG
SHOPWARE_SECRET_ACCESS_KEY=N0JzcmtYUTNiUkxPSGtuSm5qVU9rTWpBUHVSWFpIRURCV0F4U0E

# Autentication via admin user
SHOPWARE_ADMIN_USERNAME=shopware
SHOPWARE_ADMIN_PASSWORD=shopware
```

#### The **`playwright.config.ts`** File

This file holds the configuration for your tests. You can adjust the browser, the base URL, and the test files. Check out the official [Playwright documentation](https://playwright.dev/docs/test-configuration) for more information.

```javascript
import { defineConfig, devices } from '@playwright/test';
// @ts-ignore
import dotenv from 'dotenv';

dotenv.config();

process.env['SHOPWARE_ADMIN_USERNAME'] = process.env['SHOPWARE_ADMIN_USERNAME'] || 'admin';
process.env['SHOPWARE_ADMIN_PASSWORD'] = process.env['SHOPWARE_ADMIN_PASSWORD'] || 'shopware';
process.env['MAILPIT_BASE_URL'] = process.env['MAILPIT_BASE_URL'] || 'http://localhost:8025';
process.env['APP_URL'] = process.env['APP_URL'] ?? 'http://localhost:8000';

// make sure APP_URL ends with a slash
process.env['APP_URL'] = process.env['APP_URL'].replace(/\/+$/, '') + '/';
if (process.env['ADMIN_URL']) {
    process.env['ADMIN_URL'] = process.env['ADMIN_URL'].replace(/\/+$/, '') + '/';
} else {
    process.env['ADMIN_URL'] = process.env['APP_URL'] + 'admin/';
}



/**
 * See https://playwright.dev/docs/test-configuration.
 */
export default defineConfig({

    testDir: './tests',
    /* Run tests in files in parallel */
    fullyParallel: true,
    forbidOnly: !!process.env.CI,
    retries: process.env.CI ? 2 : 0,
    workers: process.env.CI ? 1 : undefined,
    reporter: 'html',
    use: {
        screenshot: 'only-on-failure',
        baseURL: process.env.APP_URL,
        trace: 'on-first-retry',
    },

    projects: [
        {
            name: 'chromium',
            use: { ...devices['Desktop Chrome'] },
        },

        {
            name: 'firefox',
            use: { ...devices['Desktop Firefox'] },
        },

    ],


});
```

#### The **`BaseTestFile.ts`** File

This file holds the base test class. You can add your custom functions here.

```typescript
import { test as base } from '@shopware-ag/acceptance-test-suite';
import type { FixtureTypes } from '@shopware-ag/acceptance-test-suite';

export * from '@shopware-ag/acceptance-test-suite';

export const test = base.extend<FixtureTypes>({

});
```

We are importing that file in our test files.

#### The **`product-buy-widget.spec.ts`** File

```typescript
import {expect, test} from './BaseTestFile';

function wait(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
}

test('Plugin test scenario.', async ({page, TestDataService, DefaultSalesChannel}) => {

    // Create a basic product
    const basicProduct = await TestDataService.createBasicProduct();

    // Open the product detail page
    await page.goto(`${DefaultSalesChannel.url}/detail/${basicProduct.id}`);

    // Wait for the page to load and check for a link with the class "open-image-modal"
    const openImageModalLink = page.locator('a.open-image-modals');

    await expect(openImageModalLink).toHaveCount(1);
});
```

The rest of the files can stay as they are. When running tests, there will be three more folders created:

- `playwright-report` for the test report.
- `test-results` for the test results.
- `node_modules` for the dependencies.

## Run Test Locally

Before running the test, ensure that your plugin is **installed and activated** your running shopware instance. You can skip this step if you already have the plugin installed.

```bash
bin/console plugin:install AcademyStorefrontController --activate
bin/console cache:clear
bin/console theme:compile
```

Next, navigate to the test folder from your shop's root directory and install the dependencies.

```bash
cd custom/plugins/AcademyStorefrontController/tests/acceptance
npm install
npx playwright install
npx playwright install-deps
```

And run the Playwright UI where you can select the tests you want to run.

```bash
npx playwright test --ui
```

![Playwright UI](assets/playwrightUi.jpg)

Or execute tests directly in the terminal:

```bash
npx playwright test
```

![Playwright CLI run](assets/playwrightCli.jpg)

<Callout title="Why here?" type="info">

The tests are located in the `tests/acceptance` folder. This folder contains the **`package.json`** file for dependencies and the **`playwright.config.ts`** file for configuration. Therefore, you need to run all Playwright commands from inside the **`tests/acceptance`** folder.

</Callout>

## Run Test in CI

You can also run the test in a **CI environment**, such as **GitHub Actions**. You can check out the full example in the GitHub [workflow](https://github.com/ShopwareAcademy/AcademyCustomCss/blob/main/.github/workflows/e2e.yml). This setup allows you to:

- Run tests automatically on **pull requests**.
- Test against the **Shopware trunk version** nightly (e.g., 3 am builds), so on **schedule**.

The Following parameters required for that are:

- The `extensionName`: It is the name of your plugin – it is recommended to name the Repository the same as the plugin.
- The `e2ePath`: It is the path to your E2E tests / root of your test folder (e.g., `[your_shop]/custom/plugins/AcademyStorefrontController/tests/acceptance`).
- The `shopwareVersion`: It is the version of Shopware you want to test on.
- The `e2eTestFramework`: In this case `playwright`.

![Playwright test in GitHub](assets/e2eAction.jpg)

<Callout title="Important" type="info">

GitHub Actions will only recognize and run your workflow if the **workflow file** (e.g., `e2e.yml`) is placed in the `.github/workflows` folder of your plugin repository. Make sure the file is committed and pushed to the repository so the workflow is automatically triggered.

</Callout>

## Summary

In this learning unit, you have learned how to:

- Use **Playwright** as the new E2E testing framework since Shopware 6.7.
- Write and structure Playwright-based tests for your Shopware plugins.
- Run tests locally via **UI** or **CLI**.
- Automate your tests in a **CI environment** (e.g., GitHub Actions).

With this knowledge, you can now confidently set up automated Playwright tests to verify that Shopware plugins function correctly across different environments.

Well done on completing the **Frontend Development Essentials** learning path! You now have the foundation to design, extend, and maintain custom Storefront experiences in Shopware.
