Skip to content

Commit 12974e0

Browse files
authored
(#8569) - Switch browser tests to playwright
Co-authored-by: alxndrsn <alxndrsn>
1 parent 2d78ed9 commit 12974e0

File tree

8 files changed

+73
-166
lines changed

8 files changed

+73
-166
lines changed

.github/actions/install-deps/action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ runs:
2525
- uses: iamssen/couchdb-github-action@master
2626
with:
2727
couchdb-version: ${{ inputs.couchdb-version }}
28+
29+
- run: sudo npx playwright install-deps
30+
shell: bash

.github/workflows/ci.yml

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ on:
1515

1616
env:
1717
NODE_VERSION: 14
18-
SELENIUM_HUB_HOST: hub
1918
TEST_HOST: localhost
2019

2120
jobs:
@@ -74,17 +73,11 @@ jobs:
7473

7574
couchdb-browser:
7675
needs: lint
77-
services:
78-
hub:
79-
image: selenium/hub:3.141.59-gold
80-
firefox:
81-
image: selenium/node-firefox:3.141.59-gold
82-
env: { HUB_HOST: hub, HUB_PORT: 4444 }
8376
strategy:
8477
fail-fast: false
8578
matrix:
8679
couchdb: ['2.3','3.1']
87-
client: ['selenium:firefox', 'selenium:chrome']
80+
client: ['firefox', 'chromium']
8881
cmd:
8982
- npm test
9083
- TYPE=find PLUGINS=pouchdb-find ADAPTERS=http npm test
@@ -156,16 +149,10 @@ jobs:
156149

157150
browser-adapter:
158151
needs: lint
159-
services:
160-
hub:
161-
image: selenium/hub:3.141.59-gold
162-
firefox:
163-
image: selenium/node-firefox:3.141.59-gold
164-
env: { HUB_HOST: hub, HUB_PORT: 4444 }
165152
strategy:
166153
fail-fast: false
167154
matrix:
168-
client: ['selenium:firefox', 'selenium:chrome']
155+
client: ['firefox', 'chromium']
169156
adapter: ['idb', 'indexeddb', 'memory']
170157
cmd:
171158
- npm test
@@ -201,16 +188,10 @@ jobs:
201188

202189
pouchdb-server:
203190
needs: lint
204-
services:
205-
hub:
206-
image: selenium/hub:3.141.59-gold
207-
firefox:
208-
image: selenium/node-firefox:3.141.59-gold
209-
env: { HUB_HOST: hub, HUB_PORT: 4444 }
210191
strategy:
211192
fail-fast: false
212193
matrix:
213-
client: ['node', 'selenium:firefox', 'selenium:chrome']
194+
client: ['node', 'firefox', 'chromium']
214195
cmd:
215196
- npm test
216197
- TYPE=find PLUGINS=pouchdb-find ADAPTERS=http npm test
@@ -246,7 +227,7 @@ jobs:
246227
matrix:
247228
node: [14, 16]
248229
cmd:
249-
- CLIENT=selenium:firefox npm run test-webpack
230+
- CLIENT=firefox npm run test-webpack
250231
- AUTO_COMPACTION=true npm test
251232
- PERF=1 npm test
252233
- npm run test-unit

TESTING.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,7 @@ this to `0` to prevent this behaviour.
8686
#### `CLIENT` (default: `node`)
8787

8888
Sets the target platform the tests will execute on. Set this to
89-
`selenium:firefox` or `selenium:chrome` to execute in the tests in the browser.
90-
91-
You can also specify a custom Firefox binary to run using the `FIREFOX_BIN`
92-
variable.
89+
`firefox`, `chromium` or `webkit` to execute the tests in the browser.
9390

9491
#### `COUCH_HOST`
9592

@@ -180,7 +177,7 @@ for example:
180177
$ TYPE=find PLUGINS=pouchdb-find CLIENT=node ADAPTERS=memory npm test
181178

182179
# run the "mapreduce" tests with indexeddb in firefox
183-
$ TYPE=mapreduce CLIENT=selenium:firefox ADAPTERS=indexeddb npm test
180+
$ TYPE=mapreduce CLIENT=firefox ADAPTERS=indexeddb npm test
184181

185182
It's also important to check these tests against server-side adapters,
186183
specifically we need to ensure compatibility with CouchDB itself. We do this by
@@ -221,7 +218,7 @@ Sets the number of iterations each test uses by default.
221218

222219
### Running tests in the browser
223220

224-
Normally we use `CLIENT=selenium:firefox` to run a set of tests in the browser
221+
Normally we use `CLIENT=firefox` to run a set of tests in the browser
225222
automatically. This opens a browser window, automatically runs the requested
226223
tests in it, and reports the results back to the shell.
227224

bin/test-browser.js

Lines changed: 57 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,28 @@
11
#!/usr/bin/env node
22
'use strict';
33

4-
var wd = require('wd');
5-
wd.configureHttp({timeout: 180000}); // 3 minutes
4+
const playwright = require('playwright');
65

7-
var selenium = require('selenium-standalone');
86
var querystring = require("querystring");
97

108
var MochaSpecReporter = require('mocha').reporters.Spec;
119

1210
var devserver = require('./dev-server.js');
1311

14-
var testTimeout = 30 * 60 * 1000;
15-
16-
var SELENIUM_VERSION = process.env.SELENIUM_VERSION || '3.141.0';
17-
var CHROME_BIN = process.env.CHROME_BIN;
18-
var FIREFOX_BIN = process.env.FIREFOX_BIN;
19-
2012
// BAIL=0 to disable bailing
2113
var bail = process.env.BAIL !== '0';
2214

23-
// process.env.CLIENT is a colon separated list of
24-
// selenium:browserName:browserVerion:platform
25-
var tmp = (process.env.CLIENT || 'selenium:firefox').split(':');
26-
var client = {
27-
runner: tmp[0] || 'selenium',
28-
browser: tmp[1] || 'firefox',
29-
version: tmp[2] || null, // Latest
30-
platform: tmp[3] || null
31-
};
15+
// Playwright BrowserType whitelist.
16+
// See: https://playwright.dev/docs/api/class-playwright
17+
const SUPPORTED_BROWSERS = [ 'chromium', 'firefox', 'webkit' ];
18+
const browserName = process.env.CLIENT || 'firefox';
19+
if (!SUPPORTED_BROWSERS.includes(browserName)) {
20+
console.log(`
21+
!!! Requested browser not supported: '${browserName}'.
22+
!!! Available browsers: ${SUPPORTED_BROWSERS.map(b => `'${b}'`).join(', ')}
23+
`);
24+
process.exit(1);
25+
}
3226

3327
var testRoot = 'http://127.0.0.1:8000/tests/';
3428
var testUrl;
@@ -46,9 +40,6 @@ if (process.env.PERF) {
4640

4741
var qs = { remote: 1 };
4842

49-
var seleniumClient;
50-
var tunnelId = process.env.TRAVIS_JOB_NUMBER || 'tunnel-' + Date.now();
51-
5243
if (process.env.INVERT) {
5344
qs.invert = process.env.INVERT;
5445
}
@@ -86,36 +77,6 @@ if (process.env.ITERATIONS) {
8677
testUrl += '?';
8778
testUrl += querystring.stringify(qs);
8879

89-
function testError(e) {
90-
console.error(e);
91-
console.error('Doh, tests failed');
92-
93-
closeClient(function () {
94-
process.exit(3);
95-
});
96-
}
97-
98-
function startSelenium(callback) {
99-
// Start selenium
100-
var opts = {version: SELENIUM_VERSION};
101-
selenium.install(opts, function (err) {
102-
if (err) {
103-
console.error('Failed to install selenium');
104-
process.exit(1);
105-
}
106-
selenium.start(opts, function () {
107-
seleniumClient = wd.promiseChainRemote();
108-
callback();
109-
});
110-
});
111-
}
112-
113-
function closeClient(callback) {
114-
seleniumClient.quit().then(function () {
115-
callback();
116-
});
117-
}
118-
11980
class RemoteRunner {
12081
constructor() {
12182
this.handlers = {};
@@ -181,90 +142,60 @@ function BenchmarkReporter(runner) {
181142
});
182143
}
183144

184-
function startTest() {
145+
async function startTest() {
185146

186-
console.log('Starting', client, 'on', testUrl);
147+
console.log('Starting', browserName, 'on', testUrl);
187148

188-
var opts = {
189-
browserName: client.browser,
190-
version: client.version,
191-
platform: client.platform,
192-
tunnelTimeout: testTimeout,
193-
name: client.browser + ' - ' + tunnelId,
194-
'max-duration': 60 * 45,
195-
'command-timeout': 599,
196-
'idle-timeout': 599,
197-
'tunnel-identifier': tunnelId
198-
};
199-
if (CHROME_BIN) {
200-
opts.chromeOptions = {
201-
binary: CHROME_BIN,
202-
args: ['--headless', '--disable-gpu', '--no-sandbox', '--disable-setuid-sandbox']
203-
};
204-
}
205-
if (FIREFOX_BIN) {
206-
opts.firefox_binary = FIREFOX_BIN;
207-
}
208-
209-
var runner = new RemoteRunner();
149+
const runner = new RemoteRunner();
210150
new MochaSpecReporter(runner);
211151
new BenchmarkReporter(runner);
212152

213-
seleniumClient.init(opts, function (err) {
214-
if (err) {
215-
testError(err);
216-
return;
217-
}
218-
console.log('Initialized');
153+
const options = {
154+
headless: true,
155+
};
156+
const browser = await playwright[browserName].launch(options);
157+
const page = await browser.newPage();
158+
if (process.env.BROWSER_CONSOLE) {
159+
page.on('console', message => {
160+
const { url, lineNumber } = message.location();
161+
console.log('BROWSER', message.type().toUpperCase(), `${url}:${lineNumber}`, message.text());
162+
});
163+
}
164+
await page.goto(testUrl);
165+
166+
const userAgent = await page.evaluate('navigator.userAgent');
167+
console.log('Testing on:', userAgent);
168+
169+
const interval = setInterval(async () => {
170+
try {
171+
const events = await page.evaluate('window.testEvents()');
172+
runner.handleEvents(events);
173+
174+
if (runner.completed || (runner.failed && bail)) {
175+
if (!runner.completed && runner.failed) {
176+
try {
177+
runner.bail();
178+
} catch (e) {
179+
// Temporary debugging of bailing failure
180+
console.log('An error occurred while bailing:');
181+
console.log(e);
182+
}
183+
}
219184

220-
seleniumClient.get(testUrl, function (err) {
221-
if (err) {
222-
testError(err);
223-
return;
185+
clearInterval(interval);
186+
await browser.close();
187+
process.exit(!process.env.PERF && runner.failed ? 1 : 0);
224188
}
225-
console.log('Successfully started');
226-
227-
seleniumClient.eval('navigator.userAgent', function (err, userAgent) {
228-
if (err) {
229-
testError(err);
230-
} else {
231-
console.log('Testing on:', userAgent);
232-
233-
var interval = setInterval(function () {
234-
seleniumClient.eval('window.testEvents()', function (err, events) {
235-
if (err) {
236-
clearInterval(interval);
237-
testError(err);
238-
} else if (events) {
239-
runner.handleEvents(events);
240-
241-
if (runner.completed || (runner.failed && bail)) {
242-
if (!runner.completed && runner.failed) {
243-
try {
244-
runner.bail();
245-
} catch (e) {
246-
// Temporary debugging of bailing failure
247-
console.log('An error occurred while bailing:');
248-
console.log(e);
249-
}
250-
}
251-
252-
clearInterval(interval);
253-
254-
closeClient(function () {
255-
process.exit(!process.env.PERF && runner.failed ? 1 : 0);
256-
});
257-
}
258-
}
259-
});
260-
}, 10 * 1000);
189+
} catch (e) {
190+
console.error('Tests failed:', e);
261191

262-
}
263-
});
264-
});
265-
});
192+
clearInterval(interval);
193+
await browser.close();
194+
process.exit(3);
195+
}
196+
}, 1000);
266197
}
267198

268199
devserver.start(function () {
269-
startSelenium(startTest);
200+
startTest();
270201
});

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
"mocha": "3.5.0",
9595
"mockery": "2.1.0",
9696
"ncp": "2.0.0",
97+
"playwright": "1.36.1",
9798
"pouchdb-express-router": "0.0.11",
9899
"query-string": "6.10.1",
99100
"replace": "1.2.1",
@@ -103,14 +104,12 @@
103104
"rollup-plugin-node-resolve": "4.2.4",
104105
"rollup-plugin-replace": "1.2.1",
105106
"seedrandom": "3.0.5",
106-
"selenium-standalone": "6.16.0",
107107
"stream-to-promise": "1.1.1",
108108
"tape": "4.13.0",
109109
"terser": "4.8.0",
110110
"throw-max-listeners-error": "1.0.1",
111111
"ua-parser-js": "0.7.24",
112-
"watch-glob": "0.1.3",
113-
"wd": "1.11.4"
112+
"watch-glob": "0.1.3"
114113
},
115114
"// greenkeeper": [
116115
"// chai-as-promised is pinned because of breaking changes in 6.0.0",

tests/integration/test.attachments.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3609,11 +3609,7 @@ repl_adapters.forEach(function (adapters) {
36093609
});
36103610
});
36113611

3612-
// Currently this test is causing occasional CI selenium:firefox
3613-
// failures. Under advice of @daleharvey, we will skip this test
3614-
// to not block other development/tests and track this issue.
3615-
// See issue #6835 and #6831 for further info
3616-
it.skip('#3961 Many attachments on same doc', function () {
3612+
it('#3961 Many attachments on same doc', function () {
36173613
var doc = {_id: 'foo', _attachments: {}};
36183614

36193615
var db = new PouchDB(dbs.name);

tests/integration/webrunner.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
window.removeEventListener("load", startTests);
99

1010
if (remote) {
11-
// Capture logs for selenium output
11+
// Capture logs for test runner output
1212
var logs = [];
1313

1414
(function () {
@@ -41,7 +41,7 @@
4141

4242
})();
4343

44-
// Capture test events for selenium output
44+
// Capture test events for test runner output
4545
var testEventsBuffer = [];
4646

4747
window.testEvents = function () {

0 commit comments

Comments
 (0)