@mochify/mochify
Version:
Run mocha tests in headless browsers
108 lines (96 loc) • 2.45 kB
JavaScript
;
const fs = require('fs');
const fs_promises = require('fs').promises;
const { promisify } = require('util');
const path = require('path');
const http = require('http');
let mimePromise;
async function getMime() {
if (!mimePromise) {
mimePromise = import('mime');
}
const { default: mime } = await mimePromise;
return mime;
}
exports.startServer = startServer;
/**
* @typedef {Object} MochifyServer
* @property {number} port
* @property {function (): Promise<void>} close
*/
/**
* @param {string} base_path
* @param {Object} [options]
* @param {number} [options.port]
* @param {string[]} [options._scripts]
* @param {string[]} [options._modules]
* @returns {Promise<MochifyServer>}
*/
async function startServer(base_path, options = {}) {
const server = http.createServer(
requestHandler(base_path, {
scripts: options._scripts,
modules: options._modules
})
);
server.on('error', (err) => {
process.stderr.write(err.stack || String(err));
process.stderr.write('\n');
});
// @ts-ignore
await promisify(server.listen).call(server, options.port);
return {
// @ts-ignore
port: server.address().port,
close: () => promisify(server.close).call(server)
};
}
/**
* @param {string} base_path
* @param {{ scripts?: string[], modules?: string[] }} options
* @returns {(req: http.IncomingMessage, res: http.ServerResponse) => Promise<void>}
*/
function requestHandler(base_path, { scripts = [], modules = [] }) {
return async (req, res) => {
const mime = await getMime();
if (!req.url) {
res.writeHead(400);
res.end();
return;
}
if (req.url === '/') {
res.writeHead(200);
res.end(`
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
${scripts.map((script) => `<script>${script}</script>`).join('')}
${modules.map((mod) => `<script type="module" src="${mod}"></script>`).join('')}
</head>
<body></body>
</html>
`);
return;
}
if (req.url === '/favicon.ico') {
res.writeHead(200, {
'Content-Type': mime.getType('favicon.ico')
});
res.end();
return;
}
const file = path.join(base_path, req.url.substring(1));
try {
await fs_promises.stat(file);
} catch {
res.writeHead(404);
res.end();
return;
}
res.writeHead(200, {
'Content-Type': mime.getType(file)
});
fs.createReadStream(file).pipe(res);
};
}