docs-v2/cypress/support/hugo-server.js

175 lines
4.8 KiB
JavaScript

import { spawn } from 'child_process';
import fs from 'fs';
import http from 'http';
import net from 'net';
// Hugo server constants
export const HUGO_PORT = 1315;
export const HUGO_LOG_FILE = '/tmp/hugo_server.log';
/**
* Check if a port is already in use
* @param {number} port - The port to check
* @returns {Promise<boolean>} True if port is in use, false otherwise
*/
export async function isPortInUse(port) {
return new Promise((resolve) => {
const tester = net
.createServer()
.once('error', () => resolve(true))
.once('listening', () => {
tester.close();
resolve(false);
})
.listen(port, '127.0.0.1');
});
}
/**
* Start the Hugo server with the specified options
* @param {Object} options - Configuration options for Hugo
* @param {string} options.configFile - Path to Hugo config file (e.g., 'hugo.testing.yml')
* @param {number} options.port - Port number for Hugo server
* @param {boolean} options.buildDrafts - Whether to build draft content
* @param {boolean} options.noHTTPCache - Whether to disable HTTP caching
* @param {string} options.logFile - Path to write Hugo logs
* @returns {Promise<Object>} Child process object
*/
export async function startHugoServer({
configFile = 'hugo.testing.yml',
port = HUGO_PORT,
buildDrafts = true,
noHTTPCache = true,
logFile = HUGO_LOG_FILE,
} = {}) {
console.log(`Starting Hugo server on port ${port}...`);
// Prepare command arguments
const hugoArgs = [
'hugo',
'server',
'--config',
configFile,
'--port',
String(port),
];
if (buildDrafts) {
hugoArgs.push('--buildDrafts');
}
if (noHTTPCache) {
hugoArgs.push('--noHTTPCache');
}
return new Promise((resolve, reject) => {
try {
// Use npx to find and execute Hugo, which will work regardless of installation method
console.log(`Running Hugo with npx: npx ${hugoArgs.join(' ')}`);
const hugoProc = spawn('npx', hugoArgs, {
stdio: ['ignore', 'pipe', 'pipe'],
shell: true,
});
// Check if the process started successfully
if (!hugoProc || !hugoProc.pid) {
return reject(new Error('Failed to start Hugo server via npx'));
}
// Set up logging
if (logFile) {
hugoProc.stdout.on('data', (data) => {
const output = data.toString();
fs.appendFileSync(logFile, output);
process.stdout.write(`Hugo: ${output}`);
});
hugoProc.stderr.on('data', (data) => {
const output = data.toString();
fs.appendFileSync(logFile, output);
process.stderr.write(`Hugo ERROR: ${output}`);
});
}
// Handle process errors
hugoProc.on('error', (err) => {
console.error(`Error in Hugo server process: ${err}`);
reject(err);
});
// Check for early exit
hugoProc.on('close', (code) => {
if (code !== null && code !== 0) {
reject(new Error(`Hugo process exited early with code ${code}`));
}
});
// Resolve with the process object after a short delay to ensure it's running
setTimeout(() => {
if (hugoProc.killed) {
reject(new Error('Hugo process was killed during startup'));
} else {
resolve(hugoProc);
}
}, 500);
} catch (err) {
console.error(`Error starting Hugo server: ${err.message}`);
reject(err);
}
});
}
/**
* Wait for the Hugo server to be ready
* @param {number} timeoutMs - Timeout in milliseconds
* @returns {Promise<void>}
*/
export async function waitForHugoReady(timeoutMs = 30000) {
console.log(
`Waiting for Hugo server to be ready on http://localhost:${HUGO_PORT}...`
);
const startTime = Date.now();
return new Promise((resolve, reject) => {
// Poll the server
function checkServer() {
const req = http.get(`http://localhost:${HUGO_PORT}`, (res) => {
if (res.statusCode === 200) {
resolve();
} else {
// If we get a response but not 200, try again after delay
const elapsed = Date.now() - startTime;
if (elapsed > timeoutMs) {
reject(
new Error(
`Hugo server responded with status ${res.statusCode} after timeout`
)
);
} else {
setTimeout(checkServer, 1000);
}
}
});
req.on('error', (err) => {
// Connection errors are expected while server is starting
const elapsed = Date.now() - startTime;
if (elapsed > timeoutMs) {
reject(
new Error(`Timed out waiting for Hugo server: ${err.message}`)
);
} else {
// Try again after a delay
setTimeout(checkServer, 1000);
}
});
req.end();
}
// Start polling
checkServer();
});
}