Skip to content

Commit

Permalink
feat: #72 issue parent code
Browse files Browse the repository at this point in the history
  • Loading branch information
sinkcup committed Oct 22, 2021
1 parent 7cbbbf6 commit 5bc4e6e
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 51 deletions.
18 changes: 14 additions & 4 deletions app/Commands/IssueImportCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class IssueImportCommand extends Command

protected array $iterationMap = [];
protected array $issueTypes = [];
protected array $issueCodeMap = [];

/**
* Execute the console command.
Expand All @@ -50,21 +51,25 @@ public function handle(Issue $codingIssue, Project $codingProject, Iteration $it
}

$rows = FastExcel::import($filePath);
if (!empty($rows) && isset($rows[0]['ID'])) {
$rows = $rows->sortBy('ID');
}
foreach ($rows as $row) {
try {
$iterationResult = $this->createByRow($codingProject, $codingIssue, $iteration, $row);
$issueResult = $this->createIssueByRow($codingProject, $codingIssue, $iteration, $row);
} catch (\Exception $e) {
$this->error('Error: ' . $e->getMessage());
return 1;
}
$this->info('标题:' . $row['标题']);
$this->info("https://{$this->codingTeamDomain}.coding.net/p/{$this->codingProjectUri}" .
"/all/issues/${iterationResult['Code']}");
"/all/issues/${issueResult['Code']}");
}

return 0;
}

private function createByRow(Project $codingProject, Issue $issue, Iteration $iteration, array $row)
private function createIssueByRow(Project $codingProject, Issue $issue, Iteration $iteration, array $row)
{
if (empty($this->issueTypes)) {
$result = $codingProject->getIssueTypes($this->codingToken, $this->codingProjectUri);
Expand All @@ -78,8 +83,13 @@ private function createByRow(Project $codingProject, Issue $issue, Iteration $it
'Name' => $row['标题'],
'Priority' => \App\Models\Issue::PRIORITY_MAP[$row['优先级']],
'IterationCode' => $row['所属迭代'] ? $this->getIterationCode($iteration, $row['所属迭代']) : null,
'ParentCode' => !empty($row['ParentCode']) ? $this->issueCodeMap[$row['ParentCode']] : null,
];
return $issue->create($this->codingToken, $this->codingProjectUri, $data);
$result = $issue->create($this->codingToken, $this->codingProjectUri, $data);
if (isset($row['ID'])) {
$this->issueCodeMap[$row['ID']] = intval($result['Code']);
}
return $result;
}

private function getIterationCode(Iteration $iteration, string $name)
Expand Down
105 changes: 88 additions & 17 deletions tests/Feature/IssueImportCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@

class IssueImportCommandTest extends TestCase
{
private string $codingToken;
private string $codingTeamDomain;
private string $codingProjectUri;
private string $token;
private string $teamDomain;
private string $projectUri;

protected function setUp(): void
{
parent::setUp();
$this->codingToken = $this->faker->md5;
config(['coding.token' => $this->codingToken]);
$this->codingTeamDomain = $this->faker->domainWord;
config(['coding.team_domain' => $this->codingTeamDomain]);
$this->codingProjectUri = $this->faker->slug;
config(['coding.project_uri' => $this->codingProjectUri]);
$this->token = $this->faker->md5;
config(['coding.token' => $this->token]);
$this->teamDomain = $this->faker->domainWord;
config(['coding.team_domain' => $this->teamDomain]);
$this->projectUri = $this->faker->slug;
config(['coding.project_uri' => $this->projectUri]);
}

public function testImportSuccess()
Expand Down Expand Up @@ -56,11 +56,11 @@ public function testImportSuccess()
$issueMock->shouldReceive('create')->times(21)->andReturn(...$results);

$this->artisan('issue:import', ['file' => $this->dataDir . 'coding/scrum-issues.csv'])
->expectsOutput("https://$this->codingTeamDomain.coding.net/p/$this->codingProjectUri/all/issues/1")
->expectsOutput("https://$this->codingTeamDomain.coding.net/p/$this->codingProjectUri/all/issues/2")
->expectsOutput("https://$this->codingTeamDomain.coding.net/p/$this->codingProjectUri/all/issues/3")
->expectsOutput("https://$this->codingTeamDomain.coding.net/p/$this->codingProjectUri/all/issues/20")
->expectsOutput("https://$this->codingTeamDomain.coding.net/p/$this->codingProjectUri/all/issues/21")
->expectsOutput("https://$this->teamDomain.coding.net/p/$this->projectUri/all/issues/1")
->expectsOutput("https://$this->teamDomain.coding.net/p/$this->projectUri/all/issues/2")
->expectsOutput("https://$this->teamDomain.coding.net/p/$this->projectUri/all/issues/3")
->expectsOutput("https://$this->teamDomain.coding.net/p/$this->projectUri/all/issues/20")
->expectsOutput("https://$this->teamDomain.coding.net/p/$this->projectUri/all/issues/21")
->assertExitCode(0);
}

Expand Down Expand Up @@ -91,20 +91,91 @@ public function testImportUserStorySuccess()
)['Response']['Iteration']);

$issueMock->shouldReceive('create')->times(1)->withArgs([
$this->codingToken,
$this->codingProjectUri,
$this->token,
$this->projectUri,
[
'Type' => 'REQUIREMENT',
'IssueTypeId' => 213218,
'Name' => '用户可通过手机号注册账户',
'Priority' => "1",
'IterationCode' => 2746,
'ParentCode' => null,
]
])->andReturn($result);

$this->artisan('issue:import', ['file' => $this->dataDir . 'coding/scrum-issue-5.csv'])
->expectsOutput("https://$this->codingTeamDomain.coding.net/p/$this->codingProjectUri/all/issues/" .
->expectsOutput('标题:用户可通过手机号注册账户')
->expectsOutput("https://$this->teamDomain.coding.net/p/$this->projectUri/all/issues/" .
$result['Code'])
->assertExitCode(0);
}

public function testImportSubTask()
{
$mock = \Mockery::mock(Project::class, [])->makePartial();
$this->instance(Project::class, $mock);

$mock->shouldReceive('getIssueTypes')->times(1)->andReturn(json_decode(
file_get_contents($this->dataDir . 'coding/' . 'DescribeProjectIssueTypeListResponse.json'),
true
)['Response']['IssueTypes']);

$issueMock = \Mockery::mock(Issue::class, [])->makePartial();
$this->instance(Issue::class, $issueMock);

$response = json_decode(
file_get_contents($this->dataDir . 'coding/' . 'CreateIssueResponse.json'),
true
)['Response']['Issue'];

$parentIssue = $response;
$issueMock->shouldReceive('create')->times(1)->withArgs([
$this->token,
$this->projectUri,
[
'Type' => 'REQUIREMENT',
'IssueTypeId' => 213218,
'Name' => '用户可通过手机号注册账户',
'Priority' => "1",
'IterationCode' => null,
'ParentCode' => null,
]
])->andReturn($parentIssue);

$subTask1 = $response;
$subTask1['Code'] = $this->faker->randomNumber();
$issueMock->shouldReceive('create')->times(1)->withArgs([
$this->token,
$this->projectUri,
[
'Type' => 'SUB_TASK',
'IssueTypeId' => 213222,
'Name' => '完成手机号注册的短信验证码发送接口',
'Priority' => "1",
'IterationCode' => null,
'ParentCode' => 2742,
]
])->andReturn($subTask1);

$subTask2 = $response;
$subTask2['Code'] = $this->faker->randomNumber();
$issueMock->shouldReceive('create')->times(1)->withArgs([
$this->token,
$this->projectUri,
[
'Type' => 'SUB_TASK',
'IssueTypeId' => 213222,
'Name' => '完成通过手机号注册用户的接口',
'Priority' => "1",
'IterationCode' => null,
'ParentCode' => 2742,
]
])->andReturn($subTask2);

$this->artisan('issue:import', ['file' => $this->dataDir . 'coding/scrum-issues-5-6-7.csv'])
->expectsOutput("https://$this->teamDomain.coding.net/p/$this->projectUri/all/issues/2742")
->expectsOutput("https://$this->teamDomain.coding.net/p/$this->projectUri/all/issues/" . $subTask1['Code'])
->expectsOutput("https://$this->teamDomain.coding.net/p/$this->projectUri/all/issues/" . $subTask2['Code'])
->assertExitCode(0);
}
}
4 changes: 4 additions & 0 deletions tests/data/coding/scrum-issues-5-6-7.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ID,ParentCode,事项类型,标题,描述,状态,创建时间,创建人,更新时间,所属迭代,故事点,处理人,缺陷类型,优先级,截止日期,模块,标签,关注人,开始日期
7,5,子工作项,完成通过手机号注册用户的接口,,已完成,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,,,,,中,,,,,
6,5,子工作项,完成手机号注册的短信验证码发送接口,,已完成,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,,,,,中,,,,,
5,,用户故事,用户可通过手机号注册账户,,开发中,2021-10-19 11:26:37,sinkcup,2021-10-19 11:26:37,,2,sinkcup,,中,2021-10-21,,,,
60 changes: 30 additions & 30 deletions tests/data/coding/scrum-issues.csv
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
ID,事项类型,标题,描述,状态,创建时间,创建人,更新时间,所属迭代,故事点,处理人,缺陷类型,优先级,截止日期,模块,标签,关注人,开始日期
23,缺陷,商品详情页中商品价格字体应当显示为红色并且加粗,"步骤:

测试环境中,打开商品列表页;
点击任意商品进详情页。
测试结果:商品的价格字体显示为正常大小,颜色为黑色。
ID,ParentCode,事项类型,标题,描述,状态,创建时间,创建人,更新时间,所属迭代,故事点,处理人,缺陷类型,优先级,截止日期,模块,标签,关注人,开始日期
23,,缺陷,商品详情页中商品价格字体应当显示为红色并且加粗,"步骤:
测试环境中,打开商品列表页;
点击任意商品进详情页。
测试结果:商品的价格字体显示为正常大小,颜色为黑色。
预期结果:商品价格字体为红色加粗。",待处理,2021-10-19 11:26:39,sinkcup,2021-10-19 11:26:39,,,,,中,,,,,
22,缺陷,登录页输入正确的用户名和密码后提示“用户不存在”,"步骤:
测试环境中,输入URL https://mywebsite.com/login 进入登录页;
输入用户名 Admin 和密码 mypassword;
点击“登录”按钮。
测试结果:页面提示“用户不存在”。
22,,缺陷,登录页输入正确的用户名和密码后提示“用户不存在”,"步骤:
测试环境中,输入URL https://mywebsite.com/login 进入登录页;
输入用户名 Admin 和密码 mypassword;
点击“登录”按钮。
测试结果:页面提示“用户不存在”。
预期结果:提示“登录成功”并且页面自动跳转到首页。",处理中,2021-10-19 11:26:39,sinkcup,2021-10-19 11:26:39,,,sinkcup,,中,,,,,
21,任务,编制新功能的帮助文档并发布,,未开始,2021-10-19 11:26:39,sinkcup,2021-10-19 11:26:39,,,,,中,,,,,
20,任务,编写脚本将 Excel 中的线下订单转换为商城后台订单,,未开始,2021-10-19 11:26:39,sinkcup,2021-10-19 11:26:39,,,,,中,,,,,
19,任务,注册腾讯云账户,搭建测试环境和生产环境服务器,,处理中,2021-10-19 11:26:39,sinkcup,2021-10-19 11:26:39,第 1 次迭代,3,sinkcup,,中,2021-10-21,,,,
18,用户故事,用户可对未支付的订单执行取消订单操作,,未开始,2021-10-19 11:26:39,sinkcup,2021-10-19 11:26:39,,,,,中,,,,,
17,用户故事,管理员可在商城后台对订单执行发货操作,,未开始,2021-10-19 11:26:39,sinkcup,2021-10-19 11:26:39,,3,,,中,,,,,
16,用户故事,用户可在手机端搜索并查看指定的订单详情,,未开始,2021-10-19 11:26:39,sinkcup,2021-10-19 11:26:39,,1,,,中,,,,,
15,用户故事,通过访问邀请链接可注册成为商城用户,,未开始,2021-10-19 11:26:39,sinkcup,2021-10-19 11:26:39,,,,,中,,,,,
14,用户故事,管理员可取消未发货且状态异常的订单,,未开始,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 2 次迭代,3,,,中,,,,,
13,用户故事,用户可在“个人信息”中编辑个人基本信息,包括修改密码,,未开始,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 2 次迭代,2,sinkcup,,中,,,,,
12,用户故事,管理员可在商城后台搜索订单,,未开始,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 1 次迭代,2,,,中,,,,,
11,用户故事,管理员可在商城后台手工为用户下单,,未开始,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 1 次迭代,5,,,中,2021-10-26,,,,
10,用户故事,用户可在个人中心的“个人信息”中查看个人信息,,已完成,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 1 次迭代,1,,,中,,,,,
9,用户故事,用户可通过短信验证码登录商城,,开发中,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 1 次迭代,,,,中,,,,,
8,子工作项,完成用户注册页面控件并集成后端接口,,处理中,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 1 次迭代,,,,中,2021-10-21,,,,
7,子工作项,完成通过手机号注册用户的接口,,已完成,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 1 次迭代,,,,中,,,,,
6,子工作项,完成手机号注册的短信验证码发送接口,,已完成,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 1 次迭代,,,,中,,,,,
5,用户故事,用户可通过手机号注册账户,,开发中,2021-10-19 11:26:37,sinkcup,2021-10-19 11:26:37,第 1 次迭代,2,sinkcup,,中,2021-10-21,,,,
2,史诗,订单管理,订单管理将实现用户的订单列表查询、订单详情、订单改价、订单地址修改、申请售后、订单取消等功能,未开始,2021-10-19 11:26:37,sinkcup,2021-10-19 11:26:37,,,,,中,,,,,2021-10-19
1,史诗,用户管理,用户管理将实现用户的注册、邀请、用户查询、个人信息管理、删除用户、注销账户等功能。,未开始,2021-10-19 11:26:37,sinkcup,2021-10-19 11:26:37,,,,,中,,,,,2021-10-19
21,,任务,编制新功能的帮助文档并发布,,未开始,2021-10-19 11:26:39,sinkcup,2021-10-19 11:26:39,,,,,中,,,,,
20,,任务,编写脚本将 Excel 中的线下订单转换为商城后台订单,,未开始,2021-10-19 11:26:39,sinkcup,2021-10-19 11:26:39,,,,,中,,,,,
19,,任务,注册腾讯云账户,搭建测试环境和生产环境服务器,,处理中,2021-10-19 11:26:39,sinkcup,2021-10-19 11:26:39,第 1 次迭代,3,sinkcup,,中,2021-10-21,,,,
18,,用户故事,用户可对未支付的订单执行取消订单操作,,未开始,2021-10-19 11:26:39,sinkcup,2021-10-19 11:26:39,,,,,中,,,,,
17,,用户故事,管理员可在商城后台对订单执行发货操作,,未开始,2021-10-19 11:26:39,sinkcup,2021-10-19 11:26:39,,3,,,中,,,,,
16,,用户故事,用户可在手机端搜索并查看指定的订单详情,,未开始,2021-10-19 11:26:39,sinkcup,2021-10-19 11:26:39,,1,,,中,,,,,
15,,用户故事,通过访问邀请链接可注册成为商城用户,,未开始,2021-10-19 11:26:39,sinkcup,2021-10-19 11:26:39,,,,,中,,,,,
14,,用户故事,管理员可取消未发货且状态异常的订单,,未开始,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 2 次迭代,3,,,中,,,,,
13,,用户故事,用户可在“个人信息”中编辑个人基本信息,包括修改密码,,未开始,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 2 次迭代,2,sinkcup,,中,,,,,
12,,用户故事,管理员可在商城后台搜索订单,,未开始,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 1 次迭代,2,,,中,,,,,
11,,用户故事,管理员可在商城后台手工为用户下单,,未开始,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 1 次迭代,5,,,中,2021-10-26,,,,
10,,用户故事,用户可在个人中心的“个人信息”中查看个人信息,,已完成,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 1 次迭代,1,,,中,,,,,
9,,用户故事,用户可通过短信验证码登录商城,,开发中,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 1 次迭代,,,,中,,,,,
8,5,子工作项,完成用户注册页面控件并集成后端接口,,处理中,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 1 次迭代,,,,中,2021-10-21,,,,
7,5,子工作项,完成通过手机号注册用户的接口,,已完成,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 1 次迭代,,,,中,,,,,
6,5,子工作项,完成手机号注册的短信验证码发送接口,,已完成,2021-10-19 11:26:38,sinkcup,2021-10-19 11:26:38,第 1 次迭代,,,,中,,,,,
5,,用户故事,用户可通过手机号注册账户,,开发中,2021-10-19 11:26:37,sinkcup,2021-10-19 11:26:37,第 1 次迭代,2,sinkcup,,中,2021-10-21,,,,
2,,史诗,订单管理,订单管理将实现用户的订单列表查询、订单详情、订单改价、订单地址修改、申请售后、订单取消等功能,未开始,2021-10-19 11:26:37,sinkcup,2021-10-19 11:26:37,,,,,中,,,,,2021-10-19
1,,史诗,用户管理,用户管理将实现用户的注册、邀请、用户查询、个人信息管理、删除用户、注销账户等功能。,未开始,2021-10-19 11:26:37,sinkcup,2021-10-19 11:26:37,,,,,中,,,,,2021-10-19

0 comments on commit 5bc4e6e

Please sign in to comment.