Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit d5af324

Browse files
author
Kerry Archibald
committed
test ExportDialog with settings
Signed-off-by: Kerry Archibald <[email protected]>
1 parent 2bd036a commit d5af324

File tree

5 files changed

+233
-37
lines changed

5 files changed

+233
-37
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@
191191
"stylelint": "^13.9.0",
192192
"stylelint-config-standard": "^20.0.0",
193193
"stylelint-scss": "^3.18.0",
194+
"ts-jest": "^27.1.3",
194195
"typescript": "4.5.3",
195196
"walk": "^2.3.14"
196197
},

src/components/views/dialogs/ExportDialog.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,11 @@ const validateNumberInRange = (min: number, max: number) => (value?: string | nu
5757
};
5858

5959
// Sanitize setting values, exclude invalid or missing values
60-
export const getSafeForceRoomExportSettings = (): {
60+
export type ForceRoomExportSettings = {
6161
format?: ExportFormat; range?: ExportType; numberOfMessages?: number; includeAttachments?: boolean; sizeMb?: number;
62-
} => {
63-
const config = SettingsStore.getValue(UIFeature.ForceRoomExportSettings);
62+
};
63+
export const getSafeForceRoomExportSettings = (): ForceRoomExportSettings => {
64+
const config = SettingsStore.getValue<ForceRoomExportSettings>(UIFeature.ForceRoomExportSettings);
6465
if (!config || typeof config !== "object") return {};
6566

6667
const { format, range, numberOfMessages, includeAttachments, sizeMb } = config;
@@ -87,6 +88,7 @@ interface ExportConfig {
8788
setNumberOfMessages?: Dispatch<SetStateAction<number>>;
8889
setSizeLimit?: Dispatch<SetStateAction<number>>;
8990
}
91+
9092
/**
9193
* Set up form state using UIFeature.ForceRoomExportSettings or defaults
9294
* Form fields configured in ForceRoomExportSettings are not allowed to be edited

test/components/views/dialogs/ExportDialog-test.tsx

Lines changed: 140 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,40 @@ limitations under the License.
1616

1717
import React from 'react';
1818
import { mount } from 'enzyme';
19+
import { mocked } from 'ts-jest/utils';
1920
import '../../../skinned-sdk';
2021
import { act } from "react-dom/test-utils";
2122
import { Room } from 'matrix-js-sdk';
2223

23-
import ExportDialog from '../../../../src/components/views/dialogs/ExportDialog';
24+
import ExportDialog,
25+
{ getSafeForceRoomExportSettings, ForceRoomExportSettings }
26+
from '../../../../src/components/views/dialogs/ExportDialog';
2427
import { ExportType, ExportFormat } from '../../../../src/utils/exportUtils/exportUtils';
2528
import { createTestClient, mkStubRoom } from '../../../test-utils';
2629
import { MatrixClientPeg } from '../../../../src/MatrixClientPeg';
2730
import HTMLExporter from "../../../../src/utils/exportUtils/HtmlExport";
31+
import SettingsStore from '../../../../src/settings/SettingsStore';
32+
import PlainTextExporter from '../../../../src/utils/exportUtils/PlainTextExport';
2833

2934
jest.useFakeTimers();
3035

31-
const mockHtmlExporter = ({
36+
const htmlExporterInstance = ({
37+
export: jest.fn().mockResolvedValue({}),
38+
});
39+
const plainTextExporterInstance = ({
3240
export: jest.fn().mockResolvedValue({}),
3341
});
3442
jest.mock("../../../../src/utils/exportUtils/HtmlExport", () => jest.fn());
43+
jest.mock("../../../../src/utils/exportUtils/PlainTextExport", () => jest.fn());
44+
45+
jest.mock('../../../../src/settings/SettingsStore', () => ({
46+
monitorSetting: jest.fn(),
47+
getValue: jest.fn(),
48+
}));
49+
50+
const SettingsStoreMock = mocked(SettingsStore);
51+
const HTMLExporterMock = mocked(HTMLExporter);
52+
const PlainTextExporterMock = mocked(PlainTextExporter);
3553

3654
describe('<ExportDialog />', () => {
3755
const mockClient = createTestClient();
@@ -81,8 +99,13 @@ describe('<ExportDialog />', () => {
8199
});
82100

83101
beforeEach(() => {
84-
(HTMLExporter as jest.Mock).mockImplementation(jest.fn().mockReturnValue(mockHtmlExporter));
85-
mockHtmlExporter.export.mockClear();
102+
HTMLExporterMock.mockClear().mockImplementation(jest.fn().mockReturnValue(htmlExporterInstance));
103+
PlainTextExporterMock.mockClear().mockImplementation(jest.fn().mockReturnValue(plainTextExporterInstance));
104+
htmlExporterInstance.export.mockClear();
105+
plainTextExporterInstance.export.mockClear();
106+
107+
// default setting value
108+
SettingsStoreMock.getValue.mockClear().mockReturnValue({});
86109
});
87110

88111
it('renders export dialog', () => {
@@ -104,7 +127,7 @@ describe('<ExportDialog />', () => {
104127
await submitForm(component);
105128

106129
// 4th arg is an component function
107-
const exportConstructorProps = (HTMLExporter as jest.Mock).mock.calls[0].slice(0, 3);
130+
const exportConstructorProps = HTMLExporterMock.mock.calls[0].slice(0, 3);
108131
expect(exportConstructorProps).toEqual([
109132
defaultProps.room,
110133
ExportType.Timeline,
@@ -114,7 +137,32 @@ describe('<ExportDialog />', () => {
114137
numberOfMessages: 100,
115138
},
116139
]);
117-
expect(mockHtmlExporter.export).toHaveBeenCalled();
140+
expect(htmlExporterInstance.export).toHaveBeenCalled();
141+
});
142+
143+
it('exports room using values set from ForceRoomExportSettings', async () => {
144+
SettingsStoreMock.getValue.mockReturnValue({
145+
format: ExportFormat.PlainText,
146+
range: ExportType.Beginning,
147+
sizeMb: 15000,
148+
numberOfMessages: 30,
149+
attachmentsIncluded: true,
150+
});
151+
const component = getComponent();
152+
await submitForm(component);
153+
154+
// 4th arg is an component function
155+
const exportConstructorProps = PlainTextExporterMock.mock.calls[0].slice(0, 3);
156+
expect(exportConstructorProps).toEqual([
157+
defaultProps.room,
158+
ExportType.Beginning,
159+
{
160+
attachmentsIncluded: false,
161+
maxSize: 15000 * 1024 * 1024,
162+
numberOfMessages: 30,
163+
},
164+
]);
165+
expect(plainTextExporterInstance.export).toHaveBeenCalled();
118166
});
119167

120168
it('renders success screen when export is finished', async () => {
@@ -139,6 +187,19 @@ describe('<ExportDialog />', () => {
139187
expect(getExportFormatInput(component, ExportFormat.PlainText).props().checked).toBeTruthy();
140188
expect(getExportFormatInput(component, ExportFormat.Html).props().checked).toBeFalsy();
141189
});
190+
191+
it('hides export format input when format is valid in ForceRoomExportSettings', () => {
192+
const component = getComponent();
193+
expect(getExportFormatInput(component, ExportFormat.Html).props().checked).toBeTruthy();
194+
});
195+
196+
it('does not render export format when set in ForceRoomExportSettings', () => {
197+
SettingsStoreMock.getValue.mockReturnValue({
198+
format: ExportFormat.PlainText,
199+
});
200+
const component = getComponent();
201+
expect(getExportFormatInput(component, ExportFormat.Html).length).toBeFalsy();
202+
});
142203
});
143204

144205
describe('export type', () => {
@@ -153,6 +214,14 @@ describe('<ExportDialog />', () => {
153214
expect(getExportTypeInput(component).props().value).toEqual(ExportType.Beginning);
154215
});
155216

217+
it('does not render export type when set in ForceRoomExportSettings', () => {
218+
SettingsStoreMock.getValue.mockReturnValue({
219+
range: ExportType.Beginning,
220+
});
221+
const component = getComponent();
222+
expect(getExportTypeInput(component).length).toBeFalsy();
223+
});
224+
156225
it('does not render message count input', async () => {
157226
const component = getComponent();
158227
expect(getMessageCountInput(component).length).toBeFalsy();
@@ -177,7 +246,7 @@ describe('<ExportDialog />', () => {
177246
await setMessageCount(component, 0);
178247
await submitForm(component);
179248

180-
expect(mockHtmlExporter.export).not.toHaveBeenCalled();
249+
expect(htmlExporterInstance.export).not.toHaveBeenCalled();
181250
});
182251

183252
it('does not export when export type is lastNMessages and message count is more than max', async () => {
@@ -186,7 +255,7 @@ describe('<ExportDialog />', () => {
186255
await setMessageCount(component, 99999999999);
187256
await submitForm(component);
188257

189-
expect(mockHtmlExporter.export).not.toHaveBeenCalled();
258+
expect(htmlExporterInstance.export).not.toHaveBeenCalled();
190259
});
191260

192261
it('exports when export type is NOT lastNMessages and message count is falsy', async () => {
@@ -196,7 +265,7 @@ describe('<ExportDialog />', () => {
196265
await selectExportType(component, ExportType.Timeline);
197266
await submitForm(component);
198267

199-
expect(mockHtmlExporter.export).toHaveBeenCalled();
268+
expect(htmlExporterInstance.export).toHaveBeenCalled();
200269
});
201270
});
202271

@@ -217,27 +286,48 @@ describe('<ExportDialog />', () => {
217286
await setSizeLimit(component, 0);
218287
await submitForm(component);
219288

220-
expect(mockHtmlExporter.export).not.toHaveBeenCalled();
289+
expect(htmlExporterInstance.export).not.toHaveBeenCalled();
221290
});
222291

223292
it('does not export when size limit is larger than max', async () => {
224293
const component = getComponent();
225294
await setSizeLimit(component, 2001);
226295
await submitForm(component);
227296

228-
expect(mockHtmlExporter.export).not.toHaveBeenCalled();
297+
expect(htmlExporterInstance.export).not.toHaveBeenCalled();
229298
});
230299

231300
it('exports when size limit is max', async () => {
232301
const component = getComponent();
233302
await setSizeLimit(component, 2000);
234303
await submitForm(component);
235304

236-
expect(mockHtmlExporter.export).toHaveBeenCalled();
305+
expect(htmlExporterInstance.export).toHaveBeenCalled();
306+
});
307+
308+
it('does not render size limit input when set in ForceRoomExportSettings', () => {
309+
SettingsStoreMock.getValue.mockReturnValue({
310+
sizeMb: 10000,
311+
});
312+
const component = getComponent();
313+
expect(getSizeInput(component).length).toBeFalsy();
314+
});
315+
316+
/**
317+
* 2000mb size limit does not apply when higher limit is configured in config
318+
*/
319+
it('exports when size limit set in ForceRoomExportSettings is larger than 2000', async () => {
320+
SettingsStoreMock.getValue.mockReturnValue({
321+
sizeMb: 10000,
322+
});
323+
const component = getComponent();
324+
await submitForm(component);
325+
326+
expect(htmlExporterInstance.export).toHaveBeenCalled();
237327
});
238328
});
239329

