Skip to content

Conversation

@zebrapurring
Copy link
Contributor

@zebrapurring zebrapurring commented Sep 17, 2025

What type of PR is this?

  • bug
  • cleanup

What this PR does / why we need it:

Fix failing unit tests blocking the CI.

Which issue(s) this PR fixes:

-

Special notes for your reviewer:

-

Testing

cd backend && go build ./app/api && cd -
cd frontend
pnpm install
../backend/api & pnpm run test:ci

Summary by CodeRabbit

  • Bug Fixes

    • Improved date normalization to consistently set times to midnight across time zones, reducing unexpected date shifts.
  • Tests

    • Updated and streamlined date utility tests to reflect current behavior.
  • Chores

    • Adjusted CI test execution to improve reliability by limiting file-level parallelism.
    • Broadened ignore rules to prevent accidental inclusion of temporary data across the repository.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 17, 2025

Walkthrough

The PR adjusts timezone handling in date utilities and tests, modifies a currency item validator’s TypeScript typing, updates a CI test script to disable file parallelism, broadens a .gitignore pattern for .data directories, and removes trailing whitespace in a Vue component’s style block.

Changes

Cohort / File(s) Summary
Date utils and tests
frontend/lib/datelib/datelib.ts, frontend/lib/datelib/datelib.test.ts
zeroTime now zeroes hours on a cloned Date via setHours(0,0,0,0) instead of constructing local midnight and adjusting by timezone offset. Tests switch Date construction to Date.UTC(...) for UTC-based instantiation.
Currency utils
frontend/composables/utils.ts
Added type import CurrenciesCurrency. Replaced a type-predicate validator with a boolean-returning function; validation logic unchanged. Affects type narrowing at call sites only.
Frontend test script
frontend/package.json
Updated test:ci to add --no-file-parallelism to vitest command.
Git ignore rule
.gitignore
Adjusted ignore rule from /.data/ to .data/ within docs VitePress cache section to match .data directories anywhere.
Styling whitespace
frontend/components/global/DetailsSection/DetailsSection.vue
Removed trailing blank lines in <style> block; no functional changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor UI as UI
  participant Utils as utils.loadCurrencyDecimals
  participant API as Currency API
  participant Cache as Local Cache

  UI->>Utils: request decimals for currency codes
  Utils->>Cache: check cached decimals
  alt cache hit
    Cache-->>Utils: return decimals
    Utils-->>UI: decimals
  else cache miss
    Utils->>API: fetch currency items
    API-->>Utils: items[]
    Utils->>Utils: isValidCurrencyItem(item): boolean
    Utils->>Cache: store UPPERCASE(code) -> clamped decimals
    Utils-->>UI: decimals
  end

  note over Utils: Validator now returns boolean (no TS type-narrowing)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Security recommendations

  • Verify timezone logic: add tests across DST boundaries and different locales to ensure zeroTime remains consistent and doesn’t shift dates around midnight.
  • Validate external data: ensure isValidCurrencyItem robustly guards against untrusted API data (unexpected types, NaN, large decimals). Consider runtime schema validation (e.g., zod) if not already used.
  • Logging/metrics: add error logging when currency validation fails to detect malformed inputs without exposing sensitive data.
  • CI determinism: disabling file parallelism can mask race conditions; keep a periodic parallel run in non-blocking CI to surface concurrency issues safely.
  • .gitignore change: confirm it won’t unintentionally hide important .data folders from version control reviews (e.g., migrations or fixtures). Ensure secrets are not committed elsewhere.

Poem

Dates are tamed at midnight’s gate,
UTC whispers, “replicate.”
Coins get checked—no sleights, no scams,
Booleans nod with steady hands.
Tests march single-file, in line,
Cache hums softly: “All is fine.”
Git sweeps crumbs of .data shine.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description Check ⚠️ Warning The description includes the required template headings but lacks the bullet pointed summary of file changes and explanations of decisions under the “What this PR does” section, leaving the reviewer without detailed context of the modifications made. Please add a bullet pointed summary of each file changed under the “What this PR does” section and briefly explain any implementation decisions to align with the repository’s PR description template.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title succinctly and accurately describes the primary change, which is addressing failing tests blocking the CI, and is clear and concise for quick scanning.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/composables/utils.ts (1)

167-174: Security: restrict bracketed link scheme to http(s) to prevent javascript: URLs.

[text](javascript:...) currently sets isUrl=true. Enforce allowed protocols.

-    if (match && match.length === 3) {
-      result.isUrl = true;
-      result.text = match[1]!;
-      result.url = match[2]!;
-    }
+    if (match && match.length === 3) {
+      const url = match[2]!;
+      const allowed = url.startsWith("http://") || url.startsWith("https://");
+      if (allowed) {
+        result.isUrl = true;
+        result.text = match[1]!;
+        result.url = url;
+      }
+    }
🧹 Nitpick comments (6)
.gitignore (1)

63-63: Broadened .data/ ignore may hide unintended directories. Scope it.

This now ignores any .data/ anywhere. If the intent was only VitePress cache, restrict the glob.

Apply:

- .data/
+ docs/.vitepress/cache/.data/
frontend/package.json (1)

12-12: Good call to disable file parallelism for CI flake reduction.

Watch for longer runtimes; consider gating slow suites instead of global serialization.

Optional:

