From a21948daf6210f67955ae4f98a81e21b8cf9f1f2 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sat, 24 Feb 2024 23:32:39 -0500 Subject: Improve type safety for playwright stuff (#727) --- test/playwright/playwright-util.js | 128 ++++++++++++++++++++----------------- 1 file changed, 71 insertions(+), 57 deletions(-) (limited to 'test/playwright/playwright-util.js') diff --git a/test/playwright/playwright-util.js b/test/playwright/playwright-util.js index 653112c6..1ea2e604 100644 --- a/test/playwright/playwright-util.js +++ b/test/playwright/playwright-util.js @@ -51,32 +51,39 @@ export const test = base.extend({ export const expect = test.expect; -export const mockModelFieldNames = [ - 'Word', - 'Reading', - 'Audio', - 'Sentence' -]; - -/** @type {{[key: string]: string|undefined}} */ -export const mockModelFieldsToAnkiValues = { - Word: '{expression}', - Reading: '{furigana-plain}', - Sentence: '{clipboard-text}', - Audio: '{audio}' -}; +/** + * @returns {Map} + */ +export function getMockModelFields() { + return new Map([ + ['Word', '{expression}'], + ['Reading', '{furigana-plain}'], + ['Sentence', '{clipboard-text}'], + ['Audio', '{audio}'] + ]); +} /** * @param {import('playwright').Route} route * @returns {Promise} */ export async function mockAnkiRouteHandler(route) { - const reqBody = route.request().postDataJSON(); - const respBody = ankiRouteResponses[reqBody.action]; - if (!respBody) { - return route.abort(); + try { + /** @type {unknown} */ + const requestJson = route.request().postDataJSON(); + if (typeof requestJson !== 'object' || requestJson === null) { + throw new Error(`Invalid request type: ${typeof requestJson}`); + } + const body = getResponseBody(/** @type {import('core').SerializableObject} */ (requestJson).action); + const responseJson = { + status: 200, + contentType: 'text/json', + body: JSON.stringify(body) + }; + await route.fulfill(responseJson); + } catch { + return await route.abort(); } - await route.fulfill(respBody); } /** @@ -88,45 +95,52 @@ export const writeToClipboardFromPage = async (page, text) => { await page.evaluate(`navigator.clipboard.writeText('${text}')`); }; -export const expectedAddNoteBody = { - version: 2, - action: 'addNote', - params: { - note: { - fields: { - Word: '読む', - Reading: '読[よ]む', - Audio: '[sound:mock_audio.mp3]', - Sentence: '読むの例文' - }, - tags: ['yomitan'], - deckName: 'Mock Deck', - modelName: 'Mock Model', - options: { - allowDuplicate: false, - duplicateScope: 'collection', - duplicateScopeOptions: { - deckName: null, - checkChildren: false, - checkAllModels: false +/** + * @returns {Record} + */ +export function getExpectedAddNoteBody() { + return { + version: 2, + action: 'addNote', + params: { + note: { + fields: { + Word: '読む', + Reading: '読[よ]む', + Audio: '[sound:mock_audio.mp3]', + Sentence: '読むの例文' + }, + tags: ['yomitan'], + deckName: 'Mock Deck', + modelName: 'Mock Model', + options: { + allowDuplicate: false, + duplicateScope: 'collection', + duplicateScopeOptions: { + deckName: null, + checkChildren: false, + checkAllModels: false + } } } } - } -}; - -const baseAnkiResp = { - status: 200, - contentType: 'text/json' -}; + }; +} -/** @type {{[key: string]: import('core').SerializableObject}} */ -const ankiRouteResponses = { - version: Object.assign({body: JSON.stringify(6)}, baseAnkiResp), - deckNames: Object.assign({body: JSON.stringify(['Mock Deck'])}, baseAnkiResp), - modelNames: Object.assign({body: JSON.stringify(['Mock Model'])}, baseAnkiResp), - modelFieldNames: Object.assign({body: JSON.stringify(mockModelFieldNames)}, baseAnkiResp), - canAddNotes: Object.assign({body: JSON.stringify([true, true])}, baseAnkiResp), - storeMediaFile: Object.assign({body: JSON.stringify('mock_audio.mp3')}, baseAnkiResp), - addNote: Object.assign({body: JSON.stringify(102312488912)}, baseAnkiResp) -}; +/** + * @param {unknown} action + * @returns {unknown} + * @throws {Error} + */ +function getResponseBody(action) { + switch (action) { + case 'version': return 6; + case 'deckNames': return ['Mock Deck']; + case 'modelNames': return ['Mock Model']; + case 'modelFieldNames': return [...getMockModelFields().keys()]; + case 'canAddNotes': return [true, true]; + case 'storeMediaFile': return 'mock_audio.mp3'; + case 'addNote': return 102312488912; + default: throw new Error(`Unknown action: ${action}`); + } +} -- cgit v1.2.3