Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Feb 10, 2026

Two test infrastructure issues identified in PR #292 review:

  1. AbortSignal.timeout() is undefined in Vitest's jsdom environment, causing runtime errors in fetchEzygoData()
  2. Circuit breaker mock in health endpoint test was set before vi.resetModules(), so the fresh route import saw unmocked instance

Changes

  • src/lib/ezygo-batch-fetcher.ts: Added createTimeoutSignal() helper with fallback to AbortController + setTimeout for environments without native AbortSignal.timeout()
function createTimeoutSignal(timeoutMs: number): AbortSignal {
  if (typeof AbortSignal !== 'undefined' && 'timeout' in AbortSignal) {
    return AbortSignal.timeout(timeoutMs);
  }
  const controller = new AbortController();
  setTimeout(() => controller.abort(), timeoutMs);
  return controller.signal;
}
  • src/app/api/health/ezygo/__tests__/route.test.ts: Re-import circuit breaker after each vi.resetModules() to ensure mock applies to the route's module instance

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

…ation

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement EzyGo API Batch Fetcher with rate limiting and circuit breaker Fix AbortSignal.timeout() jsdom compatibility and mock isolation in circuit breaker tests Feb 10, 2026
Copilot AI requested a review from devakesu February 10, 2026 20:58
@devakesu devakesu marked this pull request as ready for review February 10, 2026 21:00
Copilot AI review requested due to automatic review settings February 10, 2026 21:00
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes two test infrastructure issues discovered during the review of PR #292:

  1. AbortSignal.timeout() is undefined in Vitest's jsdom environment, causing runtime errors when executing fetchEzygoData()
  2. Circuit breaker mocks were set before vi.resetModules(), causing the freshly imported route module to see unmocked instances

Changes:

  • Added createTimeoutSignal() helper function with environment detection and fallback support for jsdom
  • Fixed mock isolation in circuit breaker tests by re-importing mocked modules after each vi.resetModules() call

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/lib/ezygo-batch-fetcher.ts Added createTimeoutSignal() helper with AbortController + setTimeout fallback for environments lacking native AbortSignal.timeout() support
src/app/api/health/ezygo/__tests__/route.test.ts Fixed mock isolation by re-importing circuit breaker module after vi.resetModules() to ensure mocks apply to fresh module instances

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@devakesu devakesu merged commit 8212a39 into 1.5.0 Feb 10, 2026
6 checks passed
@devakesu devakesu deleted the copilot/sub-pr-292-again branch February 10, 2026 21:06
devakesu added a commit that referenced this pull request Feb 11, 2026
* Implement EzyGo API Batch Fetcher with Rate Limiting and Circuit Breaker

- Added EzyGo API Batch Fetcher to optimize concurrent API calls.
- Implemented request deduplication using LRU cache with a 15-second TTL.
- Introduced rate limiting to restrict concurrent requests to a maximum of 3.
- Integrated a circuit breaker pattern to handle API failures gracefully.
- Created health check endpoint to monitor rate limiter and circuit breaker status.
- Developed comprehensive documentation for rate limiting and verification processes.
- Ensured client-side hooks and server-side calls are protected against rate limiting.

