Services 
The test suite provides several services that can be used to simplify your test code. These services are designed to be reusable and can be easily extended to fit your specific needs.
Test Data Service 
The TestDataService is a powerful utility designed to simplify test data creation, management, and cleanup when writing acceptance and API tests for Shopware. It provides ready-to-use functions for common data needs and ensures reliable, isolated test environments. For detailed documentation of the methods, you can have a look at the service class or use the auto-completion of your IDE.
When to use the TestDataService in tests 
You should use the TestDataService whenever you need test data that matches common Shopware structures, such as:
- Creating a basic product, customer, order, category, etc
 - Setting up media resources like product images or digital downloads
 - Creating promotions, rules, or payment/shipping methods
 - Fetching existing entities via helper methods (
getCurrency(),getShippingMethod(), etc) - Assigning relations between entities (e.g., linking a product to a category)
 
Typical examples 
const product = await TestDataService.createBasicProduct();
const customer = await TestDataService.createCustomer();
const shipping = await TestDataService.createBasicShippingMethod();When and why to extend the TestDataService 
You should add new functions to the TestDataService (or extend it) when:
- Your project or plugin introduces new entity types (e.g., 
CommercialCustomerGroup,CustomProductType) - You need a specialized creation logic (e.g., a shipping method with multiple rules, a pre-configured product bundle)
 - Existing methods require modifications that should not affect the core service
 - You want to reuse the same setup across multiple tests without duplicating logic
 - You require special cleanup handling for newly created entities
 
Using and extending the TestDataService properly ensures your acceptance tests stay readable, maintainable, and scalable even as your Shopware project grows.
Available create* methods in TestDataService 
These methods are designed to streamline the setup of test data, ensuring consistency and efficiency in your testing processes. They are much more available than listed below, but these are the most common ones. Use your IDE auto-completion to find all available methods.
createBasicProduct(): Promise<Product>createVariantProducts(parentProduct: Product, propertyGroups: PropertyGroup[]): Promise<Product[]>createCustomer(): Promise<Customer>createCustomerGroup(): Promise<CustomerGroup>createOrder(lineItems: SimpleLineItem[], customer: Customer): Promise<Order>createCategory(): Promise<Category>createColorPropertyGroup(): Promise<PropertyGroup>createBasicPaymentMethod(): Promise<PaymentMethod>createBasicShippingMethod(): Promise<ShippingMethod>- [...]
 
Available assign* methods in TestDataService 
These methods are designed to establish associations between entities, such as linking products to categories or assigning media to manufacturers, ensuring that your test data reflects realistic scenarios. They are much more available than listed below, but these are the most common ones. Use your IDE auto-completion to find all available methods.
assignProductCategory(productId: string, categoryIds: string[]): Promise<void>assignProductManufacturer(productId: string, manufacturerId: string): Promise<void>assignProductMedia(productId: string, mediaId: string): Promise<void>- [...]
 
Available get* methods in TestDataService 
They are much more available than listed below, but these are the most common ones. Use your IDE auto-completion to find all available methods.
getCountry(iso2: string): Promise<Country>getCurrency(isoCode: string): Promise<Currency>getCustomerGroups(): Promise<CustomerGroup[]>getPaymentMethod(name = 'Invoice'): Promise<PaymentMethod>- [...]
 
Writing new methods in TestDataService 
If you want to add new functionality to this service such as a new type of entity creation, you can follow this approach:
1. Define the purpose 
Decide whether you're creating, assigning, or retrieving data. Most methods fall into one of the following patterns:
create*: Creates a new entity (e.g., product, customer, category)assign*: Links existing entities (e.g., assign media to product)get*: Retrieves specific or filtered data from the system
2. Implement the method 
Use the AdminApiContext to interact with the Shopware Admin API. Here is a simplified example of adding a method to create a new shipping method
3. Follow naming conventions 
Be consistent in naming:
- Use 
createBasic*for standardized, default setups with predefined values (e.g.,createBasicProduct) - Use 
create*With*for variations (e.g.createProductWithImage) - Use 
assign*for methods that associate two entities (e.g.,assignProductMedia) - Use 
get*to retrieve specific entities or lists (e.g.getCurrency) 
4. Add a return type 
Always define a return type (typically a Promise<...>) to improve autocompletion and documentation support.
5. Add cleanup logic 
Make sure to clean up the entity via code after the test run by putting the entity in a record. See the example below:
async createBasicRule(): Promise<Rule> {
        [...]
                
 this.addCreatedRecord('rule', rule.id);
 [...]
 }Explore further info on this in Automatic Cleanup.
