const { promises: fs } = require('fs') const path = require('path') const Koa = require('koa') const CURRENT_STATE_KEY = '__CURRENT__' const DEFAULT_STATE_KEY = '__DEFAULT__' const FIXTURE_SERVER_HOST = 'localhost' const FIXTURE_SERVER_PORT = 12345 class FixtureServer { constructor () { this._app = new Koa() this._stateMap = new Map([ [DEFAULT_STATE_KEY, Object.create(null)], ]) this._initialStateCache = new Map() this._app.use(async (ctx) => { // Firefox is _super_ strict about needing CORS headers ctx.set('Access-Control-Allow-Origin', '*') if (this._isStateRequest(ctx)) { ctx.body = this._stateMap.get(CURRENT_STATE_KEY) } }) } async start () { const options = { host: FIXTURE_SERVER_HOST, port: FIXTURE_SERVER_PORT, exclusive: true, } return new Promise((resolve, reject) => { this._server = this._app.listen(options) this._server.once('error', reject) this._server.once('listening', resolve) }) } async stop () { if (!this._server) { return } await new Promise((resolve, reject) => { this._server.close() this._server.once('error', reject) this._server.once('close', resolve) }) } async loadState (directory) { const statePath = path.resolve(__dirname, directory, 'state.json') let state if (this._initialStateCache.has(statePath)) { state = this._initialStateCache.get(statePath) } else { const data = await fs.readFile(statePath) state = JSON.parse(data.toString('utf-8')) this._initialStateCache.set(statePath, state) } this._stateMap.set(CURRENT_STATE_KEY, state) } _isStateRequest (ctx) { return ctx.method === 'GET' && ctx.path === '/state.json' } } module.exports = FixtureServer