fix(timeline): clear multi-select on drag start and lock in SSE edge-case coverage

- useTimelineDrag: onProjectBarMouseDown and single-alloc drag path now reset
  multiSelectRef + multiSelectState before starting a new drag, so the
  FloatingActionBar is dismissed immediately when an unrelated drag begins
- FloatingActionBar.test.tsx: 4 regression tests for the null-render guard
  (count=0) and all three label variants
- useTimelineSSE.test.ts: 2 new tests — tab hides during pending reconnect
  timer (clears timer, resyncs on next open) and first-ever connection fails
  before any open (retry open still resyncs correctly)
- assistant-tools-user-admin-inventory-read.test.ts: add isActive to expected
  findMany select shape (already in production, test was stale)

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
2026-04-02 21:16:10 +02:00
parent 8d9e26872b
commit e7e525df49
6 changed files with 231 additions and 63 deletions
@@ -0,0 +1,64 @@
import React from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { describe, expect, it, vi } from "vitest";
import { FloatingActionBar } from "./FloatingActionBar.js";
const noop = vi.fn();
describe("FloatingActionBar", () => {
it("renders nothing when no items are selected", () => {
const html = renderToStaticMarkup(
<FloatingActionBar
selectedAllocationCount={0}
selectedResourceCount={0}
onDelete={noop}
onAssign={noop}
onClear={noop}
isDeleting={false}
/>,
);
expect(html).toBe("");
});
it("shows allocation count label when allocations are selected", () => {
const html = renderToStaticMarkup(
<FloatingActionBar
selectedAllocationCount={2}
selectedResourceCount={0}
onDelete={noop}
onAssign={noop}
onClear={noop}
isDeleting={false}
/>,
);
expect(html).toMatch(/2 allocations selected/i);
});
it("shows resource count label when resources are selected", () => {
const html = renderToStaticMarkup(
<FloatingActionBar
selectedAllocationCount={0}
selectedResourceCount={1}
onDelete={noop}
onAssign={noop}
onClear={noop}
isDeleting={false}
/>,
);
expect(html).toMatch(/1 resource selected/i);
});
it("shows combined label when both allocations and resources are selected", () => {
const html = renderToStaticMarkup(
<FloatingActionBar
selectedAllocationCount={1}
selectedResourceCount={1}
onDelete={noop}
onAssign={noop}
onClear={noop}
isDeleting={false}
/>,
);
expect(html).toMatch(/1 allocation.*1 resource/i);
});
});
@@ -1,5 +1,6 @@
"use client";
import React from "react";
import { clsx } from "clsx";
interface FloatingActionBarProps {