6. Test the method 
Once added, use your new method inside a test to verify it works as expected (/tests/TestDataService.spec.ts):
test('Verify new shipping method creation', async ({ TestDataService }) => {
    const shippingMethod = await TestDataService.createShippingMethod({
        name: 'Express Delivery'
 });
    expect(shippingMethod.name).toEqual('Express Delivery');
});Automatic cleanup of test data and system configurations 
The TestDataService includes a built-in mechanism to ensure that any test data & system configuration entries created during a test run are automatically deleted afterward. This ensures that the Shopware instance remains clean and consistent between tests, helping to maintain test isolation and prevent state leakage.
How cleanup works 
When you create an entity using a create* method (e.g., createBasicProduct, createCustomer), the service automatically registers that entity for deletion by calling the addCreatedRecord() method:
this.addCreatedRecord('product', product.id);These records are stored in a cleanup queue processed at the end of each test using the Playwright lifecycle.
Cleanup execution 
The cleanup() method handles the deletion of all registered entities and system config changes. All created records are grouped into two categories:
- Priority Deletions (
priorityDeleteOperations) – for entities with dependencies that must be deleted first (e.g., orders, customers) - Standard Deletions (
deleteOperations) – for all other entities 
This prioritization prevents errors when deleting interdependent data. Any modified system configurations are reset to their previous state after deleting priority records. The priority entities can be found in the TestDataService class. If you want to add a new entity to the priority deletion list, you can do so by adding it to the priorityDeleteOperations array.
Skipping cleanup 
In rare scenarios, such as performance testing or debugging, you may want to prevent cleanup for specific entities. You can simply skip the cleanup by calling TestDataService.setCleanUp(false) within your test.
Extending the TestDataService in external projects 
The TestDataService is designed to be easily extendable. This allows you to add project-specific data generation methods while still benefiting from the existing, standardized base functionality.
1. Create a new subclass 
You can create a new TypeScript class that extends the base TestDataService.
import { TestDataService } from '@shopware-ag/acceptance-test-suite';
export class CustomTestDataService extends TestDataService {
    constructor(AdminApiContext, DefaultSalesChannel) {
        super(...);
 }
    
    async createCustomCustomerGroup(data: Partial<CustomerGroup>) {
        const response = await this.adminApi.post('customer-group?_response=true', {
            data: {
 ...
 },
 });
        const { data: createdGroup } = await response.json();
        this.addCreatedRecord('customer-group', createdGroup.id);
        return createdGroup;
 }
}2. Provide the extended service as a fixture 
Following the Playwright fixture system described, you create a new fixture that initializes your extended service.
Example from AcceptanceTest.ts:
import { test as base } from '@shopware-ag/acceptance-test-suite';
import type { FixtureTypes } from './BaseTestFile';
import { CustomTestDataService } from './CustomTestDataService';
export interface CustomTestDataServiceType {
    TestDataService: CustomTestDataService;
}
export const test = base.extend<FixtureTypes & CustomTestDataServiceType>({
    TestDataService: async ({ AdminApiContext, DefaultSalesChannel }, use) => {
        const service = new CustomTestDataService(AdminApiContext, DefaultSalesChannel.salesChannel);
        await use(service);
        await service.cleanUp();
 },
});In this setup:
- The 
TestDataServicefixture is overridden with your customCustomTestDataService. - Now, all tests that use 
TestDataServicewill have access to both the original and your extended methods. - The automated cleanup is still in place, ensuring that any test data created during the test run is removed afterward.