diff --git a/packages/server/lib/index.js b/packages/server/lib/index.js index 3fc865a..015ba26 100644 --- a/packages/server/lib/index.js +++ b/packages/server/lib/index.js @@ -164,14 +164,28 @@ export default class DevTool { * @see {@link DevTool.stop} */ start() { - return new Promise((resolve) => { + return new Promise((resolve, reject) => { const start = new Date().getTime(); - this.server = this.app.listen(this.port, () => { - const ms = new Date().getTime() - start; - this.port = this.server.address().port; - this.#log.trace(`dev tool server started on port "${this.port}" (in ${ms} ms)`); - resolve(); - }); + this.server = this.app + .listen(this.port, () => { + const ms = new Date().getTime() - start; + this.port = this.server.address().port; + this.#log.trace(`dev tool server started on port "${this.port}" (in ${ms} ms)`); + resolve(); + }) + .on("error", (e) => { + if (e.code === "EADDRINUSE") { + this.#log.trace(`dev tool server port ${this.port} is already in use, trying a random port`); + this.server = this.app.listen(0, () => { + const ms = new Date().getTime() - start; + this.port = this.server.address().port; + this.#log.trace(`dev tool server started on port "${this.port}" (in ${ms} ms)`); + resolve(); + }); + } else { + reject(e); + } + }); }); } diff --git a/packages/server/lib/index.test.js b/packages/server/lib/index.test.js index d5d567d..e67b060 100644 --- a/packages/server/lib/index.test.js +++ b/packages/server/lib/index.test.js @@ -71,16 +71,38 @@ test("starting on a random port", async (t) => { error: t.mock.fn(), fatal: t.mock.fn(), }; - devTool = new DevTool({ logger, port: 0 }); + const a = new DevTool({ logger, port: 4321 }); + const b = new DevTool({ logger, port: 4321 }); + await a.start(); + await b.start(); + await a.stop(); + await b.stop(); + + assert.match(logger.trace.mock.calls[0].arguments[0], /dev tool server started on port "4321"/); + assert.match(logger.trace.mock.calls[2].arguments[0], /dev tool server started on port "/); + assert.notEqual(logger.trace.mock.calls[2].arguments[0], "undefined"); + assert.notEqual(logger.trace.mock.calls[2].arguments[0], "null"); + assert.notEqual(logger.trace.mock.calls[2].arguments[0], "8172"); + assert.equal(logger.trace.mock.calls.length, 5); +}); + +test("assigns a random port if the specified port isn't available", async (t) => { + const logger = { + trace: t.mock.fn(), + debug: t.mock.fn(), + info: t.mock.fn(), + warn: t.mock.fn(), + error: t.mock.fn(), + fatal: t.mock.fn(), + }; + devTool = new DevTool({ logger }); devTool.register(podlet); await devTool.start(); await devTool.stop(); - assert.match(logger.trace.mock.calls[0].arguments[0], /dev tool server started on port "/); - assert.notEqual(logger.trace.mock.calls[0].arguments[0], "undefined"); - assert.notEqual(logger.trace.mock.calls[0].arguments[0], "null"); - assert.notEqual(logger.trace.mock.calls[0].arguments[0], "8172"); + assert.match(logger.trace.mock.calls[0].arguments[0], /dev tool server started on port "8172" \(in/); + assert.match(logger.trace.mock.calls[1].arguments[0], /dev tool server shutdown in/); assert.equal(logger.trace.mock.calls.length, 2); });