user = User::factory()->create(); $this->actingAs($this->user); }); test('可以创建 SOP 模板', function () { $template = SopTemplate::factory()->create([ 'name' => '测试模板', 'status' => 'draft', 'created_by' => $this->user->id, ]); expect($template->name)->toBe('测试模板') ->and($template->status)->toBe('draft') ->and($template->created_by)->toBe($this->user->id); }); test('可以为模板添加步骤', function () { $template = SopTemplate::factory()->create(); $step = $template->steps()->create([ 'step_number' => 1, 'title' => '第一步', 'content' => '这是第一步的内容', 'sort_order' => 1, 'is_required' => true, ]); expect($template->steps)->toHaveCount(1) ->and($step->title)->toBe('第一步') ->and($step->template->id)->toBe($template->id); }); test('步骤按 sort_order 排序', function () { $template = SopTemplate::factory()->create(); $template->steps()->create([ 'step_number' => 3, 'title' => '第三步', 'sort_order' => 3, ]); $template->steps()->create([ 'step_number' => 1, 'title' => '第一步', 'sort_order' => 1, ]); $template->steps()->create([ 'step_number' => 2, 'title' => '第二步', 'sort_order' => 2, ]); $steps = $template->fresh()->steps; expect($steps)->toHaveCount(3) ->and($steps->first()->title)->toBe('第一步') ->and($steps->last()->title)->toBe('第三步'); }); test('可以为步骤添加交互任务', function () { $template = SopTemplate::factory()->create(); $step = $template->steps()->create([ 'step_number' => 1, 'title' => '第一步', 'sort_order' => 1, ]); $task = $step->interactiveTasks()->create([ 'task_type' => 'confirm', 'task_config' => ['message' => '确认完成?'], 'validation_rules' => [], 'is_required' => true, ]); expect($step->interactiveTasks)->toHaveCount(1) ->and($task->task_type)->toBe('confirm') ->and($task->step->id)->toBe($step->id); }); test('模板状态可以从草稿变为已发布', function () { $template = SopTemplate::factory()->create([ 'status' => 'draft', ]); $template->update([ 'status' => 'published', 'published_at' => now(), ]); expect($template->fresh()->status)->toBe('published') ->and($template->fresh()->published_at)->not->toBeNull(); }); test('模板状态可以从已发布变为已归档', function () { $template = SopTemplate::factory()->create([ 'status' => 'published', 'published_at' => now(), ]); $template->update(['status' => 'archived']); expect($template->fresh()->status)->toBe('archived'); }); test('可以创建模板版本快照', function () { $template = SopTemplate::factory()->create(); $template->steps()->create([ 'step_number' => 1, 'title' => '第一步', 'sort_order' => 1, ]); $version = $template->versions()->create([ 'version' => '1.0.0', 'change_log' => '首次发布', 'content_snapshot' => [ 'template' => $template->toArray(), 'steps' => $template->steps->toArray(), ], 'created_by' => $this->user->id, 'created_at' => now(), ]); expect($template->versions)->toHaveCount(1) ->and($version->version)->toBe('1.0.0') ->and($version->content_snapshot)->toHaveKey('template') ->and($version->content_snapshot)->toHaveKey('steps'); }); test('模板记录活动日志', function () { $template = SopTemplate::factory()->create([ 'name' => '原始名称', ]); $template->update(['name' => '新名称']); $activities = $template->activities; expect($activities)->toHaveCount(2) // created 和 updated ->and($activities->last()->description)->toContain('updated'); }); test('可以通过分类筛选模板', function () { SopTemplate::factory()->create(['category' => '安全操作']); SopTemplate::factory()->create(['category' => '设备维护']); SopTemplate::factory()->create(['category' => '安全操作']); $safetyTemplates = SopTemplate::where('category', '安全操作')->get(); expect($safetyTemplates)->toHaveCount(2); }); test('可以通过状态筛选模板', function () { SopTemplate::factory()->create(['status' => 'draft']); SopTemplate::factory()->create(['status' => 'published']); SopTemplate::factory()->create(['status' => 'draft']); $draftTemplates = SopTemplate::where('status', 'draft')->get(); expect($draftTemplates)->toHaveCount(2); }); test('模板的标签字段正确转换为数组', function () { $template = SopTemplate::factory()->create([ 'tags' => ['标签1', '标签2', '标签3'], ]); expect($template->fresh()->tags)->toBeArray() ->and($template->fresh()->tags)->toHaveCount(3) ->and($template->fresh()->tags)->toContain('标签1'); }); test('模板的适用部门字段正确转换为数组', function () { $template = SopTemplate::factory()->create([ 'applicable_departments' => ['生产部', '质检部'], ]); expect($template->fresh()->applicable_departments)->toBeArray() ->and($template->fresh()->applicable_departments)->toHaveCount(2); }); test('可以软删除模板', function () { $template = SopTemplate::factory()->create(); $templateId = $template->id; $template->delete(); expect(SopTemplate::find($templateId))->toBeNull() ->and(SopTemplate::withTrashed()->find($templateId))->not->toBeNull(); });