Skip to content

Comments

perf: remove city-timezones dep in favor of CDN#23430

Closed
volnei wants to merge 26 commits intomainfrom
perf/remove-city-timezones
Closed

perf: remove city-timezones dep in favor of CDN#23430
volnei wants to merge 26 commits intomainfrom
perf/remove-city-timezones

Conversation

@volnei
Copy link
Contributor

@volnei volnei commented Aug 28, 2025

What does this PR do?

Replace city-timezones dependency with CDN version to reduce bundle size.

  1. Keep api v2 endpoint even it's useless due to compatibility
  2. Upgrade TimezoneSelect component to start using CDN version of city-timezones
  3. Add cityTimezoneHandler tests
  4. Fixes text for TimezoneSelect.

@volnei volnei requested a review from a team August 28, 2025 18:23
@volnei volnei requested a review from a team as a code owner August 28, 2025 18:23
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 28, 2025

Walkthrough

  • Removed Redis caching from apps/api/v2 timezones.service; getCityTimeZones now directly calls cityTimezonesHandler.
  • Replaced city-timezones library with CDN JSON fetching in packages/features/cityTimezones/cityTimezonesHandler; added named export, explicit types, dedup by city (highest population), and inline London overrides.
  • Updated TRPC router to import the handler as a named export.
  • TimezoneSelect now fetches client-side via cityTimezonesHandler with loading state.
  • Added/updated tests for handler and TimezoneSelect to reflect new data source and shapes.
  • Removed city-timezones dependency from root and packages/lib package.json.
  • Added NEXT_PUBLIC_CITY_TIMEZONES_URL to .env.example and turbo.json.

Possibly related PRs

Pre-merge checks (3 passed)

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title "perf: remove city-timezones dep in favor of CDN" directly and concisely summarizes the primary change—removing the city-timezones dependency and switching to a CDN—and matches the changes in the diff (dependency removals, handler and component updates).
Description Check ✅ Passed The description clearly states the PR intent (replace the city-timezones dependency with a CDN) and enumerates the relevant changes (retain API v2, update TimezoneSelect, add tests, fix text), which aligns with the provided change summaries.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
Title Check ✅ Passed The title clearly states the removal of the city-timezones dependency in favor of a CDN, which is the primary change in this PR. The phrasing is concise, uses relevant keywords, and avoids unnecessary noise or vagueness.
Description Check ✅ Passed The description outlines the primary goal of replacing the city-timezones dependency with a CDN to reduce bundle size and enumerates the key modifications made across API, component, and tests. It directly corresponds to the summarized changes without introducing off-topic information.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch perf/remove-city-timezones

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.

@graphite-app graphite-app bot requested a review from a team August 28, 2025 18:23
@volnei volnei marked this pull request as draft August 28, 2025 18:23
@keithwillcode keithwillcode added core area: core, team members only foundation labels Aug 28, 2025
@dosubot dosubot bot added the performance area: performance, page load, slow, slow endpoints, loading screen, unresponsive label Aug 28, 2025
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: 8

Caution

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

⚠️ Outside diff range comments (1)
apps/api/v2/src/modules/timezones/services/timezones.service.ts (1)

1-10: Remove unused RedisService dependency

No longer used; keep DI clean.

