// ── Test harness: a fake ctx ─────────────────────────────────────────────── // // A module's tests cannot require core — that is the whole zero-internal-imports // rule (docs/website/MODULE_API.md §5.1), and it applies to test files too. So // instead of stubbing core's modules the way core's own tests do, a module test // hands `core.init()` a ctx it fabricated. // // That turns out to be the nicer story: the seam that exists so a module can be // swapped onto a different core is the same seam that lets its tests run with no // database, no express app and no settings table. Core's tests reach the same // place by pointing the mariadb pool at a dead port; a module does not have to. const core = require('../core') /** * Build and install a fake ctx. Every member is a stub the test can reassign. * @param {object} [over] members to override, deep-merged one level */ function installFakeCtx(over = {}) { const settings = new Map() const ctx = { moduleId: 'uo', paths: { moduleRoot: require('path').join(__dirname, '..', '..') }, // Null, not the real packages: a module cannot resolve express from outside // server/ (that is why ctx carries them at all), and these tests construct no // router. A test that needs one passes the real ones in `over`. express: null, validator: null, db: { // Every test that needs a query result reassigns this. query: async () => [], pool: { getConnection: async () => { throw new Error('no pool in tests') } }, }, log: () => ({ error() {}, warn() {}, info() {}, debug() {} }), settings: { get: async (key) => (settings.has(key) ? settings.get(key) : null), set: async (key, value) => { settings.set(key, value) }, getInstanceName: async () => 'Test Shard', }, auth: { getUserFromRequest: () => null }, push: { publish: async () => {} }, secretBox: { encrypt: (s) => s, decrypt: (s) => s }, middleware: { requireAuth: (req, res, next) => next(), requireRole: () => (req, res, next) => next(), siteMode: (req, res, next) => next(), validate: (req, res, next) => next(), noindex: (req, res, next) => next(), }, uploads: {}, posts: {}, ...over, } core.init(ctx) return ctx } module.exports = { installFakeCtx }