diff --git a/test/dev.ts b/test/dev.ts index c2b15d1365..413d729a07 100644 --- a/test/dev.ts +++ b/test/dev.ts @@ -68,13 +68,31 @@ if (args.o) { await open(`http://localhost:3000${adminRoute}`) } +const findOpenPort = (startPort: number): Promise => { + return new Promise((resolve, reject) => { + const server = createServer() + server.listen(startPort, () => { + console.log(`✓ Running on port ${startPort}`) + server.close(() => resolve(startPort)) + }) + server.on('error', () => { + console.log(`⚠ Port ${startPort} is in use, trying ${startPort + 1} instead.`) + findOpenPort(startPort + 1) + .then(resolve) + .catch(reject) + }) + }) +} + const port = process.env.PORT ? Number(process.env.PORT) : 3000 +const availablePort = await findOpenPort(port) + // @ts-expect-error the same as in test/helpers/initPayloadE2E.ts const app = nextImport({ dev: true, hostname: 'localhost', - port, + port: availablePort, dir: rootDir, }) @@ -88,7 +106,7 @@ void app.prepare().then(() => { createServer(async (req, res) => { const parsedUrl = parse(req.url || '', true) await handle(req, res, parsedUrl) - }).listen(port, () => { + }).listen(availablePort, () => { resolveServer() }) }) @@ -97,8 +115,8 @@ await serverPromise process.env.PAYLOAD_DROP_DATABASE = process.env.PAYLOAD_DROP_DATABASE === 'false' ? 'false' : 'true' // fetch the admin url to force a render -void fetch(`http://localhost:${port}${adminRoute}`) -void fetch(`http://localhost:${port}/api/access`) +void fetch(`http://localhost:${availablePort}${adminRoute}`) +void fetch(`http://localhost:${availablePort}/api/access`) // This ensures that the next-server process is killed when this process is killed and doesn't linger around. process.on('SIGINT', () => { if (child) {