79 lines
3.1 KiB
PHP
79 lines
3.1 KiB
PHP
<?php
|
|||
|
|
|
||
|
|
use App\Models\PricingPlan;
|
||
|
|
use App\Models\Product;
|
||
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||
|
|
|
||
|
|
uses(RefreshDatabase::class);
|
||
|
|
|
||
|
|
function pricingPayload(array $overrides = []): array
|
||
|
|
{
|
||
|
|
return array_merge([
|
||
|
|
'title' => 'Priced Product',
|
||
|
|
'description' => 'A product description',
|
||
|
|
'website_url' => 'https://example.com',
|
||
|
|
'category_id' => makeCategory()->id,
|
||
|
|
], $overrides);
|
||
|
|
}
|
||
|
|
|
||
|
|
test('submitter adds plans', function () {
|
||
|
|
$user = userWithRole('user');
|
||
|
|
|
||
|
|
$this->actingAs($user)->post(route('products.store'), pricingPayload([
|
||
|
|
'plans' => [
|
||
|
|
['name' => 'Free', 'price' => '0', 'period' => 'monthly', 'description' => 'Basics'],
|
||
|
|
['name' => 'Team', 'price' => '9.99', 'period' => 'monthly'],
|
||
|
|
],
|
||
|
|
]))->assertRedirect()->assertSessionHasNoErrors();
|
||
|
|
|
||
|
|
$plans = Product::firstOrFail()->pricingPlans;
|
||
|
|
expect($plans->pluck('name')->all())->toBe(['Free', 'Team']);
|
||
|
|
expect($plans->pluck('position')->all())->toBe([0, 1]);
|
||
|
|
expect((float) $plans[1]->price)->toBe(9.99);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('invalid plans fail validation and save nothing', function (array $plan, string $key) {
|
||
|
|
$user = userWithRole('user');
|
||
|
|
|
||
|
|
$this->actingAs($user)->post(route('products.store'), pricingPayload([
|
||
|
|
'plans' => [array_merge(['name' => 'Pro', 'price' => '5', 'period' => 'yearly'], $plan)],
|
||
|
|
]))->assertSessionHasErrors($key);
|
||
|
|
|
||
|
|
expect(Product::count())->toBe(0);
|
||
|
|
expect(PricingPlan::count())->toBe(0);
|
||
|
|
})->with([
|
||
|
|
'negative price' => [['price' => '-1'], 'plans.0.price'],
|
||
|
|
'non numeric price' => [['price' => 'abc'], 'plans.0.price'],
|
||
|
|
'bad period' => [['period' => 'weekly'], 'plans.0.period'],
|
||
|
|
'missing name' => [['name' => ''], 'plans.0.name'],
|
||
|
|
]);
|
||
|
|
|
||
|
|
test('update replaces the plan list', function () {
|
||
|
|
$user = userWithRole('user');
|
||
|
|
$product = Product::factory()->pending()->create(['user_id' => $user->id]);
|
||
|
|
$product->pricingPlans()->create(['name' => 'Old', 'price' => 1, 'period' => 'monthly', 'position' => 0]);
|
||
|
|
$product->pricingPlans()->create(['name' => 'Older', 'price' => 2, 'period' => 'yearly', 'position' => 1]);
|
||
|
|
|
||
|
|
$this->actingAs($user)->put(route('products.update', $product), pricingPayload([
|
||
|
|
'category_id' => $product->category_id,
|
||
|
|
'plans' => [['name' => 'New', 'price' => '3', 'period' => 'one-time']],
|
||
|
|
]))->assertRedirect();
|
||
|
|
|
||
|
|
expect($product->pricingPlans()->pluck('name')->all())->toBe(['New']);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('show page prints price and period', function () {
|
||
|
|
$product = Product::factory()->approved()->create();
|
||
|
|
$product->pricingPlans()->create(['name' => 'Free', 'price' => 0, 'period' => 'monthly', 'position' => 0]);
|
||
|
|
$product->pricingPlans()->create(['name' => 'Team', 'price' => 9.99, 'period' => 'monthly', 'position' => 1]);
|
||
|
|
|
||
|
|
$this->get(route('products.show', $product))->assertOk()
|
||
|
|
->assertSee('€9.99')->assertSee('monthly')->assertSee('€0');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('no plans, no pricing section', function () {
|
||
|
|
$product = Product::factory()->approved()->create();
|
||
|
|
|
||
|
|
$this->get(route('products.show', $product))->assertOk()->assertDontSee('data-pricing', false);
|
||
|
|
});
|