Skip to content

Commit 5534228

Browse files
committed
feat: #10 create issue
1 parent ea4eade commit 5534228

File tree

3 files changed

+320
-0
lines changed

3 files changed

+320
-0
lines changed

src/Issue.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
namespace Coding;
4+
5+
use Illuminate\Validation\Rule;
6+
7+
class Issue extends Base
8+
{
9+
public const TYPE = ['DEFECT', 'REQUIREMENT', 'MISSION', 'EPIC', 'SUB_TASK'];
10+
public const PRIORITY = [
11+
'' => '0',
12+
'' => '1',
13+
'' => '2',
14+
'紧急' => '3',
15+
];
16+
17+
public function create(array $data)
18+
{
19+
$this->validate($data, [
20+
'ProjectName' => 'string|required',
21+
'Name' => 'string|required',
22+
'Priority' => [
23+
'string',
24+
'required',
25+
Rule::in(array_values(self::PRIORITY)),
26+
],
27+
'Type' => [
28+
'required',
29+
Rule::in(self::TYPE),
30+
],
31+
// 事项类型 ID,比如「用户故事」属于「需求」,必须指定此 ID,而「缺陷」就一种,不需要
32+
'IssueTypeId' => 'nullable|integer',
33+
'ParentCode' => 'nullable|integer',
34+
'StatusId' => 'nullable|integer',
35+
'AssigneeId' => 'nullable|integer',
36+
'Description' => 'nullable|string',
37+
'StartDate' => 'nullable|date_format:Y-m-d',
38+
'DueDate' => 'nullable|date_format:Y-m-d|after:StartDate',
39+
'WorkingHours' => 'nullable|numeric',
40+
// 项目模块 ID
41+
'ProjectModuleId' => 'nullable|integer',
42+
// 事项关注人 ID 列表
43+
'WatcherIds' => 'nullable|array',
44+
'WatcherIds.*' => 'integer',
45+
// 项目缺陷类型 ID
46+
'DefectTypeId' => 'nullable|integer',
47+
// 项目需求类型 ID
48+
'RequirementTypeId' => 'nullable|integer',
49+
'IterationCode' => 'nullable|integer',
50+
'EpicCode' => 'nullable|integer',
51+
'StoryPoint' => 'nullable|string',
52+
'LabelIds' => 'nullable|array',
53+
'FileIds' => 'nullable|array',
54+
// 排序目标位置的事项 code
55+
'TargetSortCode' => 'nullable|integer',
56+
// 第三方链接列表 Array of CreateThirdLinkForm
57+
'ThirdLinks' => 'nullable|array',
58+
// 自定义属性值列表 Array of IssueCustomFieldForm
59+
'CustomFieldValues' => 'nullable|array',
60+
]);
61+
$response = $this->core->request('CreateIssue', $data);
62+
return $response['Issue'];
63+
}
64+
}

