Skip to content

Commit b6c8c6d

Browse files
committed
Enable Firefox/Edge in integration tests
Use Firefox and Edge along with Chrome. Replace Playwright with Selenium, which allows to use Firefox with extensions. Extract base driver class since most code is common to all browsers. Extract "ZAP" server to make it easier to use. Update all test cases to use Selenium. Update test timeout to allow all browsers enough time to load. Signed-off-by: thc202 <thc202@gmail.com>
1 parent d07e8c3 commit b6c8c6d

File tree

11 files changed

+1030
-1017
lines changed

11 files changed

+1030
-1017
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ jobs:
2626
- name: Build
2727
run: yarn run build
2828

29-
- name: Install browsers for tests
30-
run: yarn playwright install --with-deps --no-shell
31-
3229
- name: Test
33-
run: xvfb-run yarn test
30+
run: yarn test
3431

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
"lint": "eslint . --ext .ts,.tsx",
3737
"lint:fix": "eslint . --ext .ts,.tsx --fix",
38-
"test": "jest --coverage --testTimeout=10000",
38+
"test": "jest --coverage --testTimeout=20000",
3939
"buildAndTest": "yarn run build && yarn test"
4040
},
4141
"dependencies": {
@@ -63,11 +63,11 @@
6363
"@babel/preset-react": "^7.27.1",
6464
"@babel/preset-typescript": "^7.27.1",
6565
"@jest/globals": "^30.0.2",
66-
"@playwright/test": "^1.53.1",
6766
"@types/jest": "^30.0.0",
6867
"@types/json-server": "^0.14.8",
6968
"@types/lodash": "^4.17.18",
7069
"@types/node": "^24.0.3",
70+
"@types/selenium-webdriver": "^4.1.28",
7171
"@types/text-encoding": "^0.0.40",
7272
"@types/webextension-polyfill": "^0.12.3",
7373
"@types/webpack": "^5.28.5",
@@ -98,15 +98,15 @@
9898
"json-server": "^0.17.3",
9999
"mini-css-extract-plugin": "^2.9.2",
100100
"optimize-css-assets-webpack-plugin": "^6.0.1",
101-
"playwright": "1.53.1",
102-
"playwright-webextext": "^0.0.4",
103101
"postcss": "^8.5.6",
104102
"postcss-loader": "^8.1.1",
105103
"prettier": "^2.3.0",
106104
"resolve-url-loader": "^5.0.0",
107105
"sass": "^1.89.2",
108106
"sass-loader": "^16.0.5",
107+
"selenium-webdriver": "^4.33.0",
109108
"terser-webpack-plugin": "^5.3.14",
109+
"tmp-promise": "^3.0.3",
110110
"ts-jest": "^29.4.0",
111111
"typescript": "^5.8.3",
112112
"webpack": "^5.99.9",

test/ContentScript/ZapServer.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Zed Attack Proxy (ZAP) and its related source files.
3+
*
4+
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
5+
*
6+
* Copyright 2025 The ZAP Development Team
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
import {Request, Response} from 'express';
21+
import http from 'http';
22+
import JsonServer from 'json-server';
23+
24+
class ZapServer {
25+
server: http.Server;
26+
27+
events: Array<object>;
28+
29+
incZapEvents = false;
30+
31+
constructor(events: Array<object>, port: number) {
32+
this.events = events;
33+
const app = JsonServer.create();
34+
35+
app.use(JsonServer.bodyParser);
36+
app.post('/JSON/client/action/:action', (req: Request, res: Response) => {
37+
const action = req.params;
38+
const {body} = req;
39+
const msg = JSON.stringify({action, body});
40+
if (this.incZapEvents || msg.indexOf('localzap') === -1) {
41+
// Ignore localzap events
42+
this.events[this.getInsertPosition(body)] = {
43+
action,
44+
body: this.normalizeJson(body),
45+
};
46+
}
47+
res.sendStatus(200);
48+
});
49+
50+
this.server = app.listen(port, () => {});
51+
}
52+
53+
public setRecordZapEvents(include: boolean): void {
54+
this.incZapEvents = include;
55+
}
56+
57+
public async close(): Promise<void> {
58+
return new Promise((resolve) => {
59+
this.server.close(() => {
60+
resolve();
61+
});
62+
});
63+
}
64+
65+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
66+
private getInsertPosition(body: any): number {
67+
const statementJson = body?.statementJson;
68+
if (statementJson) {
69+
const index = JSON.parse(statementJson)?.index;
70+
if (index) {
71+
return index - 1;
72+
}
73+
}
74+
return this.events.length;
75+
}
76+
77+
private toJsonWithoutDynamicValues(value: string): string {
78+
return JSON.parse(
79+
value
80+
.replace(/timestamp":\d+/g, 'timestamp": "TIMESTAMP"')
81+
.replace(/Recorded by [^\\]+?"/g, 'Recorded by comment"')
82+
.replace(/browserType":"[^\\]+?"/g, 'browserType":"browser"')
83+
);
84+
}
85+
86+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
87+
private normalizeJson(body: any): any {
88+
['eventJson', 'statementJson', 'objectJson'].forEach((name) => {
89+
const value = body[name];
90+
if (value) {
91+
body[name] = this.toJsonWithoutDynamicValues(value);
92+
}
93+
});
94+
return body;
95+
}
96+
}
97+
98+
export {ZapServer};

test/ContentScript/constants.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ import path from 'path';
2121

2222
export const extensionPath = {
2323
CHROME: path.join(__dirname, '..', '..', 'extension', 'chrome'),
24-
FIREFOX: path.join(__dirname, '..', '..', 'extension', 'firefox.xpi'),
24+
FIREFOX: path.join(__dirname, '..', '..', 'extension', 'firefox'),
2525
};
2626

2727
export const HTTPPORT = 1801;
2828
export const JSONPORT = 8080;
2929
export const BROWSERNAME = {
3030
CHROME: 'chrome',
31+
EDGE: 'edge',
3132
FIREFOX: 'firefox',
3233
};

0 commit comments

Comments
 (0)