From b4f7612b4cc5954c110aa69da7258675bb7c6b51 Mon Sep 17 00:00:00 2001 From: Henry H Date: Wed, 7 Feb 2024 11:13:15 -0800 Subject: [PATCH 1/3] Feat: Add a README file to the root backup directory --- src/Backup.ts | 11 +++++++++++ src/locales/en_US.json | 1 + 2 files changed, 12 insertions(+) diff --git a/src/Backup.ts b/src/Backup.ts index 2c0c174..6fec441 100644 --- a/src/Backup.ts +++ b/src/Backup.ts @@ -477,6 +477,7 @@ class Backup { await this.backupNotebooks(); const backupDst = await this.makeBackupSet(); + await this.writeReadme(backupDst); await joplin.settings.setValue( "lastBackup", @@ -684,6 +685,16 @@ class Backup { } } + private async writeReadme(backupFolder: string) { + const readmePath = path.join(backupFolder, "README.md"); + this.log.info("writeReadme to", readmePath); + const readmeText = i18n.__( + "backupReadme", + this.backupStartTime.toLocaleString() + ); + await fs.writeFile(readmePath, readmeText, "utf8"); + } + private async backupNotebooks() { const notebooks = await this.selectNotebooks(); diff --git a/src/locales/en_US.json b/src/locales/en_US.json index 79b6d55..771d14c 100644 --- a/src/locales/en_US.json +++ b/src/locales/en_US.json @@ -86,6 +86,7 @@ "description": "Execute command when backup is finished" } }, + "backupReadme": "# Joplin Backup\n\nThe backups in this folder were created with the Simple Backup plugin for Joplin. The most recent backup was created on %s.\n\nSee the [Simple Backup documentation](https://joplinapp.org/plugins/plugin/io.github.jackgruber.backup/#restore) for information about how to restore from this backup.", "command": { "createBackup": "Create backup" } From b77920310c9a2cfdc772872e3cab0f9b7095ef0b Mon Sep 17 00:00:00 2001 From: Henry H Date: Wed, 14 Feb 2024 16:21:25 -0800 Subject: [PATCH 2/3] Add automated test --- __test__/backup.test.ts | 37 +++++++++++++++++++++++++++++++++++++ package.json | 2 +- src/locales/en_US.json | 2 +- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/__test__/backup.test.ts b/__test__/backup.test.ts index c557dde..49e6832 100644 --- a/__test__/backup.test.ts +++ b/__test__/backup.test.ts @@ -27,6 +27,7 @@ let spyOnLogWarn = null; let spyOnLogError = null; let spyOnShowError = null; let spyOnSaveBackupInfo = null; +let spyOnDataGet = null; const spyOnsSettingsValue = jest.spyOn(joplin.settings, "value"); const spyOnGlobalValue = jest.spyOn(joplin.settings, "globalValue"); @@ -60,6 +61,13 @@ describe("Backup", function () { .calledWith("locale").mockImplementation(() => Promise.resolve("en_US")) .calledWith("templateDir").mockImplementation(() => Promise.resolve(testPath.templates)); + spyOnDataGet = jest + .spyOn(joplin.data, "get") + .mockImplementation(async (_path, _query) => ({ + items: [], + hasMore: false, + })); + await createTestStructure(); backup = new Backup() as any; backup.backupStartTime = new Date(); @@ -93,6 +101,7 @@ describe("Backup", function () { spyOnShowError.mockReset(); spyOnsSettingsValue.mockReset(); spyOnGlobalValue.mockReset(); + spyOnDataGet.mockReset(); spyOnSaveBackupInfo.mockReset(); }); @@ -1014,4 +1023,32 @@ describe("Backup", function () { expect(backup.log.warn).toHaveBeenCalledTimes(0); }); }); + + describe("create backup readme", () => { + it("should create a README.md in the backup directory", async () => { + backup.backupStartTime = null; + backup.passwordEnabled = false; + + when(spyOnsSettingsValue) + .calledWith("zipArchive") + .mockImplementation(() => "no"); + when(spyOnsSettingsValue) + .calledWith("execFinishCmd") + .mockImplementation(() => ""); + + await backup.start(); + + // Should exist and be non-empty + const readmePath = path.join( + testPath.backupBasePath, + "JoplinBackup", + "README.md" + ); + expect(await fs.pathExists(readmePath)).toBe(true); + expect(await fs.readFile(readmePath, "utf8")).not.toBe(""); + + // Prevent "open handle" errors + backup.stopTimer(); + }); + }); }); diff --git a/package.json b/package.json index b937f80..52d6de8 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "husky": "^6.0.0", "jest": "^27.0.4", "jest-when": "^3.3.1", - "joplinplugindevtools": "^1.0.15", + "joplinplugindevtools": "^1.0.16", "lint-staged": "^11.0.0", "mime": "^2.5.2", "on-build-webpack": "^0.1.0", diff --git a/src/locales/en_US.json b/src/locales/en_US.json index 771d14c..f7db718 100644 --- a/src/locales/en_US.json +++ b/src/locales/en_US.json @@ -86,7 +86,7 @@ "description": "Execute command when backup is finished" } }, - "backupReadme": "# Joplin Backup\n\nThe backups in this folder were created with the Simple Backup plugin for Joplin. The most recent backup was created on %s.\n\nSee the [Simple Backup documentation](https://joplinapp.org/plugins/plugin/io.github.jackgruber.backup/#restore) for information about how to restore from this backup.", + "backupReadme": "# Joplin Backup\n\nThis folder contains one or more backups of data from the Joplin note taking application. The most recent backup was created on %s.\n\nSee the [Simple Backup documentation](https://joplinapp.org/plugins/plugin/io.github.jackgruber.backup/#restore) for information about how to restore from this backup.", "command": { "createBackup": "Create backup" } From a3e46fb70eba20c61386b9890ccb9c919a7bf791 Mon Sep 17 00:00:00 2001 From: Henry H Date: Sat, 17 Feb 2024 08:26:53 -0800 Subject: [PATCH 3/3] Fix README written to wrong location when revisions are enabled --- __test__/backup.test.ts | 53 ++++++++++++++++++++++------------------- src/Backup.ts | 2 +- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/__test__/backup.test.ts b/__test__/backup.test.ts index 49e6832..5695db0 100644 --- a/__test__/backup.test.ts +++ b/__test__/backup.test.ts @@ -52,7 +52,10 @@ describe("Backup", function () { when(spyOnsSettingsValue) .mockImplementation(() => Promise.resolve("no mockImplementation")) .calledWith("fileLogLevel").mockImplementation(() => Promise.resolve("error")) - .calledWith("path").mockImplementation(() => Promise.resolve(testPath.backupBasePath)); + .calledWith("path").mockImplementation(() => Promise.resolve(testPath.backupBasePath)) + .calledWith("zipArchive").mockImplementation(() => "no") + .calledWith("execFinishCmd").mockImplementation(() => "") + .calledWith("usePassword").mockImplementation(() => false); /* prettier-ignore */ when(spyOnGlobalValue) @@ -1025,30 +1028,30 @@ describe("Backup", function () { }); describe("create backup readme", () => { - it("should create a README.md in the backup directory", async () => { - backup.backupStartTime = null; - backup.passwordEnabled = false; - - when(spyOnsSettingsValue) - .calledWith("zipArchive") - .mockImplementation(() => "no"); - when(spyOnsSettingsValue) - .calledWith("execFinishCmd") - .mockImplementation(() => ""); - - await backup.start(); - - // Should exist and be non-empty - const readmePath = path.join( - testPath.backupBasePath, - "JoplinBackup", - "README.md" - ); - expect(await fs.pathExists(readmePath)).toBe(true); - expect(await fs.readFile(readmePath, "utf8")).not.toBe(""); + it.each([{ backupRetention: 1 }, { backupRetention: 2 }])( + "should create a README.md in the backup directory (case %#)", + async ({ backupRetention }) => { + when(spyOnsSettingsValue) + .calledWith("backupRetention") + .mockImplementation(async () => backupRetention) + .calledWith("backupInfo") + .mockImplementation(() => Promise.resolve("[]")); + + backup.backupStartTime = null; + await backup.start(); + + // Should exist and be non-empty + const readmePath = path.join( + testPath.backupBasePath, + "JoplinBackup", + "README.md" + ); + expect(await fs.pathExists(readmePath)).toBe(true); + expect(await fs.readFile(readmePath, "utf8")).not.toBe(""); - // Prevent "open handle" errors - backup.stopTimer(); - }); + // Prevent "open handle" errors + backup.stopTimer(); + } + ); }); }); diff --git a/src/Backup.ts b/src/Backup.ts index 6fec441..36416a9 100644 --- a/src/Backup.ts +++ b/src/Backup.ts @@ -477,8 +477,8 @@ class Backup { await this.backupNotebooks(); const backupDst = await this.makeBackupSet(); - await this.writeReadme(backupDst); + await this.writeReadme(this.backupBasePath); await joplin.settings.setValue( "lastBackup", this.backupStartTime.getTime()