github-issue-tower-defence-management 1.169.2 → 1.170.1

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 (21) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +1 -1
  3. package/bin/adapter/entry-points/cli/index.js +1 -0
  4. package/bin/adapter/entry-points/cli/index.js.map +1 -1
  5. package/bin/adapter/entry-points/console/ui-dist/assets/{index-DL4JeBCA.js → index-Db4JRB24.js} +1 -1
  6. package/bin/adapter/entry-points/console/ui-dist/index.html +1 -1
  7. package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js +6 -3
  8. package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js.map +1 -1
  9. package/package.json +1 -1
  10. package/src/adapter/entry-points/cli/index.test.ts +36 -0
  11. package/src/adapter/entry-points/cli/index.ts +1 -0
  12. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemDetail.stories.tsx +82 -0
  13. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemDetail.test.tsx +149 -30
  14. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemDetail.tsx +27 -27
  15. package/src/adapter/entry-points/console/ui-dist/assets/{index-DL4JeBCA.js → index-Db4JRB24.js} +1 -1
  16. package/src/adapter/entry-points/console/ui-dist/index.html +1 -1
  17. package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.test.ts +53 -3
  18. package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts +9 -1
  19. package/types/adapter/entry-points/cli/index.d.ts.map +1 -1
  20. package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts +1 -0
  21. package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts.map +1 -1
@@ -63,6 +63,88 @@ export default meta;
63
63
 
64
64
  type Story = StoryObj<typeof ConsoleItemDetail>;
65
65
 
