From 11101929a6580b23c5beb9be66e4c2bd26d55756 Mon Sep 17 00:00:00 2001 From: ttsukagoshi Date: Sun, 21 May 2023 00:27:49 +0900 Subject: [PATCH 1/7] Create test file for setDeeplAuthKey --- __tests__/setDeeplAuthKey.test.ts | 50 +++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 __tests__/setDeeplAuthKey.test.ts diff --git a/__tests__/setDeeplAuthKey.test.ts b/__tests__/setDeeplAuthKey.test.ts new file mode 100644 index 0000000..5e82b77 --- /dev/null +++ b/__tests__/setDeeplAuthKey.test.ts @@ -0,0 +1,50 @@ +import { setDeeplAuthKey } from '../src/sheetsl'; + +enum ButtonSet { + OK_CANCEL, +} + +enum Button { + OK, + CANCEL, +} + +SpreadsheetApp.getUi = jest.fn(() => new MockUi()) as any; +PropertiesService.getUserProperties = jest.fn(() => ({ + setProperty: jest.fn((key: string, value: string) => + console.log(`key: ${key}, value: ${value}`) + ), +})) as any; + +class MockUi { + ButtonSet: ButtonSet; + Button: Button; + constructor() { + this.ButtonSet = ButtonSet.OK_CANCEL; + this.Button = Button.OK; + } + prompt(message: string, buttonset: ButtonSet) { + return new MockPromptResponse(message, buttonset); + } + alert(message: string) { + console.log(message); + } +} + +class MockPromptResponse { + responseText: string; + buttonset: ButtonSet; + constructor(message: string, buttonset: ButtonSet) { + this.responseText = message; + this.buttonset = buttonset; + } + getResponseText() { + return this.responseText; + } + getSelectedButton = jest + .fn() + .mockReturnValueOnce(Button.OK) + .mockReturnValueOnce(Button.CANCEL) + .mockReturnValueOnce(undefined) + .mockReturnValue(Button.OK); +} From ff1697c8d2f5598aac24236e3841ee6c519301d8 Mon Sep 17 00:00:00 2001 From: ttsukagoshi Date: Sun, 21 May 2023 00:27:49 +0900 Subject: [PATCH 2/7] Create test file for setDeeplAuthKey --- __tests__/setDeeplAuthKey.test.ts | 50 +++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 __tests__/setDeeplAuthKey.test.ts diff --git a/__tests__/setDeeplAuthKey.test.ts b/__tests__/setDeeplAuthKey.test.ts new file mode 100644 index 0000000..5e82b77 --- /dev/null +++ b/__tests__/setDeeplAuthKey.test.ts @@ -0,0 +1,50 @@ +import { setDeeplAuthKey } from '../src/sheetsl'; + +enum ButtonSet { + OK_CANCEL, +} + +enum Button { + OK, + CANCEL, +} + +SpreadsheetApp.getUi = jest.fn(() => new MockUi()) as any; +PropertiesService.getUserProperties = jest.fn(() => ({ + setProperty: jest.fn((key: string, value: string) => + console.log(`key: ${key}, value: ${value}`) + ), +})) as any; + +class MockUi { + ButtonSet: ButtonSet; + Button: Button; + constructor() { + this.ButtonSet = ButtonSet.OK_CANCEL; + this.Button = Button.OK; + } + prompt(message: string, buttonset: ButtonSet) { + return new MockPromptResponse(message, buttonset); + } + alert(message: string) { + console.log(message); + } +} + +class MockPromptResponse { + responseText: string; + buttonset: ButtonSet; + constructor(message: string, buttonset: ButtonSet) { + this.responseText = message; + this.buttonset = buttonset; + } + getResponseText() { + return this.responseText; + } + getSelectedButton = jest + .fn() + .mockReturnValueOnce(Button.OK) + .mockReturnValueOnce(Button.CANCEL) + .mockReturnValueOnce(undefined) + .mockReturnValue(Button.OK); +} From 0030afc52fe1ec028e7c83452bf9f39f7a864bdf Mon Sep 17 00:00:00 2001 From: ttsukagoshi Date: Sun, 21 May 2023 00:27:49 +0900 Subject: [PATCH 3/7] Create test file for setDeeplAuthKey --- __tests__/setDeeplAuthKey.test.ts | 50 +++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 __tests__/setDeeplAuthKey.test.ts diff --git a/__tests__/setDeeplAuthKey.test.ts b/__tests__/setDeeplAuthKey.test.ts new file mode 100644 index 0000000..5e82b77 --- /dev/null +++ b/__tests__/setDeeplAuthKey.test.ts @@ -0,0 +1,50 @@ +import { setDeeplAuthKey } from '../src/sheetsl'; + +enum ButtonSet { + OK_CANCEL, +} + +enum Button { + OK, + CANCEL, +} + +SpreadsheetApp.getUi = jest.fn(() => new MockUi()) as any; +PropertiesService.getUserProperties = jest.fn(() => ({ + setProperty: jest.fn((key: string, value: string) => + console.log(`key: ${key}, value: ${value}`) + ), +})) as any; + +class MockUi { + ButtonSet: ButtonSet; + Button: Button; + constructor() { + this.ButtonSet = ButtonSet.OK_CANCEL; + this.Button = Button.OK; + } + prompt(message: string, buttonset: ButtonSet) { + return new MockPromptResponse(message, buttonset); + } + alert(message: string) { + console.log(message); + } +} + +class MockPromptResponse { + responseText: string; + buttonset: ButtonSet; + constructor(message: string, buttonset: ButtonSet) { + this.responseText = message; + this.buttonset = buttonset; + } + getResponseText() { + return this.responseText; + } + getSelectedButton = jest + .fn() + .mockReturnValueOnce(Button.OK) + .mockReturnValueOnce(Button.CANCEL) + .mockReturnValueOnce(undefined) + .mockReturnValue(Button.OK); +} From c5611d53f28e2ec276f4b36b35957866426d678f Mon Sep 17 00:00:00 2001 From: ttsukagoshi Date: Sun, 4 Jun 2023 01:25:17 +0900 Subject: [PATCH 4/7] Merge branch 'test-setDeeplAuthKey' of https://github.com/ttsukagoshi/sheetsL into test-setDeeplAuthKey From f82e65573fec9f3a11d0ecf021fdea828f0e3d07 Mon Sep 17 00:00:00 2001 From: ttsukagoshi Date: Sun, 4 Jun 2023 02:53:09 +0900 Subject: [PATCH 5/7] Remove irrelevant console.log --- __tests__/onInstallonOpen.test.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/__tests__/onInstallonOpen.test.ts b/__tests__/onInstallonOpen.test.ts index c0782c8..4ef62a3 100644 --- a/__tests__/onInstallonOpen.test.ts +++ b/__tests__/onInstallonOpen.test.ts @@ -50,9 +50,7 @@ class MockUi { this.isAddonMenu = true; return this; } - addToUi(): void { - console.log(JSON.stringify(ADDON_MENU)); - } + addToUi(): void {} createAddonMenu(): this { this.isAddonMenu = true; return this; From a9dea481ec168b074c35d0115ee3b8d90be1a8ea Mon Sep 17 00:00:00 2001 From: ttsukagoshi Date: Sun, 4 Jun 2023 02:54:06 +0900 Subject: [PATCH 6/7] Define verifyAuthKeyPrompt for testing setDeeplAuthKey --- src/sheetsl.ts | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/src/sheetsl.ts b/src/sheetsl.ts index 661db30..e6204aa 100644 --- a/src/sheetsl.ts +++ b/src/sheetsl.ts @@ -96,17 +96,7 @@ export function setDeeplAuthKey(): void { 'Enter your DeepL API Authentication Key', ui.ButtonSet.OK_CANCEL ); - if (promptResponse.getSelectedButton() !== ui.Button.OK) { - throw new Error( - `[${ADDON_NAME}] Canceled: Setting of DeepL Authentication Key has been canceled.` - ); - } - const apiKey = promptResponse.getResponseText(); - if (!apiKey || apiKey === '') { - throw new Error( - `[${ADDON_NAME}] You must enter a valid DeepL API Authentication Key.` - ); - } + const apiKey = verifyAuthKeyPrompt(promptResponse, ui).getResponseText(); PropertiesService.getUserProperties().setProperty( UP_KEY_DEEPL_API_KEY, apiKey @@ -120,6 +110,32 @@ export function setDeeplAuthKey(): void { } } +/** + * Verify the prompt response in setDeeplAuthKey and return an error + * if the prompt is canceled or if an invalid DeepL API Authentication Key + * was entered. + * @param promptResponse Response object for the user prompt in setDeeplAuthKey + * to enter the user's DeepL API Authentication Key. + * @returns The entered prompt response object. + */ +export function verifyAuthKeyPrompt( + promptResponse: GoogleAppsScript.Base.PromptResponse, + ui: GoogleAppsScript.Base.Ui +): GoogleAppsScript.Base.PromptResponse { + if (promptResponse.getSelectedButton() !== ui.Button.OK) { + throw new Error( + `[${ADDON_NAME}] Canceled: Setting of DeepL Authentication Key has been canceled.` + ); + } + const apiKey = promptResponse.getResponseText(); + if (!apiKey || apiKey === '') { + throw new Error( + `[${ADDON_NAME}] You must enter a valid DeepL API Authentication Key.` + ); + } + return promptResponse; +} + /** * Delete the stored DeepL API authentication key in user property. */ From c7f272f328b029ce5223e8ed76b1cf7ec23c1c8b Mon Sep 17 00:00:00 2001 From: ttsukagoshi Date: Sun, 4 Jun 2023 02:54:27 +0900 Subject: [PATCH 7/7] Add test for verifyAuthKeyPrompt --- __tests__/setDeeplAuthKey.test.ts | 50 ------------- __tests__/verifyAuthKeyPrompt.test.ts | 100 ++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 50 deletions(-) delete mode 100644 __tests__/setDeeplAuthKey.test.ts create mode 100644 __tests__/verifyAuthKeyPrompt.test.ts diff --git a/__tests__/setDeeplAuthKey.test.ts b/__tests__/setDeeplAuthKey.test.ts deleted file mode 100644 index 5e82b77..0000000 --- a/__tests__/setDeeplAuthKey.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { setDeeplAuthKey } from '../src/sheetsl'; - -enum ButtonSet { - OK_CANCEL, -} - -enum Button { - OK, - CANCEL, -} - -SpreadsheetApp.getUi = jest.fn(() => new MockUi()) as any; -PropertiesService.getUserProperties = jest.fn(() => ({ - setProperty: jest.fn((key: string, value: string) => - console.log(`key: ${key}, value: ${value}`) - ), -})) as any; - -class MockUi { - ButtonSet: ButtonSet; - Button: Button; - constructor() { - this.ButtonSet = ButtonSet.OK_CANCEL; - this.Button = Button.OK; - } - prompt(message: string, buttonset: ButtonSet) { - return new MockPromptResponse(message, buttonset); - } - alert(message: string) { - console.log(message); - } -} - -class MockPromptResponse { - responseText: string; - buttonset: ButtonSet; - constructor(message: string, buttonset: ButtonSet) { - this.responseText = message; - this.buttonset = buttonset; - } - getResponseText() { - return this.responseText; - } - getSelectedButton = jest - .fn() - .mockReturnValueOnce(Button.OK) - .mockReturnValueOnce(Button.CANCEL) - .mockReturnValueOnce(undefined) - .mockReturnValue(Button.OK); -} diff --git a/__tests__/verifyAuthKeyPrompt.test.ts b/__tests__/verifyAuthKeyPrompt.test.ts new file mode 100644 index 0000000..dbbc441 --- /dev/null +++ b/__tests__/verifyAuthKeyPrompt.test.ts @@ -0,0 +1,100 @@ +import { verifyAuthKeyPrompt } from '../src/sheetsl'; + +const verifyAuthKeyPromptSuccessPatterns = [ + { + testName: 'Success', + input: { + promptResponse: { + getSelectedButton: () => 'ok', + getResponseText: () => 'ThisIsAnApiAuthKey:fx', + }, + ui: { + Button: { + OK: 'ok', // Don't change this value. + }, + }, + }, + expectedOutput: { + getSelectedButton: () => 'ok', + getResponseText: () => 'ThisIsAnApiAuthKey:fx', + }, + }, +] as any[]; + +const verifyAuthKeyPromptErrorPatterns = [ + { + testName: 'Error: canceled auth key setting', + input: { + promptResponse: { + getSelectedButton: () => 'canceled', + getResponseText: () => 'ThisIsAnApiAuthKey:fx', + }, + ui: { + Button: { + OK: 'ok', // Don't change this value. + }, + }, + }, + expectedErrorMessage: + '[SheetsL] Canceled: Setting of DeepL Authentication Key has been canceled.', + }, + { + testName: 'Error: empty auth key', + input: { + promptResponse: { + getSelectedButton: () => 'ok', + getResponseText: () => '', + }, + ui: { + Button: { + OK: 'ok', // Don't change this value. + }, + }, + }, + expectedErrorMessage: + '[SheetsL] You must enter a valid DeepL API Authentication Key.', + }, + { + testName: 'Error: auth key is null', + input: { + promptResponse: { + getSelectedButton: () => 'ok', + getResponseText: () => null, + }, + ui: { + Button: { + OK: 'ok', // Don't change this value. + }, + }, + }, + expectedErrorMessage: + '[SheetsL] You must enter a valid DeepL API Authentication Key.', + }, +] as any[]; + +describe.each(verifyAuthKeyPromptSuccessPatterns)( + 'verifyAuthKeyPrompt Test: success patterns', + ({ testName, input, expectedOutput }) => { + test(`${testName}: getSelectedButton`, () => { + expect( + verifyAuthKeyPrompt(input.promptResponse, input.ui).getSelectedButton() + ).toBe(expectedOutput.getSelectedButton()); + }); + test(`${testName}: getResponseText`, () => { + expect( + verifyAuthKeyPrompt(input.promptResponse, input.ui).getResponseText() + ).toBe(expectedOutput.getResponseText()); + }); + } +); + +describe.each(verifyAuthKeyPromptErrorPatterns)( + 'verifyAuthKeyPrompt Test: error patterns', + ({ testName, input, expectedErrorMessage }) => { + test(testName, () => { + expect(() => { + verifyAuthKeyPrompt(input.promptResponse, input.ui); + }).toThrowError(new Error(expectedErrorMessage)); + }); + } +);