address greptile review feedback (greploop iteration 4)

- Fix P1: only show fetch-error banner for confirmed enterprise license
  holders, preventing misleading banner for non-enterprise users
- Fix P2: prevent concurrent in-flight requests with inFlight guard
- Fix P2: clarify test comments about ISO timestamp stripping behavior

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
yuneng-jiang 2026-03-24 09:19:58 -07:00
parent ec93880450
commit 34410d25e3
2 changed files with 22 additions and 9 deletions

View file

@ -147,8 +147,9 @@ describe("LicenseExpiryBanner", () => {
});
it("should handle expiration_date with a full ISO timestamp (not just date-only)", async () => {
// Backend might return "2026-03-22T15:00:00Z" instead of "2026-03-22"
// The component should strip the time part and still render correctly.
// Backend might return "2026-03-22T15:00:00Z" instead of "2026-03-22".
// The component strips the time part ("2026-03-22") and appends "T23:59:59Z",
// so the result is the same 8-day countdown as the date-only input.
mockGetLicenseInfo.mockResolvedValue(makeLicense("2026-03-22T15:00:00Z"));
render(<LicenseExpiryBanner />);
@ -173,14 +174,17 @@ describe("LicenseExpiryBanner", () => {
});
});
it("should show a warning when getLicenseInfo API call fails", async () => {
it("should not show error banner on first fetch failure for non-enterprise users", async () => {
mockGetLicenseInfo.mockRejectedValue(new Error("Network error"));
render(<LicenseExpiryBanner />);
expect(
await screen.findByText("Unable to verify enterprise license")
).toBeInTheDocument();
const { container } = render(<LicenseExpiryBanner />);
await waitFor(() => {
expect(mockGetLicenseInfo).toHaveBeenCalled();
});
// Non-enterprise users (no prior license info) should not see the error banner
await waitFor(() => {
expect(screen.queryByRole("alert")).toBeNull();
});
});
it("should render nothing when expiration_date is unparseable", async () => {

View file

@ -18,8 +18,11 @@ export const LicenseExpiryBanner: React.FC = () => {
if (!accessToken) return;
let cancelled = false;
let inFlight = false;
const fetchLicense = () => {
if (inFlight) return; // skip if a previous request is still pending
inFlight = true;
getLicenseInfo(accessToken)
.then((info) => {
if (!cancelled) {
@ -29,6 +32,9 @@ export const LicenseExpiryBanner: React.FC = () => {
})
.catch(() => {
if (!cancelled) setFetchError(true);
})
.finally(() => {
inFlight = false;
});
};
@ -41,7 +47,10 @@ export const LicenseExpiryBanner: React.FC = () => {
};
}, [accessToken]);
if (fetchError) {
// Only show a fetch-error banner if we previously confirmed this is an
// enterprise license holder. This prevents non-enterprise users from seeing
// a misleading "Unable to verify enterprise license" warning on network errors.
if (fetchError && licenseInfo?.has_license) {
return (
<Alert
message="Unable to verify enterprise license"