import assert from 'node:assert/strict' import test from 'node:test' import { ReleaseSetCompatibilityError, planReleaseSet, type InstalledPluginModule, type PluginReleaseCandidate, } from '../src/releaseSet' const installed: InstalledPluginModule[] = [ { moduleId: 'common', type: 'common', version: '1.0.0', appVersionRange: '>=8.0.0 <9.0.0', minNativeApiLevel: 1, }, { moduleId: 'app', type: 'app', version: '1.0.0', appVersionRange: '>=8.0.0 <9.0.0', commonVersionRange: '>=1.0.0 <2.0.0', }, { moduleId: 'buz2', type: 'buz', version: '1.0.0', appVersionRange: '>=8.0.0 <9.0.0', commonVersionRange: '>=1.0.0 <2.0.0', }, ] function candidate( module: Omit, ): PluginReleaseCandidate { return { appVersionRange: '>=8.0.0 <9.0.0', ...module, downloadUrl: `https://updates.example/${module.moduleId}.bundle`, sha256: 'a'.repeat(64), } } test('orders common before app and buz in one cold-start release set', () => { const plan = planReleaseSet({ installed, appVersion: '8.0.0', nativeApiLevel: 3, candidates: [ candidate({ moduleId: 'buz1', type: 'buz', version: '1.0.2', commonVersionRange: '>=1.0.1 <2.0.0', }), candidate({ moduleId: 'common', type: 'common', version: '1.0.2' }), candidate({ moduleId: 'app', type: 'app', version: '1.0.1', commonVersionRange: '>=1.0.1 <2.0.0', }), ], }) assert.deepEqual( plan?.modules.map(module => module.moduleId), ['common', 'app', 'buz1'], ) assert.equal(plan?.commonVersion, '1.0.2') assert.equal(plan?.requiresColdStart, true) }) test('keeps an older buz compatible when common advances in the same major range', () => { const plan = planReleaseSet({ installed, appVersion: '8.0.0', nativeApiLevel: 1, candidates: [candidate({ moduleId: 'common', type: 'common', version: '1.0.2' })], }) assert.equal(plan?.modules.length, 1) assert.equal(plan?.commonVersion, '1.0.2') }) test('rejects a common upgrade that breaks an installed plugin', () => { assert.throws( () => planReleaseSet({ installed, appVersion: '8.0.0', nativeApiLevel: 1, candidates: [candidate({ moduleId: 'common', type: 'common', version: '2.0.0' })], }), (error: unknown) => error instanceof ReleaseSetCompatibilityError && error.moduleId === 'app' && error.reason === 'COMMON_INCOMPATIBLE', ) }) test('rejects candidates that require a newer native API', () => { assert.throws( () => planReleaseSet({ installed, appVersion: '8.0.0', nativeApiLevel: 1, candidates: [ candidate({ moduleId: 'buz1', type: 'buz', version: '1.0.1', commonVersionRange: '^1.0.0', minNativeApiLevel: 2, }), ], }), (error: unknown) => error instanceof ReleaseSetCompatibilityError && error.reason === 'NATIVE_API_INCOMPATIBLE', ) }) test('rejects a plugin built against a different native baseline', () => { const nativeBaselineId = 'android-sha256:current' const installedForBaseline = installed.map(module => ({ ...module, builtAgainstNativeBaselineId: nativeBaselineId, })) assert.throws( () => planReleaseSet({ installed: installedForBaseline, appVersion: '8.0.0', nativeApiLevel: 1, nativeBaselineId, candidates: [ candidate({ moduleId: 'common', type: 'common', version: '1.0.1', builtAgainstNativeBaselineId: 'android-sha256:old', }), ], }), (error: unknown) => error instanceof ReleaseSetCompatibilityError && error.reason === 'NATIVE_BASELINE_INCOMPATIBLE', ) }) test('rejects a plugin outside the current full-app version range', () => { assert.throws( () => planReleaseSet({ installed, appVersion: '8.0.0', nativeApiLevel: 1, candidates: [ candidate({ moduleId: 'buz1', type: 'buz', version: '1.0.1', appVersionRange: '>=8.0.1 <9.0.0', commonVersionRange: '^1.0.0', }), ], }), (error: unknown) => error instanceof ReleaseSetCompatibilityError && error.reason === 'APP_INCOMPATIBLE', ) }) test('ignores equal versions and downgrades', () => { const plan = planReleaseSet({ installed, appVersion: '8.0.0', nativeApiLevel: 1, candidates: [ candidate({ moduleId: 'common', type: 'common', version: '0.9.0' }), candidate({ moduleId: 'buz2', type: 'buz', version: '1.0.0', commonVersionRange: '^1.0.0', }), ], }) assert.equal(plan, null) })