Skip to content

Conversation

@panteliselef
Copy link
Member

@panteliselef panteliselef commented Nov 4, 2025

Description

This PR is building on top of #6913 and rewrites usePageOrInfinite to use React Query instead of SWR under the hood. The benefits of that is are already mentioned in the description of the previous PR. As a reminder usePageOrInfinite is the heart of all our hooks that fetch paginated data. That involves:

  • useOrganization()
  • useOrganizationList()
  • usePlans()
  • useStatements()
  • usePaymentAttempts()

Enables Tests (both e2e and unit) in CI for both RQ and SWR versions.

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Summary by CodeRabbit

  • New Features

    • Added a unified pages/infinite data hook and related pagination utilities with typed infinite-query support and public re-exports.
  • Chores

    • Enhanced test infrastructure with shared mock helpers and a default mock query client.
    • CI updated to run React Query variants and a new runtime flag for test modes.

This reverts commit 7fc1248.
# Conflicts:
#	.changeset/tricky-badgers-post.md
#	packages/clerk-js/bundlewatch.config.json
#	packages/clerk-js/package.json
#	packages/clerk-js/src/core/clerk.ts
#	packages/shared/src/react/clerk-rq/types.ts
#	packages/shared/src/react/clerk-rq/useBaseQuery.ts
#	packages/shared/src/react/contexts.tsx
#	packages/shared/src/react/hooks/usePagesOrInfinite.ts
#	packages/shared/src/react/hooks/useSubscription.rq.tsx
#	packages/shared/src/react/hooks/useSubscription.swr.tsx
#	packages/shared/src/react/hooks/useSubscription.types.ts
#	packages/shared/src/types/virtual-data-hooks.d.ts
#	packages/shared/tsconfig.json
#	packages/shared/tsup.config.ts
#	pnpm-lock.yaml
@vercel
Copy link

vercel bot commented Nov 4, 2025

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

Project Deployment Preview Comments Updated (UTC)
clerk-js-sandbox Ready Ready Preview Comment Nov 10, 2025 5:48pm

@changeset-bot
Copy link

changeset-bot bot commented Nov 4, 2025

🦋 Changeset detected

Latest commit: 031083c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 22 packages
Name Type
@clerk/shared Patch
@clerk/agent-toolkit Patch
@clerk/astro Patch
@clerk/backend Patch
@clerk/chrome-extension Patch
@clerk/clerk-js Patch
@clerk/elements Patch
@clerk/expo-passkeys Patch
@clerk/clerk-expo Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/nextjs Patch
@clerk/nuxt Patch
@clerk/react-router Patch
@clerk/clerk-react Patch
@clerk/remix Patch
@clerk/tanstack-react-start Patch
@clerk/testing Patch
@clerk/themes Patch
@clerk/types Patch
@clerk/vue Patch
@clerk/localizations Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 4, 2025

Walkthrough

Adds React Query support and infinite-query types/hooks, implements a dual-mode usePagesOrInfinite hook (SWR + RQ), centralizes test mock factories and a default QueryClient, converts many tests to use deferred/promisified mocks or persistent rejection mocks, introduces a CLERK_USE_RQ test flag, and expands CI matrix to cover RQ runs.

Changes

Cohort / File(s) Change Summary
Mock helpers & test factories
packages/clerk-js/src/test/mock-helpers.ts, packages/shared/src/react/hooks/__tests__/mocks/clerk.ts, packages/shared/src/react/hooks/__tests__/mocks/index.ts, packages/shared/src/react/hooks/__tests__/mocks/*
Introduces createMockQueryClient, createMockClerk, createMockUser, createMockOrganization; adds __internal_queryClient getter on mock Clerk; centralizes QueryClient config for tests and re-exports mocks.
React Query infinite types & hook
packages/shared/src/react/clerk-rq/infiniteQueryOptions.ts, packages/shared/src/react/clerk-rq/types.ts, packages/shared/src/react/clerk-rq/useInfiniteQuery.ts
Adds typed overloads and option aliases for infinite queries, new UseInfiniteQueryResult/DefinedUseInfiniteQueryResult aliases, and a typed useClerkInfiniteQuery delegating to useBaseQuery/InfiniteQueryObserver.
Pagination hook (RQ implementation & shared utils)
packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx, packages/shared/src/react/hooks/usePagesOrInfinite.shared.ts, packages/shared/src/react/hooks/usePageOrInfinite.types.ts
Adds RQ-backed usePagesOrInfinite implementation, shared helpers (useWithSafeValues, getDifferentKeys), and utility types (ArrayType, ExtractData, UsePagesOrInfiniteSignature).
Pagination hook (SWR refactor & public API)
packages/shared/src/react/hooks/usePagesOrInfinite.swr.tsx, packages/shared/src/react/hooks/usePagesOrInfinite.tsx, packages/shared/src/types/virtual-data-hooks.d.ts, packages/shared/tsconfig.json
Refactors SWR variant to import shared types/utilities, re-exports usePagesOrInfinite and useWithSafeValues, adds virtual:data-hooks alias and declaration.
Hook-test updates & RQ test wiring
packages/shared/src/react/hooks/__tests__/*, packages/shared/vitest.setup.mts, packages/shared/global.d.ts
Wires __CLERK_USE_RQ__ flag in vitest setup and global types; tests now use createMockQueryClient and mock factories, clear QueryClient state between tests, and include conditional assertions for RQ vs non-RQ flows.
Numerous UI test updates (mocks & deferred patterns)
packages/clerk-js/src/ui/components/**/__tests__/*.test.tsx, packages/clerk-js/src/ui/hooks/__tests__/*, packages/clerk-js/src/ui/components/*/__tests__/*
Replaces one-off mocks with persistent mocks or rejected mocks (mockRejectedValue(null)), introduces createDeferredPromise usage to control async resolution, and adjusts wait/click/assert ordering to stabilize tests.
Changeset
.changeset/fuzzy-keys-smell.md
Adds patch changeset noting internal paginated hooks work-in-progress.
CI changes
.github/workflows/ci.yml
Adds clerk-use-rq matrix dimension, propagates CLERK_USE_RQ into rebuilds, test runs, and artifact naming; modifies matrix/strategy and conditional rebuild steps.

Sequence Diagram(s)

sequenceDiagram
    participant App as Application
    participant Hook as usePagesOrInfinite
    participant QClient as Query Layer (useClerkQuery / useClerkInfiniteQuery)
    participant Fetcher as User Fetcher

    Note over App,Hook: Mount (non-infinite)
    App->>Hook: mount(params,infinite=false)
    Hook->>QClient: useClerkQuery(queryKey, fetcher)
    QClient->>Fetcher: fetch(params,page)
    Fetcher-->>QClient: {data,total_count}
    QClient-->>Hook: result
    Hook-->>App: {data, isLoading, fetchPage}

    Note over App,Hook: Mount (infinite)
    App->>Hook: mount(params,infinite=true)
    Hook->>QClient: useClerkInfiniteQuery(infKey, fetcher)
    QClient->>Fetcher: fetch(pageParam,params)
    Fetcher-->>QClient: {data,total_count}
    QClient-->>Hook: pages
    Hook-->>App: {mergedData, fetchNext, hasNextPage}
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • usePagesOrInfinite.rq.tsx (data merging, getNextPageParam, enabled/keys logic)
  • infiniteQueryOptions/type overloads (TypeScript generics and inference)
  • Test mock wiring (QueryClient lifecycle, __internal_queryClient getter, isolation between tests)
  • CI matrix conditional rebuilds and env propagation

Possibly related PRs

Suggested reviewers

  • tmilewski
  • dstaley

Poem

🐰 I stitched the queries, page by page,
Mocks now organized upon the stage,
SWR or RQ — both paths I tread,
Tests sleep safer, CI nods ahead,
A rabbit's refactor, light as a page! 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Title check ✅ Passed The title accurately describes the main change: adding a React Query variant of the usePageOrInfinite hook, which is the primary objective of this PR.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch elef/replace-swr-with-rq-infinite

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

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 4, 2025

Open in StackBlitz

@clerk/agent-toolkit

npm i https://pkg.pr.new/@clerk/agent-toolkit@7143

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@7143

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@7143

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@7143

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@7143

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@7143

@clerk/elements

npm i https://pkg.pr.new/@clerk/elements@7143

@clerk/clerk-expo

npm i https://pkg.pr.new/@clerk/clerk-expo@7143

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@7143

@clerk/express

npm i https://pkg.pr.new/@clerk/express@7143

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@7143

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@7143

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@7143

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@7143

@clerk/clerk-react

npm i https://pkg.pr.new/@clerk/clerk-react@7143

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@7143

@clerk/remix

npm i https://pkg.pr.new/@clerk/remix@7143

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@7143

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@7143

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@7143

@clerk/themes

npm i https://pkg.pr.new/@clerk/themes@7143

@clerk/types

npm i https://pkg.pr.new/@clerk/types@7143

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@7143

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@7143

commit: 031083c

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: 4

🧹 Nitpick comments (7)
packages/shared/src/react/hooks/useSubscription.rq.tsx (1)

59-59: Update TODO to reference current React Query v5 API.

React Query v5 replaced keepPreviousData with placeholderData. Since this project uses @tanstack/query-core version 5.87.4, the TODO should reference the current API.

Apply this diff:

-    // TODO: Add support for keepPreviousData
+    // TODO: Add support for placeholderData (replaces keepPreviousData in React Query v5)
packages/shared/src/react/hooks/usePagesOrInfinite.shared.ts (1)

34-54: Consider improving type safety and clarifying behavior.

The implementation has a few areas for improvement:

  1. Type assertion at line 53: The as T assertion may not be type-safe since the function constructs a new object shape. The returned object might not match all properties of T if params has additional properties beyond those in defaultValues.

  2. Generic indexing at lines 45-46: The @ts-ignore suppresses type checking when accessing properties. Consider using a more type-safe approach:

type DefaultKeys = keyof typeof defaultValues;
const key = k as DefaultKeys;
newObj[key] = shouldUseDefaults ? defaultValues[key] : (params?.[key] ?? defaultValues[key]);
  1. Edge case: When params is an object with a property explicitly set to undefined, the nullish coalescing operator ?? will use the default value. This may or may not be the intended behavior - consider documenting this.

Consider this alternative implementation:

 export const useWithSafeValues = <T extends PagesOrInfiniteOptions>(params: T | true | undefined, defaultValues: T) => {
   const shouldUseDefaults = typeof params === 'boolean' && params;
 
   // Cache initialPage and initialPageSize until unmount
   const initialPageRef = useRef(
     shouldUseDefaults ? defaultValues.initialPage : (params?.initialPage ?? defaultValues.initialPage),
   );
   const pageSizeRef = useRef(shouldUseDefaults ? defaultValues.pageSize : (params?.pageSize ?? defaultValues.pageSize));
 
-  const newObj: Record<string, unknown> = {};
+  const newObj = {} as Record<keyof T, any>;
   for (const key of Object.keys(defaultValues)) {
-    // @ts-ignore - indexing into generic param to preserve unknown keys from defaults/params
-    newObj[key] = shouldUseDefaults ? defaultValues[key] : (params?.[key] ?? defaultValues[key]);
+    const typedKey = key as keyof T;
+    newObj[typedKey] = shouldUseDefaults ? defaultValues[typedKey] : (params?.[typedKey] ?? defaultValues[typedKey]);
   }
 
   return {
     ...newObj,
     initialPage: initialPageRef.current,
     pageSize: pageSizeRef.current,
   } as T;
 };
packages/shared/src/react/hooks/usePageOrInfinite.types.ts (1)

7-26: Consider constraining FetcherReturnData more strictly.

The generic parameter FetcherReturnData extends Record<string, any> on line 9 uses any, which weakens type safety. Since the return data should have a data property (based on the ExtractData usage), consider a more specific constraint:

 export type UsePagesOrInfiniteSignature = <
   Params extends PagesOrInfiniteOptions,
-  FetcherReturnData extends Record<string, any>,
+  FetcherReturnData extends { data?: unknown[] } | unknown,
   CacheKeys extends Record<string, unknown> = Record<string, unknown>,
   TConfig extends PagesOrInfiniteConfig = PagesOrInfiniteConfig,
 >(

This would provide better type checking while still being flexible enough for various return shapes.

packages/shared/src/react/clerk-rq/useInfiniteQuery.ts (1)

39-44: Remove empty JSDoc or add documentation.

The JSDoc comment block on lines 39-41 is empty. Either remove it or add meaningful documentation explaining the hook's purpose and usage.

Apply this diff:

-/**
- *
- */
 export function useClerkInfiniteQuery(options: UseInfiniteQueryOptions) {
   return useBaseQuery(options, InfiniteQueryObserver as unknown as typeof QueryObserver);
 }

