Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test Affordances #41

Merged
merged 14 commits into from
Dec 29, 2023
24 changes: 24 additions & 0 deletions bin/pre-commit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash

# Move into project root
BIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$BIN_DIR"
cd ..

# Exit on errors
set -e

CHANGED_FILES=$(git diff --cached --name-only --diff-filter=ACM -- '***.php')

if [[ -z "$CHANGED_FILES" ]]; then
echo 'No changed files'
exit 0
fi

if [[ -x vendor/bin/pint ]]; then
vendor/bin/pint --dirty
git add $CHANGED_FILES
else
echo 'pint is not installed'
exit 1
fi
7 changes: 7 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"pestphp/pest-plugin-laravel": "^2.2",
"pestphp/pest-plugin-watch": "^2.0",
"phpunit/phpunit": "^10.4.2",
"projektgopher/whisky": "^0.5.1",
"spatie/laravel-ray": "^1.33"
},
"autoload": {
Expand Down Expand Up @@ -74,6 +75,12 @@
"@clear",
"@prepare"
],
"post-install-cmd": [
"whisky update"
],
"post-update-cmd": [
"whisky update"
],
"test": "vendor/bin/pest",
"test-coverage": "vendor/bin/pest --coverage",
"format": "vendor/bin/pint",
Expand Down
6 changes: 4 additions & 2 deletions examples/Counter/tests/FireOnReplayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
use Thunk\Verbs\Facades\Verbs;
use Thunk\Verbs\Models\VerbEvent;

beforeEach(function () {
Verbs::commitImmediately();
});

it('firing events from the handle method is ignored while replaying', function () {
IncrementCountTwice::fire();

Verbs::commit();

expect(VerbEvent::where('type', IncrementCount::class)->count())->toBe(2);

Verbs::replay();
Expand Down
32 changes: 32 additions & 0 deletions examples/Counter/tests/InitializeStateTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

use Thunk\Verbs\Events\VerbsStateInitialized;
use Thunk\Verbs\Examples\Counter\Events\IncrementCount;
use Thunk\Verbs\Examples\Counter\States\CountState;
use Thunk\Verbs\Facades\Verbs;
use Thunk\Verbs\Models\VerbEvent;

it('State factory initializes a state', function () {
$count_state = CountState::factory()->create([
'count' => 1337,
]);

expect($events = VerbEvent::all())
->toHaveCount(1);

expect($events->first())
->type->toBe(VerbsStateInitialized::class);

expect($count_state)
->toBeInstanceOf(CountState::class)
->count
->toBe(1337);

IncrementCount::fire();
Verbs::commit();

expect($count_state)
->toBeInstanceOf(CountState::class)
->count
->toBe(1338);
});
12 changes: 4 additions & 8 deletions examples/Counter/tests/StateRehydrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
use Thunk\Verbs\Models\VerbEvent;
use Thunk\Verbs\Models\VerbSnapshot;

beforeEach(function () {
Verbs::commitImmediately();
});

it('supports rehydrating a state from snapshots', function () {
$state = IncrementCount::fire()->state();

expect($state->count)->toBe(1);

Verbs::commit();

expect(VerbSnapshot::query()->count())->toBe(1);

VerbEvent::truncate();
Expand All @@ -27,8 +29,6 @@

expect($state->count)->toBe(1);

Verbs::commit();

expect(VerbEvent::query()->count())->toBe(1);

app(StateManager::class)->reset(include_storage: true);
Expand All @@ -41,8 +41,6 @@
it('supports rehydrating a state from a combination of snapshots and events', function () {
expect(IncrementCount::fire()->state()->count)->toBe(1);

Verbs::commit();

expect(VerbSnapshot::query()->count())->toBe(1);
expect(VerbEvent::query()->count())->toBe(1);

Expand All @@ -52,8 +50,6 @@

expect(IncrementCount::fire()->state()->count)->toBe(2);

Verbs::commit();

expect(VerbEvent::query()->count())->toBe(1);

$snapshot->save();
Expand Down
7 changes: 7 additions & 0 deletions src/CommitsImmediately.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Thunk\Verbs;

interface CommitsImmediately
{
}
43 changes: 43 additions & 0 deletions src/Events/VerbsStateInitialized.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace Thunk\Verbs\Events;

use Thunk\Verbs\CommitsImmediately;
use Thunk\Verbs\Event;
use Thunk\Verbs\Support\StateCollection;

class VerbsStateInitialized extends Event implements CommitsImmediately
{
public function __construct(
public int|string|null $state_id,
public string $state_class,
public array $state_data,
) {
}

public function states(): StateCollection
{
return StateCollection::make([
$this->state_id
? $this->state_class::load($this->state_id)
: $this->state_class::singleton(),
]);
}

public function validate()
{
$this->assert(
! $this->state()->__verbs_initialized,
'State has already been initialized',
);
}

public function apply()
{
foreach ($this->state_data as $key => $value) {
$this->state()->$key = $value;
}

$this->state()->__verbs_initialized = true;
}
}
1 change: 1 addition & 0 deletions src/Facades/Verbs.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* @method static int|string|null toId($id)
* @method static Event fire(Event $event)
* @method static void createMetadataUsing(callable $callback)
* @method static void commitImmediately(bool $commit_immediately = true)
*/
class Verbs extends Facade
{
Expand Down
39 changes: 0 additions & 39 deletions src/FromState.php

This file was deleted.

12 changes: 12 additions & 0 deletions src/Lifecycle/Broker.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
use Glhd\Bits\Bits;
use Ramsey\Uuid\UuidInterface;
use Symfony\Component\Uid\AbstractUid;
use Thunk\Verbs\CommitsImmediately;
use Thunk\Verbs\Event;
use Thunk\Verbs\Lifecycle\Queue as EventQueue;

class Broker
{
public bool $is_replaying = false;

public bool $commit_immediately = false;

public function __construct(
protected Dispatcher $dispatcher,
protected MetadataManager $metadata,
Expand All @@ -37,6 +40,10 @@ public function fire(Event $event): ?Event

app(Queue::class)->queue($event);

if ($this->commit_immediately || $event instanceof CommitsImmediately) {
$this->commit();
}

return $event;
}

Expand Down Expand Up @@ -114,4 +121,9 @@ public function toId(Bits|UuidInterface|AbstractUid|int|string|null $id): int|st
default => $id,
};
}

public function commitImmediately(bool $commit_immediately = true): void
{
$this->commit_immediately = $commit_immediately;
}
}
8 changes: 8 additions & 0 deletions src/State.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ abstract class State

public Bits|UuidInterface|AbstractUid|int|string|null $last_event_id = null;

// TODO: This should move to state metadata eventually
public bool $__verbs_initialized = false;

public static function make(...$args): static
{
if ((count($args) === 1 && isset($args[0]) && is_array($args[0]))) {
Expand All @@ -28,6 +31,11 @@ public static function make(...$args): static
return $state;
}

public static function factory(): StateFactory
{
return new StateFactory(static::class);
}

public function __construct()
{
app(StateManager::class)->register($this);
Expand Down
22 changes: 22 additions & 0 deletions src/StateFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Thunk\Verbs;

use Thunk\Verbs\Events\VerbsStateInitialized;

class StateFactory
{
public function __construct(
protected string $state_class
) {
}

public function create(array $data, ?int $id = null): State
{
return VerbsStateInitialized::fire(
state_id: $id,
state_class: $this->state_class,
state_data: $data
)->state();
}
}
8 changes: 8 additions & 0 deletions whisky.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"disabled": [],
"hooks": {
"pre-commit": [
"./bin/pre-commit.sh"
]
}
}
Loading