FN-5797: fix usage indicator show hidden button behavior
Prevent hidden-window controls in UsageIndicator from acting as implicit form submitters. - Set both window-level Hide and provider-level Show hidden buttons to `type="button"`. - Preserve hidden-window reveal behavior without submitting parent forms. - Add a regression test covering hide/show persistence and rerender re-sync behavior. Files changed: .changeset/fn-5797-show-hidden-fix.md | 8 +++++ packages/dashboard/app/components/UsageIndicator.tsx | 2 ++ packages/dashboard/app/components/__tests__/UsageIndicator.test.tsx | 40 ++++++++++++++++++++++ 3 files changed, 50 insertions(+) Fusion-Task-Id: FN-5797 Fusion-Task-Lineage: 9072bb68-b86b-4ec7-8b1f-0e6b706cbb5f
This commit is contained in:
8
.changeset/fn-5797-show-hidden-fix.md
Normal file
8
.changeset/fn-5797-show-hidden-fix.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
"@runfusion/fusion": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixes the UsageIndicator popup hidden-window recovery flow by preventing hide/show controls from acting as implicit form-submit buttons.
|
||||||
|
|
||||||
|
- Sets the per-window hide control and provider-level **Show hidden (N)** control to `type="button"` so they do not trigger parent form submits.
|
||||||
|
- Adds a regression test that verifies clicking **Show hidden** reveals hidden windows, persists the unhidden state, and remains correct after rerender/state re-sync.
|
||||||
@@ -238,6 +238,7 @@ function UsageWindowRow({ window, viewMode, isHidden, onToggleHidden }: UsageWin
|
|||||||
{!isHidden && <span className="usage-window-percentage">{headerText}</span>}
|
{!isHidden && <span className="usage-window-percentage">{headerText}</span>}
|
||||||
{!isHidden && (
|
{!isHidden && (
|
||||||
<button
|
<button
|
||||||
|
type="button"
|
||||||
className="btn-icon usage-window-hide-btn"
|
className="btn-icon usage-window-hide-btn"
|
||||||
onClick={onToggleHidden}
|
onClick={onToggleHidden}
|
||||||
aria-label={`Hide ${window.label}`}
|
aria-label={`Hide ${window.label}`}
|
||||||
@@ -444,6 +445,7 @@ function ProviderCard({
|
|||||||
<span className="usage-provider-name">{provider.name}</span>
|
<span className="usage-provider-name">{provider.name}</span>
|
||||||
{hiddenCount > 0 && (
|
{hiddenCount > 0 && (
|
||||||
<button
|
<button
|
||||||
|
type="button"
|
||||||
className="btn btn-sm usage-show-hidden-btn"
|
className="btn btn-sm usage-show-hidden-btn"
|
||||||
onClick={() => onShowAllHidden(provider.name)}
|
onClick={() => onShowAllHidden(provider.name)}
|
||||||
data-testid="usage-show-hidden-btn"
|
data-testid="usage-show-hidden-btn"
|
||||||
|
|||||||
@@ -979,6 +979,46 @@ describe("UsageIndicator", () => {
|
|||||||
expect(screen.getByRole("button", { name: "Hide Weekly" })).toBeInTheDocument();
|
expect(screen.getByRole("button", { name: "Hide Weekly" })).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("show hidden remains revealed across rerender and does not submit parent forms", () => {
|
||||||
|
mockUseUsageData.mockReturnValue({
|
||||||
|
providers: mockProviders,
|
||||||
|
loading: false,
|
||||||
|
error: null,
|
||||||
|
lastUpdated: new Date(),
|
||||||
|
refresh: mockRefresh,
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = vi.fn((event: Event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
const { rerender } = render(
|
||||||
|
<form onSubmit={onSubmit}>
|
||||||
|
<UsageIndicator isOpen={true} onClose={mockOnClose} projectId={TEST_PROJECT_ID} />
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole("button", { name: "Hide Session (5h)" }));
|
||||||
|
expect(localStorage.getItem(USAGE_HIDDEN_WINDOWS_KEY)).toBe(
|
||||||
|
JSON.stringify({ Anthropic: ["Session (5h)"] })
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByTestId("usage-show-hidden-btn"));
|
||||||
|
|
||||||
|
expect(onSubmit).not.toHaveBeenCalled();
|
||||||
|
expect(localStorage.getItem(USAGE_HIDDEN_WINDOWS_KEY)).toBe(JSON.stringify({}));
|
||||||
|
expect(screen.getByText("Session (5h)").closest(".usage-window")).not.toHaveClass("usage-window--hidden");
|
||||||
|
|
||||||
|
rerender(
|
||||||
|
<form onSubmit={onSubmit}>
|
||||||
|
<UsageIndicator isOpen={true} onClose={mockOnClose} projectId={TEST_PROJECT_ID} />
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.queryByTestId("usage-show-hidden-btn")).not.toBeInTheDocument();
|
||||||
|
expect(screen.getByText("Session (5h)").closest(".usage-window")).not.toHaveClass("usage-window--hidden");
|
||||||
|
});
|
||||||
|
|
||||||
it("does not show provider-level show hidden button when no windows are hidden", () => {
|
it("does not show provider-level show hidden button when no windows are hidden", () => {
|
||||||
mockUseUsageData.mockReturnValue({
|
mockUseUsageData.mockReturnValue({
|
||||||
providers: mockProviders,
|
providers: mockProviders,
|
||||||
|
|||||||
Reference in New Issue
Block a user