Skip to content

Commit 80c5ab2

Browse files
authored
Merge pull request #1 from shopwareLabs/ci/add-unit-tests
ci: add phpunit tests
2 parents ac7ce9e + 2daf04d commit 80c5ab2

File tree

5 files changed

+236
-5
lines changed

5 files changed

+236
-5
lines changed

.github/workflows/integration.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Integration Tests
2+
on:
3+
push:
4+
branches:
5+
- main
6+
pull_request:
7+
branches:
8+
- main
9+
10+
jobs:
11+
phpunit:
12+
runs-on: ubuntu-latest
13+
env:
14+
APP_URL: http://localhost:8000
15+
DATABASE_URL: mysql://root@localhost/shopware
16+
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v4
19+
20+
- name: Setup PHP
21+
uses: shivammathur/setup-php@v2
22+
with:
23+
php-version: '8.2'
24+
25+
- name: Install dependencies
26+
run: |
27+
composer install --no-interaction --prefer-dist --optimize-autoloader
28+
29+
- name: Start MySQL Server
30+
run: |
31+
sudo mv /var/lib/mysql /var/lib/mysql-old
32+
sudo mkdir /var/lib/mysql
33+
sudo mount -t tmpfs tmpfs /var/lib/mysql -o size=1G
34+
sudo -u mysql mysqld --datadir=/var/lib/mysql --default-time-zone=SYSTEM --initialize-insecure
35+
sudo systemctl start mysql
36+
37+
- name: Bootstrap Shopware
38+
run: php vendor/shopware/core/TestBootstrap.php
39+
40+
- name: Run PHPUnit tests
41+
run: vendor/bin/phpunit

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/vendor
22
/composer.lock
33
/var
4-
/config
54
/install.lock
65
/.phpunit.cache

README.md

