Skip to content
Closed
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
4 changes: 2 additions & 2 deletions app/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ module.exports = {
// Service name
serviceName: 'Service name goes here',

// Port to run nodemon on locally
port: 2000,
// Port to run the prototype on (the port you'll see in your browser)
port: 3000,

// Automatically stores form data, and send to all views
useAutoStoreData: 'true',
Expand Down
15 changes: 11 additions & 4 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ const config = require('./app/config')
const { findAvailablePort } = require('./lib/utils')

// Set configuration variables
const port = parseInt(process.env.PORT || config.port, 10) || 2000
const browserPort = parseInt(process.env.PORT || config.port, 10) || 3000
const nodemonPort = Math.max(1024, browserPort - 1000) // Ensure port is >= 1024
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot why does it need to be above 1024?


// Delete all the files in /public build directory
function cleanPublic() {
Expand Down Expand Up @@ -82,9 +83,15 @@ async function startNodemon(done) {
let availablePort

try {
availablePort = await findAvailablePort(port)
availablePort = await findAvailablePort(nodemonPort)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be finding an available port for the browserPort, as that’s the port that the user will see, and should be prompted for if it's not available?

The nodemon port could then be a random available port selected, which the user is not even aware of?

if (!availablePort) {
throw new Error(`Port ${port} in use`)
throw new Error(`Port ${nodemonPort} in use`)
}

// Also check if the browser port is available
const { checkPortStatus } = require('portscanner')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot move this line to the top?

if ((await checkPortStatus(browserPort, '127.0.0.1')) === 'open') {
throw new Error(`Browser port ${browserPort} in use`)
}
} catch (error) {
done(new PluginError('startNodemon', error))
Expand Down Expand Up @@ -128,7 +135,7 @@ async function startBrowserSync(done) {
browserSync.init(
{
proxy: `localhost:${proxyPort}`,
port: proxyPort + 1000,
port: browserPort,
ui: false,
files: ['app/views/**/*.*', 'lib/example-templates/**/*.*'],
ghostMode: false,
Expand Down
2 changes: 1 addition & 1 deletion lib/utils/find-available-port.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const { checkPortStatus, findAPortNotInUse } = require('portscanner')
*
* @param {number} [startPort] - Find port starting from this port number (optional)
*/
async function findAvailablePort(startPort = 3000) {
async function findAvailablePort(startPort = 2000) {
const host = '127.0.0.1'

// Check default port is free
Expand Down
53 changes: 53 additions & 0 deletions tests/lib/port-config.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Mock inquirer to avoid interactive prompts in tests
jest.mock('@inquirer/prompts', () => ({
confirm: jest.fn()
}))

// Mock portscanner to control port availability
jest.mock('portscanner', () => ({
checkPortStatus: jest.fn(),
findAPortNotInUse: jest.fn()
}))

const inquirer = require('@inquirer/prompts')
const { checkPortStatus, findAPortNotInUse } = require('portscanner')

const { findAvailablePort } = require('../../lib/utils/find-available-port')

describe('Port configuration', () => {
beforeEach(() => {
jest.clearAllMocks()
})

it('findAvailablePort returns provided port when available', async () => {
checkPortStatus.mockResolvedValue('closed')

const result = await findAvailablePort(2000)

expect(result).toBe(2000)
expect(checkPortStatus).toHaveBeenCalledWith(2000, '127.0.0.1')
})

it('findAvailablePort finds alternative when port is in use and user agrees', async () => {
checkPortStatus.mockResolvedValue('open')
inquirer.confirm.mockResolvedValue(true)
findAPortNotInUse.mockResolvedValue(2001)

const result = await findAvailablePort(2000)

expect(result).toBe(2001)
expect(inquirer.confirm).toHaveBeenCalled()
expect(findAPortNotInUse).toHaveBeenCalledWith(2000, 3000, '127.0.0.1')
})

it('findAvailablePort returns undefined when port is in use and user declines', async () => {
checkPortStatus.mockResolvedValue('open')
inquirer.confirm.mockResolvedValue(false)

const result = await findAvailablePort(2000)

expect(result).toBeUndefined()
expect(inquirer.confirm).toHaveBeenCalled()
expect(findAPortNotInUse).not.toHaveBeenCalled()
})
})