* Address PR review feedback: security, docs, error handling, tests (#293)

* Initial plan

* Fix PR review issues: security, docs, error handling, and UI

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Add comprehensive unit tests for circuit breaker and rate limiter

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix cache deduplication, circuit breaker error handling, and test isolation (#294)

* Initial plan

* Fix PR review feedback: cache normalization, TTL behavior, circuit breaker error handling, CSS import, test isolation

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Address code review feedback: fix return type consistency and improve documentation

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Address PR review feedback: add tests, fix error handling, narrow 4xx scope, evict failed promises

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Address code review feedback: refine cache eviction and improve documentation

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Address PR #292 review feedback: hydration, syntax, error handling, docs (#295)

* Initial plan

* Address PR review comments: hydration, syntax, cleanup, docs

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Remove redundant clearTimeout call

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix ldrs CSS import path for Turbopack compatibility

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Update src/app/(protected)/dashboard/DashboardClient.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>
Co-authored-by: Devanarayanan <fusion@devakesu.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix invalid Tailwind utilities and chart responsiveness (#296)

* Initial plan

* Fix invalid Tailwind utilities and hydration issues

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Refactor ResizeObserver to use consistent updateDimensions function

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Remove redundant nullish coalescing operators

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix trailing whitespace, chart height, and revert problematic hydration

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix invalid Tailwind utilities, add queue limits, handle 429, and prevent cache poisoning (#297)

* Initial plan

* Fix invalid Tailwind utilities across components

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Add queue size limit and timeout to prevent unbounded growth

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Treat 429 status as circuit breaker failure to prevent retry storms

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Update documentation to reflect queue timeout and size limits

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Improve queue error handling with unique IDs and typed errors

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix cache poisoning and preserve 429 rate-limit messages

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Add tests for queue errors and 429 handling

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Improve type safety in logger usage for 429/5xx handling

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix Tailwind syntax, test timeouts, redundant SSR fetch, and cache control (#299)

* Initial plan

* Address review feedback: fix Tailwind syntax, test timeouts, SSR fetch, cache headers, and docs

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Update JSDoc for fetchDashboardData to reflect removal of profile

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix cache poisoning, health check flapping, and initialData handling (#300)

* Initial plan

* Fix review comments: cache eviction, health check, docs, and initialData handling

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix circuit breaker bypass, cache collision, and type safety issues (#301)

* Initial plan

* Fix security, type safety, and circuit breaker issues from code review

- Increased cache key hash from 16 to 64 hex chars (full SHA-256) to prevent cross-user collision
- Moved NEXT_PUBLIC_BACKEND_URL validation outside circuit breaker (now NonBreakerError)
- Made UpstreamResponseTooLargeError extend NonBreakerError to prevent tripping circuit breaker
- Fixed TypeScript type mismatches in useAttendanceReport and useFetchCourses hooks
- Added null type support to query return types and components
- Removed unused isHealthy variable in health check endpoint
- Updated comments to reflect circuit breaker behavior

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix initialData hydration and cache TTL issues from PR #292 review (#302)

* Initial plan

* Fix initialData handling, cache TTL, and chart min-height

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix initialCoursesData null handling, clarify cache TTL docs, add test coverage

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix test setup to match retry configuration

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix documentation/implementation misalignment and incorrect hook type signatures (#303)

* Initial plan

* Align documentation with actual implementation and fix hook type signatures

- Update EZYGO_RATE_LIMITING.md to reflect 60s cache TTL (was 15s)
- Update EZYGO_RATE_LIMITING.md circuit breaker description (60s timeout, 2 test requests)
- Update EZYGO_VERIFICATION.md cache TTL documentation to match actual 60s
- Remove unnecessary `| null` from useFetchCourses return type
- Remove unnecessary `| null` from useAttendanceReport return type
- Fix test mocks to use proper AttendanceReport type structure

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Address PR review feedback: remove "configurable" claim and fix test name

- Remove "(default, configurable)" from cache TTL docs since it's hard-coded
- Rename test from "normalize null initialData" to "fetch data when initialData is undefined" to match actual behavior

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix cache TTL documentation mismatch and body key collision (#304)

* Initial plan

* Fix TTL documentation inconsistencies and cache key generation

- Updated all documentation to reflect 60s TTL instead of 15s
- Fixed cache key generation to properly distinguish undefined from {} body values
- Changed body check from truthy to explicit undefined check for consistency

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Use more unique sentinel value for cache key generation

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Optimize JSON.stringify, add cache key tests, fix doc inconsistencies

- Compute JSON.stringify(body) once and reuse for cache key and fetch body
- Add unit tests for cache key deduplication: undefined vs {} vs null
- Fix EZYGO_VERIFICATION.md line 258: 15s -> 60s TTL
- Clarify EDGE_CASES_TESTS.md: cache stores both in-flight and resolved responses

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix review feedback: Add SECURITY.md, align TTL docs, hash cache keys (#305)

* Initial plan

* Address review comments: Add SECURITY.md, fix TTL docs, hash body in cache key

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Improve cache key comment clarity and fix HttpOnly casing in SECURITY.md

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Forward rate-limit headers from upstream 429 responses (#306)

* Initial plan

* Forward rate-limit headers from upstream 429 responses

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix FIFO queue starvation in EzyGo batch fetcher rate limiter (#312)

* Initial plan

* Fix FIFO queue fairness in waitForSlot function

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Add FIFO fairness regression test for queue management

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix circuit breaker 4xx handling and clarify per-user deduplication scope (#313)

* Initial plan

* Fix circuit breaker 4xx handling and clarify per-user deduplication in docs

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix documentation inconsistencies, add status code tests, clarify comments

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Improve test structure to use consistent error handling pattern

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix documentation mismatches and add Suspense boundary for lazy components (#314)

* Initial plan

* Fix PR review feedback: clarify per-user deduplication and add Suspense boundary

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix circuit breaker threshold and cache key documentation details

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Restrict health endpoint telemetry in production to prevent information disclosure (#315)

* Initial plan

* Restrict detailed telemetry in production health endpoint

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Improve NODE_ENV check to default to secure behavior

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Update documentation for production security restrictions

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Add unit tests and improve code clarity per review feedback

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix rate limiter state corruption and add aria-hidden fallback (#316)

* Initial plan

* Fix timeout cleanup and inert fallback for accessibility

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix generation guard and remove redundant clearTimeout

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Initialize slotGeneration to -1 and improve comment precision

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix AbortError handling, remove ineffective Recharts lazy loading, and add test coverage (#317)

* Initial plan

* Fix abort error handling and remove ineffective Recharts lazy loading

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Add test coverage for timeout/abort path in backend proxy

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix JSDoc, ResizeObserver performance, dev:https validation, and README accuracy (#318)

* Initial plan

* Fix JSDoc, ResizeObserver optimization, dev:https validation, and README accuracy

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix test mock memory leaks, GET request body handling, and Content-Type header semantics (#319)

* Initial plan

* Fix test mocks to respect AbortSignal and GET body parameter handling

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Conditionally set Content-Type header only for POST requests with body

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix header mutation by setting Content-Type before creating fetchOptions

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix backend route timeout test determinism and circuit breaker test isolation (#320)

* Initial plan

* Changes before error encountered

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix test isolation by resetting circuit breaker state before each Rate Limiting test

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Improve timeout test mock robustness with signal validation and early abort handling

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix AbortSignal.timeout() jsdom compatibility and mock isolation in circuit breaker tests (#321)

* Initial plan

* Fix AbortSignal.timeout() compatibility and circuit breaker mock isolation

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix resource leaks in stream reading and timeout signal handling (#322)

* Initial plan

* Fix resource leaks: cancel reader on size limit, clear timeout on fetch completion, improve AbortSignal.timeout detection

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Address review feedback: fix docstring, await reader.cancel(), add timer cleanup tests

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix comment: remove mention of logging that isn't implemented

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix invalid Tailwind CSS class names introduced in v1.5.0 (#323)

* Initial plan

* Fix invalid Tailwind CSS class names

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Remove trailing whitespace from AcceptTermsForm.tsx

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Fix attendance hook tests for initialData support (#324)

* Initial plan

* Fix attendance hook unit tests for initialData support

- Add beforeEach/afterEach hooks to prevent test state pollution
- Disable background refetch settings in test QueryClient
- Increase timeout for error state test to 3000ms
- All 5 attendance tests now passing
- No regressions in other tests (399 tests passing)

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

* Remove redundant afterEach hook

The beforeEach already clears mocks, so afterEach is unnecessary

Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>

---------

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
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