How to Test Firefox Extensions Without Publishing: Local Development Tips
Publishing to AMO every time you want to test a change is slow and painful. Here's the full toolkit for local development.
Temporary Add-on Loading
The fastest way to load your extension:
- Open Firefox and go to
about:debugging - Click This Firefox in the left sidebar
- Click Load Temporary Add-on...
- Navigate to your extension folder and select
manifest.json
The extension is loaded immediately. It disappears when Firefox restarts, but stays active during the session.
Auto-Reload on File Changes
Manually clicking "Reload" in about:debugging is tedious. Use web-ext for auto-reload:
npm install --save-dev web-ext
# Auto-reload on any file change
npx web-ext run --source-dir . --watch
# Or add to package.json scripts
{
"scripts": {
"dev": "web-ext run --source-dir .",
"build": "web-ext build --source-dir . --artifacts-dir dist"
}
}
web-ext opens a new Firefox profile with your extension loaded, and reloads it automatically when you save any file.
Inspecting the Extension's DevTools
Each extension context has its own DevTools:
For new tab page / popup:
- Right-click anywhere on the new tab → Inspect
- Or open DevTools on the popup while it's visible
For background scripts/service workers:
- Go to
about:debugging#/runtime/this-firefox - Click Inspect next to your extension
- This opens a dedicated DevTools window for the background context
Testing storage.sync
Simulate sync changes in DevTools console:
// In the extension's background context DevTools
await browser.storage.sync.set({ theme: 'dark' });
await browser.storage.sync.get(null); // Get all stored values
await browser.storage.sync.clear(); // Clear everything (for fresh testing)
Testing Across Multiple Firefox Profiles
To simulate sync across devices, use two Firefox profiles:
# Create two profiles
firefox --createprofile profile1
firefox --createprofile profile2
# Launch both simultaneously
firefox --profile profile1 &
firefox --profile profile2 &
Log into the same Firefox Account on both, install the extension on both via temporary loading, and watch changes sync.
Debugging the New Tab Override
New tab pages are special — they can't be right-clicked and inspected directly from the tab. Workarounds:
// Option 1: Open the new tab page as a regular page
// Navigate to moz-extension://YOUR-EXTENSION-ID/newtab.html
// Option 2: Log the extension ID
console.log(browser.runtime.id);
// Then navigate to moz-extension://<id>/newtab.html
Or from about:debugging, click Inspect on your extension and look for the new tab URL.
Mock browser.storage for Unit Tests
For unit testing without a real browser:
// mock-browser-storage.js
const storage = {
local: { _data: {} },
sync: { _data: {} },
};
for (const area of ['local', 'sync']) {
storage[area].get = async (keys) => {
if (!keys) return { ...storage[area]._data };
if (typeof keys === 'string') return { [keys]: storage[area]._data[keys] };
const result = {};
for (const key of Object.keys(keys)) {
result[key] = key in storage[area]._data ? storage[area]._data[key] : keys[key];
}
return result;
};
storage[area].set = async (items) => {
Object.assign(storage[area]._data, items);
};
storage[area].clear = async () => {
storage[area]._data = {};
};
}
global.browser = { storage };
Then in your tests:
require('./mock-browser-storage');
const { loadPreferences } = require('./preferences');
test('loads defaults on first run', async () => {
const prefs = await loadPreferences();
expect(prefs.theme).toBe('auto');
expect(prefs.temperatureUnit).toBe('celsius');
});
web-ext lint
Catch issues before submitting to AMO:
npx web-ext lint --source-dir .
This checks:
- Manifest validity
- Deprecated APIs
- Common mistakes
- Permission warnings
Run this before every AMO submission.
Testing the Install/First-Run Flow
To test how your extension behaves on first install:
# Launch with a clean profile every time
npx web-ext run --source-dir . --firefox-profile temp-test --profile-create-if-missing
This creates a fresh profile, so storage is always empty — you see exactly what a new user sees.
Summary
| Task | Tool |
|---|---|
| Quick load | about:debugging temporary add-on |
| Auto-reload dev | web-ext run |
| Production build | web-ext build |
| Linting | web-ext lint |
| Storage debugging | DevTools console |
| Fresh install test | web-ext run --profile-create-if-missing |
The web-ext tool is genuinely excellent — it's the official Mozilla CLI and makes extension development feel like normal web dev with hot reload.
Weather & Clock Dashboard — free Firefox new tab extension. Built and tested using all these techniques.
Top comments (0)