Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/pages/audit-report/components/View/GlobalFiltersForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ type GlobalFiltersFormProps = {
currentVariables?: Record<string, string>;
};

const EMPTY_VARIABLES: Record<string, string> = {};

function GlobalFiltersListener({
children,
variables,
globalVarPrefix,
currentVariables = {}
currentVariables = EMPTY_VARIABLES
}: GlobalFiltersFormProps): React.ReactElement {
const { values, setFieldValue } =
useFormikContext<Record<string, string | undefined>>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from "react";
import { render, screen } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import GlobalFiltersForm from "../GlobalFiltersForm";
import type { ViewVariable } from "../../../types";

const testVariables: ViewVariable[] = [
{
key: "namespace",
value: "",
type: "select",
options: ["ns-a", "ns-b"],
default: "ns-a"
}
];

function renderWithRouter(ui: React.ReactElement, { initialPath = "/" } = {}) {
return render(
<MemoryRouter initialEntries={[initialPath]}>{ui}</MemoryRouter>
);
}

describe("GlobalFiltersForm — update stability (bug #2948)", () => {
let maxDepthErrors: string[];
const originalConsoleError = console.error;

beforeEach(() => {
maxDepthErrors = [];
console.error = (...args: unknown[]) => {
const msg = String(args[0]);
if (msg.includes("Maximum update depth exceeded")) {
maxDepthErrors.push(msg);
return;
}
originalConsoleError(...args);
};
});

afterEach(() => {
console.error = originalConsoleError;
});

/**
* GlobalFiltersListener has two useEffects that sync Formik ↔ URL.
*
* Effect 2 depends on `currentVariables` which previously defaulted to
* a **new `{}` on every render** via the destructuring default. Each
* render created a fresh object → React saw a changed dependency →
* Effect 2 fired → called setFieldValue → triggered a Formik re-render
* → new `{}` again → infinite loop.
*
* The fix replaces the inline `{}` with a module-level constant so the
* reference is stable across renders.
*/
it("does not trigger an infinite update loop on mount", () => {
renderWithRouter(
<GlobalFiltersForm variables={testVariables} globalVarPrefix="viewvar">
<div data-testid="child">hello</div>
</GlobalFiltersForm>
);

expect(screen.getByTestId("child")).toBeInTheDocument();
expect(maxDepthErrors).toHaveLength(0);
});
});
Loading
Loading