115 lines
4.6 KiB
JavaScript
115 lines
4.6 KiB
JavaScript
const { TIERS, VALID_TIERS, getTier, getScanLimit, canAccess } = require('../../src/config/tiers');
|
|
|
|
describe('tiers config', () => {
|
|
test('VALID_TIERS includes free, africa, analyst, desk (Session 12 added africa)', () => {
|
|
expect(VALID_TIERS).toEqual(['free', 'africa', 'analyst', 'desk']);
|
|
});
|
|
|
|
describe('africa tier (Session 12)', () => {
|
|
test('exists with 10 scans/day, reasoning + kill conditions visible', () => {
|
|
const a = TIERS.africa;
|
|
expect(a).toBeDefined();
|
|
expect(a.scans_per_day).toBe(10);
|
|
expect(a.reasoning_visible).toBe(true);
|
|
expect(a.kill_conditions_detail).toBe(true);
|
|
// alerts + portfolio + engine2 are paid-tier extras — Africa
|
|
// does not include them.
|
|
expect(a.alerts).toBe(false);
|
|
expect(a.portfolio).toBe(false);
|
|
expect(a.engine2).toBe(false);
|
|
});
|
|
test('api_access is FALSE on africa tier (immutable)', () => {
|
|
expect(TIERS.africa.api_access).toBe(false);
|
|
});
|
|
test('africa scans_per_day sits between free (3) and analyst (15)', () => {
|
|
expect(TIERS.africa.scans_per_day).toBeGreaterThan(TIERS.free.scans_per_day);
|
|
expect(TIERS.africa.scans_per_day).toBeLessThan(TIERS.analyst.scans_per_day);
|
|
});
|
|
test('getScanLimit resolves "africa" correctly (sanity for the scan-limit middleware)', () => {
|
|
expect(getScanLimit('africa')).toBe(10);
|
|
});
|
|
test('canAccess("africa", "reasoning_visible") is true', () => {
|
|
expect(canAccess('africa', 'reasoning_visible')).toBe(true);
|
|
expect(canAccess('africa', 'kill_conditions_detail')).toBe(true);
|
|
expect(canAccess('africa', 'alerts')).toBe(false);
|
|
expect(canAccess('africa', 'api_access')).toBe(false);
|
|
});
|
|
});
|
|
|
|
test('api_access is FALSE on every tier (non-negotiable)', () => {
|
|
for (const tierName of VALID_TIERS) {
|
|
expect(TIERS[tierName].api_access).toBe(false);
|
|
}
|
|
});
|
|
|
|
test('free tier has the most restrictive defaults', () => {
|
|
const free = TIERS.free;
|
|
expect(free.scans_per_day).toBe(3);
|
|
expect(free.reasoning_visible).toBe(false);
|
|
expect(free.kill_conditions_detail).toBe(false);
|
|
expect(free.alerts).toBe(false);
|
|
expect(free.portfolio).toBe(false);
|
|
expect(free.engine2).toBe(false);
|
|
// Grade is the hook — it must be visible even on free.
|
|
expect(free.grade_visible).toBe(true);
|
|
// stat_dashboard is the entry product — visible to everyone.
|
|
expect(free.stat_dashboard).toBe(true);
|
|
});
|
|
|
|
test('analyst opens reasoning + kill conditions + alerts', () => {
|
|
const a = TIERS.analyst;
|
|
expect(a.scans_per_day).toBe(15);
|
|
expect(a.reasoning_visible).toBe(true);
|
|
expect(a.kill_conditions_detail).toBe(true);
|
|
expect(a.alerts).toBe(true);
|
|
// Still no portfolio or engine2 — those are Desk perks.
|
|
expect(a.portfolio).toBe(false);
|
|
expect(a.engine2).toBe(false);
|
|
});
|
|
|
|
test('desk unlocks everything except api_access', () => {
|
|
const d = TIERS.desk;
|
|
expect(d.scans_per_day).toBe(Infinity);
|
|
expect(d.reasoning_visible).toBe(true);
|
|
expect(d.kill_conditions_detail).toBe(true);
|
|
expect(d.alerts).toBe(true);
|
|
expect(d.portfolio).toBe(true);
|
|
expect(d.engine2).toBe(true);
|
|
expect(d.api_access).toBe(false);
|
|
});
|
|
|
|
test('getTier falls back to free for unknown tier names', () => {
|
|
expect(getTier('mystery')).toBe(TIERS.free);
|
|
expect(getTier(null)).toBe(TIERS.free);
|
|
expect(getTier(undefined)).toBe(TIERS.free);
|
|
expect(getTier('')).toBe(TIERS.free);
|
|
});
|
|
|
|
test('getScanLimit returns the per-tier daily cap', () => {
|
|
expect(getScanLimit('free')).toBe(3);
|
|
expect(getScanLimit('analyst')).toBe(15);
|
|
expect(getScanLimit('desk')).toBe(Infinity);
|
|
});
|
|
|
|
test('canAccess returns the right boolean per (tier, feature) pair', () => {
|
|
expect(canAccess('free', 'grade_visible')).toBe(true);
|
|
expect(canAccess('free', 'reasoning_visible')).toBe(false);
|
|
expect(canAccess('free', 'api_access')).toBe(false);
|
|
expect(canAccess('analyst', 'reasoning_visible')).toBe(true);
|
|
expect(canAccess('analyst', 'engine2')).toBe(false);
|
|
expect(canAccess('desk', 'engine2')).toBe(true);
|
|
expect(canAccess('desk', 'api_access')).toBe(false);
|
|
});
|
|
|
|
test('canAccess returns false for unknown features (defensive)', () => {
|
|
expect(canAccess('desk', 'no_such_feature')).toBe(false);
|
|
});
|
|
|
|
test('TIERS objects are frozen — nobody can mutate the matrix at runtime', () => {
|
|
expect(Object.isFrozen(TIERS)).toBe(true);
|
|
expect(Object.isFrozen(TIERS.free)).toBe(true);
|
|
expect(Object.isFrozen(TIERS.analyst)).toBe(true);
|
|
expect(Object.isFrozen(TIERS.desk)).toBe(true);
|
|
});
|
|
});
|