54 lines
3.1 KiB
JavaScript
54 lines
3.1 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import { readFileSync } from 'node:fs'
|
|
import test from 'node:test'
|
|
|
|
const read = (path) => readFileSync(new URL(`../${path}`, import.meta.url), 'utf8')
|
|
const registry = JSON.parse(read('contracts/numbered-ipc-registry.json'))
|
|
const runtime = read('src-tauri/src/module_package_runtime.rs')
|
|
const moduleAdapter = read('src-tauri/src/web_novel_modules.rs')
|
|
const frontend = [
|
|
read('src/modules/web-novel/WebNovelWorkspace.tsx'),
|
|
read('src/modules/web-novel/AuthorModuleCenter.tsx'),
|
|
read('src/modules/web-novel/AuthorWritingSidecar.tsx'),
|
|
].join('\n')
|
|
|
|
const packages = [
|
|
'WORKBENCH', 'OUTLINE', 'GRID', 'STORYWORLD', 'DELIVERY',
|
|
].map((name) => JSON.parse(read(`fixtures/module-packages/HLP-MOD-OFFICIAL-WEB-NOVEL-${name}-0001-0.1.0.ghmod`)))
|
|
|
|
test('web novel family has five immutable official identities behind one shared lifecycle', () => {
|
|
assert.equal(packages.length, 5)
|
|
assert.ok(packages.every((value) => value.manifest.registrationClass === 'OFFICIAL_LIGHTHOUSE'))
|
|
assert.ok(packages.every((value) => value.manifest.adapter === 'web-novel-workbench-v1'))
|
|
assert.equal(new Set(packages.map((value) => value.manifest.moduleNumber)).size, 5)
|
|
assert.match(runtime, /const BUNDLED_MODULES/)
|
|
assert.doesNotMatch(frontend, /install_web_novel_author_module|mount_web_novel_author_module|uninstall_web_novel_author_module/)
|
|
})
|
|
|
|
test('all 38 web novel effects cross exact numbered routes and no raw tauri command surface', () => {
|
|
const routes = registry.operations.filter((route) => Number(route.operation_number.slice(-4)) >= 103 && Number(route.operation_number.slice(-4)) <= 140)
|
|
assert.equal(routes.length, 38)
|
|
assert.deepEqual([...new Set(routes.map((route) => route.module_number))], [
|
|
'HLP-NIPC-MOD-0025', 'HLP-NIPC-MOD-0026', 'HLP-NIPC-MOD-0027', 'HLP-NIPC-MOD-0028', 'HLP-NIPC-MOD-0029',
|
|
])
|
|
assert.ok(routes.every((route) => route.admission === 'VERIFIED_HUMAN_ROUTE'))
|
|
assert.doesNotMatch(frontend, /from ['"]@tauri-apps\/api\/core['"]/)
|
|
for (const source of ['web_novel_workspace.rs', 'web_novel_import.rs', 'web_novel_author.rs', 'web_novel_modules.rs']) {
|
|
assert.doesNotMatch(read(`src-tauri/src/${source}`), /#\[tauri::command\]/)
|
|
}
|
|
})
|
|
|
|
test('advanced effects require their own exact active module number', () => {
|
|
assert.match(moduleAdapter, /require_module_active\(&app, OUTLINE\)/)
|
|
assert.match(moduleAdapter, /require_module_active\(&app, GRID\)/)
|
|
assert.match(moduleAdapter, /require_module_active\(&app, STORYWORLD\)/)
|
|
assert.match(moduleAdapter, /require_module_active\(&app, DELIVERY\)/)
|
|
assert.match(moduleAdapter, /shared signed package runtime/)
|
|
})
|
|
|
|
test('workspace is independently lazy-loaded and preserves old account data in place', () => {
|
|
assert.match(read('src/main.tsx'), /lazy\(\(\) => import\('\.\/modules\/web-novel\/WebNovelWorkspace'\)/)
|
|
assert.equal(packages[0].payload.adapterConfig.legacyDataPolicy, 'READ_IN_PLACE_NO_DESTRUCTIVE_MIGRATION')
|
|
assert.equal(packages[0].payload.adapterConfig.thirdPartyPublishDefault, 'DENY')
|
|
assert.doesNotMatch(read('src-tauri/src/web_novel_workspace.rs'), /serde_json::from_str[^\n]+unwrap_or_default\(\)/)
|
|
})
|