UNPKG

@mochify/mochify

Version:

Run mocha tests in headless browsers

108 lines (96 loc) 2.45 kB
'use strict'; 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); }; }