'https://test-jira.example.com', 'jira.username' => 'test-user', 'jira.password' => 'test-password', 'jira.default_user' => 'test-user', ]); $this->jiraService = app(JiraService::class); } protected function tearDown(): void { Carbon::setTestNow(); parent::tearDown(); } public function test_is_task_completed_returns_false_for_incomplete_statuses() { $reflection = new \ReflectionClass($this->jiraService); $method = $reflection->getMethod('isTaskCompleted'); // 测试不完成的状态 $incompleteStatuses = [ '开发中', '需求已排期', '需求已评审', 'In Progress', 'To Do', 'Open', ]; foreach ($incompleteStatuses as $status) { $this->assertFalse( $method->invoke($this->jiraService, $status), "状态 '{$status}' 应该返回 false" ); } } public function test_is_task_completed_returns_true_for_complete_statuses() { $reflection = new \ReflectionClass($this->jiraService); $method = $reflection->getMethod('isTaskCompleted'); // 测试完成的状态 $completeStatuses = [ 'Done', 'Closed', 'Resolved', '已完成', 'Complete', ]; foreach ($completeStatuses as $status) { $this->assertTrue( $method->invoke($this->jiraService, $status), "状态 '{$status}' 应该返回 true" ); } } public function test_organize_tasks_for_report_handles_empty_collection() { $reflection = new \ReflectionClass($this->jiraService); $method = $reflection->getMethod('organizeTasksForReport'); $emptyWorkLogs = collect(); $result = $method->invoke($this->jiraService, $emptyWorkLogs, 'test-user'); $this->assertInstanceOf(Collection::class, $result); $this->assertTrue($result->has('sprints')); $this->assertTrue($result->has('stories')); $this->assertTrue($result->has('tasks')); $this->assertTrue($result->has('bugs')); } public function test_organize_tasks_for_report_categorizes_by_sprint() { $reflection = new \ReflectionClass($this->jiraService); $method = $reflection->getMethod('organizeTasksForReport'); $workLogs = collect([ [ 'issue_key' => 'WP-1234', 'issue_summary' => '测试需求', 'issue_url' => 'https://test-jira.example.com/browse/WP-1234', 'issue_status' => 'Done', 'issue_type' => 'Story', 'sprint' => '十月中需求', 'bug_stage' => null, 'bug_type' => null, 'parent_task' => null, ], ]); $result = $method->invoke($this->jiraService, $workLogs, 'test-user'); $this->assertTrue($result['sprints']->has('十月中需求')); $this->assertCount(1, $result['sprints']['十月中需求']); } public function test_organize_tasks_for_report_categorizes_bugs_by_stage() { $reflection = new \ReflectionClass($this->jiraService); $method = $reflection->getMethod('organizeTasksForReport'); $workLogs = collect([ [ 'issue_key' => 'WP-5678', 'issue_summary' => '测试Bug', 'issue_url' => 'https://test-jira.example.com/browse/WP-5678', 'issue_status' => 'Done', 'issue_type' => 'Bug', 'sprint' => null, 'bug_stage' => 'SIT环境BUG', 'bug_type' => '需求未说明', 'bug_description' => null, 'parent_task' => null, 'assignee' => 'test-user', 'developer' => null, 'actual_fixer' => null, ], ]); $result = $method->invoke($this->jiraService, $workLogs, 'test-user'); $this->assertTrue($result['bugs']->has('SIT环境BUG')); $this->assertCount(1, $result['bugs']['SIT环境BUG']); $this->assertEquals('需求未说明', $result['bugs']['SIT环境BUG'][0]['bug_type']); } public function test_resolve_weekly_report_range_for_last_week() { Carbon::setTestNow('2026-04-02 10:00:00'); $reflection = new \ReflectionClass($this->jiraService); $method = $reflection->getMethod('resolveWeeklyReportRange'); $result = $method->invoke($this->jiraService, 'last_week'); $this->assertEquals('2026-03-23 00:00:00', $result['start']->format('Y-m-d H:i:s')); $this->assertEquals('2026-03-29 23:59:59', $result['end']->format('Y-m-d H:i:s')); $this->assertEquals('上周完成的任务', $result['title']); } public function test_resolve_weekly_report_range_for_this_week() { Carbon::setTestNow('2026-04-02 10:00:00'); $reflection = new \ReflectionClass($this->jiraService); $method = $reflection->getMethod('resolveWeeklyReportRange'); $result = $method->invoke($this->jiraService, 'this_week'); $this->assertEquals('2026-03-30 00:00:00', $result['start']->format('Y-m-d H:i:s')); $this->assertEquals('2026-04-02 23:59:59', $result['end']->format('Y-m-d H:i:s')); $this->assertEquals('本周完成的任务', $result['title']); } public function test_extract_sprint_info_from_string() { $reflection = new \ReflectionClass($this->jiraService); $method = $reflection->getMethod('extractSprintInfo'); $issue = (object) [ 'fields' => (object) [ 'customFields' => [ 'customfield_10004' => [ 'com.atlassian.greenhopper.service.sprint.Sprint@xxx[name=十月中需求,state=ACTIVE]', ], ], ], ]; $result = $method->invoke($this->jiraService, $issue); $this->assertEquals('十月中需求', $result); } public function test_extract_bug_stage_from_labels() { $reflection = new \ReflectionClass($this->jiraService); $method = $reflection->getMethod('extractBugStage'); $issue = (object) [ 'fields' => (object) [ 'labels' => ['SIT', 'bug'], ], ]; $result = $method->invoke($this->jiraService, $issue); $this->assertEquals('SIT环境BUG', $result); } public function test_extract_bug_type_from_labels() { $reflection = new \ReflectionClass($this->jiraService); $method = $reflection->getMethod('extractBugType'); $issue = (object) [ 'fields' => (object) [ 'labels' => ['需求未说明', 'bug'], ], ]; $result = $method->invoke($this->jiraService, $issue); $this->assertEquals('需求未说明', $result); } public function test_extract_developer_from_user_object() { $reflection = new \ReflectionClass($this->jiraService); $method = $reflection->getMethod('extractDeveloper'); $issue = (object) [ 'fields' => (object) [ 'customFields' => [ 'customfield_11000' => (object) [ 'name' => 'zhangsan', 'displayName' => '张三', 'emailAddress' => 'zhangsan@example.com', ], ], ], ]; $this->assertEquals('zhangsan', $method->invoke($this->jiraService, $issue)); } public function test_extract_developer_from_associative_array() { $reflection = new \ReflectionClass($this->jiraService); $method = $reflection->getMethod('extractDeveloper'); $issue = (object) [ 'fields' => (object) [ 'customFields' => [ 'customfield_11000' => [ 'name' => 'lisi', 'displayName' => '李四', ], ], ], ]; $this->assertEquals('lisi', $method->invoke($this->jiraService, $issue)); } public function test_extract_actual_fixer_from_user_object() { $reflection = new \ReflectionClass($this->jiraService); $method = $reflection->getMethod('extractActualFixer'); $issue = (object) [ 'fields' => (object) [ 'customFields' => [ 'customfield_11301' => (object) [ 'name' => 'wangwu', 'displayName' => '王五', ], ], ], ]; $this->assertEquals('wangwu', $method->invoke($this->jiraService, $issue)); } public function test_extract_developer_returns_null_when_field_missing() { $reflection = new \ReflectionClass($this->jiraService); $method = $reflection->getMethod('extractDeveloper'); $issue = (object) [ 'fields' => (object) [ 'customFields' => [], ], ]; $this->assertNull($method->invoke($this->jiraService, $issue)); } public function test_organize_tasks_for_report_includes_bug_when_user_is_developer_only() { $reflection = new \ReflectionClass($this->jiraService); $method = $reflection->getMethod('organizeTasksForReport'); // 模拟 WP-7158 场景:经办人是测试同学,开发人才是当前用户 $workLogs = collect([ [ 'issue_key' => 'WP-7158', 'issue_summary' => '生产 Bug 修复', 'issue_url' => 'https://test-jira.example.com/browse/WP-7158', 'issue_status' => 'Done', 'issue_type' => 'Bug', 'sprint' => null, 'bug_stage' => '生产环境BUG', 'bug_type' => '代码错误', 'bug_description' => null, 'parent_task' => null, 'assignee' => 'tester-user', 'developer' => 'test-user', 'actual_fixer' => null, ], ]); $result = $method->invoke($this->jiraService, $workLogs, 'test-user'); $this->assertTrue($result['bugs']->has('生产环境BUG')); $this->assertCount(1, $result['bugs']['生产环境BUG']); $this->assertEquals('WP-7158', $result['bugs']['生产环境BUG'][0]['key']); } }