eigent/test/unit/components/ChatBox/BottomBox/controlArbitration.test.ts
Douglas Lai 88f530358e
Some checks are pending
Pre-commit / pre-commit (push) Waiting to run
Test / Run Web + Local Brain Smoke (push) Waiting to run
Test / Run Frontend Guardrails (push) Waiting to run
Test / Run Python Tests (push) Waiting to run
Redesign two chat timeline view (#1856)
Co-authored-by: 4pmtong <web_chentong@163.com>
2026-08-20 23:48:54 +08:00

119 lines
3.6 KiB
TypeScript

// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
import { selectBottomBoxControl } from '@/components/ChatBox/BottomBox/controlArbitration';
import type {
BottomBoxApprovalVariant,
BottomBoxInputVariant,
BottomBoxRunControlVariant,
} from '@/components/ChatBox/BottomBox/types';
import { describe, expect, it, vi } from 'vitest';
function approvalVariant(): BottomBoxApprovalVariant {
return {
kind: 'approval',
header: { title: 'Allow this action?' },
options: [{ scope: 'once', label: 'Approve once' }],
onApprove: vi.fn(),
onReject: vi.fn(),
};
}
function runControlVariant(): BottomBoxRunControlVariant {
return {
kind: 'run_control',
header: { title: 'Run interrupted' },
runId: 'run-1',
state: 'interrupted',
onResume: vi.fn(),
onCancel: vi.fn(),
};
}
describe('BottomBox control arbitration', () => {
it('gives a pending human interaction priority over Run controls and the composer', () => {
const humanInteractionVariant = approvalVariant();
const selection = selectBottomBoxControl({
humanInteractionVariant,
runControlVariant: runControlVariant(),
composerVariant: 'input',
});
expect(selection).toEqual({
variant: humanInteractionVariant,
source: 'human_interaction',
isControlled: true,
});
});
it('gives Run controls priority over the composer', () => {
const runControl = runControlVariant();
const selection = selectBottomBoxControl({
runControlVariant: runControl,
composerVariant: 'input',
});
expect(selection).toEqual({
variant: runControl,
source: 'run_control',
isControlled: true,
});
});
it('preserves a decorated legacy input composer and otherwise uses the normal composer', () => {
const composerVariant: BottomBoxInputVariant = {
kind: 'input',
header: {
eyebrow: 'Input required',
title: 'Which output tone should I use?',
},
};
expect(selectBottomBoxControl({ composerVariant })).toEqual({
variant: composerVariant,
source: 'composer',
isControlled: false,
});
expect(selectBottomBoxControl({})).toEqual({
variant: 'input',
source: 'composer',
isControlled: false,
});
});
it('uses identical control authority for every event-native timeline style', () => {
const humanInteractionVariant = approvalVariant();
const runControl = runControlVariant();
const styles = ['normal', 'detailed', 'summarised'] as const;
const selections = styles.map(() =>
selectBottomBoxControl({
humanInteractionVariant,
runControlVariant: runControl,
composerVariant: 'input',
})
);
expect(selections.map((selection) => selection.variant)).toEqual([
humanInteractionVariant,
humanInteractionVariant,
humanInteractionVariant,
]);
expect(selections.map((selection) => selection.source)).toEqual([
'human_interaction',
'human_interaction',
'human_interaction',
]);
});
});