- "test:ci": "TEST_SHUTDOWN_API_SERVER=true vitest --run --config ./test/vitest.config.ts --no-file-parallelism",
+ "test:ci": "pnpm run typecheck && TEST_SHUTDOWN_API_SERVER=true vitest --run --config ./test/vitest.config.ts --no-file-parallelism",
frontend/lib/datelib/datelib.test.ts (2)

17-17: Test passes, but verify intent (local vs UTC).

If you adopt UTC zeroing, assert getUTCHours() instead; otherwise current local‑midnight assertion is fine.


44-49: Add a parse→format round‑trip test to prevent regressions.

Catches the UTC/local mismatch described earlier.

 describe("parse", () => {
   test("should parse a date string", () => {
     const date = parse("2020-02-01");
     expect(date).toBeInstanceOf(Date);
   });
 });
+
+describe("roundtrip", () => {
+  test("parse(format(d)) preserves calendar day", () => {
+    const s = "2020-02-01";
+    const d = parse(s);
+    expect(format(d)).toBe(s);
+  });
+});
frontend/composables/utils.ts (2)

47-62: Restore type predicate to regain compile‑time narrowing and safer API use.

Current boolean return loses narrowing and requires CurrenciesCurrency at call sites (which may be unknown from the API).

-function isValidCurrencyItem(item: CurrenciesCurrency): boolean {
+function isValidCurrencyItem(item: unknown): item is CurrenciesCurrency {
-  if (
-    typeof item !== "object" ||
-    item === null ||
-    typeof item.code !== "string" ||
-    item.code.trim() === "" ||
-    typeof item.decimals !== "number" ||
-    !Number.isFinite(item.decimals)
-  ) {
+  if (typeof item !== "object" || item === null) return false;
+  const rec = item as Partial<CurrenciesCurrency> & { decimals?: unknown };
+  if (typeof rec.code !== "string" || rec.code.trim() === "") return false;
+  if (typeof rec.decimals !== "number" || !Number.isFinite(rec.decimals)) return false;
     return false;
-  }
-  // Truncate decimals to integer and check range
-  const truncatedDecimals = Math.trunc(item.decimals);
+  // Truncate decimals to integer and check range
+  const truncatedDecimals = Math.trunc(rec.decimals);
   return truncatedDecimals >= SAFE_MIN_DECIMALS && truncatedDecimals <= SAFE_MAX_DECIMALS;
 }

95-109: Security/perf: guard against oversized currency lists from API.

Unbounded loops can spike memory/CPU if the endpoint misbehaves.

-        for (const currency of data) {
+        const MAX_ITEMS = 500;
+        for (const currency of data.slice(0, MAX_ITEMS)) {
           // Strict validation: only process items that pass all checks
           if (!isValidCurrencyItem(currency)) {
             // Skip invalid items without caching - no clamping for out-of-range values
             continue;
           }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b565054 and f97fd53.

📒 Files selected for processing (6)
  • .gitignore (1 hunks)
  • frontend/components/global/DetailsSection/DetailsSection.vue (0 hunks)
  • frontend/composables/utils.ts (2 hunks)
  • frontend/lib/datelib/datelib.test.ts (2 hunks)
  • frontend/lib/datelib/datelib.ts (1 hunks)
  • frontend/package.json (1 hunks)
💤 Files with no reviewable changes (1)
  • frontend/components/global/DetailsSection/DetailsSection.vue
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-12T23:36:19.928Z
Learnt from: realchrisolin
PR: sysadminsmedia/homebox#1004
File: frontend/composables/use-formatters.ts:64-73
Timestamp: 2025-09-12T23:36:19.928Z
Learning: In the homebox frontend, UTC dates from the backend are handled correctly by the current date formatting implementation without needing additional local day conversion for display, as confirmed by testing in negative timezones.

Applied to files:

  • frontend/lib/datelib/datelib.test.ts
📚 Learning: 2025-09-12T23:52:45.823Z
Learnt from: realchrisolin
PR: sysadminsmedia/homebox#1004
File: frontend/lib/datelib/datelib.ts:14-18
Timestamp: 2025-09-12T23:52:45.823Z
Learning: In the homebox frontend datelib, when working with day-level precision and UTC-normalized dates (T00:00:00.000Z), DST drift from addDays is not a practical concern since the system only deals with whole-day offsets and consistently uses UTC midnight as the baseline.

Applied to files:

  • frontend/lib/datelib/datelib.ts
🧬 Code graph analysis (1)
frontend/composables/utils.ts (1)
frontend/lib/api/types/data-contracts.ts (1)
  • CurrenciesCurrency (55-61)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: End-to-End Playwright Tests / E2E Playwright Testing 1/4
  • GitHub Check: End-to-End Playwright Tests / E2E Playwright Testing 3/4
  • GitHub Check: build (linux/arm64)
  • GitHub Check: build (linux/arm/v7)
  • GitHub Check: Frontend Tests / Integration Tests
  • GitHub Check: Backend Server Tests / Go
  • GitHub Check: Frontend Tests / Integration Tests PGSQL 15
  • GitHub Check: build (linux/arm/v7)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/arm64)
  • GitHub Check: build (linux/arm/v7)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/arm64)
🔇 Additional comments (2)
frontend/lib/datelib/datelib.test.ts (1)

6-6: LGTM: UTC construction removes TZ fragility.

This stabilizes expectations across environments.

frontend/composables/utils.ts (1)

1-1: Type import looks good.

Keeps runtime bundle slim.

@tonyaellie tonyaellie merged commit 116e395 into sysadminsmedia:main Oct 9, 2025
21 of 22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants