github-issue-tower-defence-management 1.99.1 → 1.101.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/.github/workflows/close-manual-prs.yml +49 -15
- package/.github/workflows/umino-project.yml +1 -3
- package/CHANGELOG.md +14 -0
- package/bin/adapter/entry-points/console/ui-dist/assets/index-DP5DGKUj.js +101 -0
- package/bin/adapter/entry-points/console/ui-dist/assets/{index-N39d52Zc.css → index-ES6SLB1Y.css} +1 -1
- package/bin/adapter/entry-points/console/ui-dist/index.html +2 -2
- package/bin/domain/usecases/console/GenerateConsoleListsUseCase.js +4 -0
- package/bin/domain/usecases/console/GenerateConsoleListsUseCase.js.map +1 -1
- package/package.json +1 -1
- package/src/adapter/entry-points/console/ui/e2e/consoleTestHarness.ts +12 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleItemList.test.tsx +12 -3
- package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleItemSummary.stories.tsx +4 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleItemSummary.test.tsx +48 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleItemSummary.tsx +40 -0
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleItemDetailData.test.ts +4 -0
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleNavigation.test.ts +87 -5
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleNavigation.ts +21 -4
- package/src/adapter/entry-points/console/ui/src/features/console/logic/grouping.test.ts +4 -0
- package/src/adapter/entry-points/console/ui/src/features/console/logic/overlay.test.ts +4 -0
- package/src/adapter/entry-points/console/ui/src/features/console/logic/tabAdvance.test.ts +33 -1
- package/src/adapter/entry-points/console/ui/src/features/console/logic/tabAdvance.ts +11 -0
- package/src/adapter/entry-points/console/ui/src/features/console/logic/types.ts +4 -0
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.test.tsx +58 -15
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.tsx +9 -8
- package/src/adapter/entry-points/console/ui/src/features/console/testing/fixtures.ts +22 -0
- package/src/adapter/entry-points/console/ui/src/index.css +24 -0
- package/src/adapter/entry-points/console/ui-dist/assets/index-DP5DGKUj.js +101 -0
- package/src/adapter/entry-points/console/ui-dist/assets/{index-N39d52Zc.css → index-ES6SLB1Y.css} +1 -1
- package/src/adapter/entry-points/console/ui-dist/index.html +2 -2
- package/src/domain/usecases/console/GenerateConsoleListsUseCase.test.ts +43 -0
- package/src/domain/usecases/console/GenerateConsoleListsUseCase.ts +9 -0
- package/types/domain/usecases/console/GenerateConsoleListsUseCase.d.ts +4 -0
- package/types/domain/usecases/console/GenerateConsoleListsUseCase.d.ts.map +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/index-D79mM9lz.js +0 -101
- package/src/adapter/entry-points/console/ui-dist/assets/index-D79mM9lz.js +0 -101
|
@@ -1,6 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
act,
|
|
3
|
+
fireEvent,
|
|
4
|
+
render,
|
|
5
|
+
waitFor,
|
|
6
|
+
within,
|
|
7
|
+
} from '@testing-library/react';
|
|
2
8
|
import { ConsolePage } from './ConsolePage';
|
|
3
9
|
|
|
10
|
+
const tabBar = (): HTMLElement => {
|
|
11
|
+
const nav = document.querySelector('nav.console-tabbar');
|
|
12
|
+
if (nav === null) {
|
|
13
|
+
throw new Error('console tab bar not found');
|
|
14
|
+
}
|
|
15
|
+
return nav as HTMLElement;
|
|
16
|
+
};
|
|
17
|
+
|
|
4
18
|
jest.mock('../lib/mermaidLoader', () => ({
|
|
5
19
|
renderMermaidToSvg: jest.fn(async () => '<svg></svg>'),
|
|
6
20
|
}));
|
|
@@ -24,6 +38,10 @@ const listPayload = (tab: string) => ({
|
|
|
24
38
|
itemId: 'PVTI_1',
|
|
25
39
|
isPr: true,
|
|
26
40
|
story: 'TDPM Console port',
|
|
41
|
+
status: 'Awaiting Quality Check',
|
|
42
|
+
nextActionDate: null,
|
|
43
|
+
nextActionHour: null,
|
|
44
|
+
dependedIssueUrls: [],
|
|
27
45
|
labels: [],
|
|
28
46
|
createdAt: '2026-06-17T00:00:00.000Z',
|
|
29
47
|
},
|
|
@@ -40,6 +58,10 @@ const listPayload = (tab: string) => ({
|
|
|
40
58
|
itemId: 'PVTI_2',
|
|
41
59
|
isPr: false,
|
|
42
60
|
story: 'TDPM Console port',
|
|
61
|
+
status: 'Unread',
|
|
62
|
+
nextActionDate: null,
|
|
63
|
+
nextActionHour: null,
|
|
64
|
+
dependedIssueUrls: [],
|
|
43
65
|
labels: [],
|
|
44
66
|
createdAt: '2026-06-18T00:00:00.000Z',
|
|
45
67
|
},
|
|
@@ -74,8 +96,12 @@ describe('ConsolePage', () => {
|
|
|
74
96
|
await waitFor(() => {
|
|
75
97
|
expect(getByText('Add serveConsole subcommand')).toBeInTheDocument();
|
|
76
98
|
});
|
|
77
|
-
expect(
|
|
78
|
-
|
|
99
|
+
expect(
|
|
100
|
+
within(tabBar()).getByText('Awaiting Quality Check'),
|
|
101
|
+
).toBeInTheDocument();
|
|
102
|
+
expect(
|
|
103
|
+
document.querySelector('.console-group-header')?.textContent,
|
|
104
|
+
).toContain('TDPM Console port');
|
|
79
105
|
});
|
|
80
106
|
|
|
81
107
|
it('opens the detail view when an item is selected', async () => {
|
|
@@ -100,12 +126,13 @@ describe('ConsolePage', () => {
|
|
|
100
126
|
it('shows a cancellable toast and only drives the tab to zero after the five second window', async () => {
|
|
101
127
|
jest.useFakeTimers();
|
|
102
128
|
try {
|
|
103
|
-
const { getByText, findByText
|
|
129
|
+
const { getByText, findByText } = render(<ConsolePage />);
|
|
104
130
|
await waitFor(() => {
|
|
105
131
|
expect(getByText('Add serveConsole subcommand')).toBeInTheDocument();
|
|
106
132
|
});
|
|
107
133
|
expect(
|
|
108
|
-
|
|
134
|
+
within(tabBar())
|
|
135
|
+
.getByText('Awaiting Quality Check')
|
|
109
136
|
.closest('a')
|
|
110
137
|
?.querySelector('.console-tab-badge')?.textContent,
|
|
111
138
|
).toBe('1');
|
|
@@ -117,7 +144,8 @@ describe('ConsolePage', () => {
|
|
|
117
144
|
expect(getByText('Approved — PR #851')).toBeInTheDocument();
|
|
118
145
|
expect(getByText('Undo')).toBeInTheDocument();
|
|
119
146
|
expect(
|
|
120
|
-
|
|
147
|
+
within(tabBar())
|
|
148
|
+
.getByText('Awaiting Quality Check')
|
|
121
149
|
.closest('a')
|
|
122
150
|
?.querySelector('.console-tab-badge')?.textContent,
|
|
123
151
|
).toBe('1');
|
|
@@ -127,7 +155,9 @@ describe('ConsolePage', () => {
|
|
|
127
155
|
});
|
|
128
156
|
|
|
129
157
|
await waitFor(() => {
|
|
130
|
-
expect(
|
|
158
|
+
expect(
|
|
159
|
+
within(tabBar()).queryByText('Awaiting Quality Check'),
|
|
160
|
+
).toBeNull();
|
|
131
161
|
});
|
|
132
162
|
} finally {
|
|
133
163
|
jest.useRealTimers();
|
|
@@ -177,7 +207,8 @@ describe('ConsolePage', () => {
|
|
|
177
207
|
);
|
|
178
208
|
expect(postCalls.length).toBe(0);
|
|
179
209
|
expect(
|
|
180
|
-
|
|
210
|
+
within(tabBar())
|
|
211
|
+
.getByText('Awaiting Quality Check')
|
|
181
212
|
.closest('a')
|
|
182
213
|
?.querySelector('.console-tab-badge')?.textContent,
|
|
183
214
|
).toBe('1');
|
|
@@ -203,15 +234,16 @@ describe('ConsolePage', () => {
|
|
|
203
234
|
});
|
|
204
235
|
|
|
205
236
|
it('hides zero-count tabs but keeps non-zero tabs', async () => {
|
|
206
|
-
const { getByText
|
|
237
|
+
const { getByText } = render(<ConsolePage />);
|
|
207
238
|
await waitFor(() => {
|
|
208
239
|
expect(getByText('Add serveConsole subcommand')).toBeInTheDocument();
|
|
209
240
|
});
|
|
210
|
-
|
|
211
|
-
expect(queryByText('
|
|
212
|
-
expect(queryByText('
|
|
213
|
-
expect(queryByText('
|
|
214
|
-
expect(queryByText('
|
|
241
|
+
const tabs = within(tabBar());
|
|
242
|
+
expect(tabs.queryByText('Awaiting Quality Check')).not.toBeNull();
|
|
243
|
+
expect(tabs.queryByText('Unread')).not.toBeNull();
|
|
244
|
+
expect(tabs.queryByText('Triage')).toBeNull();
|
|
245
|
+
expect(tabs.queryByText('Failed Preparation')).toBeNull();
|
|
246
|
+
expect(tabs.queryByText('Todo by human')).toBeNull();
|
|
215
247
|
});
|
|
216
248
|
|
|
217
249
|
it('does not render the project header bar above the tab bar', async () => {
|
|
@@ -241,6 +273,10 @@ const twoItemPrPayload = () => ({
|
|
|
241
273
|
itemId: 'PVTI_1',
|
|
242
274
|
isPr: true,
|
|
243
275
|
story: 'TDPM Console port',
|
|
276
|
+
status: 'Awaiting Quality Check',
|
|
277
|
+
nextActionDate: null,
|
|
278
|
+
nextActionHour: null,
|
|
279
|
+
dependedIssueUrls: [],
|
|
244
280
|
labels: [],
|
|
245
281
|
createdAt: '2026-06-17T00:00:00.000Z',
|
|
246
282
|
},
|
|
@@ -254,6 +290,10 @@ const twoItemPrPayload = () => ({
|
|
|
254
290
|
itemId: 'PVTI_2',
|
|
255
291
|
isPr: true,
|
|
256
292
|
story: 'TDPM Console port',
|
|
293
|
+
status: 'Awaiting Quality Check',
|
|
294
|
+
nextActionDate: null,
|
|
295
|
+
nextActionHour: null,
|
|
296
|
+
dependedIssueUrls: [],
|
|
257
297
|
labels: [],
|
|
258
298
|
createdAt: '2026-06-17T01:00:00.000Z',
|
|
259
299
|
},
|
|
@@ -422,7 +462,10 @@ describe('ConsolePage auto-advance tab', () => {
|
|
|
422
462
|
).toBeInTheDocument();
|
|
423
463
|
});
|
|
424
464
|
expect(
|
|
425
|
-
|
|
465
|
+
within(tabBar())
|
|
466
|
+
.getByText('Unread')
|
|
467
|
+
.closest('a')
|
|
468
|
+
?.getAttribute('aria-current'),
|
|
426
469
|
).toBe('page');
|
|
427
470
|
} finally {
|
|
428
471
|
jest.useRealTimers();
|
|
@@ -52,15 +52,7 @@ const OVERLAY_NAMESPACE_FALLBACK = 'console';
|
|
|
52
52
|
export const ConsolePage = () => {
|
|
53
53
|
const pjcode = useConsolePjcode();
|
|
54
54
|
const { snapshots, isLoading, error } = useConsoleTabData(pjcode);
|
|
55
|
-
const navigation = useConsoleNavigation(pjcode);
|
|
56
|
-
const { activeTab, selectedItemKey, openItem, closeItem, selectTab } =
|
|
57
|
-
navigation;
|
|
58
|
-
|
|
59
55
|
const overlayState = useConsoleOverlay(pjcode ?? OVERLAY_NAMESPACE_FALLBACK);
|
|
60
|
-
const caches = useConsoleCaches();
|
|
61
|
-
const operations = useConsoleOperations(pjcode, activeTab, overlayState);
|
|
62
|
-
const actionQueue = useConsoleActionQueue();
|
|
63
|
-
const now = Date.now();
|
|
64
56
|
|
|
65
57
|
const counts = useMemo(() => {
|
|
66
58
|
const result = emptyCounts();
|
|
@@ -77,6 +69,15 @@ export const ConsolePage = () => {
|
|
|
77
69
|
return result;
|
|
78
70
|
}, [snapshots, overlayState.overlay]);
|
|
79
71
|
|
|
72
|
+
const navigation = useConsoleNavigation(pjcode, counts);
|
|
73
|
+
const { activeTab, selectedItemKey, openItem, closeItem, selectTab } =
|
|
74
|
+
navigation;
|
|
75
|
+
|
|
76
|
+
const caches = useConsoleCaches();
|
|
77
|
+
const operations = useConsoleOperations(pjcode, activeTab, overlayState);
|
|
78
|
+
const actionQueue = useConsoleActionQueue();
|
|
79
|
+
const now = Date.now();
|
|
80
|
+
|
|
80
81
|
const activeSnapshot = snapshots[activeTab];
|
|
81
82
|
const pendingItems = useMemo(() => {
|
|
82
83
|
if (activeSnapshot === null) {
|
|
@@ -56,6 +56,12 @@ export const consoleListItemsFixture: ConsoleListItem[] = [
|
|
|
56
56
|
itemId: 'PVTI_lADOABCD1234zgABCD01',
|
|
57
57
|
isPr: true,
|
|
58
58
|
story: 'TDPM Console port',
|
|
59
|
+
status: 'Awaiting Quality Check',
|
|
60
|
+
nextActionDate: null,
|
|
61
|
+
nextActionHour: null,
|
|
62
|
+
dependedIssueUrls: [
|
|
63
|
+
'https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/845',
|
|
64
|
+
],
|
|
59
65
|
labels: ['claude'],
|
|
60
66
|
createdAt: '2026-06-17T02:14:33.000Z',
|
|
61
67
|
},
|
|
@@ -71,6 +77,10 @@ export const consoleListItemsFixture: ConsoleListItem[] = [
|
|
|
71
77
|
itemId: 'PVTI_lADOABCD1234zgABCD02',
|
|
72
78
|
isPr: true,
|
|
73
79
|
story: 'TDPM Console port',
|
|
80
|
+
status: 'Preparation',
|
|
81
|
+
nextActionDate: null,
|
|
82
|
+
nextActionHour: null,
|
|
83
|
+
dependedIssueUrls: [],
|
|
74
84
|
labels: ['claude'],
|
|
75
85
|
createdAt: '2026-06-17T05:48:09.000Z',
|
|
76
86
|
},
|
|
@@ -85,6 +95,10 @@ export const consoleListItemsFixture: ConsoleListItem[] = [
|
|
|
85
95
|
itemId: 'PVTI_lADOABCD1234zgABCD03',
|
|
86
96
|
isPr: false,
|
|
87
97
|
story: 'TDPM Console port',
|
|
98
|
+
status: 'Todo by human',
|
|
99
|
+
nextActionDate: '2026-06-20T07:00:00.000Z',
|
|
100
|
+
nextActionHour: 9,
|
|
101
|
+
dependedIssueUrls: [],
|
|
88
102
|
labels: [],
|
|
89
103
|
createdAt: '2026-06-16T22:01:55.000Z',
|
|
90
104
|
},
|
|
@@ -99,6 +113,10 @@ export const consoleListItemsFixture: ConsoleListItem[] = [
|
|
|
99
113
|
itemId: 'PVTI_lADOABCD1234zgABCD04',
|
|
100
114
|
isPr: false,
|
|
101
115
|
story: 'regular / workflow improvement',
|
|
116
|
+
status: null,
|
|
117
|
+
nextActionDate: null,
|
|
118
|
+
nextActionHour: 14,
|
|
119
|
+
dependedIssueUrls: [],
|
|
102
120
|
labels: [],
|
|
103
121
|
createdAt: '2026-06-12T23:01:55.000Z',
|
|
104
122
|
},
|
|
@@ -113,6 +131,10 @@ export const consoleListItemsFixture: ConsoleListItem[] = [
|
|
|
113
131
|
itemId: 'PVTI_lADOABCD1234zgABCD05',
|
|
114
132
|
isPr: false,
|
|
115
133
|
story: 'Publish product documentation site',
|
|
134
|
+
status: 'Icebox',
|
|
135
|
+
nextActionDate: null,
|
|
136
|
+
nextActionHour: null,
|
|
137
|
+
dependedIssueUrls: [],
|
|
116
138
|
labels: ['documentation'],
|
|
117
139
|
createdAt: '2026-06-10T11:42:00.000Z',
|
|
118
140
|
},
|
|
@@ -212,6 +212,30 @@ body {
|
|
|
212
212
|
cursor: help;
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
+
.console-item-fields {
|
|
216
|
+
display: flex;
|
|
217
|
+
flex-wrap: wrap;
|
|
218
|
+
gap: 4px 10px;
|
|
219
|
+
margin-top: 4px;
|
|
220
|
+
font-size: 11.5px;
|
|
221
|
+
color: #adbac7;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.console-item-field {
|
|
225
|
+
display: inline-flex;
|
|
226
|
+
align-items: baseline;
|
|
227
|
+
gap: 4px;
|
|
228
|
+
min-width: 0;
|
|
229
|
+
word-break: break-all;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.console-item-field-label {
|
|
233
|
+
color: #6e7681;
|
|
234
|
+
font-size: 10px;
|
|
235
|
+
text-transform: uppercase;
|
|
236
|
+
letter-spacing: 0.03em;
|
|
237
|
+
}
|
|
238
|
+
|
|
215
239
|
.console-list-message {
|
|
216
240
|
padding: 16px;
|
|
217
241
|
color: #8b949e;
|