Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidBadura committed Oct 19, 2024
1 parent db8d956 commit a24a266
Show file tree
Hide file tree
Showing 18 changed files with 820 additions and 71 deletions.
67 changes: 2 additions & 65 deletions docs/pages/pipeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ use Patchlevel\EventSourcing\Pipeline\Middleware\ExcludeEventMiddleware;
use Patchlevel\EventSourcing\Pipeline\Middleware\RecalculatePlayheadMiddleware;
use Patchlevel\EventSourcing\Pipeline\Middleware\ReplaceEventMiddleware;
use Patchlevel\EventSourcing\Pipeline\Pipeline;
use Patchlevel\EventSourcing\Pipeline\Source\StoreSource;
use Patchlevel\EventSourcing\Pipeline\Target\StoreTarget;

$pipeline = new Pipeline(
new StoreSource($oldStore),
new StoreTarget($newStore),
[
new ExcludeEventMiddleware([PrivacyAdded::class]),
Expand All @@ -28,6 +26,8 @@ $pipeline = new Pipeline(
new RecalculatePlayheadMiddleware(),
]
);

$pipeline->run($oldStore->load());
```

!!! danger
Expand All @@ -53,69 +53,6 @@ There is a source where the data comes from.
A target where the data should flow.
And any number of middlewares to do something with the data beforehand.

## Source

The first thing you need is a source of where the data should come from.

### Store

The `StoreSource` is the standard source to load all events from the database.

```php
use Patchlevel\EventSourcing\Pipeline\Source\StoreSource;

$source = new StoreSource($store);
```

### In Memory

There is an `InMemorySource` that receives the messages in an array. This source can be used to write pipeline tests.

```php
use Patchlevel\EventSourcing\EventBus\Message;
use Patchlevel\EventSourcing\Pipeline\Source\InMemorySource;

$source = new InMemorySource([
new Message(
Profile::class,
'1',
1,
new ProfileCreated(Email::fromString('[email protected]')),
),
// ...
]);
```

### Custom Source

You can also create your own source class. It has to inherit from `Source`.
Here you can, for example, create a migration from another event sourcing system or similar system.

```php
use Patchlevel\EventSourcing\EventBus\Message;
use Patchlevel\EventSourcing\Pipeline\Source\Source;

$source = new class implements Source {
/**
* @return Generator<Message>
*/
public function load(): Generator
{
yield new Message(
Profile::class,
'1',
0,
new ProfileCreated('1', ['name' => 'David'])
);
}

public function count(): int
{
reutrn 1;
}
}
```

## Target

After you have a source, you still need the destination of the pipeline.
Expand Down
10 changes: 5 additions & 5 deletions src/Pipeline/Middleware/ChainMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@

final class ChainMiddleware implements Middleware
{
/** @param iterable<Middleware> $translators */
/** @param iterable<Middleware> $middlewares */
public function __construct(
private readonly iterable $translators,
private readonly iterable $middlewares,
) {
}

Expand All @@ -21,7 +21,7 @@ public function __invoke(Message $message): array
{
$messages = [$message];

foreach ($this->translators as $middleware) {
foreach ($this->middlewares as $middleware) {
$messages = $this->process($middleware, $messages);
}

Expand All @@ -33,12 +33,12 @@ public function __invoke(Message $message): array
*
* @return list<Message>
*/
private function process(Middleware $translator, array $messages): array
private function process(Middleware $middleware, array $messages): array
{
$result = [];

foreach ($messages as $message) {
$result += $translator($message);
$result += $middleware($message);
}

return array_values($result);
Expand Down
23 changes: 23 additions & 0 deletions src/Pipeline/Middleware/ClosureMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Pipeline\Middleware;

use Closure;
use Patchlevel\EventSourcing\Message\Message;

final class ClosureMiddleware implements Middleware
{
/** @param Closure(Message): list<Message> $callable */
public function __construct(
private readonly Closure $callable,
) {
}

/** @return list<Message> */
public function __invoke(Message $message): array
{
return ($this->callable)($message);
}
}
2 changes: 1 addition & 1 deletion src/Pipeline/Pipeline.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ final class Pipeline
public function __construct(
private readonly Target $target,
array|Middleware $middlewares = [],
private readonly float|int $bufferSize = 0,
private readonly float|int $bufferSize = 1_000,

Check warning on line 24 in src/Pipeline/Pipeline.php

View workflow job for this annotation

GitHub Actions / Mutation tests on diff (locked, 8.3, ubuntu-latest)

Escaped Mutant for Mutator "DecrementInteger": --- Original +++ New @@ @@ { private readonly Middleware $middleware; /** @param list<Middleware>|Middleware $middlewares */ - public function __construct(private readonly Target $target, array|Middleware $middlewares = [], private readonly float|int $bufferSize = 1000) + public function __construct(private readonly Target $target, array|Middleware $middlewares = [], private readonly float|int $bufferSize = 999) { if (is_array($middlewares)) { $this->middleware = new ChainMiddleware($middlewares);

Check warning on line 24 in src/Pipeline/Pipeline.php

View workflow job for this annotation

GitHub Actions / Mutation tests on diff (locked, 8.3, ubuntu-latest)

Escaped Mutant for Mutator "IncrementInteger": --- Original +++ New @@ @@ { private readonly Middleware $middleware; /** @param list<Middleware>|Middleware $middlewares */ - public function __construct(private readonly Target $target, array|Middleware $middlewares = [], private readonly float|int $bufferSize = 1000) + public function __construct(private readonly Target $target, array|Middleware $middlewares = [], private readonly float|int $bufferSize = 1001) { if (is_array($middlewares)) { $this->middleware = new ChainMiddleware($middlewares);
) {
if (is_array($middlewares)) {
$this->middleware = new ChainMiddleware($middlewares);
Expand Down
43 changes: 43 additions & 0 deletions tests/Unit/Pipeline/Middleware/ChainMiddlewareTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Tests\Unit\Pipeline\Middleware;

use Patchlevel\EventSourcing\Message\Message;
use Patchlevel\EventSourcing\Pipeline\Middleware\ChainMiddleware;
use Patchlevel\EventSourcing\Pipeline\Middleware\Middleware;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\Email;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileCreated;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileId;
use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;

/** @covers \Patchlevel\EventSourcing\Pipeline\Middleware\ChainMiddleware */
final class ChainMiddlewareTest extends TestCase
{
use ProphecyTrait;

public function testChain(): void
{
$message = new Message(
new ProfileCreated(
ProfileId::fromString('1'),
Email::fromString('[email protected]'),
),
);

$child1 = $this->prophesize(Middleware::class);
$child1->__invoke($message)->willReturn([$message])->shouldBeCalled();

$child2 = $this->prophesize(Middleware::class);
$child2->__invoke($message)->willReturn([$message])->shouldBeCalled();

$middleware = new ChainMiddleware([
$child1->reveal(),
$child2->reveal(),
]);

$middleware($message);
}
}
34 changes: 34 additions & 0 deletions tests/Unit/Pipeline/Middleware/ClosureMiddlewareTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Tests\Unit\Pipeline\Middleware;

use Patchlevel\EventSourcing\Message\Message;
use Patchlevel\EventSourcing\Pipeline\Middleware\ClosureMiddleware;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\Email;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileCreated;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileId;
use PHPUnit\Framework\TestCase;

/** @covers \Patchlevel\EventSourcing\Pipeline\Middleware\ClosureMiddleware */
final class ClosureMiddlewareTest extends TestCase
{
public function testClosure(): void
{
$middleware = new ClosureMiddleware(static function (Message $message): array {
return [$message];
});

$message = new Message(
new ProfileCreated(
ProfileId::fromString('1'),
Email::fromString('[email protected]'),
),
);

$result = $middleware($message);

self::assertSame([$message], $result);
}
}
48 changes: 48 additions & 0 deletions tests/Unit/Pipeline/Middleware/ExcludeEventMiddlewareTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Tests\Unit\Pipeline\Middleware;

use Patchlevel\EventSourcing\Message\Message;
use Patchlevel\EventSourcing\Pipeline\Middleware\ExcludeEventMiddleware;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\Email;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileCreated;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileId;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileVisited;
use PHPUnit\Framework\TestCase;

/** @covers \Patchlevel\EventSourcing\Pipeline\Middleware\ExcludeEventMiddleware */
final class ExcludeEventMiddlewareTest extends TestCase
{
public function testDeleteEvent(): void
{
$middleware = new ExcludeEventMiddleware([ProfileCreated::class]);

$message = new Message(
new ProfileCreated(
ProfileId::fromString('1'),
Email::fromString('[email protected]'),
),
);

$result = $middleware($message);

self::assertSame([], $result);
}

public function testSkipEvent(): void
{
$middleware = new ExcludeEventMiddleware([ProfileCreated::class]);

$message = new Message(
new ProfileVisited(
ProfileId::fromString('1'),
),
);

$result = $middleware($message);

self::assertSame([$message], $result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Tests\Unit\Pipeline\Middleware;

use Patchlevel\EventSourcing\Message\Message;
use Patchlevel\EventSourcing\Pipeline\Middleware\ExcludeEventWithHeaderMiddleware;
use Patchlevel\EventSourcing\Store\ArchivedHeader;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\Email;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileCreated;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileId;
use PHPUnit\Framework\TestCase;

/** @covers \Patchlevel\EventSourcing\Pipeline\Middleware\ExcludeEventWithHeaderMiddleware */
final class ExcludeEventWithHeaderMiddlewareTest extends TestCase
{
public function testExcludedEvent(): void
{
$middleware = new ExcludeEventWithHeaderMiddleware(ArchivedHeader::class);

$message = Message::create(
new ProfileCreated(
ProfileId::fromString('1'),
Email::fromString('[email protected]'),
),
)->withHeader(new ArchivedHeader());

$result = $middleware($message);

self::assertSame([], $result);
}

public function testIncludeEvent(): void
{
$middleware = new ExcludeEventWithHeaderMiddleware(ArchivedHeader::class);

$message = Message::create(
new ProfileCreated(
ProfileId::fromString('1'),
Email::fromString('[email protected]'),
),
);

$result = $middleware($message);

self::assertSame([$message], $result);
}
}
52 changes: 52 additions & 0 deletions tests/Unit/Pipeline/Middleware/FilterEventMiddlewareTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Tests\Unit\Pipeline\Middleware;

use Patchlevel\EventSourcing\Message\Message;
use Patchlevel\EventSourcing\Pipeline\Middleware\FilterEventMiddleware;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\Email;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileCreated;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileId;
use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileVisited;
use PHPUnit\Framework\TestCase;

/** @covers \Patchlevel\EventSourcing\Pipeline\Middleware\FilterEventMiddleware */
final class FilterEventMiddlewareTest extends TestCase
{
public function testPositive(): void
{
$middleware = new FilterEventMiddleware(static function (object $event) {
return $event instanceof ProfileCreated;
});

$message = new Message(
new ProfileCreated(
ProfileId::fromString('1'),
Email::fromString('[email protected]'),
),
);

$result = $middleware($message);

self::assertSame([$message], $result);
}

public function testNegative(): void
{
$middleware = new FilterEventMiddleware(static function (object $event) {
return $event instanceof ProfileCreated;
});

$message = new Message(
new ProfileVisited(
ProfileId::fromString('1'),
),
);

$result = $middleware($message);

self::assertSame([], $result);
}
}
Loading

0 comments on commit a24a266

Please sign in to comment.