DEV Community

Weather Clock Dash
Weather Clock Dash

Posted on

How to Test Firefox Extensions Without Publishing: Local Development Tips

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:

  1. Open Firefox and go to about:debugging
  2. Click This Firefox in the left sidebar
  3. Click Load Temporary Add-on...
  4. 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
Enter fullscreen mode Exit fullscreen mode
{
  "scripts": {
    "dev": "web-ext run --source-dir .",
    "build": "web-ext build --source-dir . --artifacts-dir dist"
  }
}
Enter fullscreen mode Exit fullscreen mode

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:

  1. Go to about:debugging#/runtime/this-firefox
  2. Click Inspect next to your extension
  3. 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)
Enter fullscreen mode Exit fullscreen mode

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 &
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 };
Enter fullscreen mode Exit fullscreen mode

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');
});
Enter fullscreen mode Exit fullscreen mode

web-ext lint

Catch issues before submitting to AMO:

npx web-ext lint --source-dir .
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)