github-issue-tower-defence-management 2.1.2 → 2.3.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.
- package/CHANGELOG.md +14 -0
- package/README.md +8 -0
- package/bin/adapter/entry-points/cli/fleetConfig.js +30 -12
- package/bin/adapter/entry-points/cli/fleetConfig.js.map +1 -1
- package/bin/adapter/entry-points/cli/index.js +5 -0
- package/bin/adapter/entry-points/cli/index.js.map +1 -1
- package/bin/adapter/entry-points/console/consoleDoneStore.js +0 -2
- package/bin/adapter/entry-points/console/consoleDoneStore.js.map +1 -1
- package/bin/adapter/entry-points/console/consoleTabNames.js +0 -1
- package/bin/adapter/entry-points/console/consoleTabNames.js.map +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/index-C5cOzhyn.js +86 -0
- package/bin/adapter/entry-points/console/ui-dist/index.html +1 -1
- package/bin/domain/usecases/StartPreparationUseCase.js +13 -12
- package/bin/domain/usecases/StartPreparationUseCase.js.map +1 -1
- package/bin/domain/usecases/console/GenerateConsoleListsUseCase.js +0 -15
- package/bin/domain/usecases/console/GenerateConsoleListsUseCase.js.map +1 -1
- package/package.json +1 -1
- package/src/adapter/entry-points/cli/fleetConfig.test.ts +96 -0
- package/src/adapter/entry-points/cli/fleetConfig.ts +51 -6
- package/src/adapter/entry-points/cli/index.test.ts +2 -0
- package/src/adapter/entry-points/cli/index.ts +16 -0
- package/src/adapter/entry-points/console/consoleDataDelivery.test.ts +15 -9
- package/src/adapter/entry-points/console/consoleDoneStore.ts +0 -2
- package/src/adapter/entry-points/console/consoleItemUrlLookup.test.ts +1 -1
- package/src/adapter/entry-points/console/consoleTabNames.ts +0 -1
- package/src/adapter/entry-points/console/ui/e2e/consoleScenario.spec.ts +7 -115
- package/src/adapter/entry-points/console/ui/e2e/consoleTestHarness.ts +0 -16
- package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemDetail.stories.tsx +1 -3
- package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsoleTabList.stories.tsx +0 -4
- package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsoleTabList.test.tsx +0 -1
- package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleOperationMenu.stories.tsx +0 -10
- package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleOperationMenu.test.tsx +2 -28
- package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleOperationMenu.tsx +0 -10
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleNavigation.test.ts +18 -14
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleOverlay.test.ts +2 -2
- package/src/adapter/entry-points/console/ui/src/features/console/logic/actionToast.test.ts +1 -1
- package/src/adapter/entry-points/console/ui/src/features/console/logic/grouping.test.ts +7 -7
- package/src/adapter/entry-points/console/ui/src/features/console/logic/overlay.test.ts +10 -8
- package/src/adapter/entry-points/console/ui/src/features/console/logic/tabAdvance.test.ts +9 -11
- package/src/adapter/entry-points/console/ui/src/features/console/logic/types.ts +1 -12
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleItemDetailContainer.test.tsx +0 -12
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleItemDetailContainer.tsx +0 -3
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.tsx +10 -57
- package/src/adapter/entry-points/console/ui-dist/assets/index-C5cOzhyn.js +86 -0
- package/src/adapter/entry-points/console/ui-dist/index.html +1 -1
- package/src/adapter/entry-points/console/webServer.test.ts +2 -2
- package/src/adapter/entry-points/handlers/consoleListsWriter.test.ts +0 -1
- package/src/domain/usecases/StartPreparationUseCase.test.ts +97 -0
- package/src/domain/usecases/StartPreparationUseCase.ts +13 -3
- package/src/domain/usecases/console/GenerateConsoleListsUseCase.test.ts +2 -160
- package/src/domain/usecases/console/GenerateConsoleListsUseCase.ts +0 -37
- package/types/adapter/entry-points/cli/fleetConfig.d.ts +6 -0
- package/types/adapter/entry-points/cli/fleetConfig.d.ts.map +1 -1
- package/types/adapter/entry-points/cli/index.d.ts.map +1 -1
- package/types/adapter/entry-points/console/consoleDoneStore.d.ts.map +1 -1
- package/types/adapter/entry-points/console/consoleTabNames.d.ts.map +1 -1
- package/types/domain/usecases/StartPreparationUseCase.d.ts +3 -1
- package/types/domain/usecases/StartPreparationUseCase.d.ts.map +1 -1
- package/types/domain/usecases/console/GenerateConsoleListsUseCase.d.ts +1 -11
- package/types/domain/usecases/console/GenerateConsoleListsUseCase.d.ts.map +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/index-BVyeR7xJ.js +0 -86
- package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleStoryActions.stories.tsx +0 -80
- package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleStoryActions.test.tsx +0 -39
- package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleStoryActions.tsx +0 -42
- package/src/adapter/entry-points/console/ui-dist/assets/index-BVyeR7xJ.js +0 -86
|
@@ -41,7 +41,7 @@ describe('findConsoleItemUrl', () => {
|
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
it('ignores a tab file that is not valid json', () => {
|
|
44
|
-
const dir = path.join(baseDir, 'acme', '
|
|
44
|
+
const dir = path.join(baseDir, 'acme', 'failed-preparation');
|
|
45
45
|
fs.mkdirSync(dir, { recursive: true });
|
|
46
46
|
fs.writeFileSync(path.join(dir, 'list.json'), 'not json');
|
|
47
47
|
writeList('prs', [{ url: 'https://github.com/o/r/issues/1' }]);
|
|
@@ -64,7 +64,7 @@ test('processing tabs drives auto-advance and keeps emptied badges at zero', asy
|
|
|
64
64
|
|
|
65
65
|
await expect(activeTabLabel(page)).toHaveText('Awaiting Quality Check');
|
|
66
66
|
await expect(tabBadge(page, 'Awaiting Quality Check')).toHaveText('1');
|
|
67
|
-
await expect(tabBadge(page, '
|
|
67
|
+
await expect(tabBadge(page, 'Failed Preparation')).toHaveText('1');
|
|
68
68
|
await expect(tabBadge(page, 'Todo by human')).toHaveText('1');
|
|
69
69
|
|
|
70
70
|
await itemRowByText(
|
|
@@ -77,7 +77,9 @@ test('processing tabs drives auto-advance and keeps emptied badges at zero', asy
|
|
|
77
77
|
await expect(approveButton).toBeVisible();
|
|
78
78
|
await approveButton.click();
|
|
79
79
|
|
|
80
|
-
await expect(activeTabLabel(page)).toHaveText('
|
|
80
|
+
await expect(activeTabLabel(page)).toHaveText('Failed Preparation', {
|
|
81
|
+
timeout: 8000,
|
|
82
|
+
});
|
|
81
83
|
await expect(tabByLabel(page, 'Awaiting Quality Check')).toHaveCount(0, {
|
|
82
84
|
timeout: 8000,
|
|
83
85
|
});
|
|
@@ -87,10 +89,10 @@ test('processing tabs drives auto-advance and keeps emptied badges at zero', asy
|
|
|
87
89
|
await expect(tabByLabel(page, 'Awaiting Quality Check')).toHaveCount(0);
|
|
88
90
|
await expect(tabBadge(page, 'Todo by human')).toHaveText('1');
|
|
89
91
|
|
|
90
|
-
await tabByLabel(page, '
|
|
91
|
-
await expect(activeTabLabel(page)).toHaveText('
|
|
92
|
+
await tabByLabel(page, 'Failed Preparation').click();
|
|
93
|
+
await expect(activeTabLabel(page)).toHaveText('Failed Preparation');
|
|
92
94
|
await expect(tabByLabel(page, 'Awaiting Quality Check')).toHaveCount(0);
|
|
93
|
-
await expect(tabBadge(page, '
|
|
95
|
+
await expect(tabBadge(page, 'Failed Preparation')).toHaveText('1');
|
|
94
96
|
});
|
|
95
97
|
|
|
96
98
|
test('renders the Workflow Blocker tab leftmost and shows its detail operations', async ({
|
|
@@ -309,80 +311,6 @@ test('opens the comment input with the item detail, keeps it on screen while the
|
|
|
309
311
|
expect(dockHeightAfterPosting).toBe(dockHeightBeforePosting);
|
|
310
312
|
});
|
|
311
313
|
|
|
312
|
-
test('preserves the unsent comment draft when swiping between tasks', async ({
|
|
313
|
-
page,
|
|
314
|
-
}) => {
|
|
315
|
-
await page.goto(harness.appRootUrl);
|
|
316
|
-
|
|
317
|
-
await tabByLabel(page, 'Triage').click();
|
|
318
|
-
|
|
319
|
-
await itemRowByText(
|
|
320
|
-
page,
|
|
321
|
-
'Add Sonnet to Opus weekly-limit fallback routing per token',
|
|
322
|
-
).click();
|
|
323
|
-
|
|
324
|
-
await expect(page.locator('.console-composer-input')).toBeVisible();
|
|
325
|
-
await page.locator('.console-composer-input').fill('work in progress draft');
|
|
326
|
-
|
|
327
|
-
const swipeDetailScreen = async (
|
|
328
|
-
fromX: number,
|
|
329
|
-
toX: number,
|
|
330
|
-
): Promise<void> => {
|
|
331
|
-
await page.evaluate(
|
|
332
|
-
([from, to]: [number, number]) => {
|
|
333
|
-
const screen = document.querySelector('.console-detail-screen');
|
|
334
|
-
if (!screen) throw new Error('.console-detail-screen not found');
|
|
335
|
-
const mkTouch = (x: number): Touch =>
|
|
336
|
-
new Touch({
|
|
337
|
-
identifier: 1,
|
|
338
|
-
target: screen,
|
|
339
|
-
clientX: x,
|
|
340
|
-
clientY: 200,
|
|
341
|
-
pageX: x,
|
|
342
|
-
pageY: 200,
|
|
343
|
-
});
|
|
344
|
-
screen.dispatchEvent(
|
|
345
|
-
new TouchEvent('touchstart', {
|
|
346
|
-
bubbles: true,
|
|
347
|
-
cancelable: true,
|
|
348
|
-
touches: [mkTouch(from)],
|
|
349
|
-
}),
|
|
350
|
-
);
|
|
351
|
-
screen.dispatchEvent(
|
|
352
|
-
new TouchEvent('touchmove', {
|
|
353
|
-
bubbles: true,
|
|
354
|
-
cancelable: true,
|
|
355
|
-
touches: [mkTouch(to)],
|
|
356
|
-
}),
|
|
357
|
-
);
|
|
358
|
-
screen.dispatchEvent(
|
|
359
|
-
new TouchEvent('touchend', {
|
|
360
|
-
bubbles: true,
|
|
361
|
-
cancelable: true,
|
|
362
|
-
changedTouches: [mkTouch(to)],
|
|
363
|
-
touches: [],
|
|
364
|
-
}),
|
|
365
|
-
);
|
|
366
|
-
},
|
|
367
|
-
[fromX, toX] as [number, number],
|
|
368
|
-
);
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
await swipeDetailScreen(300, 100);
|
|
372
|
-
await expect(page).toHaveURL(/PVTI_lADOABCD1234zgTRI00692/, {
|
|
373
|
-
timeout: 3000,
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
await swipeDetailScreen(100, 300);
|
|
377
|
-
await expect(page).toHaveURL(/PVTI_lADOABCD1234zgTRI00778/, {
|
|
378
|
-
timeout: 3000,
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
await expect(page.locator('.console-composer-input')).toHaveValue(
|
|
382
|
-
'work in progress draft',
|
|
383
|
-
);
|
|
384
|
-
});
|
|
385
|
-
|
|
386
314
|
test('renders the stories tab with non-gray stories, their open item counts, and an add-task button', async ({
|
|
387
315
|
page,
|
|
388
316
|
}) => {
|
|
@@ -599,42 +527,6 @@ test('changes the color of a story row via the color palette in the stories tab'
|
|
|
599
527
|
await expect(palette).toHaveCount(0);
|
|
600
528
|
});
|
|
601
529
|
|
|
602
|
-
test('reorders stories on the triage tab with up/down buttons', async ({
|
|
603
|
-
page,
|
|
604
|
-
}) => {
|
|
605
|
-
await page.goto(harness.appRootUrl);
|
|
606
|
-
|
|
607
|
-
await tabByLabel(page, 'Triage').click();
|
|
608
|
-
|
|
609
|
-
const reorderPanel = page.locator('.console-story-reorder-panel');
|
|
610
|
-
await expect(reorderPanel).toBeVisible();
|
|
611
|
-
|
|
612
|
-
const rows = reorderPanel.locator('.console-story-reorder-row');
|
|
613
|
-
await expect(rows).toHaveCount(3);
|
|
614
|
-
|
|
615
|
-
await expect(rows.nth(0)).toContainText('TDPM Console port');
|
|
616
|
-
await expect(rows.nth(1)).toContainText('Publish product documentation site');
|
|
617
|
-
await expect(rows.nth(2)).toContainText('regular / WORKFLOW BLOCKER');
|
|
618
|
-
|
|
619
|
-
await rows.nth(0).locator('[aria-label="Move down"]').click();
|
|
620
|
-
|
|
621
|
-
await expect
|
|
622
|
-
.poll(() => harness.reorderStoryCalls.length, { timeout: 5000 })
|
|
623
|
-
.toBe(1);
|
|
624
|
-
|
|
625
|
-
await expect(rows.nth(0)).toContainText('Publish product documentation site');
|
|
626
|
-
await expect(rows.nth(1)).toContainText('TDPM Console port');
|
|
627
|
-
|
|
628
|
-
await rows.nth(1).locator('[aria-label="Move up"]').click();
|
|
629
|
-
|
|
630
|
-
await expect
|
|
631
|
-
.poll(() => harness.reorderStoryCalls.length, { timeout: 5000 })
|
|
632
|
-
.toBe(2);
|
|
633
|
-
|
|
634
|
-
await expect(rows.nth(0)).toContainText('TDPM Console port');
|
|
635
|
-
await expect(rows.nth(1)).toContainText('Publish product documentation site');
|
|
636
|
-
});
|
|
637
|
-
|
|
638
530
|
test('posts a comment and moves the item to Awaiting Workspace when the Comment & Awaiting Workspace button is clicked', async ({
|
|
639
531
|
page,
|
|
640
532
|
}) => {
|
|
@@ -232,22 +232,6 @@ export const CONSOLE_E2E_TAB_ITEMS: Record<string, ConsoleFixtureListItem[]> = {
|
|
|
232
232
|
'2026-06-17T23:41:08.000Z',
|
|
233
233
|
),
|
|
234
234
|
],
|
|
235
|
-
triage: [
|
|
236
|
-
issueItem(
|
|
237
|
-
778,
|
|
238
|
-
'Add Sonnet to Opus weekly-limit fallback routing per token',
|
|
239
|
-
'TRI00778',
|
|
240
|
-
'regular / workflow improvement',
|
|
241
|
-
'2026-06-12T23:01:55.000Z',
|
|
242
|
-
),
|
|
243
|
-
issueItem(
|
|
244
|
-
692,
|
|
245
|
-
'Publish the generated documentation site to GitHub Pages',
|
|
246
|
-
'TRI00692',
|
|
247
|
-
'Publish product documentation site',
|
|
248
|
-
'2026-06-10T11:42:00.000Z',
|
|
249
|
-
),
|
|
250
|
-
],
|
|
251
235
|
'failed-preparation': [
|
|
252
236
|
{
|
|
253
237
|
...issueItem(
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
consoleMermaidBodyFixture,
|
|
9
9
|
consoleRelatedPullRequestsFixture,
|
|
10
10
|
consoleStatusOptionsFixture,
|
|
11
|
-
consoleStoryOptionsFixture,
|
|
12
11
|
} from '../../testing/fixtures';
|
|
13
12
|
import { ConsoleOperationMenu } from '../operations/ConsoleOperationMenu';
|
|
14
13
|
import { ConsoleItemDetail } from './ConsoleItemDetail';
|
|
@@ -257,12 +256,11 @@ export const IssueWithRichMarkdownBody: Story = {
|
|
|
257
256
|
relatedPullRequests: [],
|
|
258
257
|
operationBar: (
|
|
259
258
|
<ConsoleOperationMenu
|
|
260
|
-
tab="
|
|
259
|
+
tab="todo-by-human"
|
|
261
260
|
item={consoleListItemsFixture[2]}
|
|
262
261
|
hasPullRequest={false}
|
|
263
262
|
rejectEnabled={false}
|
|
264
263
|
statusOptions={consoleStatusOptionsFixture}
|
|
265
|
-
storyOptions={consoleStoryOptionsFixture}
|
|
266
264
|
handlers={noopOperationHandlers}
|
|
267
265
|
/>
|
|
268
266
|
),
|
|
@@ -26,7 +26,6 @@ type Story = StoryObj<typeof ConsoleTabList>;
|
|
|
26
26
|
const counts: Record<ConsoleTabName, number> = {
|
|
27
27
|
'workflow-blocker': 5,
|
|
28
28
|
prs: 35,
|
|
29
|
-
triage: 132,
|
|
30
29
|
'failed-preparation': 2,
|
|
31
30
|
'todo-by-human': 66,
|
|
32
31
|
'todo-by-agent': 24,
|
|
@@ -46,7 +45,6 @@ export const ZeroCountTabsHidden: Story = {
|
|
|
46
45
|
counts: {
|
|
47
46
|
'workflow-blocker': 0,
|
|
48
47
|
prs: 35,
|
|
49
|
-
triage: 0,
|
|
50
48
|
'failed-preparation': 0,
|
|
51
49
|
'todo-by-human': 18,
|
|
52
50
|
'todo-by-agent': 0,
|
|
@@ -61,7 +59,6 @@ export const ZeroCountActiveTabStaysVisible: Story = {
|
|
|
61
59
|
counts: {
|
|
62
60
|
'workflow-blocker': 0,
|
|
63
61
|
prs: 35,
|
|
64
|
-
triage: 0,
|
|
65
62
|
'failed-preparation': 0,
|
|
66
63
|
'todo-by-human': 18,
|
|
67
64
|
'todo-by-agent': 0,
|
|
@@ -76,7 +73,6 @@ export const AfterAutoAdvanceToNextTab: Story = {
|
|
|
76
73
|
counts: {
|
|
77
74
|
'workflow-blocker': 0,
|
|
78
75
|
prs: 0,
|
|
79
|
-
triage: 0,
|
|
80
76
|
'failed-preparation': 2,
|
|
81
77
|
'todo-by-human': 4,
|
|
82
78
|
'todo-by-agent': 0,
|
|
@@ -3,7 +3,6 @@ import type { ConsoleOperationHandlers } from '../../logic/operations';
|
|
|
3
3
|
import {
|
|
4
4
|
consoleListItemsFixture,
|
|
5
5
|
consoleStatusOptionsFixture,
|
|
6
|
-
consoleStoryOptionsFixture,
|
|
7
6
|
} from '../../testing/fixtures';
|
|
8
7
|
import { ConsoleOperationMenu } from './ConsoleOperationMenu';
|
|
9
8
|
|
|
@@ -23,7 +22,6 @@ const meta: Meta<typeof ConsoleOperationMenu> = {
|
|
|
23
22
|
args: {
|
|
24
23
|
rejectEnabled: false,
|
|
25
24
|
statusOptions: consoleStatusOptionsFixture,
|
|
26
|
-
storyOptions: consoleStoryOptionsFixture,
|
|
27
25
|
handlers,
|
|
28
26
|
},
|
|
29
27
|
};
|
|
@@ -49,14 +47,6 @@ export const PrsTabPullRequestRejectEnabled: Story = {
|
|
|
49
47
|
},
|
|
50
48
|
};
|
|
51
49
|
|
|
52
|
-
export const TriageTabIssueWithStoryGroup: Story = {
|
|
53
|
-
args: {
|
|
54
|
-
tab: 'triage',
|
|
55
|
-
item: consoleListItemsFixture[2],
|
|
56
|
-
hasPullRequest: false,
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
|
|
60
50
|
export const TodoByHumanTabIssue: Story = {
|
|
61
51
|
args: {
|
|
62
52
|
tab: 'todo-by-human',
|
|
@@ -3,7 +3,6 @@ import type { ConsoleOperationHandlers } from '../../logic/operations';
|
|
|
3
3
|
import {
|
|
4
4
|
consoleListItemsFixture,
|
|
5
5
|
consoleStatusOptionsFixture,
|
|
6
|
-
consoleStoryOptionsFixture,
|
|
7
6
|
} from '../../testing/fixtures';
|
|
8
7
|
import { ConsoleOperationMenu } from './ConsoleOperationMenu';
|
|
9
8
|
|
|
@@ -21,7 +20,7 @@ const prItem = consoleListItemsFixture[0];
|
|
|
21
20
|
const issueItem = consoleListItemsFixture[2];
|
|
22
21
|
|
|
23
22
|
describe('ConsoleOperationMenu', () => {
|
|
24
|
-
it('shows the review and close groups for a PR
|
|
23
|
+
it('shows the review and close groups for a PR on the prs tab', () => {
|
|
25
24
|
const { getByText, queryByText } = render(
|
|
26
25
|
<ConsoleOperationMenu
|
|
27
26
|
tab="prs"
|
|
@@ -29,7 +28,6 @@ describe('ConsoleOperationMenu', () => {
|
|
|
29
28
|
hasPullRequest
|
|
30
29
|
rejectEnabled={false}
|
|
31
30
|
statusOptions={consoleStatusOptionsFixture}
|
|
32
|
-
storyOptions={consoleStoryOptionsFixture}
|
|
33
31
|
handlers={handlers}
|
|
34
32
|
/>,
|
|
35
33
|
);
|
|
@@ -42,23 +40,6 @@ describe('ConsoleOperationMenu', () => {
|
|
|
42
40
|
expect(queryByText('TDPM Console port')).toBeNull();
|
|
43
41
|
});
|
|
44
42
|
|
|
45
|
-
it('shows the story group on the triage tab and the close group for an issue', () => {
|
|
46
|
-
const { getByText } = render(
|
|
47
|
-
<ConsoleOperationMenu
|
|
48
|
-
tab="triage"
|
|
49
|
-
item={issueItem}
|
|
50
|
-
hasPullRequest={false}
|
|
51
|
-
rejectEnabled={false}
|
|
52
|
-
statusOptions={consoleStatusOptionsFixture}
|
|
53
|
-
storyOptions={consoleStoryOptionsFixture}
|
|
54
|
-
handlers={handlers}
|
|
55
|
-
/>,
|
|
56
|
-
);
|
|
57
|
-
expect(getByText('Move to Okinawa')).toBeInTheDocument();
|
|
58
|
-
expect(getByText('Close')).toBeInTheDocument();
|
|
59
|
-
expect(getByText('Close as not planned')).toBeInTheDocument();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
43
|
it('shows +1 week and skip on the todo-by-human tab', () => {
|
|
63
44
|
const { getByText } = render(
|
|
64
45
|
<ConsoleOperationMenu
|
|
@@ -67,7 +48,6 @@ describe('ConsoleOperationMenu', () => {
|
|
|
67
48
|
hasPullRequest={false}
|
|
68
49
|
rejectEnabled={false}
|
|
69
50
|
statusOptions={consoleStatusOptionsFixture}
|
|
70
|
-
storyOptions={consoleStoryOptionsFixture}
|
|
71
51
|
handlers={handlers}
|
|
72
52
|
/>,
|
|
73
53
|
);
|
|
@@ -82,7 +62,6 @@ describe('ConsoleOperationMenu', () => {
|
|
|
82
62
|
hasPullRequest={false}
|
|
83
63
|
rejectEnabled={false}
|
|
84
64
|
statusOptions={consoleStatusOptionsFixture}
|
|
85
|
-
storyOptions={consoleStoryOptionsFixture}
|
|
86
65
|
handlers={handlers}
|
|
87
66
|
/>,
|
|
88
67
|
);
|
|
@@ -97,7 +76,6 @@ describe('ConsoleOperationMenu', () => {
|
|
|
97
76
|
hasPullRequest={false}
|
|
98
77
|
rejectEnabled={false}
|
|
99
78
|
statusOptions={consoleStatusOptionsFixture}
|
|
100
|
-
storyOptions={consoleStoryOptionsFixture}
|
|
101
79
|
handlers={handlers}
|
|
102
80
|
/>,
|
|
103
81
|
);
|
|
@@ -105,7 +83,7 @@ describe('ConsoleOperationMenu', () => {
|
|
|
105
83
|
expect(queryByText('Close')).not.toBeNull();
|
|
106
84
|
});
|
|
107
85
|
|
|
108
|
-
it('shows status, close and next-action groups
|
|
86
|
+
it('shows status, close and next-action groups on the workflow-blocker tab', () => {
|
|
109
87
|
const { getByText, queryByText } = render(
|
|
110
88
|
<ConsoleOperationMenu
|
|
111
89
|
tab="workflow-blocker"
|
|
@@ -113,7 +91,6 @@ describe('ConsoleOperationMenu', () => {
|
|
|
113
91
|
hasPullRequest={false}
|
|
114
92
|
rejectEnabled={false}
|
|
115
93
|
statusOptions={consoleStatusOptionsFixture}
|
|
116
|
-
storyOptions={consoleStoryOptionsFixture}
|
|
117
94
|
handlers={handlers}
|
|
118
95
|
/>,
|
|
119
96
|
);
|
|
@@ -133,7 +110,6 @@ describe('ConsoleOperationMenu', () => {
|
|
|
133
110
|
hasPullRequest
|
|
134
111
|
rejectEnabled={false}
|
|
135
112
|
statusOptions={consoleStatusOptionsFixture}
|
|
136
|
-
storyOptions={consoleStoryOptionsFixture}
|
|
137
113
|
handlers={handlers}
|
|
138
114
|
/>,
|
|
139
115
|
);
|
|
@@ -149,7 +125,6 @@ describe('ConsoleOperationMenu', () => {
|
|
|
149
125
|
hasPullRequest
|
|
150
126
|
rejectEnabled={false}
|
|
151
127
|
statusOptions={consoleStatusOptionsFixture}
|
|
152
|
-
storyOptions={consoleStoryOptionsFixture}
|
|
153
128
|
handlers={handlers}
|
|
154
129
|
/>,
|
|
155
130
|
);
|
|
@@ -161,7 +136,6 @@ describe('ConsoleOperationMenu', () => {
|
|
|
161
136
|
hasPullRequest
|
|
162
137
|
rejectEnabled={true}
|
|
163
138
|
statusOptions={consoleStatusOptionsFixture}
|
|
164
|
-
storyOptions={consoleStoryOptionsFixture}
|
|
165
139
|
handlers={handlers}
|
|
166
140
|
/>,
|
|
167
141
|
);
|
|
@@ -12,7 +12,6 @@ import { ConsoleNextActionDateActions } from './ConsoleNextActionDateActions';
|
|
|
12
12
|
import { ConsoleOkAndAwaitingWorkspaceActions } from './ConsoleOkAndAwaitingWorkspaceActions';
|
|
13
13
|
import { ConsolePullRequestReviewActions } from './ConsolePullRequestReviewActions';
|
|
14
14
|
import { ConsoleStatusActions } from './ConsoleStatusActions';
|
|
15
|
-
import { ConsoleStoryActions } from './ConsoleStoryActions';
|
|
16
15
|
|
|
17
16
|
export type ConsoleOperationBarProps = {
|
|
18
17
|
tab: ConsoleTabName;
|
|
@@ -20,7 +19,6 @@ export type ConsoleOperationBarProps = {
|
|
|
20
19
|
hasPullRequest: boolean;
|
|
21
20
|
rejectEnabled: boolean;
|
|
22
21
|
statusOptions: ConsoleFieldOption[];
|
|
23
|
-
storyOptions: ConsoleFieldOption[];
|
|
24
22
|
handlers: ConsoleOperationHandlers;
|
|
25
23
|
};
|
|
26
24
|
|
|
@@ -29,10 +27,8 @@ export const ConsoleOperationMenu = ({
|
|
|
29
27
|
hasPullRequest,
|
|
30
28
|
rejectEnabled,
|
|
31
29
|
statusOptions,
|
|
32
|
-
storyOptions,
|
|
33
30
|
handlers,
|
|
34
31
|
}: ConsoleOperationBarProps) => {
|
|
35
|
-
const showStory = tab === 'triage';
|
|
36
32
|
return (
|
|
37
33
|
<div className="console-operation-bar">
|
|
38
34
|
<ConsoleOkAndAwaitingWorkspaceActions
|
|
@@ -49,12 +45,6 @@ export const ConsoleOperationMenu = ({
|
|
|
49
45
|
isManualTriage={isManualTriageTab(tab)}
|
|
50
46
|
onSetNextActionDate={handlers.onSetNextActionDate}
|
|
51
47
|
/>
|
|
52
|
-
{showStory && (
|
|
53
|
-
<ConsoleStoryActions
|
|
54
|
-
storyOptions={storyOptions}
|
|
55
|
-
onSetStory={handlers.onSetStory}
|
|
56
|
-
/>
|
|
57
|
-
)}
|
|
58
48
|
<ConsoleStatusActions
|
|
59
49
|
statusOptions={statusOptions}
|
|
60
50
|
onSetStatus={handlers.onSetStatus}
|
package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleNavigation.test.ts
CHANGED
|
@@ -11,7 +11,6 @@ const counts = (
|
|
|
11
11
|
): Record<ConsoleTabName, number> => ({
|
|
12
12
|
'workflow-blocker': 0,
|
|
13
13
|
prs: 0,
|
|
14
|
-
triage: 0,
|
|
15
14
|
'failed-preparation': 0,
|
|
16
15
|
'todo-by-human': 0,
|
|
17
16
|
'todo-by-agent': 0,
|
|
@@ -21,13 +20,17 @@ const counts = (
|
|
|
21
20
|
|
|
22
21
|
describe('parseTabFromPath', () => {
|
|
23
22
|
it('reads a known tab from the project path', () => {
|
|
24
|
-
expect(parseTabFromPath('/projects/acme/
|
|
23
|
+
expect(parseTabFromPath('/projects/acme/prs')).toBe('prs');
|
|
25
24
|
});
|
|
26
25
|
|
|
27
26
|
it('returns null for an unknown tab segment', () => {
|
|
28
27
|
expect(parseTabFromPath('/projects/acme/unknown')).toBeNull();
|
|
29
28
|
});
|
|
30
29
|
|
|
30
|
+
it('returns null for the removed triage segment', () => {
|
|
31
|
+
expect(parseTabFromPath('/projects/acme/triage')).toBeNull();
|
|
32
|
+
});
|
|
33
|
+
|
|
31
34
|
it('returns null when there is no tab segment', () => {
|
|
32
35
|
expect(parseTabFromPath('/projects/acme')).toBeNull();
|
|
33
36
|
});
|
|
@@ -56,16 +59,18 @@ describe('useConsoleNavigation', () => {
|
|
|
56
59
|
|
|
57
60
|
it('builds a project tab href', () => {
|
|
58
61
|
const { result } = renderHook(() => useConsoleNavigation('acme', counts()));
|
|
59
|
-
expect(result.current.tabHref('
|
|
62
|
+
expect(result.current.tabHref('todo-by-human')).toBe(
|
|
63
|
+
'/projects/acme/todo-by-human',
|
|
64
|
+
);
|
|
60
65
|
});
|
|
61
66
|
|
|
62
67
|
it('selects a tab and updates the path', () => {
|
|
63
68
|
const { result } = renderHook(() => useConsoleNavigation('acme', counts()));
|
|
64
69
|
act(() => {
|
|
65
|
-
result.current.selectTab('
|
|
70
|
+
result.current.selectTab('todo-by-human');
|
|
66
71
|
});
|
|
67
|
-
expect(result.current.activeTab).toBe('
|
|
68
|
-
expect(window.location.pathname).toBe('/projects/acme/
|
|
72
|
+
expect(result.current.activeTab).toBe('todo-by-human');
|
|
73
|
+
expect(window.location.pathname).toBe('/projects/acme/todo-by-human');
|
|
69
74
|
});
|
|
70
75
|
|
|
71
76
|
it('opens an item and reflects it in the hash', () => {
|
|
@@ -101,7 +106,6 @@ describe('useConsoleNavigation default tab without a tab segment', () => {
|
|
|
101
106
|
counts({
|
|
102
107
|
'workflow-blocker': 3,
|
|
103
108
|
prs: 5,
|
|
104
|
-
triage: 2,
|
|
105
109
|
'failed-preparation': 1,
|
|
106
110
|
'todo-by-human': 4,
|
|
107
111
|
}),
|
|
@@ -114,10 +118,10 @@ describe('useConsoleNavigation default tab without a tab segment', () => {
|
|
|
114
118
|
const { result } = renderHook(() =>
|
|
115
119
|
useConsoleNavigation(
|
|
116
120
|
'acme',
|
|
117
|
-
counts({ 'workflow-blocker': 0, prs: 0,
|
|
121
|
+
counts({ 'workflow-blocker': 0, prs: 0, 'failed-preparation': 8 }),
|
|
118
122
|
),
|
|
119
123
|
);
|
|
120
|
-
expect(result.current.activeTab).toBe('
|
|
124
|
+
expect(result.current.activeTab).toBe('failed-preparation');
|
|
121
125
|
});
|
|
122
126
|
|
|
123
127
|
it('falls back to the first tab when every tab is empty', () => {
|
|
@@ -132,15 +136,15 @@ describe('useConsoleNavigation default tab without a tab segment', () => {
|
|
|
132
136
|
{ initialProps: { tabCounts: counts() } },
|
|
133
137
|
);
|
|
134
138
|
expect(result.current.activeTab).toBe('workflow-blocker');
|
|
135
|
-
rerender({ tabCounts: counts({
|
|
136
|
-
expect(result.current.activeTab).toBe('
|
|
139
|
+
rerender({ tabCounts: counts({ 'failed-preparation': 6 }) });
|
|
140
|
+
expect(result.current.activeTab).toBe('failed-preparation');
|
|
137
141
|
});
|
|
138
142
|
|
|
139
143
|
it('keeps the tab from the path even when counts are present', () => {
|
|
140
|
-
window.history.replaceState({}, '', '/projects/acme/
|
|
144
|
+
window.history.replaceState({}, '', '/projects/acme/todo-by-human?k=token');
|
|
141
145
|
const { result } = renderHook(() =>
|
|
142
|
-
useConsoleNavigation('acme', counts({
|
|
146
|
+
useConsoleNavigation('acme', counts({ 'todo-by-human': 6 })),
|
|
143
147
|
);
|
|
144
|
-
expect(result.current.activeTab).toBe('
|
|
148
|
+
expect(result.current.activeTab).toBe('todo-by-human');
|
|
145
149
|
});
|
|
146
150
|
});
|
package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleOverlay.test.ts
CHANGED
|
@@ -19,10 +19,10 @@ describe('useConsoleOverlay', () => {
|
|
|
19
19
|
it('patches and persists overlay entries with timestamp and mode', () => {
|
|
20
20
|
const { result } = renderHook(() => useConsoleOverlay('acme'));
|
|
21
21
|
act(() => {
|
|
22
|
-
result.current.patchOverlay('PVTI_2', { done: true }, '
|
|
22
|
+
result.current.patchOverlay('PVTI_2', { done: true }, 'todo-by-human');
|
|
23
23
|
});
|
|
24
24
|
expect(result.current.overlay.PVTI_2?.done).toBe(true);
|
|
25
|
-
expect(result.current.overlay.PVTI_2?.mode).toBe('
|
|
25
|
+
expect(result.current.overlay.PVTI_2?.mode).toBe('todo-by-human');
|
|
26
26
|
const stored = JSON.parse(
|
|
27
27
|
localStorage.getItem(overlayStorageKey('acme')) ?? '{}',
|
|
28
28
|
);
|
|
@@ -47,7 +47,7 @@ describe('resolveItemStory', () => {
|
|
|
47
47
|
const overlay: ConsoleOverlay = {
|
|
48
48
|
PVTI_1: {
|
|
49
49
|
ts: 1,
|
|
50
|
-
mode: '
|
|
50
|
+
mode: 'todo-by-human',
|
|
51
51
|
story: { name: 'Overlay', color: 'BLUE' },
|
|
52
52
|
},
|
|
53
53
|
};
|
|
@@ -73,7 +73,7 @@ describe('resolveItemStory', () => {
|
|
|
73
73
|
const overlay: ConsoleOverlay = {
|
|
74
74
|
PVTI_4: {
|
|
75
75
|
ts: snapshotTs,
|
|
76
|
-
mode: '
|
|
76
|
+
mode: 'todo-by-human',
|
|
77
77
|
story: { name: 'FreshOverlay', color: 'GREEN' },
|
|
78
78
|
},
|
|
79
79
|
};
|
|
@@ -92,7 +92,7 @@ describe('resolveItemStory', () => {
|
|
|
92
92
|
const overlay: ConsoleOverlay = {
|
|
93
93
|
PVTI_5: {
|
|
94
94
|
ts: overlayTs,
|
|
95
|
-
mode: '
|
|
95
|
+
mode: 'todo-by-human',
|
|
96
96
|
story: { name: 'StaleOverlay', color: 'RED' },
|
|
97
97
|
},
|
|
98
98
|
};
|
|
@@ -109,7 +109,7 @@ describe('resolveItemStory', () => {
|
|
|
109
109
|
const overlay: ConsoleOverlay = {
|
|
110
110
|
PVTI_6: {
|
|
111
111
|
ts: 1,
|
|
112
|
-
mode: '
|
|
112
|
+
mode: 'todo-by-human',
|
|
113
113
|
story: { name: 'OverlayStory', color: 'BLUE' },
|
|
114
114
|
},
|
|
115
115
|
};
|
|
@@ -122,7 +122,7 @@ describe('resolveItemStory', () => {
|
|
|
122
122
|
const overlay: ConsoleOverlay = {
|
|
123
123
|
PVTI_7: {
|
|
124
124
|
ts: 1,
|
|
125
|
-
mode: '
|
|
125
|
+
mode: 'todo-by-human',
|
|
126
126
|
story: { name: 'OverlayStory', color: 'BLUE' },
|
|
127
127
|
},
|
|
128
128
|
};
|
|
@@ -166,7 +166,7 @@ describe('buildConsoleListRows', () => {
|
|
|
166
166
|
const overlay: ConsoleOverlay = {
|
|
167
167
|
PVTI_1: {
|
|
168
168
|
ts: 1,
|
|
169
|
-
mode: '
|
|
169
|
+
mode: 'todo-by-human',
|
|
170
170
|
story: { name: 'Alpha', color: 'BLUE' },
|
|
171
171
|
},
|
|
172
172
|
};
|
|
@@ -212,7 +212,7 @@ describe('buildConsoleListRows', () => {
|
|
|
212
212
|
const overlay: ConsoleOverlay = {
|
|
213
213
|
PVTI_1: {
|
|
214
214
|
ts: overlayTs,
|
|
215
|
-
mode: '
|
|
215
|
+
mode: 'todo-by-human',
|
|
216
216
|
story: { name: 'StaleStory', color: 'RED' },
|
|
217
217
|
},
|
|
218
218
|
};
|
|
@@ -70,9 +70,9 @@ describe('isOverlayEntryActed', () => {
|
|
|
70
70
|
});
|
|
71
71
|
|
|
72
72
|
it('treats a done entry as acted regardless of the mode it was written in', () => {
|
|
73
|
-
expect(
|
|
74
|
-
true,
|
|
75
|
-
);
|
|
73
|
+
expect(
|
|
74
|
+
isOverlayEntryActed({ ts: 100, mode: 'todo-by-human', done: true }),
|
|
75
|
+
).toBe(true);
|
|
76
76
|
});
|
|
77
77
|
});
|
|
78
78
|
|
|
@@ -86,7 +86,7 @@ describe('counts driven to zero do not revive on tab switch', () => {
|
|
|
86
86
|
|
|
87
87
|
it('does not subtract a done item from a tab other than the one it was processed in', () => {
|
|
88
88
|
const overlay: ConsoleOverlay = {
|
|
89
|
-
PVTI_1: { ts: 100, mode: '
|
|
89
|
+
PVTI_1: { ts: 100, mode: 'todo-by-human', done: true },
|
|
90
90
|
};
|
|
91
91
|
expect(countPendingItems([item(1)], overlay, 'prs')).toBe(1);
|
|
92
92
|
});
|
|
@@ -102,8 +102,10 @@ describe('counts driven to zero do not revive on tab switch', () => {
|
|
|
102
102
|
const overlay: ConsoleOverlay = {
|
|
103
103
|
PVTI_1: { ts: 100, mode: 'prs', done: true },
|
|
104
104
|
};
|
|
105
|
-
expect(countPendingItems([item(1)], overlay, '
|
|
106
|
-
expect(filterPendingItems([item(1)], overlay, '
|
|
105
|
+
expect(countPendingItems([item(1)], overlay, 'todo-by-human')).toBe(1);
|
|
106
|
+
expect(filterPendingItems([item(1)], overlay, 'todo-by-human')).toEqual([
|
|
107
|
+
item(1),
|
|
108
|
+
]);
|
|
107
109
|
});
|
|
108
110
|
|
|
109
111
|
it('counts an item that has no done entry', () => {
|
|
@@ -237,14 +239,14 @@ describe('writeOverlayEntry', () => {
|
|
|
237
239
|
overlay,
|
|
238
240
|
'PVTI_1',
|
|
239
241
|
{ story: { name: 'New Story', color: 'GREEN' } },
|
|
240
|
-
'
|
|
242
|
+
'todo-by-human',
|
|
241
243
|
999,
|
|
242
244
|
);
|
|
243
245
|
expect(next.PVTI_1).toEqual({
|
|
244
246
|
done: true,
|
|
245
247
|
story: { name: 'New Story', color: 'GREEN' },
|
|
246
248
|
ts: 999,
|
|
247
|
-
mode: '
|
|
249
|
+
mode: 'todo-by-human',
|
|
248
250
|
});
|
|
249
251
|
});
|
|
250
252
|
});
|