tests/IssueTest.php

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
namespace Coding\Tests;
4+
5+
use Coding\Core;
6+
use Coding\Issue;
7+
8+
class IssueTest extends TestCase
9+
{
10+
public function testCreateSuccessWithOnlyRequiredParams()
11+
{
12+
$response = json_decode(
13+
file_get_contents($this->dataPath('CreateIssueResponse.json')),
14+
true
15+
)['Response'];
16+
$data = [
17+
'ProjectName' => $this->projectName,
18+
'Name' => $this->faker->sentence,
19+
'Priority' => $this->faker->randomElement(Issue::PRIORITY),
20+
'Type' => $this->faker->randomElement(Issue::TYPE),
21+
];
22+
$this->coreMock->shouldReceive('request')->times(1)->withArgs([
23+
'CreateIssue',
24+
$data
25+
])->andReturn($response);
26+
27+
$issue = new Issue($this->token, $this->coreMock);
28+
$result = $issue->create($data);
29+
$this->assertEquals($response['Issue'], $result);
30+
}
31+
32+
public function testCreateSuccessWithAllParams()
33+
{
34+
$response = json_decode(
35+
file_get_contents($this->dataPath('CreateIssueResponse.json')),
36+
true
37+
)['Response'];
38+
$startDate = $this->faker->date();
39+
$data = [
40+
'ProjectName' => $this->projectName,
41+
'Name' => $this->faker->sentence,
42+
'Priority' => $this->faker->randomElement(Issue::PRIORITY),
43+
'Type' => $this->faker->randomElement(Issue::TYPE),
44+
'IssueTypeId' => $this->faker->randomNumber(),
45+
'ParentCode' => $this->faker->randomNumber(),
46+
'StatusId' => $this->faker->randomNumber(),
47+
'AssigneeId' => $this->faker->randomNumber(),
48+
'WatcherIds' => [$this->faker->randomNumber(), $this->faker->randomNumber()],
49+
'Description' => $this->faker->sentence(),
50+
'StartDate' => $startDate,
51+
'DueDate' => date('Y-m-d', strtotime($startDate) + $this->faker->randomDigitNotZero() * 86400),
52+
'WorkingHours' => $this->faker->randomDigitNotZero(),
53+
'ProjectModuleId' => $this->faker->randomNumber(),
54+
'DefectTypeId' => $this->faker->randomNumber(),
55+
'RequirementTypeId' => $this->faker->randomNumber(),
56+
'IterationCode' => $this->faker->randomNumber(),
57+
'EpicCode' => $this->faker->randomNumber(),
58+
'StoryPoint' => $this->faker->randomElement(['0.5', '1', '2', '3', '5', '8', '13', '20']),
59+
'LabelIds' => [$this->faker->randomNumber(), $this->faker->randomNumber()],
60+
'FileIds' => [$this->faker->randomNumber(), $this->faker->randomNumber()],
61+
'TargetSortCode' => $this->faker->randomDigitNotZero(),
62+
'ThirdLinks' => [
63+
[
64+
'ThirdType' => 'MODAO',
65+
'Link' => '<iframe src="https://modao.cc/app/7fb28d9af13827fd009f401579cbdc3cef2a456a/embed/v2" />',
66+
'Title' => '墨刀原型',
67+
],
68+
[
69+
'ThirdType' => 'CODESIGN',
70+
"Link" => 'https://codesign.qq.com/s/ALwE9VKWgl0X1Dp',
71+
"Title" => 'CoDesign - 腾讯自研设计协作平台',
72+
],
73+
],
74+
'CustomFieldValues' => [
75+
[
76+
// 用户单选
77+
'Id' => $this->faker->randomNumber(),
78+
'Content' => strval($this->faker->randomNumber()),
79+
],
80+
],
81+
];
82+
$this->coreMock->shouldReceive('request')->times(1)->withArgs([
83+
'CreateIssue',
84+
$data
85+
])->andReturn($response);
86+
87+
$issue = new Issue('', $this->coreMock);
88+
$issue->setToken($this->token);
89+
$result = $issue->create($data);
90+
$this->assertEquals($response['Issue'], $result);
91+
}
92+
}
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
{
2+
"Response": {
3+
"Issue": {
4+
"Epic": {
5+
"Code": 0,
6+
"Type": "",
7+
"Name": "",
8+
"IssueStatusId": 0,
9+
"IssueStatusName": "",
10+
"Priority": "",
11+
"Assignee": {
12+
"Id": 0,
13+
"Status": 0,
14+
"Avatar": "",
15+
"Name": "",
16+
"Email": "",
17+
"TeamId": 0,
18+
"Phone": "",
19+
"GlobalKey": "",
20+
"TeamGlobalKey": ""
21+
}
22+
},
23+
"ParentType": "MISSION",
24+
"Code": 2761,
25+
"Type": "MISSION",
26+
"Name": "Inventore animi deleniti quis officia unde et.",
27+
"Description": "Rerum et aliquam velit vel ea aut.",
28+
"IterationId": 0,
29+
"IssueStatusId": 1227034,
30+
"IssueStatusName": "未开始",
31+
"IssueStatusType": "TODO",
32+
"Priority": "2",
33+
"Assignee": {
34+
"Id": 7876900,
35+
"Status": 1,
36+
"Avatar": "https:\/\/coding-net-production-static-ci.codehub.cn\/WM-TEXT-AVATAR-ZGtSxcNBFKoNkHkQbMIn.jpg",
37+
"Name": "王磊",
38+
"Email": "",
39+
"TeamId": 0,
40+
"Phone": "",
41+
"GlobalKey": "",
42+
"TeamGlobalKey": ""
43+
},
44+
"StartDate": 255456000000,
45+
"DueDate": 256319999000,
46+
"WorkingHours": 6,
47+
"Creator": {
48+
"Id": 183478,
49+
"Status": 1,
50+
"Avatar": "https:\/\/coding-net-production-static-ci.codehub.cn\/2cb665a3-bebc-4b09-aa00-2b6df3e33edc.jpg?imageMogr2\/auto-orient\/format\/jpeg\/cut\/400x400x0x0",
51+
"Name": "sinkcup",
52+
"Email": "",
53+
"TeamId": 0,
54+
"Phone": "",
55+
"GlobalKey": "",
56+
"TeamGlobalKey": ""
57+
},
58+
"StoryPoint": "1.0",
59+
"CreatedAt": 1635147624016,
60+
"UpdatedAt": 1635147624016,
61+
"CompletedAt": 0,
62+
"ProjectModule": {
63+
"Id": 0,
64+
"Name": ""
65+
},
66+
"Watchers": [
67+
{
68+
"Id": 7877000,
69+
"Status": 1,
70+
"Avatar": "https:\/\/coding-net-production-static-ci.codehub.cn\/WM-TEXT-AVATAR-jJYOMnZHSaklwOoKpkBl.jpg",
71+
"Name": "韦酉旺",
72+
"Email": "",
73+
"TeamId": 0,
74+
"Phone": "",
75+
"GlobalKey": "",
76+
"TeamGlobalKey": ""
77+
},
78+
{
79+
"Id": 8124791,
80+
"Status": 1,
81+
"Avatar": "https:\/\/coding-net-production-static-ci.codehub.cn\/b37f6df8-4364-4131-854e-7a6a2f594a18.jpg?imageMogr2\/auto-orient\/format\/jpeg\/cut\/678x678x0x0",
82+
"Name": "钟其翁",
83+
"Email": "",
84+
"TeamId": 0,
85+
"Phone": "",
86+
"GlobalKey": "",
87+
"TeamGlobalKey": ""
88+
}
89+
],
90+
"Labels": [],
91+
"Files": [],
92+
"RequirementType": {
93+
"Id": 0,
94+
"Name": ""
95+
},
96+
"DefectType": {
97+
"Id": 0,
98+
"Name": "",
99+
"IconUrl": ""
100+
},
101+
"CustomFields": [
102+
{
103+
"Id": 35806839,
104+
"ValueString": "{\"Id\":7877000,\"Status\":1,\"GlobalKey\":\"bDUojijOpz\",\"Avatar\":\"https:\/\/coding-net-production-static-ci.codehub.cn\/WM-TEXT-AVATAR-jJYOMnZHSaklwOoKpkBl.jpg\",\"Media\":\"https:\/\/coding-net-production-static-ci.codehub.cn\/WM-TEXT-AVATAR-jJYOMnZHSaklwOoKpkBl.jpg\",\"Name\":\"韦酉旺\",\"Email\":\"\",\"Name_pinyin\":\"wyw||weiyouwang\"}"
105+
}
106+
],
107+
"ThirdLinks": [
108+
{
109+
"Id": 1138,
110+
"ThirdType": "MODAO",
111+
"Link": "<iframe src=\"https:\/\/modao.cc\/app\/7fb28d9af13827fd009f401579cbdc3cef2a456a\/embed\/v2\" \/>",
112+
"Title": "墨刀原型"
113+
},
114+
{
115+
"Id": 1139,
116+
"ThirdType": "CODESIGN",
117+
"Link": "https:\/\/codesign.qq.com\/s\/ALwE9VKWgl0X1Dp",
118+
"Title": "CoDesign - 腾讯自研设计协作平台"
119+
}
120+
],
121+
"SubTasks": [],
122+
"Parent": {
123+
"Code": 0,
124+
"Type": "",
125+
"Name": "",
126+
"IssueStatusId": 0,
127+
"IssueStatusName": "",
128+
"Priority": "",
129+
"Assignee": {
130+
"Id": 0,
131+
"Status": 0,
132+
"Avatar": "",
133+
"Name": "",
134+
"Email": "",
135+
"TeamId": 0,
136+
"Phone": "",
137+
"GlobalKey": "",
138+
"TeamGlobalKey": ""
139+
},
140+
"IssueStatusType": "",
141+
"IssueTypeDetail": {
142+
"Id": 0,
143+
"Name": "",
144+
"IssueType": "",
145+
"Description": "",
146+
"IsSystem": false
147+
}
148+
},
149+
"Iteration": {
150+
"Code": 0,
151+
"Name": "",
152+
"Status": ""
153+
},
154+
"IssueTypeDetail": {
155+
"Id": 213220,
156+
"Name": "任务",
157+
"IssueType": "MISSION",
158+
"Description": "任务是指为实现某个目标或需求所进行的具体活动。",
159+
"IsSystem": true
160+
},
161+
"IssueTypeId": 213220
162+
}
163+
}
164+
}

0 commit comments

Comments
 (0)