cdd-cli 4.0.0 → 4.1.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/README.es.md +29 -5
- package/README.md +29 -5
- package/dist/components/UsageMenu.js +1 -1
- package/dist/helpers/appState.js +26 -0
- package/dist/helpers/dockerService/serviceComponents/containerExec.js +211 -0
- package/dist/hooks/creation/useContainerCreation.js +25 -6
- package/dist/hooks/useContainerCommandRouter.js +12 -2
- package/dist/hooks/useControls.js +5 -0
- package/dist/hooks/useShellMode.js +101 -0
- package/dist/index.js +3 -1
- package/package.json +4 -1
- package/.atl/skill-registry.md +0 -30
- package/.editorconfig +0 -12
- package/.eslintrc.json +0 -30
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -30
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -19
- package/.github/PULL_REQUEST_TEMPLATE/pull_request.md +0 -14
- package/.github/workflows/ci.yml +0 -32
- package/.github/workflows/docs.yml +0 -42
- package/.prettierignore +0 -4
- package/.prettierrc +0 -8
- package/.~lock.ROADMAP.md# +0 -1
- package/CHANGELOG.md +0 -216
- package/CODE_OF_CONDUCT.md +0 -12
- package/CONTRIBUTING.md +0 -35
- package/ROADMAP.md +0 -647
- package/SECURITY.md +0 -5
- package/__mocks__/ink.cjs +0 -17
- package/_config.yml +0 -13
- package/babel.config.cjs +0 -23
- package/coverage/clover.xml +0 -575
- package/coverage/coverage-final.json +0 -17
- package/coverage/lcov-report/ContainerCreationPrompt.jsx.html +0 -400
- package/coverage/lcov-report/ControlsHUD.jsx.html +0 -256
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/components/ContainerCreationPrompt.jsx.html +0 -394
- package/coverage/lcov-report/components/PromptField.jsx.html +0 -229
- package/coverage/lcov-report/components/SuggestionPanel.jsx.html +0 -268
- package/coverage/lcov-report/components/index.html +0 -146
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/helpers/constants.js.html +0 -352
- package/coverage/lcov-report/helpers/containerOptionsBuilder.js.html +0 -244
- package/coverage/lcov-report/helpers/dockerHubService.js.html +0 -310
- package/coverage/lcov-report/helpers/dockerService/serviceComponents/containerActions.js.html +0 -931
- package/coverage/lcov-report/helpers/dockerService/serviceComponents/containerList.js.html +0 -307
- package/coverage/lcov-report/helpers/dockerService/serviceComponents/index.html +0 -131
- package/coverage/lcov-report/helpers/imageNameUtils.js.html +0 -181
- package/coverage/lcov-report/helpers/index.html +0 -206
- package/coverage/lcov-report/helpers/logger.js.html +0 -424
- package/coverage/lcov-report/helpers/safeCall.js.html +0 -139
- package/coverage/lcov-report/helpers/validationHelpers.js.html +0 -346
- package/coverage/lcov-report/hooks/creation/index.html +0 -146
- package/coverage/lcov-report/hooks/creation/useContainerActions.js.html +0 -313
- package/coverage/lcov-report/hooks/creation/useContainerCreation.js.html +0 -982
- package/coverage/lcov-report/hooks/creation/useLogsViewer.js.html +0 -238
- package/coverage/lcov-report/hooks/debug/index.html +0 -116
- package/coverage/lcov-report/hooks/debug/useDebugLogs.js.html +0 -187
- package/coverage/lcov-report/hooks/index.html +0 -161
- package/coverage/lcov-report/hooks/navigation/index.html +0 -116
- package/coverage/lcov-report/hooks/navigation/useContainerSelection.js.html +0 -169
- package/coverage/lcov-report/hooks/useContainerCommandRouter.js.html +0 -454
- package/coverage/lcov-report/hooks/useControls.js.html +0 -868
- package/coverage/lcov-report/hooks/useEraseConfirmation.js.html +0 -202
- package/coverage/lcov-report/hooks/useExitHandler.js.html +0 -292
- package/coverage/lcov-report/index.html +0 -176
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -210
- package/coverage/lcov.info +0 -1163
- package/fix-imports.cjs +0 -54
- package/jest.config.cjs +0 -14
- package/src/App.jsx +0 -102
- package/src/components/ContainerCreationPrompt.jsx +0 -107
- package/src/components/ContainerList.jsx +0 -32
- package/src/components/ContainerRow.jsx +0 -84
- package/src/components/ContainerSection.jsx +0 -24
- package/src/components/ControlsHUD.jsx +0 -66
- package/src/components/Footer.jsx +0 -15
- package/src/components/Header.jsx +0 -41
- package/src/components/LogViewer.jsx +0 -36
- package/src/components/MessageFeedback.jsx +0 -25
- package/src/components/PromptField.jsx +0 -48
- package/src/components/StatsBar.jsx +0 -70
- package/src/components/SuggestionPanel.jsx +0 -61
- package/src/components/UsageMenu.jsx +0 -52
- package/src/helpers/appInfo.js +0 -23
- package/src/helpers/constants.js +0 -89
- package/src/helpers/containerOptionsBuilder.js +0 -53
- package/src/helpers/dockerHubService.js +0 -75
- package/src/helpers/dockerService/dockerService.js +0 -28
- package/src/helpers/dockerService/serviceComponents/containerActions.js +0 -282
- package/src/helpers/dockerService/serviceComponents/containerList.js +0 -74
- package/src/helpers/dockerService/serviceComponents/containerLogs.js +0 -60
- package/src/helpers/dockerService/serviceComponents/containerStats.js +0 -69
- package/src/helpers/dockerService/serviceComponents/imageUtils.js +0 -32
- package/src/helpers/exitWithMessage.js +0 -32
- package/src/helpers/imageNameUtils.js +0 -32
- package/src/helpers/logger.js +0 -112
- package/src/helpers/safeCall.js +0 -18
- package/src/helpers/validationHelpers.js +0 -87
- package/src/hooks/creation/useContainerActions.js +0 -89
- package/src/hooks/creation/useContainerCreation.js +0 -377
- package/src/hooks/creation/useLogsViewer.js +0 -51
- package/src/hooks/debug/useDebugLogs.js +0 -34
- package/src/hooks/navigation/useContainerSelection.js +0 -28
- package/src/hooks/useContainerCommandRouter.js +0 -123
- package/src/hooks/useContainerStats.js +0 -44
- package/src/hooks/useContainers.js +0 -26
- package/src/hooks/useControls.js +0 -263
- package/src/hooks/useEraseConfirmation.js +0 -39
- package/src/hooks/useExitHandler.js +0 -69
- package/src/index.js +0 -20
- package/test/ContainerCreationPrompt.dom.test.js +0 -313
- package/test/ControlsHUD.dom.test.js +0 -125
- package/test/SuggestionPanel.dom.test.js +0 -83
- package/test/constants.test.js +0 -41
- package/test/containerActions.test.js +0 -229
- package/test/containerList.test.js +0 -79
- package/test/containerOptionsBuilder.test.js +0 -36
- package/test/dockerHubService.test.js +0 -213
- package/test/jest.setup.js +0 -7
- package/test/logger.test.js +0 -58
- package/test/resolveImageTag.test.js +0 -26
- package/test/safeCall.test.js +0 -25
- package/test/useContainerCreation.dom.test.js +0 -567
- package/test/useContainerCreationHub.dom.test.js +0 -184
- package/test/useControls.dom.test.js +0 -519
- package/test/validationHelpers.test.js +0 -111
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @jest-environment jsdom
|
|
3
|
-
*
|
|
4
|
-
* Tests for Hub-search additions to useContainerCreation:
|
|
5
|
-
* - isSearchingHub state
|
|
6
|
-
* - hubResults state (string[] after formatHubResult mapping)
|
|
7
|
-
* - triggerHubSearch() guards (empty input, already searching)
|
|
8
|
-
* - stale response ignored via requestId
|
|
9
|
-
* - updateImageInput() aborts in-flight search and clears hubResults
|
|
10
|
-
*/
|
|
11
|
-
import React, { useEffect } from 'react';
|
|
12
|
-
import { render, act } from '@testing-library/react';
|
|
13
|
-
import { jest } from '@jest/globals';
|
|
14
|
-
|
|
15
|
-
// ── Mock dockerHubService BEFORE any import that might pull it in ─────────────
|
|
16
|
-
jest.unstable_mockModule('../src/helpers/dockerHubService.js', () => ({
|
|
17
|
-
searchDockerHub: jest.fn(),
|
|
18
|
-
formatHubResult: jest.fn((r) => r.name), // identity-like stub: returns name string
|
|
19
|
-
}));
|
|
20
|
-
|
|
21
|
-
// Dynamic import resolves AFTER jest.unstable_mockModule is registered
|
|
22
|
-
const { useContainerCreation } = await import('../src/hooks/creation/useContainerCreation.js');
|
|
23
|
-
const { searchDockerHub } = await import('../src/helpers/dockerHubService.js');
|
|
24
|
-
|
|
25
|
-
const mockSearchDockerHub = searchDockerHub;
|
|
26
|
-
|
|
27
|
-
// ── Test harness ─────────────────────────────────────────────────────────────
|
|
28
|
-
|
|
29
|
-
function HookTester({ onCreate, onCancel, dbImages, imageProfiles, expose }) {
|
|
30
|
-
const hook = useContainerCreation({
|
|
31
|
-
onCreate: onCreate ?? (() => {}),
|
|
32
|
-
onCancel: onCancel ?? (() => {}),
|
|
33
|
-
dbImages: dbImages ?? [],
|
|
34
|
-
imageProfiles: imageProfiles ?? {},
|
|
35
|
-
});
|
|
36
|
-
useEffect(() => {
|
|
37
|
-
if (expose) expose.current = hook;
|
|
38
|
-
});
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function makeExpose() {
|
|
43
|
-
const expose = { current: null };
|
|
44
|
-
render(<HookTester expose={expose} />);
|
|
45
|
-
return expose;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// ── Tests ─────────────────────────────────────────────────────────────────────
|
|
49
|
-
|
|
50
|
-
describe('useContainerCreation — Hub search state', () => {
|
|
51
|
-
beforeEach(() => {
|
|
52
|
-
mockSearchDockerHub.mockReset();
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test('exposes isSearchingHub (initially false) and hubResults (initially null)', () => {
|
|
56
|
-
const expose = makeExpose();
|
|
57
|
-
|
|
58
|
-
expect(expose.current.isSearchingHub).toBe(false);
|
|
59
|
-
expect(expose.current.hubResults).toBeNull();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
test('triggerHubSearch() ignores empty imageName', async () => {
|
|
63
|
-
const expose = makeExpose();
|
|
64
|
-
// imageName is '' by default
|
|
65
|
-
await act(async () => {
|
|
66
|
-
expose.current.triggerHubSearch();
|
|
67
|
-
});
|
|
68
|
-
expect(mockSearchDockerHub).not.toHaveBeenCalled();
|
|
69
|
-
expect(expose.current.isSearchingHub).toBe(false);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
test('triggerHubSearch() sets isSearchingHub=true during the request', async () => {
|
|
73
|
-
const expose = makeExpose();
|
|
74
|
-
let resolveSearch;
|
|
75
|
-
mockSearchDockerHub.mockReturnValue(
|
|
76
|
-
new Promise((res) => { resolveSearch = res; })
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
act(() => { expose.current.updateImageInput('nginx'); });
|
|
80
|
-
|
|
81
|
-
let searchPromise;
|
|
82
|
-
act(() => { searchPromise = expose.current.triggerHubSearch(); });
|
|
83
|
-
|
|
84
|
-
expect(expose.current.isSearchingHub).toBe(true);
|
|
85
|
-
|
|
86
|
-
await act(async () => { resolveSearch([]); await searchPromise; });
|
|
87
|
-
expect(expose.current.isSearchingHub).toBe(false);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
test('triggerHubSearch() ignores call when isSearchingHub is already true', async () => {
|
|
91
|
-
const expose = makeExpose();
|
|
92
|
-
let resolveFirst;
|
|
93
|
-
mockSearchDockerHub.mockReturnValue(
|
|
94
|
-
new Promise((res) => { resolveFirst = res; })
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
act(() => { expose.current.updateImageInput('nginx'); });
|
|
98
|
-
act(() => { expose.current.triggerHubSearch(); }); // first call — now searching
|
|
99
|
-
expect(expose.current.isSearchingHub).toBe(true);
|
|
100
|
-
|
|
101
|
-
// second call — should be ignored
|
|
102
|
-
act(() => { expose.current.triggerHubSearch(); });
|
|
103
|
-
expect(mockSearchDockerHub).toHaveBeenCalledTimes(1);
|
|
104
|
-
|
|
105
|
-
// cleanup
|
|
106
|
-
await act(async () => { resolveFirst([]); });
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
test('triggerHubSearch() stores formatted results (strings) in hubResults on success', async () => {
|
|
110
|
-
const expose = makeExpose();
|
|
111
|
-
const fakeResults = [
|
|
112
|
-
{ name: 'library/nginx', isOfficial: true, pullCount: 1e9, description: 'official' },
|
|
113
|
-
];
|
|
114
|
-
mockSearchDockerHub.mockResolvedValue(fakeResults);
|
|
115
|
-
|
|
116
|
-
act(() => { expose.current.updateImageInput('nginx'); });
|
|
117
|
-
await act(async () => { await expose.current.triggerHubSearch(); });
|
|
118
|
-
|
|
119
|
-
// hubResults should be string[] (after formatHubResult mapping)
|
|
120
|
-
expect(Array.isArray(expose.current.hubResults)).toBe(true);
|
|
121
|
-
expect(expose.current.hubResults).toHaveLength(1);
|
|
122
|
-
expect(typeof expose.current.hubResults[0]).toBe('string');
|
|
123
|
-
expect(expose.current.isSearchingHub).toBe(false);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
test('stale response is ignored — only the latest requestId wins', async () => {
|
|
127
|
-
const expose = makeExpose();
|
|
128
|
-
|
|
129
|
-
let resolveFirst;
|
|
130
|
-
let resolveSecond;
|
|
131
|
-
|
|
132
|
-
mockSearchDockerHub
|
|
133
|
-
.mockReturnValueOnce(new Promise((res) => { resolveFirst = res; }))
|
|
134
|
-
.mockReturnValueOnce(new Promise((res) => { resolveSecond = res; }));
|
|
135
|
-
|
|
136
|
-
act(() => { expose.current.updateImageInput('nginx'); });
|
|
137
|
-
act(() => { expose.current.triggerHubSearch(); }); // request #1 starts, isSearchingHub=true
|
|
138
|
-
|
|
139
|
-
// Simulate user typing (aborts #1, clears hub state)
|
|
140
|
-
act(() => { expose.current.updateImageInput('ngi'); });
|
|
141
|
-
// Now trigger again (request #2)
|
|
142
|
-
act(() => { expose.current.triggerHubSearch(); });
|
|
143
|
-
|
|
144
|
-
const secondResults = [{ name: 'ngi/x', isOfficial: false, pullCount: 0, description: '' }];
|
|
145
|
-
|
|
146
|
-
// Resolve second first (fresh), then first (stale)
|
|
147
|
-
await act(async () => { resolveSecond(secondResults); });
|
|
148
|
-
await act(async () => { resolveFirst([{ name: 'stale', isOfficial: false, pullCount: 0, description: '' }]); });
|
|
149
|
-
|
|
150
|
-
// Only second results should be stored (as strings)
|
|
151
|
-
expect(Array.isArray(expose.current.hubResults)).toBe(true);
|
|
152
|
-
expect(expose.current.hubResults).toHaveLength(1);
|
|
153
|
-
expect(expose.current.hubResults[0]).toBe('ngi/x');
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
test('updateImageInput() clears hubResults and sets isSearchingHub=false', async () => {
|
|
157
|
-
const expose = makeExpose();
|
|
158
|
-
mockSearchDockerHub.mockResolvedValue([
|
|
159
|
-
{ name: 'library/nginx', isOfficial: true, pullCount: 1e9, description: '' },
|
|
160
|
-
]);
|
|
161
|
-
|
|
162
|
-
act(() => { expose.current.updateImageInput('nginx'); });
|
|
163
|
-
await act(async () => { await expose.current.triggerHubSearch(); });
|
|
164
|
-
expect(expose.current.hubResults).not.toBeNull();
|
|
165
|
-
|
|
166
|
-
// Typing clears Hub results
|
|
167
|
-
act(() => { expose.current.updateImageInput('nginy'); });
|
|
168
|
-
expect(expose.current.hubResults).toBeNull();
|
|
169
|
-
expect(expose.current.isSearchingHub).toBe(false);
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
test('failed Hub search (non-abort) sets hubResults=null silently', async () => {
|
|
173
|
-
const expose = makeExpose();
|
|
174
|
-
mockSearchDockerHub.mockRejectedValue(new Error('Network Error'));
|
|
175
|
-
|
|
176
|
-
act(() => { expose.current.updateImageInput('nginx'); });
|
|
177
|
-
await act(async () => {
|
|
178
|
-
try { await expose.current.triggerHubSearch(); } catch (_) { /* silenced */ }
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
expect(expose.current.hubResults).toBeNull();
|
|
182
|
-
expect(expose.current.isSearchingHub).toBe(false);
|
|
183
|
-
});
|
|
184
|
-
});
|