-import { RedisService } from "@/modules/redis/redis.service";
 import { Injectable } from "@nestjs/common";
 
 import { cityTimezonesHandler } from "@calcom/platform-libraries";
 import type { CityTimezones } from "@calcom/platform-libraries";
 
 @Injectable()
 export class TimezonesService {
-  constructor(private readonly redisService: RedisService) {}
+  constructor() {}
🧹 Nitpick comments (4)
packages/features/cityTimezones/cityTimezonesHandler.ts (1)

36-37: Return stable, locale-aware ordering

Provide deterministic ordering for UX/search.

-  const uniqueCities = Object.values(topByName);
-  return uniqueCities;
+  const uniqueCities = Object.values(uniqueByKey).sort((a, b) =>
+    a.city.localeCompare(b.city, undefined, { sensitivity: "base" })
+  );
+  return uniqueCities;
apps/api/v2/src/modules/timezones/services/timezones.service.ts (1)

11-13: Use RedisService for caching city time zones
The service already injects RedisService but never uses it. Replace the per-request CDN call with a Redis-backed cache to avoid in-memory state and support multi-instance setups:

async getCityTimeZones(): Promise<CityTimezones> {
  const key = 'city-timezones';
  const cached = await this.redisService.get<CityTimezones>(key);
  if (cached) return cached;

  const data = await cityTimezonesHandler();
  await this.redisService.set(key, data, { ttl: 60 * 60 * 1000 }); // 1h TTL
  return data;
}

This centralizes caching, leverages the existing RedisService, and makes TTL configurable via your config service.

packages/features/components/timezone-select/TimezoneSelect.tsx (2)

112-114: Localize aria-label

Per guideline, use t() for user-visible strings.

Replace with your project’s i18n helper:

-      aria-label="Timezone Select"
+      aria-label={t("timezone_select")}

Please confirm the correct import for t() in this package (e.g., next-intl or your i18n util).


58-60: Consider SSR/server fetch to avoid client CDN dependency

Client-side fetching adds latency and leaks CDN calls to browsers. Prefer server-side fetch (API or RSC) and pass data as props, with cache and revalidate.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e07f800 and e976cb5.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (5)
  • apps/api/v2/src/modules/timezones/services/timezones.service.ts (1 hunks)
  • package.json (0 hunks)
  • packages/features/cityTimezones/cityTimezonesHandler.ts (1 hunks)
  • packages/features/components/timezone-select/TimezoneSelect.tsx (2 hunks)
  • packages/lib/package.json (0 hunks)
💤 Files with no reviewable changes (2)
  • packages/lib/package.json
  • package.json
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{service,repository}.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes

Files:

  • apps/api/v2/src/modules/timezones/services/timezones.service.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • apps/api/v2/src/modules/timezones/services/timezones.service.ts
  • packages/features/cityTimezones/cityTimezonesHandler.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • apps/api/v2/src/modules/timezones/services/timezones.service.ts
  • packages/features/components/timezone-select/TimezoneSelect.tsx
  • packages/features/cityTimezones/cityTimezonesHandler.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • apps/api/v2/src/modules/timezones/services/timezones.service.ts
  • packages/features/components/timezone-select/TimezoneSelect.tsx
  • packages/features/cityTimezones/cityTimezonesHandler.ts
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Always use t() for text localization in frontend code; direct text embedding should trigger a warning

Files:

  • packages/features/components/timezone-select/TimezoneSelect.tsx
🧠 Learnings (1)
📓 Common learnings
Learnt from: mdm317
PR: calcom/cal.com#23221
File: packages/features/schedules/components/NewScheduleButton.tsx:35-35
Timestamp: 2025-08-20T17:36:46.521Z
Learning: PR #20804 "perf: server-side fetching for /availability" moved availability data fetching from TRPC to server-side in the Cal.com codebase. This means TRPC cache updates like `utils.viewer.availability.list.setData()` have no effect on the availability page, making server actions like `revalidateAvailabilityList()` necessary for proper cache invalidation.
🧬 Code graph analysis (2)
apps/api/v2/src/modules/timezones/services/timezones.service.ts (1)
packages/features/cityTimezones/cityTimezonesHandler.ts (1)
  • cityTimezonesHandler (9-38)
packages/features/components/timezone-select/TimezoneSelect.tsx (1)
packages/features/cityTimezones/cityTimezonesHandler.ts (1)
  • cityTimezonesHandler (9-38)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache

@vercel
Copy link

vercel bot commented Aug 28, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
cal Ignored Ignored Nov 3, 2025 8:30am
cal-eu Ignored Ignored Nov 3, 2025 8:30am

- Replace outdated tRPC mock with proper cityTimezonesHandler mock
- Update test expectations to match component's actual rendering behavior
- Fix openMenu function to wait for component loading and use correct option text
- All timezone tests now pass with proper mocking approach

Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
@volnei volnei changed the title perf: remove city timezones perf: remove city-timezones dep in favor of CDN Aug 29, 2025
@volnei volnei self-assigned this Aug 29, 2025
@volnei volnei marked this pull request as ready for review August 29, 2025 14:15
@github-actions
Copy link
Contributor

github-actions bot commented Sep 2, 2025

E2E results are ready!

const uniqueCities = Object.values(topPopulatedCities);
/** Add specific overrides in here */
uniqueCities.forEach((city) => {
if (city.city === "London") city.timezone = "Europe/London";
Copy link
Contributor

Choose a reason for hiding this comment

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

don't we need this condition in the new refactor?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

adjusted!

Copy link
Contributor

@Udit-takkar Udit-takkar left a comment

Choose a reason for hiding this comment

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

Image

Locally it keeps showing loading(...) next to the timezone

@github-actions github-actions bot marked this pull request as draft September 2, 2025 14:14
@supalarry
Copy link
Contributor

I see the PR is in Draft mode and has updated platform libraries - in the meanwhile I needed to update platform libraries for another PR so once PR #23514 is merged then it is needed to merge main into this branch and release platform libraries again.

@volnei volnei marked this pull request as ready for review September 9, 2025 19:24
@github-actions
Copy link
Contributor

This PR is being marked as stale due to inactivity.

@github-actions github-actions bot added Stale and removed Stale labels Sep 26, 2025
@volnei volnei requested a review from a team as a code owner October 26, 2025 23:11
@github-actions github-actions bot added the ❗️ migrations contains migration files label Oct 26, 2025
@volnei volnei force-pushed the perf/remove-city-timezones branch from 230615c to b0e70a3 Compare October 26, 2025 23:12
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

8 issues found across 48 files

Prompt for AI agents (all 8 issues)

Understand the root cause of the following 8 issues and fix them.


<file name="apps/api/v2/src/modules/timezones/services/timezones.service.ts">

<violation number="1" location="apps/api/v2/src/modules/timezones/services/timezones.service.ts:9">
Calling cityTimezonesHandler() directly here removes the Redis cache, so every request now re-fetches the full timezone list from the CDN. Because cityTimezonesHandler performs an uncached remote fetch, this change regresses latency and risks rate-limiting under load—please keep or replace the caching layer.</violation>
</file>

<file name="packages/features/components/timezone-select/TimezoneSelect.tsx">

<violation number="1" location="packages/features/components/timezone-select/TimezoneSelect.tsx:48">
If cityTimezonesHandler rejects (e.g., CDN outage), this await never settles successfully, leaving the select stuck in a loading state and emitting an unhandled rejection. Please handle errors and clear isPending in a finally/catch path.</violation>
</file>

<file name="apps/web/components/apps/paypal/Setup.tsx">

<violation number="1" location="apps/web/components/apps/paypal/Setup.tsx:104">
When opening a link in a new tab, include `noopener` along with `noreferrer` so the external page cannot reach back via `window.opener`.</violation>

<violation number="2" location="apps/web/components/apps/paypal/Setup.tsx:123">
Add `noopener` alongside `noreferrer` on new-tab links to block `window.opener` access and avoid reverse tabnabbing.</violation>
</file>

<file name="packages/app-store-cli/src/build.ts">

<violation number="1" location="packages/app-store-cli/src/build.ts:3">
Dropping this eslint-disable reactivates our no-restricted-imports rule against the lodash import, so linting will now fail unless the directive (or the import) is restored.</violation>
</file>

<file name="apps/web/components/team/screens/Team.tsx">

<violation number="1" location="apps/web/components/team/screens/Team.tsx:42">
Removing the lint suppression here re-enables the `react/no-danger` error for the existing `dangerouslySetInnerHTML` call, so linting will now fail. Please restore the guard (or refactor to avoid `dangerouslySetInnerHTML`) before merging.</violation>
</file>

<file name="packages/features/ee/managed-event-types/lib/handleChildrenEventTypes.ts">

<violation number="1" location="packages/features/ee/managed-event-types/lib/handleChildrenEventTypes.ts:1">
Removing the eslint-disable for `no-restricted-imports` while still importing from &quot;vitest-mock-extended&quot; will cause the linter to fail. Please restore the directive so this import continues to pass lint.</violation>
</file>

<file name="packages/features/cityTimezones/cityTimezonesHandler.test.ts">

<violation number="1" location="packages/features/cityTimezones/cityTimezonesHandler.test.ts:15">
Assigning `global.fetch` directly in the test without restoring it pollutes the global environment, so later suites will still see the mocked fetch and can break. Use a spy/mock that is restored after the test (or restore `global.fetch` in teardown) instead of overwriting it permanently.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

} else {
return JSON.parse(cachedTimezones) as CityTimezones;
}
return await cityTimezonesHandler();
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 3, 2025

Choose a reason for hiding this comment

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

Calling cityTimezonesHandler() directly here removes the Redis cache, so every request now re-fetches the full timezone list from the CDN. Because cityTimezonesHandler performs an uncached remote fetch, this change regresses latency and risks rate-limiting under load—please keep or replace the caching layer.

Prompt for AI agents
Address the following comment on apps/api/v2/src/modules/timezones/services/timezones.service.ts at line 9:

<comment>Calling cityTimezonesHandler() directly here removes the Redis cache, so every request now re-fetches the full timezone list from the CDN. Because cityTimezonesHandler performs an uncached remote fetch, this change regresses latency and risks rate-limiting under load—please keep or replace the caching layer.</comment>

<file context>
@@ -1,24 +1,11 @@
-    } else {
-      return JSON.parse(cachedTimezones) as CityTimezones;
-    }
+    return await cityTimezonesHandler();
   }
 }
