Skip to content

Commit 8d03282

Browse files
committed
fix: firefox e2e test
1 parent 9a88d84 commit 8d03282

4 files changed

Lines changed: 151 additions & 121 deletions

File tree

.puppeteerrc.cjs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* @type {import("puppeteer").Configuration}
3+
*/
4+
module.exports = {
5+
chrome: {
6+
skipDownload: false,
7+
},
8+
firefox: {
9+
skipDownload: false,
10+
},
11+
};

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"format": "biome format --write",
2020
"release": "node ./scripts/release.mjs",
2121
"pack": "node ./scripts/pack.mjs",
22+
"run-test-server": "php -S 0.0.0.0:8899 -t tests/simple-server",
2223
"test:e2e": "cross-env NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" npx jest --config ./tests/e2e/jest.config.json"
2324
},
2425
"dependencies": {

tests/e2e/browser.spec.mjs

Lines changed: 101 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,119 @@
11
import {
2+
cleanup,
3+
getBrowserClient,
24
getHeader,
35
getPageValue,
4-
getResponseHeader,
6+
runTest,
57
saveRule,
6-
startUp,
78
testServer,
89
waitTestServer,
910
} from './utils.mjs';
1011

11-
let browser;
12-
1312
beforeAll(async () => {
14-
browser = await startUp('chrome_v3');
13+
await Promise.all([
14+
getBrowserClient('chrome_v3'),
15+
getBrowserClient('firefox_v3'),
16+
]);
1517
console.log('browser ready');
1618
// Check if test server is running
1719
await waitTestServer();
1820
console.log('test server ready');
1921
}, 20000);
2022

2123
afterAll(async () => {
22-
if (browser) {
23-
await browser.popup.close();
24-
await browser.browser.close();
25-
}
26-
});
27-
28-
test('Modify Request Header', async () => {
29-
const key = String(Math.random()).replace('.', '');
30-
31-
const { remove } = await saveRule(browser.popup, {
32-
name: 'test modify request header',
33-
ruleType: 'modifySendHeader',
34-
pattern: '^' + testServer,
35-
matchType: 'regexp',
36-
isFunction: false,
37-
enable: true,
38-
action: {
39-
name: 'X-Test-Header',
40-
value: key,
41-
},
42-
});
43-
44-
const header = await getHeader(browser.browser);
45-
46-
expect(header['X_TEST_HEADER']).toBe(key);
47-
48-
await remove();
49-
});
50-
51-
test('Disable rule', async () => {
52-
const key = String(Math.random()).replace('.', '');
53-
54-
const { remove } = await saveRule(browser.popup, {
55-
name: 'test disable rule',
56-
ruleType: 'modifySendHeader',
57-
pattern: '^' + testServer,
58-
matchType: 'regexp',
59-
isFunction: false,
60-
enable: false,
61-
action: {
62-
name: 'X-Test-Header',
63-
value: key,
64-
},
65-
});
66-
67-
const header = await getHeader(browser.browser);
68-
69-
expect(header['X_TEST_HEADER']).toBeUndefined();
70-
71-
await remove();
72-
});
73-
74-
test('Remove Response Header', async () => {
75-
const { remove } = await saveRule(browser.popup, {
76-
name: 'test remove request header',
77-
ruleType: 'modifyReceiveHeader',
78-
pattern: '^' + testServer,
79-
matchType: 'regexp',
80-
isFunction: false,
81-
enable: true,
82-
action: {
83-
name: 'content-security-policy',
84-
value: '_header_editor_remove_',
85-
},
86-
});
87-
88-
const value = await getPageValue(browser.browser, 'csp.php');
89-
90-
expect(value).toBe('Executed');
91-
92-
await remove();
24+
await cleanup();
9325
});
9426

95-
test('Modify Response Header', async () => {
96-
const key = String(Math.random()).replace('.', '');
97-
98-
const { remove } = await saveRule(browser.popup, {
99-
name: 'test modify request header',
100-
ruleType: 'modifyReceiveHeader',
101-
pattern: '^' + testServer,
102-
matchType: 'regexp',
103-
isFunction: false,
104-
enable: true,
105-
action: {
106-
name: 'content-security-policy',
107-
value: `script-src 'self' 'nonce-${key}'`,
108-
},
109-
});
110-
111-
const value = await getPageValue(browser.browser, 'csp.php?nonce=' + key);
112-
113-
expect(value).toBe(key);
114-
115-
await remove();
116-
});
27+
test('Modify Request Header', async () =>
28+
runTest(['chrome_v3', 'firefox_v3'], async browser => {
29+
const key = String(Math.random()).replace('.', '');
30+
31+
const { remove } = await saveRule(browser.popup, {
32+
name: 'test modify request header',
33+
ruleType: 'modifySendHeader',
34+
pattern: '^' + testServer,
35+
matchType: 'regexp',
36+
isFunction: false,
37+
enable: true,
38+
action: {
39+
name: 'X-Test-Header',
40+
value: key,
41+
},
42+
});
43+
44+
const header = await getHeader(browser.browser);
45+
46+
expect(header['X_TEST_HEADER']).toBe(key);
47+
48+
await remove();
49+
}));
50+
51+
test('Disable rule', async () =>
52+
runTest(['chrome_v3', 'firefox_v3'], async browser => {
53+
const key = String(Math.random()).replace('.', '');
54+
55+
const { remove } = await saveRule(browser.popup, {
56+
name: 'test disable rule',
57+
ruleType: 'modifySendHeader',
58+
pattern: '^' + testServer,
59+
matchType: 'regexp',
60+
isFunction: false,
61+
enable: false,
62+
action: {
63+
name: 'X-Test-Header',
64+
value: key,
65+
},
66+
});
67+
68+
const header = await getHeader(browser.browser);
69+
70+
expect(header['X_TEST_HEADER']).toBeUndefined();
71+
72+
await remove();
73+
}));
74+
75+
test('Remove Response Header', async () =>
76+
runTest(['chrome_v3', 'firefox_v3'], async browser => {
77+
const { remove } = await saveRule(browser.popup, {
78+
name: 'test remove request header',
79+
ruleType: 'modifyReceiveHeader',
80+
pattern: '^' + testServer,
81+
matchType: 'regexp',
82+
isFunction: false,
83+
enable: true,
84+
action: {
85+
name: 'content-security-policy',
86+
value: '_header_editor_remove_',
87+
},
88+
});
89+
90+
const value = await getPageValue(browser.browser, 'csp.php');
91+
92+
expect(value).toBe('Executed');
93+
94+
await remove();
95+
}));
96+
97+
test('Modify Response Header', async () =>
98+
runTest(['chrome_v3', 'firefox_v3'], async browser => {
99+
const key = String(Math.random()).replace('.', '');
100+
101+
const { remove } = await saveRule(browser.popup, {
102+
name: 'test modify request header',
103+
ruleType: 'modifyReceiveHeader',
104+
pattern: '^' + testServer,
105+
matchType: 'regexp',
106+
isFunction: false,
107+
enable: true,
108+
action: {
109+
name: 'content-security-policy',
110+
value: `script-src 'self' 'nonce-${key}'`,
111+
},
112+
});
113+
114+
const value = await getPageValue(browser.browser, 'csp.php?nonce=' + key);
115+
116+
expect(value).toBe(key);
117+
118+
await remove();
119+
}));

tests/e2e/utils.mjs

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { promisify } from 'util';
1010

1111
export const testServer = 'http://127.0.0.1:8899/';
1212
export const fxAddonUUID = 'f492d714-700a-4402-8b96-4ec9e829332d';
13+
const browserList = {};
1314

1415
const __filename = fileURLToPath(import.meta.url);
1516
const __dirname = path.dirname(__filename);
@@ -28,23 +29,6 @@ export async function sleep(ms) {
2829
});
2930
}
3031

