Files
LangBot/web/tests/unit/runner-merge-contract.test.mjs
T
RockChinQ 273b1ea3cf Merge master into dev/4.11.x and preserve plugin runner architecture
Reconcile migration branches without rewriting published revisions; retain additive Codex, monitoring, provider and platform fixes. Keep dynamic runner schemas and Host ownership, restore compatibility regressions, and preserve safe model-test error handling.
2026-09-16 08:13:07 +00:00

113 lines
3.1 KiB
JavaScript

import assert from 'node:assert/strict';
import fs from 'node:fs';
import test from 'node:test';
import ts from 'typescript';
const read = (path) => fs.readFileSync(new URL(path, import.meta.url), 'utf8');
test('dynamic form combines manifest normalization and shared condition helpers', () => {
const source = read(
'../../src/app/home/components/dynamic-form/DynamicFormComponent.tsx',
);
const parsed = ts.createSourceFile(
'DynamicFormComponent.tsx',
source,
ts.ScriptTarget.Latest,
true,
ts.ScriptKind.TSX,
);
assert.equal(
parsed.parseDiagnostics.length,
0,
'Dynamic form must parse after the merge',
);
const imports = parsed.statements.filter(ts.isImportDeclaration);
const importedNames = (module) =>
imports
.filter((item) => item.moduleSpecifier.text === module)
.flatMap(
(item) =>
item.importClause?.namedBindings?.elements?.map(
(entry) => entry.name.text,
) ?? [],
);
assert.ok(
importedNames('./DynamicFormItemConfig').includes(
'parseDynamicFormItemType',
),
);
assert.deepEqual(importedNames('./DynamicFormConditions').sort(), [
'resolveDisabledState',
'resolveShowIfValue',
]);
assert.equal(
parsed.statements.filter(
(item) =>
ts.isFunctionDeclaration(item) &&
item.name?.text === 'resolveShowIfValue',
).length,
0,
);
});
test('pipeline defaults retain plugin runner containers, not retired Core runners', () => {
const config = JSON.parse(
read('../../../src/langbot/templates/default-pipeline-config.json'),
);
assert.deepEqual(config.ai, {
runner: { id: '', 'expire-time': 0 },
runner_config: {},
});
const metadata = read(
'../../../src/langbot/templates/metadata/pipeline/ai.yaml',
);
assert.doesNotMatch(
metadata,
/^\s+- name: (?:local-agent|n8n-service-api|langflow-api)$/m,
);
assert.match(metadata, /RunnerRegistry/);
});
test('pipeline UI does not restore host-owned Box scope as local-agent config', () => {
const source = read(
'../../src/app/home/pipelines/components/pipeline-form/PipelineFormComponent.tsx',
);
assert.doesNotMatch(
source,
/getBoxScopeContext|force_box_session_id_template|N8nAuthFormComponent/,
);
assert.match(source, /ai\.runner_config/);
assert.match(source, /systemContext=\{dynamicFormSystemContext\}/);
});
test('backend client preserves complementary Codex and runner debug API imports', () => {
const source = read('../../src/app/infra/http/BackendClient.ts');
const parsed = ts.createSourceFile(
'BackendClient.ts',
source,
ts.ScriptTarget.Latest,
true,
);
assert.equal(
parsed.parseDiagnostics.length,
0,
'API client must parse after the merge',
);
const imports = parsed.statements
.filter(ts.isImportDeclaration)
.flatMap(
(item) =>
item.importClause?.namedBindings?.elements?.map(
(entry) => entry.name.text,
) ?? [],
);
for (const name of [
'CodexAuthStatus',
'CodexDeviceAuthorization',
'CodexDevicePoll',
'DebugExecutionEvent',
]) {
assert.ok(imports.includes(name), name);
}
});