ui: finalize wizard modularization

This commit is contained in:
a.tolmachev
2026-05-02 20:17:17 +00:00
parent 95d9006d70
commit fa2a98765d
6 changed files with 30 additions and 40 deletions
+10 -32
View File
@@ -2,42 +2,20 @@
## Current
### `feat/frontend-wizard-modularization`
### `feat/websocket-test-run-polish`
Status: in_progress
Status: ready
DoD:
- `wizard.js` is split by responsibility into smaller files with stable ownership boundaries
- extracted modules keep existing wizard behavior and asset build flow
- modularization changes pass UI build and targeted wizard smoke checks
- websocket test-run flow clearly reports bounded results, reconnect/error states, and final status
- operator-facing UI reflects websocket-specific runtime semantics instead of generic streaming copy
- targeted UI checks cover websocket wizard/test-run behavior
## Next
- `feat/distributed-mcp-session-store`
## Backlog
- `feat/frontend-xss-hardening`
- `feat/frontend-login-simplification`
- `feat/frontend-settings-honesty-pass`
- `feat/frontend-command-palette-decision`
- `feat/frontend-plural-rules`
- `feat/frontend-template-safety-cleanup`
- `feat/frontend-shell-unification`
- `feat/frontend-wizard-modularization`
- `feat/frontend-css-state-cleanup`
- `feat/frontend-performance-polish`
- `feat/frontend-wizard-modularization`
- `feat/frontend-observability-and-testability`
- `feat/id-display-support`
- `feat/postgres-pool-config`
- `feat/postgres-registry-modularization`
- `feat/sqlx-compile-time-verification`
- `feat/secret-crypto-hkdf`
- `feat/typed-timestamps`
- `feat/error-structure-normalization`
- `feat/correlation-id-propagation`
- `feat/runtime-rate-limiting-and-backpressure`
- `feat/distributed-mcp-session-store`
- `feat/websocket-test-run-polish`
- `feat/live-authenticated-staging-entry`
## Completed
- `feat/frontend-wizard-modularization`
- `feat/distributed-mcp-session-store`
+2
View File
@@ -318,6 +318,8 @@
updateStreamingConfigVisibility();
},
serializeStreamingConfig: serializeStreamingConfig,
updateStreamingModeOptions: updateStreamingModeOptions,
updateStreamingConfigVisibility: updateStreamingConfigVisibility,
deserializeStreamingConfig: function(streaming) {
if (typeof window.applyStreamingConfig === 'function') {
window.applyStreamingConfig(streaming);
+3
View File
@@ -1,3 +1,6 @@
var updateStreamingModeOptions = window.CrankStreamingForm.updateStreamingModeOptions;
var updateStreamingConfigVisibility = window.CrankStreamingForm.updateStreamingConfigVisibility;
function buildToolDescription() {
return {
title: textValue('tool-title') || textValue('tool-display-name') || textValue('tool-name'),
+5 -4
View File
@@ -53,10 +53,11 @@ function mappingRootForProtocol(protocol) {
}
function normalizeInputSource(path) {
if (!path) return '$.input';
if (path === '$') return '$.input';
if (path.indexOf('$.input') === 0) return path;
return '$.input.' + path.replace(/^\$\./, '');
if (!path) return '$.mcp';
if (path === '$') return '$.mcp';
if (path.indexOf('$.mcp') === 0) return path;
if (path.indexOf('$.input') === 0) return '$.mcp' + path.slice('$.input'.length);
return '$.mcp.' + path.replace(/^\$\./, '');
}
function normalizeOutputSource(path) {
+3
View File
@@ -84,6 +84,7 @@ async function initWizardPage() {
await (window.whenWorkspacesReady ? window.whenWorkspacesReady() : Promise.resolve());
var workspace = window.getCurrentWorkspace ? window.getCurrentWorkspace() : null;
wizardWorkspaceId = workspace ? workspace.id : null;
window.wizardWorkspaceId = wizardWorkspaceId;
await loadProtocolCapabilities();
await loadWizardPanels([1, 2, 3, 4, 5]);
@@ -130,6 +131,8 @@ async function initWizardPage() {
if (params.get('mode') === 'edit' && params.get('operationId')) {
wizardMode = 'edit';
wizardEditId = params.get('operationId');
window.wizardMode = wizardMode;
window.wizardEditId = wizardEditId;
document.title = 'Crank — ' + tKey('wizard.progress.edit');
await loadOperationForEdit();
}
+7 -4
View File
@@ -12,11 +12,10 @@ const {
test('wizard loads and protocol selection updates flow', async ({ page }) => {
await login(page);
await page.goto('/wizard/');
await expect(page.locator('[data-step-counter]')).toContainText(localized('Step', 'Шаг'));
await expect(page.locator('[data-step-counter]').first()).toContainText(localized('Step', 'Шаг'));
await expect(page.locator('#step-panel-1 .step-panel-title')).toContainText(localized('Choose a protocol', 'Выберите протокол'));
await page.getByText(/graphql/i).first().click();
await page.locator('#btn-continue').click();
await expect(page.locator('[data-step-counter]')).toContainText(/2/);
await expect(page.locator('#step-panel-2 .step-panel-title')).toContainText(localized('Select upstream', 'Выберите upstream'));
});
@@ -82,8 +81,12 @@ test('soap wizard uploads wsdl, applies discovered binding and runs test', async
}, null, 2));
await page.locator('#btn-continue').click();
await expect(page.locator('[data-i18n="wizard.step5.test_title"]')).toContainText(localized('Test run', 'Тестовый запуск'));
await page.locator('#tool-input-mapping').fill('email: "$.input.email"');
await page.locator('#tool-output-mapping').fill('id: "$.response.body.id"');
await page.locator('#tool-input-mapping').fill(JSON.stringify({
email: '$.input.email',
}, null, 2));
await page.locator('#tool-output-mapping').fill(JSON.stringify({
id: '$.response.body.id',
}, null, 2));
await page.locator('#tool-exec-config').fill('timeout_ms: 1000');
await page.locator('#wizard-test-input').fill(JSON.stringify({ email: 'user@example.com' }, null, 2));