Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lambdatest/smartui-cli",
"version": "4.1.33",
"version": "4.1.34",
"description": "A command line interface (CLI) to run SmartUI tests on LambdaTest",
"files": [
"dist/**/*"
Expand Down Expand Up @@ -53,6 +53,7 @@
"simple-swizzle": "0.2.2"
},
"devDependencies": {
"find-free-port": "^2.0.0",
"typescript": "^5.3.2"
}
}
2 changes: 2 additions & 0 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export default {
EDGE: 'edge',
EDGE_CHANNEL: 'msedge',
WEBKIT: 'webkit',
MIN_PORT_RANGE: 49100,
MAX_PORT_RANGE: 60000,

// discovery browser launch arguments
LAUNCH_ARGS: [
Expand Down
54 changes: 48 additions & 6 deletions src/lib/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,43 @@ import path from 'path';
import fastify, { FastifyInstance, RouteShorthandOptions } from 'fastify';
import { readFileSync, truncate } from 'fs'
import { Context } from '../types.js'
import { Logger } from 'winston'
import { validateSnapshot } from './schemaValidation.js'
import { pingIntervalId, startPollingForTunnel, stopTunnelHelper, isTunnelPolling } from './utils.js';
import constants from './constants.js';
var fp = require("find-free-port")

const uploadDomToS3ViaEnv = process.env.USE_LAMBDA_INTERNAL || false;

// Helper function to find an available port
async function findAvailablePort(server: FastifyInstance, startPort: number, log: Logger): Promise<number> {
let currentPort = startPort;

// If the default port gives error, use find-free-port with range 49100-60000
try {
await server.listen({ port: currentPort });
return currentPort;
} catch (error: any) {
if (error.code === 'EADDRINUSE') {
log.debug(`Port ${currentPort} is in use, finding available port in range 49100-60000`);

// Use find-free-port to get an available port in the specified range
const availablePorts = await fp(constants.MIN_PORT_RANGE, constants.MAX_PORT_RANGE);
if (availablePorts.length > 0) {
const freePort = availablePorts[0];
await server.listen({ port: freePort });
log.debug(`Found and started server on port ${freePort}`);
return freePort;
} else {
throw new Error('No available ports found in range 49100-60000');
}
} else {
// If it's not a port conflict error, rethrow it
throw error;
}
}
}

export default async (ctx: Context): Promise<FastifyInstance<Server, IncomingMessage, ServerResponse>> => {

const server: FastifyInstance<Server, IncomingMessage, ServerResponse> = fastify({
Expand Down Expand Up @@ -307,12 +340,21 @@ export default async (ctx: Context): Promise<FastifyInstance<Server, IncomingMes
}
});


await server.listen({ port: ctx.options.port });
// store server's address for SDK
let { port } = server.addresses()[0];
process.env.SMARTUI_SERVER_ADDRESS = `http://localhost:${port}`;
process.env.CYPRESS_SMARTUI_SERVER_ADDRESS = `http://localhost:${port}`;
// Use the helper function to find and start server on available port
if (ctx.sourceCommand && ctx.sourceCommand === 'exec-start') {

await server.listen({ port: ctx.options.port });
let { port } = server.addresses()[0];
process.env.SMARTUI_SERVER_ADDRESS = `http://localhost:${port}`;
process.env.CYPRESS_SMARTUI_SERVER_ADDRESS = `http://localhost:${port}`;
ctx.log.debug(`Server started successfully on port ${port}`);

} else {
const actualPort = await findAvailablePort(server, ctx.options.port, ctx.log);
process.env.SMARTUI_SERVER_ADDRESS = `http://localhost:${actualPort}`;
process.env.CYPRESS_SMARTUI_SERVER_ADDRESS = `http://localhost:${actualPort}`;
ctx.log.debug(`Server started successfully on port ${actualPort}`);
}

return server;
}