address greptile review feedback (greploop iteration 1)

- Fix P1: strip existing time component from expiration_date before
  appending end-of-day time to prevent NaN when backend returns full
  ISO timestamps
- Fix P2: append Z suffix for explicit UTC parsing
- Fix P2: restore global.Date in afterEach to prevent mock leaking
- Add test for full ISO timestamp input edge case

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
yuneng-jiang 2026-03-24 05:28:17 -07:00
parent 6d21a31e66
commit 3d472aa21e
2 changed files with 19 additions and 3 deletions

View file

@ -19,6 +19,7 @@ const mockGetLicenseInfo = vi.mocked(getLicenseInfo);
const FIXED_NOW = new Date("2026-03-15T12:00:00Z").getTime();
let realDateNow: () => number;
let OrigDate: typeof Date;
function makeLicense(expirationDate: string) {
return {
@ -34,9 +35,8 @@ describe("LicenseExpiryBanner", () => {
beforeEach(() => {
vi.clearAllMocks();
realDateNow = Date.now;
OrigDate = Date; // capture before patching so we can restore in afterEach
Date.now = () => FIXED_NOW;
// Also override new Date() with no args
const OrigDate = Date;
const MockDate = class extends OrigDate {
constructor(...args: any[]) {
if (args.length === 0) {
@ -70,6 +70,7 @@ describe("LicenseExpiryBanner", () => {
});
afterEach(() => {
global.Date = OrigDate;
Date.now = realDateNow;
});
@ -145,6 +146,18 @@ describe("LicenseExpiryBanner", () => {
expect(container.innerHTML).toBe("");
});
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.
mockGetLicenseInfo.mockResolvedValue(makeLicense("2026-03-22T15:00:00Z"));
render(<LicenseExpiryBanner />);
expect(
await screen.findByText("Enterprise License Expiring in 8 days")
).toBeInTheDocument();
});
it("should not render when has_license is false", async () => {
mockGetLicenseInfo.mockResolvedValue({
...makeLicense("2026-03-20"),

View file

@ -23,7 +23,10 @@ export const LicenseExpiryBanner: React.FC = () => {
return null;
}
const expDate = new Date(licenseInfo.expiration_date + "T23:59:59");
// Strip any existing time component so we always get a valid date-only base,
// then append end-of-day in UTC to avoid timezone-dependent parsing.
const dateOnly = licenseInfo.expiration_date.split("T")[0];
const expDate = new Date(dateOnly + "T23:59:59Z");
const now = new Date();
const diffMs = expDate.getTime() - now.getTime();
const daysRemaining = Math.ceil(diffMs / (1000 * 60 * 60 * 24));