@scality/data-browser-library 1.0.5 → 1.0.7
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/dist/components/__tests__/BucketCreate.test.js +60 -20
- package/dist/components/__tests__/BucketLifecycleFormPage.test.js +72 -0
- package/dist/components/__tests__/BucketList.test.js +19 -7
- package/dist/components/__tests__/BucketNotificationFormPage.test.js +54 -19
- package/dist/components/__tests__/BucketPolicyPage.test.js +5 -0
- package/dist/components/__tests__/BucketReplicationFormPage.test.js +259 -61
- package/dist/components/__tests__/MetadataSearch.test.js +18 -12
- package/dist/components/buckets/BucketLifecycleFormPage.js +50 -3
- package/dist/components/buckets/BucketReplicationFormPage.js +50 -4
- package/dist/components/buckets/__tests__/BucketVersioning.test.js +2 -0
- package/dist/components/objects/ObjectLock/__tests__/EditRetentionButton.test.js +8 -0
- package/dist/components/objects/ObjectLock/__tests__/ObjectLockSettings.test.js +78 -26
- package/dist/config/__tests__/factory.test.js +29 -1
- package/dist/config/factory.d.ts +2 -0
- package/dist/config/factory.js +3 -1
- package/dist/hooks/__tests__/useISVBucketDetection.test.js +22 -1
- package/dist/hooks/useISVBucketDetection.d.ts +1 -0
- package/dist/hooks/useISVBucketDetection.js +5 -3
- package/dist/test/testUtils.d.ts +1 -0
- package/dist/test/testUtils.js +1 -0
- package/dist/utils/constants.d.ts +2 -0
- package/dist/utils/constants.js +2 -1
- package/package.json +4 -3
|
@@ -76,7 +76,9 @@ const setupMocks = (overrides = {})=>{
|
|
|
76
76
|
mockUseSetBucketEncryption.mockReturnValue(createMockMutationResult(mockMutations.setBucketEncryption));
|
|
77
77
|
};
|
|
78
78
|
const fillBucketName = async (name)=>{
|
|
79
|
-
const nameInput = screen.
|
|
79
|
+
const nameInput = screen.getByRole('textbox', {
|
|
80
|
+
name: /bucket name/i
|
|
81
|
+
});
|
|
80
82
|
await user_event.type(nameInput, name);
|
|
81
83
|
};
|
|
82
84
|
const submitForm = async ()=>{
|
|
@@ -101,13 +103,21 @@ describe('BucketCreate', ()=>{
|
|
|
101
103
|
it('renders form with required fields', ()=>{
|
|
102
104
|
renderBucketCreate();
|
|
103
105
|
expect(screen.getByText('Create a New Bucket')).toBeInTheDocument();
|
|
104
|
-
expect(screen.
|
|
105
|
-
|
|
106
|
-
|
|
106
|
+
expect(screen.getByRole('textbox', {
|
|
107
|
+
name: /bucket name/i
|
|
108
|
+
})).toBeInTheDocument();
|
|
109
|
+
expect(screen.getByRole('checkbox', {
|
|
110
|
+
name: /versioning/i
|
|
111
|
+
})).toBeInTheDocument();
|
|
112
|
+
expect(screen.getByRole('checkbox', {
|
|
113
|
+
name: /object-lock/i
|
|
114
|
+
})).toBeInTheDocument();
|
|
107
115
|
});
|
|
108
116
|
it('shows validation error for invalid bucket name with uppercase', async ()=>{
|
|
109
117
|
renderBucketCreate();
|
|
110
|
-
await user_event.type(screen.
|
|
118
|
+
await user_event.type(screen.getByRole('textbox', {
|
|
119
|
+
name: /bucket name/i
|
|
120
|
+
}), 'INVALID');
|
|
111
121
|
await user_event.tab();
|
|
112
122
|
await waitFor(()=>{
|
|
113
123
|
expect(screen.getByText(/bucket names can include only lowercase/i)).toBeInTheDocument();
|
|
@@ -115,7 +125,9 @@ describe('BucketCreate', ()=>{
|
|
|
115
125
|
});
|
|
116
126
|
it('shows validation error for bucket name starting with hyphen', async ()=>{
|
|
117
127
|
renderBucketCreate();
|
|
118
|
-
await user_event.type(screen.
|
|
128
|
+
await user_event.type(screen.getByRole('textbox', {
|
|
129
|
+
name: /bucket name/i
|
|
130
|
+
}), '-invalid');
|
|
119
131
|
await user_event.tab();
|
|
120
132
|
await waitFor(()=>{
|
|
121
133
|
expect(screen.getByText(/bucket names can include only lowercase/i)).toBeInTheDocument();
|
|
@@ -123,7 +135,9 @@ describe('BucketCreate', ()=>{
|
|
|
123
135
|
});
|
|
124
136
|
it('shows validation error for bucket name ending with hyphen', async ()=>{
|
|
125
137
|
renderBucketCreate();
|
|
126
|
-
await user_event.type(screen.
|
|
138
|
+
await user_event.type(screen.getByRole('textbox', {
|
|
139
|
+
name: /bucket name/i
|
|
140
|
+
}), 'invalid-');
|
|
127
141
|
await user_event.tab();
|
|
128
142
|
await waitFor(()=>{
|
|
129
143
|
expect(screen.getByText(/bucket names can include only lowercase/i)).toBeInTheDocument();
|
|
@@ -131,7 +145,9 @@ describe('BucketCreate', ()=>{
|
|
|
131
145
|
});
|
|
132
146
|
it('shows validation error for bucket name with adjacent periods', async ()=>{
|
|
133
147
|
renderBucketCreate();
|
|
134
|
-
await user_event.type(screen.
|
|
148
|
+
await user_event.type(screen.getByRole('textbox', {
|
|
149
|
+
name: /bucket name/i
|
|
150
|
+
}), 'test..bucket');
|
|
135
151
|
await user_event.tab();
|
|
136
152
|
await waitFor(()=>{
|
|
137
153
|
expect(screen.getByText(/bucket names cannot contain two adjacent periods/i)).toBeInTheDocument();
|
|
@@ -139,7 +155,9 @@ describe('BucketCreate', ()=>{
|
|
|
139
155
|
});
|
|
140
156
|
it('shows validation error for bucket name formatted as IP address', async ()=>{
|
|
141
157
|
renderBucketCreate();
|
|
142
|
-
await user_event.type(screen.
|
|
158
|
+
await user_event.type(screen.getByRole('textbox', {
|
|
159
|
+
name: /bucket name/i
|
|
160
|
+
}), '192.168.1.1');
|
|
143
161
|
await user_event.tab();
|
|
144
162
|
await waitFor(()=>{
|
|
145
163
|
expect(screen.getByText(/bucket names must not be formatted as an ip address/i)).toBeInTheDocument();
|
|
@@ -147,7 +165,9 @@ describe('BucketCreate', ()=>{
|
|
|
147
165
|
});
|
|
148
166
|
it('shows validation error for bucket name with forbidden prefix', async ()=>{
|
|
149
167
|
renderBucketCreate();
|
|
150
|
-
await user_event.type(screen.
|
|
168
|
+
await user_event.type(screen.getByRole('textbox', {
|
|
169
|
+
name: /bucket name/i
|
|
170
|
+
}), 'xn--test');
|
|
151
171
|
await user_event.tab();
|
|
152
172
|
await waitFor(()=>{
|
|
153
173
|
expect(screen.getByText(/bucket names must not start with/i)).toBeInTheDocument();
|
|
@@ -155,7 +175,9 @@ describe('BucketCreate', ()=>{
|
|
|
155
175
|
});
|
|
156
176
|
it('shows validation error for bucket name with forbidden suffix', async ()=>{
|
|
157
177
|
renderBucketCreate();
|
|
158
|
-
await user_event.type(screen.
|
|
178
|
+
await user_event.type(screen.getByRole('textbox', {
|
|
179
|
+
name: /bucket name/i
|
|
180
|
+
}), 'test-s3alias');
|
|
159
181
|
await user_event.tab();
|
|
160
182
|
await waitFor(()=>{
|
|
161
183
|
expect(screen.getByText(/bucket names must not end with/i)).toBeInTheDocument();
|
|
@@ -170,7 +192,9 @@ describe('BucketCreate', ()=>{
|
|
|
170
192
|
]
|
|
171
193
|
}
|
|
172
194
|
});
|
|
173
|
-
await user_event.type(screen.
|
|
195
|
+
await user_event.type(screen.getByRole('textbox', {
|
|
196
|
+
name: /bucket name/i
|
|
197
|
+
}), 'existing-bucket');
|
|
174
198
|
await user_event.tab();
|
|
175
199
|
await waitFor(()=>{
|
|
176
200
|
expect(screen.getByText(/a bucket with this name already exists/i)).toBeInTheDocument();
|
|
@@ -185,7 +209,9 @@ describe('BucketCreate', ()=>{
|
|
|
185
209
|
'123-bucket-456'
|
|
186
210
|
];
|
|
187
211
|
for (const name of validNames){
|
|
188
|
-
const input = screen.
|
|
212
|
+
const input = screen.getByRole('textbox', {
|
|
213
|
+
name: /bucket name/i
|
|
214
|
+
});
|
|
189
215
|
await user_event.clear(input);
|
|
190
216
|
await user_event.type(input, name);
|
|
191
217
|
await user_event.tab();
|
|
@@ -469,7 +495,9 @@ describe('BucketCreate', ()=>{
|
|
|
469
495
|
});
|
|
470
496
|
renderBucketCreate();
|
|
471
497
|
await fillBucketName('test-bucket');
|
|
472
|
-
const encryptionCheckbox = screen.
|
|
498
|
+
const encryptionCheckbox = screen.getByRole('checkbox', {
|
|
499
|
+
name: /encryption/i
|
|
500
|
+
});
|
|
473
501
|
await user_event.click(encryptionCheckbox);
|
|
474
502
|
await submitForm();
|
|
475
503
|
const createSuccessCallback = mockMutations.createBucket.mock.calls[0][1].onSuccess;
|
|
@@ -516,8 +544,12 @@ describe('BucketCreate', ()=>{
|
|
|
516
544
|
});
|
|
517
545
|
renderBucketCreate();
|
|
518
546
|
await fillBucketName('test-bucket');
|
|
519
|
-
await user_event.click(screen.
|
|
520
|
-
|
|
547
|
+
await user_event.click(screen.getByRole('checkbox', {
|
|
548
|
+
name: /versioning/i
|
|
549
|
+
}));
|
|
550
|
+
await user_event.click(screen.getByRole('checkbox', {
|
|
551
|
+
name: /encryption/i
|
|
552
|
+
}));
|
|
521
553
|
await submitForm();
|
|
522
554
|
const createSuccessCallback = mockMutations.createBucket.mock.calls[0][1].onSuccess;
|
|
523
555
|
createSuccessCallback();
|
|
@@ -536,9 +568,15 @@ describe('BucketCreate', ()=>{
|
|
|
536
568
|
});
|
|
537
569
|
renderBucketCreate();
|
|
538
570
|
await fillBucketName('test-bucket');
|
|
539
|
-
await user_event.click(screen.
|
|
540
|
-
|
|
541
|
-
|
|
571
|
+
await user_event.click(screen.getByRole('checkbox', {
|
|
572
|
+
name: /object-lock/i
|
|
573
|
+
}));
|
|
574
|
+
await user_event.click(screen.getByRole('checkbox', {
|
|
575
|
+
name: /default retention/i
|
|
576
|
+
}));
|
|
577
|
+
await user_event.click(screen.getByRole('checkbox', {
|
|
578
|
+
name: /encryption/i
|
|
579
|
+
}));
|
|
542
580
|
await submitForm();
|
|
543
581
|
const createSuccessCallback = mockMutations.createBucket.mock.calls[0][1].onSuccess;
|
|
544
582
|
createSuccessCallback();
|
|
@@ -557,7 +595,9 @@ describe('BucketCreate', ()=>{
|
|
|
557
595
|
});
|
|
558
596
|
renderBucketCreate();
|
|
559
597
|
await fillBucketName('test-bucket');
|
|
560
|
-
await user_event.click(screen.
|
|
598
|
+
await user_event.click(screen.getByRole('checkbox', {
|
|
599
|
+
name: /encryption/i
|
|
600
|
+
}));
|
|
561
601
|
await submitForm();
|
|
562
602
|
const createSuccessCallback = mockMutations.createBucket.mock.calls[0][1].onSuccess;
|
|
563
603
|
createSuccessCallback();
|
|
@@ -3,14 +3,19 @@ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
|
3
3
|
import user_event from "@testing-library/user-event";
|
|
4
4
|
import { MemoryRouter, Route, Routes } from "react-router";
|
|
5
5
|
import { useGetBucketLifecycle, useSetBucketLifecycle } from "../../hooks/bucketConfiguration.js";
|
|
6
|
+
import { useISVBucketStatus } from "../../hooks/useISVBucketDetection.js";
|
|
6
7
|
import { createTestWrapper, findToggleByLabel, mockErrorSubmit, mockOffsetSize, mockSuccessSubmit, submitForm } from "../../test/testUtils.js";
|
|
7
8
|
import { BucketLifecycleFormPage } from "../buckets/BucketLifecycleFormPage.js";
|
|
8
9
|
jest.mock('../../hooks/bucketConfiguration', ()=>({
|
|
9
10
|
useGetBucketLifecycle: jest.fn(),
|
|
10
11
|
useSetBucketLifecycle: jest.fn()
|
|
11
12
|
}));
|
|
13
|
+
jest.mock('../../hooks/useISVBucketDetection', ()=>({
|
|
14
|
+
useISVBucketStatus: jest.fn()
|
|
15
|
+
}));
|
|
12
16
|
const mockUseGetBucketLifecycle = jest.mocked(useGetBucketLifecycle);
|
|
13
17
|
const mockUseSetBucketLifecycle = jest.mocked(useSetBucketLifecycle);
|
|
18
|
+
const mockUseISVBucketStatus = jest.mocked(useISVBucketStatus);
|
|
14
19
|
const mockNavigate = jest.fn();
|
|
15
20
|
const mockShowToast = jest.fn();
|
|
16
21
|
jest.mock('react-router', ()=>({
|
|
@@ -69,6 +74,15 @@ describe('BucketLifecycleFormPage', ()=>{
|
|
|
69
74
|
mutate: mockMutate,
|
|
70
75
|
isPending: false
|
|
71
76
|
});
|
|
77
|
+
mockUseISVBucketStatus.mockReturnValue({
|
|
78
|
+
isVeeamBucket: false,
|
|
79
|
+
isCommvaultBucket: false,
|
|
80
|
+
isKastenBucket: false,
|
|
81
|
+
isISVManaged: false,
|
|
82
|
+
isvApplication: void 0,
|
|
83
|
+
isLoading: false,
|
|
84
|
+
bucketTagsStatus: 'success'
|
|
85
|
+
});
|
|
72
86
|
});
|
|
73
87
|
describe('Page Rendering', ()=>{
|
|
74
88
|
it('renders create mode with correct title', ()=>{
|
|
@@ -615,4 +629,62 @@ describe('BucketLifecycleFormPage', ()=>{
|
|
|
615
629
|
});
|
|
616
630
|
});
|
|
617
631
|
});
|
|
632
|
+
describe('ISV Bucket Warning', ()=>{
|
|
633
|
+
const setupISVMock = (isvApplication = 'Veeam')=>{
|
|
634
|
+
mockUseISVBucketStatus.mockReturnValue({
|
|
635
|
+
isVeeamBucket: 'Veeam' === isvApplication,
|
|
636
|
+
isCommvaultBucket: 'Commvault' === isvApplication,
|
|
637
|
+
isKastenBucket: 'Kasten' === isvApplication,
|
|
638
|
+
isISVManaged: true,
|
|
639
|
+
isvApplication,
|
|
640
|
+
isLoading: false,
|
|
641
|
+
bucketTagsStatus: 'success'
|
|
642
|
+
});
|
|
643
|
+
};
|
|
644
|
+
it('renders ISV warning banner and checkbox when bucket is ISV-managed', ()=>{
|
|
645
|
+
setupISVMock('Veeam');
|
|
646
|
+
renderBucketLifecycleFormPage();
|
|
647
|
+
expect(screen.getByText(/bucket used for external integration with Veeam/i)).toBeInTheDocument();
|
|
648
|
+
expect(screen.getByText(/may conflict with Veeam's backup strategy/i)).toBeInTheDocument();
|
|
649
|
+
expect(screen.getByLabelText(/i understand what i'm doing/i)).toBeInTheDocument();
|
|
650
|
+
});
|
|
651
|
+
it('does not render ISV warning for non-ISV buckets', ()=>{
|
|
652
|
+
renderBucketLifecycleFormPage();
|
|
653
|
+
expect(screen.queryByText(/bucket used for external integration with/i)).not.toBeInTheDocument();
|
|
654
|
+
expect(screen.queryByLabelText(/i understand what i'm doing/i)).not.toBeInTheDocument();
|
|
655
|
+
});
|
|
656
|
+
it('blocks form submission when ISV checkbox is unchecked', async ()=>{
|
|
657
|
+
setupISVMock('Veeam');
|
|
658
|
+
renderBucketLifecycleFormPage();
|
|
659
|
+
await fillRequiredFields('isv-rule');
|
|
660
|
+
await waitFor(()=>{
|
|
661
|
+
const createButton = screen.getByRole('button', {
|
|
662
|
+
name: /create/i
|
|
663
|
+
});
|
|
664
|
+
expect(createButton).toBeDisabled();
|
|
665
|
+
});
|
|
666
|
+
});
|
|
667
|
+
it('allows form submission when ISV checkbox is checked', async ()=>{
|
|
668
|
+
setupISVMock('Veeam');
|
|
669
|
+
renderBucketLifecycleFormPage();
|
|
670
|
+
await fillRequiredFields('isv-rule');
|
|
671
|
+
const checkbox = screen.getByLabelText(/i understand what i'm doing/i);
|
|
672
|
+
await user_event.click(checkbox);
|
|
673
|
+
mockSuccessSubmit(mockMutate);
|
|
674
|
+
await submitForm('create');
|
|
675
|
+
await waitFor(()=>{
|
|
676
|
+
expect(mockMutate).toHaveBeenCalled();
|
|
677
|
+
});
|
|
678
|
+
});
|
|
679
|
+
it('displays correct application name for Commvault ISV bucket', ()=>{
|
|
680
|
+
setupISVMock('Commvault');
|
|
681
|
+
renderBucketLifecycleFormPage();
|
|
682
|
+
expect(screen.getByText(/bucket used for external integration with Commvault/i)).toBeInTheDocument();
|
|
683
|
+
});
|
|
684
|
+
it('displays correct application name for Kasten ISV bucket', ()=>{
|
|
685
|
+
setupISVMock('Kasten');
|
|
686
|
+
renderBucketLifecycleFormPage();
|
|
687
|
+
expect(screen.getByText(/bucket used for external integration with Kasten/i)).toBeInTheDocument();
|
|
688
|
+
});
|
|
689
|
+
});
|
|
618
690
|
});
|
|
@@ -45,9 +45,15 @@ describe('BucketList', ()=>{
|
|
|
45
45
|
buckets: mockBuckets
|
|
46
46
|
});
|
|
47
47
|
expect(screen.getByRole('grid')).toBeInTheDocument();
|
|
48
|
-
expect(screen.
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
expect(screen.getByRole('columnheader', {
|
|
49
|
+
name: /bucket name/i
|
|
50
|
+
})).toBeInTheDocument();
|
|
51
|
+
expect(screen.getByRole('columnheader', {
|
|
52
|
+
name: /storage location/i
|
|
53
|
+
})).toBeInTheDocument();
|
|
54
|
+
expect(screen.getByRole('columnheader', {
|
|
55
|
+
name: /created on/i
|
|
56
|
+
})).toBeInTheDocument();
|
|
51
57
|
});
|
|
52
58
|
it('displays buckets with their names as clickable links', ()=>{
|
|
53
59
|
const onNavigateToBucket = jest.fn();
|
|
@@ -109,14 +115,16 @@ describe('BucketList', ()=>{
|
|
|
109
115
|
});
|
|
110
116
|
const searchInput = screen.getByRole('searchbox');
|
|
111
117
|
expect(searchInput).toBeInTheDocument();
|
|
112
|
-
expect(searchInput).toHaveAttribute('placeholder', '
|
|
118
|
+
expect(searchInput).toHaveAttribute('placeholder', 'Search');
|
|
113
119
|
});
|
|
114
120
|
it('handles empty buckets list', ()=>{
|
|
115
121
|
renderBucketList({
|
|
116
122
|
buckets: []
|
|
117
123
|
});
|
|
118
124
|
expect(screen.getByRole('grid')).toBeInTheDocument();
|
|
119
|
-
expect(screen.
|
|
125
|
+
expect(screen.getByRole('columnheader', {
|
|
126
|
+
name: /bucket name/i
|
|
127
|
+
})).toBeInTheDocument();
|
|
120
128
|
});
|
|
121
129
|
it('handles buckets without names gracefully', ()=>{
|
|
122
130
|
const bucketsWithMissingNames = [
|
|
@@ -248,7 +256,9 @@ describe('BucketList', ()=>{
|
|
|
248
256
|
renderBucketList({
|
|
249
257
|
buckets: bucketsWithReversedDateOrder
|
|
250
258
|
});
|
|
251
|
-
fireEvent.click(screen.
|
|
259
|
+
fireEvent.click(screen.getByRole('columnheader', {
|
|
260
|
+
name: /created on/i
|
|
261
|
+
}));
|
|
252
262
|
const rows = screen.getAllByRole('row');
|
|
253
263
|
expect(rows[1]).toHaveTextContent('alpha-bucket');
|
|
254
264
|
expect(rows[2]).toHaveTextContent('gamma-bucket');
|
|
@@ -272,7 +282,9 @@ describe('BucketList', ()=>{
|
|
|
272
282
|
renderBucketList({
|
|
273
283
|
buckets: mockBuckets
|
|
274
284
|
});
|
|
275
|
-
fireEvent.click(screen.
|
|
285
|
+
fireEvent.click(screen.getByRole('columnheader', {
|
|
286
|
+
name: /storage location/i
|
|
287
|
+
}));
|
|
276
288
|
const rows = screen.getAllByRole('row');
|
|
277
289
|
expect(rows[1]).toHaveTextContent('test-bucket-3');
|
|
278
290
|
expect(rows[2]).toHaveTextContent('test-bucket-2');
|
|
@@ -66,11 +66,18 @@ describe('BucketNotificationFormPage', ()=>{
|
|
|
66
66
|
it('renders create notification form with all fields', ()=>{
|
|
67
67
|
renderCreatePage();
|
|
68
68
|
expect(screen.getByText('Create Bucket Notification')).toBeInTheDocument();
|
|
69
|
-
expect(screen.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
expect(screen.
|
|
73
|
-
|
|
69
|
+
expect(screen.getByRole('textbox', {
|
|
70
|
+
name: /rule name/i
|
|
71
|
+
})).toBeInTheDocument();
|
|
72
|
+
expect(screen.getByRole('textbox', {
|
|
73
|
+
name: /destination queue/i
|
|
74
|
+
})).toBeInTheDocument();
|
|
75
|
+
expect(screen.getByRole('textbox', {
|
|
76
|
+
name: /^prefix$/i
|
|
77
|
+
})).toBeInTheDocument();
|
|
78
|
+
expect(screen.getByRole('textbox', {
|
|
79
|
+
name: /^suffix$/i
|
|
80
|
+
})).toBeInTheDocument();
|
|
74
81
|
});
|
|
75
82
|
it('disables create button when form is pristine', ()=>{
|
|
76
83
|
renderCreatePage();
|
|
@@ -80,7 +87,9 @@ describe('BucketNotificationFormPage', ()=>{
|
|
|
80
87
|
});
|
|
81
88
|
it('shows validation error when rule name is empty', async ()=>{
|
|
82
89
|
renderCreatePage();
|
|
83
|
-
const ruleNameInput = screen.
|
|
90
|
+
const ruleNameInput = screen.getByRole('textbox', {
|
|
91
|
+
name: /rule name/i
|
|
92
|
+
});
|
|
84
93
|
await user_event.type(ruleNameInput, 'a');
|
|
85
94
|
await user_event.clear(ruleNameInput);
|
|
86
95
|
await waitFor(()=>{
|
|
@@ -104,7 +113,9 @@ describe('BucketNotificationFormPage', ()=>{
|
|
|
104
113
|
status: 'success'
|
|
105
114
|
});
|
|
106
115
|
renderCreatePage();
|
|
107
|
-
const ruleNameInput = screen.
|
|
116
|
+
const ruleNameInput = screen.getByRole('textbox', {
|
|
117
|
+
name: /rule name/i
|
|
118
|
+
});
|
|
108
119
|
await user_event.type(ruleNameInput, 'existing-rule');
|
|
109
120
|
await waitFor(()=>{
|
|
110
121
|
expect(screen.getByText(/a rule with this name already exists/i)).toBeInTheDocument();
|
|
@@ -112,7 +123,9 @@ describe('BucketNotificationFormPage', ()=>{
|
|
|
112
123
|
});
|
|
113
124
|
it('shows validation error when queue ARN is invalid', async ()=>{
|
|
114
125
|
renderCreatePage();
|
|
115
|
-
const queueArnInput = screen.
|
|
126
|
+
const queueArnInput = screen.getByRole('textbox', {
|
|
127
|
+
name: /destination queue/i
|
|
128
|
+
});
|
|
116
129
|
await user_event.type(queueArnInput, 'invalid-arn');
|
|
117
130
|
await waitFor(()=>{
|
|
118
131
|
expect(screen.getByText(/must be a valid arn/i)).toBeInTheDocument();
|
|
@@ -120,8 +133,12 @@ describe('BucketNotificationFormPage', ()=>{
|
|
|
120
133
|
});
|
|
121
134
|
it('enables create button when form is valid', async ()=>{
|
|
122
135
|
renderCreatePage();
|
|
123
|
-
await user_event.type(screen.
|
|
124
|
-
|
|
136
|
+
await user_event.type(screen.getByRole('textbox', {
|
|
137
|
+
name: /rule name/i
|
|
138
|
+
}), 'test-rule');
|
|
139
|
+
await user_event.type(screen.getByRole('textbox', {
|
|
140
|
+
name: /destination queue/i
|
|
141
|
+
}), 'arn:aws:sqs:us-east-1:123:queue');
|
|
125
142
|
const checkbox = screen.getByRole('checkbox', {
|
|
126
143
|
name: /s3:ObjectCreated:\*/i
|
|
127
144
|
});
|
|
@@ -134,13 +151,21 @@ describe('BucketNotificationFormPage', ()=>{
|
|
|
134
151
|
});
|
|
135
152
|
it('creates notification with all fields and navigates on success', async ()=>{
|
|
136
153
|
renderCreatePage();
|
|
137
|
-
await user_event.type(screen.
|
|
138
|
-
|
|
154
|
+
await user_event.type(screen.getByRole('textbox', {
|
|
155
|
+
name: /rule name/i
|
|
156
|
+
}), 'test-rule');
|
|
157
|
+
await user_event.type(screen.getByRole('textbox', {
|
|
158
|
+
name: /destination queue/i
|
|
159
|
+
}), 'arn:aws:sqs:us-east-1:123:my-queue');
|
|
139
160
|
fireEvent.click(screen.getByRole('checkbox', {
|
|
140
161
|
name: /s3:ObjectCreated:Put/i
|
|
141
162
|
}));
|
|
142
|
-
await user_event.type(screen.
|
|
143
|
-
|
|
163
|
+
await user_event.type(screen.getByRole('textbox', {
|
|
164
|
+
name: /^prefix$/i
|
|
165
|
+
}), 'uploads/');
|
|
166
|
+
await user_event.type(screen.getByRole('textbox', {
|
|
167
|
+
name: /^suffix$/i
|
|
168
|
+
}), '.jpg');
|
|
144
169
|
mockMutate.mockImplementation((_, options)=>{
|
|
145
170
|
options?.onSuccess?.();
|
|
146
171
|
});
|
|
@@ -263,9 +288,15 @@ describe('BucketNotificationFormPage', ()=>{
|
|
|
263
288
|
it('pre-fills form with existing rule data', async ()=>{
|
|
264
289
|
renderEditPage();
|
|
265
290
|
await waitFor(()=>{
|
|
266
|
-
expect(screen.
|
|
267
|
-
|
|
268
|
-
|
|
291
|
+
expect(screen.getByRole('textbox', {
|
|
292
|
+
name: /destination queue/i
|
|
293
|
+
})).toHaveValue('arn:aws:sqs:us-east-1:123:existing-queue');
|
|
294
|
+
expect(screen.getByRole('textbox', {
|
|
295
|
+
name: /^prefix$/i
|
|
296
|
+
})).toHaveValue('data/');
|
|
297
|
+
expect(screen.getByRole('textbox', {
|
|
298
|
+
name: /^suffix$/i
|
|
299
|
+
})).toHaveValue('.json');
|
|
269
300
|
});
|
|
270
301
|
});
|
|
271
302
|
it('shows Save button instead of Create in edit mode', ()=>{
|
|
@@ -280,9 +311,13 @@ describe('BucketNotificationFormPage', ()=>{
|
|
|
280
311
|
it('updates notification and navigates on success', async ()=>{
|
|
281
312
|
renderEditPage();
|
|
282
313
|
await waitFor(()=>{
|
|
283
|
-
expect(screen.
|
|
314
|
+
expect(screen.getByRole('textbox', {
|
|
315
|
+
name: /destination queue/i
|
|
316
|
+
})).toHaveValue('arn:aws:sqs:us-east-1:123:existing-queue');
|
|
317
|
+
});
|
|
318
|
+
const queueInput = screen.getByRole('textbox', {
|
|
319
|
+
name: /destination queue/i
|
|
284
320
|
});
|
|
285
|
-
const queueInput = screen.getByLabelText(/destination queue/i);
|
|
286
321
|
await user_event.clear(queueInput);
|
|
287
322
|
await user_event.type(queueInput, 'arn:aws:sqs:us-east-1:123:updated-queue');
|
|
288
323
|
mockMutate.mockImplementation((_, options)=>{
|
|
@@ -73,6 +73,7 @@ describe('BucketPolicyPage', ()=>{
|
|
|
73
73
|
mockUseISVBucketStatus.mockReturnValue({
|
|
74
74
|
isVeeamBucket: false,
|
|
75
75
|
isCommvaultBucket: false,
|
|
76
|
+
isKastenBucket: false,
|
|
76
77
|
isISVManaged: false,
|
|
77
78
|
isvApplication: void 0,
|
|
78
79
|
isLoading: false,
|
|
@@ -204,6 +205,7 @@ describe('BucketPolicyPage', ()=>{
|
|
|
204
205
|
mockUseISVBucketStatus.mockReturnValue({
|
|
205
206
|
isVeeamBucket: false,
|
|
206
207
|
isCommvaultBucket: false,
|
|
208
|
+
isKastenBucket: false,
|
|
207
209
|
isISVManaged: false,
|
|
208
210
|
isvApplication: void 0,
|
|
209
211
|
isLoading: true,
|
|
@@ -217,6 +219,7 @@ describe('BucketPolicyPage', ()=>{
|
|
|
217
219
|
mockUseISVBucketStatus.mockReturnValue({
|
|
218
220
|
isVeeamBucket: true,
|
|
219
221
|
isCommvaultBucket: false,
|
|
222
|
+
isKastenBucket: false,
|
|
220
223
|
isISVManaged: true,
|
|
221
224
|
isvApplication: 'Veeam',
|
|
222
225
|
isLoading: false,
|
|
@@ -234,6 +237,7 @@ describe('BucketPolicyPage', ()=>{
|
|
|
234
237
|
mockUseISVBucketStatus.mockReturnValue({
|
|
235
238
|
isVeeamBucket: false,
|
|
236
239
|
isCommvaultBucket: true,
|
|
240
|
+
isKastenBucket: false,
|
|
237
241
|
isISVManaged: true,
|
|
238
242
|
isvApplication: 'Commvault',
|
|
239
243
|
isLoading: false,
|
|
@@ -251,6 +255,7 @@ describe('BucketPolicyPage', ()=>{
|
|
|
251
255
|
mockUseISVBucketStatus.mockReturnValue({
|
|
252
256
|
isVeeamBucket: false,
|
|
253
257
|
isCommvaultBucket: false,
|
|
258
|
+
isKastenBucket: false,
|
|
254
259
|
isISVManaged: false,
|
|
255
260
|
isvApplication: void 0,
|
|
256
261
|
isLoading: false,
|