browser-extension-manager 1.3.49 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -70
- package/dist/background.js +6 -1
- package/dist/build.js +5 -7
- package/dist/cli.js +1 -0
- package/dist/commands/install.js +1 -1
- package/dist/commands/test.js +55 -0
- package/dist/content.js +4 -0
- package/dist/defaults/CHANGELOG.md +15 -0
- package/dist/defaults/CLAUDE.md +82 -6
- package/dist/defaults/docs/README.md +17 -0
- package/dist/defaults/test/README.md +32 -0
- package/dist/defaults/test/_init.js +10 -0
- package/dist/gulp/tasks/defaults.js +15 -2
- package/dist/offscreen.js +4 -0
- package/dist/options.js +4 -0
- package/dist/page.js +4 -0
- package/dist/popup.js +4 -0
- package/dist/sidepanel.js +4 -0
- package/dist/test/assert.js +120 -0
- package/dist/test/fixtures/consumer-extension/dist/background.js +15 -0
- package/dist/test/fixtures/consumer-extension/dist/manifest.json +20 -0
- package/dist/test/fixtures/consumer-extension/dist/options.html +10 -0
- package/dist/test/fixtures/consumer-extension/dist/popup.html +11 -0
- package/dist/test/harness/extension/background.js +26 -0
- package/dist/test/harness/extension/manifest.json +27 -0
- package/dist/test/harness/extension/options.html +12 -0
- package/dist/test/harness/extension/popup.html +12 -0
- package/dist/test/harness/extension/sidepanel.html +12 -0
- package/dist/test/index.js +63 -0
- package/dist/test/runner.js +469 -0
- package/dist/test/runners/boot.js +201 -0
- package/dist/test/runners/chromium.js +399 -0
- package/dist/test/suites/background/messaging.test.js +42 -0
- package/dist/test/suites/background/storage.test.js +44 -0
- package/dist/test/suites/background/sw-context.test.js +47 -0
- package/dist/test/suites/boot/extension-loads.test.js +56 -0
- package/dist/test/suites/build/affiliatizer.test.js +63 -0
- package/dist/test/suites/build/cli.test.js +123 -0
- package/dist/test/suites/build/expect.test.js +47 -0
- package/dist/test/suites/build/exports.test.js +52 -0
- package/dist/test/suites/build/extension-fallback.test.js +41 -0
- package/dist/test/suites/build/logger-lite.test.js +59 -0
- package/dist/test/suites/build/manager.test.js +184 -0
- package/dist/test/suites/build/mode-helpers.test.js +135 -0
- package/dist/test/suites/view/options-and-sidepanel.test.js +14 -0
- package/dist/test/suites/view/popup-context.test.js +51 -0
- package/dist/test/suites/view/sidepanel.test.js +14 -0
- package/dist/utils/mode-helpers.js +117 -0
- package/package.json +7 -4
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// View-layer smoke for the popup page. Verifies the test code is executing
|
|
2
|
+
// inside a tab that has loaded popup.html (chrome-extension://<id>/popup.html),
|
|
3
|
+
// has DOM + chrome.* APIs, and matches the harness's expected page shape.
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
type: 'suite',
|
|
7
|
+
layer: 'view',
|
|
8
|
+
context: 'popup',
|
|
9
|
+
description: 'view/popup — DOM + chrome surface',
|
|
10
|
+
tests: [
|
|
11
|
+
{
|
|
12
|
+
name: 'document is present and body has data-bxm-context="popup"',
|
|
13
|
+
run: async (ctx) => {
|
|
14
|
+
ctx.expect(typeof document).toBe('object');
|
|
15
|
+
ctx.expect(document.body.dataset.bxmContext).toBe('popup');
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'page title matches the harness popup.html',
|
|
20
|
+
run: async (ctx) => {
|
|
21
|
+
ctx.expect(document.title).toContain('Popup');
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'chrome.* APIs are exposed in extension-page context',
|
|
26
|
+
run: async (ctx) => {
|
|
27
|
+
ctx.expect(typeof chrome).toBe('object');
|
|
28
|
+
ctx.expect(typeof chrome.runtime).toBe('object');
|
|
29
|
+
ctx.expect(typeof chrome.runtime.id).toBe('string');
|
|
30
|
+
ctx.expect(typeof chrome.storage).toBe('object');
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'window globals (fetch, URL) are available',
|
|
35
|
+
run: async (ctx) => {
|
|
36
|
+
ctx.expect(typeof fetch).toBe('function');
|
|
37
|
+
ctx.expect(typeof URL).toBe('function');
|
|
38
|
+
const u = new URL('https://example.com/path?q=1');
|
|
39
|
+
ctx.expect(u.searchParams.get('q')).toBe('1');
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'popup ↔ background messaging round-trip',
|
|
44
|
+
run: async (ctx) => {
|
|
45
|
+
const reply = await chrome.runtime.sendMessage({ type: 'bxm:test:ping' });
|
|
46
|
+
ctx.expect(reply.pong).toBe(true);
|
|
47
|
+
ctx.expect(typeof reply.ts).toBe('number');
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// View-layer test for the sidepanel context. Most consumers of BXM use
|
|
2
|
+
// chrome.sidePanel for the Chrome 114+ UI panel surface — verify that
|
|
3
|
+
// the test harness can target it just like popup/options.
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
layer: 'view',
|
|
7
|
+
context: 'sidepanel',
|
|
8
|
+
description: 'view/sidepanel — DOM + context attribute',
|
|
9
|
+
run: async (ctx) => {
|
|
10
|
+
ctx.expect(document.body.dataset.bxmContext).toBe('sidepanel');
|
|
11
|
+
ctx.expect(document.title).toContain('Side Panel');
|
|
12
|
+
ctx.expect(typeof chrome.runtime.id).toBe('string');
|
|
13
|
+
},
|
|
14
|
+
};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// Runtime mode helpers (BEM/EM/UJM-pattern), shared across BXM's eight context Managers
|
|
2
|
+
// (build / background / popup / options / content / sidepanel / page / offscreen).
|
|
3
|
+
//
|
|
4
|
+
// `getEnvironment()` is the SINGLE SOURCE OF TRUTH: it is the ONLY function that reads the
|
|
5
|
+
// raw signals (BXM_TEST_MODE / manifest.update_url / BXM_BUILD_MODE / NODE_ENV /
|
|
6
|
+
// config.bxm.environment) and resolves them to exactly ONE of three mutually-exclusive
|
|
7
|
+
// values. The three is*() checks DERIVE from it — they never read raw signals themselves,
|
|
8
|
+
// so they can never disagree with getEnvironment().
|
|
9
|
+
//
|
|
10
|
+
// isDevelopment() — `getEnvironment() === 'development'`: running unpacked from disk (an
|
|
11
|
+
// unpacked extension via chrome://extensions or a dev build), and NOT
|
|
12
|
+
// testing.
|
|
13
|
+
// isTesting() — `getEnvironment() === 'testing'`: BXM's test framework is running this
|
|
14
|
+
// process (BXM_TEST_MODE=true). TAKES PRECEDENCE — a test run is not dev.
|
|
15
|
+
// isProduction() — `getEnvironment() === 'production'`: running from a packed .crx /
|
|
16
|
+
// store-installed extension, and NOT testing. A real positive check —
|
|
17
|
+
// NOT `!isDevelopment()`.
|
|
18
|
+
//
|
|
19
|
+
// To gate "anything non-production" use `!isProduction()` or `isDevelopment() ||
|
|
20
|
+
// isTesting()` intentionally — never assume two values.
|
|
21
|
+
//
|
|
22
|
+
// Context caveat: in build-time Node (gulp / CLI), `chrome` is undefined. getEnvironment()
|
|
23
|
+
// detects via `typeof chrome` so the same code works in every context. Browser detection
|
|
24
|
+
// uses `chrome.runtime.getManifest().update_url` — packed store extensions have one,
|
|
25
|
+
// unpacked ones do not.
|
|
26
|
+
|
|
27
|
+
// getEnvironment() — the SINGLE SOURCE OF TRUTH. Reads every raw signal and resolves to
|
|
28
|
+
// exactly ONE of 'development' | 'testing' | 'production' (mutually exclusive; testing wins).
|
|
29
|
+
// Precedence: testing → production → development.
|
|
30
|
+
function getEnvironment() {
|
|
31
|
+
// 1. Testing wins — set by BXM's test runners / harness, or a testing-baked build.
|
|
32
|
+
// Works in Node (process.env), extension contexts (globalThis set before consumer JS),
|
|
33
|
+
// and config-baked builds (config.bxm.environment === 'testing').
|
|
34
|
+
if (typeof process !== 'undefined' && process.env && process.env.BXM_TEST_MODE === 'true') return 'testing';
|
|
35
|
+
if (typeof globalThis !== 'undefined' && globalThis.BXM_TEST_MODE === true) return 'testing';
|
|
36
|
+
if (this && this.config && this.config.bxm && this.config.bxm.environment === 'testing') return 'testing';
|
|
37
|
+
|
|
38
|
+
// 2. Browser-side: packed/store extensions have `update_url`; unpacked ones do not.
|
|
39
|
+
// This is the authoritative runtime signal in an extension context.
|
|
40
|
+
if (typeof chrome !== 'undefined' && chrome.runtime && typeof chrome.runtime.getManifest === 'function') {
|
|
41
|
+
try {
|
|
42
|
+
return chrome.runtime.getManifest().update_url ? 'production' : 'development';
|
|
43
|
+
} catch (_) { /* fall through to Node/config signals */ }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 3. Node / build-time + config signals.
|
|
47
|
+
if (process.env.BXM_BUILD_MODE === 'true') return 'production';
|
|
48
|
+
if (process.env.NODE_ENV === 'development') return 'development';
|
|
49
|
+
if (this && this.config && this.config.bxm && this.config.bxm.environment === 'development') return 'development';
|
|
50
|
+
if (this && this.config && this.config.bxm && this.config.bxm.environment === 'production') return 'production';
|
|
51
|
+
|
|
52
|
+
// 4. Default: development. BXM's deployed artifacts ALWAYS carry their signal — a packed /
|
|
53
|
+
// store extension has `manifest.update_url`, and build-time Node sets BXM_BUILD_MODE. So
|
|
54
|
+
// reaching here means a bare tooling / unpacked context, where development is the sensible
|
|
55
|
+
// answer. (Contrast BEM/EM, whose deployed RUNTIME can legitimately lack a signal, so they
|
|
56
|
+
// default to production.)
|
|
57
|
+
return 'development';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// The three checks DERIVE from getEnvironment() — they never read raw signals, so they can
|
|
61
|
+
// never disagree with it. isDevelopment() is NOT true in testing; isProduction() is a real
|
|
62
|
+
// positive check (never `!isDevelopment()`).
|
|
63
|
+
function isDevelopment() {
|
|
64
|
+
return getEnvironment.call(this) === 'development';
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function isProduction() {
|
|
68
|
+
return getEnvironment.call(this) === 'production';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function isTesting() {
|
|
72
|
+
return getEnvironment.call(this) === 'testing';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// `getVersion()` — returns the extension's version string.
|
|
76
|
+
// 1. `chrome.runtime.getManifest().version` when running inside an extension context.
|
|
77
|
+
// 2. `<cwd>/package.json#version` for build-time scripts.
|
|
78
|
+
// 3. null when neither resolves.
|
|
79
|
+
function getVersion() {
|
|
80
|
+
if (typeof chrome !== 'undefined' && chrome.runtime && typeof chrome.runtime.getManifest === 'function') {
|
|
81
|
+
try {
|
|
82
|
+
return chrome.runtime.getManifest().version || null;
|
|
83
|
+
} catch (_) { /* fall through */ }
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
const path = require('path');
|
|
87
|
+
const pkg = require(path.join(process.cwd(), 'package.json'));
|
|
88
|
+
return pkg.version || null;
|
|
89
|
+
} catch (_) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Mix the helpers into a Manager constructor's prototype + the constructor itself
|
|
95
|
+
// (so `Manager.isTesting()` works statically too, matching BEM/EM/UJM pattern).
|
|
96
|
+
// getEnvironment() is the SSOT and is attached here too — build.js no longer defines it.
|
|
97
|
+
function attachTo(Manager) {
|
|
98
|
+
Manager.prototype.getEnvironment = getEnvironment;
|
|
99
|
+
Manager.prototype.isDevelopment = isDevelopment;
|
|
100
|
+
Manager.prototype.isProduction = isProduction;
|
|
101
|
+
Manager.prototype.isTesting = isTesting;
|
|
102
|
+
Manager.prototype.getVersion = getVersion;
|
|
103
|
+
Manager.getEnvironment = getEnvironment;
|
|
104
|
+
Manager.isDevelopment = isDevelopment;
|
|
105
|
+
Manager.isProduction = isProduction;
|
|
106
|
+
Manager.isTesting = isTesting;
|
|
107
|
+
Manager.getVersion = getVersion;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
module.exports = {
|
|
111
|
+
attachTo,
|
|
112
|
+
getEnvironment,
|
|
113
|
+
isDevelopment,
|
|
114
|
+
isProduction,
|
|
115
|
+
isTesting,
|
|
116
|
+
getVersion,
|
|
117
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browser-extension-manager",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Browser Extension Manager dependency manager",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"start": "npm run prepare:watch",
|
|
23
23
|
"prepare": "node -e \"require('prepare-package')()\"",
|
|
24
24
|
"prepare:watch": "node -e \"require('prepare-package/watch')()\"",
|
|
25
|
+
"test": "node ./bin/browser-extension-manager test",
|
|
25
26
|
"wm:prod": "npm uninstall web-manager && npm i web-manager@latest",
|
|
26
27
|
"wm:local": "npm uninstall web-manager && npm i ../web-manager"
|
|
27
28
|
},
|
|
@@ -47,7 +48,8 @@
|
|
|
47
48
|
"gulp": "gulp --cwd ./ --gulpfile ./node_modules/browser-extension-manager/dist/gulp/main.js",
|
|
48
49
|
"build": "npx mgr clean && npx mgr setup && BXM_BUILD_MODE=true npm run gulp -- build",
|
|
49
50
|
"publish": "BXM_IS_PUBLISH=true npm run gulp -- publish",
|
|
50
|
-
"release": "npm run build && npm run publish"
|
|
51
|
+
"release": "npm run build && npm run publish",
|
|
52
|
+
"test": "npx mgr test"
|
|
51
53
|
},
|
|
52
54
|
"engines": {
|
|
53
55
|
"node": "22"
|
|
@@ -94,7 +96,7 @@
|
|
|
94
96
|
"node-powertools": "^3.0.0",
|
|
95
97
|
"npm-api": "^1.0.1",
|
|
96
98
|
"sass": "^1.99.0",
|
|
97
|
-
"web-manager": "^4.1.
|
|
99
|
+
"web-manager": "^4.1.42",
|
|
98
100
|
"webpack": "^5.106.2",
|
|
99
101
|
"wonderful-fetch": "^2.0.5",
|
|
100
102
|
"wonderful-version": "^1.3.2",
|
|
@@ -105,6 +107,7 @@
|
|
|
105
107
|
"gulp": "^5.0.1"
|
|
106
108
|
},
|
|
107
109
|
"devDependencies": {
|
|
108
|
-
"prepare-package": "^2.1.0"
|
|
110
|
+
"prepare-package": "^2.1.0",
|
|
111
|
+
"puppeteer": "^24.43.1"
|
|
109
112
|
}
|
|
110
113
|
}
|