240-
describe('include attachements', () => {
330+
describe('include attachments', () => {
241331
it('renders input with default value of false', () => {
242332
const component = getComponent();
243333
expect(getAttachmentsCheckbox(component).props().checked).toEqual(false);
@@ -248,6 +338,43 @@ describe('<ExportDialog />', () => {
248338
await setIncludeAttachments(component, true);
249339
expect(getAttachmentsCheckbox(component).props().checked).toEqual(true);
250340
});
341+
342+
it('does not render input when set in ForceRoomExportSettings', () => {
343+
SettingsStoreMock.getValue.mockReturnValue({
344+
includeAttachments: false,
345+
});
346+
const component = getComponent();
347+
expect(getAttachmentsCheckbox(component).length).toBeFalsy();
348+
});
349+
});
350+
351+
describe('getSafeForceRoomExportSettings()', () => {
352+
const testCases: [string, ForceRoomExportSettings, ForceRoomExportSettings][] = [
353+
['setting is falsy', undefined, {}],
354+
['setting is configured to string', 'test' as unknown, {}],
355+
['setting is empty', {}, {}],
356+
['format is not a valid ExportFormat', { format: 'mp3' }, {}],
357+
['format is a valid ExportFormat', { format: ExportFormat.Html }, { format: ExportFormat.Html }],
358+
['range is not a valid ExportType', { range: 'yesterday' }, {}],
359+
['range is a valid ExportType', { range: ExportType.LastNMessages }, { range: ExportType.LastNMessages }],
360+
['numberOfMessages is not a number', { numberOfMessages: 'test' }, {}],
361+
['numberOfMessages is less than 1', { numberOfMessages: -1 }, {}],
362+
['numberOfMessages is more than 100000000', { numberOfMessages: 9999999999 }, {}],
363+
['numberOfMessages is valid', { numberOfMessages: 2000 }, { numberOfMessages: 2000 }],
364+
['sizeMb is not a number', { sizeMb: 'test' }, {}],
365+
['sizeMb is less than 1', { sizeMb: -1 }, {}],
366+
['sizeMb is more than 1024000', { sizeMb: Number.MAX_SAFE_INTEGER }, {}],
367+
['sizeMb is valid', { sizeMb: 50000 }, { sizeMb: 50000 }],
368+
['includeAttachments is not a boolean', { includeAttachments: 'yes' }, {}],
369+
['includeAttachments is true', { includeAttachments: true }, { includeAttachments: true }],
370+
['includeAttachments is false', { includeAttachments: false }, { includeAttachments: false }],
371+
];
372+
373+
it.each(testCases)('sanitizes correctly when %s', (_d, setting, expected) => {
374+
SettingsStoreMock.getValue.mockReturnValue(setting);
375+
376+
expect(getSafeForceRoomExportSettings()).toEqual(expected);
377+
});
251378
});
252379
});
253380

test/utils/export-test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ describe('export', function() {
194194
).toBeTruthy();
195195
});
196196

197-
const testCases: [string, IExportOptions][] = [
197+
const invalidExportOptions: [string, IExportOptions][] = [
198198
['numberOfMessages exceeds max', {
199199
numberOfMessages: 10 ** 9,
200200
maxSize: 1024 * 1024 * 1024,
@@ -211,7 +211,7 @@ describe('export', function() {
211211
attachmentsIncluded: false,
212212
}],
213213
];
214-
it.each(testCases)('%s', (_d, options) => {
214+
it.each(invalidExportOptions)('%s', (_d, options) => {
215215
expect(
216216
() =>
217217
new PlainTextExporter(mockRoom, ExportType.Beginning, options, null),

0 commit comments

Comments
 (0)