66
+ export const PullRequestItemHeadArrangement: Story = {
67
+ args: {
68
+ item: consoleListItemsFixture[0],
69
+ storyName: 'TDPM Console port',
70
+ storyColorEnum: 'BLUE',
71
+ overlayStatus: { name: 'Awaiting Workspace', color: 'BLUE' },
72
+ state: {
73
+ state: 'open',
74
+ merged: false,
75
+ isPullRequest: true,
76
+ title: 'Add serveConsole subcommand under entry-points',
77
+ },
78
+ body: '',
79
+ bodyIsLoading: false,
80
+ bodyError: null,
81
+ stateError: null,
82
+ pullRequestStatusError: null,
83
+ relatedPullRequestsError: null,
84
+ comments: [],
85
+ commentsAreLoading: false,
86
+ commentsError: null,
87
+ files: [],
88
+ filesAreLoading: false,
89
+ filesError: null,
90
+ commits: [],
91
+ commitsAreLoading: false,
92
+ commitsError: null,
93
+ pullRequestStatus: {
94
+ found: true,
95
+ isConflicted: false,
96
+ mergeableStatus: 'MERGEABLE',
97
+ isPassedAllCiJob: true,
98
+ isCiStateSuccess: true,
99
+ isBranchOutOfDate: false,
100
+ missingRequiredCheckNames: [],
101
+ },
102
+ relatedPullRequests: [],
103
+ },
104
+ };
105
+
106
+ export const IssueItemWithLinkedPrHeadArrangement: Story = {
107
+ args: {
108
+ item: consoleListItemsFixture[2],
109
+ storyName: 'TDPM Console port',
110
+ storyColorEnum: 'BLUE',
111
+ overlayStatus: { name: 'In Progress', color: 'GREEN' },
112
+ state: {
113
+ state: 'open',
114
+ merged: false,
115
+ isPullRequest: false,
116
+ title: 'Scaffold React console UI under entry-points with build bundling',
117
+ },
118
+ body: '',
119
+ bodyIsLoading: false,
120
+ bodyError: null,
121
+ stateError: null,
122
+ pullRequestStatusError: null,
123
+ relatedPullRequestsError: null,
124
+ comments: [],
125
+ commentsAreLoading: false,
126
+ commentsError: null,
127
+ files: [],
128
+ filesAreLoading: false,
129
+ filesError: null,
130
+ commits: [],
131
+ commitsAreLoading: false,
132
+ commitsError: null,
133
+ pullRequestStatus: null,
134
+ relatedPullRequests: [
135
+ {
136
+ pullRequest: consoleRelatedPullRequestsFixture[0],
137
+ files: [],
138
+ filesAreLoading: false,
139
+ filesError: null,
140
+ commits: [],
141
+ commitsAreLoading: false,
142
+ commitsError: null,
143
+ },
144
+ ],
145
+ },
146
+ };
147
+
66
148
  export const PullRequestItem: Story = {
67
149
  args: {
68
150
  item: consoleListItemsFixture[0],
@@ -209,6 +209,128 @@ describe('ConsoleItemDetail', () => {
209
209
  expect(getByRole('button', { name: 'Copy URL' })).toBeInTheDocument();
210
210
  });
211
211
 
212
+ it('puts the type mark, title text and number in the title line and moves the status chip, story tag and CI state to the row below the title for a pull request item', () => {
213
+ const { getByText, container } = render(
214
+ <ConsoleItemDetail
215
+ item={prItem}
216
+ {...baseProps}
217
+ overlayStatus={{ name: 'Awaiting Workspace', color: 'BLUE' }}
218
+ pullRequestStatus={{
219
+ found: true,
220
+ isConflicted: false,
221
+ mergeableStatus: 'MERGEABLE',
222
+ isPassedAllCiJob: true,
223
+ isCiStateSuccess: true,
224
+ isBranchOutOfDate: false,
225
+ missingRequiredCheckNames: [],
226
+ }}
227
+ />,
228
+ );
229
+ const title = container.querySelector('.console-detail-title');
230
+ const subline = container.querySelector('.console-detail-topline');
231
+ if (title === null || subline === null) {
232
+ throw new Error('title and subline must both render');
233
+ }
234
+ expect(title.contains(getByText('Awaiting Workspace'))).toBe(false);
235
+ expect(title.contains(getByText('TDPM Console port'))).toBe(false);
236
+ expect(title.contains(getByText('CI passing'))).toBe(false);
237
+ expect(
238
+ title.compareDocumentPosition(subline) & Node.DOCUMENT_POSITION_FOLLOWING,
239
+ ).toBeTruthy();
240
+ expect(subline.contains(getByText('Awaiting Workspace'))).toBe(true);
241
+ expect(subline.contains(getByText('TDPM Console port'))).toBe(true);
242
+ expect(subline.contains(getByText('CI passing'))).toBe(true);
243
+ });
244
+
245
+ it('title line contains exactly the type mark then title text then number and no other children for a pull request item', () => {
246
+ const { container } = render(
247
+ <ConsoleItemDetail
248
+ item={prItem}
249
+ {...baseProps}
250
+ overlayStatus={{ name: 'Awaiting Workspace', color: 'BLUE' }}
251
+ pullRequestStatus={{
252
+ found: true,
253
+ isConflicted: false,
254
+ mergeableStatus: 'MERGEABLE',
255
+ isPassedAllCiJob: true,
256
+ isCiStateSuccess: true,
257
+ isBranchOutOfDate: false,
258
+ missingRequiredCheckNames: [],
259
+ }}
260
+ />,
261
+ );
262
+ const title = container.querySelector('.console-detail-title');
263
+ if (title === null) {
264
+ throw new Error('title must render');
265
+ }
266
+ expect(title.childElementCount).toBe(3);
267
+ expect(title.children[0]).toHaveClass('console-item-icon');
268
+ expect(title.children[1]).toHaveClass('console-detail-title-text');
269
+ expect(title.children[2]).toHaveClass('console-detail-number');
270
+ expect(title.children[2]).toHaveTextContent(`PR #${prItem.number}`);
271
+ });
272
+
273
+ it('title line contains exactly the type mark then title text then number and no other children for a closed task item', () => {
274
+ const { container } = render(
275
+ <ConsoleItemDetail
276
+ item={issueItem}
277
+ {...baseProps}
278
+ state={{
279
+ state: 'closed',
280
+ merged: false,
281
+ isPullRequest: false,
282
+ title: '',
283
+ }}
284
+ />,
285
+ );
286
+ const title = container.querySelector('.console-detail-title');
287
+ if (title === null) {
288
+ throw new Error('title must render');
289
+ }
290
+ expect(title.childElementCount).toBe(3);
291
+ expect(title.children[0]).toHaveClass('console-item-icon');
292
+ expect(title.children[1]).toHaveClass('console-detail-title-text');
293
+ expect(title.children[2]).toHaveClass('console-detail-number');
294
+ expect(title.children[2]).toHaveTextContent(`#${issueItem.number}`);
295
+ });
296
+
297
+ it('puts CI badges, related pull request groups and conflict chips in the row below the title for a task item with related pull requests', () => {
298
+ const { container } = render(
299
+ <ConsoleItemDetail
300
+ item={issueItem}
301
+ {...baseProps}
302
+ state={{
303
+ state: 'open',
304
+ merged: false,
305
+ isPullRequest: false,
306
+ title: '',
307
+ }}
308
+ relatedPullRequests={consoleRelatedPullRequestsFixture.map(
309
+ (pullRequest) => ({
310
+ pullRequest,
311
+ files: [],
312
+ filesAreLoading: false,
313
+ filesError: null,
314
+ commits: [],
315
+ commitsAreLoading: false,
316
+ commitsError: null,
317
+ }),
318
+ )}
319
+ />,
320
+ );
321
+ const title = container.querySelector('.console-detail-title');
322
+ const subline = container.querySelector('.console-detail-topline');
323
+ if (title === null || subline === null) {
324
+ throw new Error('title and subline must both render');
325
+ }
326
+ expect(
327
+ title.compareDocumentPosition(subline) & Node.DOCUMENT_POSITION_FOLLOWING,
328
+ ).toBeTruthy();
329
+ expect(
330
+ within(subline as HTMLElement).getByText('No conflict'),
331
+ ).toBeInTheDocument();
332
+ });
333
+
212
334
  it('renders the overlay status chip when set', () => {
213
335
  const { getByText } = render(
214
336
  <ConsoleItemDetail
@@ -220,7 +342,7 @@ describe('ConsoleItemDetail', () => {
220
342
  expect(getByText('Awaiting Workspace')).toBeInTheDocument();
221
343
  });
222
344
 
223
- it('renders the overlay status chip inside the title header', () => {
345
+ it('renders the overlay status chip in the subline below the title, not inside the title line', () => {
224
346
  const { getByText, container } = render(
225
347
  <ConsoleItemDetail
226
348
  item={issueItem}
@@ -229,20 +351,14 @@ describe('ConsoleItemDetail', () => {
229
351
  />,
230
352
  );
231
353
  const title = container.querySelector('.console-detail-title');
354
+ const subline = container.querySelector('.console-detail-topline');
232
355
  expect(title).not.toBeNull();
233
- expect(title?.contains(getByText('Awaiting Workspace'))).toBe(true);
356
+ expect(subline).not.toBeNull();
357
+ expect(title?.contains(getByText('Awaiting Workspace'))).toBe(false);
358
+ expect(subline?.contains(getByText('Awaiting Workspace'))).toBe(true);
234
359
  });
235
360
 
236
- const firstRowOfDetail = (container: HTMLElement): Element => {
237
- const detail = container.querySelector('.console-detail');
238
- const firstRow = detail?.firstElementChild ?? null;
239
- if (firstRow === null) {
240
- throw new Error('the item detail must render a first row');
241
- }
242
- return firstRow;
243
- };
244
-
245
- it('renders the merge conflict state on the first row of the detail', () => {
361
+ it('renders the merge conflict state in the subline below the title, not inside the title line', () => {
246
362
  const { getByText, container } = render(
247
363
  <ConsoleItemDetail
248
364
  item={prItem}
@@ -258,14 +374,13 @@ describe('ConsoleItemDetail', () => {
258
374
  }}
259
375
  />,
260
376
  );
261
- expect(firstRowOfDetail(container).contains(getByText('Conflict'))).toBe(
262
- true,
263
- );
264
377
  const title = container.querySelector('.console-detail-title');
378
+ const subline = container.querySelector('.console-detail-topline');
379
+ expect(subline?.contains(getByText('Conflict'))).toBe(true);
265
380
  expect(title?.contains(getByText('Conflict'))).toBe(false);
266
381
  });
267
382
 
268
- it('renders the absence of a merge conflict on the first row of the detail', () => {
383
+ it('renders the absence of a merge conflict in the subline below the title', () => {
269
384
  const { getByText, container } = render(
270
385
  <ConsoleItemDetail
271
386
  item={prItem}
@@ -281,12 +396,11 @@ describe('ConsoleItemDetail', () => {
281
396
  }}
282
397
  />,
283
398
  );
284
- expect(firstRowOfDetail(container).contains(getByText('No conflict'))).toBe(
285
- true,
286
- );
399
+ const subline = container.querySelector('.console-detail-topline');
400
+ expect(subline?.contains(getByText('No conflict'))).toBe(true);
287
401
  });
288
402
 
289
- it('renders the related pull request merge state on the first row when the item is an issue', () => {
403
+ it('renders the related pull request merge state in the subline below the title when the item is an issue', () => {
290
404
  const { container } = render(
291
405
  <ConsoleItemDetail
292
406
  item={issueItem}
@@ -310,14 +424,13 @@ describe('ConsoleItemDetail', () => {
310
424
  )}
311
425
  />,
312
426
  );
427
+ const subline = container.querySelector('.console-detail-topline');
313
428
  expect(
314
- within(firstRowOfDetail(container) as HTMLElement).getByText(
315
- 'No conflict',
316
- ),
429
+ within(subline as HTMLElement).getByText('No conflict'),
317
430
  ).toBeInTheDocument();
318
431
  });
319
432
 
320
- it('renders failing CI, missing checks, and conflict badges on the top line above the title', () => {
433
+ it('renders failing CI, missing checks, and conflict badges in the subline below the title, not inside the title line', () => {
321
434
  const { getByText, container } = render(
322
435
  <ConsoleItemDetail
323
436
  item={prItem}
@@ -336,13 +449,13 @@ describe('ConsoleItemDetail', () => {
336
449
  const title = container.querySelector('.console-detail-title');
337
450
  const topline = container.querySelector('.console-detail-topline');
338
451
  if (title === null || topline === null) {
339
- throw new Error('title and top line must both render');
452
+ throw new Error('title and subline must both render');
340
453
  }
341
454
  expect(title.contains(getByText('CI failing'))).toBe(false);
342
455
  expect(topline.contains(getByText('CI failing'))).toBe(true);
343
456
  expect(topline.contains(getByText('Conflict'))).toBe(true);
344
457
  expect(
345
- topline.compareDocumentPosition(title) & Node.DOCUMENT_POSITION_FOLLOWING,
458
+ title.compareDocumentPosition(topline) & Node.DOCUMENT_POSITION_FOLLOWING,
346
459
  ).toBeTruthy();
347
460
  expect(getByText(/missing: build, test/)).toBeInTheDocument();
348
461
  expect(getByText('Conflict')).toBeInTheDocument();
@@ -483,7 +596,7 @@ describe('ConsoleItemDetail', () => {
483
596
  ).toBeInTheDocument();
484
597
  });
485
598
 
486
- it('shows the snapshot status chip in the header when the item has a status and no overlay entry applies', () => {
599
+ it('shows the snapshot status chip in the subline below the title when the item has a status and no overlay entry applies', () => {
487
600
  const { getByText, container } = render(
488
601
  <ConsoleItemDetail
489
602
  item={issueItem}
@@ -492,11 +605,14 @@ describe('ConsoleItemDetail', () => {
492
605
  />,
493
606
  );
494
607
  const title = container.querySelector('.console-detail-title');
608
+ const subline = container.querySelector('.console-detail-topline');
495
609
  expect(title).not.toBeNull();
496
- expect(title?.contains(getByText(issueItem.status as string))).toBe(true);
610
+ expect(subline).not.toBeNull();
611
+ expect(title?.contains(getByText(issueItem.status as string))).toBe(false);
612
+ expect(subline?.contains(getByText(issueItem.status as string))).toBe(true);
497
613
  });
498
614
 
499
- it('shows the overlay status in the header when the overlay entry is newer than the snapshot', () => {
615
+ it('shows the overlay status in the subline below the title when the overlay entry is newer than the snapshot', () => {
500
616
  const { getByText, queryByText, container } = render(
501
617
  <ConsoleItemDetail
502
618
  item={issueItem}
@@ -505,8 +621,11 @@ describe('ConsoleItemDetail', () => {
505
621
  />,
506
622
  );
507
623
  const title = container.querySelector('.console-detail-title');
624
+ const subline = container.querySelector('.console-detail-topline');
508
625
  expect(title).not.toBeNull();
509
- expect(title?.contains(getByText('In Progress'))).toBe(true);
626
+ expect(subline).not.toBeNull();
627
+ expect(title?.contains(getByText('In Progress'))).toBe(false);
628
+ expect(subline?.contains(getByText('In Progress'))).toBe(true);
510
629
  expect(queryByText(issueItem.status as string)).toBeNull();
511
630
  });
512
631
 
@@ -178,7 +178,33 @@ export const ConsoleItemDetail = ({
178
178
 
179
179
  return (
180
180
  <article className="console-detail">
181
+ <h2 className="console-detail-title">
182
+ <ConsoleItemIcon
183
+ isPr={item.isPr}
184
+ state={resolvedState}
185
+ merged={merged}
186
+ isDraft={false}
187
+ stateReason=""
188
+ />
189
+ <span className="console-detail-title-text">{item.title}</span>
190
+ <span className="console-detail-number">
191
+ {item.isPr ? `PR #${item.number}` : `#${item.number}`}
192
+ </span>
193
+ </h2>
194
+
181
195
  <div className="console-detail-topline">
196
+ {displayStatus !== null && statusPalette !== null && (
197
+ <span
198
+ className="console-detail-status-chip"
199
+ style={{
200
+ color: statusPalette.fg,
201
+ borderColor: statusPalette.border,
202
+ backgroundColor: statusPalette.bg,
203
+ }}
204
+ >
205
+ {displayStatus.name}
206
+ </span>
207
+ )}
182
208
  {storyName !== null && (
183
209
  <span className="console-storytag">
184
210
  <span
@@ -228,38 +254,12 @@ export const ConsoleItemDetail = ({
228
254
  mergeableStatus={chip.mergeableStatus}
229
255
  />
230
256
  ))}
231
- </div>
232
-
233
- <h2 className="console-detail-title">
234
- {displayStatus !== null && statusPalette !== null && (
235
- <span
236
- className="console-detail-status-chip"
237
- style={{
238
- color: statusPalette.fg,
239
- borderColor: statusPalette.border,
240
- backgroundColor: statusPalette.bg,
241
- }}
242
- >
243
- {displayStatus.name}
244
- </span>
245
- )}
246
- <ConsoleItemIcon
247
- isPr={item.isPr}
248
- state={resolvedState}
249
- merged={merged}
250
- isDraft={false}
251
- stateReason=""
252
- />
253
- <span className="console-detail-title-text">{item.title}</span>
254
- <span className="console-detail-number">
255
- {item.isPr ? `PR #${item.number}` : `#${item.number}`}
256
- </span>
257
257
  {closedStateLabel !== null && (
258
258
  <span className="console-detail-closed-label">
259
259
  {closedStateLabel}
260
260
  </span>
261
261
  )}
262
- </h2>
262
+ </div>
263
263
 
264
264
  <ConsoleFetchFailureAlert failures={fetchFailures} />
265
265