Files
Agent-System/web/src/lib/dutyCellAssertion.ts
T
weichenandCursor c8318e8551 fix(e2e): read duty from select value, not row option text
UI-13a treated concatenated select options as the current role.
Assert the control value or badge role for that doc instead.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-13 21:26:23 +00:00

62 lines
2.2 KiB
TypeScript

export const DOC_DUTY_ROW_TESTID = 'doc-duty-row';
export const DOC_DUTY_SELECT_TESTID = 'doc-duty-select';
export const DOC_DUTY_BADGE_TESTID = 'doc-duty-badge';
export const DOC_DUTY_ROLES = ['author', 'reviewer', 'approver', 'viewer'] as const;
export type DocDutyRole = (typeof DOC_DUTY_ROLES)[number];
export type DutyCellInput =
| { source: 'select'; value: string; disabled: boolean; canAssignLead: boolean }
| { source: 'badge'; role: string }
| { source: 'row-text'; text: string };
export type DutyCellVerdict = {
ok: boolean;
role?: DocDutyRole;
reason: string;
};
export function isDocDutyRole(value: string): value is DocDutyRole {
return (DOC_DUTY_ROLES as readonly string[]).includes(value);
}
export function resolveDutyCell(input: DutyCellInput): { role: DocDutyRole; disabled?: boolean } {
if (input.source === 'row-text') {
throw new Error('must_not_infer_duty_from_row_option_text');
}
if (input.source === 'select') {
if (!isDocDutyRole(input.value)) {
throw new Error(`unknown_duty_select_value:${input.value}`);
}
return { role: input.value, disabled: input.disabled };
}
if (!isDocDutyRole(input.role)) {
throw new Error(`unknown_duty_badge_role:${input.role}`);
}
return { role: input.role };
}
export function isAcceptableReviewerOrViewer(role: DocDutyRole): boolean {
return role === 'reviewer' || role === 'viewer';
}
/** Reviewer B intake: current control value, never the concatenated option labels. */
export function evaluateReviewerOrViewerDuty(input: DutyCellInput): DutyCellVerdict {
if (input.source === 'row-text') {
return { ok: false, reason: 'must_not_infer_duty_from_row_option_text' };
}
let role: DocDutyRole;
try {
role = resolveDutyCell(input).role;
} catch (err) {
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
}
if (!isAcceptableReviewerOrViewer(role)) {
return { ok: false, role, reason: `unexpected_duty:${role}` };
}
if (input.source === 'select' && !input.canAssignLead && !input.disabled) {
return { ok: false, role, reason: 'reviewer_select_must_be_disabled_when_cannot_assign' };
}
return { ok: true, role, reason: 'ok' };
}