github-issue-tower-defence-management 1.153.6 → 1.154.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js +26 -6
  3. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js.map +1 -1
  4. package/bin/adapter/repositories/issue/RestIssueRepository.js +6 -0
  5. package/bin/adapter/repositories/issue/RestIssueRepository.js.map +1 -1
  6. package/bin/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.js +10 -16
  7. package/bin/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.js.map +1 -1
  8. package/package.json +1 -1
  9. package/src/adapter/entry-points/console/ui/e2e/consoleTestHarness.ts +3 -0
  10. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.test.ts +58 -0
  11. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.ts +36 -6
  12. package/src/adapter/repositories/issue/RestIssueRepository.test.ts +19 -0
  13. package/src/adapter/repositories/issue/RestIssueRepository.ts +13 -0
  14. package/src/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.test.ts +211 -200
  15. package/src/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.ts +13 -18
  16. package/src/domain/usecases/adapter-interfaces/IssueRepository.ts +5 -0
  17. package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts +6 -2
  18. package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts.map +1 -1
  19. package/types/adapter/repositories/issue/RestIssueRepository.d.ts +1 -0
  20. package/types/adapter/repositories/issue/RestIssueRepository.d.ts.map +1 -1
  21. package/types/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.d.ts +2 -2
  22. package/types/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.d.ts.map +1 -1
  23. package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts +2 -0
  24. package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts.map +1 -1
@@ -467,6 +467,7 @@ export class ApiV3CheerioRestIssueRepository
467
467
  RestIssueRepository,
468
468
  | 'createNewIssue'
469
469
  | 'updateIssue'
470
+ | 'updateIssueBody'
470
471
  | 'createComment'
471
472
  | 'getIssue'
472
473
  | 'updateLabels'
@@ -803,6 +804,12 @@ export class ApiV3CheerioRestIssueRepository
803
804
  updateIssue = async (issue: Issue): Promise<void> => {
804
805
  await this.restIssueRepository.updateIssue(issue);
805
806
  };
807
+ updateIssueBody = async (
808
+ issue: Pick<Issue, 'org' | 'repo' | 'number'>,
809
+ body: string,
810
+ ): Promise<void> => {
811
+ await this.restIssueRepository.updateIssueBody(issue, body);
812
+ };
806
813
  getIssueByUrl = async (url: string): Promise<Issue | null> => {
807
814
  const projectItem =
808
815
  await this.graphqlProjectItemRepository.fetchProjectItemByUrl(url);
@@ -2296,9 +2303,9 @@ export class ApiV3CheerioRestIssueRepository
2296
2303
  await this.restIssueRepository.createComment(issueOrPrUrl, commentBody);
2297
2304
  };
2298
2305
 
2299
- getIssueOrPullRequestBody = async (url: string): Promise<string> => {
2306
+ private fetchIssueBodyResponse = (url: string): Promise<Response> => {
2300
2307
  const { owner, repo, issueNumber } = this.parseIssueUrl(url);
2301
- const response = await this.fetchWithRateLimitRetry(() =>
2308
+ return this.fetchWithRateLimitRetry(() =>
2302
2309
  fetch(
2303
2310
  `https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/issues/${issueNumber}`,
2304
2311
  {
@@ -2310,10 +2317,12 @@ export class ApiV3CheerioRestIssueRepository
2310
2317
  },
2311
2318
  ),
2312
2319
  );
2313
- if (!response.ok) {
2314
- const reason = await this.formatGitHubErrorWithStatus(response);
2315
- throw new Error(`Failed to fetch body for ${url}: ${reason}`);
2316
- }
2320
+ };
2321
+
2322
+ private parseIssueBodyResponse = async (
2323
+ url: string,
2324
+ response: Response,
2325
+ ): Promise<string> => {
2317
2326
  const body: unknown = await response.json();
2318
2327
  if (!isIssueOrPullRequestBodyResponse(body)) {
2319
2328
  throw new Error(
@@ -2323,6 +2332,27 @@ export class ApiV3CheerioRestIssueRepository
2323
2332
  return body.body ?? '';
2324
2333
  };
2325
2334
 
2335
+ getIssueOrPullRequestBody = async (url: string): Promise<string> => {
2336
+ const response = await this.fetchIssueBodyResponse(url);
2337
+ if (!response.ok) {
2338
+ const reason = await this.formatGitHubErrorWithStatus(response);
2339
+ throw new Error(`Failed to fetch body for ${url}: ${reason}`);
2340
+ }
2341
+ return this.parseIssueBodyResponse(url, response);
2342
+ };
2343
+
2344
+ getIssueBodyByUrl = async (url: string): Promise<string | null> => {
2345
+ const response = await this.fetchIssueBodyResponse(url);
2346
+ if (response.status === 404) {
2347
+ return null;
2348
+ }
2349
+ if (!response.ok) {
2350
+ const reason = await this.formatGitHubErrorWithStatus(response);
2351
+ throw new Error(`Failed to fetch body for ${url}: ${reason}`);
2352
+ }
2353
+ return this.parseIssueBodyResponse(url, response);
2354
+ };
2355
+
2326
2356
  getIssueOrPullRequestComments = async (
2327
2357
  url: string,
2328
2358
  ): Promise<IssueComment[]> => {
@@ -263,6 +263,25 @@ describe('RestIssueRepository', () => {
263
263
  });
264
264
  });
265
265
 
266
+ describe('updateIssueBody', () => {
267
+ it('sends only the body so the title, labels, assignees and state are left untouched', async () => {
268
+ const issue = buildIssue();
269
+
270
+ mockPatch.mockResolvedValue(undefined);
271
+
272
+ await restIssueRepository.updateIssueBody(issue, 'rewritten body');
273
+
274
+ expect(mockPatch).toHaveBeenCalledTimes(1);
275
+ expect(mockPatch).toHaveBeenCalledWith(
276
+ 'https://api.github.com/repos/HiromiShikata/test-repository/issues/40',
277
+ {
278
+ json: { body: 'rewritten body' },
279
+ headers: { Authorization: 'token dummy-token' },
280
+ },
281
+ );
282
+ });
283
+ });
284
+
266
285
  describe('searchIssues', () => {
267
286
  const buildSearchItem = (
268
287
  overrides: Partial<{
@@ -105,6 +105,19 @@ export class RestIssueRepository
105
105
  );
106
106
  };
107
107
 
108
+ updateIssueBody = async (
109
+ issue: Pick<Issue, 'org' | 'repo' | 'number'>,
110
+ body: string,
111
+ ): Promise<void> => {
112
+ await ky.patch(
113
+ `https://api.github.com/repos/${issue.org}/${issue.repo}/issues/${issue.number}`,
114
+ {
115
+ json: { body },
116
+ headers: { Authorization: `token ${this.ghToken}` },
117
+ },
118
+ );
119
+ };
120
+
108
121
  updateLabels = async (
109
122
  issue: Issue,
110
123
  labels: Issue['labels'],