Or add proper documentation:

 /**
- *
+ * Hook for infinite/paginated queries using React Query with Clerk integration.
+ * Delegates to useBaseQuery with InfiniteQueryObserver for managing cursor-based pagination.
  */
 export function useClerkInfiniteQuery(options: UseInfiniteQueryOptions) {
   return useBaseQuery(options, InfiniteQueryObserver as unknown as typeof QueryObserver);
 }
packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx (2)

22-23: Track TODO for keepPreviousData support.

The React Query implementation lacks support for keepPreviousData configuration. This feature is available in the SWR variant and should be implemented for feature parity.

Do you want me to open a new issue to track this enhancement, or will this be addressed before the PR is merged?


52-53: Document or resolve type assertions.

The @ts-ignore comments on lines 52 and 82 suppress TypeScript errors for type compatibility. Consider:

  1. Adding detailed comments explaining why the types differ and why the assertion is safe
  2. Refining the types to eliminate the need for suppression
  3. Using @ts-expect-error with specific error codes instead of @ts-ignore for better type safety

Also applies to: 82-83

packages/shared/src/react/clerk-rq/infiniteQueryOptions.ts (1)

89-94: Remove empty JSDoc or add documentation.

The JSDoc comment block on lines 89-91 is empty. Either remove it or add meaningful documentation explaining that this is a type-level helper that returns options unchanged for type inference purposes.

Apply this diff:

-/**
- *
- */
 export function infiniteQueryOptions(options: unknown) {
   return options;
 }

Or add proper documentation:

 /**
- *
+ * Type-level helper for infinite query options that adds proper type inference.
+ * Returns the options unchanged at runtime but provides enhanced TypeScript types.
  */
 export function infiniteQueryOptions(options: unknown) {
   return options;
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • 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 85b5acc and 751dd31.

📒 Files selected for processing (15)
  • .changeset/fuzzy-keys-smell.md (1 hunks)
  • packages/clerk-js/src/test/mock-helpers.ts (3 hunks)
  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx (2 hunks)
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx (2 hunks)
  • packages/shared/src/react/clerk-rq/infiniteQueryOptions.ts (1 hunks)
  • packages/shared/src/react/clerk-rq/types.ts (2 hunks)
  • packages/shared/src/react/clerk-rq/useInfiniteQuery.ts (1 hunks)
  • packages/shared/src/react/hooks/usePageOrInfinite.types.ts (1 hunks)
  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx (1 hunks)
  • packages/shared/src/react/hooks/usePagesOrInfinite.shared.ts (1 hunks)
  • packages/shared/src/react/hooks/usePagesOrInfinite.swr.tsx (4 hunks)
  • packages/shared/src/react/hooks/usePagesOrInfinite.tsx (1 hunks)
  • packages/shared/src/react/hooks/useSubscription.rq.tsx (1 hunks)
  • packages/shared/src/types/virtual-data-hooks.d.ts (1 hunks)
  • packages/shared/tsconfig.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (15)
**/*.{js,jsx,ts,tsx}

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

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/shared/src/react/hooks/usePagesOrInfinite.tsx
  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/shared/src/react/hooks/usePagesOrInfinite.shared.ts
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/test/mock-helpers.ts
  • packages/shared/src/types/virtual-data-hooks.d.ts
  • packages/shared/src/react/clerk-rq/types.ts
  • packages/shared/src/react/clerk-rq/useInfiniteQuery.ts
  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
  • packages/shared/src/react/hooks/useSubscription.rq.tsx
  • packages/shared/src/react/hooks/usePageOrInfinite.types.ts
  • packages/shared/src/react/clerk-rq/infiniteQueryOptions.ts
  • packages/shared/src/react/hooks/usePagesOrInfinite.swr.tsx
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

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

Use Prettier for consistent code formatting

Files:

  • packages/shared/src/react/hooks/usePagesOrInfinite.tsx
  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/shared/src/react/hooks/usePagesOrInfinite.shared.ts
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/test/mock-helpers.ts
  • packages/shared/src/types/virtual-data-hooks.d.ts
  • packages/shared/src/react/clerk-rq/types.ts
  • packages/shared/src/react/clerk-rq/useInfiniteQuery.ts
  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
  • packages/shared/src/react/hooks/useSubscription.rq.tsx
  • packages/shared/src/react/hooks/usePageOrInfinite.types.ts
  • packages/shared/src/react/clerk-rq/infiniteQueryOptions.ts
  • packages/shared/tsconfig.json
  • packages/shared/src/react/hooks/usePagesOrInfinite.swr.tsx
packages/**/*.{ts,tsx}

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

TypeScript is required for all packages

Files:

  • packages/shared/src/react/hooks/usePagesOrInfinite.tsx
  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/shared/src/react/hooks/usePagesOrInfinite.shared.ts
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/test/mock-helpers.ts
  • packages/shared/src/types/virtual-data-hooks.d.ts
  • packages/shared/src/react/clerk-rq/types.ts
  • packages/shared/src/react/clerk-rq/useInfiniteQuery.ts
  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
  • packages/shared/src/react/hooks/useSubscription.rq.tsx
  • packages/shared/src/react/hooks/usePageOrInfinite.types.ts
  • packages/shared/src/react/clerk-rq/infiniteQueryOptions.ts
  • packages/shared/src/react/hooks/usePagesOrInfinite.swr.tsx
packages/**/*.{ts,tsx,d.ts}

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

Packages should export TypeScript types alongside runtime code

Files:

  • packages/shared/src/react/hooks/usePagesOrInfinite.tsx
  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/shared/src/react/hooks/usePagesOrInfinite.shared.ts
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/test/mock-helpers.ts
  • packages/shared/src/types/virtual-data-hooks.d.ts
  • packages/shared/src/react/clerk-rq/types.ts
  • packages/shared/src/react/clerk-rq/useInfiniteQuery.ts
  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
  • packages/shared/src/react/hooks/useSubscription.rq.tsx
  • packages/shared/src/react/hooks/usePageOrInfinite.types.ts
  • packages/shared/src/react/clerk-rq/infiniteQueryOptions.ts
  • packages/shared/src/react/hooks/usePagesOrInfinite.swr.tsx
**/*.{ts,tsx}

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

Use proper TypeScript error types

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/shared/src/react/hooks/usePagesOrInfinite.tsx
  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/shared/src/react/hooks/usePagesOrInfinite.shared.ts
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/test/mock-helpers.ts
  • packages/shared/src/types/virtual-data-hooks.d.ts
  • packages/shared/src/react/clerk-rq/types.ts
  • packages/shared/src/react/clerk-rq/useInfiniteQuery.ts
  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
  • packages/shared/src/react/hooks/useSubscription.rq.tsx
  • packages/shared/src/react/hooks/usePageOrInfinite.types.ts
  • packages/shared/src/react/clerk-rq/infiniteQueryOptions.ts
  • packages/shared/src/react/hooks/usePagesOrInfinite.swr.tsx
**/*.{jsx,tsx}

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

**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components

**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components: UserProfile, NavigationMenu
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...

Files:

  • packages/shared/src/react/hooks/usePagesOrInfinite.tsx
  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
  • packages/shared/src/react/hooks/useSubscription.rq.tsx
  • packages/shared/src/react/hooks/usePagesOrInfinite.swr.tsx
**/*.{js,ts,tsx,jsx}

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

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/shared/src/react/hooks/usePagesOrInfinite.tsx
  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/shared/src/react/hooks/usePagesOrInfinite.shared.ts
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/test/mock-helpers.ts
  • packages/shared/src/types/virtual-data-hooks.d.ts
  • packages/shared/src/react/clerk-rq/types.ts
  • packages/shared/src/react/clerk-rq/useInfiniteQuery.ts
  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
  • packages/shared/src/react/hooks/useSubscription.rq.tsx
  • packages/shared/src/react/hooks/usePageOrInfinite.types.ts
  • packages/shared/src/react/clerk-rq/infiniteQueryOptions.ts
  • packages/shared/src/react/hooks/usePagesOrInfinite.swr.tsx
**/*.tsx

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

**/*.tsx: Use proper type definitions for props and state
Leverage TypeScript's type inference where possible
Use proper event types for handlers
Implement proper generic types for reusable components
Use proper type guards for conditional rendering

Files:

  • packages/shared/src/react/hooks/usePagesOrInfinite.tsx
  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
  • packages/shared/src/react/hooks/useSubscription.rq.tsx
  • packages/shared/src/react/hooks/usePagesOrInfinite.swr.tsx
packages/clerk-js/src/ui/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/clerk-js-ui.mdc)

packages/clerk-js/src/ui/**/*.{ts,tsx}: Element descriptors should always be camelCase
Use element descriptors in UI components to enable consistent theming and styling via appearance.elements
Element descriptors should generate unique, stable CSS classes for theming
Element descriptors should handle state classes (e.g., cl-loading, cl-active, cl-error, cl-open) automatically based on component state
Do not render hard-coded values; all user-facing strings must be localized using provided localization methods
Use the useLocalizations hook and localizationKeys utility for all text and error messages
Use the styled system (sx prop, theme tokens, responsive values) for custom component styling
Use useCardState for card-level state, useFormState for form-level state, and useLoadingStatus for loading states
Always use handleError utility for API errors and use translateError for localized error messages
Use useFormControl for form field state, implement proper validation, and handle loading and error states in forms
Use localization keys for all form labels and placeholders
Use element descriptors for consistent styling and follow the theme token system
Use the Card and FormContainer patterns for consistent UI structure

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
packages/**/*.{test,spec}.{js,jsx,ts,tsx}

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

Unit tests should use Jest or Vitest as the test runner.

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
packages/{clerk-js,elements,themes}/**/*.{test,spec}.{js,jsx,ts,tsx}

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

Visual regression testing should be performed for UI components.

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
**/*.test.{jsx,tsx}

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

**/*.test.{jsx,tsx}: Use React Testing Library
Test component behavior, not implementation
Use proper test queries
Implement proper test isolation
Use proper test coverage
Test component interactions
Use proper test data
Implement proper test setup
Use proper test cleanup
Implement proper test assertions
Use proper test structure

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
**/__tests__/**/*.{ts,tsx}

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

**/__tests__/**/*.{ts,tsx}: Create type-safe test builders/factories
Use branded types for test isolation
Implement proper mock types that match interfaces

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
.changeset/**

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

Automated releases must use Changesets.

Files:

  • .changeset/fuzzy-keys-smell.md
packages/*/tsconfig.json

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

Type checking must be performed with TypeScript and publint.

Files:

  • packages/shared/tsconfig.json
🧬 Code graph analysis (8)
packages/shared/src/react/hooks/usePagesOrInfinite.shared.ts (1)
packages/shared/src/react/types.ts (1)
  • PagesOrInfiniteOptions (133-156)
packages/clerk-js/src/test/mock-helpers.ts (1)
packages/clerk-js/src/core/query-core.ts (1)
  • QueryClient (3-3)
packages/shared/src/types/virtual-data-hooks.d.ts (2)
packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx (1)
  • usePagesOrInfinite (13-191)
packages/shared/src/react/hooks/usePagesOrInfinite.swr.tsx (1)
  • usePagesOrInfinite (32-228)
packages/shared/src/react/clerk-rq/useInfiniteQuery.ts (3)
packages/shared/src/react/clerk-rq/infiniteQueryOptions.ts (2)
  • DefinedInitialDataInfiniteOptions (40-51)
  • UndefinedInitialDataInfiniteOptions (14-25)
packages/shared/src/react/clerk-rq/types.ts (3)
  • DefinedUseInfiniteQueryResult (60-63)
  • UseInfiniteQueryResult (58-58)
  • UseInfiniteQueryOptions (38-50)
packages/shared/src/react/clerk-rq/useBaseQuery.ts (1)
  • useBaseQuery (23-79)
packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx (7)
packages/shared/src/react/hooks/usePagesOrInfinite.swr.tsx (1)
  • usePagesOrInfinite (32-228)
packages/shared/src/react/hooks/usePageOrInfinite.types.ts (1)
  • UsePagesOrInfiniteSignature (7-26)
packages/shared/src/react/clerk-rq/use-clerk-query-client.ts (1)
  • useClerkQueryClient (84-84)
packages/shared/src/react/clerk-rq/useQuery.ts (1)
  • useClerkQuery (40-42)
packages/shared/src/react/hooks/usePagesOrInfinite.shared.ts (1)
  • getDifferentKeys (75-89)
packages/shared/src/react/clerk-rq/useInfiniteQuery.ts (1)
  • useClerkInfiniteQuery (42-44)
packages/shared/src/react/types.ts (2)
  • ValueOrSetter (4-4)
  • CacheSetter (6-8)
packages/shared/src/react/hooks/usePageOrInfinite.types.ts (1)
packages/shared/src/react/types.ts (3)
  • PagesOrInfiniteOptions (133-156)
  • PagesOrInfiniteConfig (104-128)
  • PaginatedResources (13-79)
packages/shared/src/react/clerk-rq/infiniteQueryOptions.ts (1)
packages/shared/src/react/clerk-rq/types.ts (1)
  • UseInfiniteQueryOptions (38-50)
packages/shared/src/react/hooks/usePagesOrInfinite.swr.tsx (2)
packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx (1)
  • usePagesOrInfinite (13-191)
packages/shared/src/react/hooks/usePageOrInfinite.types.ts (1)
  • UsePagesOrInfiniteSignature (7-26)
🪛 LanguageTool
.changeset/fuzzy-keys-smell.md

[grammar] ~1-~1: Dit kan een fout zijn.
Context: --- '@clerk/shared': patch --- wip

(QB_NEW_NL)


[grammar] ~5-~5: Dit kan een fout zijn.
Context: --- '@clerk/shared': patch --- wip

(QB_NEW_NL)

⏰ 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). (27)
  • GitHub Check: Integration Tests (expo-web, chrome)
  • GitHub Check: Integration Tests (astro, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 15)
  • GitHub Check: Integration Tests (quickstart, chrome, 15)
  • GitHub Check: Integration Tests (machine, chrome)
  • GitHub Check: Integration Tests (quickstart, chrome, 16)
  • GitHub Check: Integration Tests (nextjs, chrome, 16)
  • GitHub Check: Integration Tests (billing, chrome)
  • GitHub Check: Integration Tests (custom, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 14)
  • GitHub Check: Integration Tests (sessions:staging, chrome)
  • GitHub Check: Integration Tests (handshake:staging, chrome)
  • GitHub Check: Integration Tests (nuxt, chrome)
  • GitHub Check: Integration Tests (vue, chrome)
  • GitHub Check: Integration Tests (react-router, chrome)
  • GitHub Check: Integration Tests (tanstack-react-start, chrome)
  • GitHub Check: Integration Tests (generic, chrome)
  • GitHub Check: Integration Tests (handshake, chrome)
  • GitHub Check: Integration Tests (sessions, chrome)
  • GitHub Check: Integration Tests (ap-flows, chrome)
  • GitHub Check: Integration Tests (localhost, chrome)
  • GitHub Check: Integration Tests (elements, chrome)
  • GitHub Check: Integration Tests (express, chrome)
  • GitHub Check: Publish with pkg-pr-new
  • GitHub Check: Static analysis
  • GitHub Check: Unit Tests (22, **)
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (18)
.changeset/fuzzy-keys-smell.md (1)