31-
function getExecutablePath(name) {
32-
const path = process.env.PATH.split(':');
33-
for (const p of path) {
34-
const fullPath = path.join(p, name);
35-
if (existsSync(fullPath)) {
36-
return fullPath;
37-
}
38-
}
39-
}
40-
41-
function getFirefox() {
42-
if (config.firefoxPath) {
43-
return config.firefoxPath;
44-
}
45-
return getExecutablePath('firefox');
46-
}
47-
4832
async function createBrowser(browserKey, pathToExtension) {
4933
const browserType =
5034
browserKey.indexOf('firefox') === 0 ? 'firefox' : 'chrome';
@@ -65,7 +49,7 @@ async function createBrowser(browserKey, pathToExtension) {
6549
const browser = await puppeteer.launch({
6650
// headless: false,
6751
browser: 'firefox',
68-
executablePath: getFirefox(),
52+
executablePath: config.firefoxPath ? config.firefoxPath : undefined,
6953
args: [`--start-debugger-server=${rppPort}`],
7054
extraPrefsFirefox: {
7155
'devtools.chrome.enabled': true,
@@ -91,7 +75,11 @@ async function createBrowser(browserKey, pathToExtension) {
9175
}
9276
}
9377

94-
export async function startUp(browserKey) {
78+
export async function getBrowserClient(browserKey) {
79+
if (typeof browserList[browserKey] !== 'undefined') {
80+
return browserList[browserKey];
81+
}
82+
9583
const pathToExtension = path.join(__dirname, `../../dist_${browserKey}`);
9684

9785
const manifest = JSON.parse(
@@ -109,7 +97,9 @@ export async function startUp(browserKey) {
10997
const page = await browser.newPage();
11098
if (url.startsWith('moz-extension://')) {
11199
// Firefox will not resolve goto
112-
page.goto(url);
100+
page.goto(url, { timeout: 0 }).catch(() => {
101+
// ignore
102+
});
113103
} else {
114104
await page.goto(url);
115105
}
@@ -125,13 +115,14 @@ export async function startUp(browserKey) {
125115
);
126116
const page = await backgroundPageTarget.page();
127117
const popup = await openPopup(page);
128-
return {
118+
browserList[browserKey] = {
129119
browserType: 'chrome',
130120
type: 'page',
131121
target: page,
132122
browser,
133123
popup,
134124
};
125+
return browserList[browserKey];
135126
}
136127

137128
if (manifest.background.service_worker) {
@@ -143,23 +134,40 @@ export async function startUp(browserKey) {
143134
);
144135
const worker = await workerTarget.worker();
145136
const popup = await openPopup(worker);
146-
return {
137+
browserList[browserKey] = {
147138
browserType: 'chrome',
148139
type: 'worker',
149140
target: worker,
150141
browser,
151142
popup,
152143
};
144+
return browserList[browserKey];
153145
}
154146
} else {
155147
// Firefox has no 'background_page' target
156148
const popup = await openPopup();
157-
return {
149+
browserList[browserKey] = {
158150
browserType: 'firefox',
159151
type: 'none',
160152
browser,
161153
popup,
162154
};
155+
return browserList[browserKey];
156+
}
157+
}
158+
159+
export async function cleanup() {
160+
for (const client of Object.values(browserList)) {
161+
try {
162+
if (client.popup && !client.popup.isClosed()) {
163+
await client.popup.close();
164+
}
165+
if (client.browser.isConnected()) {
166+
await client.browser.close();
167+
}
168+
} catch (error) {
169+
console.log('Cleanup error:', error.message);
170+
}
163171
}
164172
}
165173

@@ -182,6 +190,13 @@ export async function waitTestServer() {
182190
}
183191
}
184192

193+
export async function runTest(targets, cb) {
194+
for (const target of targets) {
195+
const client = await getBrowserClient(target);
196+
await cb(client);
197+
}
198+
}
199+
185200
export async function saveRule(popup, rule) {
186201
const action = {
187202
method: 'save_rule',

0 commit comments

Comments
 (0)