151 lines
5.5 KiB
PHP
151 lines
5.5 KiB
PHP
<?php
|
|
|
|
use App\Models\Product;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
function teamPayload(array $overrides = []): array
|
|
{
|
|
return array_merge([
|
|
'title' => 'Team Product',
|
|
'description' => 'A product description',
|
|
'website_url' => 'https://example.com',
|
|
'category_id' => makeCategory()->id,
|
|
], $overrides);
|
|
}
|
|
|
|
test('user search returns matching users, requires auth', function () {
|
|
$this->getJson(route('users.search', ['q' => 'ali']))->assertUnauthorized();
|
|
|
|
$viewer = userWithRole('user');
|
|
$alice = User::factory()->create(['name' => 'Alice Wonder']);
|
|
User::factory()->create(['name' => 'Bob Builder']);
|
|
|
|
$response = $this->actingAs($viewer)->getJson(route('users.search', ['q' => 'lic']))->assertOk();
|
|
|
|
expect($response->json())->toHaveCount(1);
|
|
expect($response->json(0))->toBe(['id' => $alice->id, 'name' => 'Alice Wonder', 'slug' => $alice->slug]);
|
|
});
|
|
|
|
test('user search returns empty for one character queries', function () {
|
|
$viewer = userWithRole('user');
|
|
User::factory()->create(['name' => 'Alice Wonder']);
|
|
|
|
$this->actingAs($viewer)->getJson(route('users.search', ['q' => 'a']))->assertOk()->assertExactJson([]);
|
|
});
|
|
|
|
test('submitter adds members with roles', function () {
|
|
$user = userWithRole('user');
|
|
$a = User::factory()->create();
|
|
$b = User::factory()->create();
|
|
|
|
$this->actingAs($user)->post(route('products.store'), teamPayload([
|
|
'members' => [
|
|
['user_id' => $a->id, 'role' => 'Designer'],
|
|
['user_id' => $b->id, 'role' => 'Engineer'],
|
|
],
|
|
]))->assertRedirect()->assertSessionHasNoErrors();
|
|
|
|
$members = Product::firstOrFail()->members;
|
|
expect($members->pluck('id')->all())->toEqualCanonicalizing([$a->id, $b->id]);
|
|
expect($members->firstWhere('id', $a->id)->pivot->role)->toBe('Designer');
|
|
});
|
|
|
|
test('update replaces members and uses the product owner for the owner rule', function () {
|
|
$owner = userWithRole('user');
|
|
$admin = userWithRole('admin');
|
|
$a = User::factory()->create();
|
|
$b = User::factory()->create();
|
|
$product = Product::factory()->pending()->create(['user_id' => $owner->id]);
|
|
$product->members()->attach($a->id, ['role' => 'Old']);
|
|
|
|
$this->actingAs($admin)->put(route('products.update', $product), teamPayload([
|
|
'category_id' => $product->category_id,
|
|
'members' => [['user_id' => $owner->id, 'role' => 'Founder']],
|
|
]))->assertSessionHasErrors('members.0.user_id');
|
|
expect($product->members()->pluck('users.id')->all())->toBe([$a->id]);
|
|
|
|
$this->actingAs($admin)->put(route('products.update', $product), teamPayload([
|
|
'category_id' => $product->category_id,
|
|
'members' => [['user_id' => $admin->id, 'role' => 'Helper'], ['user_id' => $b->id, 'role' => 'New']],
|
|
]))->assertRedirect()->assertSessionHasNoErrors();
|
|
expect($product->members()->pluck('users.id')->all())->toEqualCanonicalizing([$admin->id, $b->id]);
|
|
});
|
|
|
|
test('submitter cannot be added as a member', function () {
|
|
$user = userWithRole('user');
|
|
|
|
$this->actingAs($user)->post(route('products.store'), teamPayload([
|
|
'members' => [['user_id' => $user->id, 'role' => 'Founder']],
|
|
]))->assertSessionHasErrors('members.0.user_id');
|
|
|
|
expect(Product::count())->toBe(0);
|
|
});
|
|
|
|
test('same user cannot be added twice', function () {
|
|
$user = userWithRole('user');
|
|
$a = User::factory()->create();
|
|
|
|
$this->actingAs($user)->post(route('products.store'), teamPayload([
|
|
'members' => [
|
|
['user_id' => $a->id, 'role' => 'One'],
|
|
['user_id' => $a->id, 'role' => 'Two'],
|
|
],
|
|
]))->assertSessionHasErrors();
|
|
|
|
expect(Product::count())->toBe(0);
|
|
expect(\DB::table('product_members')->count())->toBe(0);
|
|
});
|
|
|
|
test('unknown user id fails validation', function () {
|
|
$user = userWithRole('user');
|
|
|
|
$this->actingAs($user)->post(route('products.store'), teamPayload([
|
|
'members' => [['user_id' => 999999, 'role' => 'Ghost']],
|
|
]))->assertSessionHasErrors('members.0.user_id');
|
|
|
|
expect(Product::count())->toBe(0);
|
|
});
|
|
|
|
test('missing role fails validation', function () {
|
|
$user = userWithRole('user');
|
|
$a = User::factory()->create();
|
|
|
|
$this->actingAs($user)->post(route('products.store'), teamPayload([
|
|
'members' => [['user_id' => $a->id, 'role' => '']],
|
|
]))->assertSessionHasErrors('members.0.role');
|
|
|
|
expect(Product::count())->toBe(0);
|
|
});
|
|
|
|
test('deleting a user removes their membership', function () {
|
|
$product = Product::factory()->approved()->create();
|
|
$member = User::factory()->create();
|
|
$product->members()->attach($member->id, ['role' => 'Dev']);
|
|
|
|
$member->delete();
|
|
|
|
expect(\DB::table('product_members')->count())->toBe(0);
|
|
expect(Product::find($product->id))->not->toBeNull();
|
|
});
|
|
|
|
test('show page lists submitter first as Author then members linking to profiles', function () {
|
|
$product = Product::factory()->approved()->create();
|
|
$member = User::factory()->create(['name' => 'Zed Member']);
|
|
$product->members()->attach($member->id, ['role' => 'Designer']);
|
|
|
|
$this->get(route('products.show', $product))->assertOk()
|
|
->assertSeeInOrder([$product->user->name, 'Author', 'Zed Member', 'Designer'])
|
|
->assertSee(route('profile.show', $member), false);
|
|
});
|
|
|
|
test('no members shows only the submitter as author', function () {
|
|
$product = Product::factory()->approved()->create();
|
|
|
|
$this->get(route('products.show', $product))->assertOk()
|
|
->assertSee('Author')
|
|
->assertDontSee('data-team-members', false);
|
|
});
|