</file context>
Fix with Cubic


useEffect(() => {
(async () => {
const data = await cityTimezonesHandler();
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 3, 2025

Choose a reason for hiding this comment

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

If cityTimezonesHandler rejects (e.g., CDN outage), this await never settles successfully, leaving the select stuck in a loading state and emitting an unhandled rejection. Please handle errors and clear isPending in a finally/catch path.

Prompt for AI agents
Address the following comment on packages/features/components/timezone-select/TimezoneSelect.tsx at line 48:

<comment>If cityTimezonesHandler rejects (e.g., CDN outage), this await never settles successfully, leaving the select stuck in a loading state and emitting an unhandled rejection. Please handle errors and clear isPending in a finally/catch path.</comment>

<file context>
@@ -40,14 +40,17 @@ export type TimezoneSelectProps = SelectProps &amp; {
+
+  useEffect(() =&gt; {
+    (async () =&gt; {
+      const data = await cityTimezonesHandler();
+      setData(data);
+      setIsPending(false);
</file context>
Fix with Cubic

target="_blank"
href="https://developer.paypal.com/dashboard/applications/live"
className="text-orange-600 underline">
className="text-orange-600 underline" rel="noreferrer">
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 3, 2025

Choose a reason for hiding this comment

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

Add noopener alongside noreferrer on new-tab links to block window.opener access and avoid reverse tabnabbing.

Prompt for AI agents
Address the following comment on apps/web/components/apps/paypal/Setup.tsx at line 123:

<comment>Add `noopener` alongside `noreferrer` on new-tab links to block `window.opener` access and avoid reverse tabnabbing.</comment>

<file context>
@@ -120,7 +120,7 @@ export default function PayPalSetup() {
                     target=&quot;_blank&quot;
                     href=&quot;https://developer.paypal.com/dashboard/applications/live&quot;
-                    className=&quot;text-orange-600 underline&quot;&gt;
+                    className=&quot;text-orange-600 underline&quot; rel=&quot;noreferrer&quot;&gt;
                     {t(&quot;here&quot;)}
                   &lt;/a&gt;
</file context>
Suggested change
className="text-orange-600 underline" rel="noreferrer">
className="text-orange-600 underline" rel="noopener noreferrer">
Fix with Cubic

className="text-orange-600 underline"
target="_blank"
href="https://developer.paypal.com/api/rest/#link-getclientidandclientsecret">
href="https://developer.paypal.com/api/rest/#link-getclientidandclientsecret" rel="noreferrer">
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 3, 2025

Choose a reason for hiding this comment

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

When opening a link in a new tab, include noopener along with noreferrer so the external page cannot reach back via window.opener.

Prompt for AI agents
Address the following comment on apps/web/components/apps/paypal/Setup.tsx at line 104:

<comment>When opening a link in a new tab, include `noopener` along with `noreferrer` so the external page cannot reach back via `window.opener`.</comment>

<file context>
@@ -101,7 +101,7 @@ export default function PayPalSetup() {
                 className=&quot;text-orange-600 underline&quot;
                 target=&quot;_blank&quot;
-                href=&quot;https://developer.paypal.com/api/rest/#link-getclientidandclientsecret&quot;&gt;
+                href=&quot;https://developer.paypal.com/api/rest/#link-getclientidandclientsecret&quot; rel=&quot;noreferrer&quot;&gt;
                 Link to Paypal developer API REST Setup Guide:
                 https://developer.paypal.com/api/rest/#link-getclientidandclientsecret
</file context>
Suggested change
href="https://developer.paypal.com/api/rest/#link-getclientidandclientsecret" rel="noreferrer">
href="https://developer.paypal.com/api/rest/#link-getclientidandclientsecret" rel="noopener noreferrer">
Fix with Cubic

import chokidar from "chokidar";
import fs from "fs";
// eslint-disable-next-line no-restricted-imports
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 3, 2025

Choose a reason for hiding this comment

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

Dropping this eslint-disable reactivates our no-restricted-imports rule against the lodash import, so linting will now fail unless the directive (or the import) is restored.

Prompt for AI agents
Address the following comment on packages/app-store-cli/src/build.ts at line 3:

<comment>Dropping this eslint-disable reactivates our no-restricted-imports rule against the lodash import, so linting will now fail unless the directive (or the import) is restored.</comment>

<file context>
@@ -1,6 +1,6 @@
 import chokidar from &quot;chokidar&quot;;
 import fs from &quot;fs&quot;;
-// eslint-disable-next-line no-restricted-imports
+ 
 import { debounce } from &quot;lodash&quot;;
 import path from &quot;path&quot;;
</file context>
Suggested change
// eslint-disable-next-line no-restricted-imports
Fix with Cubic

<div
className=" text-subtle break-words text-sm [&_a]:text-blue-500 [&_a]:underline [&_a]:hover:text-blue-600"
// eslint-disable-next-line react/no-danger
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 3, 2025

Choose a reason for hiding this comment

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

Removing the lint suppression here re-enables the react/no-danger error for the existing dangerouslySetInnerHTML call, so linting will now fail. Please restore the guard (or refactor to avoid dangerouslySetInnerHTML) before merging.

Prompt for AI agents
Address the following comment on apps/web/components/team/screens/Team.tsx at line 42:

<comment>Removing the lint suppression here re-enables the `react/no-danger` error for the existing `dangerouslySetInnerHTML` call, so linting will now fail. Please restore the guard (or refactor to avoid `dangerouslySetInnerHTML`) before merging.</comment>

<file context>
@@ -39,7 +39,7 @@ const Member = ({ member, teamName }: { member: MemberType; teamName: string | n
                 &lt;div
                   className=&quot;  text-subtle break-words text-sm [&amp;_a]:text-blue-500 [&amp;_a]:underline [&amp;_a]:hover:text-blue-600&quot;
-                  // eslint-disable-next-line react/no-danger
+                   
                   dangerouslySetInnerHTML={{ __html: markdownToSafeHTML(member.bio) }}
                 /&gt;
</file context>
Suggested change
// eslint-disable-next-line react/no-danger
Fix with Cubic

@@ -1,4 +1,4 @@
// eslint-disable-next-line no-restricted-imports
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 3, 2025

Choose a reason for hiding this comment

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

Removing the eslint-disable for no-restricted-imports while still importing from "vitest-mock-extended" will cause the linter to fail. Please restore the directive so this import continues to pass lint.

Prompt for AI agents
Address the following comment on packages/features/ee/managed-event-types/lib/handleChildrenEventTypes.ts at line 1:

<comment>Removing the eslint-disable for `no-restricted-imports` while still importing from &quot;vitest-mock-extended&quot; will cause the linter to fail. Please restore the directive so this import continues to pass lint.</comment>

<file context>
@@ -1,4 +1,4 @@
-// eslint-disable-next-line no-restricted-imports
+ 
 import type { DeepMockProxy } from &quot;vitest-mock-extended&quot;;
 
</file context>
Suggested change
// eslint-disable-next-line no-restricted-imports
Fix with Cubic

],
});

global.fetch = mockFetch;
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 3, 2025

Choose a reason for hiding this comment

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

Assigning global.fetch directly in the test without restoring it pollutes the global environment, so later suites will still see the mocked fetch and can break. Use a spy/mock that is restored after the test (or restore global.fetch in teardown) instead of overwriting it permanently.

Prompt for AI agents
Address the following comment on packages/features/cityTimezones/cityTimezonesHandler.test.ts at line 15:

<comment>Assigning `global.fetch` directly in the test without restoring it pollutes the global environment, so later suites will still see the mocked fetch and can break. Use a spy/mock that is restored after the test (or restore `global.fetch` in teardown) instead of overwriting it permanently.</comment>

<file context>
@@ -0,0 +1,76 @@
+      ],
+    });
+
+    global.fetch = mockFetch;
+
+    const result = await cityTimezonesHandler();
</file context>
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core area: core, team members only ⬆️ dependencies Pull requests that update a dependency file ❗️ .env changes contains changes to env variables foundation ❗️ migrations contains migration files performance area: performance, page load, slow, slow endpoints, loading screen, unresponsive ready-for-e2e size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants