joplin-plugin-backup 1.2.1 → 1.3.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.
@@ -1,992 +0,0 @@
1
- import { Backup } from "../src/Backup";
2
- import * as fs from "fs-extra";
3
- import * as path from "path";
4
- import { when } from "jest-when";
5
- import { sevenZip } from "../src/sevenZip";
6
- import joplin from "api";
7
-
8
- function getTestPaths(): any {
9
- const testPath: any = {};
10
- testPath.base = path.join(__dirname, "tests");
11
- testPath.backupBasePath = path.join(testPath.base, "Backup");
12
- testPath.activeBackupJob = path.join(
13
- testPath.backupBasePath,
14
- "activeBackupJob"
15
- );
16
- testPath.joplinProfile = path.join(testPath.base, "joplin-desktop");
17
- testPath.templates = path.join(testPath.joplinProfile, "templates");
18
- testPath.plugins = path.join(testPath.joplinProfile, "plugins");
19
- return testPath;
20
- }
21
-
22
- let backup = null;
23
-
24
- let spyOnLogVerbose = null;
25
- let spyOnLogInfo = null;
26
- let spyOnLogWarn = null;
27
- let spyOnLogError = null;
28
- let spyOnShowError = null;
29
- let spyOnSaveBackupInfo = null;
30
-
31
- const spyOnsSettingsValue = jest.spyOn(joplin.settings, "value");
32
- const spyOnGlobalValue = jest.spyOn(joplin.settings, "globalValue");
33
- const spyOnSettingsSetValue = jest
34
- .spyOn(joplin.settings, "setValue")
35
- .mockImplementation();
36
-
37
- async function createTestStructure() {
38
- const test = await getTestPaths();
39
- fs.emptyDirSync(test.base);
40
- fs.emptyDirSync(test.backupBasePath);
41
- fs.emptyDirSync(test.joplinProfile);
42
- fs.emptyDirSync(test.templates);
43
- fs.emptyDirSync(test.plugins);
44
- }
45
-
46
- const testPath = getTestPaths();
47
-
48
- describe("Backup", function () {
49
- beforeEach(async () => {
50
- /* prettier-ignore */
51
- when(spyOnsSettingsValue)
52
- .mockImplementation(() => Promise.resolve("no mockImplementation"))
53
- .calledWith("fileLogLevel").mockImplementation(() => Promise.resolve("error"))
54
- .calledWith("path").mockImplementation(() => Promise.resolve(testPath.backupBasePath));
55
-
56
- /* prettier-ignore */
57
- when(spyOnGlobalValue)
58
- .mockImplementation(() => Promise.resolve("no mockImplementation"))
59
- .calledWith("profileDir").mockImplementation(() => Promise.resolve(testPath.joplinProfile))
60
- .calledWith("templateDir").mockImplementation(() => Promise.resolve(testPath.templates));
61
-
62
- await createTestStructure();
63
- backup = new Backup() as any;
64
- backup.backupStartTime = new Date();
65
- backup.backupSetName = "{YYYYMMDDHHmm}";
66
-
67
- spyOnSaveBackupInfo = jest
68
- .spyOn(backup, "saveBackupInfo")
69
- .mockImplementation(() => {});
70
-
71
- spyOnLogVerbose = jest
72
- .spyOn(backup.log, "verbose")
73
- .mockImplementation(() => {});
74
- spyOnLogInfo = jest.spyOn(backup.log, "info").mockImplementation(() => {});
75
- spyOnLogWarn = jest.spyOn(backup.log, "warn").mockImplementation(() => {});
76
- spyOnLogError = jest
77
- .spyOn(backup.log, "error")
78
- .mockImplementation(() => {});
79
-
80
- spyOnShowError = jest
81
- .spyOn(backup, "showError")
82
- .mockImplementation(() => {});
83
- });
84
-
85
- afterEach(async () => {
86
- spyOnLogVerbose.mockReset();
87
- spyOnLogInfo.mockReset();
88
- spyOnLogWarn.mockReset();
89
- spyOnLogError.mockReset();
90
- spyOnShowError.mockReset();
91
- spyOnsSettingsValue.mockReset();
92
- spyOnGlobalValue.mockReset();
93
- spyOnSaveBackupInfo.mockReset();
94
- });
95
-
96
- afterAll(async () => {
97
- fs.removeSync(testPath.base);
98
- });
99
- describe("Backup path", function () {
100
- it(`Path tests`, async () => {
101
- const testCases = [
102
- {
103
- backupPath: testPath.joplinProfile,
104
- createSubfolder: false,
105
- expectedBackupPath: null,
106
- expectedBackupPathExist: null,
107
- },
108
- {
109
- backupPath: testPath.joplinProfile,
110
- createSubfolder: true,
111
- expectedBackupPath: path.join(testPath.joplinProfile, "JoplinBackup"),
112
- expectedBackupPathExist: true,
113
- },
114
- {
115
- backupPath: testPath.backupBasePath,
116
- createSubfolder: false,
117
- expectedBackupPath: testPath.backupBasePath,
118
- expectedBackupPathExist: true,
119
- },
120
- {
121
- backupPath: testPath.backupBasePath,
122
- createSubfolder: true,
123
- expectedBackupPath: path.join(
124
- testPath.backupBasePath,
125
- "JoplinBackup"
126
- ),
127
- expectedBackupPathExist: true,
128
- },
129
- {
130
- backupPath: path.join(testPath.backupBasePath, "NotExisting"),
131
- createSubfolder: false,
132
- expectedBackupPath: path.join(testPath.backupBasePath, "NotExisting"),
133
- expectedBackupPathExist: false,
134
- },
135
- {
136
- backupPath: path.join(testPath.backupBasePath, "NotExisting"),
137
- createSubfolder: true,
138
- expectedBackupPath: path.join(
139
- testPath.backupBasePath,
140
- "NotExisting",
141
- "JoplinBackup"
142
- ),
143
- expectedBackupPathExist: false,
144
- },
145
- ];
146
-
147
- for (const testCase of testCases) {
148
- when(spyOnsSettingsValue)
149
- .calledWith("path")
150
- .mockImplementation(() => Promise.resolve(testCase.backupPath));
151
- backup.createSubfolder = testCase.createSubfolder;
152
- await backup.loadBackupPath();
153
- expect(backup.backupBasePath).toBe(testCase.expectedBackupPath);
154
- expect(backup.backupBasePath).not.toBe(testPath.joplinProfile);
155
-
156
- if (testCase.expectedBackupPathExist !== null) {
157
- expect(fs.existsSync(backup.backupBasePath)).toBe(
158
- testCase.expectedBackupPathExist
159
- );
160
- }
161
-
162
- expect(backup.log.error).toHaveBeenCalledTimes(0);
163
- expect(backup.log.warn).toHaveBeenCalledTimes(0);
164
- }
165
- });
166
-
167
- it(`relative paths`, async () => {
168
- const backupPath = "../";
169
- /* prettier-ignore */
170
- when(spyOnsSettingsValue)
171
- .calledWith("path").mockImplementation(() => Promise.resolve(backupPath));
172
- await backup.loadBackupPath();
173
- const toBe = path.normalize(
174
- path.join(testPath.backupBasePath, backupPath)
175
- );
176
- expect(backup.backupBasePath).toBe(toBe);
177
- expect(backup.log.error).toHaveBeenCalledTimes(0);
178
- expect(backup.log.warn).toHaveBeenCalledTimes(0);
179
- });
180
- });
181
-
182
- describe("Div", function () {
183
- it(`Create empty folder`, async () => {
184
- const folder = await backup.createEmptyFolder(
185
- testPath.backupBasePath,
186
- "profile"
187
- );
188
- const check = path.join(testPath.backupBasePath, "profile");
189
- expect(folder).toBe(check);
190
- expect(fs.existsSync(check)).toBe(true);
191
- expect(backup.log.error).toHaveBeenCalledTimes(0);
192
- expect(backup.log.warn).toHaveBeenCalledTimes(0);
193
- });
194
-
195
- it(`Delete log`, async () => {
196
- backup.logFile = path.join(testPath.backupBasePath, "test.log");
197
- fs.writeFileSync(backup.logFile, "data");
198
-
199
- expect(fs.existsSync(backup.logFile)).toBe(true);
200
- await backup.deleteLogFile();
201
- expect(fs.existsSync(backup.logFile)).toBe(false);
202
- expect(backup.log.error).toHaveBeenCalledTimes(0);
203
- expect(backup.log.warn).toHaveBeenCalledTimes(0);
204
- });
205
- });
206
-
207
- describe("moveFinishedBackup", function () {
208
- it(`no retention`, async () => {
209
- const emptyFolder = path.join(testPath.activeBackupJob, "emptyFolder");
210
- const emptyFolderCheck = path.join(
211
- testPath.backupBasePath,
212
- "emptyFolder"
213
- );
214
- const folder = path.join(testPath.activeBackupJob, "folder");
215
- const folderCheck = path.join(testPath.backupBasePath, "folder");
216
- const file1 = path.join(folder, "file.txt");
217
- const file1Check = path.join(folderCheck, "file.txt");
218
- const file2 = path.join(testPath.activeBackupJob, "file.txt");
219
- const file2Check = path.join(testPath.backupBasePath, "file.txt");
220
- backup.backupBasePath = testPath.backupBasePath;
221
- backup.activeBackupPath = testPath.activeBackupJob;
222
-
223
- fs.emptyDirSync(testPath.activeBackupJob);
224
- fs.emptyDirSync(emptyFolder);
225
- fs.emptyDirSync(folder);
226
- fs.writeFileSync(file1, "file");
227
- fs.writeFileSync(file2, "file");
228
-
229
- backup.backupRetention = 1;
230
-
231
- expect(await backup.moveFinishedBackup()).toBe(testPath.backupBasePath);
232
- expect(fs.existsSync(folderCheck)).toBe(true);
233
- expect(fs.existsSync(emptyFolderCheck)).toBe(true);
234
- expect(fs.existsSync(file1Check)).toBe(true);
235
- expect(fs.existsSync(file2Check)).toBe(true);
236
- expect(backup.log.error).toHaveBeenCalledTimes(0);
237
- expect(backup.log.warn).toHaveBeenCalledTimes(0);
238
- });
239
-
240
- it(`retention > 1`, async () => {
241
- const backupDst = path.join(testPath.backupBasePath, "202101021630");
242
- const testEpoch = new Date(2021, 0, 2, 16, 30, 45, 0).getTime();
243
- const spyOnDateNow = jest
244
- .spyOn(Date, "now")
245
- .mockImplementation(() => testEpoch);
246
-
247
- const emptyFolder = path.join(testPath.activeBackupJob, "emptyFolder");
248
- const emptyFolderCheck = path.join(backupDst, "emptyFolder");
249
- const folder = path.join(testPath.activeBackupJob, "folder");
250
- const folderCheck = path.join(backupDst, "folder");
251
- const file1 = path.join(folder, "file.txt");
252
- const file1Check = path.join(folderCheck, "file.txt");
253
- const file2 = path.join(testPath.activeBackupJob, "file.txt");
254
- const file2Check = path.join(backupDst, "file.txt");
255
- backup.backupBasePath = testPath.backupBasePath;
256
- backup.activeBackupPath = testPath.activeBackupJob;
257
-
258
- fs.emptyDirSync(testPath.activeBackupJob);
259
- fs.emptyDirSync(emptyFolder);
260
- fs.emptyDirSync(folder);
261
- fs.writeFileSync(file1, "file");
262
- fs.writeFileSync(file2, "file");
263
-
264
- backup.backupRetention = 2;
265
-
266
- expect(await backup.moveFinishedBackup()).toBe(backupDst);
267
- expect(fs.existsSync(folderCheck)).toBe(true);
268
- expect(fs.existsSync(emptyFolderCheck)).toBe(true);
269
- expect(fs.existsSync(file1Check)).toBe(true);
270
- expect(fs.existsSync(file2Check)).toBe(true);
271
- expect(backup.log.error).toHaveBeenCalledTimes(0);
272
- expect(backup.log.warn).toHaveBeenCalledTimes(0);
273
-
274
- spyOnDateNow.mockRestore();
275
- });
276
-
277
- it(`retention > 1, folder exist`, async () => {
278
- backup.backupBasePath = testPath.backupBasePath;
279
- backup.activeBackupPath = testPath.activeBackupJob;
280
- backup.backupSetName = "JoplinBackupSet";
281
- backup.backupRetention = 2;
282
-
283
- const expected = path.join(
284
- testPath.backupBasePath,
285
- backup.backupSetName + " (1)"
286
- );
287
-
288
- fs.emptyDirSync(testPath.activeBackupJob);
289
- const existingBackupSet = path.join(
290
- testPath.backupBasePath,
291
- backup.backupSetName
292
- );
293
- fs.emptyDirSync(existingBackupSet);
294
- expect(fs.existsSync(existingBackupSet)).toBe(true);
295
-
296
- expect(fs.existsSync(expected)).toBe(false);
297
- expect(await backup.moveFinishedBackup()).toBe(expected);
298
- expect(fs.existsSync(expected)).toBe(true);
299
- });
300
-
301
- it(`retention = 1, folder exist with same files and folder`, async () => {
302
- const emptyFolder = path.join(testPath.activeBackupJob, "emptyFolder");
303
- const emptyFolderCheck = path.join(
304
- testPath.backupBasePath,
305
- "emptyFolder"
306
- );
307
- const folderNotes = path.join(testPath.activeBackupJob, "notes");
308
- const folderNotesCheck = path.join(testPath.backupBasePath, "notes");
309
- const file1 = path.join(folderNotes, "file.txt");
310
- const file1Check = path.join(folderNotesCheck, "file.txt");
311
- const file2 = path.join(testPath.activeBackupJob, "file.txt");
312
- const file2Check = path.join(testPath.backupBasePath, "file.txt");
313
- const file3Check = path.join(testPath.backupBasePath, "fileStay.txt");
314
- const file4Check = path.join(folderNotesCheck, "fileNo.txt");
315
- backup.backupBasePath = testPath.backupBasePath;
316
- backup.activeBackupPath = testPath.activeBackupJob;
317
-
318
- fs.emptyDirSync(testPath.backupBasePath);
319
- fs.emptyDirSync(emptyFolderCheck);
320
- fs.emptyDirSync(folderNotesCheck);
321
- fs.writeFileSync(file1Check, "old file");
322
- fs.writeFileSync(file2Check, "old file");
323
- fs.writeFileSync(file3Check, "old file");
324
- fs.writeFileSync(file4Check, "old file");
325
-
326
- fs.emptyDirSync(testPath.activeBackupJob);
327
- fs.emptyDirSync(emptyFolder);
328
- fs.emptyDirSync(folderNotes);
329
- fs.writeFileSync(file1, "new file");
330
- fs.writeFileSync(file2, "new file");
331
-
332
- backup.backupRetention = 1;
333
-
334
- expect(await backup.moveFinishedBackup()).toBe(testPath.backupBasePath);
335
- expect(fs.existsSync(folderNotes)).toBe(false);
336
- expect(fs.existsSync(folderNotesCheck)).toBe(true);
337
- expect(fs.existsSync(emptyFolderCheck)).toBe(true);
338
- expect(fs.existsSync(file1Check)).toBe(true);
339
- expect(fs.existsSync(file2Check)).toBe(true);
340
- expect(fs.existsSync(file3Check)).toBe(true);
341
- expect(fs.existsSync(file4Check)).toBe(false);
342
- expect(backup.log.error).toHaveBeenCalledTimes(0);
343
- expect(backup.log.warn).toHaveBeenCalledTimes(0);
344
- });
345
-
346
- it(`retention > 1, file exist`, async () => {
347
- backup.backupBasePath = testPath.backupBasePath;
348
- backup.activeBackupPath = testPath.activeBackupJob;
349
- backup.backupSetName = "JoplinBackupSet";
350
- backup.backupRetention = 2;
351
-
352
- const zipFile = path.join(testPath.backupBasePath, "test.7z");
353
- fs.writeFileSync(zipFile, "backup set");
354
- expect(fs.existsSync(zipFile)).toBe(true);
355
-
356
- const expected = path.join(
357
- testPath.backupBasePath,
358
- backup.backupSetName + " (1).7z"
359
- );
360
-
361
- fs.emptyDirSync(testPath.activeBackupJob);
362
- const existingBackupSet = path.join(
363
- testPath.backupBasePath,
364
- backup.backupSetName + ".7z"
365
- );
366
- fs.writeFileSync(existingBackupSet, "backup set");
367
- expect(fs.existsSync(existingBackupSet)).toBe(true);
368
-
369
- expect(fs.existsSync(expected)).toBe(false);
370
- expect(await backup.moveFinishedBackup(zipFile)).toBe(expected);
371
- expect(fs.existsSync(expected)).toBe(true);
372
- });
373
- });
374
- describe("Backup set", function () {
375
- it(`Name`, async () => {
376
- const testEpoch = new Date(2021, 0, 2, 16, 30, 45, 0).getTime();
377
- /* prettier-ignore */
378
- const spyOnDateNow = jest.spyOn(Date, "now").mockImplementation(() => testEpoch);
379
-
380
- const testCases = [
381
- {
382
- backupSetName: "{YYYYMMDDHHmm}",
383
- expected: "202101021630",
384
- },
385
- {
386
- backupSetName: "{YYYY-MM-DD HH:mm}",
387
- expected: "2021-01-02 16:30",
388
- },
389
- {
390
- backupSetName: "Joplinbackup_{YYYYMMDDHHmm}",
391
- expected: "Joplinbackup_202101021630",
392
- },
393
- {
394
- backupSetName: "A {YYYY} b {MMDDHHmm}",
395
- expected: "A 2021 b 01021630",
396
- },
397
- {
398
- backupSetName: "j{j}j",
399
- expected: "jjj",
400
- },
401
- {
402
- backupSetName: "No var",
403
- expected: "No var",
404
- },
405
- ];
406
-
407
- for (const testCase of testCases) {
408
- backup.backupSetName = testCase.backupSetName;
409
- expect(await backup.getBackupSetFolderName()).toBe(testCase.expected);
410
- }
411
-
412
- spyOnDateNow.mockRestore();
413
- expect(backup.log.error).toHaveBeenCalledTimes(0);
414
- expect(backup.log.warn).toHaveBeenCalledTimes(0);
415
- });
416
-
417
- it(`Creation`, async () => {
418
- const testEpoch = new Date(2021, 0, 2, 16, 30, 45, 0);
419
- const spyOnDateNow = jest
420
- .spyOn(Date, "now")
421
- .mockImplementation(() => testEpoch.getTime());
422
-
423
- const testCases = [
424
- {
425
- zipArchive: "no",
426
- backupRetention: 1,
427
- password: null,
428
- singleJex: false,
429
- result: testPath.backupBasePath,
430
- testFile: "testFile.txt",
431
- checkFile: path.join(testPath.backupBasePath, "testFile.txt"),
432
- saveBackupInfoCalled: 0,
433
- },
434
- {
435
- zipArchive: "no",
436
- backupRetention: 1,
437
- password: "secret",
438
- singleJex: false,
439
- result: testPath.backupBasePath,
440
- testFile: "testFile.txt",
441
- checkFile: path.join(testPath.backupBasePath, "testFile.txt.7z"),
442
- saveBackupInfoCalled: 0,
443
- },
444
- {
445
- zipArchive: "no",
446
- backupRetention: 2,
447
- password: null,
448
- singleJex: false,
449
- result: path.join(testPath.backupBasePath, "202101021630"),
450
- testFile: "testFile.txt",
451
- checkFile: path.join(
452
- testPath.backupBasePath,
453
- "202101021630",
454
- "testFile.txt"
455
- ),
456
- saveBackupInfoCalled: 1,
457
- },
458
- {
459
- zipArchive: "yes",
460
- backupRetention: 1,
461
- password: null,
462
- singleJex: false,
463
- result: testPath.backupBasePath,
464
- testFile: "testFile.txt",
465
- checkFile: path.join(testPath.backupBasePath, "testFile.txt.7z"),
466
- saveBackupInfoCalled: 0,
467
- },
468
- {
469
- zipArchive: "yes",
470
- backupRetention: 2,
471
- password: null,
472
- singleJex: false,
473
- result: path.join(testPath.backupBasePath, "202101021630"),
474
- testFile: "testFile.txt",
475
- checkFile: path.join(
476
- testPath.backupBasePath,
477
- "202101021630",
478
- "testFile.txt.7z"
479
- ),
480
- saveBackupInfoCalled: 1,
481
- },
482
- {
483
- zipArchive: "yesone",
484
- backupRetention: 1,
485
- password: null,
486
- singleJex: false,
487
- result: path.join(testPath.backupBasePath, "JoplinBackup.7z"),
488
- testFile: "testFile.txt",
489
- checkFile: path.join(testPath.backupBasePath, "JoplinBackup.7z"),
490
- saveBackupInfoCalled: 0,
491
- },
492
- {
493
- zipArchive: "yesone",
494
- backupRetention: 2,
495
- password: null,
496
- singleJex: false,
497
- result: path.join(testPath.backupBasePath, "202101021630.7z"),
498
- testFile: "testFile.txt",
499
- checkFile: path.join(testPath.backupBasePath, "202101021630.7z"),
500
- saveBackupInfoCalled: 1,
501
- },
502
- {
503
- zipArchive: "no",
504
- backupRetention: 1,
505
- password: null,
506
- singleJex: true,
507
- result: testPath.backupBasePath,
508
- testFile: "testFile.txt",
509
- checkFile: path.join(testPath.backupBasePath, "testFile.txt"),
510
- saveBackupInfoCalled: 0,
511
- },
512
- {
513
- zipArchive: "no",
514
- backupRetention: 2,
515
- password: null,
516
- singleJex: true,
517
- result: path.join(testPath.backupBasePath, "202101021630"),
518
- testFile: "testFile.txt",
519
- checkFile: path.join(
520
- testPath.backupBasePath,
521
- "202101021630",
522
- "testFile.txt"
523
- ),
524
- saveBackupInfoCalled: 1,
525
- },
526
- {
527
- zipArchive: "yes",
528
- backupRetention: 1,
529
- password: null,
530
- singleJex: true,
531
- result: path.join(testPath.backupBasePath, "JoplinBackup.7z"),
532
- testFile: "testFile.txt",
533
- checkFile: path.join(testPath.backupBasePath, "JoplinBackup.7z"),
534
- saveBackupInfoCalled: 0,
535
- },
536
- {
537
- zipArchive: "yes",
538
- backupRetention: 2,
539
- password: null,
540
- singleJex: true,
541
- result: path.join(testPath.backupBasePath, "202101021630.7z"),
542
- testFile: "testFile.txt",
543
- checkFile: path.join(testPath.backupBasePath, "202101021630.7z"),
544
- saveBackupInfoCalled: 1,
545
- },
546
- {
547
- zipArchive: "yesone",
548
- backupRetention: 1,
549
- password: null,
550
- singleJex: true,
551
- result: path.join(testPath.backupBasePath, "JoplinBackup.7z"),
552
- testFile: "testFile.txt",
553
- checkFile: path.join(testPath.backupBasePath, "JoplinBackup.7z"),
554
- saveBackupInfoCalled: 0,
555
- },
556
- {
557
- zipArchive: "yesone",
558
- backupRetention: 1,
559
- password: "secret",
560
- singleJex: true,
561
- result: path.join(testPath.backupBasePath, "JoplinBackup.7z"),
562
- testFile: "testFile.txt",
563
- checkFile: path.join(testPath.backupBasePath, "JoplinBackup.7z"),
564
- saveBackupInfoCalled: 0,
565
- },
566
- {
567
- zipArchive: "yesone",
568
- backupRetention: 2,
569
- password: null,
570
- singleJex: true,
571
- result: path.join(testPath.backupBasePath, "202101021630.7z"),
572
- testFile: "testFile.txt",
573
- checkFile: path.join(testPath.backupBasePath, "202101021630.7z"),
574
- saveBackupInfoCalled: 1,
575
- },
576
- ];
577
-
578
- backup.backupBasePath = testPath.backupBasePath;
579
- backup.activeBackupPath = testPath.activeBackupJob;
580
- backup.backupStartTime = testEpoch;
581
- backup.logFile = path.join(testPath.backupBasePath, "test.log");
582
-
583
- /* prettier-ignore */
584
- when(spyOnsSettingsValue)
585
- .calledWith("backupInfo").mockImplementation(() => Promise.resolve(JSON.stringify([])));
586
- jest.spyOn(backup, "saveBackupInfo").mockImplementation(() => {});
587
-
588
- for (const testCase of testCases) {
589
- await createTestStructure();
590
- fs.emptyDirSync(testPath.activeBackupJob);
591
- const fileName = testCase.testFile;
592
- const file = path.join(testPath.activeBackupJob, fileName);
593
- fs.writeFileSync(file, "testFile");
594
- expect(fs.existsSync(file)).toBe(true);
595
-
596
- backup.zipArchive = testCase.zipArchive;
597
- backup.backupRetention = testCase.backupRetention;
598
- backup.singleJex = testCase.singleJex;
599
- backup.passwordEnabled = testCase.password === null ? false : true;
600
- backup.password = testCase.password;
601
-
602
- const result = await backup.makeBackupSet();
603
- expect(result).toBe(testCase.result);
604
- expect(fs.existsSync(testCase.checkFile)).toBe(true);
605
- expect(backup.saveBackupInfo).toHaveBeenCalledTimes(
606
- testCase.saveBackupInfoCalled
607
- );
608
- const pwCheck = await sevenZip.passwordProtected(testCase.checkFile);
609
- if (backup.passwordEnabled === true || testCase.zipArchive !== "no") {
610
- expect(pwCheck).toBe(backup.passwordEnabled);
611
- }
612
-
613
- backup.saveBackupInfo.mockReset();
614
- fs.emptyDirSync(testPath.activeBackupJob);
615
- expect(fs.existsSync(file)).toBe(false);
616
- }
617
-
618
- spyOnDateNow.mockRestore();
619
- });
620
- });
621
-
622
- describe("Backup retention", function () {
623
- it(`file/Folder deletion`, async () => {
624
- const backupRetention = 2;
625
- const set1 = path.join(testPath.backupBasePath, "202101011630");
626
- const set2 = path.join(testPath.backupBasePath, "202101021630.7z");
627
- const set3 = path.join(testPath.backupBasePath, "202101031630");
628
- const set4 = path.join(testPath.backupBasePath, "202101041630.7z");
629
-
630
- fs.emptyDirSync(set1);
631
- fs.closeSync(fs.openSync(set2, "w"));
632
- fs.emptyDirSync(set3);
633
- fs.closeSync(fs.openSync(set4, "w"));
634
-
635
- const backupInfo = [
636
- { name: "202101011630", date: 1609515000 },
637
- { name: "202101021630.7z", date: 1609601400 },
638
- { name: "202101031630", date: 1609687800 },
639
- { name: "202101041630.7z", date: 1609774200 },
640
- ];
641
-
642
- when(spyOnsSettingsValue)
643
- .calledWith("backupInfo")
644
- .mockImplementation(() => Promise.resolve(JSON.stringify(backupInfo)));
645
-
646
- expect(fs.existsSync(set1)).toBe(true);
647
- expect(fs.existsSync(set2)).toBe(true);
648
- expect(fs.existsSync(set3)).toBe(true);
649
- expect(fs.existsSync(set4)).toBe(true);
650
- await backup.deleteOldBackupSets(
651
- testPath.backupBasePath,
652
- backupRetention
653
- );
654
-
655
- expect(fs.existsSync(set1)).toBe(false);
656
- expect(fs.existsSync(set2)).toBe(false);
657
- expect(fs.existsSync(set3)).toBe(true);
658
- expect(fs.existsSync(set4)).toBe(true);
659
- expect(fs.readdirSync(testPath.backupBasePath).length).toBe(2);
660
- });
661
-
662
- it(`Backups < retention`, async () => {
663
- const backupRetention = 3;
664
- const folder1 = path.join(testPath.backupBasePath, "202101011630");
665
- const folder2 = path.join(testPath.backupBasePath, "202101021630");
666
-
667
- fs.emptyDirSync(folder1);
668
- fs.emptyDirSync(folder2);
669
-
670
- const backupInfo = [
671
- { name: "202101011630", date: 1 },
672
- { name: "202101021630", date: 2 },
673
- ];
674
-
675
- when(spyOnsSettingsValue)
676
- .calledWith("backupInfo")
677
- .mockImplementation(() => Promise.resolve(JSON.stringify(backupInfo)));
678
-
679
- await backup.deleteOldBackupSets(
680
- testPath.backupBasePath,
681
- backupRetention
682
- );
683
-
684
- const folderAnz = fs
685
- .readdirSync(testPath.backupBasePath, { withFileTypes: true })
686
- .filter((dirent) => dirent.isDirectory()).length;
687
-
688
- expect(folderAnz).toBe(2);
689
-
690
- expect(fs.existsSync(folder1)).toBe(true);
691
- expect(fs.existsSync(folder2)).toBe(true);
692
- });
693
-
694
- it(`Backups = retention`, async () => {
695
- const backupRetention = 3;
696
- const folder1 = path.join(testPath.backupBasePath, "202101011630");
697
- const folder2 = path.join(testPath.backupBasePath, "202101021630");
698
- const folder3 = path.join(testPath.backupBasePath, "202101031630");
699
-
700
- fs.emptyDirSync(folder1);
701
- fs.emptyDirSync(folder2);
702
- fs.emptyDirSync(folder3);
703
-
704
- const backupInfo = [
705
- { name: "202101011630", date: 1 },
706
- { name: "202101021630", date: 2 },
707
- { name: "202101031630", date: 3 },
708
- ];
709
-
710
- when(spyOnsSettingsValue)
711
- .calledWith("backupInfo")
712
- .mockImplementation(() => Promise.resolve(JSON.stringify(backupInfo)));
713
-
714
- await backup.deleteOldBackupSets(
715
- testPath.backupBasePath,
716
- backupRetention
717
- );
718
- const folderAnz = fs
719
- .readdirSync(testPath.backupBasePath, { withFileTypes: true })
720
- .filter((dirent) => dirent.isDirectory()).length;
721
-
722
- expect(folderAnz).toBe(3);
723
-
724
- expect(fs.existsSync(folder1)).toBe(true);
725
- expect(fs.existsSync(folder2)).toBe(true);
726
- expect(fs.existsSync(folder3)).toBe(true);
727
- });
728
-
729
- it(`Backups > retention`, async () => {
730
- const backupRetention = 3;
731
- const folder1 = path.join(testPath.backupBasePath, "202101011630");
732
- const folder2 = path.join(testPath.backupBasePath, "202101021630");
733
- const folder3 = path.join(testPath.backupBasePath, "202101031630");
734
- const folder4 = path.join(testPath.backupBasePath, "202101041630");
735
- const folder5 = path.join(testPath.backupBasePath, "202101051630");
736
-
737
- fs.emptyDirSync(folder1);
738
- fs.emptyDirSync(folder2);
739
- fs.emptyDirSync(folder3);
740
- fs.emptyDirSync(folder4);
741
- fs.emptyDirSync(folder5);
742
-
743
- const backupInfo = [
744
- { name: "202101011630", date: 1 },
745
- { name: "202101021630", date: 2 },
746
- { name: "202101031630", date: 3 },
747
- { name: "202101041630", date: 4 },
748
- { name: "202101051630", date: 5 },
749
- ];
750
-
751
- when(spyOnsSettingsValue)
752
- .calledWith("backupInfo")
753
- .mockImplementation(() => Promise.resolve(JSON.stringify(backupInfo)));
754
-
755
- await backup.deleteOldBackupSets(
756
- testPath.backupBasePath,
757
- backupRetention
758
- );
759
-
760
- const folderAnz = fs
761
- .readdirSync(testPath.backupBasePath, { withFileTypes: true })
762
- .filter((dirent) => dirent.isDirectory()).length;
763
-
764
- expect(folderAnz).toBe(3);
765
- expect(fs.existsSync(folder1)).toBe(false);
766
- expect(fs.existsSync(folder2)).toBe(false);
767
- expect(fs.existsSync(folder3)).toBe(true);
768
- expect(fs.existsSync(folder4)).toBe(true);
769
- expect(fs.existsSync(folder5)).toBe(true);
770
- });
771
- });
772
-
773
- describe("Logging", function () {
774
- beforeEach(async () => {
775
- backup.setupLog();
776
- });
777
-
778
- it(`Default`, async () => {
779
- expect(backup.log.transports.console.level).toBe("verbose");
780
- expect(backup.log.transports.file.level).toBe(false);
781
- });
782
-
783
- it(`Toggel file`, async () => {
784
- await backup.fileLogging(false);
785
- expect(backup.log.transports.file.level).toBe(false);
786
-
787
- /* prettier-ignore */
788
- when(spyOnsSettingsValue)
789
- .calledWith("fileLogLevel").mockImplementation(() => Promise.resolve("verbose"));
790
-
791
- backup.backupBasePath = "./";
792
- await backup.fileLogging(true);
793
- expect(backup.log.transports.file.level).toBe("verbose");
794
-
795
- /* prettier-ignore */
796
- when(spyOnsSettingsValue)
797
- .calledWith("fileLogLevel").mockImplementation(() => Promise.resolve("error"));
798
-
799
- backup.backupBasePath = "./";
800
- await backup.fileLogging(true);
801
- expect(backup.log.transports.file.level).toBe("error");
802
- });
803
-
804
- it(`move logfile`, async () => {
805
- const testCases = [
806
- {
807
- zipArchive: "no",
808
- password: null,
809
- logDst: testPath.backupBasePath,
810
- testLogFile: path.join(testPath.backupBasePath, "backup.log"),
811
- },
812
- {
813
- zipArchive: "no",
814
- password: null,
815
- logDst: path.join(testPath.backupBasePath, "testDir"),
816
- testLogFile: path.join(
817
- testPath.backupBasePath,
818
- "testDir",
819
- "backup.log"
820
- ),
821
- },
822
- {
823
- zipArchive: "yes",
824
- password: null,
825
- logDst: path.join(testPath.backupBasePath, "testDir"),
826
- testLogFile: path.join(
827
- testPath.backupBasePath,
828
- "testDir",
829
- "backup.log"
830
- ),
831
- },
832
- {
833
- zipArchive: "yesone",
834
- password: null,
835
- logDst: path.join(testPath.backupBasePath, "Backup.7z"),
836
- testLogFile: "backup.log",
837
- },
838
- {
839
- zipArchive: "yesone",
840
- password: "secret",
841
- logDst: path.join(testPath.backupBasePath, "Backup.7z"),
842
- testLogFile: "backup.log",
843
- },
844
- {
845
- zipArchive: "no",
846
- password: "secret",
847
- logDst: testPath.backupBasePath,
848
- testLogFile: "backup.log",
849
- },
850
- ];
851
-
852
- backup.logFile = path.join(testPath.base, "test.log");
853
- for (const testCase of testCases) {
854
- await createTestStructure();
855
- if (testCase.zipArchive !== "yesone") {
856
- fs.emptyDirSync(testCase.logDst);
857
- }
858
- if (testCase.zipArchive === "yesone") {
859
- const dummyFile = path.join(testPath.base, "dummy");
860
- fs.writeFileSync(dummyFile, "dummy");
861
- await sevenZip.add(testCase.logDst, dummyFile, testCase.password);
862
- expect(fs.existsSync(dummyFile)).toBe(true);
863
- expect(fs.existsSync(testCase.logDst)).toBe(true);
864
- }
865
-
866
- fs.writeFileSync(backup.logFile, "log");
867
-
868
- backup.zipArchive = testCase.zipArchive;
869
- backup.password = testCase.password;
870
-
871
- expect(fs.existsSync(backup.logFile)).toBe(true);
872
- expect(await backup.moveLogFile(testCase.logDst)).toBe(true);
873
- expect(fs.existsSync(backup.logFile)).toBe(false);
874
-
875
- if (testCase.password !== null || testCase.zipArchive === "yesone") {
876
- const fileList = await sevenZip.list(
877
- testCase.logDst,
878
- testCase.password
879
- );
880
- expect(fileList.map((f) => f.file)).toContain(testCase.testLogFile);
881
- } else {
882
- expect(fs.existsSync(testCase.testLogFile)).toBe(true);
883
- }
884
- }
885
- });
886
- });
887
-
888
- describe("Backup action", function () {
889
- it(`File`, async () => {
890
- const src1 = path.join(testPath.joplinProfile, "settings.json");
891
- const src2 = path.join(testPath.joplinProfile, "doesNotExist.json");
892
- const dst = path.join(testPath.backupBasePath, "settings.json");
893
- fs.writeFileSync(src1, "data");
894
-
895
- expect(await backup.backupFile(src1, dst)).toBe(true);
896
- expect(fs.existsSync(dst)).toBe(true);
897
-
898
- expect(await backup.backupFile(src2, dst)).toBe(false);
899
-
900
- expect(backup.log.error).toHaveBeenCalledTimes(0);
901
- expect(backup.log.warn).toHaveBeenCalledTimes(0);
902
- });
903
-
904
- it(`Folder`, async () => {
905
- const file1 = path.join(testPath.templates, "template1.md");
906
- const file2 = path.join(testPath.templates, "template2.md");
907
-
908
- const doesNotExist = path.join(testPath.base, "doesNotExist");
909
-
910
- const dst = path.join(testPath.backupBasePath, "templates");
911
- const checkFile1 = path.join(dst, "template1.md");
912
- const checkFile2 = path.join(dst, "template2.md");
913
-
914
- fs.writeFileSync(file1, "template1");
915
- fs.writeFileSync(file2, "template2");
916
-
917
- expect(await backup.backupFolder(testPath.templates, dst)).toBe(true);
918
- expect(fs.existsSync(checkFile1)).toBe(true);
919
- expect(fs.existsSync(checkFile2)).toBe(true);
920
-
921
- expect(await backup.backupFolder(doesNotExist, dst)).toBe(false);
922
-
923
- expect(backup.log.error).toHaveBeenCalledTimes(0);
924
- expect(backup.log.warn).toHaveBeenCalledTimes(0);
925
- });
926
-
927
- it(`Profile`, async () => {
928
- const template = path.join(testPath.templates, "template1.md");
929
- const settings = path.join(testPath.joplinProfile, "settings.json");
930
- const userstyle = path.join(testPath.joplinProfile, "userstyle.css");
931
- const userchrome = path.join(testPath.joplinProfile, "userchrome.css");
932
- const keymap = path.join(testPath.joplinProfile, "keymap-desktop.json");
933
- const plugin = path.join(testPath.plugins, "test-plugin.jpl");
934
-
935
- fs.writeFileSync(template, "template");
936
- fs.writeFileSync(settings, "settings");
937
- fs.writeFileSync(userstyle, "userstyle");
938
- fs.writeFileSync(userchrome, "userchrome");
939
- fs.writeFileSync(keymap, "keymap");
940
- fs.writeFileSync(plugin, "plugin");
941
-
942
- fs.emptyDirSync(testPath.activeBackupJob);
943
-
944
- const backupTemplate = path.join(
945
- testPath.activeBackupJob,
946
- "profile",
947
- "templates",
948
- "template1.md"
949
- );
950
- const backupSettings = path.join(
951
- testPath.activeBackupJob,
952
- "profile",
953
- "settings.json"
954
- );
955
- const backupUserstyle = path.join(
956
- testPath.activeBackupJob,
957
- "profile",
958
- "userstyle.css"
959
- );
960
- const backupUserchrome = path.join(
961
- testPath.activeBackupJob,
962
- "profile",
963
- "userchrome.css"
964
- );
965
- const backupKeymap = path.join(
966
- testPath.activeBackupJob,
967
- "profile",
968
- "keymap-desktop.json"
969
- );
970
- const backupPlugin = path.join(
971
- testPath.activeBackupJob,
972
- "profile",
973
- "plugins",
974
- "test-plugin.jpl"
975
- );
976
-
977
- backup.activeBackupPath = testPath.activeBackupJob;
978
- backup.backupPlugins = true;
979
- await backup.backupProfileData();
980
-
981
- expect(fs.existsSync(backupTemplate)).toBe(true);
982
- expect(fs.existsSync(backupSettings)).toBe(true);
983
- expect(fs.existsSync(backupUserstyle)).toBe(true);
984
- expect(fs.existsSync(backupUserchrome)).toBe(true);
985
- expect(fs.existsSync(backupKeymap)).toBe(true);
986
- expect(fs.existsSync(backupPlugin)).toBe(true);
987
-
988
- expect(backup.log.error).toHaveBeenCalledTimes(0);
989
- expect(backup.log.warn).toHaveBeenCalledTimes(0);
990
- });
991
- });
992
- });