laravel-shop/tests/Feature/ProductActionTest.php

362 lines
10 KiB
PHP
Raw Normal View History

2025-11-21 10:49:41 +00:00
<?php
namespace Blax\Shop\Tests\Feature;
use Blax\Shop\Models\Product;
use Blax\Shop\Models\ProductAction;
use Blax\Shop\Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Workbench\App\Models\User;
2025-12-24 18:40:10 +00:00
use PHPUnit\Framework\Attributes\Test;
2025-11-21 10:49:41 +00:00
class ProductActionTest extends TestCase
{
use RefreshDatabase;
2025-12-24 18:40:10 +00:00
#[Test]
2025-11-21 10:49:41 +00:00
public function it_can_create_a_product_action()
{
$product = Product::factory()->create();
2025-11-29 19:09:19 +00:00
$action = $product->actions()->create([
'events' => ['purchased', 'refunded'],
'class' => 'App\\Actions\\SendWelcomeEmail',
2025-11-21 10:49:41 +00:00
]);
$this->assertDatabaseHas('product_actions', [
'id' => $action->id,
'product_id' => $product->id,
]);
2025-11-29 19:09:19 +00:00
$this->assertContains('purchased', $action->events ?? []);
$this->assertContains('refunded', $action->events ?? []);
2025-11-21 10:49:41 +00:00
}
2025-12-24 18:40:10 +00:00
#[Test]
2025-11-21 10:49:41 +00:00
public function product_has_many_actions()
{
$product = Product::factory()->create();
ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\SendWelcomeEmail',
2025-11-21 10:49:41 +00:00
]);
ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\GrantAccess',
2025-11-21 10:49:41 +00:00
]);
$this->assertCount(2, $product->fresh()->actions);
}
2025-12-24 18:40:10 +00:00
#[Test]
2025-11-21 10:49:41 +00:00
public function action_belongs_to_product()
{
$product = Product::factory()->create();
$action = ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'event' => ['purchased'],
'class' => 'App\\Actions\\TestAction',
2025-11-21 10:49:41 +00:00
]);
$this->assertEquals($product->id, $action->product->id);
}
2025-12-24 18:40:10 +00:00
#[Test]
2025-11-21 10:49:41 +00:00
public function it_can_enable_and_disable_actions()
{
$product = Product::factory()->create();
$action = ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\TestAction',
2025-11-21 10:49:41 +00:00
]);
2025-11-29 19:09:19 +00:00
$action->refresh();
2025-11-21 10:49:41 +00:00
$this->assertTrue($action->active);
$action->update(['active' => false]);
$this->assertFalse($action->fresh()->active);
}
2025-12-24 18:40:10 +00:00
#[Test]
2025-11-21 10:49:41 +00:00
public function it_can_store_action_parameters()
{
$product = Product::factory()->create();
$action = ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\SendEmail',
2025-11-21 10:49:41 +00:00
'parameters' => [
'template' => 'welcome',
'delay' => 60,
'subject' => 'Welcome to our service',
],
]);
2025-11-22 17:09:45 +00:00
$action = $action->fresh();
2025-11-21 10:49:41 +00:00
$this->assertEquals('welcome', $action->parameters['template']);
$this->assertEquals(60, $action->parameters['delay']);
$this->assertEquals('Welcome to our service', $action->parameters['subject']);
}
2025-12-24 18:40:10 +00:00
#[Test]
2025-11-21 10:49:41 +00:00
public function it_can_set_action_priority()
{
$product = Product::factory()->create();
$action1 = ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\FirstAction',
2025-11-21 10:49:41 +00:00
]);
$action2 = ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\SecondAction',
2025-11-21 10:49:41 +00:00
]);
$sorted = ProductAction::where('product_id', $product->id)
->orderBy('sort_order')
->get();
$this->assertEquals($action1->id, $sorted[0]->id);
$this->assertEquals($action2->id, $sorted[1]->id);
}
2025-12-24 18:40:10 +00:00
#[Test]
2025-11-21 10:49:41 +00:00
public function it_can_have_different_events()
{
$product = Product::factory()->create();
$purchasedAction = ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\OnPurchase',
2025-11-21 10:49:41 +00:00
'active' => true,
]);
$refundedAction = ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['refunded'],
'class' => 'App\\Actions\\OnRefund',
2025-11-21 10:49:41 +00:00
'active' => true,
]);
2025-11-29 19:09:19 +00:00
$this->assertContains('purchased', $purchasedAction->events);
$this->assertContains('refunded', $refundedAction->events);
2025-11-21 10:49:41 +00:00
}
2025-12-24 18:40:10 +00:00
#[Test]
2025-11-21 10:49:41 +00:00
public function it_can_get_actions_for_specific_event()
{
$product = Product::factory()->create();
ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\OnPurchase',
2025-11-21 10:49:41 +00:00
]);
ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\OnPurchase',
2025-11-21 10:49:41 +00:00
]);
ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['refunded'],
'class' => 'App\\Actions\\OnPurchase',
2025-11-21 10:49:41 +00:00
]);
$purchaseActions = ProductAction::where('product_id', $product->id)
2025-11-29 19:09:19 +00:00
->whereJsonContains('events', 'purchased')
2025-11-21 10:49:41 +00:00
->get();
$this->assertCount(2, $purchaseActions);
}
2025-12-24 18:40:10 +00:00
#[Test]
2025-11-21 10:49:41 +00:00
public function it_can_filter_enabled_actions()
{
$product = Product::factory()->create();
ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\EnabledAction',
2025-11-21 10:49:41 +00:00
]);
ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\DisabledAction',
2025-11-21 10:49:41 +00:00
'active' => false,
]);
$enabledActions = ProductAction::where('product_id', $product->id)
->where('active', true)
->get();
$this->assertCount(1, $enabledActions);
}
2025-12-24 18:40:10 +00:00
#[Test]
2025-11-21 10:49:41 +00:00
public function multiple_products_can_have_same_action()
{
$product1 = Product::factory()->create();
$product2 = Product::factory()->create();
ProductAction::create([
'product_id' => $product1->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\CommonAction',
2025-11-21 10:49:41 +00:00
]);
ProductAction::create([
'product_id' => $product2->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\CommonAction',
2025-11-21 10:49:41 +00:00
]);
$this->assertCount(1, $product1->actions);
$this->assertCount(1, $product2->actions);
}
2025-12-24 18:40:10 +00:00
#[Test]
2025-11-21 10:49:41 +00:00
public function it_can_update_action_parameters()
{
$product = Product::factory()->create();
$action = ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\TestAction',
2025-11-22 17:09:45 +00:00
'parameters' => [
'key' => 'old_value'
],
2025-11-21 10:49:41 +00:00
]);
$action->update([
2025-11-22 17:09:45 +00:00
'parameters' => [
'key' => 'new_value',
'another_key' => 'another_value'
],
2025-11-21 10:49:41 +00:00
]);
$fresh = $action->fresh();
2025-11-22 17:09:45 +00:00
$this->assertNotEquals('old_value', $fresh->parameters['key']);
2025-11-21 10:49:41 +00:00
$this->assertEquals('new_value', $fresh->parameters['key']);
$this->assertEquals('another_value', $fresh->parameters['another_key']);
}
2025-12-24 18:40:10 +00:00
#[Test]
2025-11-21 10:49:41 +00:00
public function deleting_product_deletes_actions()
{
$product = Product::factory()->create();
$action = ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'event' => ['purchased'],
'class' => 'App\\Actions\\TestAction',
2025-11-21 10:49:41 +00:00
'active' => true,
]);
$actionId = $action->id;
$product->delete();
$this->assertDatabaseMissing('product_actions', ['id' => $actionId]);
}
2025-12-24 18:40:10 +00:00
#[Test]
2025-11-21 10:49:41 +00:00
public function action_can_have_empty_parameters()
{
$product = Product::factory()->create();
$action = ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\SimpleAction',
2025-11-21 10:49:41 +00:00
]);
$this->assertNull($action->parameters);
}
2025-12-24 18:40:10 +00:00
#[Test]
2025-11-21 10:49:41 +00:00
public function it_can_query_actions_by_priority_order()
{
$product = Product::factory()->create();
$high = ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\HighPriority',
2025-11-21 10:49:41 +00:00
'sort_order' => 100,
'active' => true,
]);
$medium = ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\MediumPriority',
2025-11-21 10:49:41 +00:00
'sort_order' => 50,
'active' => true,
]);
$low = ProductAction::create([
'product_id' => $product->id,
2025-11-29 19:09:19 +00:00
'events' => ['purchased'],
'class' => 'App\\Actions\\LowPriority',
2025-11-21 10:49:41 +00:00
'sort_order' => 10,
'active' => true,
]);
$ordered = ProductAction::where('product_id', $product->id)
->orderBy('sort_order', 'asc')
->get();
$this->assertEquals($low->id, $ordered[0]->id);
$this->assertEquals($medium->id, $ordered[1]->id);
$this->assertEquals($high->id, $ordered[2]->id);
}
2025-11-29 19:09:19 +00:00
2025-12-24 18:40:10 +00:00
#[Test]
2025-11-29 19:09:19 +00:00
public function it_can_be_triggered_on_purchase()
{
$user = User::factory()->create();
$product = Product::factory()
->withStocks()
->withPrices(1, 5000)
->create();
$product->actions()->create([
'events' => ['purchased'],
'class' => 'App\\Actions\\SendThankYouEmail',
2025-12-03 13:42:22 +00:00
'defer' => false,
2025-11-29 19:09:19 +00:00
]);
$product->actions()->create([
'events' => ['purchased'],
'class' => 'App\\Actions\\SendThankYouEmail',
2025-12-03 13:42:22 +00:00
'defer' => false,
2025-11-29 19:09:19 +00:00
]);
$purchase = $user->purchase($product, 1);
2025-12-03 13:39:07 +00:00
$this->assertEquals(2, $purchase->actionRuns()->count());
2025-11-29 19:09:19 +00:00
}
2025-11-21 10:49:41 +00:00
}