feat: product badges and show page layout

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Doar Mihai
2026-10-17 15:56:58 +03:00
co-authored by Claude Sonnet 5.5
parent 029689407b
commit 9920fafab6
12 changed files with 382 additions and 63 deletions
+102
View File
@@ -0,0 +1,102 @@
<?php
use App\Models\Product;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
function badgePayload(array $overrides = []): array
{
return array_merge([
'title' => 'Badge Product',
'description' => 'A product description',
'website_url' => 'https://example.com',
'category_id' => makeCategory()->id,
], $overrides);
}
test('submitter ticks badges on create', function () {
$user = userWithRole('user');
$this->actingAs($user)->post(route('products.store'), badgePayload([
'eu_hosted' => 1,
'open_source' => 1,
]))->assertRedirect();
$product = Product::firstOrFail();
expect($product->eu_hosted)->toBeTrue()
->and($product->open_source)->toBeTrue()
->and($product->free_tier)->toBeFalse()
->and($product->eu_made)->toBeFalse();
});
test('submitter can change badges while pending', function () {
$user = userWithRole('user');
$product = Product::factory()->pending()->create(['user_id' => $user->id]);
$this->actingAs($user)->put(route('products.update', $product), badgePayload([
'category_id' => $product->category_id,
'eu_made' => 1,
]))->assertRedirect();
expect($product->fresh()->eu_made)->toBeTrue();
});
test('submitter cannot change badges after approval', function () {
$user = userWithRole('user');
$product = Product::factory()->approved()->create([
'user_id' => $user->id,
'eu_hosted' => false,
]);
$this->actingAs($user)->put(route('products.update', $product), badgePayload([
'category_id' => $product->category_id,
'eu_hosted' => 1,
]))->assertRedirect();
expect($product->fresh()->eu_hosted)->toBeFalse();
});
test('moderator can untick a badge on an approved product', function () {
$moderator = userWithRole('moderator');
$product = Product::factory()->approved()->create(['eu_hosted' => true]);
$this->actingAs($moderator)->put(route('products.update', $product), badgePayload([
'category_id' => $product->category_id,
]))->assertRedirect();
expect($product->fresh()->eu_hosted)->toBeFalse();
});
test('edit form shows badges read-only to owner of approved product', function () {
$user = userWithRole('user');
$approved = Product::factory()->approved()->create(['user_id' => $user->id]);
$pending = Product::factory()->pending()->create(['user_id' => $user->id]);
$this->actingAs($user)->get(route('products.edit', $approved))
->assertOk()
->assertSee('EU hosted')
->assertSee('disabled')
->assertSee('Locked after approval');
$this->actingAs($user)->get(route('products.edit', $pending))
->assertOk()
->assertSee('EU hosted')
->assertDontSee('disabled')
->assertDontSee('Locked after approval');
});
test('show page lists ticked badges only', function () {
$product = Product::factory()->approved()->create(['eu_hosted' => true]);
$this->get(route('products.show', $product))
->assertOk()
->assertSee('EU hosted')
->assertDontSee('EU made');
});
test('existing product without new data still renders', function () {
$product = Product::factory()->approved()->create();
$this->get(route('products.show', $product))->assertOk();
});
+24
View File
@@ -45,3 +45,27 @@ function something()
{
// ..
}
function userWithRole(string $slug): \App\Models\User
{
$role = \App\Models\Role::firstOrCreate(
['slug' => $slug],
['name' => ucfirst($slug), 'description' => ucfirst($slug)]
);
$user = \App\Models\User::factory()->create();
$user->roles()->attach($role);
return $user;
}
function makeCategory(): \App\Models\Category
{
$name = 'Category ' . \Illuminate\Support\Str::random(8);
return \App\Models\Category::create([
'name' => $name,
'slug' => \Illuminate\Support\Str::slug($name),
'description' => 'Test description',
]);
}