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>
62 lines
2.2 KiB
TypeScript
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' };
|
|
}
|