Fix label immutability help text (#37748)

- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually
- [x] Confirmed that the fix is not expected to adversely impact load
test results

---------

Co-authored-by: RachelElysia <71795832+RachelElysia@users.noreply.github.com>
This commit is contained in:
Ian Littman 2026-01-01 10:56:33 -06:00 committed by GitHub
parent 20e3b1c132
commit 889e2c0deb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 86 additions and 5 deletions

View file

@ -66,4 +66,77 @@ describe("LabelForm", () => {
true
);
});
it("should not render immutable help text when no immutable fields are provided (ManualLabelForm without team)", () => {
render(
<LabelForm
onSave={noop}
onCancel={noop}
teamName={null}
immutableFields={[]}
/>
);
// Help text container should not be in the document
expect(
screen.queryByText(
/are immutable\. To make changes, delete this label and create a new one\./
)
).not.toBeInTheDocument();
});
it("should render correct immutable help text for a single field (ManualLabelForm with team)", () => {
render(
<LabelForm
onSave={noop}
onCancel={noop}
teamName={"Example Team"}
immutableFields={["teams"]}
/>
);
expect(
screen.getByText(
"Label teams are immutable. To make changes, delete this label and create a new one."
)
).toBeInTheDocument();
});
it("should render correct immutable help text for two fields (DynamicLabelForm without team)", () => {
const immutableFields = ["queries", "platforms"];
render(
<LabelForm
onSave={noop}
onCancel={noop}
teamName={null}
immutableFields={immutableFields}
/>
);
expect(
screen.getByText(
"Label queries and platforms are immutable. To make changes, delete this label and create a new one."
)
).toBeInTheDocument();
expect(immutableFields.length).toBe(2);
});
it("should render correct immutable help text for three fields (DynamicLabelForm with team)", () => {
render(
<LabelForm
onSave={noop}
onCancel={noop}
teamName={"Example Team"}
immutableFields={["teams", "queries", "platforms"]}
/>
);
expect(
screen.getByText(
"Label teams, queries, and platforms are immutable. To make changes, delete this label and create a new one."
)
).toBeInTheDocument();
});
});

View file

@ -33,11 +33,19 @@ const generateDescriptionHelpText = (immutableFields: string[]) => {
const SUFFIX =
"are immutable. To make changes, delete this label and create a new one.";
return immutableFields.length === 1
? `Label ${immutableFields[0]} ${SUFFIX}`
: `Label ${immutableFields
.slice(0, -1)
.join(", ")} and ${immutableFields.pop()} ${SUFFIX}`;
if (immutableFields.length === 1) {
return `Label ${immutableFields[0]} ${SUFFIX}`;
}
if (immutableFields.length === 2) {
// No comma for two items: "queries and platforms"
return `Label ${immutableFields[0]} and ${immutableFields[1]} ${SUFFIX}`;
}
// 3+ items: Oxford comma before "and"
const allButLast = immutableFields.slice(0, -1).join(", ");
const last = immutableFields.slice(-1);
return `Label ${allButLast}, and ${last} ${SUFFIX}`;
};
const LabelForm = ({