food-runner
v3.0.1
Published
Tools for building web apps inside of browser extensions
Downloads
6
Readme
Food Runner
Tools for building web apps inside of browser extensions
Introduction
Food Runner provides solutions for a lot of thorny problems you might run into while developing web apps that are designed to work inside of browser extensions.
Food Runner offers the following features:
- Tools for building and running tests inside a real browser, instead of running against mocks in a server like Node.js
- An RPC-like interface to the browser's message-passing systems,
so you can express inter-context communications more easily.
Connect to your extension's background page from:
- Your extension pages
- Extension pages from a different extension
- A regular web page on any website
- Utilities for dealing with raw binary data easily and efficiently,
including:
- Utility functions for creating, transforming, and comparing buffers
- Encoding and decoding buffers using base 64
- Serialization and deserialization using protocol buffers
- Tools for defining custom protocol handlers
- Utility functions for:
- persistent browser storage
- iterators
- eg, call chaining like map, filter
- both sync and async friendly!
- arrays
- promises
- errors
Wait, what? What's a food runner?
In the restaurant industry, a food runner is the person who brings food from the kitchen to the table. They're a kind of communication channel between a restaurant's guests and its operators.
It seemed like a good metaphor for a piece of software whose main job is to facilitate communication between front-end and back-end pages in a browser extension.
Getting Started
Install the package using your favorite JavaScript package manager using the package name:
food-runner
Creating a service
On your extension's background page:
import { server } from 'food-runner/src/comlink.js';
export class TestService {
/**
* @param {string} name
* @returns {Promise.<string>}
*/
async greet(name) {
return 'hello, ' + name;
}
}
server.internalService = new TestService();
server.start();
FoodRunner's service system is based on (a heavily modified version of) the powerful Comlink library. Tragically, Comlink by itself won't work inside of browser extensions, but FoodRunner extends Comlink to work just as naturally inside browser extensions as anywhere else.
Using a service
On your extension's application page:
import { connect } from 'food-runner/src/comlink.js';
const service = /** @type {TestService} */ await connect();
const greeting = await bg.greet('bob');
// greeting should be 'hello, bob'
Using a service from a different extension
Let's assume the server extension's id is server
,
and that extension is running the background page:
import { server } from 'food-runner/src/comlink.js';
export class TestService {
/**
* @param {string} name
* @returns {Promise.<string>}
*/
async greet(name) {
return 'hello, ' + name;
}
}
server.externalService = new TestService();
server.start();
Note that we made the service external this time by assigning it to server.externalService
.
Let's assume the client extension's id is client
,
running an extension page:
import { connect } from 'food-runner/src/comlink.js';
const service = /** @type {TestService} */ await connect('server');
const greeting = await bg.greet('client');
// greeting should be 'hello, client'
This time, we supplied an argument to connect()
with the id of the server extension, server
.
Running tests using services
FoodRunner provides tools for building your tests into browser extensions that you can temporarily load into your browser.
To use the build tools, add the food-runner-build
package to your project in the devDependencies
section.
The FoodRunner build tools use Rollup to generate HTML pages with the
Mocha test runner that you can run in your browser.
To build your tests, run a script like the following in your JavaScript build system (eg, Node.js):
import { collectTestFiles, buildTestExtension } from 'food-runner-build';
(async () => {
await buildTestExtension(
"my-extension-test@cuchaz",
"My Extension Test",
'build/extensions/test',
{
testFiles: await collectTestFiles('test/tests'),
bgScript: 'test/bg.js'
}
);
})();
This will build your extension into the build/extensions/test
folder and give it the id my-extension-test@cuchaz
.
collectTestFiles()
will collect all the .js
files you have in the test/tests
folder and add them to
the extension build, and the test runner.
The background script in bgScript
can be the real actual background script from your extension, or it can be a special
background script just for testing.
The tests folder should contain JavaScript files that look like Mocha tests:
import { expect } from 'chai';
import { formatErrors } from 'food-runner/testlib/errors.js';
describe("my tests", function() {
it("works", function() {
expect(5).equal(5);
});
});
You can use any assertion library you like, but the describe
and it
test scaffolding functions
are already defined by Mocha.
More examples
For more examples, see the extensive test suite.
Documentation
This is a very new project. Documentation practically non-existent at the moment.
The source code itself has many JSDoc comments, and the Getting Started section above has some simple examples. That's about it so far.
If/when this project gets more attention, the documention will be improved.
License
Copyright (C) 2024 Cuchaz Interactive, LLC and contributors (see AUTHORS.md)
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.