create(); $project = Project::factory()->create([ 'name' => 'Core Platform', 'key' => 'CORE', ]); $template = ProjectTemplate::factory()->create([ 'name' => 'Foundation Template', 'slug' => 'foundation-template', 'source_project_id' => $project->id, ]); $this->syncGlobalPermissions($user, ['project:create']); $this->syncProjectPermissions($project, $user, ['view']); $this->actingAs($user) ->get('/project-templates') ->assertOk() ->assertInertia(fn (Assert $page) => $page ->component('project-templates/Index') ->has('templates', 1) ->where('templates.0.id', $template->id) ->where('templates.0.slug', 'foundation-template')); $this->actingAs($user) ->get(route('projects.templates.create', $project)) ->assertOk() ->assertInertia(fn (Assert $page) => $page ->component('project-templates/Create') ->where('project.id', $project->id) ->has('copyAreaOptions', count(DuplicateProjectConfiguration::copyableAreas()))); } public function test_users_can_save_and_delete_templates_from_projects(): void { $user = User::factory()->create(); $project = Project::factory()->create([ 'name' => 'Source Project', 'key' => 'SRC1', 'show_author' => false, 'show_story_points' => false, ]); $this->syncGlobalPermissions($user, ['project:create']); $this->syncProjectPermissions($project, $user, ['view']); $project->ticketTypes()->delete(); $project->ticketStatuses()->delete(); $project->boardColumns()->delete(); $boardColumn = BoardColumn::factory()->create([ 'project_id' => $project->id, 'name' => 'Doing', 'position' => 1, ]); $ticketStatus = TicketStatus::factory()->create([ 'project_id' => $project->id, 'board_column_id' => $boardColumn->id, 'name' => 'Doing', 'position' => 1, ]); $ticketStatus->allowedTargetStatuses()->sync([$ticketStatus->id]); TicketType::factory()->create([ 'project_id' => $project->id, 'name' => 'Bug', 'position' => 1, ]); $this->actingAs($user) ->post(route('projects.templates.store', $project), [ 'name' => 'Core Reusable', 'slug' => 'core-reusable', 'copy_areas' => [ DuplicateProjectConfiguration::COPY_PROJECT_SETTINGS, DuplicateProjectConfiguration::COPY_TICKET_TYPES, ], ]) ->assertRedirect('/project-templates'); $template = ProjectTemplate::query()->where('slug', 'core-reusable')->firstOrFail(); $this->assertSame([ DuplicateProjectConfiguration::COPY_PROJECT_SETTINGS => [ 'show_author' => false, 'show_story_points' => false, ], DuplicateProjectConfiguration::COPY_TICKET_TYPES => [ [ 'name' => 'Bug', 'position' => 1, 'is_parent' => false, ], ], ], $template->configuration_snapshot); $this->actingAs($user) ->delete(route('project-templates.destroy', $template)) ->assertRedirect('/project-templates'); $this->assertDatabaseMissing('project_templates', [ 'id' => $template->id, ]); } }