1-5: Update changeset description before merging.

The changeset currently contains only "wip" as the description. Before merging this PR, replace this placeholder with a clear description of the changes (e.g., "Add React Query variant of usePagesOrInfinite hook with infinite query support").

packages/clerk-js/src/test/mock-helpers.ts (1)

49-97: LGTM! Clean test infrastructure for React Query.

The addition of defaultQueryClient with test-appropriate configuration (no retries, zero stale time) and the __internal_queryClient getter provides a solid foundation for testing React Query-based hooks. The __internal_ prefix appropriately signals this is for internal/test use.

packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx (1)

120-138: Verify test isolation with persistent mocks.

The change from mockReturnValueOnce to mockReturnValue makes these mocks persist across multiple invocations. This aligns with React Query's behavior where queries may be invoked multiple times (initial fetch, refetch, etc.). Ensure the persistent mock values correctly represent the expected behavior for all invocations within the test.

Also applies to: 159-164

packages/shared/src/react/hooks/usePagesOrInfinite.shared.ts (1)

75-89: LGTM! Clean implementation with good examples.

The getDifferentKeys function is well-implemented with efficient O(n+m) time complexity using a Set for lookups. The JSDoc examples clearly demonstrate the intended use cases.

packages/shared/src/react/hooks/usePageOrInfinite.types.ts (1)

3-5: LGTM! Clean type utilities for data extraction.

The ArrayType and ExtractData type helpers correctly use conditional types and infer to extract element types from arrays and unwrap data properties. These will be useful for maintaining type safety across the pagination hooks.

packages/shared/src/types/virtual-data-hooks.d.ts (1)

5-5: LGTM! Consistent with existing virtual module pattern.

The addition of usePagesOrInfinite export follows the same pattern as other virtual module exports. Using any is appropriate here since the actual implementation is resolved at build time through the virtual module system.

packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx (1)

222-227: Test isolation is properly maintained—no actionable changes needed.

The change from mockReturnValueOnce to mockReturnValue is correct. Test isolation is ensured through multiple layers:

  1. clearFetchCache() in beforeEach clears the fetch cache before each test
  2. Each test creates fresh fixtures via await createFixtures()
  3. Mocks are configured independently within each test (not in beforeEach)
  4. Each test specifies distinct mock values (e.g., total_count: 14 vs. total_count: 5)

The persistent mock pattern is appropriate for React Query's potential multiple fetches within a single test execution, while cache clearing prevents state leakage between tests.

packages/shared/tsconfig.json (1)

27-28: LGTM!

The new path mapping for virtual:data-hooks/usePagesOrInfinite correctly follows the established pattern for virtual module resolution, pointing to the SWR implementation file.

packages/shared/src/react/hooks/usePagesOrInfinite.tsx (1)

1-2: LGTM!

Clean re-export pattern that establishes the public API surface. The virtual module import will resolve to the appropriate implementation (SWR or RQ) based on build configuration.

packages/shared/src/react/clerk-rq/types.ts (2)

3-6: LGTM!

Imports the necessary observer result types from TanStack Query Core to support infinite query operations.


58-63: LGTM!

The new type aliases mirror the existing pattern for standard queries and provide proper TypeScript support for infinite query results with appropriate generic parameters.

packages/shared/src/react/hooks/usePagesOrInfinite.swr.tsx (3)

6-8: LGTM!

Good refactoring to import shared types and utilities, promoting code reuse between SWR and RQ implementations.


32-32: LGTM!

Using the shared UsePagesOrInfiniteSignature type ensures consistency across different implementation variants.


230-230: LGTM!

Re-exporting useWithSafeValues makes this utility available to consumers of the module.

packages/shared/src/react/clerk-rq/useInfiniteQuery.ts (1)

10-38: LGTM!

The three function overloads correctly provide type inference based on initialData presence, following TanStack Query's typing patterns. This ensures proper return types for defined vs undefined data scenarios.

packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx (1)

193-193: LGTM!

Re-exporting useWithSafeValues maintains API parity with the SWR implementation.

packages/shared/src/react/clerk-rq/infiniteQueryOptions.ts (2)

14-51: LGTM!

The three option type aliases provide precise typing for different infinite query scenarios (undefined initial data, unused skip token, defined initial data), following TanStack Query conventions.


53-87: LGTM!

The function overloads correctly map each option type to a return type that includes the DataTag type brand, enabling better type inference for query keys.

