import { test } from 'node:test' import assert from 'node:assert/strict' import { buildFeatureGate, OPEN_GATE } from '../src/modules/featureGate.js' // The feature seam's decision logic (MODULE_SYSTEM.md §1.5, MODULE_API.md §3.3). // Every branch here fails OPEN, and that is the property under test as much as // the happy path: this is presentation, the server is the gate, and a UI mistake // that hides a page from someone entitled to it is worse in every case than one // that shows a link which then 403s. const flags = (...names) => new Set(names) test('a row with no feature is always visible', () => { const gate = buildFeatureGate(new Map([['uo', flags()]])) assert.equal(gate({ to: '/site/news' }), true) }) test('a core row resolves against the owner id `core`', () => { // Core's ten shard-gated rows carry no moduleId, and core registers its // provider under `core` (main.jsx) precisely so they resolve without one. const gate = buildFeatureGate(new Map([['core', flags('atlas')]])) assert.equal(gate({ to: '/site/atlas', feature: 'atlas' }), true) assert.equal(gate({ to: '/site/market', feature: 'market' }), false) }) test('a module row resolves against ITS module, not another one', () => { const gate = buildFeatureGate( new Map([ ['uo', flags('atlas')], ['rust', flags('market')], ]), ) assert.equal(gate({ to: '/uo/atlas', feature: 'atlas', moduleId: 'uo' }), true) // `market` is a flag the OTHER module grants. Resolution is by registration, // so there is no string a module can write to borrow it. assert.equal(gate({ to: '/uo/market', feature: 'market', moduleId: 'uo' }), false) assert.equal(gate({ to: '/rust/market', feature: 'market', moduleId: 'rust' }), true) }) test('no provider for the owner shows the row', () => { // The no-module-installed case, and the reason the filter is a correct no-op // on a bare core rather than a nav that renders nothing. const gate = buildFeatureGate(new Map()) assert.equal(gate({ to: '/site/atlas', feature: 'atlas' }), true) assert.equal(gate({ to: '/uo/atlas', feature: 'atlas', moduleId: 'uo' }), true) }) test('a provider still loading shows the row', () => { // useShardFlags returns null until its fetch lands. Blanking the nav on every // page load and filling it in a moment later is the behaviour this avoids. const gate = buildFeatureGate(new Map([['core', null]])) assert.equal(gate({ to: '/site/atlas', feature: 'atlas' }), true) }) test('a provider that returned something unusable shows the row', () => { for (const bad of [undefined, 42, 'atlas', {}, []]) { const gate = buildFeatureGate(new Map([['core', bad]])) assert.equal(gate({ to: '/site/atlas', feature: 'atlas' }), true, `failed closed on ${JSON.stringify(bad)}`) } }) test('an array-backed provider is not silently treated as a Set', () => { // `[].has` does not exist, so this is the unusable case above rather than a // membership test that quietly always fails. Asserted so that a future // "helpful" normalisation knows it changed a documented behaviour. const gate = buildFeatureGate(new Map([['core', ['atlas']]])) assert.equal(gate({ to: '/site/atlas', feature: 'atlas' }), true) }) test('a missing map, or a junk row, shows rather than throws', () => { assert.equal(buildFeatureGate(null)({ feature: 'atlas' }), true) assert.equal(buildFeatureGate(new Map())(null), true) assert.equal(buildFeatureGate(new Map())(undefined), true) }) test('any Set-like satisfies a provider — core does not require a Set', () => { const gate = buildFeatureGate(new Map([['uo', { has: (name) => name === 'ruleset' }]])) assert.equal(gate({ feature: 'ruleset', moduleId: 'uo' }), true) assert.equal(gate({ feature: 'champs', moduleId: 'uo' }), false) }) test('the open gate is what a component outside the provider gets', () => { assert.equal(OPEN_GATE({ feature: 'anything' }), true) })