From daffa0377f242ed7470fc273cab3416a4deac2d2 Mon Sep 17 00:00:00 2001 From: Jack Steam Date: Mon, 7 Dec 2020 15:56:41 -0600 Subject: [PATCH] [tests] update tests for frameId --- src/ChromeMessageError.ts | 23 ++++++++++++++++ src/scope.ts | 11 ++++++-- src/send.ts | 17 +++++++----- tests/units/send-async.test.ts | 38 ++++++++++++++++++++++++-- tests/units/send-one-way.test.ts | 47 ++++++++++++++++++++++++++------ 5 files changed, 115 insertions(+), 21 deletions(-) create mode 100644 src/ChromeMessageError.ts diff --git a/src/ChromeMessageError.ts b/src/ChromeMessageError.ts new file mode 100644 index 0000000..e28545a --- /dev/null +++ b/src/ChromeMessageError.ts @@ -0,0 +1,23 @@ +import { CoreMessage, CoreResponse } from './types' + +export class ChromeMessageError extends Error { + coreMessage: CoreMessage | null + coreResponse: CoreResponse | null + + constructor({ + coreMessage = null, + coreResponse = null, + message = chrome.runtime?.lastError?.message || + coreResponse?.payload.greeting || + 'chrome.runtime.lastError is undefined', + }: { + coreMessage?: CoreMessage | null + coreResponse?: CoreResponse | null + message?: string + }) { + super(message) + + this.coreMessage = coreMessage + this.coreResponse = coreResponse + } +} diff --git a/src/scope.ts b/src/scope.ts index 5624f8c..b6c89b2 100644 --- a/src/scope.ts +++ b/src/scope.ts @@ -121,11 +121,18 @@ export function getScope(scope: string) { if (typeof _options.tabId === 'number') { tabId = _options.tabId } + let frameId: number | undefined + if (typeof _options.frameId === 'number') { + frameId = _options.frameId + } if (async) { - return send({ greeting, data }, { async, tabId }) + return send( + { greeting, data }, + { async, tabId, frameId }, + ) } else { - return send({ greeting, data }, { tabId }) + return send({ greeting, data }, { tabId, frameId }) } } diff --git a/src/send.ts b/src/send.ts index d8c0b79..f021827 100644 --- a/src/send.ts +++ b/src/send.ts @@ -1,3 +1,4 @@ +import { ChromeMessageError } from './ChromeMessageError' import { CoreMessage, CoreResponse, SendOptions } from './types' export const scopeSend = (scope: string) => ( @@ -21,7 +22,7 @@ export const scopeSend = (scope: string) => ( if (lastError && lastError.includes(noResponse)) { resolve() } else { - reject({ message: lastError }) + reject(new ChromeMessageError({ coreMessage })) } } else { if (response && !response.success) { @@ -53,13 +54,15 @@ export const scopeAsyncSend = (scope: string) => ( scope, } - const callback = (coreResponse: CoreResponse) => { - if (chrome.runtime.lastError) { - reject(chrome.runtime.lastError) - } else if (coreResponse.success === false) { - reject(new Error(coreResponse.payload.greeting)) + const callback = (coreResponse: CoreResponse | null) => { + if ( + chrome.runtime.lastError || + coreResponse === null || + !coreResponse.success + ) { + reject(new ChromeMessageError({ coreMessage, coreResponse })) } else { - resolve(coreResponse.payload) + resolve(coreResponse!.payload) } } diff --git a/tests/units/send-async.test.ts b/tests/units/send-async.test.ts index 2ddef6f..9fa3a5a 100644 --- a/tests/units/send-async.test.ts +++ b/tests/units/send-async.test.ts @@ -1,4 +1,5 @@ import { chrome } from 'jest-chrome' +import { ChromeMessageError } from '../../src/ChromeMessageError' import { getScope } from '../../src/scope' import { CoreMessage, CoreResponse } from '../../src/types' @@ -52,6 +53,30 @@ test('sends async CoreMessage to tab', () => { ) }) +test('sends async CoreMessage to frame', () => { + const payload = { greeting: 'hello' } + const tabId = 1234 + const frameId = 5678 + + const coreMessage: CoreMessage = { + async: true, + payload, + scope, + tabId, + } + + messages.send(payload, { tabId, frameId, async: true }) + + expect(chrome.tabs.sendMessage).toBeCalledWith( + tabId, + coreMessage, + { frameId }, + expect.any(Function), + ) + + expect(chrome.runtime.sendMessage).not.toBeCalled() +}) + test('resolves with response', async () => { const message = { greeting: 'hello' } @@ -73,7 +98,7 @@ test('resolves with response', async () => { }) test('rejects if success === false', async () => { - expect.assertions(2) + expect.assertions(4) const message = { greeting: 'hello' } const response = { @@ -93,13 +118,19 @@ test('rejects if success === false', async () => { try { await messages.send(message, { async: true }) } catch (error) { - expect(error).toBeInstanceOf(Error) + expect(error).toBeInstanceOf(ChromeMessageError) expect(error.message).toBe(response.greeting) + expect(error.coreResponse).toBe(coreResponse) + expect(error.coreMessage).toMatchObject({ + async: true, + payload: message, + scope, + }) } }) test('rejects if runtime.lastError', async () => { - expect.assertions(2) + expect.assertions(3) const message = { greeting: 'hello' } lastErrorMessage = 'should reject' @@ -109,6 +140,7 @@ test('rejects if runtime.lastError', async () => { await messages.send(message, { async: true }) } catch (error) { expect(lastErrorSpy).toBeCalled() + expect(error).toBeInstanceOf(ChromeMessageError) expect(error.message).toBe(lastErrorMessage) } }) diff --git a/tests/units/send-one-way.test.ts b/tests/units/send-one-way.test.ts index ba269db..0b592da 100644 --- a/tests/units/send-one-way.test.ts +++ b/tests/units/send-one-way.test.ts @@ -1,4 +1,5 @@ import { chrome } from 'jest-chrome' +import { ChromeMessageError } from '../../src/ChromeMessageError' import { getScope } from '../../src/scope' import { CoreMessage } from '../../src/types' @@ -42,7 +43,7 @@ test('calls runtime.sendMessage if no target', () => { expect(chrome.tabs.sendMessage).not.toBeCalled() }) -test('calls tabs.sendMessage if target is number', () => { +test('calls tabs.sendMessage if tabId is given', () => { const message = { greeting: 'hello' } const tabId = 1234 @@ -52,6 +53,30 @@ test('calls tabs.sendMessage if target is number', () => { expect(chrome.runtime.sendMessage).not.toBeCalled() }) +test('calls tabs.sendMessage with frameId if frameId is given', () => { + const payload = { greeting: 'hello' } + const tabId = 1234 + const frameId = 5678 + + const coreMessage: CoreMessage = { + async: false, + tabId, + payload, + scope, + } + + messages.send(payload, { tabId, frameId }) + + expect(chrome.tabs.sendMessage).toBeCalledWith( + tabId, + coreMessage, + { frameId }, + expect.any(Function), + ) + + expect(chrome.runtime.sendMessage).not.toBeCalled() +}) + test('creates one-way coreMessage', () => { const message = { greeting: 'hello' } @@ -70,19 +95,23 @@ test('creates one-way coreMessage', () => { ) }) -// TODO: unskip once last error implemented -test.skip('rejects if runtime.lastError', async () => { - expect.assertions(1) +test('rejects if runtime.lastError', async () => { + expect.assertions(2) const message = { greeting: 'hello' } - const errorMessage = 'should not resolve' - // chrome.runtime.sendMessage.setLastError(errorMessage) + const lastError = { message: 'should not resolve' } + chrome.runtime.lastError = lastError - const result = messages.send(message) + chrome.runtime.sendMessage.mockImplementation( + (m: any, sendResponse?: (respond: any) => void) => { + sendResponse?.({}) + }, + ) try { - await result + await messages.send(message) } catch (error) { - expect(error.message).toBe(errorMessage) + expect(error).toBeInstanceOf(ChromeMessageError) + expect(error.message).toBe(lastError.message) } })