Comment on lines +73 to +76
getNextPageParam: (lastPage, allPages, lastPageParam) => {
const total = lastPage?.total_count ?? 0;
const consumed = (allPages.length + (params.initialPage ? params.initialPage - 1 : 0)) * (params.pageSize ?? 10);
return consumed < total ? (lastPageParam as number) + 1 : undefined;
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Verify getNextPageParam calculation for edge cases.

The calculation (allPages.length + (params.initialPage ? params.initialPage - 1 : 0)) assumes a specific page indexing pattern. Ensure this works correctly when:

  • initialPage is not 1
  • Pages have variable sizes
  • Total count changes between requests

Run the following verification to check usage patterns of initialPage:


🏁 Script executed:

#!/bin/bash
# Description: Find usages of initialPage to understand expected values and edge cases

# Search for initialPage assignments and usage
rg -n -C3 "initialPage\s*[:=]" --type=ts --type=tsx

Length of output: 27


I need to search for initialPage usage with a corrected approach. Let me retry the verification:


🏁 Script executed:

#!/bin/bash
# Description: Find usages of initialPage to understand expected values and edge cases

# Search for initialPage without file type restriction
rg -n -C3 "initialPage" packages/shared/src/react/hooks/ -g "*.ts" -g "*.tsx"

# Also search the broader codebase
echo "=== Broader search for initialPage ==="
rg -n "initialPage\s*=" --type typescript || rg -n "initialPage\s*=" packages/

Length of output: 85488


🏁 Script executed:

#!/bin/bash
# Check the complete getNextPageParam implementation and related test coverage

# Show the complete usePagesOrInfinite.rq.tsx around the problematic lines
echo "=== Complete getNextPageParam implementation ===" 
sed -n '70,85p' packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx

# Find and show relevant test case that validates initialPage behavior
echo ""
echo "=== Test case validating initialPage > 1 ===" 
sed -n '299,320p' packages/shared/src/react/hooks/__tests__/usePagesOrInfinite.spec.ts

Length of output: 1680


Refactor the getNextPageParam calculation to use the defaulted initialPageParam value consistently.

The calculation at line 75 should reference the initialPageParam value (set at line 72 with a default of 1) rather than rechecking params.initialPage directly. Replace:

const consumed = (allPages.length + (params.initialPage ? params.initialPage - 1 : 0)) * (params.pageSize ?? 10);

with:

const consumed = (allPages.length + (initialPageParam - 1)) * (params.pageSize ?? 10);

This eliminates the unnecessary ternary, improves clarity, and ensures the calculation uses the actual starting page value that was already computed. The current code works because undefined being falsy accidentally produces the correct offset (0), but it's fragile and inconsistent with the initialPageParam default set on line 72.

🤖 Prompt for AI Agents
In packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx around lines 73 to
76, the getNextPageParam calculation uses params.initialPage directly causing
inconsistency with the defaulted initialPageParam set at line 72; replace the
ternary that references params.initialPage with a calculation that uses
initialPageParam (i.e., compute consumed using (allPages.length +
(initialPageParam - 1)) * (params.pageSize ?? 10)) so the offset consistently
respects the defaulted starting page and removes the fragile conditional.

Comment on lines 96 to 111
const fetchPage: ValueOrSetter<number> = useCallback(
numberOrgFn => {
if (triggerInfinite) {
const next = typeof numberOrgFn === 'function' ? (numberOrgFn as (n: number) => number)(page) : numberOrgFn;
const targetCount = Math.max(0, next);
const currentCount = infiniteQuery.data?.pages?.length ?? 0;
const toFetch = targetCount - currentCount;
if (toFetch > 0) {
void infiniteQuery.fetchNextPage({ cancelRefetch: false });
}
return;
}
return setPaginatedPage(numberOrgFn);
},
[infiniteQuery, page, triggerInfinite],
);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

fetchPage infinite mode only supports forward pagination.

In infinite mode (lines 98-106), fetchPage can only fetch forward - it calls fetchNextPage when toFetch > 0 but silently no-ops when trying to navigate backward. This differs from the paginated mode behavior and may confuse users.

Consider either:

  1. Adding a warning when attempting backward navigation in infinite mode
  2. Documenting this limitation clearly in JSDoc
  3. Implementing backward navigation support if feasible
🤖 Prompt for AI Agents
In packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx around lines 96 to
111, the infinite-mode branch only handles forward pagination (calls
fetchNextPage when toFetch > 0) and silently no-ops on backward navigation;
update the handler to detect toFetch < 0 and give clear feedback instead of
silently doing nothing — add a warning log (e.g. console.warn or a logger) that
backward navigation isn’t supported in infinite mode and return, and add a short
JSDoc note above the hook explaining this limitation (or alternatively implement
backward support if you prefer); ensure tests or callers relying on fetchPage
are adjusted to expect the warning behavior.

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: 5

Caution

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

⚠️ Outside diff range comments (2)
packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx (1)

570-590: Mock configuration issue: Second mockReturnValue overwrites the first.

The second mockReturnValue call on line 590 completely overwrites the first one on line 570. Unlike mockReturnValueOnce, mockReturnValue persists for all subsequent calls.

This means:

  • The initial fetch (before line 570) won't get the expected data
  • When fetchNext is called on line 610, it will return items with ids '3' and '4'
  • But items '1' and '2' were never returned, breaking the infinite fetch expectation

This is likely why the test is failing.

Apply this diff to fix the mock setup:

-fixtures.clerk.organization?.getInvitations.mockReturnValue(
+fixtures.clerk.organization?.getInvitations.mockReturnValueOnce(
   Promise.resolve({
     data: [
       createFakeOrganizationInvitation({
         id: '1',
         emailAddress: '[email protected]',
         organizationId: '1',
         createdAt: new Date('2022-01-01'),
       }),
       createFakeOrganizationInvitation({
         id: '2',
         emailAddress: '[email protected]',
         organizationId: '1',
         createdAt: new Date('2022-01-01'),
       }),
     ],
     total_count: 4,
   }),
 );

-fixtures.clerk.organization?.getInvitations.mockReturnValue(
+fixtures.clerk.organization?.getInvitations.mockReturnValueOnce(
   Promise.resolve({
     data: [
       createFakeOrganizationInvitation({
         id: '3',
         emailAddress: '[email protected]',
         organizationId: '1',
         createdAt: new Date('2022-01-01'),
       }),
       createFakeOrganizationInvitation({
         id: '4',
         emailAddress: '[email protected]',
         organizationId: '1',
         createdAt: new Date('2022-01-01'),
       }),
     ],
     total_count: 4,
   }),
 );

After fixing this, you should be able to unskip the test on line 526.

packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationProfile.test.tsx (1)

73-84: Remove redundant mockRejectedValue call.

Lines 73-74 call mockRejectedValue(null), but lines 76-84 immediately call mockResolvedValue(...) on the same mocks. The second call overrides the first, making the rejection setup unnecessary and potentially confusing.

-      fixtures.clerk.billing.getSubscription.mockRejectedValue(null);
-      fixtures.clerk.billing.getStatements.mockRejectedValue(null);
-
       fixtures.clerk.billing.getSubscription.mockResolvedValue({
         id: 'sub_top',
         subscriptionItems: [
🧹 Nitpick comments (6)
packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx (1)

105-107: Consider using proper Error objects instead of null for mock rejections.

The pattern mockRejectedValue(null) is repeated throughout the test file (lines 105-107, 232-234, 332-334, 440-442) to prevent unrelated resources from being fetched. However, rejecting with null doesn't realistically simulate error scenarios—real API failures typically reject with Error objects.

Consider this approach:

-fixtures.clerk.organization?.getDomains.mockRejectedValue(null);
-fixtures.clerk.organization?.getMembershipRequests.mockRejectedValue(null);
-fixtures.clerk.organization?.getInvitations.mockRejectedValue(null);
+fixtures.clerk.organization?.getDomains.mockRejectedValue(new Error('Not testing domains'));
+fixtures.clerk.organization?.getMembershipRequests.mockRejectedValue(new Error('Not testing membership requests'));
+fixtures.clerk.organization?.getInvitations.mockRejectedValue(new Error('Not testing invitations'));

This ensures error-handling paths are tested more realistically.

packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx (1)

58-59: Pass explicit error values to mockRejectedValue().

Throughout the tests, mockRejectedValue() is called without arguments, which will reject with undefined. For better test clarity and realism, consider passing explicit error objects.

Example:

-fixtures.clerk.billing.getStatements.mockRejectedValue();
-fixtures.clerk.user.getPaymentMethods.mockRejectedValue();
+fixtures.clerk.billing.getStatements.mockRejectedValue(new Error('Not available'));
+fixtures.clerk.user.getPaymentMethods.mockRejectedValue(new Error('Not available'));

Also applies to: 119-120, 159-159, 191-191, 220-221, 314-315, 341-342, 390-390, 412-413, 435-436, 464-465, 526-527, 581-582, 635-636

packages/clerk-js/src/ui/components/SubscriptionDetails/__tests__/SubscriptionDetails.test.tsx (1)

41-44: Consider extracting repeated mock setup to reduce duplication.

The same four billing method mocks are repeated across 11 tests. This pattern could be extracted into a shared test helper function or moved to a common setup block to improve maintainability and adhere to the DRY principle.

Example refactor:

// Add a helper function at the top of the describe block
const setupBillingMocks = (fixtures: ReturnType<typeof createFixtures>['fixtures']) => {
  fixtures.clerk.billing.getPlans.mockResolvedValue([]);
  fixtures.clerk.billing.getStatements.mockResolvedValue([]);
  fixtures.clerk.billing.getPaymentAttempts.mockResolvedValue([]);
  fixtures.clerk.user.getPaymentMethods.mockResolvedValue([]);
};

Then replace each occurrence with:

-    fixtures.clerk.billing.getPlans.mockResolvedValue([]);
-    fixtures.clerk.billing.getStatements.mockResolvedValue([]);
-    fixtures.clerk.billing.getPaymentAttempts.mockResolvedValue([]);
-    fixtures.clerk.user.getPaymentMethods.mockResolvedValue([]);
+    setupBillingMocks(fixtures);

Also applies to: 148-151, 255-258, 342-345, 505-508, 647-650, 754-757, 861-864, 971-974, 1065-1068, 1178-1181

packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/InviteMembersPage.test.tsx (1)

33-34: Consider using mockResolvedValue with empty data instead of mockRejectedValue(null).

Throughout this file, getInvitations is mocked to reject with null. While this prevents unintended API calls, it's more idiomatic to resolve with empty data to simulate the absence of invitations:

-fixtures.clerk.organization?.getInvitations.mockRejectedValue(null);
+fixtures.clerk.organization?.getInvitations.mockResolvedValue({ data: [], total_count: 0 });

This pattern better represents the actual API behavior and avoids the unusual practice of rejecting with null (which isn't a proper Error object).

packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx (1)

33-34: Consider using mockResolvedValue with empty data instead of mockRejectedValue(null).

Similar to the InviteMembersPage test file, rejecting with null is unusual. Consider resolving with empty data instead:

-fixtures.clerk.organization?.getInvitations.mockRejectedValue(null);
-fixtures.clerk.organization?.getMemberships.mockRejectedValue(null);
+fixtures.clerk.organization?.getInvitations.mockResolvedValue({ data: [], total_count: 0 });
+fixtures.clerk.organization?.getMemberships.mockResolvedValue({ data: [], total_count: 0 });
packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx (1)

68-69: Consider using mockResolvedValue with empty data.

Similar to other test files, rejecting with null is unusual. Consider resolving with empty data instead:

-fixtures.clerk.user?.getOrganizationInvitations.mockRejectedValue(null);
-fixtures.clerk.user?.getOrganizationSuggestions.mockRejectedValue(null);
+fixtures.clerk.user?.getOrganizationInvitations.mockResolvedValue({ data: [], total_count: 0 });
+fixtures.clerk.user?.getOrganizationSuggestions.mockResolvedValue({ data: [], total_count: 0 });
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • 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 751dd31 and 582f018.

📒 Files selected for processing (12)
  • packages/clerk-js/src/test/mock-helpers.ts (3 hunks)
  • packages/clerk-js/src/ui/components/Checkout/__tests__/Checkout.test.tsx (1 hunks)
  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx (7 hunks)
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/InviteMembersPage.test.tsx (12 hunks)
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx (14 hunks)
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationProfile.test.tsx (5 hunks)
  • packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx (15 hunks)
  • packages/clerk-js/src/ui/components/SubscriptionDetails/__tests__/SubscriptionDetails.test.tsx (12 hunks)
  • packages/clerk-js/src/ui/components/Subscriptions/__tests__/SubscriptionsList.test.tsx (7 hunks)
  • packages/clerk-js/src/ui/components/UserProfile/__tests__/UserProfile.test.tsx (2 hunks)
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx (10 hunks)
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx (13 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/clerk-js/src/test/mock-helpers.ts
🧰 Additional context used
📓 Path-based instructions (13)
packages/clerk-js/src/ui/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/clerk-js-ui.mdc)

packages/clerk-js/src/ui/**/*.{ts,tsx}: Element descriptors should always be camelCase
Use element descriptors in UI components to enable consistent theming and styling via appearance.elements
Element descriptors should generate unique, stable CSS classes for theming
Element descriptors should handle state classes (e.g., cl-loading, cl-active, cl-error, cl-open) automatically based on component state
Do not render hard-coded values; all user-facing strings must be localized using provided localization methods
Use the useLocalizations hook and localizationKeys utility for all text and error messages
Use the styled system (sx prop, theme tokens, responsive values) for custom component styling
Use useCardState for card-level state, useFormState for form-level state, and useLoadingStatus for loading states
Always use handleError utility for API errors and use translateError for localized error messages
Use useFormControl for form field state, implement proper validation, and handle loading and error states in forms
Use localization keys for all form labels and placeholders
Use element descriptors for consistent styling and follow the theme token system
Use the Card and FormContainer patterns for consistent UI structure

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/ui/components/SubscriptionDetails/__tests__/SubscriptionDetails.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/InviteMembersPage.test.tsx
  • packages/clerk-js/src/ui/components/Checkout/__tests__/Checkout.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx
  • packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationProfile.test.tsx
  • packages/clerk-js/src/ui/components/UserProfile/__tests__/UserProfile.test.tsx
  • packages/clerk-js/src/ui/components/Subscriptions/__tests__/SubscriptionsList.test.tsx
**/*.{js,jsx,ts,tsx}

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

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/ui/components/SubscriptionDetails/__tests__/SubscriptionDetails.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/InviteMembersPage.test.tsx
  • packages/clerk-js/src/ui/components/Checkout/__tests__/Checkout.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx
  • packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationProfile.test.tsx
  • packages/clerk-js/src/ui/components/UserProfile/__tests__/UserProfile.test.tsx
  • packages/clerk-js/src/ui/components/Subscriptions/__tests__/SubscriptionsList.test.tsx
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

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

Use Prettier for consistent code formatting

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/ui/components/SubscriptionDetails/__tests__/SubscriptionDetails.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/InviteMembersPage.test.tsx
  • packages/clerk-js/src/ui/components/Checkout/__tests__/Checkout.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx
  • packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationProfile.test.tsx
  • packages/clerk-js/src/ui/components/UserProfile/__tests__/UserProfile.test.tsx
  • packages/clerk-js/src/ui/components/Subscriptions/__tests__/SubscriptionsList.test.tsx
packages/**/*.{ts,tsx}

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

TypeScript is required for all packages

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/ui/components/SubscriptionDetails/__tests__/SubscriptionDetails.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/InviteMembersPage.test.tsx
  • packages/clerk-js/src/ui/components/Checkout/__tests__/Checkout.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx
  • packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationProfile.test.tsx
  • packages/clerk-js/src/ui/components/UserProfile/__tests__/UserProfile.test.tsx
  • packages/clerk-js/src/ui/components/Subscriptions/__tests__/SubscriptionsList.test.tsx
packages/**/*.{ts,tsx,d.ts}

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

Packages should export TypeScript types alongside runtime code

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/ui/components/SubscriptionDetails/__tests__/SubscriptionDetails.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/InviteMembersPage.test.tsx
  • packages/clerk-js/src/ui/components/Checkout/__tests__/Checkout.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx
  • packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationProfile.test.tsx
  • packages/clerk-js/src/ui/components/UserProfile/__tests__/UserProfile.test.tsx
  • packages/clerk-js/src/ui/components/Subscriptions/__tests__/SubscriptionsList.test.tsx
**/*.{ts,tsx}

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

Use proper TypeScript error types

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/ui/components/SubscriptionDetails/__tests__/SubscriptionDetails.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/InviteMembersPage.test.tsx
  • packages/clerk-js/src/ui/components/Checkout/__tests__/Checkout.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx
  • packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationProfile.test.tsx
  • packages/clerk-js/src/ui/components/UserProfile/__tests__/UserProfile.test.tsx
  • packages/clerk-js/src/ui/components/Subscriptions/__tests__/SubscriptionsList.test.tsx
**/*.{jsx,tsx}

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

**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components

**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components: UserProfile, NavigationMenu
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/ui/components/SubscriptionDetails/__tests__/SubscriptionDetails.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/InviteMembersPage.test.tsx
  • packages/clerk-js/src/ui/components/Checkout/__tests__/Checkout.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx
  • packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationProfile.test.tsx
  • packages/clerk-js/src/ui/components/UserProfile/__tests__/UserProfile.test.tsx
  • packages/clerk-js/src/ui/components/Subscriptions/__tests__/SubscriptionsList.test.tsx
packages/**/*.{test,spec}.{js,jsx,ts,tsx}

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

Unit tests should use Jest or Vitest as the test runner.

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/ui/components/SubscriptionDetails/__tests__/SubscriptionDetails.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/InviteMembersPage.test.tsx
  • packages/clerk-js/src/ui/components/Checkout/__tests__/Checkout.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx
  • packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationProfile.test.tsx
  • packages/clerk-js/src/ui/components/UserProfile/__tests__/UserProfile.test.tsx
  • packages/clerk-js/src/ui/components/Subscriptions/__tests__/SubscriptionsList.test.tsx
packages/{clerk-js,elements,themes}/**/*.{test,spec}.{js,jsx,ts,tsx}

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

Visual regression testing should be performed for UI components.

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/ui/components/SubscriptionDetails/__tests__/SubscriptionDetails.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/InviteMembersPage.test.tsx
  • packages/clerk-js/src/ui/components/Checkout/__tests__/Checkout.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx
  • packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationProfile.test.tsx
  • packages/clerk-js/src/ui/components/UserProfile/__tests__/UserProfile.test.tsx
  • packages/clerk-js/src/ui/components/Subscriptions/__tests__/SubscriptionsList.test.tsx
**/*.{js,ts,tsx,jsx}

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

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/ui/components/SubscriptionDetails/__tests__/SubscriptionDetails.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/InviteMembersPage.test.tsx
  • packages/clerk-js/src/ui/components/Checkout/__tests__/Checkout.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx
  • packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationProfile.test.tsx
  • packages/clerk-js/src/ui/components/UserProfile/__tests__/UserProfile.test.tsx
  • packages/clerk-js/src/ui/components/Subscriptions/__tests__/SubscriptionsList.test.tsx
**/*.tsx

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

**/*.tsx: Use proper type definitions for props and state
Leverage TypeScript's type inference where possible
Use proper event types for handlers
Implement proper generic types for reusable components
Use proper type guards for conditional rendering

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/ui/components/SubscriptionDetails/__tests__/SubscriptionDetails.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/InviteMembersPage.test.tsx
  • packages/clerk-js/src/ui/components/Checkout/__tests__/Checkout.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx
  • packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationProfile.test.tsx
  • packages/clerk-js/src/ui/components/UserProfile/__tests__/UserProfile.test.tsx
  • packages/clerk-js/src/ui/components/Subscriptions/__tests__/SubscriptionsList.test.tsx
**/*.test.{jsx,tsx}

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

**/*.test.{jsx,tsx}: Use React Testing Library
Test component behavior, not implementation
Use proper test queries
Implement proper test isolation
Use proper test coverage
Test component interactions
Use proper test data
Implement proper test setup
Use proper test cleanup
Implement proper test assertions
Use proper test structure

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/ui/components/SubscriptionDetails/__tests__/SubscriptionDetails.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/InviteMembersPage.test.tsx
  • packages/clerk-js/src/ui/components/Checkout/__tests__/Checkout.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx
  • packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationProfile.test.tsx
  • packages/clerk-js/src/ui/components/UserProfile/__tests__/UserProfile.test.tsx
  • packages/clerk-js/src/ui/components/Subscriptions/__tests__/SubscriptionsList.test.tsx
**/__tests__/**/*.{ts,tsx}

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

**/__tests__/**/*.{ts,tsx}: Create type-safe test builders/factories
Use branded types for test isolation
Implement proper mock types that match interfaces

Files:

  • packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx
  • packages/clerk-js/src/ui/components/SubscriptionDetails/__tests__/SubscriptionDetails.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/InviteMembersPage.test.tsx
  • packages/clerk-js/src/ui/components/Checkout/__tests__/Checkout.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx
  • packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx
  • packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx
  • packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationProfile.test.tsx
  • packages/clerk-js/src/ui/components/UserProfile/__tests__/UserProfile.test.tsx
  • packages/clerk-js/src/ui/components/Subscriptions/__tests__/SubscriptionsList.test.tsx
🧬 Code graph analysis (1)
packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx (1)
packages/shared/src/utils/createDeferredPromise.ts (1)
  • createDeferredPromise (11-19)
⏰ 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). (29)
  • GitHub Check: Integration Tests (machine, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 14)
  • GitHub Check: Integration Tests (quickstart, chrome, 16)
  • GitHub Check: Integration Tests (quickstart, chrome, 15)
  • GitHub Check: Integration Tests (nextjs, chrome, 16)
  • GitHub Check: Integration Tests (custom, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 15)
  • GitHub Check: Integration Tests (billing, chrome)
  • GitHub Check: Integration Tests (vue, chrome)
  • GitHub Check: Integration Tests (tanstack-react-start, chrome)
  • GitHub Check: Integration Tests (astro, chrome)
  • GitHub Check: Integration Tests (ap-flows, chrome)
  • GitHub Check: Integration Tests (react-router, chrome)
  • GitHub Check: Integration Tests (handshake:staging, chrome)
  • GitHub Check: Integration Tests (handshake, chrome)
  • GitHub Check: Integration Tests (nuxt, chrome)
  • GitHub Check: Integration Tests (expo-web, chrome)
  • GitHub Check: Integration Tests (sessions:staging, chrome)
  • GitHub Check: Integration Tests (express, chrome)
  • GitHub Check: Integration Tests (elements, chrome)
  • GitHub Check: Integration Tests (sessions, chrome)
  • GitHub Check: Integration Tests (localhost, chrome)
  • GitHub Check: Integration Tests (generic, chrome)
  • GitHub Check: Static analysis
  • GitHub Check: Unit Tests (22, **)
  • GitHub Check: Publish with pkg-pr-new
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (15)
packages/clerk-js/src/ui/components/UserProfile/__tests__/UserProfile.test.tsx (1)

116-117: LGTM!

The assertions correctly verify that the billing API methods are called even when hasPaidPlans is true, ensuring the component doesn't short-circuit the API calls based solely on configuration flags.

packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx (1)

45-72: LGTM! Good test coverage improvement.

Destructuring fixtures and asserting that API methods are not invoked in the default state properly validates that resources are fetched lazily only when requested.

packages/clerk-js/src/ui/components/PricingTable/__tests__/PricingTable.test.tsx (1)

1-1: LGTM!

The import is correctly added and properly used in the test at line 438.

packages/clerk-js/src/ui/components/Checkout/__tests__/Checkout.test.tsx (1)

312-313: Remove the skip or provide clear tracking before merge; this test cannot be deferred without documentation.

This is the only skipped test in the file. While the PR enables RQ variant support, test skips require either immediate fixes or formal tracking (issue link, detailed failure description in TODO). The vague TODO "Why is this failing?" doesn't help future developers.

The comparable status: 'completed' test at line 396 passes with identical mock structure, suggesting the issue is specific to the needs_confirmation state handling under the RQ variant.

Options:

  • Fix it now: Investigate whether confirmation stage component logic or mock setup needs adjustment for RQ variant
  • Track it formally: Replace TODO with issue link and specific failure symptom (e.g., "timeout waiting for element X" or "React Query retry causing assertion to fail")
  • Remove entirely: If confirmation stage isn't required for this PR, remove the incomplete test and file a separate task
packages/clerk-js/src/ui/components/SubscriptionDetails/__tests__/SubscriptionDetails.test.tsx (2)

1-1283: Well-structured test suite with comprehensive coverage.

The test suite demonstrates good practices:

  • Proper use of React Testing Library queries and user interactions
  • Well-isolated tests with explicit mocking
  • Comprehensive coverage of different subscription states (active, past due, free trial, etc.)
  • Clear test naming and assertions

12-34: ****

The first test is correctly set up without the billing method mocks. The SubscriptionDetails component only calls useSubscription(), which fetches subscription data via __experimental_useSubscription. The additional mocks for getPlans, getStatements, getPaymentAttempts, and getPaymentMethods are not invoked by the SubscriptionDetails component during initialization or rendering, so their absence in the first test is not a problem. The four mocks present in the other tests appear to be either unnecessary for this component or copied from a different test context.

Likely an incorrect or invalid review comment.

packages/clerk-js/src/ui/components/Subscriptions/__tests__/SubscriptionsList.test.tsx (2)

54-57: Good addition: Explicitly verifying data-fetching calls.

These expectations ensure the component properly attempts to fetch billing data even when subscriptions are empty. This improves test coverage and makes the test intent clearer.


24-25: Clarify the skipped test and resolve before merging.

The TODO comment is confusing—it states the test "passes with RQ and fails with SWR," suggesting RQ works correctly, yet the test remains skipped. The RQ implementation already includes proper enabled flags (in useSubscription.rq.tsx line 58: enabled: Boolean(user?.id && billingEnabled) && ...), so the concern about unwanted requests appears to be addressed.

Before merging, verify one of the following:

  1. If RQ is working: Unskip the test and confirm it passes.
  2. If the test still fails: Document the specific failure reason in the TODO comment and track resolution separately.

Update the TODO to be explicit: clarify whether this is a known limitation of the test setup, a remaining RQ issue, or a case where the test expectations need adjustment.

packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationMembers.test.tsx (1)

162-174: Verify the mock strategy change from one-time to persistent.

The mock has been changed from mockReturnValueOnce to mockReturnValue, which means it will persist across multiple invocations instead of being consumed after the first call. Ensure this aligns with the component's actual behavior—if getMemberships is called multiple times during the test lifecycle, this change is correct.

packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx (2)

48-66: Mock strategy change looks correct.

The shift from mockReturnValueOnce to mockReturnValue for getOrganizationMemberships and getOrganizationInvitations aligns with the pattern used across other test files in this PR. This allows mocks to persist across multiple invocations, which is appropriate if these methods are called multiple times during the test lifecycle.

Also applies to: 120-138, 159-164


345-345: setActive mock change is consistent.

Changing setActive.mockReturnValueOnce to setActive.mockReturnValue is consistent with the broader mock strategy update in this PR.

Also applies to: 395-395, 426-426

packages/clerk-js/src/ui/components/OrganizationProfile/__tests__/OrganizationProfile.test.tsx (2)

183-184: Good addition of explicit API call assertions.

Adding explicit assertions to verify that getSubscription and getStatements are called improves test clarity and ensures the billing APIs are invoked as expected when billing is enabled.


92-115: Re-enable test after implementing permission guard for billing API calls.

The test correctly identifies a real issue: billing APIs (getSubscription, getStatements) are called unconditionally in useOrganizationProfileContext before any permission checks. The wrapper only controls UI visibility, not API execution.

To re-enable this test, add a permission check that prevents useSubscription() and useStatements() from being called when the user lacks org:sys_billing:read or org:sys_billing:manage permissions. This ensures billing data is not fetched for unauthorized users.

packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx (2)

108-109: Good addition of explicit API call verification.

Adding waitFor expectations to verify that getOrganizationInvitations and getOrganizationSuggestions are called improves test reliability by ensuring these APIs are invoked during the test flow.


173-174: Investigate and re-enable skipped infinite fetch tests.

The three "infinite fetch" tests in packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganizationList.test.tsx (at lines 173-174, 402-403, 582-583) are valid test cases that should be investigated and re-enabled.

Verification confirms that:

  • The infinite parameter is fully supported and properly implemented in the shared library's usePagesOrInfinite hook
  • Production code actively uses infinite: true through organizationListParams for all three collection types
  • The shared package has comprehensive passing tests for infinite mode, including data accumulation behavior during fetchNext() calls
  • The clerk-js test structure mirrors the working tests in the shared package, suggesting the issue is test-specific rather than feature-related

Re-enabling these tests is important for maintaining test coverage of infinite scrolling behavior in organization list components, which is actively used in production.

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

♻️ Duplicate comments (1)
packages/shared/src/react/hooks/__tests__/usePagesOrInfinite.spec.ts (1)

735-756: Add assertions on captured states as previously requested.

The past review comment correctly identifies that capturedStates is collected but never asserted. Without assertions, the test provides no signal if the transient loading behavior changes.

Apply this diff to add the missing assertions:

     // Wait for new data to settle
     await waitFor(() => expect(result.current.data).toEqual([{ id: 'item-B' }]));
     expect(result.current.isLoading).toBe(false);

+    // Verify we captured some transitional states
+    expect(capturedStates.length).toBeGreaterThan(0);
+    // At least one state during transition should show loading or fetching
+    const hadTransition = capturedStates.some(s => s.isLoading || s.isFetching);
+    expect(hadTransition).toBe(true);
+
     // Document that during transition, we may see loading/fetching states
     // This is expected RQ behavior and tests must account for it
     expect(fetcher).toHaveBeenCalledTimes(2);
🧹 Nitpick comments (7)
packages/shared/src/react/hooks/__tests__/createBillingPaginatedHook.spec.tsx (2)

59-61: Recreating mocks in beforeEach may hide mutation issues.

While this ensures test isolation, recreating mockUser and mockOrganization on each test may hide issues where tests inadvertently mutate shared state. Consider whether tests should explicitly recreate mocks only when needed.


163-186: Consider consolidating with existing orgId forwarding test.

This test is nearly identical to the test at lines 149-161, except it uses infinite: true. The differences are:

  • Line 172: adds infinite: true
  • Line 164-169: mocks fetcher to return data
  • Line 185: asserts data length

Consider parameterizing the existing test or adding a focused assertion for the infinite-mode-specific behavior rather than duplicating the entire test.

Apply this approach to reduce duplication:

it.each([
  { infinite: false },
  { infinite: true },
])('when for=organization orgId should be forwarded to fetcher (infinite: $infinite)', async ({ infinite }) => {
  if (infinite) {
    fetcherMock.mockImplementation((params: any) =>
      Promise.resolve({
        data: Array.from({ length: params.pageSize }, (_, i) => ({ id: `item-${params.initialPage}-${i}` })),
        total_count: 20,
      }),
    );
  }

  const { result } = renderHook(
    () => useDummyAuth({ initialPage: 1, pageSize: 4, for: 'organization', infinite } as any),
    { wrapper },
  );

  await waitFor(() => expect(result.current.isLoading).toBe(false));
  expect(useFetcherMock).toHaveBeenCalledWith('organization');
  expect(fetcherMock.mock.calls[0][0]).toStrictEqual({
    initialPage: 1,
    pageSize: 4,
    orgId: 'org_1',
  });
  
  if (infinite) {
    expect(result.current.data.length).toBe(4);
  }
});
packages/shared/src/react/hooks/__tests__/mocks/clerk.ts (2)

27-55: Add type constraints to mock factories.

The extensive use of any reduces type safety. Consider defining interfaces for the mock shapes:

interface MockClerkConfig {
  billing?: any;
  queryClient?: ReturnType<typeof createMockQueryClient>;
  loaded?: boolean;
  __unstable__environment?: any;
  [key: string]: any;
}

export function createMockClerk(overrides: MockClerkConfig = {}) {
  const queryClient = overrides.queryClient || createMockQueryClient();
  // ... rest of implementation
}

This provides better IntelliSense and catches misuse while maintaining flexibility for test-specific overrides.

As per coding guidelines


57-63: Add JSDoc comments to test utility functions.

These factories are reused across multiple test files. Add JSDoc comments documenting:

  • Purpose of each factory
  • Available override options
  • Return type structure
/**
 * Creates a mock user object for testing.
 * @param overrides - Properties to override on the default mock user
 * @returns Mock user with id 'user_1' by default
 */
export function createMockUser(overrides: any = {}) {
  return { id: 'user_1', ...overrides };
}

As per coding guidelines

packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx (2)

51-55: Recreating mocks in beforeEach may hide mutation issues.

Similar to the pattern in createBillingPaginatedHook.spec.tsx, recreating mockUser and mockOrganization in every test may mask issues where tests inadvertently mutate shared state. Consider whether tests should only recreate mocks when explicitly needed for their scenario.


106-113: Conditional test logic adds maintenance complexity.

The if (__CLERK_USE_RQ__) branching creates dual execution paths. As noted in createBillingPaginatedHook.spec.tsx, consider:

  1. Separating RQ and SWR test suites
  2. Using parameterized tests
  3. Extracting conditional expectations into helper functions

This pattern appears in multiple test files (lines 106-113, 134-142), suggesting it could benefit from a shared abstraction.

Based on learnings

.github/workflows/ci.yml (1)

289-289: Artifact naming now includes CLERK_USE_RQ context for better traceability.

Line 289 uses matrix.clerk-use-rq || 'default' to label artifacts with the flag state; line 490 uses conditional formatting to append -rq{value} suffix. This enhances debuggability. However, consider consistent formatting: line 290 produces names like -node-22-false, -node-22-true, or -node-22-default, while line 490 produces -rqtrue or -rqfalse (no hyphen between prefix and value). Minor nitpick, but -rq-true/-rq-false would be more readable.

If more readable naming is preferred, update line 490 format:

-name: playwright-traces-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.test-name }}${{ matrix.next-version && format('-next{0}', matrix.next-version) || '' }}${{ matrix.clerk-use-rq && format('-rq{0}', matrix.clerk-use-rq) || '' }}
+name: playwright-traces-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.test-name }}${{ matrix.next-version && format('-next{0}', matrix.next-version) || '' }}${{ matrix.clerk-use-rq && format('-rq-{0}', matrix.clerk-use-rq) || '' }}

Also applies to: 490-490

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • 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 6f27804 and b876a94.

📒 Files selected for processing (7)
  • .github/workflows/ci.yml (7 hunks)
  • packages/shared/src/react/hooks/__tests__/createBillingPaginatedHook.spec.tsx (4 hunks)
  • packages/shared/src/react/hooks/__tests__/mocks/clerk.ts (1 hunks)
  • packages/shared/src/react/hooks/__tests__/mocks/index.ts (1 hunks)
  • packages/shared/src/react/hooks/__tests__/usePagesOrInfinite.spec.ts (5 hunks)
  • packages/shared/src/react/hooks/__tests__/usePlans.spec.tsx (5 hunks)
  • packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx (5 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/shared/src/react/hooks/tests/mocks/index.ts
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{js,jsx,ts,tsx}

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

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/shared/src/react/hooks/__tests__/mocks/clerk.ts
  • packages/shared/src/react/hooks/__tests__/usePagesOrInfinite.spec.ts
  • packages/shared/src/react/hooks/__tests__/createBillingPaginatedHook.spec.tsx
  • packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx
  • packages/shared/src/react/hooks/__tests__/usePlans.spec.tsx
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

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

Use Prettier for consistent code formatting

Files:

  • packages/shared/src/react/hooks/__tests__/mocks/clerk.ts
  • packages/shared/src/react/hooks/__tests__/usePagesOrInfinite.spec.ts
  • packages/shared/src/react/hooks/__tests__/createBillingPaginatedHook.spec.tsx
  • packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx
  • packages/shared/src/react/hooks/__tests__/usePlans.spec.tsx
packages/**/*.{ts,tsx}

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

TypeScript is required for all packages

Files:

  • packages/shared/src/react/hooks/__tests__/mocks/clerk.ts
  • packages/shared/src/react/hooks/__tests__/usePagesOrInfinite.spec.ts
  • packages/shared/src/react/hooks/__tests__/createBillingPaginatedHook.spec.tsx
  • packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx
  • packages/shared/src/react/hooks/__tests__/usePlans.spec.tsx
packages/**/*.{ts,tsx,d.ts}

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

Packages should export TypeScript types alongside runtime code

Files:

  • packages/shared/src/react/hooks/__tests__/mocks/clerk.ts
  • packages/shared/src/react/hooks/__tests__/usePagesOrInfinite.spec.ts
  • packages/shared/src/react/hooks/__tests__/createBillingPaginatedHook.spec.tsx
  • packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx
  • packages/shared/src/react/hooks/__tests__/usePlans.spec.tsx
**/*.{ts,tsx}

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

Use proper TypeScript error types

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/shared/src/react/hooks/__tests__/mocks/clerk.ts
  • packages/shared/src/react/hooks/__tests__/usePagesOrInfinite.spec.ts
  • packages/shared/src/react/hooks/__tests__/createBillingPaginatedHook.spec.tsx
  • packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx
  • packages/shared/src/react/hooks/__tests__/usePlans.spec.tsx
**/*.{js,ts,tsx,jsx}

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

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/shared/src/react/hooks/__tests__/mocks/clerk.ts
  • packages/shared/src/react/hooks/__tests__/usePagesOrInfinite.spec.ts
  • packages/shared/src/react/hooks/__tests__/createBillingPaginatedHook.spec.tsx
  • packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx
  • packages/shared/src/react/hooks/__tests__/usePlans.spec.tsx
**/__tests__/**/*.{ts,tsx}

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

**/__tests__/**/*.{ts,tsx}: Create type-safe test builders/factories
Use branded types for test isolation
Implement proper mock types that match interfaces

Files:

  • packages/shared/src/react/hooks/__tests__/mocks/clerk.ts
  • packages/shared/src/react/hooks/__tests__/usePagesOrInfinite.spec.ts
  • packages/shared/src/react/hooks/__tests__/createBillingPaginatedHook.spec.tsx
  • packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx
  • packages/shared/src/react/hooks/__tests__/usePlans.spec.tsx
packages/**/*.{test,spec}.{js,jsx,ts,tsx}

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

Unit tests should use Jest or Vitest as the test runner.

Files:

  • packages/shared/src/react/hooks/__tests__/usePagesOrInfinite.spec.ts
  • packages/shared/src/react/hooks/__tests__/createBillingPaginatedHook.spec.tsx
  • packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx
  • packages/shared/src/react/hooks/__tests__/usePlans.spec.tsx
**/*.{jsx,tsx}

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

**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components

**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components: UserProfile, NavigationMenu
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...

Files:

  • packages/shared/src/react/hooks/__tests__/createBillingPaginatedHook.spec.tsx
  • packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx
  • packages/shared/src/react/hooks/__tests__/usePlans.spec.tsx
**/*.tsx

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

**/*.tsx: Use proper type definitions for props and state
Leverage TypeScript's type inference where possible
Use proper event types for handlers
Implement proper generic types for reusable components
Use proper type guards for conditional rendering

Files:

  • packages/shared/src/react/hooks/__tests__/createBillingPaginatedHook.spec.tsx
  • packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx
  • packages/shared/src/react/hooks/__tests__/usePlans.spec.tsx
.github/workflows/*.yml

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

CI/CD must be configured with GitHub Actions.

Files:

  • .github/workflows/ci.yml
🧬 Code graph analysis (4)
packages/shared/src/react/hooks/__tests__/usePagesOrInfinite.spec.ts (2)
packages/shared/src/react/hooks/__tests__/mocks/clerk.ts (2)
  • createMockQueryClient (7-22)
  • createMockClerk (27-55)
packages/shared/src/utils/createDeferredPromise.ts (1)
  • createDeferredPromise (11-19)
packages/shared/src/react/hooks/__tests__/createBillingPaginatedHook.spec.tsx (1)
packages/shared/src/react/hooks/__tests__/mocks/clerk.ts (4)
  • createMockUser (57-59)
  • createMockOrganization (61-63)
  • createMockQueryClient (7-22)
  • createMockClerk (27-55)
packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx (1)
packages/shared/src/react/hooks/__tests__/mocks/clerk.ts (4)
  • createMockUser (57-59)
  • createMockOrganization (61-63)
  • createMockQueryClient (7-22)
  • createMockClerk (27-55)
packages/shared/src/react/hooks/__tests__/usePlans.spec.tsx (2)
packages/shared/src/react/hooks/__tests__/mocks/clerk.ts (4)
  • createMockUser (57-59)
  • createMockOrganization (61-63)
  • createMockQueryClient (7-22)
  • createMockClerk (27-55)
packages/shared/src/react/hooks/usePlans.tsx (1)
  • usePlans (8-21)
⏰ 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). (5)
  • GitHub Check: Build Packages
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (16)
packages/shared/src/react/hooks/__tests__/usePlans.spec.tsx (3)

5-8: LGTM! Mock factory imports are clean.

The migration to centralized mock factories improves test maintainability.


21-28: LGTM! Shared query client setup enables test isolation.

The defaultQueryClient is properly wired to mockClerk and will be cleared between tests (line 49), ensuring clean state.


183-204: LGTM! Test correctly verifies data persistence for unauthenticated hooks.

The test properly captures initial data, simulates sign-out by nulling mockUser.id, and asserts that data persists. This aligns with the expected behavior for hooks with unauthenticated: true option.

packages/shared/src/react/hooks/__tests__/createBillingPaginatedHook.spec.tsx (2)

50-55: Good addition of default mock implementation.

Setting a default empty response in beforeEach prevents undefined behavior when tests don't explicitly mock the fetcher.


277-286: Conditional test logic adds complexity.

The if (__CLERK_USE_RQ__) branching creates dual execution paths, making tests harder to maintain and reason about. Consider:

  1. Splitting into separate test files for RQ and SWR implementations
  2. Using parameterized tests with it.each
  3. Extracting conditional expectations into helper functions

Based on learnings

packages/shared/src/react/hooks/__tests__/mocks/clerk.ts (1)

7-22: LGTM! Query client configuration is appropriate for tests.

The configuration disables retry, sets infinite staleTime, and prevents automatic refetches—all good defaults for deterministic testing.

packages/shared/src/react/hooks/__tests__/usePagesOrInfinite.spec.ts (3)

9-28: LGTM! Consistent mock setup with other test files.

The global mock setup with defaultQueryClient and beforeEach cleanup ensures test isolation.


317-351: LGTM! Test correctly verifies non-keepPreviousData behavior.

The test properly asserts that data becomes empty (line 345) during page transitions when keepPreviousData: false, contrasting with the existing test at lines 281-315 where data is retained.


823-878: LGTM! Excellent documentation of isLoading vs isFetching semantics.

This test clearly demonstrates the difference between isLoading (true only on first fetch) and isFetching (true on any fetch). The inline comments make this critical distinction explicit for future test authors.

packages/shared/src/react/hooks/__tests__/useSubscription.spec.tsx (1)

19-34: LGTM! Consistent mock setup.

The defaultQueryClient is properly created and wired to mockClerk, and will be cleared in beforeEach (line 55).

.github/workflows/ci.yml (6)

213-230: Matrix expansion for CLERK_USE_RQ testing is well-structured.

The unit-test matrix selectively introduces RQ variants for @clerk/shared and @clerk/clerk-js while running the full suite without the flag. The run-name field improves visibility in logs. The strategy of testing both modes for core packages while leaving other packages in the baseline run is reasonable.


273-273: CLERK_USE_RQ propagated consistently across test environments.

Env var is set in both unit-tests and integration-tests steps. For matrix entries without clerk-use-rq defined, the interpolation yields an empty string; ensure downstream code and build scripts handle this gracefully as default (non-RQ) behavior.

Does the codebase check CLERK_USE_RQ with a conditional like if CLERK_USE_RQ == 'true' (which would safely ignore empty/undefined) or does it depend on the variable being set?

Also applies to: 481-481


278-278: Typedoc gating refined to main test run only.

The condition now checks both node-version == 22 and test-filter == "**", ensuring Typedoc tests run only on the full suite run and not on per-package matrix variants. This aligns with the comment and reduces redundant checks.


330-346: Integration test matrix strategically includes CLERK_USE_RQ variants.

The matrix adds RQ testing for billing and nextjs (Next.js 15 + 16), leaving other test suites (generic, express, astro, etc.) and Next.js 14 without RQ variants. This focused approach keeps CI time reasonable while covering critical paths. Each variant (false/true) is explicitly defined.


421-421: Verdaccio publish command propagates CLERK_USE_RQ.

The command includes CLERK_USE_RQ=${{ matrix.clerk-use-rq }} inline. For matrix entries without clerk-use-rq defined, this interpolates to an empty string, which should resolve to default (non-RQ) behavior. Verify that the pnpm/turbo build invocation handles empty or unset CLERK_USE_RQ safely.

For matrix entries that don't define clerk-use-rq, confirm that CLERK_USE_RQ= (empty) is the intended default and that build/publish scripts don't fail or produce unexpected behavior when the env var is empty.


250-260: All claims verified—code is correctly implemented.

The filter syntax --filter=@clerk/shared^... selects all dependencies of @clerk/shared but excludes @clerk/shared itself, which is the correct turbo pattern for this two-step rebuild approach. The conditions are properly applied (with additional steps.task-status.outputs.affected == '1' check in the integration test section), and positioning before test execution is correct.

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

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • 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 b876a94 and d10f7d3.

📒 Files selected for processing (1)
  • packages/shared/src/react/clerk-rq/useBaseQuery.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{js,jsx,ts,tsx}

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

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/shared/src/react/clerk-rq/useBaseQuery.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

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

Use Prettier for consistent code formatting

Files:

  • packages/shared/src/react/clerk-rq/useBaseQuery.ts
packages/**/*.{ts,tsx}

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

TypeScript is required for all packages

Files:

  • packages/shared/src/react/clerk-rq/useBaseQuery.ts
packages/**/*.{ts,tsx,d.ts}

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

Packages should export TypeScript types alongside runtime code

Files:

  • packages/shared/src/react/clerk-rq/useBaseQuery.ts
**/*.{ts,tsx}

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

Use proper TypeScript error types

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/shared/src/react/clerk-rq/useBaseQuery.ts
**/*.{js,ts,tsx,jsx}

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

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/shared/src/react/clerk-rq/useBaseQuery.ts
⏰ 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). (5)
  • GitHub Check: Build Packages
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan

@blacksmith-sh

This comment has been minimized.

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: 0

🧹 Nitpick comments (2)
.github/workflows/ci.yml (2)

210-225: Full test suite never runs with CLERK_USE_RQ=true.

The unit-tests matrix runs individual packages (@clerk/shared, @clerk/clerk-js) with both clerk-use-rq: "false" and "true", but the full suite (line 210-212) only runs with clerk-use-rq: "false". This means end-to-end cross-package compatibility is never validated when CLERK_USE_RQ is active.

Consider adding a full-suite variant with clerk-use-rq: "true" to ensure RQ support doesn't break inter-package integration, or document if this is intentional (e.g., to avoid CI bloat).


304-341: Integration tests matrix relies on implicit undefined for clerk-use-rq in base matrix items.

The base matrix items (lines 304–322) do not define clerk-use-rq, leaving it undefined for most test combinations. While conditionals like matrix.clerk-use-rq == 'true' will correctly evaluate to false when undefined, this is implicit and fragile.

Consider explicitly setting a default value like clerk-use-rq: 'false' in the base matrix or using a more explicit fallback pattern to improve clarity and maintainability.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • 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 d10f7d3 and 8475329.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml (8 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
.github/workflows/*.yml

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

CI/CD must be configured with GitHub Actions.

Files:

  • .github/workflows/ci.yml
⏰ 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). (27)
  • GitHub Check: Integration Tests (CLERK_USE_RQ=true)
  • GitHub Check: Integration Tests
  • GitHub Check: Integration Tests
  • GitHub Check: Integration Tests
  • GitHub Check: Integration Tests
  • GitHub Check: Integration Tests (CLERK_USE_RQ=true)
  • GitHub Check: Integration Tests
  • GitHub Check: Integration Tests
  • GitHub Check: Integration Tests
  • GitHub Check: Integration Tests
  • GitHub Check: Integration Tests
  • GitHub Check: Integration Tests
  • GitHub Check: Integration Tests
  • GitHub Check: Integration Tests
  • GitHub Check: Integration Tests
  • GitHub Check: Integration Tests
  • GitHub Check: Unit Tests
  • GitHub Check: Unit Tests (CLERK_USE_RQ=true)
  • GitHub Check: Unit Tests (CLERK_USE_RQ=true)
  • GitHub Check: Static analysis
  • GitHub Check: Unit Tests
  • GitHub Check: Unit Tests
  • GitHub Check: Publish with pkg-pr-new
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (4)
.github/workflows/ci.yml (4)

245-256: Rebuild strategy for CLERK_USE_RQ environment variable is sound.

The conditional rebuilds with --force when clerk-use-rq: "true" ensure that environment-dependent builds don't rely on cached artifacts from clerk-use-rq: "false" runs. This is the correct approach for environment-gated code paths.


257-287: Unit test environment variable and artifact naming are correctly configured.

The CLERK_USE_RQ environment variable is properly propagated to test runs, and artifacts are appropriately named with -rq suffix when applicable. The Typedoc gating (line 273) correctly restricts tests to the full suite run only, preventing duplicate runs across filtered matrix variants.


465-487: Integration test environment variable and artifact naming are correctly configured.

The CLERK_USE_RQ environment variable is properly passed to integration test runs, and artifact naming correctly combines next-version and clerk-use-rq indicators. The conditional formatting handles undefined matrix variables appropriately.


411-417: Verdaccio publish correctly propagates CLERK_USE_RQ to build step.

The inline environment variable assignment ensures that packages are built with the appropriate RQ flag before publishing to Verdaccio. This maintains consistency between test and publish paths.

@blacksmith-sh

This comment has been minimized.

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

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • 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 92b24d6 and 7be0dc3.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml (8 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
.github/workflows/*.yml

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

CI/CD must be configured with GitHub Actions.

Files:

  • .github/workflows/ci.yml
⏰ 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). (4)
  • GitHub Check: check-major-bump
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (5)
.github/workflows/ci.yml (5)

318-343: Document asymmetry in RQ coverage across integration-test variants.

The matrix configures RQ testing inconsistently:

  • billing: both 'false' and 'true'
  • nextjs: version 15 gets both variants; versions 14 and 16 get neither
  • quickstart: neither variant (no explicit clerk-use-rq)

This selective RQ coverage may be intentional (e.g., focusing on nextjs 15 for gradual rollout), but it's undocumented in the workflow or PR description. If RQ is a significant variant, ensure consistent coverage or document the rationale for skipping certain combinations.


238-248: Rebuild steps correctly target packages with RQ flag.

The conditional rebuilds of @clerk/shared and its dependents are properly gated on matrix.clerk-use-rq == 'true' and use --force to bypass cache. The CLERK_USE_RQ=true environment variable is correctly passed during the build phase. This ensures that RQ-variant builds are distinct and not cached with non-RQ builds.

Also applies to: 392-402


263-268: Typedoc tests correctly limited to main test run.

The condition restricts Typedoc tests to Node 22 and the full test-filter ("**"), which ensures they run only once per workflow on the non-RQ variant. This prevents unnecessary test duplication across matrix rows.


409-409: Verify environment variable expansion in Verdaccio publish command.

The publish command passes CLERK_USE_RQ=${{ matrix.clerk-use-rq }}. For matrix entries where clerk-use-rq is undefined, this expands to an empty string (not the boolean false). Verify that the Verdaccio action or downstream build correctly interprets an empty CLERK_USE_RQ variable as "disabled" (or explicitly default undefined values to 'false' in the matrix, as noted above).


194-194: Matrix context correctly propagated to job names and artifacts.

Job names and artifact naming now include RQ context (e.g., "Unit Tests (22, shared, clerk-js, RQ)" and suffix "-rq" on turbo summaries and playwright traces). This improves observability and traceability when debugging RQ-specific failures.

Also applies to: 284-284, 277-277, 478-478

@panteliselef panteliselef changed the title [WIP] chore(share): Add RQ variant of usePageOrInfinite chore(share): Add RQ variant of usePageOrInfinite Nov 10, 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: 0

♻️ Duplicate comments (1)
packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx (1)

141-158: CRITICAL: fetchPage only fetches one page at a time, breaking multi-page jumps.

The current implementation computes toFetch (lines 149) but only calls fetchNextPage once (line 151). This is a regression from the SWR version, which used setSize(targetCount) to jump directly to the requested page count.

Impact: Calling fetchPage(5) when at page 1 will only fetch one additional page (reaching page 2), not four. This breaks the existing API contract and any consumers expecting arbitrary page jumps.

Fix by looping until the target is reached:

       const fetchPage: ValueOrSetter<number> = useCallback(
         numberOrgFn => {
           if (triggerInfinite) {
             const next = typeof numberOrgFn === 'function' ? (numberOrgFn as (n: number) => number)(page) : numberOrgFn;
             const targetCount = Math.max(0, next);
             const cachedData = queryClient.getQueryData<{ pages?: Array<ClerkPaginatedResponse<any>> }>(infiniteQueryKey);
             const pages = infiniteQuery.data?.pages ?? cachedData?.pages ?? [];
             const currentCount = pages.length;
             const toFetch = targetCount - currentCount;
-            if (toFetch > 0) {
-              void infiniteQuery.fetchNextPage({ cancelRefetch: false });
+            
+            // Handle shrinking (backward navigation)
+            if (toFetch < 0) {
+              queryClient.setQueryData(infiniteQueryKey, (prev: any) => ({
+                ...prev,
+                pages: (prev?.pages ?? []).slice(0, targetCount),
+              }));
+              forceUpdate(n => n + 1);
+              return;
+            }
+            
+            // Handle growing (forward navigation) - loop until target reached
+            if (toFetch > 0) {
+              const fetchUntilTarget = async () => {
+                let remaining = toFetch;
+                while (remaining > 0) {
+                  await infiniteQuery.fetchNextPage({ cancelRefetch: false });
+                  // Re-read pages to check progress
+                  const updated = queryClient.getQueryData<{ pages?: Array<ClerkPaginatedResponse<any>> }>(infiniteQueryKey);
+                  const updatedPages = updated?.pages ?? [];
+                  remaining = targetCount - updatedPages.length;
+                  // Safety: break if no progress
+                  if (remaining === toFetch) break;
+                }
+              };
+              void fetchUntilTarget();
             }
             return;
           }
           return setPaginatedPage(numberOrgFn);
         },
         [infiniteQuery, page, triggerInfinite, queryClient, infiniteQueryKey, forceUpdate],
       );

Based on learnings

🧹 Nitpick comments (2)
packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx (2)

84-88: Use initialPageParam consistently in getNextPageParam calculation.

Line 84 defaults initialPageParam to 1, but line 87's consumed calculation re-checks params.initialPage with a ternary. This is inconsistent and fragile (relies on undefined being falsy to produce offset 0).

Apply this diff to use the defaulted value:

     initialPageParam: params.initialPage ?? 1,
     getNextPageParam: (lastPage, allPages, lastPageParam) => {
       const total = lastPage?.total_count ?? 0;
-      const consumed = (allPages.length + (params.initialPage ? params.initialPage - 1 : 0)) * (params.pageSize ?? 10);
+      const initialPageParam = params.initialPage ?? 1;
+      const consumed = (allPages.length + (initialPageParam - 1)) * (params.pageSize ?? 10);
       return consumed < total ? (lastPageParam as number) + 1 : undefined;
     },

Based on learnings


223-229: Add console warning for unsupported backward navigation in infinite mode.

fetchPrevious silently no-ops in infinite mode (lines 224-226), which could confuse developers who expect it to work. Consider adding a warning to provide clear feedback.

Apply this diff:

   const fetchPrevious = useCallback(() => {
     if (triggerInfinite) {
-      // not natively supported by forward-only pagination; noop
+      if (process.env.NODE_ENV !== 'production') {
+        console.warn('fetchPrevious is not supported in infinite query mode. Use paginated mode for backward navigation.');
+      }
       return;
     }
     setPaginatedPage(n => Math.max(0, n - 1));
   }, [triggerInfinite]);

Based on learnings

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • 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 35f4e83 and 031083c.

📒 Files selected for processing (3)
  • .changeset/fuzzy-keys-smell.md (1 hunks)
  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx (1 hunks)
  • packages/shared/src/react/hooks/useSubscription.rq.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .changeset/fuzzy-keys-smell.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/shared/src/react/hooks/useSubscription.rq.tsx
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{js,jsx,ts,tsx}

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

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

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

Use Prettier for consistent code formatting

Files:

  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
packages/**/*.{ts,tsx}

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

TypeScript is required for all packages

Files:

  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
packages/**/*.{ts,tsx,d.ts}

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

Packages should export TypeScript types alongside runtime code

Files:

  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
**/*.{ts,tsx}

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

Use proper TypeScript error types

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
**/*.{jsx,tsx}

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

**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components

**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components: UserProfile, NavigationMenu
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...

Files:

  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
**/*.{js,ts,tsx,jsx}

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

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
**/*.tsx

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

**/*.tsx: Use proper type definitions for props and state
Leverage TypeScript's type inference where possible
Use proper event types for handlers
Implement proper generic types for reusable components
Use proper type guards for conditional rendering

Files:

  • packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx
🧬 Code graph analysis (1)
packages/shared/src/react/hooks/usePagesOrInfinite.rq.tsx (7)
packages/shared/src/react/hooks/usePagesOrInfinite.swr.tsx (1)
  • usePagesOrInfinite (37-233)
packages/shared/src/react/hooks/usePageOrInfinite.types.ts (1)
  • UsePagesOrInfiniteSignature (7-26)
packages/shared/src/react/clerk-rq/useQuery.ts (1)
  • useClerkQuery (40-42)
packages/shared/src/react/hooks/usePagesOrInfinite.shared.ts (1)
  • getDifferentKeys (75-89)
packages/shared/src/react/clerk-rq/useInfiniteQuery.ts (1)
  • useClerkInfiniteQuery (42-44)
packages/shared/src/react/hooks/usePreviousValue.ts (1)
  • usePreviousValue (20-30)
packages/shared/src/react/types.ts (2)
  • ValueOrSetter (4-4)
  • CacheSetter (6-8)
⏰ 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). (5)
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Build Packages
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan

@panteliselef panteliselef changed the title chore(share): Add RQ variant of usePageOrInfinite chore(shared): Add RQ variant of usePageOrInfinite Nov 10, 2025
@blacksmith-sh
Copy link

blacksmith-sh bot commented Nov 10, 2025

Found 20 test failures on Blacksmith runners:

Test View Logs
[chrome] › integration/tests/
session-tasks-eject-flow.test.ts:88:7 › session tasks eject flow @nextjs › redirects to
completion page after resolving task
View Logs
[chrome] › integration/tests/
session-tasks-eject-flow.test.ts:88:7 › session tasks eject flow @nextjs › redirects to
completion page after resolving task
View Logs
[chrome] › integration/tests/
session-tasks-eject-flow.test.ts:88:7 › session tasks eject flow @nextjs › redirects to
completion page after resolving task
View Logs
[chrome] › integration/tests/
session-tasks-eject-flow.test.ts:88:7 › session tasks eject flow @nextjs › redirects to
completion page after resolving task
View Logs
[chrome] › integration/tests/
session-tasks-multi-session.test.ts:33:9 › session tasks multi-session flow @nextjs › l
ong-running--next.appRouter.withSessionTasks › when switching sessions, navigate to tas
k
View Logs
[chrome] › integration/tests/
session-tasks-multi-session.test.ts:33:9 › session tasks multi-session flow @nextjs › l
ong-running--next.appRouter.withSessionTasks › when switching sessions, navigate to tas
k
View Logs
[chrome] › integration/tests/
session-tasks-multi-session.test.ts:33:9 › session tasks multi-session flow @nextjs › l
ong-running--next.appRouter.withSessionTasks › when switching sessions, navigate to tas
k
View Logs
[chrome] › integration/tests/
session-tasks-multi-session.test.ts:33:9 › session tasks multi-session flow @nextjs › l
ong-running--next.appRouter.withSessionTasks › when switching sessions, navigate to tas
k
View Logs
[chrome] › integration/tests/
session-tasks-sign-in.test.ts:36:9 › session tasks after sign-in flow @nextjs › long-ru
nning--next.appRouter.withSessionTasks › with email and password, navigate to task on a
fter sign-in
View Logs
[chrome] › integration/tests/
session-tasks-sign-in.test.ts:36:9 › session tasks after sign-in flow @nextjs › long-ru
nning--next.appRouter.withSessionTasks › with email and password, navigate to task on a
fter sign-in
View Logs
[chrome] › integration/tests/
session-tasks-sign-in.test.ts:36:9 › session tasks after sign-in flow @nextjs › long-ru
nning--next.appRouter.withSessionTasks › with email and password, navigate to task on a
fter sign-in
View Logs
[chrome] › integration/tests/
session-tasks-sign-in.test.ts:36:9 › session tasks after sign-in flow @nextjs › long-ru
nning--next.appRouter.withSessionTasks › with email and password, navigate to task on a
fter sign-in
View Logs
[chrome] › integration/tests/
session-tasks-sign-up.test.ts:54:9 › session tasks after sign-up flow @nextjs › long-ru
nning--next.appRouter.withSessionTasks › navigate to task on after sign-up
View Logs
[chrome] › integration/tests/
session-tasks-sign-up.test.ts:54:9 › session tasks after sign-up flow @nextjs › long-ru
nning--next.appRouter.withSessionTasks › navigate to task on after sign-up
View Logs
[chrome] › integration/tests/
session-tasks-sign-up.test.ts:54:9 › session tasks after sign-up flow @nextjs › long-ru
nning--next.appRouter.withSessionTasks › navigate to task on after sign-up
View Logs
[chrome] › integration/tests/
session-tasks-sign-up.test.ts:54:9 › session tasks after sign-up flow @nextjs › long-ru
nning--next.appRouter.withSessionTasks › navigate to task on after sign-up
View Logs
[chrome] › integration/tests/session-token-cache/
multi-session.test.ts:54:9 › MemoryTokenCache Multi-Session Integration @nextjs › long-
running--next.appRouter.withSessionTasks › MemoryTokenCache multi-session - multiple us
ers in different tabs with separate token caches
View Logs
[chrome] › integration/tests/session-token-cache/
multi-session.test.ts:54:9 › MemoryTokenCache Multi-Session Integration @nextjs › long-
running--next.appRouter.withSessionTasks › MemoryTokenCache multi-session - multiple us
ers in different tabs with separate token caches
View Logs
[chrome] › integration/tests/session-token-cache/
multi-session.test.ts:54:9 › MemoryTokenCache Multi-Session Integration @nextjs › long-
running--next.appRouter.withSessionTasks › MemoryTokenCache multi-session - multiple us
ers in different tabs with separate token caches
View Logs
[chrome] › integration/tests/session-token-cache/
multi-session.test.ts:54:9 › MemoryTokenCache Multi-Session Integration @nextjs › long-
running--next.appRouter.withSessionTasks › MemoryTokenCache multi-session - multiple us
ers in different tabs with separate token caches
View Logs


Fix in Cursor

@panteliselef panteliselef changed the title chore(shared): Add RQ variant of usePageOrInfinite chore(shared): Add React Query variant of usePageOrInfinite Nov 11, 2025
@panteliselef panteliselef merged commit 4011c5e into main Nov 11, 2025
166 of 179 checks passed
@panteliselef panteliselef deleted the elef/replace-swr-with-rq-infinite branch November 11, 2025 10:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants