github-issue-tower-defence-management 1.117.9 → 1.117.10

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.
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>TDPM Console</title>
7
- <script type="module" crossorigin src="/assets/index-DID_sTas.js"></script>
7
+ <script type="module" crossorigin src="/assets/index-DWiG7btO.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="/assets/index-BMe1bEF4.css">
9
9
  </head>
10
10
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "github-issue-tower-defence-management",
3
- "version": "1.117.9",
3
+ "version": "1.117.10",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "scripts": {
@@ -146,7 +146,29 @@ test('renders the Workflow Blocker tab leftmost and shows its detail operations'
146
146
  ).toBeVisible();
147
147
  });
148
148
 
149
- test('adds an inline review comment on a related pull request diff without hover on a touch viewport', async ({
149
+ test('shows CI, conflict and out-of-date badges in the related PR header', async ({
150
+ page,
151
+ }) => {
152
+ await page.goto(harness.appRootUrl);
153
+
154
+ await tabByLabel(page, 'Failed Preparation').click();
155
+ await itemRowByText(
156
+ page,
157
+ 'Add inline review comments on the related pull request diff',
158
+ ).click();
159
+
160
+ const prHeader = page.locator('.console-pr-header').first();
161
+ await expect(prHeader.getByText('CI failing')).toBeVisible();
162
+ await expect(prHeader.getByText(/missing: build, test/)).toBeVisible();
163
+ await expect(prHeader.getByText('Conflict')).toBeVisible();
164
+ await expect(prHeader.getByText('Out of date')).toBeVisible();
165
+
166
+ await prHeader.screenshot({
167
+ path: '/tmp/after-related-pr-header.png',
168
+ });
169
+ });
170
+
171
+ test('collects an inline comment on a related pull request diff without hover on a touch viewport, enabling Reject and submitting it as request-changes', async ({
150
172
  browser,
151
173
  }) => {
152
174
  const touchContext = await browser.newContext({
@@ -179,6 +201,11 @@ test('adds an inline review comment on a related pull request diff without hover
179
201
  );
180
202
  expect(Number(opacity)).toBeGreaterThan(0);
181
203
 
204
+ const rejectButton = page
205
+ .locator('.console-op-button', { hasText: 'Reject' })
206
+ .first();
207
+ await expect(rejectButton).toBeDisabled();
208
+
182
209
  await commentButton.click();
183
210
  await page
184
211
  .locator('.console-diff-composer-input')
@@ -189,35 +216,21 @@ test('adds an inline review comment on a related pull request diff without hover
189
216
  'Comment saved.',
190
217
  );
191
218
 
192
- expect(harness.reviewCommentCalls).toHaveLength(1);
193
- expect(harness.reviewCommentCalls[0].url).toBe(
219
+ expect(harness.reviewCommentCalls).toHaveLength(0);
220
+
221
+ await expect(rejectButton).toBeEnabled();
222
+ await rejectButton.click();
223
+
224
+ await expect
225
+ .poll(() => harness.requestChangesCalls.length, { timeout: 10000 })
226
+ .toBe(1);
227
+ expect(harness.requestChangesCalls[0].url).toBe(
194
228
  'https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/pull/912',
195
229
  );
196
- expect(harness.reviewCommentCalls[0].body).toBe(
230
+ expect(harness.requestChangesCalls[0].body).toContain(
197
231
  'Please verify this opacity change on touch devices.',
198
232
  );
233
+ expect(harness.requestChangesCalls[0].body.length).toBeGreaterThan(0);
199
234
 
200
235
  await touchContext.close();
201
236
  });
202
-
203
- test('shows CI, conflict and out-of-date badges in the related PR header', async ({
204
- page,
205
- }) => {
206
- await page.goto(harness.appRootUrl);
207
-
208
- await tabByLabel(page, 'Failed Preparation').click();
209
- await itemRowByText(
210
- page,
211
- 'Add inline review comments on the related pull request diff',
212
- ).click();
213
-
214
- const prHeader = page.locator('.console-pr-header').first();
215
- await expect(prHeader.getByText('CI failing')).toBeVisible();
216
- await expect(prHeader.getByText(/missing: build, test/)).toBeVisible();
217
- await expect(prHeader.getByText('Conflict')).toBeVisible();
218
- await expect(prHeader.getByText('Out of date')).toBeVisible();
219
-
220
- await prHeader.screenshot({
221
- path: '/tmp/after-related-pr-header.png',
222
- });
223
- });
@@ -30,6 +30,13 @@ export type ConsoleE2eReviewCommentCall = {
30
30
  body: string;
31
31
  };
32
32
 
33
+ export type ConsoleE2eRequestChangesCall = {
34
+ url: string;
35
+ changedFilePath: string | null;
36
+ body: string;
37
+ inlineCommentLocation: { line: number; side: string } | null;
38
+ };
39
+
33
40
  type ConsoleFixtureListItem = {
34
41
  number: number;
35
42
  title: string;
@@ -370,6 +377,7 @@ const inlineCommentPullRequestDetail: PullRequestDetail = {
370
377
 
371
378
  const createStubIssueRepository = (
372
379
  reviewCommentCalls: ConsoleE2eReviewCommentCall[],
380
+ requestChangesCalls: ConsoleE2eRequestChangesCall[],
373
381
  ): IssueRepository => ({
374
382
  getAllIssues: () => notImplemented('getAllIssues'),
375
383
  getIssueByUrl: async (url: string): Promise<Issue | null> =>
@@ -402,7 +410,19 @@ const createStubIssueRepository = (
402
410
  : null,
403
411
  getPullRequestChangedFilePaths: async (): Promise<string[]> => [],
404
412
  approvePullRequest: async (): Promise<void> => undefined,
405
- requestChangesWithInlineComment: async (): Promise<void> => undefined,
413
+ requestChangesWithInlineComment: async (
414
+ prUrl: string,
415
+ changedFilePath: string | null,
416
+ commentBody: string,
417
+ inlineCommentLocation?: { line: number; side: string } | null,
418
+ ): Promise<void> => {
419
+ requestChangesCalls.push({
420
+ url: prUrl,
421
+ changedFilePath,
422
+ body: commentBody,
423
+ inlineCommentLocation: inlineCommentLocation ?? null,
424
+ });
425
+ },
406
426
  createPullRequestReviewComment: async (
407
427
  prUrl: string,
408
428
  filePath: string,
@@ -469,6 +489,7 @@ export type ConsoleE2eHarness = {
469
489
  appRootUrl: string;
470
490
  consoleDataOutputDir: string;
471
491
  reviewCommentCalls: ConsoleE2eReviewCommentCall[];
492
+ requestChangesCalls: ConsoleE2eRequestChangesCall[];
472
493
  stop: () => Promise<void>;
473
494
  };
474
495
 
@@ -486,12 +507,16 @@ export const startConsoleE2eHarness = async (): Promise<ConsoleE2eHarness> => {
486
507
  pjcode === CONSOLE_E2E_PJCODE ? { pjcode, project } : null;
487
508
 
488
509
  const reviewCommentCalls: ConsoleE2eReviewCommentCall[] = [];
510
+ const requestChangesCalls: ConsoleE2eRequestChangesCall[] = [];
489
511
 
490
512
  const server = await startWebServer({
491
513
  accessToken: CONSOLE_E2E_TOKEN,
492
514
  uiDistDir,
493
515
  consoleDataOutputDir,
494
- issueRepository: createStubIssueRepository(reviewCommentCalls),
516
+ issueRepository: createStubIssueRepository(
517
+ reviewCommentCalls,
518
+ requestChangesCalls,
519
+ ),
495
520
  resolveProject,
496
521
  issueTitleStateCache: new IssueTitleStateCache(),
497
522
  pullRequestStatusCache: new PullRequestStatusCache(),
@@ -518,6 +543,7 @@ export const startConsoleE2eHarness = async (): Promise<ConsoleE2eHarness> => {
518
543
  appRootUrl,
519
544
  consoleDataOutputDir,
520
545
  reviewCommentCalls,
546
+ requestChangesCalls,
521
547
  stop: async (): Promise<void> => {
522
548
  await closeServer(server);
523
549
  fs.rmSync(tmpRoot, { recursive: true, force: true });
@@ -212,8 +212,8 @@ export const IssueWithLinkedPullRequest: Story = {
212
212
  commitsError: null,
213
213
  },
214
214
  ],
215
- buildAddInlineComment: (prUrl) => async (path, line, side, body) => {
216
- window.alert(`comment on ${prUrl} ${path}:${line} (${side})\n${body}`);
215
+ onAddInlineComment: async (path, line, side, body) => {
216
+ window.alert(`comment on ${path}:${line} (${side})\n${body}`);
217
217
  },
218
218
  },
219
219
  };
@@ -64,7 +64,6 @@ export type ConsoleItemDetailProps = {
64
64
  buildImageProxyUrl?: ImageProxyUrlBuilder;
65
65
  renderReferenceLink?: ConsoleReferenceLinkRenderer;
66
66
  onAddInlineComment?: ConsoleAddInlineComment;
67
- buildAddInlineComment?: (prUrl: string) => ConsoleAddInlineComment;
68
67
  };
69
68
 
70
69
  export const ConsoleItemDetail = ({
@@ -93,7 +92,6 @@ export const ConsoleItemDetail = ({
93
92
  buildImageProxyUrl,
94
93
  renderReferenceLink,
95
94
  onAddInlineComment,
96
- buildAddInlineComment,
97
95
  }: ConsoleItemDetailProps) => {
98
96
  const resolvedState = state?.state ?? 'open';
99
97
  const merged = state?.merged ?? false;
@@ -283,11 +281,7 @@ export const ConsoleItemDetail = ({
283
281
  now={now}
284
282
  buildImageProxyUrl={buildImageProxyUrl}
285
283
  renderReferenceLink={renderReferenceLink}
286
- onAddInlineComment={
287
- buildAddInlineComment
288
- ? buildAddInlineComment(related.pullRequest.url)
289
- : undefined
290
- }
284
+ onAddInlineComment={onAddInlineComment}
291
285
  />
292
286
  ))}
293
287
 
@@ -187,28 +187,39 @@ describe('ConsoleItemDetailContainer', () => {
187
187
  ]);
188
188
  });
189
189
 
190
- it('routes an inline review comment on an issue related pull request to that pull request url', async () => {
190
+ it('collects an inline comment on an issue related pull request diff, enables Reject, and submits it as the request-changes review for that pull request url', async () => {
191
191
  const operations = buildOperations();
192
+ const onQueueAction = jest.fn();
192
193
  const relatedPullRequest = consoleRelatedPullRequestsFixture[0];
193
- const { container, findByRole, getAllByRole, getByPlaceholderText } =
194
- render(
195
- <ConsoleItemDetailContainer
196
- tab="unread"
197
- item={issueItem}
198
- caches={buildCaches({
199
- relatedPrs: [relatedPullRequest],
200
- prFiles: consoleChangedFilesFixture,
201
- })}
202
- operations={operations}
203
- statusOptions={consoleStatusOptionsFixture}
204
- storyOptions={consoleStoryOptionsFixture}
205
- storyColors={consoleStoryColorsFixture}
206
- storyName="TDPM Console port"
207
- overlayStatus={null}
208
- now={Date.parse('2026-06-19T12:00:00.000Z')}
209
- onQueueAction={jest.fn()}
210
- />,
211
- );
194
+ const {
195
+ container,
196
+ findByRole,
197
+ getAllByRole,
198
+ getByPlaceholderText,
199
+ getByText,
200
+ } = render(
201
+ <ConsoleItemDetailContainer
202
+ tab="unread"
203
+ item={issueItem}
204
+ caches={buildCaches({
205
+ relatedPrs: [relatedPullRequest],
206
+ prFiles: consoleChangedFilesFixture,
207
+ })}
208
+ operations={operations}
209
+ statusOptions={consoleStatusOptionsFixture}
210
+ storyOptions={consoleStoryOptionsFixture}
211
+ storyColors={consoleStoryColorsFixture}
212
+ storyName="TDPM Console port"
213
+ overlayStatus={null}
214
+ now={Date.parse('2026-06-19T12:00:00.000Z')}
215
+ onQueueAction={onQueueAction}
216
+ />,
217
+ );
218
+
219
+ await waitFor(() => {
220
+ expect(getByText('Reject')).toBeInTheDocument();
221
+ });
222
+ expect(getByText('Reject')).toBeDisabled();
212
223
 
213
224
  const fileRow = await findByRole('button', {
214
225
  name: new RegExp(consoleChangedFilesFixture[0].path),
@@ -230,13 +241,31 @@ describe('ConsoleItemDetailContainer', () => {
230
241
  expect(submitButton).not.toBeNull();
231
242
  fireEvent.click(submitButton as Element);
232
243
 
233
- const addInlineReviewComment =
234
- operations.addInlineReviewComment as jest.Mock;
235
244
  await waitFor(() => {
236
- expect(addInlineReviewComment).toHaveBeenCalledTimes(1);
245
+ expect(getByText('Reject')).not.toBeDisabled();
237
246
  });
238
- const call = addInlineReviewComment.mock.calls[0];
239
- expect(call[0]).toBe(relatedPullRequest.url);
240
- expect(call[4]).toBe('Please rename this variable.');
247
+ expect(operations.addInlineReviewComment).not.toHaveBeenCalled();
248
+
249
+ fireEvent.click(getByText('Reject'));
250
+ const rejectInput = onQueueAction.mock.calls.at(-1)?.[0];
251
+ expect(rejectInput.kind).toEqual({
252
+ type: 'review',
253
+ action: 'request_changes',
254
+ });
255
+ rejectInput.commit();
256
+ const reviewCall = (
257
+ operations.reviewPullRequest as jest.Mock
258
+ ).mock.calls.at(-1);
259
+ expect(reviewCall?.[1]).toBe(relatedPullRequest.url);
260
+ expect(reviewCall?.[2]).toBe('request_changes');
261
+ expect(reviewCall?.[3]).toEqual([
262
+ {
263
+ path: consoleChangedFilesFixture[0].path,
264
+ line: expect.any(Number),
265
+ side: expect.stringMatching(/LEFT|RIGHT/),
266
+ body: 'Please rename this variable.',
267
+ },
268
+ ]);
269
+ expect(reviewCall?.[3][0].body).not.toBe('');
241
270
  });
242
271
  });
@@ -77,12 +77,6 @@ export const ConsoleItemDetailContainer = ({
77
77
  const [pendingReviewComments, setPendingReviewComments] = useState<
78
78
  ConsolePendingReviewComment[]
79
79
  >([]);
80
- const buildAddInlineComment = useCallback(
81
- (prUrl: string): ConsoleAddInlineComment =>
82
- (path, line, side, body) =>
83
- operations.addInlineReviewComment(prUrl, path, line, side, body),
84
- [operations],
85
- );
86
80
  const addInlineComment = useCallback<ConsoleAddInlineComment>(
87
81
  async (path, line, side, body) => {
88
82
  setPendingReviewComments((previous) => [
@@ -175,8 +169,7 @@ export const ConsoleItemDetailContainer = ({
175
169
  now={now}
176
170
  buildImageProxyUrl={resolveImageProxyUrl}
177
171
  renderReferenceLink={renderReferenceLink}
178
- onAddInlineComment={item.isPr ? addInlineComment : undefined}
179
- buildAddInlineComment={buildAddInlineComment}
172
+ onAddInlineComment={addInlineComment}
180
173
  commentComposer={
181
174
  <ConsoleCommentComposer
182
175
  isPr={item.isPr}