Lines changed: 168 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,12 +384,179 @@ class CustomFieldFixture implements FixtureInterface
384384
}
385385
```
386386

387+
## Customer Fixtures
388+
389+
The FixtureBundle provides comprehensive customer management through fixtures using `CustomerFixtureLoader` and `CustomerFixtureDefinition` classes for creating test customers with addresses, custom fields, and relationships.
390+
391+
### Basic Customer Fixture
392+
393+
```php
394+
<?php
395+
396+
declare(strict_types=1);
397+
398+
namespace Acme\Fixture;
399+
400+
use Shopware\FixtureBundle\Attribute\Fixture;
401+
use Shopware\FixtureBundle\FixtureInterface;
402+
use Shopware\FixtureBundle\Helper\Customer\CustomerFixtureDefinition;
403+
use Shopware\FixtureBundle\Helper\Customer\CustomerFixtureLoader;
404+
405+
#[Fixture]
406+
class CustomerFixture implements FixtureInterface
407+
{
408+
public function __construct(
409+
private readonly CustomerFixtureLoader $customerFixtureLoader
410+
) {
411+
}
412+
413+
public function load(): void
414+
{
415+
$this->customerFixtureLoader->apply(
416+
(new CustomerFixtureDefinition('john.doe@example.com'))
417+
->firstName('John')
418+
->lastName('Doe')
419+
->salutation('mr')
420+
->password('password123')
421+
->company('ACME Corporation')
422+
->department('IT Department')
423+
);
424+
}
425+
}
426+
```
427+
428+
### Customer with Complete Information
429+
430+
```php
431+
#[Fixture(groups: ['customers', 'test-data'])]
432+
class DetailedCustomerFixture implements FixtureInterface
433+
{
434+
public function __construct(
435+
private readonly CustomerFixtureLoader $customerFixtureLoader
436+
) {
437+
}
438+
439+
public function load(): void
440+
{
441+
$this->customerFixtureLoader->apply(
442+
(new CustomerFixtureDefinition('jane.smith@example.com'))
443+
->firstName('Jane')
444+
->lastName('Smith')
445+
->salutation('mrs')
446+
->title('Dr.')
447+
->birthday('1990-05-15')
448+
->company('Tech Solutions Ltd')
449+
->department('Marketing')
450+
->vatId('DE123456789')
451+
->password('secure123')
452+
->customerNumber('CUST-001')
453+
->affiliateCode('PARTNER-123')
454+
->campaignCode('SUMMER2024')
455+
->active(true)
456+
->guest(false)
457+
->customFields([
458+
'vip_level' => 'gold',
459+
'newsletter_subscription' => true,
460+
'preferred_contact' => 'email'
461+
])
462+
);
463+
}
464+
}
465+
```
466+
467+
### Customer with Addresses
468+
469+
```php
470+
#[Fixture(groups: ['customers', 'addresses'])]
471+
class CustomerWithAddressesFixture implements FixtureInterface
472+
{
473+
public function __construct(
474+
private readonly CustomerFixtureLoader $customerFixtureLoader
475+
) {
476+
}
477+
478+
public function load(): void
479+
{
480+
$this->customerFixtureLoader->apply(
481+
(new CustomerFixtureDefinition('customer@example.com'))
482+
->firstName('Max')
483+
->lastName('Mustermann')
484+
->salutation('mr')
485+
->password('password')
486+
->defaultBillingAddress([
487+
'firstName' => 'Max',
488+
'lastName' => 'Mustermann',
489+
'street' => 'Musterstraße 123',
490+
'zipcode' => '12345',
491+
'city' => 'Musterstadt',
492+
'country' => 'DEU',
493+
'company' => 'Musterfirma GmbH',
494+
'phoneNumber' => '+49 123 456789',
495+
'salutation' => 'mr'
496+
])
497+
->defaultShippingAddress([
498+
'firstName' => 'Max',
499+
'lastName' => 'Mustermann',
500+
'street' => 'Lieferadresse 456',
501+
'zipcode' => '67890',
502+
'city' => 'Lieferstadt',
503+
'country' => 'DEU',
504+
'additionalAddressLine1' => 'Building B',
505+
'additionalAddressLine2' => '3rd Floor'
506+
])
507+
->addAddress('work', [
508+
'firstName' => 'Max',
509+
'lastName' => 'Mustermann',
510+
'street' => 'Office Street 789',
511+
'zipcode' => '11111',
512+
'city' => 'Business City',
513+
'country' => 'DEU',
514+
'company' => 'Work Corporation'
515+
])
516+
);
517+
}
518+
}
519+
```
520+
521+
### Guest Customer Fixture
522+
523+
```php
524+
#[Fixture(groups: ['customers', 'guest-orders'])]
525+
class GuestCustomerFixture implements FixtureInterface
526+
{
527+
public function __construct(
528+
private readonly CustomerFixtureLoader $customerFixtureLoader
529+
) {
530+
}
531+
532+
public function load(): void
533+
{
534+
$this->customerFixtureLoader->apply(
535+
(new CustomerFixtureDefinition('guest@example.com'))
536+
->firstName('Guest')
537+
->lastName('User')
538+
->guest(true)
539+
->active(false)
540+
->defaultBillingAddress([
541+
'firstName' => 'Guest',
542+
'lastName' => 'User',
543+
'street' => 'Guest Street 1',
544+
'zipcode' => '99999',
545+
'city' => 'Guest City',
546+
'country' => 'DEU'
547+
])
548+
);
549+
}
550+
}
551+
```
552+
387553
## Best Practices
388554

389555
1. **Use meaningful names**: Name your fixtures clearly to indicate what data they create
390-
2. **Organize with groups**: Use groups to categorize fixtures (e.g., 'test-data', 'demo-data', 'performance-test', 'theme-config')
556+
2. **Organize with groups**: Use groups to categorize fixtures (e.g., 'test-data', 'demo-data', 'performance-test', 'theme-config', 'customers')
391557
3. **Declare dependencies explicitly**: Always declare dependencies to ensure correct execution order
392558
4. **Keep fixtures focused**: Each fixture should have a single responsibility
393559
5. **Make fixtures idempotent**: Fixtures should be able to run multiple times without errors
394560
6. **Use dependency injection**: Inject the services you need rather than accessing the container directly
395561
7. **Handle theme errors gracefully**: Use try-catch blocks when configuring optional themes
562+
8. **Use email as unique identifier**: Customer fixtures use email as the primary identifier for updates vs. creation

composer.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
},
1212
"require": {
1313
"php": "^8.2",
14-
"shopware/administration": "^6.6",
15-
"shopware/core": "^6.6",
16-
"shopware/storefront": "^6.6"
14+
"shopware/administration": "^6.6.10",
15+
"shopware/core": "^6.6.10",
16+
"shopware/storefront": "^6.6.10"
1717
},
1818
"extra": {
1919
"shopware-bundle-name": "FixtureBundle"

config/bundles.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php declare(strict_types=1);
2+
3+
use Composer\InstalledVersions;
4+
use Shopware\FixtureBundle\FixtureBundle;
5+
use Shopware\Storefront\Storefront;
6+
7+
$bundles = [
8+
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
9+
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
10+
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
11+
Shopware\Core\Profiling\Profiling::class => ['all' => true],
12+
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true],
13+
Shopware\Core\Framework\Framework::class => ['all' => true],
14+
Shopware\Core\System\System::class => ['all' => true],
15+
Shopware\Core\Content\Content::class => ['all' => true],
16+
Shopware\Core\Checkout\Checkout::class => ['all' => true],
17+
Shopware\Core\DevOps\DevOps::class => ['all' => true],
18+
Shopware\Core\Maintenance\Maintenance::class => ['all' => true],
19+
Storefront::class => ['all' => true],
20+
Shopware\Administration\Administration::class => ['all' => true],
21+
FixtureBundle::class => ['all' => true],
22+
];
23+
24+
return $bundles;

0 commit comments

Comments
 (0)