From 303d98c7ca09908b557bdd8d8691ca609a4f389f Mon Sep 17 00:00:00 2001 From: Lawrence Forooghian Date: Tue, 30 Jul 2024 09:20:47 +0100 Subject: [PATCH 1/3] Fix logging of test web server port --- test/web_server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/web_server.js b/test/web_server.js index 9d10abcb3..1660dc6c2 100755 --- a/test/web_server.js +++ b/test/web_server.js @@ -48,7 +48,7 @@ class MochaServer { const port = process.env.PORT || 3000; this.server = app.listen(port); - console.log('Mocha test server listening on http://localhost:3000/'); + console.log(`Mocha test server listening on http://localhost:${port}/`); } close() { From 33e66514d7e2e062a5a901eff0f69f8de198d959 Mon Sep 17 00:00:00 2001 From: Lawrence Forooghian Date: Tue, 30 Jul 2024 09:22:46 +0100 Subject: [PATCH 2/3] Handle errors when starting test web server The following errors were just being absorbed, making them hard to notice and debug: - app.listen throwing a synchronous error (e.g. in the case where you specify -1 as a port number) - app.listen throwing an asynchronous error (e.g. in the EADDRINUSE case) --- test/support/runPlaywrightTests.js | 2 +- test/web_server.js | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/support/runPlaywrightTests.js b/test/support/runPlaywrightTests.js index be73457d7..edbcc1531 100644 --- a/test/support/runPlaywrightTests.js +++ b/test/support/runPlaywrightTests.js @@ -10,7 +10,7 @@ const playwrightBrowsers = ['chromium', 'firefox', 'webkit']; const mochaServer = new MochaServer(/* playwrightTest: */ true); const runTests = async (browserType) => { - mochaServer.listen(); + await mochaServer.listen(); const browser = await browserType.launch(); const context = await browser.newContext(); const page = await context.newPage(); diff --git a/test/web_server.js b/test/web_server.js index 1660dc6c2..7b510bee3 100755 --- a/test/web_server.js +++ b/test/web_server.js @@ -46,13 +46,16 @@ class MochaServer { app.use(express.static(__dirname)); const port = process.env.PORT || 3000; - this.server = app.listen(port); + await new Promise((resolve, reject) => { + this.server = app.listen(port, resolve); + this.server.once('error', reject); + }); console.log(`Mocha test server listening on http://localhost:${port}/`); } close() { - this.server.close(); + this.server?.close(); } } From 3ce70325c6e6c511012d73ecce52a2483bfe18b3 Mon Sep 17 00:00:00 2001 From: Lawrence Forooghian Date: Tue, 30 Jul 2024 09:45:32 +0100 Subject: [PATCH 3/3] Fail test web server if port is unavailable for IPv4 --- test/web_server.js | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/test/web_server.js b/test/web_server.js index 7b510bee3..1e6822fde 100755 --- a/test/web_server.js +++ b/test/web_server.js @@ -13,6 +13,8 @@ var express = require('express'), */ class MochaServer { + servers = []; + constructor(playwrightTest) { this.playwrightTest = playwrightTest; } @@ -46,16 +48,28 @@ class MochaServer { app.use(express.static(__dirname)); const port = process.env.PORT || 3000; - await new Promise((resolve, reject) => { - this.server = app.listen(port, resolve); - this.server.once('error', reject); - }); + // Explicitly listen on the IPv4 and IPv6 loopback interfaces. If you don’t + // pass an address to `app.listen`, then it will bind in a manner that + // succeeds even if the IPv4 socket address is already in use, as long as + // the IPv6 socket address is free. This can lead to confusion. + await this.startServer(app, '127.0.0.1', port); + await this.startServer(app, '::1', port); console.log(`Mocha test server listening on http://localhost:${port}/`); } + async startServer(app, address, port) { + await new Promise((resolve, reject) => { + const server = app.listen(port, address, resolve); + this.servers.push(server); + server.once('error', reject); + }); + } + close() { - this.server?.close(); + for (const server of this.servers) { + server.close(); + } } }