Files
LangBot/web/tests/unit/wizard-page-bot.test.mjs
T
Dongchuan Fu be3734ffda feat(wizard): rework agent onboarding flow (#2471)
* feat(wizard): rework agent onboarding flow

* fix(web): support LAN development access

* fix(wizard): parse ranked model selection entries

* feat(wizard): add inbound bot verification

* feat(wizard): add floating page bot verification

* fix(wizard): repair HTTP bot inbound test setup

* feat(wizard): streamline custom model onboarding

* feat(wizard): label page bot test preview

* style(space): apply ruff formatting

* fix(wizard): polish AI engine onboarding

* fix(wizard): clarify local account message test

* feat(wizard): animate AI engine transitions

* fix(wizard): align AI engine setup headers

---------

Co-authored-by: langbot-dev <langbot@users.noreply.github.com>
Co-authored-by: RockChinQ <rockchinq@gmail.com>
2026-08-28 01:30:30 +08:00

129 lines
3.7 KiB
JavaScript

import assert from 'node:assert/strict';
import fs from 'node:fs';
import path from 'node:path';
import test from 'node:test';
import { fileURLToPath } from 'node:url';
const currentDirectory = path.dirname(fileURLToPath(import.meta.url));
const wizardSource = fs.readFileSync(
path.resolve(currentDirectory, '../../src/app/wizard/page.tsx'),
'utf8',
);
const ownModelSetupSource = fs.readFileSync(
path.resolve(
currentDirectory,
'../../src/app/wizard/components/OwnModelSetup.tsx',
),
'utf8',
);
const widgetSource = fs.readFileSync(
path.resolve(
currentDirectory,
'../../../src/langbot/templates/embed/widget.js',
),
'utf8',
);
test('shows the test-only notice only when the wizard opts in', () => {
assert.match(
wizardSource,
/widget\.js\?preview=wizard&v=\$\{Date\.now\(\)\}/,
);
assert.match(wizardSource, /script\.dataset\.testNotice = testNotice/);
assert.match(
wizardSource,
/testNotice=\{t\('wizard\.botConfig\.pageBotTestNotice'\)\}/,
);
assert.match(widgetSource, /getAttribute\("data-test-notice"\)/);
assert.match(widgetSource, /if \(scriptTestNotice\)/);
assert.match(widgetSource, /testNotice\.textContent = scriptTestNotice/);
});
test('defaults the AI engine step to the workbench option and lists it first', () => {
assert.match(
wizardSource,
/const \[aiChoice, setAiChoice\] = useState<[\s\S]*?>\('more-features'\);/,
);
const choicesStart = wizardSource.indexOf('const choices = [');
const moreFeaturesChoice = wizardSource.indexOf(
"id: 'more-features' as const",
choicesStart,
);
const externalChoice = wizardSource.indexOf(
"id: 'external' as const",
choicesStart,
);
const ownModelChoice = wizardSource.indexOf(
"id: 'own-model' as const",
choicesStart,
);
assert.ok(choicesStart >= 0);
assert.ok(moreFeaturesChoice > choicesStart);
assert.ok(moreFeaturesChoice < externalChoice);
assert.ok(moreFeaturesChoice < ownModelChoice);
});
test('uses the external-runner layout only while that configuration is open', () => {
assert.match(
wizardSource,
/currentStep === 2 && aiChoice === 'external' && selectedRunner/,
);
});
test('restores the default workbench choice when leaving a nested AI setup', () => {
assert.equal(
wizardSource.match(/onChoiceChange\('more-features'\)/g)?.length,
3,
);
});
test('warns local-account users after the bot receives an IM message', () => {
assert.match(
wizardSource,
/messageReceived && userInfo\?\.account_type !== 'space'/,
);
assert.match(
wizardSource,
/wizard\.botConfig\.messageReceivedLocalAccountWarning/,
);
assert.match(wizardSource, /<AlertTriangle className="size-3 text-white"/);
});
test('animates AI engine sub-pages and the return to choices', () => {
assert.match(
wizardSource,
/key="ai-engine-own-model"[\s\S]*?slide-in-from-right-4/,
);
assert.match(
wizardSource,
/key="ai-engine-external-picker"[\s\S]*?slide-in-from-right-4/,
);
assert.match(
wizardSource,
/key="ai-engine-choices"[\s\S]*?slide-in-from-left-4/,
);
assert.match(wizardSource, /motion-reduce:animate-none/);
});
test('aligns the own-model title and back button with external Agent setup', () => {
const ownModelTitle = ownModelSetupSource.indexOf(
"t('wizard.aiEngine.ownModelSetupTitle')",
);
const ownModelBack = ownModelSetupSource.indexOf(
"t('wizard.aiEngine.backToChoices')",
);
assert.ok(ownModelTitle >= 0);
assert.ok(ownModelBack > ownModelTitle);
assert.match(ownModelSetupSource, /mx-auto w-full max-w-4xl space-y-6/);
});
test('labels both external Agent setup states with their specific title', () => {
assert.equal(
wizardSource.match(/t\('wizard\.aiEngine\.externalTitle'\)/g)?.length,
3,
);
});