datajunction-ui 0.0.59 → 0.0.62
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/package.json +1 -1
- package/src/app/components/NamespaceHeader.jsx +651 -568
- package/src/app/components/__tests__/GitModals.test.jsx +68 -39
- package/src/app/components/__tests__/NamespaceHeader.test.jsx +12 -16
- package/src/app/components/__tests__/__snapshots__/NamespaceHeader.test.jsx.snap +150 -140
- package/src/app/components/git/CreateBranchModal.jsx +16 -3
- package/src/app/components/git/GitSettingsModal.jsx +366 -102
- package/src/app/components/git/__tests__/GitSettingsModal.test.jsx +216 -25
|
@@ -11,18 +11,28 @@ describe('<GitSettingsModal />', () => {
|
|
|
11
11
|
jest.clearAllMocks();
|
|
12
12
|
// Mock window.confirm
|
|
13
13
|
global.confirm = jest.fn(() => true);
|
|
14
|
+
// Mock fetch for parent config fetching
|
|
15
|
+
global.fetch = jest.fn(() =>
|
|
16
|
+
Promise.resolve({
|
|
17
|
+
ok: true,
|
|
18
|
+
json: () =>
|
|
19
|
+
Promise.resolve({
|
|
20
|
+
github_repo_path: 'test/repo',
|
|
21
|
+
git_path: 'nodes/',
|
|
22
|
+
}),
|
|
23
|
+
}),
|
|
24
|
+
);
|
|
14
25
|
});
|
|
15
26
|
|
|
16
27
|
afterEach(() => {
|
|
17
28
|
jest.restoreAllMocks();
|
|
18
29
|
});
|
|
19
30
|
|
|
20
|
-
it('should render with existing config', () => {
|
|
31
|
+
it('should render with existing git root config', () => {
|
|
21
32
|
const currentConfig = {
|
|
22
33
|
github_repo_path: 'test/repo',
|
|
23
|
-
git_branch: 'main',
|
|
24
34
|
git_path: 'nodes/',
|
|
25
|
-
|
|
35
|
+
default_branch: 'main',
|
|
26
36
|
};
|
|
27
37
|
|
|
28
38
|
render(
|
|
@@ -37,16 +47,41 @@ describe('<GitSettingsModal />', () => {
|
|
|
37
47
|
);
|
|
38
48
|
|
|
39
49
|
expect(screen.getByDisplayValue('test/repo')).toBeInTheDocument();
|
|
40
|
-
expect(screen.getByDisplayValue('main')).toBeInTheDocument();
|
|
41
50
|
expect(screen.getByDisplayValue('nodes/')).toBeInTheDocument();
|
|
51
|
+
// Default branch field should be present in git root mode
|
|
52
|
+
expect(screen.getByLabelText(/Default Branch/)).toBeInTheDocument();
|
|
53
|
+
expect(screen.getByDisplayValue('main')).toBeInTheDocument();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('should render with existing branch namespace config', () => {
|
|
57
|
+
const currentConfig = {
|
|
58
|
+
parent_namespace: 'test',
|
|
59
|
+
git_branch: 'main',
|
|
60
|
+
git_only: false,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
render(
|
|
64
|
+
<GitSettingsModal
|
|
65
|
+
isOpen={true}
|
|
66
|
+
onClose={mockOnClose}
|
|
67
|
+
onSave={mockOnSave}
|
|
68
|
+
onRemove={mockOnRemove}
|
|
69
|
+
currentConfig={currentConfig}
|
|
70
|
+
namespace="test.feature"
|
|
71
|
+
/>,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
expect(screen.getByDisplayValue('main')).toBeInTheDocument();
|
|
75
|
+
expect(screen.getByText('test')).toBeInTheDocument(); // Parent shown as read-only
|
|
76
|
+
// git_only is false, so checkbox should not be checked
|
|
77
|
+
const checkbox = screen.getByRole('checkbox');
|
|
78
|
+
expect(checkbox).not.toBeChecked();
|
|
42
79
|
});
|
|
43
80
|
|
|
44
81
|
it('should call onRemove when Reset button is clicked and confirmed', async () => {
|
|
45
82
|
const currentConfig = {
|
|
46
83
|
github_repo_path: 'test/repo',
|
|
47
|
-
git_branch: 'main',
|
|
48
84
|
git_path: 'nodes/',
|
|
49
|
-
git_only: false,
|
|
50
85
|
};
|
|
51
86
|
|
|
52
87
|
mockOnRemove.mockResolvedValue({ success: true });
|
|
@@ -85,9 +120,7 @@ describe('<GitSettingsModal />', () => {
|
|
|
85
120
|
|
|
86
121
|
const currentConfig = {
|
|
87
122
|
github_repo_path: 'test/repo',
|
|
88
|
-
git_branch: 'main',
|
|
89
123
|
git_path: 'nodes/',
|
|
90
|
-
git_only: false,
|
|
91
124
|
};
|
|
92
125
|
|
|
93
126
|
render(
|
|
@@ -111,9 +144,7 @@ describe('<GitSettingsModal />', () => {
|
|
|
111
144
|
it('should show error message when remove fails', async () => {
|
|
112
145
|
const currentConfig = {
|
|
113
146
|
github_repo_path: 'test/repo',
|
|
114
|
-
git_branch: 'main',
|
|
115
147
|
git_path: 'nodes/',
|
|
116
|
-
git_only: false,
|
|
117
148
|
};
|
|
118
149
|
|
|
119
150
|
mockOnRemove.mockResolvedValue({
|
|
@@ -150,9 +181,7 @@ describe('<GitSettingsModal />', () => {
|
|
|
150
181
|
|
|
151
182
|
const currentConfig = {
|
|
152
183
|
github_repo_path: 'test/repo',
|
|
153
|
-
git_branch: 'main',
|
|
154
184
|
git_path: 'nodes/',
|
|
155
|
-
git_only: false,
|
|
156
185
|
};
|
|
157
186
|
|
|
158
187
|
mockOnRemove.mockResolvedValue({ success: true });
|
|
@@ -195,9 +224,7 @@ describe('<GitSettingsModal />', () => {
|
|
|
195
224
|
it('should handle exception during remove', async () => {
|
|
196
225
|
const currentConfig = {
|
|
197
226
|
github_repo_path: 'test/repo',
|
|
198
|
-
git_branch: 'main',
|
|
199
227
|
git_path: 'nodes/',
|
|
200
|
-
git_only: false,
|
|
201
228
|
};
|
|
202
229
|
|
|
203
230
|
mockOnRemove.mockRejectedValue(new Error('Network error'));
|
|
@@ -224,9 +251,7 @@ describe('<GitSettingsModal />', () => {
|
|
|
224
251
|
it('should show removing state while operation is in progress', async () => {
|
|
225
252
|
const currentConfig = {
|
|
226
253
|
github_repo_path: 'test/repo',
|
|
227
|
-
git_branch: 'main',
|
|
228
254
|
git_path: 'nodes/',
|
|
229
|
-
git_only: false,
|
|
230
255
|
};
|
|
231
256
|
|
|
232
257
|
// Create a promise that we can control
|
|
@@ -266,7 +291,7 @@ describe('<GitSettingsModal />', () => {
|
|
|
266
291
|
});
|
|
267
292
|
});
|
|
268
293
|
|
|
269
|
-
it('should call onSave when Save Settings is clicked', async () => {
|
|
294
|
+
it('should call onSave when Save Settings is clicked in git root mode', async () => {
|
|
270
295
|
mockOnSave.mockResolvedValue({ success: true });
|
|
271
296
|
|
|
272
297
|
render(
|
|
@@ -280,22 +305,188 @@ describe('<GitSettingsModal />', () => {
|
|
|
280
305
|
/>,
|
|
281
306
|
);
|
|
282
307
|
|
|
283
|
-
|
|
308
|
+
// Default mode is git root
|
|
309
|
+
fireEvent.change(screen.getByLabelText(/Repository/), {
|
|
284
310
|
target: { value: 'myorg/repo' },
|
|
285
311
|
});
|
|
286
|
-
|
|
287
|
-
|
|
312
|
+
|
|
313
|
+
fireEvent.click(screen.getByText('Save Settings'));
|
|
314
|
+
|
|
315
|
+
await waitFor(() => {
|
|
316
|
+
expect(mockOnSave).toHaveBeenCalledWith({
|
|
317
|
+
github_repo_path: 'myorg/repo',
|
|
318
|
+
git_path: 'nodes/', // Default value
|
|
319
|
+
default_branch: 'main', // Default value for git roots
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
it('should call onSave when Save Settings is clicked in branch mode', async () => {
|
|
325
|
+
mockOnSave.mockResolvedValue({ success: true });
|
|
326
|
+
|
|
327
|
+
render(
|
|
328
|
+
<GitSettingsModal
|
|
329
|
+
isOpen={true}
|
|
330
|
+
onClose={mockOnClose}
|
|
331
|
+
onSave={mockOnSave}
|
|
332
|
+
onRemove={mockOnRemove}
|
|
333
|
+
currentConfig={null}
|
|
334
|
+
namespace="test.feature"
|
|
335
|
+
/>,
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
// Switch to branch mode
|
|
339
|
+
fireEvent.click(screen.getByText('Branch Namespace'));
|
|
340
|
+
|
|
341
|
+
// Fill in branch name
|
|
342
|
+
fireEvent.change(screen.getByLabelText(/Branch/), {
|
|
343
|
+
target: { value: 'feature-x' },
|
|
288
344
|
});
|
|
289
345
|
|
|
290
346
|
fireEvent.click(screen.getByText('Save Settings'));
|
|
291
347
|
|
|
292
348
|
await waitFor(() => {
|
|
293
|
-
expect(mockOnSave).toHaveBeenCalledWith(
|
|
294
|
-
|
|
295
|
-
|
|
349
|
+
expect(mockOnSave).toHaveBeenCalledWith({
|
|
350
|
+
git_branch: 'feature-x',
|
|
351
|
+
parent_namespace: 'test',
|
|
352
|
+
git_only: true, // Default for branch mode
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
it('should show error when branch name is empty in branch mode', async () => {
|
|
358
|
+
render(
|
|
359
|
+
<GitSettingsModal
|
|
360
|
+
isOpen={true}
|
|
361
|
+
onClose={mockOnClose}
|
|
362
|
+
onSave={mockOnSave}
|
|
363
|
+
onRemove={mockOnRemove}
|
|
364
|
+
currentConfig={null}
|
|
365
|
+
namespace="test.feature"
|
|
366
|
+
/>,
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
// Switch to branch mode
|
|
370
|
+
fireEvent.click(screen.getByText('Branch Namespace'));
|
|
371
|
+
|
|
372
|
+
// Try to save without entering a branch name
|
|
373
|
+
fireEvent.click(screen.getByText('Save Settings'));
|
|
374
|
+
|
|
375
|
+
await waitFor(() => {
|
|
376
|
+
expect(
|
|
377
|
+
screen.getByText('Git branch is required for branch mode'),
|
|
378
|
+
).toBeInTheDocument();
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
expect(mockOnSave).not.toHaveBeenCalled();
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it('should show error when namespace has no parent in branch mode', async () => {
|
|
385
|
+
render(
|
|
386
|
+
<GitSettingsModal
|
|
387
|
+
isOpen={true}
|
|
388
|
+
onClose={mockOnClose}
|
|
389
|
+
onSave={mockOnSave}
|
|
390
|
+
onRemove={mockOnRemove}
|
|
391
|
+
currentConfig={null}
|
|
392
|
+
namespace="toplevel"
|
|
393
|
+
/>,
|
|
394
|
+
);
|
|
395
|
+
|
|
396
|
+
// Switch to branch mode (should fail because namespace has no parent)
|
|
397
|
+
fireEvent.click(screen.getByText('Branch Namespace'));
|
|
398
|
+
|
|
399
|
+
// Try to save
|
|
400
|
+
fireEvent.click(screen.getByText('Save Settings'));
|
|
401
|
+
|
|
402
|
+
await waitFor(() => {
|
|
403
|
+
expect(
|
|
404
|
+
screen.getByText(
|
|
405
|
+
/Cannot configure as branch namespace: namespace has no parent/,
|
|
406
|
+
),
|
|
407
|
+
).toBeInTheDocument();
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
expect(mockOnSave).not.toHaveBeenCalled();
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
it('should show error when repository is empty in git root mode', async () => {
|
|
414
|
+
render(
|
|
415
|
+
<GitSettingsModal
|
|
416
|
+
isOpen={true}
|
|
417
|
+
onClose={mockOnClose}
|
|
418
|
+
onSave={mockOnSave}
|
|
419
|
+
onRemove={mockOnRemove}
|
|
420
|
+
currentConfig={null}
|
|
421
|
+
namespace="test.namespace"
|
|
422
|
+
/>,
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
// Default is git root mode
|
|
426
|
+
// Clear the repository field if it has any default value
|
|
427
|
+
const repoInput = screen.getByLabelText(/Repository/);
|
|
428
|
+
fireEvent.change(repoInput, { target: { value: '' } });
|
|
429
|
+
|
|
430
|
+
// Try to save without entering a repository
|
|
431
|
+
fireEvent.click(screen.getByText('Save Settings'));
|
|
432
|
+
|
|
433
|
+
await waitFor(() => {
|
|
434
|
+
expect(screen.getByText('Repository is required')).toBeInTheDocument();
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
expect(mockOnSave).not.toHaveBeenCalled();
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
it('should handle parent config fetch failure gracefully', async () => {
|
|
441
|
+
// Mock fetch to fail
|
|
442
|
+
global.fetch = jest.fn(() => Promise.reject(new Error('Network error')));
|
|
443
|
+
|
|
444
|
+
render(
|
|
445
|
+
<GitSettingsModal
|
|
446
|
+
isOpen={true}
|
|
447
|
+
onClose={mockOnClose}
|
|
448
|
+
onSave={mockOnSave}
|
|
449
|
+
onRemove={mockOnRemove}
|
|
450
|
+
currentConfig={{
|
|
451
|
+
parent_namespace: 'test',
|
|
296
452
|
git_branch: 'main',
|
|
297
|
-
}
|
|
298
|
-
|
|
453
|
+
}}
|
|
454
|
+
namespace="test.feature"
|
|
455
|
+
/>,
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
// Wait for the component to attempt fetching parent config
|
|
459
|
+
await waitFor(() => {
|
|
460
|
+
// Should still render even if parent config fetch fails
|
|
461
|
+
expect(screen.getByDisplayValue('main')).toBeInTheDocument();
|
|
299
462
|
});
|
|
463
|
+
|
|
464
|
+
// Parent config should not be shown (fetch failed)
|
|
465
|
+
expect(screen.queryByText('test/repo')).not.toBeInTheDocument();
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
it('should allow switching from branch mode to root mode', async () => {
|
|
469
|
+
render(
|
|
470
|
+
<GitSettingsModal
|
|
471
|
+
isOpen={true}
|
|
472
|
+
onClose={mockOnClose}
|
|
473
|
+
onSave={mockOnSave}
|
|
474
|
+
onRemove={mockOnRemove}
|
|
475
|
+
currentConfig={null}
|
|
476
|
+
namespace="test.feature"
|
|
477
|
+
/>,
|
|
478
|
+
);
|
|
479
|
+
|
|
480
|
+
// Start in branch mode
|
|
481
|
+
fireEvent.click(screen.getByText('Branch Namespace'));
|
|
482
|
+
expect(screen.getByLabelText('Branch *')).toBeInTheDocument();
|
|
483
|
+
|
|
484
|
+
// Switch to root mode
|
|
485
|
+
fireEvent.click(screen.getByText('Git Root'));
|
|
486
|
+
|
|
487
|
+
// Should show repository and default branch fields instead of branch field
|
|
488
|
+
expect(screen.getByLabelText(/Repository/)).toBeInTheDocument();
|
|
489
|
+
expect(screen.getByLabelText(/Default Branch/)).toBeInTheDocument();
|
|
490
|
+
expect(screen.queryByLabelText('Branch *')).not.toBeInTheDocument();
|
|
300
491
|
});
|
|
301
492
|
});
|