feat(KAN-23): rebuild project overview and entry pages
CI/CD / test_and_check_app (push) Canceled after 0s
CI/CD / Publish immutable image (push) Canceled after 0s
CI/CD / test_and_check_app (pull_request) Canceled after 0s
CI/CD / Publish immutable image (pull_request) Canceled after 0s

This commit is contained in:
2026-09-11 14:19:07 +02:00
parent 17caabbb3e
commit 0e78be0eae
7 changed files with 915 additions and 242 deletions
@@ -0,0 +1,84 @@
<?php
namespace Tests\Feature\Projects;
use App\Models\Project;
use App\Models\Team;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Inertia\Testing\AssertableInertia as Assert;
use PHPUnit\Framework\Attributes\DataProvider;
use Symfony\Component\Process\Process;
use Tests\TestCase;
class ProjectOverviewTest extends TestCase
{
use RefreshDatabase;
public function test_projects_without_access_do_not_appear_in_the_empty_overview(): void
{
$user = User::factory()->create();
Project::factory()->create(['name' => 'Private workspace']);
$this->actingAs($user)->get(route('projects.index'))
->assertOk()->assertInertia(fn (Assert $page) => $page
->component('projects/Index')
->has('projects', 0)
->where('auth.permissions.projectCreate', false));
$this->syncGlobalPermissions($user, ['project:create']);
$this->get(route('projects.index'))
->assertOk()->assertInertia(fn (Assert $page) => $page
->has('projects', 0)
->where('auth.permissions.projectCreate', true));
}
#[DataProvider('projectRoles')]
public function test_project_entry_actions_follow_effective_permissions(string $role, bool $teamAccess, bool $canManage): void
{
$user = User::factory()->create();
$project = Project::factory()->create();
$assignee = $user;
if ($teamAccess) {
$assignee = Team::factory()->create();
$assignee->users()->attach($user);
}
$this->syncProjectPermissions($project, $assignee, [$role]);
$this->actingAs($user)->get(route('projects.show', $project))
->assertOk()->assertInertia(fn (Assert $page) => $page
->component('projects/Show')
->where('project.id', $project->id)
->where('canManageAccess', $canManage)
->where('auth.permissions.projectCreate', false));
foreach (['projects.board.index', 'projects.backlog.index'] as $route) {
$this->get(route($route, $project))->assertOk();
}
foreach (['projects.settings.general', 'projects.settings.board', 'projects.settings.metadata', 'projects.settings.repositories', 'projects.settings.notifications', 'projects.access'] as $route) {
$this->get(route($route, $project))->assertStatus($canManage ? 200 : 403);
}
}
/** @return array<string, array{string, bool, bool}> */
public static function projectRoles(): array
{
return [
'reader' => ['read', false, false],
'writer' => ['write', false, false],
'project admin' => ['admin', false, true],
'team reader' => ['read', true, false],
'team admin' => ['admin', true, true],
];
}
public function test_project_overview_rendering_and_actions(): void
{
$process = new Process(['node', 'tests/Fixtures/project-overview.mjs'], base_path());
$process->setTimeout(60);
$process->run();
$this->assertTrue($process->isSuccessful(), $process->getOutput().$process->getErrorOutput());
$this->assertStringContainsString('Project overview behavior checks passed.', $process->getOutput());
}
}