305 lines
8.3 KiB
PHP
305 lines
8.3 KiB
PHP
<?php
|
|
|
|
use App\Enums\TeamRole;
|
|
use App\Models\Team;
|
|
use App\Models\User;
|
|
|
|
test('the teams index page can be rendered', function () {
|
|
$user = User::factory()->create();
|
|
|
|
$response = $this
|
|
->actingAs($user)
|
|
->get(route('teams.index'));
|
|
|
|
$response->assertOk();
|
|
});
|
|
|
|
test('teams can be created', function () {
|
|
$user = User::factory()->create();
|
|
|
|
$response = $this
|
|
->actingAs($user)
|
|
->post(route('teams.store'), [
|
|
'name' => 'Test Team',
|
|
]);
|
|
|
|
$response->assertRedirect();
|
|
|
|
$this->assertDatabaseHas('teams', [
|
|
'name' => 'Test Team',
|
|
'is_personal' => false,
|
|
]);
|
|
});
|
|
|
|
test('team slug uses next available suffix', function () {
|
|
$user = User::factory()->create();
|
|
|
|
Team::factory()->create(['name' => 'Acme', 'slug' => 'acme']);
|
|
Team::factory()->create(['name' => 'Acme One', 'slug' => 'acme-1']);
|
|
Team::factory()->create(['name' => 'Acme Ten', 'slug' => 'acme-10']);
|
|
|
|
$this
|
|
->actingAs($user)
|
|
->post(route('teams.store'), [
|
|
'name' => 'Acme',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('teams', [
|
|
'name' => 'Acme',
|
|
'slug' => 'acme-11',
|
|
]);
|
|
});
|
|
|
|
test('the team edit page can be rendered', function () {
|
|
$user = User::factory()->create();
|
|
$team = Team::factory()->create();
|
|
|
|
$team->members()->attach($user, ['role' => TeamRole::Owner->value]);
|
|
|
|
$response = $this
|
|
->actingAs($user)
|
|
->get(route('teams.edit', $team));
|
|
|
|
$response->assertOk();
|
|
});
|
|
|
|
test('teams can be updated by owners', function () {
|
|
$user = User::factory()->create();
|
|
$team = Team::factory()->create(['name' => 'Original Name']);
|
|
|
|
$team->members()->attach($user, ['role' => TeamRole::Owner->value]);
|
|
|
|
$response = $this
|
|
->actingAs($user)
|
|
->patch(route('teams.update', $team), [
|
|
'name' => 'Updated Name',
|
|
]);
|
|
|
|
$response->assertRedirect(route('teams.edit', $team->fresh()));
|
|
|
|
$this->assertDatabaseHas('teams', [
|
|
'id' => $team->id,
|
|
'name' => 'Updated Name',
|
|
]);
|
|
});
|
|
|
|
test('teams cannot be updated by members', function () {
|
|
$owner = User::factory()->create();
|
|
$member = User::factory()->create();
|
|
$team = Team::factory()->create();
|
|
|
|
$team->members()->attach($owner, ['role' => TeamRole::Owner->value]);
|
|
$team->members()->attach($member, ['role' => TeamRole::Member->value]);
|
|
|
|
$response = $this
|
|
->actingAs($member)
|
|
->patch(route('teams.update', $team), [
|
|
'name' => 'Updated Name',
|
|
]);
|
|
|
|
$response->assertForbidden();
|
|
});
|
|
|
|
test('teams can be deleted by owners', function () {
|
|
$user = User::factory()->create();
|
|
$team = Team::factory()->create();
|
|
|
|
$team->members()->attach($user, ['role' => TeamRole::Owner->value]);
|
|
|
|
$response = $this
|
|
->actingAs($user)
|
|
->delete(route('teams.destroy', $team), [
|
|
'name' => $team->name,
|
|
]);
|
|
|
|
$response->assertRedirect();
|
|
|
|
$this->assertSoftDeleted('teams', [
|
|
'id' => $team->id,
|
|
]);
|
|
});
|
|
|
|
test('team deletion requires name confirmation', function () {
|
|
$user = User::factory()->create();
|
|
$team = Team::factory()->create();
|
|
|
|
$team->members()->attach($user, ['role' => TeamRole::Owner->value]);
|
|
|
|
$response = $this
|
|
->actingAs($user)
|
|
->delete(route('teams.destroy', $team), [
|
|
'name' => 'Wrong Name',
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('name');
|
|
|
|
$this->assertDatabaseHas('teams', [
|
|
'id' => $team->id,
|
|
'deleted_at' => null,
|
|
]);
|
|
});
|
|
|
|
test('deleting current team switches to alphabetically first remaining team', function () {
|
|
$user = User::factory()->create(['name' => 'Mike']);
|
|
|
|
$zuluTeam = Team::factory()->create(['name' => 'Zulu Team']);
|
|
$zuluTeam->members()->attach($user, ['role' => TeamRole::Owner->value]);
|
|
|
|
$alphaTeam = Team::factory()->create(['name' => 'Alpha Team']);
|
|
$alphaTeam->members()->attach($user, ['role' => TeamRole::Owner->value]);
|
|
|
|
$betaTeam = Team::factory()->create(['name' => 'Beta Team']);
|
|
$betaTeam->members()->attach($user, ['role' => TeamRole::Owner->value]);
|
|
|
|
$user->update(['current_team_id' => $zuluTeam->id]);
|
|
|
|
$response = $this
|
|
->actingAs($user)
|
|
->delete(route('teams.destroy', $zuluTeam), [
|
|
'name' => $zuluTeam->name,
|
|
]);
|
|
|
|
$response->assertRedirect();
|
|
|
|
$this->assertSoftDeleted('teams', [
|
|
'id' => $zuluTeam->id,
|
|
]);
|
|
|
|
expect($user->fresh()->current_team_id)->toEqual($alphaTeam->id);
|
|
});
|
|
|
|
test('deleting current team falls back to personal team when alphabetically first', function () {
|
|
$user = User::factory()->create();
|
|
$personalTeam = $user->personalTeam();
|
|
$team = Team::factory()->create(['name' => 'Zulu Team']);
|
|
$team->members()->attach($user, ['role' => TeamRole::Owner->value]);
|
|
|
|
$user->update(['current_team_id' => $team->id]);
|
|
|
|
$response = $this
|
|
->actingAs($user)
|
|
->delete(route('teams.destroy', $team), [
|
|
'name' => $team->name,
|
|
]);
|
|
|
|
$response->assertRedirect();
|
|
|
|
$this->assertSoftDeleted('teams', [
|
|
'id' => $team->id,
|
|
]);
|
|
|
|
expect($user->fresh()->current_team_id)->toEqual($personalTeam->id);
|
|
});
|
|
|
|
test('deleting non current team leaves current team unchanged', function () {
|
|
$user = User::factory()->create();
|
|
$personalTeam = $user->personalTeam();
|
|
$team = Team::factory()->create();
|
|
$team->members()->attach($user, ['role' => TeamRole::Owner->value]);
|
|
|
|
$user->update(['current_team_id' => $personalTeam->id]);
|
|
|
|
$response = $this
|
|
->actingAs($user)
|
|
->delete(route('teams.destroy', $team), [
|
|
'name' => $team->name,
|
|
]);
|
|
|
|
$response->assertRedirect();
|
|
|
|
$this->assertSoftDeleted('teams', [
|
|
'id' => $team->id,
|
|
]);
|
|
|
|
expect($user->fresh()->current_team_id)->toEqual($personalTeam->id);
|
|
});
|
|
|
|
test('deleting team switches other affected users to their personal team', function () {
|
|
$owner = User::factory()->create();
|
|
$member = User::factory()->create();
|
|
|
|
$team = Team::factory()->create();
|
|
$team->members()->attach($owner, ['role' => TeamRole::Owner->value]);
|
|
$team->members()->attach($member, ['role' => TeamRole::Member->value]);
|
|
|
|
$owner->update(['current_team_id' => $team->id]);
|
|
$member->update(['current_team_id' => $team->id]);
|
|
|
|
$response = $this
|
|
->actingAs($owner)
|
|
->delete(route('teams.destroy', $team), [
|
|
'name' => $team->name,
|
|
]);
|
|
|
|
$response->assertRedirect();
|
|
|
|
expect($member->fresh()->current_team_id)->toEqual($member->personalTeam()->id);
|
|
});
|
|
|
|
test('personal teams cannot be deleted', function () {
|
|
$user = User::factory()->create();
|
|
|
|
$personalTeam = $user->personalTeam();
|
|
|
|
$response = $this
|
|
->actingAs($user)
|
|
->delete(route('teams.destroy', $personalTeam), [
|
|
'name' => $personalTeam->name,
|
|
]);
|
|
|
|
$response->assertForbidden();
|
|
|
|
$this->assertDatabaseHas('teams', [
|
|
'id' => $personalTeam->id,
|
|
'deleted_at' => null,
|
|
]);
|
|
});
|
|
|
|
test('teams cannot be deleted by non owners', function () {
|
|
$owner = User::factory()->create();
|
|
$member = User::factory()->create();
|
|
$team = Team::factory()->create();
|
|
|
|
$team->members()->attach($owner, ['role' => TeamRole::Owner->value]);
|
|
$team->members()->attach($member, ['role' => TeamRole::Member->value]);
|
|
|
|
$response = $this
|
|
->actingAs($member)
|
|
->delete(route('teams.destroy', $team), [
|
|
'name' => $team->name,
|
|
]);
|
|
|
|
$response->assertForbidden();
|
|
});
|
|
|
|
test('users can switch teams', function () {
|
|
$user = User::factory()->create();
|
|
$team = Team::factory()->create();
|
|
|
|
$team->members()->attach($user, ['role' => TeamRole::Member->value]);
|
|
|
|
$response = $this
|
|
->actingAs($user)
|
|
->post(route('teams.switch', $team));
|
|
|
|
$response->assertRedirect();
|
|
|
|
expect($user->fresh()->current_team_id)->toEqual($team->id);
|
|
});
|
|
|
|
test('users cannot switch to team they dont belong to', function () {
|
|
$user = User::factory()->create();
|
|
$team = Team::factory()->create();
|
|
|
|
$response = $this
|
|
->actingAs($user)
|
|
->post(route('teams.switch', $team));
|
|
|
|
$response->assertForbidden();
|
|
});
|
|
|
|
test('guests cannot access teams', function () {
|
|
$response = $this->get(route('teams.index'));
|
|
|
|
$response->assertRedirect(route('login'));
|
|
}); |