|
- import test from 'ava'
- import { spy } from 'sinon'
-
- import { remoteFunction, RpcError, RemoteError } from '../src/webextension-rpc.js'
-
- test.beforeEach(() => {
- // We mock the browser globally. Note we therefore need to test serially to prevent the tests from
- // interfering with each other.
- global.browser = {
- runtime: {
- sendMessage: spy(async () => {}),
- },
- tabs: {
- sendMessage: spy(async () => {}),
- },
- }
- })
-
- test.serial('should create a function', t => {
- const remoteFunc = remoteFunction('remoteFunc', { tabId: 1 })
- t.is(remoteFunc.name, 'remoteFunc_RPC')
- t.is(typeof remoteFunc, 'function')
- })
-
- test.serial('should throw an error when unable to sendMessage', async t => {
- const remoteFunc = remoteFunction('remoteFunc', { tabId: 1 })
- browser.tabs.sendMessage = async () => { throw new Error() }
- await t.throwsAsync(remoteFunc, {
- instanceOf: RpcError,
- message: `Got no response when trying to call 'remoteFunc'. Did you enable RPC in the tab's content script?`,
- })
- })
-
- test.serial('should call the browser.tabs function when tabId is given', async t => {
- const remoteFunc = remoteFunction('remoteFunc', { tabId: 1 })
- try {
- await remoteFunc()
- } catch (e) {}
- console.log(browser.tabs.sendMessage.callCount)
- t.true(browser.tabs.sendMessage.calledOnce)
- t.true(browser.runtime.sendMessage.notCalled)
- })
-
- test.serial('should call the browser.runtime function when tabId is undefined', async t => {
- const remoteFunc = remoteFunction('remoteFunc')
- try {
- await remoteFunc()
- } catch (e) {}
- t.true(browser.tabs.sendMessage.notCalled)
- t.true(browser.runtime.sendMessage.calledOnce)
- })
-
- test.serial('should throw an "interfering listener" error if response is unrecognised', async t => {
- browser.tabs.sendMessage = async () => 'some unexpected return value'
- const remoteFunc = remoteFunction('remoteFunc', { tabId: 1 })
- await t.throwsAsync(remoteFunc, {
- instanceOf: RpcError,
- message: /RPC got a response from an interfering listener/,
- })
- })
-
- test.serial('should throw a "no response" error if response is undefined', async t => {
- // It seems we can get back undefined when the tab is closed before the response is sent.
- // In such cases 'no response' seems a better error message than 'interfering listener'.
- browser.tabs.sendMessage = async () => undefined
- const remoteFunc = remoteFunction('remoteFunc', { tabId: 1 })
- await t.throwsAsync(remoteFunc, {
- instanceOf: RpcError,
- message: /Got no response/,
- })
- })
-
- test.serial('should throw RemoteError if the response contains an error message', async t => {
- browser.tabs.sendMessage = async () => ({
- __RPC_RESPONSE__: '__RPC_RESPONSE__',
- errorMessage: 'Remote function error',
- })
- const remoteFunc = remoteFunction('remoteFunc', { tabId: 1 })
- await t.throwsAsync(remoteFunc, {
- instanceOf: RemoteError,
- message: 'Remote function error',
- })
- })
-
- test.serial('should return the value contained in the response', async t => {
- browser.tabs.sendMessage = async () => ({
- __RPC_RESPONSE__: '__RPC_RESPONSE__',
- returnValue: 'Remote function return value',
- })
- const remoteFunc = remoteFunction('remoteFunc', { tabId: 1 })
- t.is(await remoteFunc(), 'Remote function return value')
- })
-
- // TODO Test behaviour of executing side.
|