@transferwise/components 46.94.1 → 46.94.2
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/build/dateLookup/dateHeader/DateHeader.js +27 -22
- package/build/dateLookup/dateHeader/DateHeader.js.map +1 -1
- package/build/dateLookup/dateHeader/DateHeader.mjs +27 -22
- package/build/dateLookup/dateHeader/DateHeader.mjs.map +1 -1
- package/build/i18n/nl.json +73 -0
- package/build/main.css +2 -7
- package/build/styles/button/Button.css +2 -2
- package/build/styles/dateLookup/DateLookup.css +0 -5
- package/build/styles/main.css +2 -7
- package/build/types/dateLookup/dateHeader/DateHeader.d.ts.map +1 -1
- package/build/types/upload/Upload.d.ts.map +1 -1
- package/build/upload/Upload.js +3 -1
- package/build/upload/Upload.js.map +1 -1
- package/build/upload/Upload.mjs +3 -1
- package/build/upload/Upload.mjs.map +1 -1
- package/package.json +4 -4
- package/src/button/Button.css +2 -2
- package/src/button/Button.less +2 -2
- package/src/dateLookup/DateLookup.css +0 -5
- package/src/dateLookup/DateLookup.less +0 -4
- package/src/dateLookup/dateHeader/DateHeader.tsx +24 -26
- package/src/i18n/nl.json +73 -0
- package/src/main.css +2 -7
- package/src/upload/Upload.spec.tsx +293 -0
- package/src/upload/Upload.tsx +5 -1
- package/src/upload/steps/completeStep/completeStep.spec.tsx +51 -0
- package/src/upload/steps/processingStep/processingStep.spec.tsx +59 -0
- package/src/upload/steps/uploadImageStep/uploadImageStep.spec.tsx +79 -0
- package/src/upload/Upload.events.spec.js +0 -49
- package/src/upload/Upload.spec.js +0 -305
- package/src/upload/steps/completeStep/completeStep.spec.js +0 -51
- package/src/upload/steps/processingStep/processingStep.spec.js +0 -55
- package/src/upload/steps/uploadImageStep/uploadImageStep.spec.js +0 -91
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { render, fireEvent, waitFor, screen } from '../test-utils';
|
|
2
|
+
import { act } from 'react';
|
|
3
|
+
import Upload from '.';
|
|
4
|
+
import { asyncFileRead } from './utils/asyncFileRead';
|
|
5
|
+
import { postData } from './utils/postData';
|
|
6
|
+
|
|
7
|
+
jest.mock('./utils/asyncFileRead');
|
|
8
|
+
jest.mock('./utils/postData');
|
|
9
|
+
|
|
10
|
+
const TEST_FILE = new File(['test content'], 'test.png', { type: 'image/png' });
|
|
11
|
+
const INVALID_FILE = new File(['invalid content'], 'invalid.txt', { type: 'text/plain' });
|
|
12
|
+
|
|
13
|
+
beforeAll(() => {
|
|
14
|
+
class MockDataTransfer {
|
|
15
|
+
items: { add: (file: File) => void };
|
|
16
|
+
files: File[];
|
|
17
|
+
|
|
18
|
+
constructor() {
|
|
19
|
+
this.items = {
|
|
20
|
+
add: (file: File) => {
|
|
21
|
+
this.files.push(file);
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
this.files = [];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// @ts-expect-error: Mocking global DataTransfer for testing purposes
|
|
29
|
+
global.DataTransfer = MockDataTransfer;
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('Upload Component', () => {
|
|
33
|
+
const props = {
|
|
34
|
+
animationDelay: 100,
|
|
35
|
+
csButtonText: 'csButtonText',
|
|
36
|
+
csFailureText: 'csFailureText',
|
|
37
|
+
csSuccessText: 'csSuccessText',
|
|
38
|
+
csTooLargeMessage: 'csTooLargeMessage',
|
|
39
|
+
maxSize: 5000000,
|
|
40
|
+
onCancel: jest.fn(),
|
|
41
|
+
onChange: jest.fn(),
|
|
42
|
+
onFailure: jest.fn(),
|
|
43
|
+
onStart: jest.fn(),
|
|
44
|
+
onSuccess: jest.fn(),
|
|
45
|
+
psButtonText: 'psButtonText',
|
|
46
|
+
psProcessingText: 'psProcessingText',
|
|
47
|
+
usAccept: 'image/*',
|
|
48
|
+
usButtonText: 'Or Select File',
|
|
49
|
+
usButtonRetryText: 'Try again',
|
|
50
|
+
usDropMessage: 'Drop file to start upload',
|
|
51
|
+
usPlaceholder: 'Drag and drop a file less than 5MB',
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const waitForUpload = async () => {
|
|
55
|
+
for (let i = 0; i < 4; i += 1) {
|
|
56
|
+
await act(async () => {
|
|
57
|
+
await jest.runOnlyPendingTimersAsync();
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
beforeEach(() => {
|
|
63
|
+
jest.useFakeTimers();
|
|
64
|
+
(asyncFileRead as jest.Mock).mockImplementation(async () => 'a value');
|
|
65
|
+
(postData as jest.Mock).mockResolvedValue('ServerResponse');
|
|
66
|
+
Object.defineProperty(window, 'matchMedia', {
|
|
67
|
+
writable: true,
|
|
68
|
+
value: jest.fn().mockImplementation((query: string) => ({
|
|
69
|
+
matches: false,
|
|
70
|
+
media: query,
|
|
71
|
+
onchange: null,
|
|
72
|
+
addListener: jest.fn(),
|
|
73
|
+
removeListener: jest.fn(),
|
|
74
|
+
addEventListener: jest.fn(),
|
|
75
|
+
removeEventListener: jest.fn(),
|
|
76
|
+
dispatchEvent: jest.fn(),
|
|
77
|
+
})),
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
afterEach(async () => {
|
|
82
|
+
await jest.runOnlyPendingTimersAsync();
|
|
83
|
+
jest.runOnlyPendingTimers();
|
|
84
|
+
jest.useRealTimers();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('adds droppable-dropping class on dragenter', async () => {
|
|
88
|
+
const { container } = render(<Upload {...props} />);
|
|
89
|
+
const droppableElement = await waitFor(() => container.querySelector('.droppable-area'));
|
|
90
|
+
expect(droppableElement).toBeTruthy();
|
|
91
|
+
|
|
92
|
+
fireEvent.dragEnter(droppableElement!, { dataTransfer: new DataTransfer() });
|
|
93
|
+
|
|
94
|
+
await waitFor(() => {
|
|
95
|
+
expect(droppableElement).toHaveClass('droppable-dropping');
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('removes droppable-dropping class on dragleave', async () => {
|
|
100
|
+
const { container } = render(<Upload {...props} />);
|
|
101
|
+
const droppableElement = await waitFor(() => container.querySelector('.droppable-area'));
|
|
102
|
+
expect(droppableElement).toBeTruthy();
|
|
103
|
+
|
|
104
|
+
fireEvent.dragEnter(droppableElement!, { dataTransfer: new DataTransfer() });
|
|
105
|
+
|
|
106
|
+
await waitFor(() => {
|
|
107
|
+
expect(droppableElement).toHaveClass('droppable-dropping');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
fireEvent.dragLeave(droppableElement!);
|
|
111
|
+
|
|
112
|
+
await waitFor(() => {
|
|
113
|
+
expect(droppableElement).not.toHaveClass('droppable-dropping');
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test('adds droppable-processing when file is dropped', async () => {
|
|
118
|
+
const { container } = render(<Upload {...props} />);
|
|
119
|
+
const droppableElement = await waitFor(() => container.querySelector('.droppable-area'));
|
|
120
|
+
|
|
121
|
+
const dataTransfer = new DataTransfer();
|
|
122
|
+
dataTransfer.items.add(TEST_FILE);
|
|
123
|
+
|
|
124
|
+
fireEvent.drop(droppableElement!, { dataTransfer });
|
|
125
|
+
|
|
126
|
+
await waitFor(() => expect(droppableElement).toHaveClass('droppable-processing'));
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test('should handle successful file upload', async () => {
|
|
130
|
+
(asyncFileRead as jest.Mock).mockResolvedValue('mockBase64Image');
|
|
131
|
+
(postData as jest.Mock).mockResolvedValue('mockSuccessResponse');
|
|
132
|
+
|
|
133
|
+
const { container } = render(<Upload {...props} />);
|
|
134
|
+
|
|
135
|
+
await act(async () => {
|
|
136
|
+
const droppableElement = await waitFor(() => container.querySelector('.droppable-area'));
|
|
137
|
+
|
|
138
|
+
const dataTransfer = new DataTransfer();
|
|
139
|
+
dataTransfer.items.add(TEST_FILE);
|
|
140
|
+
fireEvent.drop(droppableElement!, { dataTransfer });
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
await act(async () => {
|
|
144
|
+
jest.advanceTimersByTime(10);
|
|
145
|
+
jest.advanceTimersByTime(props.animationDelay);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
expect(await screen.findByText(/csSuccessText/i)).toBeInTheDocument();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test('should handle file size exceeding the limit', async () => {
|
|
152
|
+
const largeFile = new File(['large '.repeat(1000000)], 'large.jpg', { type: 'image/jpeg' });
|
|
153
|
+
const { container } = render(<Upload {...props} maxSize={10} />);
|
|
154
|
+
|
|
155
|
+
await act(async () => {
|
|
156
|
+
const droppableElement = await waitFor(() => container.querySelector('.droppable-area'));
|
|
157
|
+
const dataTransfer = new DataTransfer();
|
|
158
|
+
dataTransfer.items.add(largeFile);
|
|
159
|
+
fireEvent.drop(droppableElement!, { dataTransfer });
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
await act(async () => {
|
|
163
|
+
jest.advanceTimersByTime(1000);
|
|
164
|
+
jest.advanceTimersByTime(props.animationDelay);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
await waitForUpload();
|
|
168
|
+
|
|
169
|
+
expect(await screen.findByText(/csTooLargeMessage/i)).toBeInTheDocument();
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
test('should handle invalid file type', async () => {
|
|
173
|
+
(postData as jest.Mock).mockRejectedValue(new Error('mockErrorResponse'));
|
|
174
|
+
|
|
175
|
+
const { container } = render(<Upload {...props} />);
|
|
176
|
+
|
|
177
|
+
await act(async () => {
|
|
178
|
+
const droppableElement = await waitFor(() => container.querySelector('.droppable-area'));
|
|
179
|
+
|
|
180
|
+
const dataTransfer = new DataTransfer();
|
|
181
|
+
dataTransfer.items.add(INVALID_FILE);
|
|
182
|
+
fireEvent.drop(droppableElement!, { dataTransfer });
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
await waitForUpload();
|
|
186
|
+
|
|
187
|
+
expect(await screen.findByText(/File type not supported. Please try again with a different file/i)).toBeInTheDocument();
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
test('should handle canceling the upload', async () => {
|
|
191
|
+
const { container } = render(<Upload {...props} />);
|
|
192
|
+
|
|
193
|
+
await act(async () => {
|
|
194
|
+
const droppableElement = await waitFor(() => container.querySelector('.droppable-area'));
|
|
195
|
+
|
|
196
|
+
const dataTransfer = new DataTransfer();
|
|
197
|
+
dataTransfer.items.add(TEST_FILE);
|
|
198
|
+
fireEvent.drop(droppableElement!, { dataTransfer });
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
fireEvent.click(await screen.findByText(/csButtonText/i));
|
|
202
|
+
|
|
203
|
+
expect(props.onCancel).toHaveBeenCalled();
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
test('should handle retrying the upload', async () => {
|
|
207
|
+
(asyncFileRead as jest.Mock).mockRejectedValueOnce('error');
|
|
208
|
+
|
|
209
|
+
const { container } = render(<Upload {...props} />);
|
|
210
|
+
|
|
211
|
+
await act(async () => {
|
|
212
|
+
const droppableElement = await waitFor(() => container.querySelector('.droppable-area'));
|
|
213
|
+
|
|
214
|
+
const dataTransfer = new DataTransfer();
|
|
215
|
+
dataTransfer.items.add(TEST_FILE);
|
|
216
|
+
fireEvent.drop(droppableElement!, { dataTransfer });
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
await waitForUpload();
|
|
220
|
+
|
|
221
|
+
fireEvent.click(await screen.findByText(/Try again/i));
|
|
222
|
+
|
|
223
|
+
expect(props.onStart).toHaveBeenCalled();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
test('should call onSuccess with the server response when httpOptions are provided', async () => {
|
|
227
|
+
(asyncFileRead as jest.Mock).mockResolvedValue('mockBase64Image');
|
|
228
|
+
(postData as jest.Mock).mockResolvedValue('mockServerResponse');
|
|
229
|
+
|
|
230
|
+
const { container } = render(<Upload {...props} httpOptions={{ url: 'test-url' }} />);
|
|
231
|
+
const droppableElement = await waitFor(() => container.querySelector('.droppable-area'));
|
|
232
|
+
|
|
233
|
+
const dataTransfer = new DataTransfer();
|
|
234
|
+
dataTransfer.items.add(TEST_FILE);
|
|
235
|
+
|
|
236
|
+
await act(async () => {
|
|
237
|
+
fireEvent.drop(droppableElement!, { dataTransfer });
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
await waitForUpload();
|
|
241
|
+
|
|
242
|
+
expect(props.onSuccess).toHaveBeenCalledWith('mockServerResponse', TEST_FILE.name);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
test('should not allow new file to process while current one is in progress', async () => {
|
|
246
|
+
(asyncFileRead as jest.Mock).mockResolvedValue('someResult');
|
|
247
|
+
|
|
248
|
+
const { container } = render(<Upload {...props} httpOptions={{ url: 'test-url' }} />);
|
|
249
|
+
const droppableElement = await waitFor(() => container.querySelector('.droppable-area'));
|
|
250
|
+
|
|
251
|
+
const dataTransfer = new DataTransfer();
|
|
252
|
+
dataTransfer.items.add(TEST_FILE);
|
|
253
|
+
|
|
254
|
+
await act(async () => {
|
|
255
|
+
fireEvent.drop(droppableElement!, { dataTransfer });
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
const secondFileDataTransfer = new DataTransfer();
|
|
259
|
+
secondFileDataTransfer.items.add(TEST_FILE);
|
|
260
|
+
|
|
261
|
+
let dropResult = true;
|
|
262
|
+
await act(async () => {
|
|
263
|
+
try {
|
|
264
|
+
fireEvent.drop(droppableElement!, { dataTransfer: secondFileDataTransfer });
|
|
265
|
+
} catch {
|
|
266
|
+
dropResult = false;
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
expect(dropResult).toBe(true);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test('should override the error icon label when errorIconLabel prop is provided', async () => {
|
|
274
|
+
(asyncFileRead as jest.Mock).mockRejectedValueOnce('mockReadError');
|
|
275
|
+
(postData as jest.Mock).mockRejectedValueOnce(new Error('mockPostError'));
|
|
276
|
+
|
|
277
|
+
const customLabel = 'Custom error label';
|
|
278
|
+
const { container } = render(<Upload {...props} errorIconLabel={customLabel} />);
|
|
279
|
+
const droppableElement = await waitFor(() => container.querySelector('.droppable-area'));
|
|
280
|
+
|
|
281
|
+
const dataTransfer = new DataTransfer();
|
|
282
|
+
dataTransfer.items.add(TEST_FILE);
|
|
283
|
+
|
|
284
|
+
await act(async () => {
|
|
285
|
+
fireEvent.drop(droppableElement!, { dataTransfer });
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
await waitForUpload();
|
|
289
|
+
|
|
290
|
+
const errorIcon = await screen.findByLabelText(/Custom error label/i);
|
|
291
|
+
expect(errorIcon).toBeInTheDocument();
|
|
292
|
+
});
|
|
293
|
+
});
|
package/src/upload/Upload.tsx
CHANGED
|
@@ -172,7 +172,11 @@ export class Upload extends Component<UploadProps, UploadState> {
|
|
|
172
172
|
isProcessing: false,
|
|
173
173
|
isComplete: true,
|
|
174
174
|
},
|
|
175
|
-
onSuccess
|
|
175
|
+
onSuccess
|
|
176
|
+
? () => {
|
|
177
|
+
onSuccess(response as string | Response, fileName);
|
|
178
|
+
}
|
|
179
|
+
: undefined,
|
|
176
180
|
);
|
|
177
181
|
}, animationDelay);
|
|
178
182
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { render, fireEvent, waitFor, screen } from '../../../test-utils';
|
|
2
|
+
|
|
3
|
+
import CompleteStep from '.';
|
|
4
|
+
|
|
5
|
+
describe('CompleteStep', () => {
|
|
6
|
+
const COMPLETED_STEP_PROPS = {
|
|
7
|
+
isComplete: true,
|
|
8
|
+
uploadedImage: '',
|
|
9
|
+
fileName: 'fileName',
|
|
10
|
+
isError: false,
|
|
11
|
+
isImage: true,
|
|
12
|
+
csSuccessText: 'csSuccessText',
|
|
13
|
+
csFailureText: 'csFailureText',
|
|
14
|
+
csButtonText: 'csButtonText',
|
|
15
|
+
onClear: jest.fn(),
|
|
16
|
+
usLabel: 'usLabel',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
let container: HTMLElement;
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
const view = render(<CompleteStep {...COMPLETED_STEP_PROPS} />);
|
|
23
|
+
container = view.container;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('renders container', async () => {
|
|
27
|
+
await waitFor(() => {
|
|
28
|
+
const complete = container.querySelector('.droppable-complete-card');
|
|
29
|
+
expect(complete).toBeInTheDocument();
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('when error is false', () => {
|
|
34
|
+
test('renders isImage or Upload icon', () => {
|
|
35
|
+
expect(screen.getByTestId('document-icon')).toBeInTheDocument();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('renders filename when error is false', () => {
|
|
39
|
+
expect(screen.getByText(COMPLETED_STEP_PROPS.fileName)).toBeInTheDocument();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('renders button when csButtonText is set up', () => {
|
|
44
|
+
expect(screen.getByText(COMPLETED_STEP_PROPS.csButtonText)).toBeInTheDocument();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('calls onClear when button is clicked', () => {
|
|
48
|
+
fireEvent.click(screen.getByText(COMPLETED_STEP_PROPS.csButtonText));
|
|
49
|
+
expect(COMPLETED_STEP_PROPS.onClear).toHaveBeenCalledTimes(1);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { render, fireEvent, waitFor, screen } from '../../../test-utils';
|
|
2
|
+
|
|
3
|
+
import ProcessingStep from '.';
|
|
4
|
+
|
|
5
|
+
describe('ProcessingStep', () => {
|
|
6
|
+
const PROCESSING_STEP_PROPS = {
|
|
7
|
+
isComplete: false,
|
|
8
|
+
isError: false,
|
|
9
|
+
isSuccess: false,
|
|
10
|
+
onAnimationCompleted: jest.fn(),
|
|
11
|
+
onClear: jest.fn(),
|
|
12
|
+
psButtonText: 'psButtonText',
|
|
13
|
+
psProcessingText: 'psProcessingText',
|
|
14
|
+
psButtonDisabled: false,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
let container: HTMLElement;
|
|
18
|
+
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
const view = render(<ProcessingStep {...PROCESSING_STEP_PROPS} />);
|
|
21
|
+
container = view.container;
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('renders container', async () => {
|
|
25
|
+
await waitFor(() => {
|
|
26
|
+
const processing = container.querySelector('.droppable-processing-card');
|
|
27
|
+
expect(processing).toBeInTheDocument();
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('renders ProcessIndicator with default status', () => {
|
|
32
|
+
expect(screen.getByText(PROCESSING_STEP_PROPS.psProcessingText)).toBeInTheDocument();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('renders ProcessIndicator with success status', async () => {
|
|
36
|
+
const { container } = render(<ProcessingStep {...PROCESSING_STEP_PROPS} isSuccess />);
|
|
37
|
+
await waitFor(() => {
|
|
38
|
+
const processIndicator = container.querySelector('.process-success');
|
|
39
|
+
expect(processIndicator).toBeInTheDocument();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('renders ProcessIndicator with error status', async () => {
|
|
44
|
+
const { container } = render(<ProcessingStep {...PROCESSING_STEP_PROPS} isError />);
|
|
45
|
+
await waitFor(() => {
|
|
46
|
+
const processIndicator = container.querySelector('.process-danger');
|
|
47
|
+
expect(processIndicator).toBeInTheDocument();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('renders button when psButtonText is set up', () => {
|
|
52
|
+
expect(screen.getByText(PROCESSING_STEP_PROPS.psButtonText)).toBeInTheDocument();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('calls onClear when button is clicked', () => {
|
|
56
|
+
fireEvent.click(screen.getByText(PROCESSING_STEP_PROPS.psButtonText));
|
|
57
|
+
expect(PROCESSING_STEP_PROPS.onClear).toHaveBeenCalledTimes(1);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { render, screen } from '../../../test-utils';
|
|
2
|
+
|
|
3
|
+
import UploadImageStep from '.';
|
|
4
|
+
|
|
5
|
+
beforeAll(() => {
|
|
6
|
+
Object.defineProperty(window, 'matchMedia', {
|
|
7
|
+
writable: true,
|
|
8
|
+
value: jest.fn().mockImplementation((query: string) => ({
|
|
9
|
+
matches: false,
|
|
10
|
+
media: query,
|
|
11
|
+
onchange: null,
|
|
12
|
+
addListener: jest.fn(),
|
|
13
|
+
removeListener: jest.fn(),
|
|
14
|
+
addEventListener: jest.fn(),
|
|
15
|
+
removeEventListener: jest.fn(),
|
|
16
|
+
dispatchEvent: jest.fn(),
|
|
17
|
+
})),
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('uploadImageStep', () => {
|
|
22
|
+
const UPLOADIMAGE_STEP_PROPS = {
|
|
23
|
+
fileDropped: jest.fn(),
|
|
24
|
+
isComplete: false,
|
|
25
|
+
usAccept: 'image/*',
|
|
26
|
+
usButtonText: 'Upload Image',
|
|
27
|
+
usDisabled: false,
|
|
28
|
+
usLabel: 'Upload your image',
|
|
29
|
+
usHelpImage: 'https://example.com/help-image.png',
|
|
30
|
+
usPlaceholder: 'Drag and drop an image or click to upload',
|
|
31
|
+
errorMessage: '',
|
|
32
|
+
errorIconLabel: '',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
let container: HTMLElement;
|
|
36
|
+
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
const view = render(<UploadImageStep {...UPLOADIMAGE_STEP_PROPS} />);
|
|
39
|
+
container = view.container;
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('renders container', () => {
|
|
43
|
+
const processing = container.querySelector('.droppable-default-card');
|
|
44
|
+
expect(processing).toBeInTheDocument();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('renders helpImage or Upload icon', () => {
|
|
48
|
+
const uploadIcons = screen.getAllByAltText('Upload your image');
|
|
49
|
+
expect(uploadIcons.length).toBeGreaterThan(0);
|
|
50
|
+
expect(uploadIcons[0]).toBeInTheDocument();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('renders label', () => {
|
|
54
|
+
expect(screen.getByText(UPLOADIMAGE_STEP_PROPS.usLabel)).toBeInTheDocument();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('renders placeholder', () => {
|
|
58
|
+
expect(screen.getByText(UPLOADIMAGE_STEP_PROPS.usPlaceholder)).toBeInTheDocument();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('renders buttonText', () => {
|
|
62
|
+
expect(screen.getByText(UPLOADIMAGE_STEP_PROPS.usButtonText)).toBeInTheDocument();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test('should render with `errorIconLabel` and `errorMessage` override', () => {
|
|
66
|
+
const errorIconLabel = 'Error icon label';
|
|
67
|
+
const errorMessage = 'Maximum filesize is 2MB.';
|
|
68
|
+
const { container } = render(
|
|
69
|
+
<UploadImageStep
|
|
70
|
+
{...UPLOADIMAGE_STEP_PROPS}
|
|
71
|
+
errorMessage={errorMessage}
|
|
72
|
+
errorIconLabel={errorIconLabel}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
expect(screen.getByLabelText(errorIconLabel)).toBeInTheDocument();
|
|
77
|
+
expect(screen.getByText(errorMessage)).toBeInTheDocument();
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { shallow } from 'enzyme';
|
|
2
|
-
|
|
3
|
-
import Upload from '.';
|
|
4
|
-
|
|
5
|
-
const defaultLocale = 'en-GB';
|
|
6
|
-
jest.mock('react-intl', () => ({
|
|
7
|
-
injectIntl: (Component) =>
|
|
8
|
-
function (props) {
|
|
9
|
-
return (
|
|
10
|
-
<Component {...props} intl={{ locale: defaultLocale, formatMessage: (id) => `${id}` }} />
|
|
11
|
-
);
|
|
12
|
-
},
|
|
13
|
-
defineMessages: (translations) => translations,
|
|
14
|
-
}));
|
|
15
|
-
|
|
16
|
-
describe('Upload (events)', () => {
|
|
17
|
-
let component;
|
|
18
|
-
const props = {
|
|
19
|
-
onCancel: jest.fn(),
|
|
20
|
-
onChange: jest.fn(),
|
|
21
|
-
onFailure: jest.fn(),
|
|
22
|
-
onStart: jest.fn(),
|
|
23
|
-
onSuccess: jest.fn(),
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
describe('on shallow', () => {
|
|
27
|
-
beforeEach(() => {
|
|
28
|
-
component = shallow(<Upload {...props} />).dive();
|
|
29
|
-
jest.restoreAllMocks();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('increments dragCounter on dragenter', () => {
|
|
33
|
-
component.find('.droppable').simulate('dragenter', new Event('event'));
|
|
34
|
-
expect(component.instance().dragCounter).toBe(1);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('decrements dragCounter on dragleave', () => {
|
|
38
|
-
component.find('.droppable').simulate('dragleave', new Event('event'));
|
|
39
|
-
expect(component.instance().dragCounter).toBe(-1);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('reset dragCounter on drop', () => {
|
|
43
|
-
component.find('.droppable').simulate('dragenter', new Event('event'));
|
|
44
|
-
expect(component.instance().dragCounter).toBe(1);
|
|
45
|
-
component.find('.droppable').simulate('drop', new Event('event'));
|
|
46
|
-
expect(component.instance().dragCounter).toBe(0);
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
});
|