Testing a Chrome extension before shipping it
The test plan I ran on my own Manifest V3 extension before sending it to the Chrome Web Store: permissions, blocking rules, time counting, strict mode, updates and the review checklist.
I recently shipped a small Chrome extension of my own: TimeFence, a website blocker with daily time limits. Most of my working life is spent testing other people’s products, so this was the first release where I wrote the code, the test plan and the readiness decision myself. Here is the plan I used. It applies to most Manifest V3 extensions that block, redirect or count anything.
A browser extension has a different risk profile from a web app. It runs on every page the user opens, it keeps working when no window of its own is visible, and the store reviews it before anyone can install it. A defect does not stay on one screen. It follows the user around the web.
Review the permissions before testing anything else
The manifest is the first thing I test, because it decides what the user is warned about at install time and what the store reviewer asks about. TimeFence asks for storage, declarativeNetRequest, alarms and idle, plus host access to all sites. For each one I wrote down a single sentence: why it is needed and what would break without it.
| Permission | Why it is needed | What I checked |
|---|---|---|
storage | Keeps the site list and today’s minutes | Settings survive a browser restart; nothing is written anywhere else |
declarativeNetRequest | Redirects a blocked site to the block page | Rules are added and removed as the list changes |
alarms | Wakes the extension once a minute to count time | Counting continues after the service worker is shut down |
idle | Stops counting when the user walks away | No minutes are added while the machine is idle or locked |
| Host access to all sites | Needed to redirect any site the user chooses and to see the active tab’s site | No content script reads page content |
Host access to every site produces the most alarming install warning Chrome shows. If a permission cannot be justified in one sentence, I remove it and test again before going further. One fewer permission is one fewer question in review and one fewer reason for a user to hesitate.
Blocking rules: declarativeNetRequest under real conditions
With declarativeNetRequest, the extension hands Chrome a set of rules and Chrome applies them. The extension never sees the request itself. That makes blocking fast, but it also means a wrong rule fails silently. My checks:
- A blocked domain is blocked with and without
www., on subdomains such asm.youtube.com, and over both http and https. - A domain that merely contains the blocked name is not blocked: blocking
x.commust not touchexample.com. - Tabs that are already open on a site get redirected when it becomes blocked, not only new navigations.
- Rules are rebuilt from saved settings after a browser restart and after the extension is reloaded, with no duplicate rule IDs left behind.
- Removing a site from the list unblocks it straight away.
The substring case is the one I would expect to slip through a quick manual pass, so I wrote it down as an explicit check.
Time counting with idle detection and alarms
Daily limits are where most of the logic lives, and where most of my test time went. In Manifest V3 the background script is a service worker that Chrome stops when it is not needed, so nothing can rely on a timer kept in memory. TimeFence wakes on an alarm once a minute, asks the idle API whether the user has been active, and adds a minute to the site in the active tab.
- Leave a limited site open in a background tab: no minutes should count.
- Leave it in the active tab and walk away from the keyboard: counting should stop once the idle threshold passes.
- Lock the screen: no counting.
- Cross midnight with the browser open: the minutes reset and the site unblocks without a restart.
- Use up the limit while on the site: the open tab moves to the block page instead of waiting for the next navigation.
TimeFence keeps the date and schedule logic in plain functions with no Chrome APIs, so most of these cases can run as fast unit tests with a fixed date. The checks in a real browser then confirm the wiring, not the arithmetic.
Strict mode and schedule edge cases
Strict mode prevents removing sites or pausing while a block is active. A lock like this tends to have side doors, so I tried to get round it the way an impatient user would: from the options page, from the toolbar popup, by turning the schedule off, by pausing first and enabling strict mode second. Then the opposite failure: the lock must release on its own when the focus hours end or the limits reset at midnight, or the user is stuck with a list they cannot edit.
Schedules that cross midnight, such as 22:00 to 06:00, need their own cases. The early-morning part belongs to the previous day’s schedule, so a schedule set for Friday night must still block at 01:00 on Saturday.
Updates, uninstall and saved data
An update is a release for users who already have data. The test: install the previous version, add sites and limits, use up some minutes, then load the new version over it. The list, limits and today’s minutes must survive, and settings added in the new version must get sensible defaults instead of breaking the old ones. On uninstall Chrome removes the extension’s local storage, and the TimeFence privacy policy promises exactly that, so the check is to reinstall and expect an empty list.
The store review checklist I used
- Single-purpose statement written, and every feature fits under it.
- Each permission justified in the submission form with the same sentence as in my notes.
- Data-use answers match the code: if nothing is collected, nothing leaves the device, including from the payment code.
- Privacy policy published at a public URL and linked from the listing.
- No remotely hosted code: every script is in the package.
- Screenshots show the current build, and every claim in the description can be checked against it.
The last item is the one I would expect to slip. Listing copy tends to be written early and features change after, so before submitting I read the description line by line against the build. The result is live in the Chrome Web Store, and the same plan will run before every update.
Questions I get asked
How do you test a Manifest V3 extension’s background logic if the service worker can stop at any time?
Keep nothing important in memory. Store state, wake on alarms, and test the cases where the worker has been stopped: after a restart, after an idle period and across midnight. Logic that does not need Chrome APIs can be unit tested on its own with fixed dates.
What does the Chrome Web Store check in review?
Among other things, that the extension has a single clear purpose, that each permission is justified, that the data-use answers and privacy policy match what the code does, and that no code is loaded from a remote server.
Filed under Release readiness and regression.
