mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
fix(web): cancel stale invite dialog close timer (#6580)
This commit is contained in:
@@ -111,6 +111,7 @@ export function InviteDialog({
|
||||
const rowsRef = useRef<HTMLDivElement | null>(null);
|
||||
const roleTriggerRefs = useRef<Array<HTMLButtonElement | null>>([]);
|
||||
const roleMenuRef = useRef<HTMLDivElement | null>(null);
|
||||
const autoCloseTimerRef = useRef<number | null>(null);
|
||||
const [roleMenuPos, setRoleMenuPos] = useState<CSSProperties | null>(null);
|
||||
const roleListboxId = useId();
|
||||
|
||||
@@ -163,6 +164,12 @@ export function InviteDialog({
|
||||
if (!open) setOpenRoleIndex(null);
|
||||
}, [open]);
|
||||
|
||||
useEffect(() => () => {
|
||||
if (autoCloseTimerRef.current === null) return;
|
||||
window.clearTimeout(autoCloseTimerRef.current);
|
||||
autoCloseTimerRef.current = null;
|
||||
}, [open]);
|
||||
|
||||
// Reset the submit lifecycle each time the dialog opens so a prior error /
|
||||
// success never lingers on the next invite.
|
||||
useEffect(() => {
|
||||
@@ -337,7 +344,8 @@ export function InviteDialog({
|
||||
}, { requestId });
|
||||
setSuccess(true);
|
||||
onSubmit?.(valid);
|
||||
window.setTimeout(() => {
|
||||
autoCloseTimerRef.current = window.setTimeout(() => {
|
||||
autoCloseTimerRef.current = null;
|
||||
onClose();
|
||||
setRows([{ email: '', role: DEFAULT_ROLE }]);
|
||||
setSuccess(false);
|
||||
|
||||
@@ -670,6 +670,50 @@ test('[P0] team owner completes a multi-row invite with explicit roles', async (
|
||||
await expect(dialog).toHaveCount(0, { timeout: 5_000 });
|
||||
});
|
||||
|
||||
test('[P1] stale invite success timer does not close a reopened dialog', async ({ page }) => {
|
||||
await page.addInitScript(
|
||||
({ workspaceId, workspaceMemberId }) => {
|
||||
window.sessionStorage.setItem(
|
||||
'od.workspaceSelection.v1',
|
||||
JSON.stringify({ workspaceId, workspaceMemberId }),
|
||||
);
|
||||
},
|
||||
{
|
||||
workspaceId: TEAM_OWNER.workspaceId,
|
||||
workspaceMemberId: TEAM_OWNER.workspaceMemberId,
|
||||
},
|
||||
);
|
||||
await wireWorkspaceMocks(page, TEAM_OWNER, [PERSONAL, TEAM_OWNER]);
|
||||
await gotoHome(page);
|
||||
await ensureRailOpen(page);
|
||||
await page.clock.install();
|
||||
await page.clock.pauseAt((await page.evaluate(() => Date.now())) + 60_000);
|
||||
|
||||
await page.getByTestId('workspace-switcher').click();
|
||||
await page.getByRole('menu').getByRole('menuitem', { name: 'Invite colleague' }).click();
|
||||
|
||||
const dialog = page.getByRole('dialog', { name: 'Invite members' });
|
||||
const emailInput = dialog.getByPlaceholder('Enter email address…').first();
|
||||
await emailInput.fill('first@example.com');
|
||||
await dialog.getByRole('button', { name: 'Confirm and invite' }).click();
|
||||
await expect(dialog.getByRole('button', { name: 'Invitation sent' })).toBeVisible();
|
||||
|
||||
await dialog.getByRole('button', { name: 'Close' }).click();
|
||||
await page.getByTestId('workspace-switcher').click();
|
||||
await page.getByRole('menu').getByRole('menuitem', { name: 'Invite colleague' }).click();
|
||||
await expect(dialog).toBeVisible();
|
||||
await emailInput.fill('second@example.com');
|
||||
|
||||
await page.clock.fastForward(999);
|
||||
await expect(dialog).toBeVisible();
|
||||
await expect(emailInput).toHaveValue('second@example.com');
|
||||
|
||||
await page.clock.fastForward(1);
|
||||
|
||||
await expect(dialog).toBeVisible();
|
||||
await expect(emailInput).toHaveValue('second@example.com');
|
||||
});
|
||||
|
||||
test('[P0] full team routes every invite entry to Vela seat resolution without opening the local dialog', async ({
|
||||
page,
|
||||
}) => {
|
||||
|
||||
Reference in New Issue
Block a user