joplin-plugin-backup 1.2.2 → 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,1014 +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),
532
- testFile: "testFile.txt",
533
- checkFile: path.join(testPath.backupBasePath, "testFile.txt.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"),
542
- testFile: "testFile.txt",
543
- checkFile: path.join(
544
- testPath.backupBasePath,
545
- "202101021630",
546
- "testFile.txt.7z"
547
- ),
548
- saveBackupInfoCalled: 1,
549
- },
550
- {
551
- zipArchive: "yesone",
552
- backupRetention: 1,
553
- password: null,
554
- singleJex: true,
555
- result: path.join(testPath.backupBasePath, "JoplinBackup.7z"),
556
- testFile: "testFile.txt",
557
- checkFile: path.join(testPath.backupBasePath, "JoplinBackup.7z"),
558
- saveBackupInfoCalled: 0,
559
- },
560
- {
561
- zipArchive: "yesone",
562
- backupRetention: 1,
563
- password: "secret",
564
- singleJex: true,
565
- result: path.join(testPath.backupBasePath, "JoplinBackup.7z"),
566
- testFile: "testFile.txt",
567
- checkFile: path.join(testPath.backupBasePath, "JoplinBackup.7z"),
568
- saveBackupInfoCalled: 0,
569
- },
570
- {
571
- zipArchive: "yesone",
572
- backupRetention: 2,
573
- password: null,
574
- singleJex: true,
575
- result: path.join(testPath.backupBasePath, "202101021630.7z"),
576
- testFile: "testFile.txt",
577
- checkFile: path.join(testPath.backupBasePath, "202101021630.7z"),
578
- saveBackupInfoCalled: 1,
579
- },
580
- ];
581
-
582
- backup.backupBasePath = testPath.backupBasePath;
583
- backup.activeBackupPath = testPath.activeBackupJob;
584
- backup.backupStartTime = testEpoch;
585
- backup.logFile = path.join(testPath.backupBasePath, "test.log");
586
-
587
- /* prettier-ignore */
588
- when(spyOnsSettingsValue)
589
- .calledWith("backupInfo").mockImplementation(() => Promise.resolve(JSON.stringify([])));
590
- jest.spyOn(backup, "saveBackupInfo").mockImplementation(() => {});
591
-
592
- for (const testCase of testCases) {
593
- await createTestStructure();
594
- fs.emptyDirSync(testPath.activeBackupJob);
595
- const fileName = testCase.testFile;
596
- const file = path.join(testPath.activeBackupJob, fileName);
597
- fs.writeFileSync(file, "testFile");
598
- expect(fs.existsSync(file)).toBe(true);
599
-
600
- backup.zipArchive = testCase.zipArchive;
601
- backup.backupRetention = testCase.backupRetention;
602
- backup.singleJex = testCase.singleJex;
603
- backup.passwordEnabled = testCase.password === null ? false : true;
604
- backup.password = testCase.password;
605
-
606
- const result = await backup.makeBackupSet();
607
- expect(result).toBe(testCase.result);
608
- expect(fs.existsSync(testCase.checkFile)).toBe(true);
609
- expect(backup.saveBackupInfo).toHaveBeenCalledTimes(
610
- testCase.saveBackupInfoCalled
611
- );
612
- const pwCheck = await sevenZip.passwordProtected(testCase.checkFile);
613
- if (backup.passwordEnabled === true || testCase.zipArchive !== "no") {
614
- expect(pwCheck).toBe(backup.passwordEnabled);
615
- }
616
-
617
- backup.saveBackupInfo.mockReset();
618
- fs.emptyDirSync(testPath.activeBackupJob);
619
- expect(fs.existsSync(file)).toBe(false);
620
- }
621
-
622
- spyOnDateNow.mockRestore();
623
- });
624
- });
625
-
626
- describe("Backup retention", function () {
627
- it(`file/Folder deletion`, async () => {
628
- const backupRetention = 2;
629
- const set1 = path.join(testPath.backupBasePath, "202101011630");
630
- const set2 = path.join(testPath.backupBasePath, "202101021630.7z");
631
- const set3 = path.join(testPath.backupBasePath, "202101031630");
632
- const set4 = path.join(testPath.backupBasePath, "202101041630.7z");
633
-
634
- fs.emptyDirSync(set1);
635
- fs.closeSync(fs.openSync(set2, "w"));
636
- fs.emptyDirSync(set3);
637
- fs.closeSync(fs.openSync(set4, "w"));
638
-
639
- const backupInfo = [
640
- { name: "202101011630", date: 1609515000 },
641
- { name: "202101021630.7z", date: 1609601400 },
642
- { name: "202101031630", date: 1609687800 },
643
- { name: "202101041630.7z", date: 1609774200 },
644
- ];
645
-
646
- when(spyOnsSettingsValue)
647
- .calledWith("backupInfo")
648
- .mockImplementation(() => Promise.resolve(JSON.stringify(backupInfo)));
649
-
650
- expect(fs.existsSync(set1)).toBe(true);
651
- expect(fs.existsSync(set2)).toBe(true);
652
- expect(fs.existsSync(set3)).toBe(true);
653
- expect(fs.existsSync(set4)).toBe(true);
654
- await backup.deleteOldBackupSets(
655
- testPath.backupBasePath,
656
- backupRetention
657
- );
658
-
659
- expect(fs.existsSync(set1)).toBe(false);
660
- expect(fs.existsSync(set2)).toBe(false);
661
- expect(fs.existsSync(set3)).toBe(true);
662
- expect(fs.existsSync(set4)).toBe(true);
663
- expect(fs.readdirSync(testPath.backupBasePath).length).toBe(2);
664
- });
665
-
666
- it(`Backups < retention`, async () => {
667
- const backupRetention = 3;
668
- const folder1 = path.join(testPath.backupBasePath, "202101011630");
669
- const folder2 = path.join(testPath.backupBasePath, "202101021630");
670
-
671
- fs.emptyDirSync(folder1);
672
- fs.emptyDirSync(folder2);
673
-
674
- const backupInfo = [
675
- { name: "202101011630", date: 1 },
676
- { name: "202101021630", date: 2 },
677
- ];
678
-
679
- when(spyOnsSettingsValue)
680
- .calledWith("backupInfo")
681
- .mockImplementation(() => Promise.resolve(JSON.stringify(backupInfo)));
682
-
683
- await backup.deleteOldBackupSets(
684
- testPath.backupBasePath,
685
- backupRetention
686
- );
687
-
688
- const folderAnz = fs
689
- .readdirSync(testPath.backupBasePath, { withFileTypes: true })
690
- .filter((dirent) => dirent.isDirectory()).length;
691
-
692
- expect(folderAnz).toBe(2);
693
-
694
- expect(fs.existsSync(folder1)).toBe(true);
695
- expect(fs.existsSync(folder2)).toBe(true);
696
- });
697
-
698
- it(`Backups = retention`, async () => {
699
- const backupRetention = 3;
700
- const folder1 = path.join(testPath.backupBasePath, "202101011630");
701
- const folder2 = path.join(testPath.backupBasePath, "202101021630");
702
- const folder3 = path.join(testPath.backupBasePath, "202101031630");
703
-
704
- fs.emptyDirSync(folder1);
705
- fs.emptyDirSync(folder2);
706
- fs.emptyDirSync(folder3);
707
-
708
- const backupInfo = [
709
- { name: "202101011630", date: 1 },
710
- { name: "202101021630", date: 2 },
711
- { name: "202101031630", date: 3 },
712
- ];
713
-
714
- when(spyOnsSettingsValue)
715
- .calledWith("backupInfo")
716
- .mockImplementation(() => Promise.resolve(JSON.stringify(backupInfo)));
717
-
718
- await backup.deleteOldBackupSets(
719
- testPath.backupBasePath,
720
- backupRetention
721
- );
722
- const folderAnz = fs
723
- .readdirSync(testPath.backupBasePath, { withFileTypes: true })
724
- .filter((dirent) => dirent.isDirectory()).length;
725
-
726
- expect(folderAnz).toBe(3);
727
-
728
- expect(fs.existsSync(folder1)).toBe(true);
729
- expect(fs.existsSync(folder2)).toBe(true);
730
- expect(fs.existsSync(folder3)).toBe(true);
731
- });
732
-
733
- it(`Backups > retention`, async () => {
734
- const backupRetention = 3;
735
- const folder1 = path.join(testPath.backupBasePath, "202101011630");
736
- const folder2 = path.join(testPath.backupBasePath, "202101021630");
737
- const folder3 = path.join(testPath.backupBasePath, "202101031630");
738
- const folder4 = path.join(testPath.backupBasePath, "202101041630");
739
- const folder5 = path.join(testPath.backupBasePath, "202101051630");
740
-
741
- fs.emptyDirSync(folder1);
742
- fs.emptyDirSync(folder2);
743
- fs.emptyDirSync(folder3);
744
- fs.emptyDirSync(folder4);
745
- fs.emptyDirSync(folder5);
746
-
747
- const backupInfo = [
748
- { name: "202101011630", date: 1 },
749
- { name: "202101021630", date: 2 },
750
- { name: "202101031630", date: 3 },
751
- { name: "202101041630", date: 4 },
752
- { name: "202101051630", date: 5 },
753
- ];
754
-
755
- when(spyOnsSettingsValue)
756
- .calledWith("backupInfo")
757
- .mockImplementation(() => Promise.resolve(JSON.stringify(backupInfo)));
758
-
759
- await backup.deleteOldBackupSets(
760
- testPath.backupBasePath,
761
- backupRetention
762
- );
763
-
764
- const folderAnz = fs
765
- .readdirSync(testPath.backupBasePath, { withFileTypes: true })
766
- .filter((dirent) => dirent.isDirectory()).length;
767
-
768
- expect(folderAnz).toBe(3);
769
- expect(fs.existsSync(folder1)).toBe(false);
770
- expect(fs.existsSync(folder2)).toBe(false);
771
- expect(fs.existsSync(folder3)).toBe(true);
772
- expect(fs.existsSync(folder4)).toBe(true);
773
- expect(fs.existsSync(folder5)).toBe(true);
774
- });
775
- });
776
-
777
- describe("Logging", function () {
778
- beforeEach(async () => {
779
- backup.setupLog();
780
- });
781
-
782
- it(`Default`, async () => {
783
- expect(backup.log.transports.console.level).toBe("verbose");
784
- expect(backup.log.transports.file.level).toBe(false);
785
- });
786
-
787
- it(`Toggel file`, async () => {
788
- await backup.fileLogging(false);
789
- expect(backup.log.transports.file.level).toBe(false);
790
-
791
- /* prettier-ignore */
792
- when(spyOnsSettingsValue)
793
- .calledWith("fileLogLevel").mockImplementation(() => Promise.resolve("verbose"));
794
-
795
- backup.backupBasePath = "./";
796
- await backup.fileLogging(true);
797
- expect(backup.log.transports.file.level).toBe("verbose");
798
-
799
- /* prettier-ignore */
800
- when(spyOnsSettingsValue)
801
- .calledWith("fileLogLevel").mockImplementation(() => Promise.resolve("error"));
802
-
803
- backup.backupBasePath = "./";
804
- await backup.fileLogging(true);
805
- expect(backup.log.transports.file.level).toBe("error");
806
- });
807
-
808
- describe("move logfile", function () {
809
- const testCases = [
810
- {
811
- description: "backupBasePath",
812
- zipArchive: "no",
813
- password: null,
814
- logDst: testPath.backupBasePath,
815
- },
816
- {
817
- description: "backupBasePath, password",
818
- zipArchive: "no",
819
- password: "secret",
820
- logDst: testPath.backupBasePath,
821
- },
822
- {
823
- description: "backupBasePath, zip, password",
824
- zipArchive: "yes",
825
- password: "secret",
826
- logDst: testPath.backupBasePath,
827
- },
828
- {
829
- description: "backupBasePath, zip one",
830
- zipArchive: "yesone",
831
- password: null,
832
- logDst: path.join(testPath.backupBasePath, "retention.7z"),
833
- },
834
- {
835
- description: "backupBasePath, zip one, password",
836
- zipArchive: "yesone",
837
- password: "secret",
838
- logDst: path.join(testPath.backupBasePath, "retention.7z"),
839
- },
840
- {
841
- description: "sub in backupBasePath",
842
- zipArchive: "no",
843
- password: null,
844
- logDst: path.join(testPath.backupBasePath, "retentionfolder"),
845
- },
846
- {
847
- description: "sub in backupBasePath, password",
848
- zipArchive: "no",
849
- password: "secret",
850
- logDst: path.join(testPath.backupBasePath, "retentionfolder"),
851
- },
852
- {
853
- description: "sub in backupBasePath, zip",
854
- zipArchive: "yes",
855
- password: null,
856
- logDst: path.join(testPath.backupBasePath, "retentionfolder"),
857
- },
858
- {
859
- description: "sub in backupBasePath, password, zip",
860
- zipArchive: "yes",
861
- password: "secret",
862
- logDst: path.join(testPath.backupBasePath, "retentionfolder"),
863
- },
864
- ];
865
-
866
- for (const testCase of testCases) {
867
- it(`${testCase.description}`, async () => {
868
- backup.logFile = path.join(testPath.base, "test.log");
869
- backup.zipArchive = testCase.zipArchive;
870
- backup.password = testCase.password;
871
-
872
- await createTestStructure();
873
-
874
- if (testCase.zipArchive === "yesone") {
875
- const dummyFile = path.join(testPath.base, "dummy");
876
- fs.writeFileSync(dummyFile, "dummy");
877
- expect(fs.existsSync(dummyFile)).toBe(true);
878
- await sevenZip.add(testCase.logDst, dummyFile, testCase.password);
879
- expect(fs.existsSync(testCase.logDst)).toBe(true);
880
- } else {
881
- fs.emptyDirSync(testCase.logDst);
882
- }
883
-
884
- fs.writeFileSync(backup.logFile, "log");
885
- expect(fs.existsSync(backup.logFile)).toBe(true);
886
-
887
- expect(await backup.moveLogFile(testCase.logDst)).toBe(true);
888
- expect(fs.existsSync(backup.logFile)).toBe(false);
889
-
890
- let checkBackupLogFile = path.join(testCase.logDst, "backup.log");
891
- if (testCase.zipArchive === "yesone") {
892
- checkBackupLogFile = testCase.logDst;
893
- } else if (testCase.password !== null) {
894
- checkBackupLogFile = path.join(testCase.logDst, "backuplog.7z");
895
- }
896
- expect(fs.existsSync(checkBackupLogFile)).toBe(true);
897
-
898
- if (testCase.password !== null || testCase.zipArchive === "yesone") {
899
- const fileList = await sevenZip.list(
900
- testCase.logDst,
901
- testCase.password
902
- );
903
- expect(fileList.map((f) => f.file)).toContain("backup.log");
904
- }
905
- });
906
- }
907
- });
908
- });
909
-
910
- describe("Backup action", function () {
911
- it(`File`, async () => {
912
- const src1 = path.join(testPath.joplinProfile, "settings.json");
913
- const src2 = path.join(testPath.joplinProfile, "doesNotExist.json");
914
- const dst = path.join(testPath.backupBasePath, "settings.json");
915
- fs.writeFileSync(src1, "data");
916
-
917
- expect(await backup.backupFile(src1, dst)).toBe(true);
918
- expect(fs.existsSync(dst)).toBe(true);
919
-
920
- expect(await backup.backupFile(src2, dst)).toBe(false);
921
-
922
- expect(backup.log.error).toHaveBeenCalledTimes(0);
923
- expect(backup.log.warn).toHaveBeenCalledTimes(0);
924
- });
925
-
926
- it(`Folder`, async () => {
927
- const file1 = path.join(testPath.templates, "template1.md");
928
- const file2 = path.join(testPath.templates, "template2.md");
929
-
930
- const doesNotExist = path.join(testPath.base, "doesNotExist");
931
-
932
- const dst = path.join(testPath.backupBasePath, "templates");
933
- const checkFile1 = path.join(dst, "template1.md");
934
- const checkFile2 = path.join(dst, "template2.md");
935
-
936
- fs.writeFileSync(file1, "template1");
937
- fs.writeFileSync(file2, "template2");
938
-
939
- expect(await backup.backupFolder(testPath.templates, dst)).toBe(true);
940
- expect(fs.existsSync(checkFile1)).toBe(true);
941
- expect(fs.existsSync(checkFile2)).toBe(true);
942
-
943
- expect(await backup.backupFolder(doesNotExist, dst)).toBe(false);
944
-
945
- expect(backup.log.error).toHaveBeenCalledTimes(0);
946
- expect(backup.log.warn).toHaveBeenCalledTimes(0);
947
- });
948
-
949
- it(`Profile`, async () => {
950
- const template = path.join(testPath.templates, "template1.md");
951
- const settings = path.join(testPath.joplinProfile, "settings.json");
952
- const userstyle = path.join(testPath.joplinProfile, "userstyle.css");
953
- const userchrome = path.join(testPath.joplinProfile, "userchrome.css");
954
- const keymap = path.join(testPath.joplinProfile, "keymap-desktop.json");
955
- const plugin = path.join(testPath.plugins, "test-plugin.jpl");
956
-
957
- fs.writeFileSync(template, "template");
958
- fs.writeFileSync(settings, "settings");
959
- fs.writeFileSync(userstyle, "userstyle");
960
- fs.writeFileSync(userchrome, "userchrome");
961
- fs.writeFileSync(keymap, "keymap");
962
- fs.writeFileSync(plugin, "plugin");
963
-
964
- fs.emptyDirSync(testPath.activeBackupJob);
965
-
966
- const backupTemplate = path.join(
967
- testPath.activeBackupJob,
968
- "profile",
969
- "templates",
970
- "template1.md"
971
- );
972
- const backupSettings = path.join(
973
- testPath.activeBackupJob,
974
- "profile",
975
- "settings.json"
976
- );
977
- const backupUserstyle = path.join(
978
- testPath.activeBackupJob,
979
- "profile",
980
- "userstyle.css"
981
- );
982
- const backupUserchrome = path.join(
983
- testPath.activeBackupJob,
984
- "profile",
985
- "userchrome.css"
986
- );
987
- const backupKeymap = path.join(
988
- testPath.activeBackupJob,
989
- "profile",
990
- "keymap-desktop.json"
991
- );
992
- const backupPlugin = path.join(
993
- testPath.activeBackupJob,
994
- "profile",
995
- "plugins",
996
- "test-plugin.jpl"
997
- );
998
-
999
- backup.activeBackupPath = testPath.activeBackupJob;
1000
- backup.backupPlugins = true;
1001
- await backup.backupProfileData();
1002
-
1003
- expect(fs.existsSync(backupTemplate)).toBe(true);
1004
- expect(fs.existsSync(backupSettings)).toBe(true);
1005
- expect(fs.existsSync(backupUserstyle)).toBe(true);
1006
- expect(fs.existsSync(backupUserchrome)).toBe(true);
1007
- expect(fs.existsSync(backupKeymap)).toBe(true);
1008
- expect(fs.existsSync(backupPlugin)).toBe(true);
1009
-
1010
- expect(backup.log.error).toHaveBeenCalledTimes(0);
1011
- expect(backup.log.warn).toHaveBeenCalledTimes(0);
1012
- });
1013
- });
1014
- });