-
Notifications
You must be signed in to change notification settings - Fork 3
Upgrade nextjs #253
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Upgrade nextjs #253
Conversation
- Remove unnecessary console.log statements from production code - Reorder and organize package.json dependencies - Add missing dev dependency @rollup/rollup-darwin-arm64
- Upgrade React, Next.js, and related dependencies to React 19 RC versions - Update type definitions and component implementations for React 19 compatibility - Remove deprecated experimental instrumentation hook from Next config - Fix ref initialization and type issues in several components - Update params handling in server components to support async params
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Warning Rate limit exceeded@kasumi-1 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 8 minutes and 23 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (1)
WalkthroughMigrates the website from Apollo Client to URQL across providers, hooks, and pages; adjusts Next.js route params to async Promises; adds URQL client/server utilities; introduces extensive Vitest-based tests and setup for website and subsquid; updates CI (coverage, Lighthouse) and Dependabot; modifies icons/UI styling; revises contract tests and coverage config. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant NextServer as Next.js Server Page
participant URQLSrv as createServerUrqlClient
participant Subsquid as Subsquid GraphQL API
User->>NextServer: Request /users/[address]
NextServer->>NextServer: await params (Promise<{address}>)
NextServer->>URQLSrv: create client
NextServer->>Subsquid: query GET_USER_BY_ADDRESS
Subsquid-->>NextServer: { data }
NextServer-->>User: HTML (SSR) with data
sequenceDiagram
autonumber
actor Component
participant URQL as urql useQuery
participant Subsquid as Subsquid GraphQL API
participant JobsHook as useJobsByIds
Component->>URQL: useQuery(GET_USER_NOTIFICATIONS, vars)
URQL->>Subsquid: GraphQL request
Subsquid-->>URQL: { notifications }
URQL-->>Component: result { data, fetching, error }
Component->>JobsHook: derive jobIds, useJobsByIds(jobIds)
JobsHook->>Subsquid: GET_JOBS_BY_IDS
Subsquid-->>JobsHook: { jobs }
JobsHook-->>Component: { data, loading, error }
Component-->>Component: Map notifications + jobs
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60–90 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this 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: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
website/package-lock.json
is excluded by!**/package-lock.json
website/yarn.lock
is excluded by!**/yarn.lock
,!**/*.lock
📒 Files selected for processing (11)
website/next.config.mjs
(0 hunks)website/package.json
(1 hunks)website/src/app/arbitrators/[address]/page.tsx
(2 hunks)website/src/app/jobs/[id]/JobActions/PostMessageButton.tsx
(1 hunks)website/src/app/jobs/[id]/JobActions/UpdateButton.tsx
(1 hunks)website/src/app/jobs/[id]/JobChat/JobChatStatus.tsx
(0 hunks)website/src/app/jobs/[id]/page.tsx
(2 hunks)website/src/app/post-job/PostJobPage.tsx
(1 hunks)website/src/app/users/[address]/page.tsx
(2 hunks)website/src/components/AddToHomescreen.tsx
(0 hunks)website/src/hooks/useWriteContractWithNotifications.ts
(1 hunks)
💤 Files with no reviewable changes (3)
- website/src/app/jobs/[id]/JobChat/JobChatStatus.tsx
- website/next.config.mjs
- website/src/components/AddToHomescreen.tsx
🧰 Additional context used
🧬 Code graph analysis (3)
website/src/app/users/[address]/page.tsx (1)
website/src/app/users/[address]/UserPageClient.tsx (1)
UserPageClient
(56-389)
website/src/app/jobs/[id]/page.tsx (1)
website/src/app/jobs/[id]/JobPageClient.tsx (1)
JobPageClient
(83-579)
website/src/app/arbitrators/[address]/page.tsx (1)
website/src/app/arbitrators/[address]/ArbitratorPageClient.tsx (1)
ArbitratorPageClient
(67-467)
🔇 Additional comments (5)
website/src/app/post-job/PostJobPage.tsx (1)
384-384
: LGTM! Type annotation correctly reflects React ref semantics.The widened type
React.RefObject<HTMLDivElement | null>
properly aligns with React's ref behavior wherecurrent
can benull
before mounting. This matches the null check at line 459 and improves type safety.website/src/app/jobs/[id]/JobActions/UpdateButton.tsx (1)
289-289
: LGTM! Type annotation correctly reflects React ref semantics.The widened type
React.RefObject<HTMLDivElement | null>
properly aligns with React's ref behavior wherecurrent
can benull
before mounting. This matches the null check at line 361 and improves type safety.website/src/hooks/useWriteContractWithNotifications.ts (1)
102-106
: LGTM! Explicit ref initialization improves clarity.The explicit
undefined
initialization for these refs is clearer and more intentional than relying on implicit defaults. All three refs are safely used throughout the code with optional chaining (lines 237, 247) or null checks (line 125).website/src/app/jobs/[id]/page.tsx (2)
101-107
: LGTM! Correctly updated for Next.js 15.The
generateMetadata
function properly awaits theparams
Promise before destructuring theid
. This aligns with Next.js 15's change to async route parameters.
201-208
: LGTM! Server component correctly migrated to async params.The
JobPage
component properly awaits theparams
Promise and passes the unwrappedid
string toJobPageClient
, which expects a string parameter as confirmed by the relevant code snippets.
- Add GitHub Actions workflow for website testing with coverage reporting - Add pull request template with comprehensive checklist - Add Jest configuration and setup for frontend testing - Add extensive test coverage for components, hooks, and API routes - Add mock implementations for wagmi, Apollo, and contract dependencies - Update README with testing instructions and coverage badge - Add test utilities and mock data for consistent test execution
- Add GitHub Actions workflow for running contract tests with coverage - Update EACCToken tests to use correct import paths and remove unused imports - Remove obsolete EACCBar and MarketplaceV2 test files - Fix publishMediaToIpfs function calls in utils tests - Remove IPFS upload secret check from utils tests
Moved all test files to __tests__ directory and updated import paths accordingly. This change restructures the testing organization to be more consistent and maintainable.
- Configure Vitest for unit and integration testing with coverage support - Add mock event data fixtures for job-related events and entities - Create unit tests for data models, event types, and job event processing - Add skipped integration tests for database operations with setup instructions - Update package.json with test scripts and dev dependencies
This commit replaces Apollo Client with URQL across the application for several key reasons: - Better integration with Next.js server components - Automatic cache invalidation without manual resets - Improved performance for server-side rendering - Reduced bundle size by removing Apollo dependencies The migration includes: - Removed @apollo/client and related dependencies - Added urql, wonka, and graphql-tag as dependencies - Updated all GraphQL hooks and components to use URQL - Rewrote server-side data fetching with createServerUrqlClient - Updated testing utilities to mock URQL instead of Apollo - Enhanced cache configuration with ssrExchange for better SSR support Key benefits: - Eliminates manual cache reset logic previously required with Apollo - Server components now fetch data more efficiently - Simplified testing setup with URQL's more straightforward mocking - Better TypeScript support with automatic BigInt handling
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 46
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
website/src/hooks/useSwResetMessage.tsx (1)
3-30
: Verify URQL cache invalidation behavior
The client uses the defaultcacheExchange
without external invalidation—ensureresets
actually triggers query refetch (e.g., pass it as a variable/key) or invokeurqlClient.reexecuteQuery()
inuseSwResetMessage
.website/src/hooks/subsquid/useJobSearch.tsx (1)
88-101
: Invalid GraphQL filter whenuserAddress
is provided.
allowedWorkers_containsAny
expects a list input, but we’re injecting a bare string literal. As soon asuserAddress
is defined the generated query is invalid (allowedWorkers_containsAny: "0x..."
), so Subsquid rejects the request and the hook never resolves. Wrap the address in an array (e.g.["${userAddress}"]
) before interpolating the filter.
🧹 Nitpick comments (23)
subsquid/vitest.config.ts (1)
8-8
: Consider including.spec.ts
files in the test pattern.The current pattern only matches
*.test.ts
files. For flexibility and consistency with common testing conventions, consider also matching*.spec.ts
files.Apply this diff to broaden the test file matching:
- include: ['tests/**/*.test.ts'], + include: ['tests/**/*.{test,spec}.ts'],subsquid/tests/integration/database.test.ts (1)
17-23
: Consider a more idiomatic placeholder test.The current placeholder test with
expect(true).toBe(true)
is functional but redundant. Consider one of these alternatives:
- Remove the assertion entirely (the test will pass by default)
- Use a more descriptive assertion that documents the intent
Apply this diff for option 1 (simplest):
it('should have database integration tests when enabled', () => { // Placeholder test for when integration tests are enabled // See the comment block above for instructions on enabling these tests - expect(true).toBe(true); });
Or for option 2 (more descriptive):
it('should have database integration tests when enabled', () => { - // Placeholder test for when integration tests are enabled - // See the comment block above for instructions on enabling these tests - expect(true).toBe(true); + // This is a placeholder. Remove .skip from describe.skip above and + // uncomment the scaffold code below to enable real integration tests });subsquid/tests/unit/data-models.test.ts (2)
4-12
: Clear explanation for skipped tests.The comment appropriately explains why these tests are skipped and provides actionable alternatives (integration tests or factory functions). This is good documentation for future maintainers.
Consider adding a brief note about what specific setup is missing, to make it even more actionable:
* Note: These tests are currently skipped because the TypeORM models * require reflect-metadata and specific TypeORM setup to instantiate. + * Specifically: import 'reflect-metadata' and a configured DataSource. * To test the models properly, you should:
16-39
: Test structure is sound, assuming constructor signature matches.The test correctly uses
getAddress
for checksummed addresses and covers key User properties. Assertions are appropriate for a basic model test.The
address_
property name (with trailing underscore) is unusual. Verify whether this matches the actual User entity schema. If the entity usesaddress
(without underscore), update the test accordingly.website/__tests__/lib/tokens.test.ts (1)
9-38
: Consider parameterizing token-specific tests.While the individual token tests (USDC, USDT, WETH, AIUS, EACC) are correct, they contain hardcoded expectations that could become brittle if token details change. Consider using a data-driven approach:
const expectedTokens = [ { symbol: 'USDC', name: 'USD Coin', decimals: 6 }, { symbol: 'USDT', name: 'USDT', decimals: 6 }, { symbol: 'WETH', name: 'Wrapped Ether', decimals: 18 }, // ... etc ]; it.each(expectedTokens)('should have $symbol token with correct properties', ({ symbol, name, decimals }) => { const token = tokens.find((t) => t.symbol === symbol); expect(token).toBeDefined(); expect(token?.name).toBe(name); if (decimals !== undefined) { expect(token?.decimals).toBe(decimals); } });This would make the tests more maintainable and easier to update when tokens change.
website/__tests__/lib/utils.test.ts (1)
150-182
: LGTM!The
isImageValid
test suite correctly validates success, failure, and error scenarios with appropriate console.error mocking.Optionally, verify the Sentry.captureException call in the error scenario:
it('should return false on fetch error', async () => { (global.fetch as jest.Mock).mockRejectedValue(new Error('Network error')); const consoleSpy = jest.spyOn(console, 'error').mockImplementation(); + const sentrySpy = jest.spyOn(Sentry, 'captureException').mockImplementation(); const result = await isImageValid('https://example.com/error.jpg'); expect(result).toBe(false); + expect(sentrySpy).toHaveBeenCalledWith(expect.any(Error)); consoleSpy.mockRestore(); + sentrySpy.mockRestore(); });website/src/app/open-job-list/page.tsx (1)
8-9
: LGTM! Dynamic rendering enforced for URQL compatibility.The
dynamic = 'force-dynamic'
export correctly forces request-time rendering to avoid URQL prerendering issues. The comment clearly explains the rationale.Consider investigating URQL's SSR configuration to enable static prerendering in the future. URQL supports SSR with proper setup (e.g., using
ssrExchange
and server-side data prefetching). This could improve performance by allowing static generation where appropriate.subsquid/tests/unit/job-event-processing.test.ts (4)
24-33
: Strengthen enum value assertions.The tests only verify that enum properties exist but don't validate their actual values. Consider asserting the specific numeric values to catch accidental changes to the enum definitions.
Apply this diff to add value assertions:
describe('JobEventType', () => { it('should have correct event type values', () => { - expect(JobEventType.Created).toBeDefined(); - expect(JobEventType.Taken).toBeDefined(); - expect(JobEventType.Paid).toBeDefined(); - expect(JobEventType.Updated).toBeDefined(); - expect(JobEventType.Signed).toBeDefined(); - expect(JobEventType.Completed).toBeDefined(); + expect(JobEventType.Created).toBe(0); + expect(JobEventType.Taken).toBe(1); + expect(JobEventType.Paid).toBe(2); + expect(JobEventType.Updated).toBe(3); + expect(JobEventType.Signed).toBe(4); + expect(JobEventType.Completed).toBe(5); }); });
35-41
: Strengthen state value assertions.Similar to the JobEventType tests, these only check existence. Assert the specific numeric values (0, 1, 2) to ensure the enum contract is preserved.
Apply this diff:
describe('JobState', () => { it('should have correct state values', () => { - expect(JobState.Open).toBeDefined(); - expect(JobState.Taken).toBeDefined(); - expect(JobState.Closed).toBeDefined(); + expect(JobState.Open).toBe(0); + expect(JobState.Taken).toBe(1); + expect(JobState.Closed).toBe(2); }); });
43-80
: Add functional decoder tests.The current tests only verify that decoder functions exist. The mock data from
../fixtures/mock-events
is imported but never used. Consider adding tests that actually encode mock data and then decode it to verify round-trip correctness.Example pattern for one decoder:
it('should correctly decode JobCreated event data', () => { // First encode the mock data (you'll need an encode function) const encoded = encodeJobCreatedEvent(mockJobCreatedEventData); // Then decode and verify const decoded = decodeJobCreatedEvent(encoded); expect(decoded.title).toBe(mockJobCreatedEventData.title); expect(decoded.contentHash).toBe(mockJobCreatedEventData.contentHash); expect(decoded.amount).toBe(mockJobCreatedEventData.amount); // ... verify all fields });
111-117
: Remove redundant state type test.Lines 112-116 duplicate what's already tested in the "JobState" describe block (lines 35-41). This test validates that state values are numbers, which is already implicitly covered.
Consider removing this redundant test block:
- describe('Job State Transitions', () => { - it('should validate job state values are numbers', () => { - expect(typeof JobState.Open).toBe('number'); - expect(typeof JobState.Taken).toBe('number'); - expect(typeof JobState.Closed).toBe('number'); - }); - });website/__tests__/hooks/useDimensions.test.tsx (2)
22-35
: Simplify ref mocking approach.Directly assigning a partial
HTMLDivElement
object toref.current
works but is brittle. Consider using a more realistic test setup or document this as a unit-level mock pattern.
49-64
: Add test for actual resize behavior.The current test only verifies that
addEventListener
is called with'resize'
but doesn't test that the hook actually updates dimensions when a resize event fires. Consider adding a test that triggers a resize event and verifies the dimensions update.Add a test like this:
it('should update dimensions on window resize', async () => { const { result, rerender } = renderHook(() => { const ref = useRef<HTMLDivElement>({ offsetWidth: 100, offsetHeight: 200, } as HTMLDivElement); return { ref, dimensions: useDimensions(ref) }; }); expect(result.current.dimensions).toEqual({ width: 100, height: 200 }); // Simulate element size change Object.assign(result.current.ref.current, { offsetWidth: 150, offsetHeight: 250, }); // Trigger resize event act(() => { window.dispatchEvent(new Event('resize')); }); await waitFor(() => { expect(result.current.dimensions).toEqual({ width: 150, height: 250 }); }); });website/__tests__/api/total_supply.test.ts (2)
34-42
: Strengthen cache validation test.Calling
GET()
twice in immediate succession doesn't effectively test the 24-hour cache behavior. The test only verifies that the mock returns consistent data, not that caching actually works.Consider using Jest's fake timers to advance time and verify cache expiration:
it('should cache the result for 24 hours', async () => { jest.useFakeTimers(); const response1 = await GET(); const data1 = await response1.json(); // Advance time by 23 hours - should still use cache jest.advanceTimersByTime(23 * 60 * 60 * 1000); const response2 = await GET(); const data2 = await response2.json(); expect(data2.totalSupply).toBe(data1.totalSupply); // Advance past 24 hours - should fetch fresh data jest.advanceTimersByTime(2 * 60 * 60 * 1000); const response3 = await GET(); const data3 = await response3.json(); // Verify fresh fetch (may need to change mock to return different value) jest.useRealTimers(); });
44-54
: Verify error handling behavior.The error handling test mocks a rejection but only verifies that a response exists. It should verify that the API returns an appropriate error response or cached data when the RPC call fails.
Enhance the test to verify the actual error handling:
it('should handle RPC errors', async () => { const { Contract } = require('ethers'); Contract.mockImplementationOnce(() => ({ totalSupply: jest.fn().mockRejectedValue(new Error('Network error')), })); const response = await GET(); + const data = await response.json(); - // Should still return a response (from cache or error handling) - expect(response).toBeDefined(); + // Should return error response or cached data + expect(response.status).toBeGreaterThanOrEqual(200); + expect(data).toHaveProperty('totalSupply'); + // OR verify error response structure if that's the expected behavior });website/__tests__/api/circulating_supply.test.ts (1)
56-67
: Strengthen error test to verify error handling behavior.The error test only checks that
response
is defined, but doesn't verify how the error was handled (e.g., returning cached data, specific status code, or error payload). The comment suggests "Should return cached data or fallback" but this isn't asserted.Consider enhancing the test to verify the actual error handling behavior:
it('should handle errors gracefully', async () => { // Mock contract error const { Contract } = require('ethers'); Contract.mockImplementationOnce(() => ({ totalSupply: jest.fn().mockRejectedValue(new Error('RPC Error')), })); const response = await GET(); + const data = await response.json(); - // Should return cached data or fallback - expect(response).toBeDefined(); + // Should return cached data or a valid fallback value + expect(response).toBeDefined(); + expect(response.status).toBe(200); // or appropriate error status + expect(data).toHaveProperty('circulatingSupply'); + expect(typeof data.circulatingSupply).toBe('string'); });This ensures the error path returns a valid response structure and doesn't just pass by accident.
website/src/hooks/subsquid/useJobs.tsx (1)
37-48
: Simplify useMemo dependencies.The dependency array includes
[fake, offset, limit, maxTimestamp, minTimestamp, result]
(line 46), butoffset
,limit
,maxTimestamp
, andminTimestamp
are already query variables that affectresult
. Including them separately is redundant and may cause unnecessary memoization.- }, [fake, offset, limit, maxTimestamp, minTimestamp, result]); + }, [fake, result]);The
result
object already captures changes to the query variables, andfake
controls the conditional logic.website/src/hooks/subsquid/useUsers.tsx (1)
19-26
: Simplify useMemo dependencies.The dependency array includes
[offset, limit, result]
(line 25), butoffset
andlimit
are query variables that already affectresult
. Including them separately is redundant.- [offset, limit, result] + [result]website/__tests__/hooks/subsquid/useCreatorDisputedJobs.test.tsx (1)
1-2
: Consider migrating to URQL mocks for consistency.This test uses Apollo's
MockedProvider
, but the PR migrates the codebase from Apollo to URQL. For consistency with the broader migration, consider updating this test to use URQL mocks instead.Based on the URQL migration patterns in the PR, you can use URQL's testing utilities. The test utilities are available at
website/__tests__/setup/mocks/urql.ts
andwebsite/__tests__/setup/test-utils.tsx
.website/src/hooks/subsquid/useMarketplace.tsx (1)
6-9
: Consider removing the empty variables object.The query doesn't use any variables, so passing an empty object is unnecessary. While harmless, omitting it makes the code cleaner.
Apply this diff:
const [result] = useQuery({ query: GET_MARKETPLACES, - variables: {}, });
website/__tests__/hooks/subsquid/useUsers.test.tsx (1)
1-2
: Migrate to URQL mocks for consistency.This test uses Apollo's
MockedProvider
, but the PR migrates the entire codebase from Apollo to URQL (see the URQL client setup inwebsite/src/lib/urql-client.ts
andwebsite/src/lib/urql-server.ts
). For consistency with the broader migration, update this test to use URQL testing utilities.The codebase provides URQL test utilities at
website/__tests__/setup/mocks/urql.ts
andwebsite/__tests__/setup/test-utils.tsx
. Consider refactoring this test to use those utilities instead of Apollo's MockedProvider.website/src/app/users/[address]/page.tsx (2)
83-88
: Consider checking URQL'sresult.error
for robust error handling.The URQL query pattern is correct, but the result object can contain an
error
property when the query fails. While the current code safely handles undefined data with optional chaining, explicitly checking for errors would provide better observability.Consider this pattern for more explicit error handling:
const client = createServerUrqlClient(); const result = await client .query(GET_USER_QUERY, { address: checksummedAddress }) .toPromise(); + +if (result.error) { + console.error('GraphQL query error:', result.error); + return null; +} + const data = result.data;This change makes error paths more explicit and improves debugging by surfacing GraphQL-specific errors separately from network/runtime exceptions.
110-115
: Consider checking URQL'sresult.error
(consistent with line 85-88).Same pattern as
getCachedUserData
: explicitly checkingresult.error
would improve error handling and observability.Apply the same pattern:
const client = createServerUrqlClient(); const result = await client .query(GET_USER_REVIEWS_QUERY, { address: checksummedAddress }) .toPromise(); + +if (result.error) { + console.error('GraphQL query error:', result.error); + return []; +} + const data = result.data;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (4)
subsquid/package-lock.json
is excluded by!**/package-lock.json
website/package-lock.json
is excluded by!**/package-lock.json
website/yarn.lock
is excluded by!**/yarn.lock
,!**/*.lock
yarn.lock
is excluded by!**/yarn.lock
,!**/*.lock
📒 Files selected for processing (103)
.github/PULL_REQUEST_TEMPLATE.md
(1 hunks).github/workflows/test-contract.yml
(1 hunks).github/workflows/test-website.yml
(1 hunks)contract/test/eaccbar.test.ts
(0 hunks)contract/test/eacctoken.test.ts
(1 hunks)contract/test/marketplacev2.test.ts
(0 hunks)contract/test/utils.test.ts
(1 hunks)subsquid/package.json
(2 hunks)subsquid/tests/fixtures/mock-events.ts
(1 hunks)subsquid/tests/integration/database.test.ts
(1 hunks)subsquid/tests/unit/data-models.test.ts
(1 hunks)subsquid/tests/unit/event-types.test.ts
(1 hunks)subsquid/tests/unit/job-event-processing.test.ts
(1 hunks)subsquid/vitest.config.ts
(1 hunks)website/README.md
(2 hunks)website/__tests__/api/circulating_supply.test.ts
(1 hunks)website/__tests__/api/market_cap.test.ts
(1 hunks)website/__tests__/api/total_supply.test.ts
(1 hunks)website/__tests__/components/Button.test.tsx
(1 hunks)website/__tests__/components/Input.test.tsx
(1 hunks)website/__tests__/components/JobsList.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useArbitrator.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useArbitrators.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useCreatorClosedJobs.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useCreatorCompletedJobs.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useCreatorDisputedJobs.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useCreatorOpenJobs.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useCreatorTakenJobs.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useJob.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useJobEvents.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useJobSearch.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useJobs.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useJobsByIds.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useMarketplace.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useReviews.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useSquidStatus.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useUser.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useUserNotifications.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useUsers.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useUsersByAddresses.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useWorkerApplications.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useWorkerCompletedJobs.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useWorkerDisputedJobs.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useWorkerTakenJobs.test.tsx
(1 hunks)website/__tests__/hooks/useConfig.test.ts
(1 hunks)website/__tests__/hooks/useDimensions.test.tsx
(1 hunks)website/__tests__/hooks/useToast.test.ts
(1 hunks)website/__tests__/integration/job-creation-flow.test.tsx
(1 hunks)website/__tests__/lib/tokens.test.ts
(1 hunks)website/__tests__/lib/utils.test.ts
(1 hunks)website/__tests__/pages/AcceptButton.test.tsx
(1 hunks)website/__tests__/pages/ConnectWallet.test.tsx
(1 hunks)website/__tests__/pages/DeliverResultButton.test.tsx
(1 hunks)website/__tests__/pages/PostJobPage.test.tsx
(1 hunks)website/__tests__/pages/TakeJobButton.test.tsx
(1 hunks)website/__tests__/setup/mocks/apollo.ts
(1 hunks)website/__tests__/setup/mocks/contracts.ts
(1 hunks)website/__tests__/setup/mocks/urql.ts
(1 hunks)website/__tests__/setup/mocks/wagmi.ts
(1 hunks)website/__tests__/setup/test-utils.tsx
(1 hunks)website/jest.config.ts
(1 hunks)website/jest.setup.ts
(1 hunks)website/package.json
(2 hunks)website/src/app/arbitrators/[address]/page.tsx
(4 hunks)website/src/app/arbitrators/page.tsx
(2 hunks)website/src/app/jobs/[id]/page.tsx
(4 hunks)website/src/app/open-job-list/page.tsx
(1 hunks)website/src/app/post-job/page.tsx
(1 hunks)website/src/app/providers.tsx
(2 hunks)website/src/app/users/[address]/page.tsx
(5 hunks)website/src/app/users/page.tsx
(2 hunks)website/src/components/Dashboard/Navbar/NotificationsButton.tsx
(1 hunks)website/src/hooks/subsquid/queries.ts
(1 hunks)website/src/hooks/subsquid/useArbitrator.tsx
(2 hunks)website/src/hooks/subsquid/useArbitratorPublicKeys.tsx
(1 hunks)website/src/hooks/subsquid/useArbitrators.tsx
(1 hunks)website/src/hooks/subsquid/useArbitratorsByAddresses.tsx
(2 hunks)website/src/hooks/subsquid/useCreatorClosedJobs.tsx
(1 hunks)website/src/hooks/subsquid/useCreatorCompletedJobs.tsx
(1 hunks)website/src/hooks/subsquid/useCreatorDisputedJobs.tsx
(1 hunks)website/src/hooks/subsquid/useCreatorOpenJobs.tsx
(1 hunks)website/src/hooks/subsquid/useCreatorTakenJobs.tsx
(1 hunks)website/src/hooks/subsquid/useJob.tsx
(1 hunks)website/src/hooks/subsquid/useJobEvents.tsx
(1 hunks)website/src/hooks/subsquid/useJobSearch.tsx
(3 hunks)website/src/hooks/subsquid/useJobs.tsx
(2 hunks)website/src/hooks/subsquid/useJobsByIds.tsx
(1 hunks)website/src/hooks/subsquid/useMarketplace.tsx
(1 hunks)website/src/hooks/subsquid/useReviews.tsx
(3 hunks)website/src/hooks/subsquid/useSquidStatus.tsx
(1 hunks)website/src/hooks/subsquid/useUser.tsx
(2 hunks)website/src/hooks/subsquid/useUserJobNotifications.tsx
(4 hunks)website/src/hooks/subsquid/useUserNotifications.tsx
(4 hunks)website/src/hooks/subsquid/useUsers.tsx
(2 hunks)website/src/hooks/subsquid/useUsersByAddresses.tsx
(2 hunks)website/src/hooks/subsquid/useWorkerApplications.tsx
(1 hunks)website/src/hooks/subsquid/useWorkerCompletedJobs.tsx
(1 hunks)website/src/hooks/subsquid/useWorkerDisputedJobs.tsx
(1 hunks)website/src/hooks/subsquid/useWorkerTakenJobs.tsx
(1 hunks)website/src/hooks/useSwResetMessage.tsx
(2 hunks)website/src/hooks/useWriteContractWithNotifications.ts
(3 hunks)website/src/lib/urql-client.ts
(1 hunks)website/src/lib/urql-server.ts
(1 hunks)
💤 Files with no reviewable changes (2)
- contract/test/eaccbar.test.ts
- contract/test/marketplacev2.test.ts
🧰 Additional context used
🧬 Code graph analysis (72)
website/__tests__/hooks/subsquid/useWorkerApplications.test.tsx (2)
website/__tests__/setup/mocks/apollo.ts (1)
mockJob
(5-25)website/src/hooks/subsquid/queries.ts (1)
GET_WORKER_APPLICATIONS
(192-205)
website/__tests__/hooks/subsquid/useUsersByAddresses.test.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_USERS_BY_ADDRESSES
(108-114)website/src/hooks/subsquid/useUsersByAddresses.tsx (1)
useUsersByAddresses
(13-47)
website/__tests__/hooks/subsquid/useWorkerDisputedJobs.test.tsx (2)
website/__tests__/setup/mocks/apollo.ts (1)
mockJob
(5-25)website/src/hooks/subsquid/queries.ts (1)
GET_WORKER_DISPUTED_JOBS
(223-229)
website/__tests__/hooks/subsquid/useArbitrator.test.tsx (3)
website/__tests__/setup/mocks/apollo.ts (1)
mockArbitrator
(38-45)website/src/hooks/subsquid/queries.ts (1)
GET_ARBITRATOR_BY_ADDRESS
(35-41)website/src/hooks/subsquid/useArbitrator.tsx (1)
useArbitrator
(11-38)
website/__tests__/hooks/subsquid/useUser.test.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_USER_BY_ADDRESS
(100-106)website/src/hooks/subsquid/useUser.tsx (1)
useUser
(22-46)
website/src/hooks/subsquid/useCreatorTakenJobs.tsx (6)
website/src/hooks/subsquid/useWorkerApplications.tsx (1)
useCreatorTakenJobs
(7-24)website/src/hooks/subsquid/useWorkerCompletedJobs.tsx (1)
useCreatorTakenJobs
(7-24)website/src/hooks/subsquid/useWorkerTakenJobs.tsx (1)
useCreatorTakenJobs
(7-24)website/src/service/Interfaces.ts (1)
OrderByType
(38-79)website/src/hooks/subsquid/queries.ts (1)
GET_CREATOR_TAKEN_JOBS
(140-146)contract/src/interfaces.ts (1)
Job
(33-40)
website/src/hooks/subsquid/useArbitratorPublicKeys.tsx (2)
website/src/hooks/subsquid/useArbitratorsByAddresses.tsx (1)
useArbitratorsByAddresses
(6-38)website/src/hooks/subsquid/queries.ts (1)
GET_ARBITRATORS_BY_ADDRESSES
(43-49)
website/__tests__/hooks/subsquid/useWorkerCompletedJobs.test.tsx (2)
website/__tests__/setup/mocks/apollo.ts (1)
mockJob
(5-25)website/src/hooks/subsquid/queries.ts (1)
GET_WORKER_COMPLETED_JOBS
(215-221)
website/src/hooks/useSwResetMessage.tsx (2)
contract/src/interfaces.ts (1)
JobEvent
(44-48)website/src/lib/urql-client.ts (1)
urqlClient
(6-17)
website/src/hooks/subsquid/useCreatorDisputedJobs.tsx (4)
website/src/hooks/subsquid/useWorkerDisputedJobs.tsx (1)
useCreatorDisputedJobs
(7-24)website/src/service/Interfaces.ts (1)
OrderByType
(38-79)website/src/hooks/subsquid/queries.ts (1)
GET_CREATOR_DISPUTED_JOBS
(156-162)contract/src/interfaces.ts (1)
Job
(33-40)
subsquid/tests/unit/job-event-processing.test.ts (2)
contract/src/utils/decodeEvents.ts (7)
decodeJobCreatedEvent
(6-22)decodeJobUpdatedEvent
(24-38)decodeJobSignedEvent
(40-46)decodeJobRatedEvent
(48-55)decodeJobDisputedEvent
(57-66)decodeJobArbitratedEvent
(88-100)decodeJobMessageEvent
(102-109)subsquid/tests/fixtures/mock-events.ts (3)
mockJobCreatedEventData
(3-14)mockJobRatedEventData
(30-33)mockJobArbitratedEventData
(39-43)
website/src/hooks/subsquid/useWorkerApplications.tsx (6)
website/src/hooks/subsquid/useCreatorTakenJobs.tsx (1)
useCreatorTakenJobs
(7-24)website/src/hooks/subsquid/useWorkerCompletedJobs.tsx (1)
useCreatorTakenJobs
(7-24)website/src/hooks/subsquid/useWorkerTakenJobs.tsx (1)
useCreatorTakenJobs
(7-24)website/src/service/Interfaces.ts (1)
OrderByType
(38-79)website/src/hooks/subsquid/queries.ts (1)
GET_WORKER_APPLICATIONS
(192-205)contract/src/interfaces.ts (1)
Job
(33-40)
website/src/app/open-job-list/page.tsx (1)
website/src/app/post-job/page.tsx (1)
dynamic
(6-6)
website/__tests__/hooks/subsquid/useCreatorClosedJobs.test.tsx (3)
website/__tests__/setup/mocks/apollo.ts (1)
mockJob
(5-25)website/src/hooks/subsquid/queries.ts (1)
GET_CREATOR_CLOSED_JOBS
(164-170)website/src/hooks/subsquid/useCreatorClosedJobs.tsx (1)
useCreatorClosedJobs
(7-24)
website/src/hooks/subsquid/useArbitrators.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_ARBITRATORS
(27-33)contract/src/interfaces.ts (1)
Arbitrator
(17-17)
website/__tests__/hooks/subsquid/useSquidStatus.test.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_SQUID_STATUS
(19-25)website/src/hooks/subsquid/useSquidStatus.tsx (1)
useSquidStatus
(5-21)
website/src/hooks/subsquid/useMarketplace.tsx (1)
website/src/hooks/subsquid/queries.ts (1)
GET_MARKETPLACES
(11-17)
website/__tests__/hooks/subsquid/useCreatorTakenJobs.test.tsx (2)
website/__tests__/setup/mocks/apollo.ts (1)
mockJob
(5-25)website/src/hooks/subsquid/queries.ts (1)
GET_CREATOR_TAKEN_JOBS
(140-146)
website/src/app/users/page.tsx (1)
website/src/lib/urql-server.ts (1)
createServerUrqlClient
(4-14)
website/src/hooks/subsquid/useUserJobNotifications.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_USER_JOB_NOTIFICATIONS
(287-308)website/src/service/Interfaces.ts (1)
Notification
(29-36)
website/src/hooks/useWriteContractWithNotifications.ts (2)
website/src/lib/urql-client.ts (1)
urqlClient
(6-17)website/src/hooks/useToast.ts (1)
useToast
(3-35)
website/__tests__/pages/AcceptButton.test.tsx (1)
website/__tests__/setup/mocks/apollo.ts (1)
mockJob
(5-25)
website/src/hooks/subsquid/useJobs.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_JOBS
(76-82)contract/src/interfaces.ts (1)
Job
(33-40)
website/src/components/Dashboard/Navbar/NotificationsButton.tsx (1)
website/src/hooks/subsquid/useUserNotifications.tsx (1)
useUserNotifications
(29-128)
website/__tests__/hooks/subsquid/useArbitrators.test.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_ARBITRATORS
(27-33)website/src/hooks/subsquid/useArbitrators.tsx (1)
useArbitrators
(6-20)
website/__tests__/hooks/useToast.test.ts (1)
website/src/hooks/useToast.ts (1)
useToast
(3-35)
website/__tests__/hooks/subsquid/useUserNotifications.test.tsx (2)
website/src/hooks/subsquid/queries.ts (2)
GET_USER_NOTIFICATIONS
(231-251)GET_JOBS_BY_IDS
(68-74)website/src/hooks/subsquid/useUserNotifications.tsx (1)
useUserNotifications
(29-128)
website/src/hooks/subsquid/useJob.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_JOB_BY_ID
(60-66)contract/src/interfaces.ts (1)
Job
(33-40)
website/__tests__/lib/utils.test.ts (1)
website/src/lib/utils.ts (9)
cn
(7-9)formatDate
(10-17)absoluteUrl
(18-20)EventTextMap
(21-90)isImageValid
(92-102)shortenText
(104-124)convertToSeconds
(126-143)getUnitAndValueFromSeconds
(145-171)formatTimeLeft
(182-191)
website/__tests__/setup/mocks/apollo.ts (1)
website/src/hooks/subsquid/queries.ts (2)
GET_JOBS
(76-82)GET_USERS
(92-98)
website/__tests__/hooks/subsquid/useCreatorCompletedJobs.test.tsx (3)
website/__tests__/setup/mocks/apollo.ts (1)
mockJob
(5-25)website/src/hooks/subsquid/queries.ts (1)
GET_CREATOR_COMPLETED_JOBS
(148-154)website/src/hooks/subsquid/useCreatorCompletedJobs.tsx (1)
useCreatorCompletedJobs
(7-24)
website/__tests__/hooks/subsquid/useJobEvents.test.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_JOB_EVENTS
(124-130)website/src/hooks/subsquid/useJobEvents.tsx (1)
useJobEvents
(6-20)
website/src/hooks/subsquid/useArbitrator.tsx (1)
website/src/hooks/subsquid/queries.ts (1)
GET_ARBITRATOR_BY_ADDRESS
(35-41)
website/__tests__/components/JobsList.test.tsx (2)
website/src/hooks/subsquid/useJobs.tsx (1)
useJobs
(23-49)website/src/components/Dashboard/JobsList/JobsList.tsx (1)
JobsList
(8-14)
website/__tests__/hooks/subsquid/useUsers.test.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_USERS
(92-98)website/src/hooks/subsquid/useUsers.tsx (1)
useUsers
(13-27)
website/src/hooks/subsquid/useCreatorOpenJobs.tsx (3)
website/src/service/Interfaces.ts (1)
OrderByType
(38-79)website/src/hooks/subsquid/queries.ts (1)
GET_CREATOR_OPEN_JOBS
(132-138)contract/src/interfaces.ts (1)
Job
(33-40)
website/__tests__/hooks/subsquid/useCreatorOpenJobs.test.tsx (3)
website/__tests__/setup/mocks/apollo.ts (1)
mockJob
(5-25)website/src/hooks/subsquid/queries.ts (1)
GET_CREATOR_OPEN_JOBS
(132-138)website/src/hooks/subsquid/useCreatorOpenJobs.tsx (1)
useCreatorOpenJobs
(7-24)
website/src/app/jobs/[id]/page.tsx (3)
contract/src/interfaces.ts (1)
Job
(33-40)website/src/lib/urql-server.ts (1)
createServerUrqlClient
(4-14)website/src/app/jobs/[id]/JobPageClient.tsx (1)
JobPageClient
(83-579)
website/__tests__/hooks/subsquid/useJob.test.tsx (3)
website/__tests__/setup/mocks/apollo.ts (1)
mockJob
(5-25)website/src/hooks/subsquid/queries.ts (1)
GET_JOB_BY_ID
(60-66)website/src/hooks/subsquid/useJob.tsx (1)
useJob
(6-20)
contract/test/utils.test.ts (1)
contract/src/utils/encryption.ts (1)
publishMediaToIpfs
(71-88)
website/src/hooks/subsquid/useWorkerDisputedJobs.tsx (4)
website/src/hooks/subsquid/useCreatorDisputedJobs.tsx (1)
useCreatorDisputedJobs
(7-24)website/src/service/Interfaces.ts (1)
OrderByType
(38-79)website/src/hooks/subsquid/queries.ts (1)
GET_WORKER_DISPUTED_JOBS
(223-229)contract/src/interfaces.ts (1)
Job
(33-40)
website/src/app/post-job/page.tsx (1)
website/src/app/open-job-list/page.tsx (1)
dynamic
(9-9)
website/src/hooks/subsquid/useReviews.tsx (1)
website/src/hooks/subsquid/queries.ts (1)
GET_REVIEWS
(116-122)
website/src/hooks/subsquid/useUsersByAddresses.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_USERS_BY_ADDRESSES
(108-114)website/src/hooks/subsquid/useUser.tsx (1)
ExtendedUser
(7-20)
website/src/hooks/subsquid/useSquidStatus.tsx (1)
website/src/hooks/subsquid/queries.ts (1)
GET_SQUID_STATUS
(19-25)
website/__tests__/hooks/subsquid/useJobSearch.test.tsx (3)
website/__tests__/setup/mocks/apollo.ts (1)
mockJob
(5-25)website/src/hooks/subsquid/queries.ts (1)
GET_JOB_SEARCH
(172-190)website/src/hooks/subsquid/useJobSearch.tsx (1)
useJobSearch
(10-130)
website/src/hooks/subsquid/useWorkerTakenJobs.tsx (6)
website/src/hooks/subsquid/useCreatorTakenJobs.tsx (1)
useCreatorTakenJobs
(7-24)website/src/hooks/subsquid/useWorkerApplications.tsx (1)
useCreatorTakenJobs
(7-24)website/src/hooks/subsquid/useWorkerCompletedJobs.tsx (1)
useCreatorTakenJobs
(7-24)website/src/service/Interfaces.ts (1)
OrderByType
(38-79)website/src/hooks/subsquid/queries.ts (1)
GET_WORKER_TAKEN_JOBS
(207-213)contract/src/interfaces.ts (1)
Job
(33-40)
website/src/app/arbitrators/[address]/page.tsx (2)
contract/src/interfaces.ts (1)
Arbitrator
(17-17)website/src/lib/urql-server.ts (1)
createServerUrqlClient
(4-14)
subsquid/tests/unit/data-models.test.ts (2)
contract/src/interfaces.ts (4)
User
(18-18)Arbitrator
(17-17)Job
(33-40)Review
(20-20)subsquid/src/abi/MarketplaceDataV1.ts (1)
marketplace
(136-138)
website/src/hooks/subsquid/useJobEvents.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_JOB_EVENTS
(124-130)contract/src/interfaces.ts (1)
JobEvent
(44-48)
website/src/hooks/subsquid/useCreatorCompletedJobs.tsx (3)
website/src/service/Interfaces.ts (1)
OrderByType
(38-79)website/src/hooks/subsquid/queries.ts (1)
GET_CREATOR_COMPLETED_JOBS
(148-154)contract/src/interfaces.ts (1)
Job
(33-40)
website/__tests__/components/Input.test.tsx (1)
website/src/components/Input.tsx (1)
Input
(11-89)
website/src/hooks/subsquid/useUserNotifications.tsx (1)
website/src/hooks/subsquid/queries.ts (1)
GET_USER_NOTIFICATIONS
(231-251)
website/__tests__/hooks/subsquid/useJobsByIds.test.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_JOBS_BY_IDS
(68-74)website/src/hooks/subsquid/useJobsByIds.tsx (1)
useJobsByIds
(6-21)
website/__tests__/hooks/subsquid/useCreatorDisputedJobs.test.tsx (2)
website/__tests__/setup/mocks/apollo.ts (1)
mockJob
(5-25)website/src/hooks/subsquid/queries.ts (1)
GET_CREATOR_DISPUTED_JOBS
(156-162)
website/src/app/arbitrators/page.tsx (1)
website/src/lib/urql-server.ts (1)
createServerUrqlClient
(4-14)
website/src/hooks/subsquid/useUser.tsx (1)
website/src/hooks/subsquid/queries.ts (1)
GET_USER_BY_ADDRESS
(100-106)
website/__tests__/hooks/subsquid/useMarketplace.test.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_MARKETPLACES
(11-17)website/src/hooks/subsquid/useMarketplace.tsx (1)
useMarketplace
(5-19)
website/__tests__/hooks/useConfig.test.ts (1)
website/src/hooks/useConfig.ts (1)
useConfig
(5-19)
website/__tests__/hooks/subsquid/useWorkerTakenJobs.test.tsx (2)
website/__tests__/setup/mocks/apollo.ts (1)
mockJob
(5-25)website/src/hooks/subsquid/queries.ts (1)
GET_WORKER_TAKEN_JOBS
(207-213)
website/src/app/providers.tsx (1)
website/src/lib/urql-client.ts (1)
urqlClient
(6-17)
website/__tests__/setup/test-utils.tsx (1)
website/src/lib/urql-client.ts (1)
urqlClient
(6-17)
website/src/hooks/subsquid/useWorkerCompletedJobs.tsx (6)
website/src/hooks/subsquid/useCreatorTakenJobs.tsx (1)
useCreatorTakenJobs
(7-24)website/src/hooks/subsquid/useWorkerApplications.tsx (1)
useCreatorTakenJobs
(7-24)website/src/hooks/subsquid/useWorkerTakenJobs.tsx (1)
useCreatorTakenJobs
(7-24)website/src/service/Interfaces.ts (1)
OrderByType
(38-79)website/src/hooks/subsquid/queries.ts (1)
GET_WORKER_COMPLETED_JOBS
(215-221)contract/src/interfaces.ts (1)
Job
(33-40)
website/jest.setup.ts (1)
website/__tests__/setup/mocks/contracts.ts (1)
mockConfig
(9-14)
website/__tests__/hooks/subsquid/useReviews.test.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_REVIEWS
(116-122)website/src/hooks/subsquid/useReviews.tsx (1)
useReviews
(12-74)
website/__tests__/hooks/subsquid/useJobs.test.tsx (2)
website/__tests__/setup/mocks/urql.ts (1)
createMockClient
(6-24)website/src/hooks/subsquid/useJobs.tsx (1)
useJobs
(23-49)
website/src/app/users/[address]/page.tsx (2)
website/src/lib/urql-server.ts (1)
createServerUrqlClient
(4-14)website/src/app/users/[address]/UserPageClient.tsx (1)
UserPageClient
(56-389)
website/src/hooks/subsquid/useCreatorClosedJobs.tsx (3)
website/src/service/Interfaces.ts (1)
OrderByType
(38-79)website/src/hooks/subsquid/queries.ts (1)
GET_CREATOR_CLOSED_JOBS
(164-170)contract/src/interfaces.ts (1)
Job
(33-40)
website/src/hooks/subsquid/useJobsByIds.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_JOBS_BY_IDS
(68-74)contract/src/interfaces.ts (1)
Job
(33-40)
website/src/hooks/subsquid/useJobSearch.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_JOB_SEARCH
(172-190)contract/src/interfaces.ts (1)
Job
(33-40)
website/src/hooks/subsquid/useUsers.tsx (3)
website/src/hooks/subsquid/queries.ts (1)
GET_USERS
(92-98)website/src/hooks/subsquid/useUser.tsx (1)
ExtendedUser
(7-20)website/src/hooks/subsquid/useUsersByAddresses.tsx (1)
ExtendedUser
(7-11)
website/src/hooks/subsquid/useArbitratorsByAddresses.tsx (2)
website/src/hooks/subsquid/queries.ts (1)
GET_ARBITRATORS_BY_ADDRESSES
(43-49)contract/src/interfaces.ts (1)
Arbitrator
(17-17)
🪛 Biome (2.1.2)
website/__tests__/setup/mocks/urql.ts
[error] 31-31: expected >
but instead found value
Remove value
(parse)
[error] 31-31: Invalid assignment to <Provider value
This expression cannot be assigned to
(parse)
[error] 31-31: unterminated regex literal
...but the line ends here
a regex literal starts there...
(parse)
.github/workflows/test-contract.yml
Outdated
- name: Upload coverage to Coveralls | ||
uses: coverallsapp/github-action@v2 | ||
with: | ||
github-token: ${{ secrets.GITHUB_TOKEN }} | ||
path-to-lcov: ./contract/coverage/lcov.info | ||
flag-name: contract | ||
parallel: false | ||
env: | ||
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coveralls upload breaks on forked PRs
Forked pull requests won’t receive COVERALLS_REPO_TOKEN
, so this step fails and the whole workflow turns red for external contributors. Please guard the Coveralls upload so it only runs when the secret is present (or switch to the Coveralls GitHub App flow).
Consider:
- name: Upload coverage to Coveralls
- uses: coverallsapp/github-action@v2
+ if: ${{ secrets.COVERALLS_REPO_TOKEN != '' }}
+ uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: ./contract/coverage/lcov.info
flag-name: contract
parallel: false
env:
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
🤖 Prompt for AI Agents
In .github/workflows/test-contract.yml around lines 44 to 52, the Coveralls
upload step runs on forked PRs without the COVERALLS_REPO_TOKEN and fails; guard
the step so it only runs when the secret is present. Add an if condition to the
upload step that checks the secret (for example using GitHub Actions expression
checking secrets.COVERALLS_REPO_TOKEN is non-empty) or switch to the Coveralls
GitHub App flow; ensure the step is skipped when the secret is absent to avoid
failing workflows for external contributors.
/* | ||
* Uncomment the code below and import the required models when ready to enable integration tests | ||
* | ||
* import { DataSource } from 'typeorm'; | ||
* import { ZeroAddress, getAddress } from 'ethers'; | ||
* import { User, Arbitrator, Job, JobRoles, JobTimes, Marketplace } from '../../src/model'; | ||
* | ||
* let dataSource: DataSource; | ||
* | ||
* beforeAll(async () => { | ||
* dataSource = new DataSource({ | ||
* type: 'postgres', | ||
* host: process.env.DB_HOST || 'localhost', | ||
* port: parseInt(process.env.DB_PORT || '5432'), | ||
* database: process.env.DB_NAME || 'squid', | ||
* username: process.env.DB_USER || 'postgres', | ||
* password: process.env.DB_PASS || 'postgres', | ||
* entities: [User, Arbitrator, Job, Marketplace], | ||
* synchronize: false, | ||
* }); | ||
* await dataSource.initialize(); | ||
* }); | ||
* | ||
* afterAll(async () => { | ||
* if (dataSource?.isInitialized) { | ||
* await dataSource.destroy(); | ||
* } | ||
* }); | ||
* | ||
* // Add your integration tests here | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Address inconsistencies in the commented scaffold.
The commented scaffold has a few issues to fix before enabling:
-
Missing entities in DataSource configuration: Lines 29 imports
JobRoles
andJobTimes
, but line 41 only includes[User, Arbitrator, Job, Marketplace]
. Either remove the unused imports or add these entities to the array. -
Missing vitest lifecycle imports: The scaffold uses
beforeAll
andafterAll
(lines 33, 47) but these are not in the import list at line 27. These should be imported from 'vitest'. -
Port parsing could be more robust: Line 37 uses
parseInt
without a radix, and could fail silently on invalid input (though the fallback '5432' provides safety).
Apply this diff to fix the issues:
* Uncomment the code below and import the required models when ready to enable integration tests
*
+ * import { beforeAll, afterAll } from 'vitest';
* import { DataSource } from 'typeorm';
* import { ZeroAddress, getAddress } from 'ethers';
- * import { User, Arbitrator, Job, JobRoles, JobTimes, Marketplace } from '../../src/model';
+ * import { User, Arbitrator, Job, Marketplace } from '../../src/model';
*
* let dataSource: DataSource;
*
* beforeAll(async () => {
* dataSource = new DataSource({
* type: 'postgres',
* host: process.env.DB_HOST || 'localhost',
-* port: parseInt(process.env.DB_PORT || '5432'),
+* port: parseInt(process.env.DB_PORT || '5432', 10),
* database: process.env.DB_NAME || 'squid',
* username: process.env.DB_USER || 'postgres',
* password: process.env.DB_PASS || 'postgres',
* entities: [User, Arbitrator, Job, Marketplace],
* synchronize: false,
* });
* await dataSource.initialize();
* });
Note: If JobRoles
and JobTimes
are TypeORM entities that should be included in the DataSource, add them back to the entities array instead of removing them from the imports.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
/* | |
* Uncomment the code below and import the required models when ready to enable integration tests | |
* | |
* import { DataSource } from 'typeorm'; | |
* import { ZeroAddress, getAddress } from 'ethers'; | |
* import { User, Arbitrator, Job, JobRoles, JobTimes, Marketplace } from '../../src/model'; | |
* | |
* let dataSource: DataSource; | |
* | |
* beforeAll(async () => { | |
* dataSource = new DataSource({ | |
* type: 'postgres', | |
* host: process.env.DB_HOST || 'localhost', | |
* port: parseInt(process.env.DB_PORT || '5432'), | |
* database: process.env.DB_NAME || 'squid', | |
* username: process.env.DB_USER || 'postgres', | |
* password: process.env.DB_PASS || 'postgres', | |
* entities: [User, Arbitrator, Job, Marketplace], | |
* synchronize: false, | |
* }); | |
* await dataSource.initialize(); | |
* }); | |
* | |
* afterAll(async () => { | |
* if (dataSource?.isInitialized) { | |
* await dataSource.destroy(); | |
* } | |
* }); | |
* | |
* // Add your integration tests here | |
*/ | |
/* | |
* Uncomment the code below and import the required models when ready to enable integration tests | |
* | |
* import { beforeAll, afterAll } from 'vitest'; | |
* import { DataSource } from 'typeorm'; | |
* import { ZeroAddress, getAddress } from 'ethers'; | |
* import { User, Arbitrator, Job, Marketplace } from '../../src/model'; | |
* | |
* let dataSource: DataSource; | |
* | |
* beforeAll(async () => { | |
* dataSource = new DataSource({ | |
* type: 'postgres', | |
* host: process.env.DB_HOST || 'localhost', | |
* port: parseInt(process.env.DB_PORT || '5432', 10), | |
* database: process.env.DB_NAME || 'squid', | |
* username: process.env.DB_USER || 'postgres', | |
* password: process.env.DB_PASS || 'postgres', | |
* entities: [User, Arbitrator, Job, Marketplace], | |
* synchronize: false, | |
* }); | |
* await dataSource.initialize(); | |
* }); | |
* | |
* afterAll(async () => { | |
* if (dataSource?.isInitialized) { | |
* await dataSource.destroy(); | |
* } | |
* }); | |
* | |
* // Add your integration tests here | |
*/ |
🤖 Prompt for AI Agents
In subsquid/tests/integration/database.test.ts around lines 24 to 54, the
commented scaffold has inconsistent imports and minor robustness issues: update
the import block to include vitest lifecycle functions (import beforeAll and
afterAll from 'vitest'), make the DataSource entities array match the imported
entities (add JobRoles and JobTimes to entities if they are TypeORM entities,
otherwise remove their imports), and make port parsing explicit by using
parseInt(process.env.DB_PORT || '5432', 10). Ensure the rest of the scaffold
remains commented until ready to enable.
import { describe, it, expect } from 'vitest'; | ||
import { ZeroAddress, ZeroHash, getAddress } from 'ethers'; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Missing imports for all model classes.
The test file references User
, Arbitrator
, Job
, Review
, Marketplace
, JobRoles
, and JobTimes
throughout but never imports them. If these tests are unskipped, they will fail immediately with "ReferenceError: User is not defined" (and similar for other models).
Add the missing imports at the top of the file. Based on the project structure, you likely need:
import { describe, it, expect } from 'vitest';
import { ZeroAddress, ZeroHash, getAddress } from 'ethers';
+import { User } from '../path/to/User';
+import { Arbitrator } from '../path/to/Arbitrator';
+import { Job } from '../path/to/Job';
+import { JobRoles } from '../path/to/JobRoles';
+import { JobTimes } from '../path/to/JobTimes';
+import { Review } from '../path/to/Review';
+import { Marketplace } from '../path/to/Marketplace';
Run the following script to locate the model class definitions:
🏁 Script executed:
#!/bin/bash
# Find TypeORM entity definitions
rg -n --type=ts -C3 '@Entity.*User|@Entity.*Arbitrator|@Entity.*Job|@Entity.*Review|@Entity.*Marketplace' subsquid/
Length of output: 0
🏁 Script executed:
#!/bin/bash
# Search for all TypeORM entity definitions across the repo
rg -n --type=ts '@Entity' -C3 .
Length of output: 4972
🏁 Script executed:
#!/bin/bash
# Locate JobRoles and JobTimes class definitions
rg -n --type=ts 'export class JobRoles' -C3 .
rg -n --type=ts 'export class JobTimes' -C3 .
# Search by filename
fd JobRoles
fd JobTimes
Length of output: 1142
Add missing model imports
The test references User
, Review
, Job
, Marketplace
, Arbitrator
, JobRoles
, and JobTimes
but doesn’t import them; unskipping will cause ReferenceErrors.
import { describe, it, expect } from 'vitest';
import { ZeroAddress, ZeroHash, getAddress } from 'ethers';
+import { User } from '../../src/model/generated/user.model';
+import { Review } from '../../src/model/generated/review.model';
+import { Job } from '../../src/model/generated/job.model';
+import { Marketplace } from '../../src/model/generated/marketplace.model';
+import { Arbitrator } from '../../src/model/generated/arbitrator.model';
+import { JobRoles } from '../../src/model/generated/_jobRoles';
+import { JobTimes } from '../../src/model/generated/_jobTimes';
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
import { describe, it, expect } from 'vitest'; | |
import { ZeroAddress, ZeroHash, getAddress } from 'ethers'; | |
import { describe, it, expect } from 'vitest'; | |
import { ZeroAddress, ZeroHash, getAddress } from 'ethers'; | |
import { User } from '../../src/model/generated/user.model'; | |
import { Review } from '../../src/model/generated/review.model'; | |
import { Job } from '../../src/model/generated/job.model'; | |
import { Marketplace } from '../../src/model/generated/marketplace.model'; | |
import { Arbitrator } from '../../src/model/generated/arbitrator.model'; | |
import { JobRoles } from '../../src/model/generated/_jobRoles'; | |
import { JobTimes } from '../../src/model/generated/_jobTimes'; |
🤖 Prompt for AI Agents
In subsquid/tests/unit/data-models.test.ts lines 1-3, the test file imports
vitest and ethers but is missing named imports for the data models used (User,
Review, Job, Marketplace, Arbitrator, JobRoles, JobTimes); add named imports for
those symbols from the module that defines your ORM/data models (e.g., the
project file that exports them — adjust path accordingly) by adding a single
import statement at the top like: import { User, Review, Job, Marketplace,
Arbitrator, JobRoles, JobTimes } from '<correct-models-module-path>'; this will
prevent ReferenceErrors when unskipping tests.
useEffect(() => { | ||
if (data) { | ||
if (result.data) { | ||
const results: Record<string, string> = {}; | ||
for (const arbitrator of data.arbitrators) { | ||
for (const arbitrator of result.data.arbitrators) { | ||
resultMap[arbitrator.address_] = arbitrator.publicKey; | ||
} | ||
|
||
setResultMap((prev) => ({ ...prev, ...results })); | ||
} | ||
}, [data]); | ||
}, [result.data]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Variable assignment bug in effect.
Line 20 assigns to resultMap
instead of the local results
object:
resultMap[arbitrator.address_] = arbitrator.publicKey;
This means the local results
object remains empty and setResultMap
on line 23 receives an empty object merged with previous state. New arbitrator data won't be added.
Apply this fix:
if (result.data) {
const results: Record<string, string> = {};
for (const arbitrator of result.data.arbitrators) {
- resultMap[arbitrator.address_] = arbitrator.publicKey;
+ results[arbitrator.address_] = arbitrator.publicKey;
}
setResultMap((prev) => ({ ...prev, ...results }));
}
🤖 Prompt for AI Agents
In website/src/hooks/subsquid/useArbitratorPublicKeys.tsx around lines 16 to 25,
the effect loop mistakenly writes to the outer state variable `resultMap`
instead of the local `results` accumulator, leaving `results` empty and causing
setResultMap to merge no new data; change the assignment inside the loop to
write to the local `results` object (i.e., results[arbitrator.address_] =
arbitrator.publicKey), keep the existing results typing, then call
setResultMap(prev => ({ ...prev, ...results })) as-is so the new arbitrator
entries are merged into state.
export default function useCreatorTakenJobs( | ||
workerAddress: string, | ||
orderBy?: OrderByType | ||
) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Function name mismatch.
The function is declared as useCreatorTakenJobs
but the file is named useWorkerApplications.tsx
. This will cause import errors when other modules try to import this hook.
Apply this diff:
-export default function useCreatorTakenJobs(
+export default function useWorkerApplications(
workerAddress: string,
orderBy?: OrderByType
) {
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
export default function useCreatorTakenJobs( | |
workerAddress: string, | |
orderBy?: OrderByType | |
) { | |
export default function useWorkerApplications( | |
workerAddress: string, | |
orderBy?: OrderByType | |
) { |
🤖 Prompt for AI Agents
In website/src/hooks/subsquid/useWorkerApplications.tsx around lines 7 to 10,
the default-exported function is named useCreatorTakenJobs which mismatches the
filename and will break imports; rename the function to useWorkerApplications
(and update any internal references) so the default export matches the file
name, and ensure any callers/imports elsewhere are updated accordingly.
export default function useCreatorDisputedJobs( | ||
creatorAddress: string, | ||
orderBy?: OrderByType | ||
) { | ||
const { data, ...rest } = useQuery(GET_WORKER_DISPUTED_JOBS, { | ||
const [result] = useQuery({ | ||
query: GET_WORKER_DISPUTED_JOBS, | ||
variables: { creatorAddress, ...(orderBy && { orderBy }) }, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Function name and parameter mismatches.
Multiple critical issues:
- Function name mismatch: Function is declared as
useCreatorDisputedJobs
but the file is nameduseWorkerDisputedJobs.tsx
. This will cause import errors. - Parameter name mismatch: Parameter is named
creatorAddress
but the queryGET_WORKER_DISPUTED_JOBS
expects a$worker
variable (see query definition at website/src/hooks/subsquid/queries.ts:222-228). - Variable mismatch: Line 13 passes
creatorAddress
but the query expectsworker
orworkerAddress
.
Apply this diff to fix all issues:
-export default function useCreatorDisputedJobs(
- creatorAddress: string,
+export default function useWorkerDisputedJobs(
+ workerAddress: string,
orderBy?: OrderByType
) {
const [result] = useQuery({
query: GET_WORKER_DISPUTED_JOBS,
- variables: { creatorAddress, ...(orderBy && { orderBy }) },
+ variables: { worker: workerAddress, ...(orderBy && { orderBy }) },
});
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
export default function useCreatorDisputedJobs( | |
creatorAddress: string, | |
orderBy?: OrderByType | |
) { | |
const { data, ...rest } = useQuery(GET_WORKER_DISPUTED_JOBS, { | |
const [result] = useQuery({ | |
query: GET_WORKER_DISPUTED_JOBS, | |
variables: { creatorAddress, ...(orderBy && { orderBy }) }, | |
}); | |
export default function useWorkerDisputedJobs( | |
workerAddress: string, | |
orderBy?: OrderByType | |
) { | |
const [result] = useQuery({ | |
query: GET_WORKER_DISPUTED_JOBS, | |
variables: { worker: workerAddress, ...(orderBy && { orderBy }) }, | |
}); |
🤖 Prompt for AI Agents
In website/src/hooks/subsquid/useWorkerDisputedJobs.tsx around lines 7 to 14,
the exported function name and parameter/variable names do not match the file
and the GraphQL query: rename the function to export default function
useWorkerDisputedJobs(workerAddress: string, orderBy?: OrderByType) and change
the variables passed to the query to use the expected worker variable (e.g.,
variables: { worker: workerAddress, ...(orderBy && { orderBy }) }) so the
exported name, parameter name, and GraphQL variable all align.
// Create a server-side URQL client | ||
export function createServerUrqlClient() { | ||
return new Client({ | ||
url: process.env.NEXT_PUBLIC_SUBSQUID_API_URL || '', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add validation for required environment variable.
Falling back to an empty string when NEXT_PUBLIC_SUBSQUID_API_URL
is missing will cause runtime errors when the client attempts to make requests. Consider throwing an error or providing a more robust fallback.
Apply this diff:
export function createServerUrqlClient() {
+ const url = process.env.NEXT_PUBLIC_SUBSQUID_API_URL;
+ if (!url) {
+ throw new Error('NEXT_PUBLIC_SUBSQUID_API_URL environment variable is required');
+ }
+
return new Client({
- url: process.env.NEXT_PUBLIC_SUBSQUID_API_URL || '',
+ url,
exchanges: [cacheExchange, fetchExchange],
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
url: process.env.NEXT_PUBLIC_SUBSQUID_API_URL || '', | |
export function createServerUrqlClient() { | |
const url = process.env.NEXT_PUBLIC_SUBSQUID_API_URL; | |
if (!url) { | |
throw new Error('NEXT_PUBLIC_SUBSQUID_API_URL environment variable is required'); | |
} | |
return new Client({ | |
url, | |
exchanges: [cacheExchange, fetchExchange], | |
}); | |
} |
🤖 Prompt for AI Agents
In website/src/lib/urql-server.ts around line 6, the code currently falls back
to an empty string for url: process.env.NEXT_PUBLIC_SUBSQUID_API_URL || '',
which can cause runtime request failures; change this to validate the
environment variable at startup and fail fast: if
process.env.NEXT_PUBLIC_SUBSQUID_API_URL is undefined or empty, throw a clear
Error (including the variable name and instructions) or return early so the
server won't start with an invalid URL, otherwise assign the env value; ensure
the change surfaces at build/start time rather than allowing an empty string to
propagate to the client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review continued from previous batch...
query: GET_CREATOR_DISPUTED_JOBS, | ||
variables: { | ||
creatorAddress: '0xCreator1', | ||
offset: 0, | ||
limit: 1000, | ||
}, |
There was a problem hiding this comment.
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 mock variables match the actual hook signature.
The mock includes offset
and limit
variables (lines 26-28), but the typical pattern for subsquid hooks in this codebase uses orderBy
instead (see related hooks like useWorkerCompletedJobs
, useCreatorTakenJobs
). Additionally, the hook is invoked with object syntax { creatorAddress, offset, limit }
(lines 48, 63), but related hooks use positional parameters.
Run the following script to verify the actual signature of useCreatorDisputedJobs
:
🏁 Script executed:
#!/bin/bash
# Description: Verify the signature and query variables for useCreatorDisputedJobs
# Find the hook implementation
echo "=== Hook Implementation ==="
ast-grep --pattern $'export default function useCreatorDisputedJobs($$$) {
$$$
}'
# Find the query definition
echo "=== Query Definition ==="
rg -A 5 'GET_CREATOR_DISPUTED_JOBS'
Length of output: 5525
Update test to use orderBy
and positional args for useCreatorDisputedJobs
The mock for GET_CREATOR_DISPUTED_JOBS currently passes offset
/limit
and calls the hook with an object, but useCreatorDisputedJobs
is defined as (creatorAddress: string, orderBy?: OrderByType)
and the query only accepts $orderBy
. Change the test’s variables to:
variables: {
creatorAddress: '0xCreator1',
...(orderBy && { orderBy }),
},
and invoke the hook as:
useCreatorDisputedJobs('0xCreator1', orderByParam)
to match the hook signature and GraphQL parameters.
🤖 Prompt for AI Agents
In website/__tests__/hooks/subsquid/useCreatorDisputedJobs.test.tsx around lines
24 to 29, the test mock is using offset/limit and calling the hook with an
object, but the real hook signature is useCreatorDisputedJobs(creatorAddress:
string, orderBy?: OrderByType) and the GraphQL query only accepts $orderBy;
update the mocked variables to remove offset/limit and instead include orderBy
conditionally (variables: { creatorAddress: '0xCreator1', ...(orderBy && {
orderBy }) }) and change the hook invocation to call
useCreatorDisputedJobs('0xCreator1', orderByParam) so the test matches the hook
signature and query parameters.
request: { | ||
query: GET_JOBS, | ||
variables: { first: 10, skip: 0 }, | ||
}, | ||
result: { | ||
data: { | ||
jobs: [mockJob], | ||
}, | ||
}, | ||
}; | ||
|
||
export const mockUserQueryResponse: MockedResponse = { | ||
request: { | ||
query: GET_USER, | ||
variables: { address: mockUser.address }, | ||
}, | ||
result: { | ||
data: { | ||
user: mockUser, | ||
}, | ||
}, | ||
}; | ||
|
||
export const mockUsersQueryResponse: MockedResponse = { | ||
request: { | ||
query: GET_USERS, | ||
variables: { first: 10, skip: 0 }, | ||
}, | ||
result: { | ||
data: { | ||
users: [mockUser], | ||
}, | ||
}, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update mock variables to match new query signatures.
GET_JOBS
/ GET_USERS
now take $offset
and $limit
, but these mocks still declare { first, skip }
. Apollo’s mock matcher is strict; with the current shape it never finds a match, so any test using these responses will fall through to “no mock found”. Please switch the variable payloads to { offset: ..., limit: ... }
to align with the updated queries.
🤖 Prompt for AI Agents
In website/__tests__/setup/mocks/apollo.ts around lines 60 to 93, the mocked
request variable shapes for GET_JOBS and GET_USERS still use { first, skip }
which no longer match the queries; update those mocked request objects to use {
offset: 0, limit: 10 } (or equivalent values) for GET_JOBS and { offset: 0,
limit: 10 } for GET_USERS so the Apollo mock matcher finds the responses.
() => ({ | ||
data: data ? (data?.marketplaces[0] as any) : undefined, | ||
...rest, | ||
data: result.data ? (result.data?.marketplaces[0] as any) : undefined, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Replace as any
cast with proper typing.
Using as any
bypasses type safety. Consider defining a proper Marketplace type or importing it from the contracts package.
If a Marketplace type exists in @effectiveacceleration/contracts
or elsewhere in the codebase, import and use it:
+import type { Marketplace } from '@effectiveacceleration/contracts';
export default function useMarketplace() {
const [result] = useQuery({
query: GET_MARKETPLACES,
variables: {},
});
return useMemo(
() => ({
- data: result.data ? (result.data?.marketplaces[0] as any) : undefined,
+ data: result.data ? (result.data?.marketplaces[0] as Marketplace) : undefined,
loading: result.fetching,
error: result.error
}),
[result]
);
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
data: result.data ? (result.data?.marketplaces[0] as any) : undefined, | |
import type { Marketplace } from '@effectiveacceleration/contracts'; | |
export default function useMarketplace() { | |
const [result] = useQuery({ | |
query: GET_MARKETPLACES, | |
variables: {}, | |
}); | |
return useMemo( | |
() => ({ | |
data: result.data | |
? (result.data.marketplaces[0] as Marketplace) | |
: undefined, | |
loading: result.fetching, | |
error: result.error | |
}), | |
[result] | |
); | |
} |
🤖 Prompt for AI Agents
In website/src/hooks/subsquid/useMarketplace.tsx around line 13, the code casts
result.data?.marketplaces[0] to any which bypasses TypeScript safety; replace
the as any with a proper Marketplace type by importing Marketplace (or defining
an interface) from @effectiveacceleration/contracts (or the appropriate module),
use that type for the GraphQL query/result generics so result.data is typed
(e.g., QueryResult<{ marketplaces: Marketplace[] }>), update the hook/return
type to reflect Marketplace | undefined, and remove the as any cast so the
compiler enforces correct typing.
const [result] = useQuery({ | ||
query: GET_USER_JOB_NOTIFICATIONS, | ||
variables: { | ||
userAddress: userAddress ?? '', | ||
minTimestamp: minTimestamp ?? 0, | ||
offset: offset ?? 0, | ||
limit: limit ?? 10, | ||
}, | ||
skip: !userAddress || !jobIds.length, | ||
pause: !userAddress || !jobIds.length, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Restore jobIds
in the query variables.
We stop pausing once jobIds.length
is truthy, but the request never sends that array to Subsquid. URQL therefore issues the query with $jobIds
missing/null, so the jobId_in
filter is ignored and we end up pulling notifications for every job the user has. Please add jobIds
back into the variables
payload (e.g. jobIds,
or jobIds: jobIds.length ? jobIds : undefined
) before merging.
Apply this diff:
const [result] = useQuery({
query: GET_USER_JOB_NOTIFICATIONS,
variables: {
userAddress: userAddress ?? '',
+ jobIds,
minTimestamp: minTimestamp ?? 0,
offset: offset ?? 0,
limit: limit ?? 10,
},
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const [result] = useQuery({ | |
query: GET_USER_JOB_NOTIFICATIONS, | |
variables: { | |
userAddress: userAddress ?? '', | |
minTimestamp: minTimestamp ?? 0, | |
offset: offset ?? 0, | |
limit: limit ?? 10, | |
}, | |
skip: !userAddress || !jobIds.length, | |
pause: !userAddress || !jobIds.length, | |
}); | |
const [result] = useQuery({ | |
query: GET_USER_JOB_NOTIFICATIONS, | |
variables: { | |
userAddress: userAddress ?? '', | |
jobIds, | |
minTimestamp: minTimestamp ?? 0, | |
offset: offset ?? 0, | |
limit: limit ?? 10, | |
}, | |
pause: !userAddress || !jobIds.length, | |
}); |
🤖 Prompt for AI Agents
In website/src/hooks/subsquid/useUserJobNotifications.tsx around lines 13 to 22,
the query pauses until jobIds is truthy but the variables object omits jobIds,
causing the $jobIds parameter to be null and the jobId_in filter to be ignored;
add jobIds back into the variables payload (e.g. include jobIds, or jobIds:
jobIds.length ? jobIds : undefined) so the query sends the array when present
and omits it when empty.
- Upgrade multiple package dependencies including React, Next.js, and UI libraries - Fix Blob construction in useFetchAvatar and useMediaDownloadHandler hooks - Refactor Markdown components in job chat event displays - Update class names for consistent styling in message components
There was a problem hiding this 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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
website/src/hooks/useMediaDownloadHandler.ts (1)
9-16
: History.state manipulation may not work as intended.This code attempts to define
history.state
when it'snull
, but:
- Setting
writable: false
means this property cannot be changed later, which may break browser history functionality- Modern browsers manage
history.state
internally, and attempting to redefine it withObject.defineProperty
may not work or could cause unexpected behavior- The check
window.history.state === null
is fragileConsider removing this workaround or explaining why it's necessary. If this is to handle a specific browser issue, document it clearly.
♻️ Duplicate comments (2)
website/package.json (1)
82-87
: Restore Next.js and React to runtime dependencies.
next
,react
, andreact-dom
now live underdevDependencies
, so any production install (npm install --production
, Vercel, etc.) skips them and the app fails to build/run. Please move all three back into"dependencies"
and drop them from"devDependencies"
."tailwind-merge": "^3.3.1", - "tailwindcss-animate": "^1.0.7", - "urql": "^5.0.1", + "tailwindcss-animate": "^1.0.7", + "next": "^15.5.4", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "urql": "^5.0.1", ... - "next": "^15.5.4", ... - "react": "^19.2.0", - "react-dom": "^19.2.0",website/src/hooks/useMediaDownloadHandler.ts (1)
46-46
: Verify the necessity of accessing.buffer
.Same issue as in
useFetchAvatar.tsx
line 16: the Blob constructor accepts typed arrays directly, and theas ArrayBuffer
assertion is potentially unsafe if the property doesn't exist or isn't the expected type.See the verification script in the review comment for
website/src/hooks/useFetchAvatar.tsx
line 16.
🧹 Nitpick comments (4)
website/src/hooks/useFetchAvatar.tsx (2)
13-13
: Remove unsafe type assertion.The
as any
cast onsessionKey
bypasses type safety. Consider one of these approaches:
- Update
safeGetMediaFromIpfs
to acceptstring | undefined
- Use a proper type guard or conditional
- Document why the type assertion is necessary if it's intentional
16-16
: Simplify Blob constructor
Replacenew Blob([mediaBytes.buffer as ArrayBuffer], { type: mimeType })
withnew Blob([mediaBytes], { type: mimeType })
sinceUint8Array
is already anArrayBufferView
.website/src/hooks/useMediaDownloadHandler.ts (2)
61-61
: Avoid unsafe type assertion for event parameter.Passing
{} as any
bypasses type safety. Ifonhashchange
doesn't actually use the event parameter, consider:
- Checking if the parameter is optional and calling without arguments
- Creating a proper mock event object
- Refactoring to extract the hash-handling logic into a separate function
49-49
: Consider increasing timeout for URL cleanup.The 1-second timeout before revoking the blob URL may be insufficient for large files or slow downloads, potentially causing the download to fail.
Consider increasing the timeout to 5-10 seconds or using a more robust approach:
- setTimeout(() => URL.revokeObjectURL(url), 1000); + setTimeout(() => URL.revokeObjectURL(url), 5000);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
website/package-lock.json
is excluded by!**/package-lock.json
📒 Files selected for processing (8)
website/package.json
(1 hunks)website/src/app/jobs/[id]/JobChat/Events/DeliveredEvent.tsx
(1 hunks)website/src/app/jobs/[id]/JobChat/Events/OwnerMessageEvent.tsx
(1 hunks)website/src/app/jobs/[id]/JobChat/Events/WorkerMessageEvent.tsx
(1 hunks)website/src/app/jobs/[id]/JobChat/StatusStates/ResultAccepted.tsx
(1 hunks)website/src/app/jobs/[id]/JobChat/StatusStates/ResultVerification.tsx
(1 hunks)website/src/hooks/useFetchAvatar.tsx
(1 hunks)website/src/hooks/useMediaDownloadHandler.ts
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- website/src/app/jobs/[id]/JobChat/Events/WorkerMessageEvent.tsx
🔇 Additional comments (4)
website/src/app/jobs/[id]/JobChat/StatusStates/ResultVerification.tsx (1)
156-160
: LGTM! Styling successfully moved to container level.The relocation of text styling from the Markdown component to the wrapper div is correct and aligns with the broader UI consistency refactor across the codebase. Content rendering logic remains unchanged.
website/src/app/jobs/[id]/JobChat/StatusStates/ResultAccepted.tsx (1)
206-210
: LGTM! Consistent styling pattern applied.The styling relocation follows the same pattern as other components in this PR, moving typography classes to the container while preserving content rendering behavior.
website/src/app/jobs/[id]/JobChat/Events/OwnerMessageEvent.tsx (1)
139-143
: LGTM! Responsive styling correctly maintained.The styling relocation properly preserves responsive text sizing (
text-sm sm:text-base
) while moving other typography classes to the container level, consistent with the refactor pattern.website/src/app/jobs/[id]/JobChat/Events/DeliveredEvent.tsx (1)
116-120
: LGTM! Styling pattern consistently applied.The relocation of typography classes to the wrapper div, including responsive text sizing (
text-xs sm:text-sm
), maintains the original presentation while aligning with the broader UI refactor pattern across all message and status components.
- Remove @mui/material and @mui/icons-material packages - Replace MUI Rating component with custom star rating implementation - Remove MUI LinearProgress component - Replace MUI SvgIcon wrappers with direct SVG elements - Update package.json to reflect removed dependencies
There was a problem hiding this 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
🧹 Nitpick comments (3)
website/src/components/TokenSelector/icons/ExternalLinkIcon.tsx (1)
1-17
: Consider stronger typing for the props parameter.The
props: any
type reduces type safety. Consider usingReact.SVGProps<SVGSVGElement>
to enable proper autocomplete and type checking for SVG attributes.Apply this diff to improve type safety:
-export const ExternalLinkIcon = (props: any) => { +export const ExternalLinkIcon = (props: React.SVGProps<SVGSVGElement>) => { return (website/src/components/TokenSelector/icons/EthereumIcon.tsx (1)
1-30
: Consider stronger typing for the props parameter.The
props: any
type reduces type safety. Consider usingReact.SVGProps<SVGSVGElement>
to enable proper autocomplete and type checking for SVG attributes.Apply this diff to improve type safety:
-export const EthereumIcon = (props: any) => { +export const EthereumIcon = (props: React.SVGProps<SVGSVGElement>) => { return (website/src/components/TokenSelector/icons/PinIcon.tsx (1)
1-17
: Consider stronger typing for the props parameter.The
props: any
type reduces type safety. Consider usingReact.SVGProps<SVGSVGElement>
to enable proper autocomplete and type checking for SVG attributes.Apply this diff to improve type safety:
-export const PinIcon = (props: any) => { +export const PinIcon = (props: React.SVGProps<SVGSVGElement>) => { return (
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
website/package.json
(1 hunks)website/src/app/jobs/[id]/JobActions/ApproveButton.tsx
(2 hunks)website/src/app/jobs/[id]/JobChatDetails.tsx
(0 hunks)website/src/components/TokenSelector/icons/EthereumIcon.tsx
(1 hunks)website/src/components/TokenSelector/icons/ExternalLinkIcon.tsx
(1 hunks)website/src/components/TokenSelector/icons/PinIcon.tsx
(1 hunks)
💤 Files with no reviewable changes (1)
- website/src/app/jobs/[id]/JobChatDetails.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- website/package.json
🔇 Additional comments (1)
website/src/app/jobs/[id]/JobActions/ApproveButton.tsx (1)
12-12
: Verify react-icons compatibility in website/package.json
Ensure the installedreact-icons
version (inwebsite/package.json
) isn’t impacted by the v5.5.0 typing change (IconType → ReactNode); confirmApproveButton.tsx
compiles without JSX/TS errors.
<div className='flex gap-2'> | ||
{[1, 2, 3, 4, 5].map((value) => ( | ||
<button | ||
key={value} | ||
type='button' | ||
onClick={() => setRating(value)} | ||
onMouseEnter={(e) => { | ||
const stars = e.currentTarget.parentElement?.querySelectorAll('button'); | ||
stars?.forEach((star, idx) => { | ||
const icon = star.querySelector('svg'); | ||
if (idx < value && icon) { | ||
icon.classList.add('text-amber-500'); | ||
icon.classList.remove('text-gray-300'); | ||
} | ||
}); | ||
}} | ||
onMouseLeave={(e) => { | ||
const stars = e.currentTarget.parentElement?.querySelectorAll('button'); | ||
stars?.forEach((star, idx) => { | ||
const icon = star.querySelector('svg'); | ||
if (idx < rating && icon) { | ||
icon.classList.add('text-amber-400'); | ||
icon.classList.remove('text-gray-300', 'text-amber-500'); | ||
} else if (icon) { | ||
icon.classList.add('text-gray-300'); | ||
icon.classList.remove('text-amber-400', 'text-amber-500'); | ||
} | ||
}); | ||
}} | ||
className='transition-transform hover:scale-110' | ||
> | ||
{value <= rating ? ( | ||
<PiStarFill className='h-8 w-8 text-amber-400' /> | ||
) : ( | ||
<PiStar className='h-8 w-8 text-gray-300 dark:text-gray-600' /> | ||
)} | ||
</button> | ||
))} | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace direct DOM manipulation with React state.
The current implementation directly manipulates the DOM via classList
in event handlers, which violates React's declarative paradigm and creates several critical issues:
- State inconsistency: Visual state (classList) can diverge from React state during re-renders, causing flickers or lost hover effects.
- Race conditions: classList changes conflict with React's reconciliation, especially during rapid hover events.
- Fragile queries:
querySelector
/querySelectorAll
assumptions about DOM structure can break and return null (NPE risk). - Maintainability: Direct DOM manipulation makes the component harder to reason about and test.
Refactor to use React state for hover tracking:
export function ApproveButton({
address,
job,
...rest
}: ApproveButtonProps & React.ComponentPropsWithoutRef<'div'>) {
const Config = useConfig();
const [review, setReview] = useState<string>('');
const [rating, setRating] = useState<number>(0);
+ const [hoveredRating, setHoveredRating] = useState<number>(0);
const [isApproving, setIsApproving] = useState(false);
Then update the star rendering logic:
<div className='rounded-xl border border-gray-200 bg-gradient-to-br from-gray-50 to-gray-100 p-4 dark:border-gray-700 dark:from-gray-800/50 dark:to-gray-900/50'>
- <div className='flex gap-2'>
+ <div
+ className='flex gap-2'
+ onMouseLeave={() => setHoveredRating(0)}
+ >
{[1, 2, 3, 4, 5].map((value) => (
<button
key={value}
type='button'
onClick={() => setRating(value)}
- onMouseEnter={(e) => {
- const stars = e.currentTarget.parentElement?.querySelectorAll('button');
- stars?.forEach((star, idx) => {
- const icon = star.querySelector('svg');
- if (idx < value && icon) {
- icon.classList.add('text-amber-500');
- icon.classList.remove('text-gray-300');
- }
- });
- }}
- onMouseLeave={(e) => {
- const stars = e.currentTarget.parentElement?.querySelectorAll('button');
- stars?.forEach((star, idx) => {
- const icon = star.querySelector('svg');
- if (idx < rating && icon) {
- icon.classList.add('text-amber-400');
- icon.classList.remove('text-gray-300', 'text-amber-500');
- } else if (icon) {
- icon.classList.add('text-gray-300');
- icon.classList.remove('text-amber-400', 'text-amber-500');
- }
- });
- }}
+ onMouseEnter={() => setHoveredRating(value)}
className='transition-transform hover:scale-110'
>
- {value <= rating ? (
- <PiStarFill className='h-8 w-8 text-amber-400' />
+ {value <= (hoveredRating || rating) ? (
+ <PiStarFill
+ className={`h-8 w-8 ${
+ hoveredRating > 0 && value <= hoveredRating
+ ? 'text-amber-500'
+ : 'text-amber-400'
+ }`}
+ />
) : (
<PiStar className='h-8 w-8 text-gray-300 dark:text-gray-600' />
)}
</button>
))}
</div>
</div>
This approach:
- Uses
hoveredRating
state to track hover interactions declaratively - Removes all direct DOM manipulation
- Ensures visual state stays in sync with React state
- Eliminates NPE risks from querySelector
- Makes the component easier to test and maintain
- Removed @radix-ui/react-separator and @radix-ui/react-slider - Removed @urql/exchange-graphcache - Dependencies are no longer used in the project and can be safely removed to reduce bundle size
- Replace separate test workflows with single coverage workflow - Use matrix strategy to handle both packages - Update Node.js version to 22 - Handle different coverage file locations - Enable parallel coverage uploads to Coveralls - Add workflow completion step for Coveralls
- Removed conditional logic for running coverage commands - Standardized on `npm run test:coverage` for both packages - Reduced complexity in workflow step execution
The workflow now only runs on master branch pushes and pull requests. This change ensures Lighthouse tests are only triggered for the primary branch, avoiding duplicate checks on feature branches.
- Configure .solcover.js to skip specific contracts and directories - Migrate jest.config.ts to .js format with commonjs exports - Update @types/react dependencies to stable versions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
website/package.json (1)
78-79
: React must be in dependencies, not devDependencies.React and react-dom are currently in
devDependencies
, but Next.js requires them as runtime dependencies. This will break production builds whennpm install --production
is run (e.g., on Vercel or other deployment platforms), as these packages will be excluded.Move both packages to the
dependencies
section:+ "dependencies": { + ...existing dependencies... + "react": "^19.2.0", + "react-dom": "^19.2.0", + }, "devDependencies": { ... - "react": "^19.2.0", - "react-dom": "^19.2.0", ... }
🧹 Nitpick comments (1)
.github/workflows/lighthouse.yml (1)
24-34
: Optional: Consider usingdefaults.run.working-directory
for cleaner code.Each step currently changes to the
website
directory withcd website &&
. You could simplify this by adding a job-level default:jobs: lighthouse: runs-on: ubuntu-latest + defaults: + run: + working-directory: website steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '22' cache: 'npm' cache-dependency-path: website/package-lock.json - name: Install dependencies - run: cd website && npm ci + run: npm ci - name: Build site - run: cd website && npm run build + run: npm run build - name: Start server run: | - cd website npm start & npx wait-on http://localhost:3000 --timeout 60000
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
website/package-lock.json
is excluded by!**/package-lock.json
📒 Files selected for processing (8)
.github/dependabot.yml
(1 hunks).github/workflows/coverage.yml
(1 hunks).github/workflows/lighthouse.yml
(1 hunks)contract/.solcover.js
(1 hunks)contract/package.json
(1 hunks)website/jest.config.js
(1 hunks)website/lighthouserc.js
(1 hunks)website/package.json
(1 hunks)
✅ Files skipped from review due to trivial changes (3)
- .github/workflows/coverage.yml
- .github/dependabot.yml
- contract/.solcover.js
🔇 Additional comments (8)
.github/workflows/lighthouse.yml (1)
1-43
: LGTM! Lighthouse CI workflow is well-structured.The workflow correctly sets up the environment, builds the site, starts the server with a wait mechanism, and runs Lighthouse CI with the configuration file.
website/lighthouserc.js (1)
1-23
: LGTM! Lighthouse CI configuration is appropriate.The configuration uses reasonable thresholds and settings for CI environment. The 'warn' level for assertions won't fail the build but provides visibility into performance metrics.
website/jest.config.js (3)
1-6
: LGTM!The Next.js Jest integration follows the recommended pattern, enabling Next.js config and environment loading during tests.
31-34
: LGTM! Correct handling of ESM packages.The
transformIgnorePatterns
correctly allows Jest to transform wagmi, viem, and @TanStack packages, which are ESM-only modules that require transformation in the Jest environment.
37-38
: LGTM!The export pattern correctly uses
createJestConfig
to ensure Next.js async config loading is handled properly.website/package.json (3)
14-16
: LGTM!The test scripts are standard Jest patterns and properly integrate with the new
jest.config.js
configuration.
53-56
: Apollo → URQL migration complete
No remaining Apollo imports, requires,ApolloClient
, orApolloProvider
references detected.
78-79
: Verify and complete React 19 upgrade
- Upgrade bundler/Babel/TypeScript configs and frameworks (Next.js, Vite, CRA) to versions supporting React 19 and the new JSX runtime
- Run React 19 codemods (API removals/renames) and TypeScript codemods (e.g.,
npx types-react-codemod@latest preset-19 ./src
)- Replace ReactDOM.render/hydrate → createRoot/hydrateRoot (+ use
onUncaughtError
/onCaughtError
) and root.unmount()- Migrate legacy APIs: defaultProps on function components, childContextTypes/contextTypes, string refs → modern hooks/APIs
- Update error-reporting integrations to use window.reportError/console.error or
createRoot
error hooks; test Error Boundaries- Run full test suite in StrictMode; fix render-phase side effects, Suspense/use(...) patterns, TS signature errors
- Update all React-integrated dependencies (testing libraries, react-is, devtools, SSR frameworks) to React 19–compatible versions
// Don't fail on Chrome extensions or other issues | ||
skipAudits: ['uses-http2'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify the comment about skipped audits.
The comment mentions "Chrome extensions or other issues," but the uses-http2
audit specifically checks whether the server uses the HTTP/2 protocol, which is unrelated to Chrome extensions.
Apply this diff to clarify the comment:
settings: {
- // Don't fail on Chrome extensions or other issues
+ // Skip HTTP/2 audit for local testing
skipAudits: ['uses-http2'],
},
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
// Don't fail on Chrome extensions or other issues | |
skipAudits: ['uses-http2'], | |
settings: { | |
// Skip HTTP/2 audit for local testing | |
skipAudits: ['uses-http2'], | |
}, |
🤖 Prompt for AI Agents
In website/lighthouserc.js around lines 7 to 8, the existing comment "Don't fail
on Chrome extensions or other issues" is misleading for the skipAudits entry
since uses-http2 checks whether the server uses HTTP/2 (not Chrome extensions);
update the comment to explicitly state that the uses-http2 audit is being
skipped because the hosting or CI environment doesn't require/guarantee HTTP/2
(or similar rationale used in the project) so it doesn't fail the Lighthouse
run, leaving the skipAudits line intact.
"feed": "^5.1.0", | ||
"jest": "^30.2.0", | ||
"jest-environment-jsdom": "^30.2.0", | ||
"next": "^15.5.4", |
There was a problem hiding this comment.
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 Next.js 15 breaking changes and migration requirements.
Next.js 15 is a major version upgrade that typically includes breaking changes. Ensure all breaking changes have been addressed in the codebase.
🌐 Web query:
What are the breaking changes in Next.js 15 and what migration steps are required from Next.js 14?
💡 Result:
Short summary — main breaking changes in Next.js 15 and the migration steps from 14.
Breaking changes (highest-impact)
- Async Request APIs: request-scoped APIs that were synchronous now must be awaited (cookies, headers, draftMode, params/searchParams in pages/layouts/route handlers/generators). Synchronous access is temporarily warned but will be removed. [1][2]
- Caching semantics: fetch, GET Route Handlers, and client navigations are not cached by default (default behaves like no-store). You must explicitly opt into static/caching behavior (e.g., export const dynamic = 'force-static' or specify cache/stale options). [1][3]
- React minimum bumped: Next 15 targets React 19 — some React hooks changed (useFormState → useActionState, useFormStatus keys expanded). Upgrade React if you rely on those APIs. [2]
- Tooling/bundler changes (developer-facing): Turbopack is promoted (dev) and Turbopack/rspack configuration locations changed — check next.config updates if you depend on custom bundler config. [1]
Required migration steps (practical checklist)
- Read/prepare:
- Review the official Next.js 15 upgrade guide and release notes. [2][1]
- Upgrade packages:
- npm/yarn: npm i next@latest react@latest react-dom@latest eslint-config-next@latest (minimum React 19). [2]
- Run codemods:
- Run the Next 15 codemods to automate common changes:
npx @next/codemod@canary upgrade latest
npx @next/codemod@canary next-async-request-api .
These convert synchronous request-APIs to async and apply other automated fixes. [2][4]
- Run the Next 15 codemods to automate common changes:
- Fix async request-API usage:
- Replace synchronous calls with await (example: const cookieStore = await cookies();). Update any uses of headers(), cookies(), draftMode(), params/searchParams in page/layout/route/generator functions to be async. Ensure components that call them are async where needed. [1][3]
- Update caching behavior:
- Audit places relying on implicit caching (fetch, GET handlers, client navigations). Explicitly set caching/dynamic behavior:
- For route handlers/pages you want cached/static: export const dynamic = 'force-static' or use fetch cache options (cache: 'force-cache' / { next: { revalidate } } / set staleTimes as appropriate). For client data, set stale times or client-side caching explicitly. [1][3]
- Audit places relying on implicit caching (fetch, GET handlers, client navigations). Explicitly set caching/dynamic behavior:
- Address React hook changes & types:
- Replace deprecated React hooks (useFormState → useActionState) and update usages of useFormStatus to handle the new keys. Update @types/react/@types/react-dom if using TypeScript. [2]
- Adjust bundler/dev-server config if needed:
- If you relied on experimental.turbo or custom webpack config, move Turbopack settings to the new turbopack key in next.config.ts or follow guidance for Rspack plugin. Verify dev server behavior after upgrade. [1]
- Test thoroughly:
- Run unit/integration tests and manual QA for pages, route handlers, redirects, middleware, and any analytics/monitoring that run early (new client instrumentation hooks exist). Fix any runtime warnings about synchronous API usage. [1][2]
- Fallbacks & gradual migration:
- The docs note temporary synchronous access with warnings — you can migrate in stages, but remove warns and address async usage before the next major removal. Use the codemod output to find remaining manual edits. [3][2]
If you want, I can:
- run the async-request codemod locally and show example diffs for a sample file you paste, or
- search your repo for usages of cookies()/headers()/draftMode/params to produce a migration plan.
Sources:
- Next.js 15 release blog (breaking changes summary). [1]
- Next.js upgrade guide — Upgrading from 14 → 15 (codemods, React 19 notes). [2]
- Next.js 15 RC / migration details (async APIs, warnings, codemod command). [3]
References:
[1] Next.js blog — Next 15 release.
[2] Next.js docs — Upgrading: Version 15.
[3] Next.js blog — Next 15 RC notes (async request APIs and codemod).
Apply Next.js 15 migration codemods and fix breaking changes
- Run
npx @next/codemod@canary upgrade latest
andnpx @next/codemod@canary next-async-request-api .
- Convert synchronous request APIs (
cookies()
,headers()
,draftMode()
,params/searchParams
) toawait
in page/layout/route handlers - Explicitly configure caching/static behavior (e.g.
export const dynamic = 'force-static'
or fetchcache
options) - Upgrade to React 19+, update deprecated hooks (e.g.
useFormState
→useActionState
) - Move any custom bundler config under the new
turbopack
key innext.config.*
and verify dev server - Run full test suite and fix any runtime warnings
🤖 Prompt for AI Agents
In website/package.json around line 74 the Next.js dependency was bumped to
15.5.4 but the codebase hasn’t been migrated; run the Next 15 codemods (npx
@next/codemod@canary upgrade latest and npx @next/codemod@canary
next-async-request-api .), then update all uses of synchronous request APIs
(cookies(), headers(), draftMode(), params/searchParams) to await their async
versions in pages/layouts/routes, explicitly set component caching/static
behavior (e.g. export const dynamic = 'force-static' or use fetch cache
options), upgrade React to v19+ and replace deprecated hooks (e.g. useFormState
→ useActionState), move any custom bundler config under the new turbopack key in
next.config.* and verify dev server, and finally run the full test suite and fix
any runtime warnings.
- Configure mocha-junit-reporter for contract tests in CI - Set up jest-junit reporter for website tests - Update coverage scripts to create test-results directories - Add GitHub Actions step to publish test results - Ignore test-results directories in both packages
- Replace all Jest mocks with Vitest equivalents - Update test utilities and setup files - Configure Vitest with proper aliases and coverage settings - Remove Jest configuration and dependencies - Update package scripts to use Vitest commands
- Replace MockedProvider with custom URQL mock implementation - Remove redundant Apollo imports and ReactNode wrappers - Standardize mock query structure and wrapper creation - Update test assertions to match new mock data structure - Remove overly specific assertions that duplicated mock data - Fix localStorage mock implementation in useUserNotifications.test.tsx
- Update NextResponse mocks to properly handle text() and json() methods - Simplify hook tests by removing unnecessary loading state checks - Fix parameter handling in subsquid hooks tests - Update component tests to use direct prop passing instead of hooks - Improve urql mock client implementation for better query matching - Skip several tests that require complex mocking setups - Fix type mismatches in test data structures - Update test utility providers and wrappers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
♻️ Duplicate comments (2)
website/__tests__/lib/utils.test.ts (1)
66-68
: Test validates potentially incorrect behavior.This test expects
absoluteUrl('about')
to produce'https://example.comabout'
(no slash between domain and path), which validates the current implementation but is likely incorrect behavior as noted in the previous review.website/package.json (1)
83-84
: Move React and React-DOM to dependenciesNext.js requires React at runtime; production installs skip devDependencies.
In website/package.json:
"dependencies": { + "react": "^19.2.0", + "react-dom": "^19.2.0", }, "devDependencies": { - "react": "^19.2.0", - "react-dom": "^19.2.0",
🧹 Nitpick comments (18)
website/__tests__/lib/utils.test.ts (2)
71-149
: Expand test coverage for all event types.The test suite covers most
JobEventType
values but is missing tests for:
JobEventType.Signed
JobEventType.Rated
JobEventType.Refunded
JobEventType.ArbitrationRefused
Consider adding test cases for these event types to ensure complete coverage of the
EventTextMap
function.Add test cases for the missing event types:
it('should return correct text for Signed event', () => { expect(EventTextMap(JobEventType.Signed, '150')).toBe( 'Job #150 has been signed.' ); }); it('should return correct text for Rated event', () => { expect(EventTextMap(JobEventType.Rated, '250')).toBe( 'Job #250 has been rated.' ); }); it('should return correct text for Refunded event', () => { expect(EventTextMap(JobEventType.Refunded, '350')).toBe( 'Job #350 has been refunded.' ); }); it('should return correct text for ArbitrationRefused event', () => { expect(EventTextMap(JobEventType.ArbitrationRefused, '450')).toBe( 'Job #450 arbitration has been refused.' ); });
176-182
: Consider verifying error handling side effects.The test verifies that
isImageValid
returnsfalse
on fetch error, but doesn't verify that the error was logged to console or captured by Sentry (both called in the production code).Consider asserting the side effects to ensure complete error handling verification:
it('should return false on fetch error', async () => { (global.fetch as any).mockRejectedValue(new Error('Network error')); const consoleSpy = vi.spyOn(console, 'error').mockImplementation(); const result = await isImageValid('https://example.com/error.jpg'); expect(result).toBe(false); + expect(consoleSpy).toHaveBeenCalledWith( + 'Error checking image URL:', + expect.any(Error) + ); consoleSpy.mockRestore(); });Note: You may also want to mock
Sentry.captureException
to verify it was called with the error.website/__tests__/hooks/useConfig.test.ts (2)
1-5
: Remove unused import.The
afterEach
function is imported but never used in the test suite.Apply this diff to remove the unused import:
-import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest'; +import { vi, describe, it, expect, beforeEach } from 'vitest';
60-68
: Strengthen the assertion for the disconnected wallet scenario.When the wallet is not connected, the hook defaults to 'Arbitrum One' config (per the implementation). Consider verifying the specific config values rather than just checking if the result is defined.
Apply this diff to add a more specific assertion:
it('should return default config when wallet not connected', () => { (useWalletClient as any).mockReturnValue({ data: undefined, }); const { result } = renderHook(() => useConfig()); expect(result.current).toBeDefined(); + expect(result.current?.marketplaceAddress).toBe('0xArbitrumMarketplace'); });
website/__tests__/hooks/subsquid/useUsersByAddresses.test.tsx (1)
38-50
: LGTM! Test correctly handles async state updates.The test invokes the hook with the correct array parameter signature (
useUsersByAddresses(['0xUser1', '0xUser2'])
) and appropriately useswaitFor
to handle the hook's internal state updates. The comment explaining the async behavior is helpful.Consider adding more specific assertions to validate the returned user data structure:
await waitFor(() => { // useUsersByAddresses uses state and effects, so we need to wait for updates expect(result.current.data).toBeDefined(); + expect(result.current.data?.['0xUser1']).toEqual(mockUser1); + expect(result.current.data?.['0xUser2']).toEqual(mockUser2); });This would more thoroughly validate that the hook returns the expected user objects keyed by address.
website/__tests__/hooks/subsquid/useJobSearch.test.tsx (3)
1-4
: Remove unusedwaitFor
import.The test imports
waitFor
but never uses it (line 53 shows synchronous assertions only). This is a minor cleanup item.Apply this diff:
-import { renderHook, waitFor } from '@testing-library/react'; +import { renderHook } from '@testing-library/react';
6-19
: Consider using the sharedmockJob
from test mocks.The test defines a local
mockJob
object, but there's already a more comprehensivemockJob
exported fromwebsite/__tests__/setup/mocks/urql.tsx
(lines 69-89) that includes additional fields likechainId
,maxTime
,deliveryMethod
,timestamp
, andevents
. Using the shared mock improves consistency across tests and reduces duplication.Apply this diff:
+import { mockJob } from '../../setup/mocks/urql'; + -const mockJob = { - id: '1', - state: 0, - title: 'Search Result Job', - tags: ['digital-audio'], - content: 'Test content with search term', - roles: { - creator: '0xCreator', - worker: null, - arbitrator: '0xArbitrator', - }, - amount: '1000000', - token: '0xUSDC', -};If you need test-specific overrides, you can spread the shared mock:
const testJob = { ...mockJob, title: 'Search Result Job' };
41-57
: Expand test coverage for the hook.The test only validates the happy path with minimal assertions. Consider adding test cases for:
- Error handling when the query fails
- Different search criteria (tags, amounts, multiple filters)
- Verification of the returned data structure/content (currently only checks
data
is defined)- Edge cases like empty results or limit/offset behavior
Example additional test cases:
it('should return empty array for no matches', async () => { const emptyMocks = [{ query: GET_JOB_SEARCH({ search: 'state_eq: 999', orderBy: 'timestamp_ASC', limit: 100, offset: 0 }), variables: {}, data: { jobs: [] }, }]; const emptyWrapper = createUrqlWrapper(emptyMocks); const { result } = renderHook( () => useJobSearch({ jobSearch: { state: 999 }, orderBy: 'timestamp_ASC', limit: 100, offset: 0 }), { wrapper: emptyWrapper } ); expect(result.current.data).toEqual([]); expect(result.current.loading).toBe(false); }); it('should handle query errors', async () => { const errorMocks = [{ query: GET_JOB_SEARCH({ search: 'state_eq: 0', orderBy: 'timestamp_ASC', limit: 100, offset: 0 }), variables: {}, error: new Error('GraphQL error'), }]; const errorWrapper = createUrqlWrapper(errorMocks); const { result } = renderHook( () => useJobSearch({ jobSearch: { state: 0 }, orderBy: 'timestamp_ASC', limit: 100, offset: 0 }), { wrapper: errorWrapper } ); expect(result.current.error).toBeDefined(); expect(result.current.data).toBeUndefined(); });website/__tests__/pages/ConnectWallet.test.tsx (1)
22-70
: Consider accessibility-focused queries when enabling tests.When you enable these tests, consider using
getByRole
instead ofgetByText
for better accessibility coverage:// Instead of: expect(screen.getByText(/connect/i)).toBeInTheDocument(); // Use: expect(screen.getByRole('button', { name: /connect/i })).toBeInTheDocument();This ensures the interactive elements are properly exposed to assistive technologies.
website/__tests__/pages/PostJobPage.test.tsx (1)
31-110
: Improve test robustness when enabling.When you enable these tests, consider these improvements:
- Use more specific queries: Prefer
getByRole
overgetByLabelText
for better accessibility testing:// Instead of: screen.getByLabelText(/title/i) // Use: screen.getByRole('textbox', { name: /title/i })
Complete validation test (line 38): The test expects validation errors but only checks for one. Either add more validation checks or rename the test to be more specific.
Tag selection test (lines 69-80): Assumes specific tag text "digital audio" exists. Consider making this more resilient by checking for any tag selection mechanism.
website/__tests__/api/circulating_supply.test.ts (4)
15-35
: Consider simplifying the ethers mock structure.The mock duplicates the Contract and utility functions at both the
ethers.ethers
and top-level exports. If the API route only uses one import style, you could simplify this. However, this duplication is safe and ensures compatibility with both import patterns.
42-56
: Strengthen supply calculation assertions.The tests verify that the supply value is a number >= 0, but don't validate the actual calculation logic. Consider asserting against expected values based on the mocked balances:
it('should calculate correct circulating supply', async () => { const response = await GET(); const data = await response.text(); // Based on mocks: totalSupply (10000) - burnBalance (1000) = 9000 // (in actual tokens: 10000 - 1000 = 9000 tokens) const expectedSupply = 9000; expect(Number(data)).toBeCloseTo(expectedSupply, 1); });
58-67
: Caching test doesn't validate actual caching behavior.This test only verifies that two calls return the same value, which would be true even without caching (deterministic mock). To properly test caching:
- Track how many times the Contract methods are called
- Verify they're only called once despite multiple GET() calls
- Or test cache invalidation after a time period
it('should cache the result', async () => { const mockBalanceOf = vi.fn().mockResolvedValue(BigInt('1000000000000000000000')); vi.mocked(Contract).mockImplementation(() => ({ balanceOf: mockBalanceOf, totalSupply: vi.fn().mockResolvedValue(BigInt('10000000000000000000000')), })); await GET(); await GET(); // Verify contract methods called only once due to caching expect(mockBalanceOf).toHaveBeenCalledTimes(1); });
69-77
: Error handling test is incomplete.The test acknowledges it's incomplete (lines 70-71) and only checks that a response exists. To properly test error handling:
it('should handle errors gracefully', async () => { // Mock contract to throw error vi.mocked(Contract).mockImplementation(() => ({ balanceOf: vi.fn().mockRejectedValue(new Error('RPC error')), totalSupply: vi.fn().mockResolvedValue(BigInt('10000000000000000000000')), })); const response = await GET(); expect(response.status).toBe(500); const data = await response.text(); expect(data).toBeDefined(); });website/__tests__/hooks/subsquid/useArbitrators.test.tsx (1)
69-78
: Strengthen assertion for default limit test.The test only checks that the result is defined (line 76), which doesn't verify the default limit behavior. Since the hook converts
limit: 0
tolimit: 1000
(seeuseArbitrators.tsx
line 8), you should verify the returned data matches the mock configured for that limit:it('should use default limit when 0', () => { const { result } = renderHook( () => useArbitrators(0, 0), { wrapper } ); expect(result.current.loading).toBe(false); expect(result.current.data).toBeDefined(); expect(result.current.data?.length).toBe(2); // Based on mockArbitrators });website/__tests__/pages/TakeJobButton.test.tsx (1)
139-143
: Add missingaddress
prop for consistency.The test at line 139 omits the
address
prop that other tests include (e.g., lines 77, 88, 101, 126). While the component may work without it, inconsistent prop usage across tests can mask issues and reduce test reliability.Apply this diff:
- render(<TakeJobButton job={takenJob} />); + render(<TakeJobButton address="0xWorker" job={takenJob} events={mockEvents} />);Similarly, update line 158:
- render(<TakeJobButton job={jobWithCollateral} />); + render(<TakeJobButton address="0xWorker" job={jobWithCollateral} events={mockEvents} />);website/__tests__/api/market_cap.test.ts (1)
21-40
: Remove duplicate ethers mocking.The ethers library is mocked twice: once nested under
ethers.Contract
(lines 23-31) and again as direct exportsContract
,JsonRpcProvider
, etc. (lines 32-40). This duplication is confusing and unnecessary.Simplify to a single mock structure:
vi.mock('ethers', () => ({ - ethers: { - Contract: vi.fn().mockImplementation(() => ({ - totalSupply: vi.fn().mockResolvedValue(BigInt('10000000000000000000000')), - balanceOf: vi.fn().mockResolvedValue(BigInt('1000000000000000000000')), - })), - JsonRpcProvider: vi.fn(), - formatUnits: vi.fn((value) => (Number(value) / 1e18).toString()), - formatEther: vi.fn((value) => (Number(value) / 1e18).toString()), - parseEther: vi.fn((value) => BigInt(value) * BigInt(10 ** 18)), - }, Contract: vi.fn().mockImplementation(() => ({ totalSupply: vi.fn().mockResolvedValue(BigInt('10000000000000000000000')), balanceOf: vi.fn().mockResolvedValue(BigInt('1000000000000000000000')), })), JsonRpcProvider: vi.fn(), formatUnits: vi.fn((value) => (Number(value) / 1e18).toString()), formatEther: vi.fn((value) => (Number(value) / 1e18).toString()), parseEther: vi.fn((value) => BigInt(value) * BigInt(10 ** 18)), }));website/__tests__/setup/mocks/urql.tsx (1)
44-51
: Update misleading comment.The comment on line 44 says "Return empty data if no mock found", but the code actually returns an error. This discrepancy can confuse future maintainers.
Update the comment to match the implementation:
- // Return empty data if no mock found + // Return error if no mock found return fromValue({
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
website/package-lock.json
is excluded by!**/package-lock.json
📒 Files selected for processing (44)
README.md
(2 hunks)website/__tests__/api/circulating_supply.test.ts
(1 hunks)website/__tests__/api/market_cap.test.ts
(1 hunks)website/__tests__/api/total_supply.test.ts
(1 hunks)website/__tests__/components/Button.test.tsx
(1 hunks)website/__tests__/components/Input.test.tsx
(1 hunks)website/__tests__/components/JobsList.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useArbitrator.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useArbitrators.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useCreatorClosedJobs.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useCreatorCompletedJobs.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useCreatorDisputedJobs.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useCreatorOpenJobs.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useCreatorTakenJobs.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useJob.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useJobEvents.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useJobSearch.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useJobsByIds.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useMarketplace.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useReviews.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useSquidStatus.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useUser.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useUserNotifications.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useUsers.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useUsersByAddresses.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useWorkerApplications.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useWorkerCompletedJobs.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useWorkerDisputedJobs.test.tsx
(1 hunks)website/__tests__/hooks/subsquid/useWorkerTakenJobs.test.tsx
(1 hunks)website/__tests__/hooks/useConfig.test.ts
(1 hunks)website/__tests__/hooks/useDimensions.test.tsx
(1 hunks)website/__tests__/hooks/useToast.test.ts
(1 hunks)website/__tests__/integration/job-creation-flow.test.tsx
(1 hunks)website/__tests__/lib/utils.test.ts
(1 hunks)website/__tests__/pages/AcceptButton.test.tsx
(1 hunks)website/__tests__/pages/ConnectWallet.test.tsx
(1 hunks)website/__tests__/pages/DeliverResultButton.test.tsx
(1 hunks)website/__tests__/pages/PostJobPage.test.tsx
(1 hunks)website/__tests__/pages/TakeJobButton.test.tsx
(1 hunks)website/__tests__/setup/mocks/urql.tsx
(1 hunks)website/__tests__/setup/test-utils.tsx
(1 hunks)website/package.json
(1 hunks)website/vitest.config.ts
(1 hunks)website/vitest.setup.ts
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- website/tests/hooks/subsquid/useCreatorDisputedJobs.test.tsx
🚧 Files skipped from review as they are similar to previous changes (19)
- website/tests/hooks/subsquid/useSquidStatus.test.tsx
- website/tests/hooks/subsquid/useJob.test.tsx
- website/tests/hooks/subsquid/useReviews.test.tsx
- website/tests/hooks/subsquid/useJobsByIds.test.tsx
- website/tests/hooks/subsquid/useWorkerCompletedJobs.test.tsx
- website/tests/hooks/subsquid/useUser.test.tsx
- website/tests/hooks/subsquid/useJobEvents.test.tsx
- website/tests/pages/AcceptButton.test.tsx
- website/tests/hooks/subsquid/useCreatorTakenJobs.test.tsx
- website/tests/hooks/useToast.test.ts
- website/tests/hooks/subsquid/useWorkerApplications.test.tsx
- website/tests/hooks/subsquid/useWorkerDisputedJobs.test.tsx
- website/tests/hooks/useDimensions.test.tsx
- website/tests/components/Button.test.tsx
- website/tests/pages/DeliverResultButton.test.tsx
- website/tests/api/total_supply.test.ts
- website/tests/hooks/subsquid/useCreatorOpenJobs.test.tsx
- website/tests/hooks/subsquid/useUserNotifications.test.tsx
- website/tests/components/JobsList.test.tsx
🧰 Additional context used
🧬 Code graph analysis (14)
website/__tests__/hooks/subsquid/useArbitrator.test.tsx (3)
website/__tests__/setup/mocks/urql.tsx (1)
createUrqlWrapper
(61-67)website/src/hooks/subsquid/queries.ts (1)
GET_ARBITRATOR_BY_ADDRESS
(35-41)website/src/hooks/subsquid/useArbitrator.tsx (1)
useArbitrator
(11-38)
website/__tests__/hooks/subsquid/useArbitrators.test.tsx (3)
website/__tests__/setup/mocks/urql.tsx (2)
mockArbitrator
(101-108)createUrqlWrapper
(61-67)website/src/hooks/subsquid/queries.ts (1)
GET_ARBITRATORS
(27-33)website/src/hooks/subsquid/useArbitrators.tsx (1)
useArbitrators
(6-20)
website/__tests__/components/Input.test.tsx (1)
website/src/components/Input.tsx (1)
Input
(11-89)
website/__tests__/hooks/subsquid/useUsersByAddresses.test.tsx (3)
website/src/hooks/subsquid/queries.ts (1)
GET_USERS_BY_ADDRESSES
(108-114)website/__tests__/setup/mocks/urql.tsx (1)
createUrqlWrapper
(61-67)website/src/hooks/subsquid/useUsersByAddresses.tsx (1)
useUsersByAddresses
(13-47)
website/__tests__/hooks/subsquid/useUsers.test.tsx (3)
website/src/hooks/subsquid/queries.ts (1)
GET_USERS
(92-98)website/__tests__/setup/mocks/urql.tsx (1)
createUrqlWrapper
(61-67)website/src/hooks/subsquid/useUsers.tsx (1)
useUsers
(13-27)
website/__tests__/hooks/subsquid/useMarketplace.test.tsx (3)
website/src/hooks/subsquid/queries.ts (1)
GET_MARKETPLACES
(11-17)website/__tests__/setup/mocks/urql.tsx (1)
createUrqlWrapper
(61-67)website/src/hooks/subsquid/useMarketplace.tsx (1)
useMarketplace
(5-19)
website/__tests__/hooks/subsquid/useCreatorClosedJobs.test.tsx (3)
website/__tests__/setup/mocks/urql.tsx (2)
mockJob
(70-90)createUrqlWrapper
(61-67)website/src/hooks/subsquid/queries.ts (1)
GET_CREATOR_CLOSED_JOBS
(164-170)website/src/hooks/subsquid/useCreatorClosedJobs.tsx (1)
useCreatorClosedJobs
(7-24)
website/vitest.setup.ts (1)
website/__tests__/setup/mocks/contracts.ts (1)
mockConfig
(9-14)
website/__tests__/pages/TakeJobButton.test.tsx (2)
website/__tests__/setup/mocks/urql.tsx (1)
mockJob
(70-90)website/__tests__/setup/mocks/apollo.ts (1)
mockJob
(5-25)
website/__tests__/hooks/useConfig.test.ts (1)
website/src/hooks/useConfig.ts (1)
useConfig
(5-19)
website/__tests__/hooks/subsquid/useCreatorCompletedJobs.test.tsx (3)
website/__tests__/setup/mocks/urql.tsx (1)
createUrqlWrapper
(61-67)website/src/hooks/subsquid/queries.ts (1)
GET_CREATOR_COMPLETED_JOBS
(148-154)website/src/hooks/subsquid/useCreatorCompletedJobs.tsx (1)
useCreatorCompletedJobs
(7-24)
website/__tests__/hooks/subsquid/useJobSearch.test.tsx (3)
website/__tests__/setup/mocks/urql.tsx (2)
mockJob
(70-90)createUrqlWrapper
(61-67)website/src/hooks/subsquid/queries.ts (1)
GET_JOB_SEARCH
(172-190)website/src/hooks/subsquid/useJobSearch.tsx (1)
useJobSearch
(10-130)
website/__tests__/hooks/subsquid/useWorkerTakenJobs.test.tsx (2)
website/__tests__/setup/mocks/urql.tsx (2)
mockJob
(70-90)createUrqlWrapper
(61-67)website/src/hooks/subsquid/queries.ts (1)
GET_WORKER_TAKEN_JOBS
(207-213)
website/__tests__/lib/utils.test.ts (1)
website/src/lib/utils.ts (9)
cn
(7-9)formatDate
(10-17)absoluteUrl
(18-20)EventTextMap
(21-90)isImageValid
(92-102)shortenText
(104-124)convertToSeconds
(126-143)getUnitAndValueFromSeconds
(145-171)formatTimeLeft
(182-191)
🔇 Additional comments (36)
README.md (2)
3-7
: LGTM! Badges enhance project visibility.The badges provide useful at-a-glance information about the license, tech stack versions, test coverage, and PR review activity.
37-39
: LGTM! Star history provides useful growth metrics.The Star History chart is a standard addition that helps track the project's GitHub popularity over time.
website/__tests__/components/Input.test.tsx (5)
1-11
: LGTM! Test setup and basic rendering are well-structured.The imports and initial rendering test provide a solid foundation for the test suite.
13-21
: LGTM! User interaction test follows best practices.Using
user-event
for typing simulation provides realistic user interaction testing, and the assertion correctly verifies the input value.
23-37
: LGTM! Comprehensive type testing.The tests cover various input types efficiently using
rerender
, and the date type test ensures proper handling of date-specific inputs.
39-77
: LGTM! Thorough state and attribute testing.The tests comprehensively cover disabled state, custom styling, ref forwarding, event handling, and invalid state. The use of
vi.fn()
for onChange andReact.createRef()
for ref testing are appropriate.
79-118
: LGTM! Excellent HTML5 attribute coverage.The tests comprehensively verify support for standard HTML5 input attributes including min/max, required, maxLength, pattern, autoComplete, and autoFocus. The
toHaveFocus()
assertion for autoFocus is particularly appropriate.website/vitest.setup.ts (5)
1-25
: LGTM! Comprehensive wagmi mock for test environment.The wagmi mock provides safe defaults for all essential hooks and prevents ESM module resolution issues during testing. The passthrough providers and default hook returns ensure tests can run without real wallet connections.
27-31
: LGTM! RainbowKit mock is appropriate for test isolation.The mock provides passthrough for the RainbowKitProvider and stubs
getDefaultConfig
, allowing tests to run without full RainbowKit configuration.
33-52
: LGTM! Next.js navigation mocks cover essential routing.The mocks for
useRouter
,useSearchParams
, andusePathname
provide safe defaults that allow components using Next.js navigation to render and function in tests without actual routing.
54-86
: LGTM! Browser API mocks prevent jsdom compatibility issues.The mocks for
matchMedia
,IntersectionObserver
, andResizeObserver
provide the minimal implementations needed for jsdom, preventing "not defined" errors when components use these browser-specific APIs.
88-90
: LGTM! TextEncoder/TextDecoder shims enable encoding tests.Adding global
TextEncoder
andTextDecoder
ensures compatibility with code that uses these Web APIs for text encoding, which may not be available by default in the Node.js test environment.website/vitest.config.ts (3)
1-10
: LGTM! Vitest configuration is well-structured for React testing.The configuration correctly enables the React plugin, global test APIs, jsdom environment, and references the setup file for environment mocks.
11-24
: LGTM! Coverage and reporting configuration is comprehensive.The coverage setup uses the modern v8 provider with multiple output formats (text, lcov, html) and appropriate include/exclude patterns. The junit reporter with output file enables CI integration for test results.
26-31
: LGTM! Path aliases improve import ergonomics.The path aliases for
@
(src directory) and@/__tests__
(test utilities) provide cleaner imports and align with common project conventions.website/__tests__/hooks/subsquid/useCreatorCompletedJobs.test.tsx (2)
1-32
: LGTM! Test correctly uses URQL mocks.The test properly uses
createUrqlWrapper
for URQL-based testing (addressing the migration from Apollo). The mock structure matches theGET_CREATOR_COMPLETED_JOBS
query with correct variable names.
34-46
: LGTM! Test case correctly validates hook behavior.The test invokes the hook with the correct signature (
useCreatorCompletedJobs('0xCreator1')
) and validates that completed jobs (state: 3) are returned with appropriate loading state. The comment about synchronous mocks is helpful context.website/__tests__/hooks/subsquid/useMarketplace.test.tsx (2)
1-25
: LGTM! Mock setup correctly uses URQL.The test uses
createUrqlWrapper
for URQL-based testing (correctly migrated from Apollo). The mock structure matches theGET_MARKETPLACES
query and returns a single marketplace in an array, which aligns with the hook implementation that extractsmarketplaces[0]
.
27-38
: LGTM! Test validates marketplace stats retrieval.The test correctly invokes
useMarketplace()
with no arguments and validates that marketplace statistics are retrieved with the appropriate data structure and loading state.website/__tests__/hooks/subsquid/useUsersByAddresses.test.tsx (1)
1-36
: LGTM! Mock setup uses correct URQL wrapper and variable names.The test correctly uses
createUrqlWrapper
for URQL-based testing and properly names the query variableuserAddresses
(matching theGET_USERS_BY_ADDRESSES
query definition). This addresses the issues flagged in previous reviews.website/__tests__/hooks/subsquid/useWorkerTakenJobs.test.tsx (2)
1-31
: LGTM! Mock setup correctly uses URQL with proper variables.The test uses
createUrqlWrapper
for URQL-based testing and correctly provides onlyworkerAddress
as a variable (matching theGET_WORKER_TAKEN_JOBS
query definition). This addresses the issues with extra variables flagged in previous reviews.
33-45
: LGTM! Test validates worker taken jobs retrieval.The test correctly invokes the hook with a string parameter (
useWorkerTakenJobs('0xWorker1')
) and validates that taken jobs (state: 1) are returned with correct loading state and data structure.website/__tests__/hooks/subsquid/useArbitrator.test.tsx (4)
6-16
: LGTM! Comprehensive mock arbitrator.The mock arbitrator object includes all necessary fields for testing, including
address_
,publicKey
,fee
,settledCount
, andrefusedCount
. The field naming (address_
with underscore) correctly matches the GraphQL schema field name.
18-39
: LGTM! Well-structured mock scenarios.The mock setup covers both success and not-found cases, providing comprehensive test data for the different scenarios tested below.
41-69
: LGTM! Proper async testing with clear assertions.Both test cases correctly use
waitFor
to handle async state updates and verify the expected behavior for found and not-found scenarios.
71-79
: LGTM! Correct handling of empty address case.The test properly validates the hook's behavior when no address is provided, matching the implementation that immediately returns
null
data without making a query.website/__tests__/pages/ConnectWallet.test.tsx (1)
15-15
: Test suite is skipped.The entire test suite uses
describe.skip
, meaning these tests won't run. If the ConnectWallet component is ready for testing, remove the.skip
to enable the tests. If there are known issues preventing test execution, document them in a comment.Do you want me to help investigate why these tests are skipped, or open an issue to track enabling them?
website/__tests__/pages/PostJobPage.test.tsx (1)
22-22
: Test suite is skipped.The entire test suite uses
describe.skip
, meaning these tests won't run. Since this tests core job posting functionality, consider prioritizing enabling these tests or documenting the blockers.Do you want me to help investigate why these tests are skipped, or open an issue to track enabling them?
website/__tests__/api/circulating_supply.test.ts (1)
5-13
: LGTM! Functional NextResponse mock.The mock provides the essential methods (
text
,json
,status
,headers
) needed for these tests. The implementation correctly simulates the response interface.website/__tests__/hooks/subsquid/useArbitrators.test.tsx (2)
6-24
: Consider field name consistency.The local
mockArbitrator
usesfeePercentage
(line 9) while the shared mock inwebsite/__tests__/setup/mocks/urql.tsx
usesfee
(line 105). Verify which field name matches the actual GraphQL schema to ensure test accuracy.Additionally, consider reusing the shared
mockArbitrator
if the schema allows, to maintain consistency across tests:import { mockArbitrator } from '../../setup/mocks/urql';
41-67
: LGTM! Correct hook invocation and async testing.The tests now correctly use positional parameters
useArbitrators(0, 1000)
instead of the previously incorrect object syntax. The async testing withwaitFor
is properly implemented.website/__tests__/setup/test-utils.tsx (2)
10-15
: LGTM! Minimal but functional mock client.The mock URQL client provides a good baseline for tests that don't need specific data. Tests requiring custom responses can use
createUrqlWrapper
fromwebsite/__tests__/setup/mocks/urql.tsx
instead, which this utility complements nicely.
17-31
: LGTM! Well-structured custom render utility.The custom render function follows testing-library best practices by wrapping components with necessary providers. Re-exporting as
render
allows tests to import from this file and automatically get the URQL provider, reducing boilerplate.website/package.json (2)
13-16
: LGTM! Well-configured test scripts.The new test scripts provide good coverage for development workflows:
test
: Single run for CItest:watch
: Interactive developmenttest:coverage
: Coverage reporting with output directoryThis aligns well with the Vitest configuration added in this PR.
79-79
: ```bash
#!/bin/bashRe-run synchronous API usage checks, including .tsx files
echo "Checking for synchronous cookies() usage in TS/TSX files:"
rg -n -C2 -g '!node_modules/**' -g '.ts' -g '.tsx' '\bcookies()' | grep -v 'await cookies'echo -e "\nChecking for synchronous headers() usage in TS/TSX files:"
rg -n -C2 -g '!node_modules/**' -g '.ts' -g '.tsx' '\bheaders()' | grep -v 'await headers'echo -e "\nChecking for synchronous params access in exported route handlers:"
rg -n -C2 -g '!node_modules/**' -g '.ts' -g '.tsx' 'export function [A-Z].*(.*params:' | grep -v '^.*async'echo -e "\nChecking for deprecated React hooks:"
rg -n -C2 -g '!node_modules/**' -g '.ts' -g '.tsx' 'useFormState'</blockquote></details> <details> <summary>website/__tests__/hooks/subsquid/useUsers.test.tsx (1)</summary><blockquote> `49-59`: **LGTM!** The test correctly calls `useUsers(0, 1000)` with positional arguments matching the hook's signature, and properly verifies synchronous mock behavior with URQL. </blockquote></details> </blockquote></details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
import { renderHook, waitFor } from '@testing-library/react'; | ||
import useCreatorClosedJobs from '../../../src/hooks/subsquid/useCreatorClosedJobs'; | ||
import { GET_CREATOR_CLOSED_JOBS } from '../../../src/hooks/subsquid/queries'; | ||
import { createUrqlWrapper } from '../../setup/mocks/urql'; | ||
|
There was a problem hiding this comment.
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 query name and filter alignment.
In website/src/hooks/subsquid/queries.ts
(lines 163-169), the query is named GetCreatorDisputedJobs
but it's exported as GET_CREATOR_CLOSED_JOBS
and filters for state_eq: 2
with type__eq:7
. Please verify:
- Is state
2
the correct value for "closed" jobs (not "disputed")? - Should the query name be updated to match its actual purpose?
Run this script to check the query definition and verify the state values used across the codebase:
🏁 Script executed:
#!/bin/bash
# Check the query definition
echo "=== GET_CREATOR_CLOSED_JOBS query ==="
rg -A 5 "GET_CREATOR_CLOSED_JOBS = gql" website/src/hooks/subsquid/queries.ts
# Find all references to job states to understand the state enum
echo "=== Job state references ==="
rg "state_eq: \d+" website/src/hooks/subsquid/queries.ts
Length of output: 1258
🏁 Script executed:
#!/bin/bash
echo "=== Exported query constants in queries.ts ==="
rg -nP "^export const \w+" website/src/hooks/subsquid/queries.ts
echo "=== Queries mentioning 'disputed' ==="
rg -n "disputed" website/src/hooks/subsquid/queries.ts
Length of output: 1647
Fix GraphQL operation name for closed jobs.
In website/src/hooks/subsquid/queries.ts
, GET_CREATOR_CLOSED_JOBS
is declared as query GetCreatorDisputedJobs
but filters for closed jobs (state_eq: 2
). Rename the operation to GetCreatorClosedJobs
to align its name with its purpose and avoid conflicts with the disputed jobs query.
🤖 Prompt for AI Agents
In website/__tests__/hooks/subsquid/useCreatorClosedJobs.test.tsx lines 1-5, the
test imports GET_CREATOR_CLOSED_JOBS which in
website/src/hooks/subsquid/queries.ts is defined with the wrong GraphQL
operation name `query GetCreatorDisputedJobs` despite filtering for closed jobs;
update the operation name to `query GetCreatorClosedJobs` in the
GET_CREATOR_CLOSED_JOBS definition so the GraphQL operation name matches its
purpose and avoids conflicts with the disputed jobs query.
const mockJob = { | ||
id: '1', | ||
state: 4, | ||
title: 'Closed Job', | ||
roles: { | ||
creator: '0xCreator1', | ||
worker: null, | ||
arbitrator: '0xArbitrator', | ||
}, | ||
amount: '1000000', | ||
token: '0xUSDC', | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix state value to match query filter.
The mock job has state: 4
(line 8), but the GET_CREATOR_CLOSED_JOBS
query filters for state_eq: 2
. This mismatch will cause the test to pass with unrealistic data that wouldn't match the actual query results.
Update the mock to match the query's filter:
const mockJob = {
id: '1',
- state: 4,
+ state: 2,
title: 'Closed Job',
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const mockJob = { | |
id: '1', | |
state: 4, | |
title: 'Closed Job', | |
roles: { | |
creator: '0xCreator1', | |
worker: null, | |
arbitrator: '0xArbitrator', | |
}, | |
amount: '1000000', | |
token: '0xUSDC', | |
}; | |
const mockJob = { | |
id: '1', | |
state: 2, | |
title: 'Closed Job', | |
roles: { | |
creator: '0xCreator1', | |
worker: null, | |
arbitrator: '0xArbitrator', | |
}, | |
amount: '1000000', | |
token: '0xUSDC', | |
}; |
🤖 Prompt for AI Agents
In website/__tests__/hooks/subsquid/useCreatorClosedJobs.test.tsx around lines 6
to 17, the mockJob uses state: 4 but the GET_CREATOR_CLOSED_JOBS query filters
for state_eq: 2; update the mock to use state: 2 so the mocked data matches the
query filter (change state value from 4 to 2) and rerun the test.
useSearchParams: () => new URLSearchParams(), | ||
})); | ||
|
||
describe.skip('Job Creation Flow Integration', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enable the integration test suite.
The entire integration test suite is skipped with describe.skip
, preventing these important end-to-end tests from running in CI/CD.
Remove the .skip
to enable the tests:
-describe.skip('Job Creation Flow Integration', () => {
+describe('Job Creation Flow Integration', () => {
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
describe.skip('Job Creation Flow Integration', () => { | |
describe('Job Creation Flow Integration', () => { |
🤖 Prompt for AI Agents
In website/__tests__/integration/job-creation-flow.test.tsx around line 34, the
integration test suite is currently disabled using describe.skip which prevents
the tests from running; remove the .skip so the suite is executed (change
describe.skip to describe) and run the test suite locally/CI to ensure no
flakiness or required test updates before committing.
const PostJobPage = require('@/app/post-job/PostJobPage').default; | ||
render(<PostJobPage />); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Replace dynamic require with static import.
Using require('@/app/post-job/PostJobPage').default
bypasses static analysis and can cause issues with module mocking and tree-shaking. Static imports are more reliable and work better with TypeScript.
Add a static import at the top of the file:
+import PostJobPage from '@/app/post-job/PostJobPage';
+
/**
+ * Integration Test: Complete Job Creation Flow
Then replace the dynamic requires:
- const PostJobPage = require('@/app/post-job/PostJobPage').default;
render(<PostJobPage />);
Apply the same pattern at lines 135 and 163.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const PostJobPage = require('@/app/post-job/PostJobPage').default; | |
render(<PostJobPage />); | |
// At the top of website/__tests__/integration/job-creation-flow.test.tsx | |
import PostJobPage from '@/app/post-job/PostJobPage'; | |
/** | |
* Integration Test: Complete Job Creation Flow | |
* …rest of file header… | |
*/ | |
// …later in the file, replace the dynamic require: | |
render(<PostJobPage />); |
🤖 Prompt for AI Agents
In website/__tests__/integration/job-creation-flow.test.tsx around lines 57-58
(and also update occurrences at lines 135 and 163), replace the dynamic require
calls with static imports: add top-of-file imports like `import PostJobPage from
'@/app/post-job/PostJobPage';` (and the equivalent static imports for the
modules currently required at lines 135 and 163), then remove the
`require(...).default` usages and use the imported identifiers directly in the
render calls; ensure the import paths match the existing require paths and
update any TypeScript types if necessary.
readContract: vi.fn(), | ||
})); | ||
|
||
describe.skip('TakeJobButton', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enable the test suite.
The entire test suite is skipped with describe.skip
. This prevents these tests from running in CI/CD, reducing test coverage for the TakeJobButton
component.
Remove the .skip
to enable the tests:
-describe.skip('TakeJobButton', () => {
+describe('TakeJobButton', () => {
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
describe.skip('TakeJobButton', () => { | |
describe('TakeJobButton', () => { |
🤖 Prompt for AI Agents
In website/__tests__/pages/TakeJobButton.test.tsx around line 46, the test suite
is currently disabled using describe.skip which prevents tests from running;
remove the ".skip" so the suite reads describe('TakeJobButton', () => { and
ensure any tests inside are not individually skipped so the suite runs in CI/CD.
const executeQuery = vi.fn((request: any) => { | ||
const mock = mocks.find( | ||
(m) => { | ||
// Compare query by converting to string (handles DocumentNode comparison) | ||
const queryMatch = String(m.query) === String(request.query) || m.query === request.query; | ||
const variablesMatch = JSON.stringify(m.variables || {}) === JSON.stringify(request.variables || {}); | ||
return queryMatch && variablesMatch; | ||
} | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Query comparison may fail for complex DocumentNode objects.
Converting GraphQL queries to strings (line 18) for comparison can be unreliable. DocumentNode objects may have different serialization results despite being semantically identical, leading to false negatives in mock matching.
Consider using a more robust comparison approach:
const executeQuery = vi.fn((request: any) => {
const mock = mocks.find(
(m) => {
- // Compare query by converting to string (handles DocumentNode comparison)
- const queryMatch = String(m.query) === String(request.query) || m.query === request.query;
+ // Compare queries by their loc.source.body if available (GraphQL DocumentNode)
+ const mockQueryStr = m.query?.loc?.source?.body || String(m.query);
+ const reqQueryStr = request.query?.loc?.source?.body || String(request.query);
+ const queryMatch = mockQueryStr === reqQueryStr;
const variablesMatch = JSON.stringify(m.variables || {}) === JSON.stringify(request.variables || {});
return queryMatch && variablesMatch;
}
);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const executeQuery = vi.fn((request: any) => { | |
const mock = mocks.find( | |
(m) => { | |
// Compare query by converting to string (handles DocumentNode comparison) | |
const queryMatch = String(m.query) === String(request.query) || m.query === request.query; | |
const variablesMatch = JSON.stringify(m.variables || {}) === JSON.stringify(request.variables || {}); | |
return queryMatch && variablesMatch; | |
} | |
); | |
const executeQuery = vi.fn((request: any) => { | |
const mock = mocks.find( | |
(m) => { | |
// Compare queries by their loc.source.body if available (GraphQL DocumentNode) | |
const mockQueryStr = m.query?.loc?.source?.body || String(m.query); | |
const reqQueryStr = request.query?.loc?.source?.body || String(request.query); | |
const queryMatch = mockQueryStr === reqQueryStr; | |
const variablesMatch = JSON.stringify(m.variables || {}) === JSON.stringify(request.variables || {}); | |
return queryMatch && variablesMatch; | |
} | |
); |
🤖 Prompt for AI Agents
In website/__tests__/setup/mocks/urql.tsx around lines 14 to 22, comparing
GraphQL queries by String(m.query) is unreliable for DocumentNode ASTs; instead
normalize both queries before comparing by either importing and using graphql's
print() to serialize both ASTs consistently (compare print(m.query) ===
print(request.query)) or perform a structural AST deep-equality check (e.g.,
lodash.isEqual on m.query and request.query); update the comparison to use one
of these robust approaches and keep the existing variables JSON comparison.
Summary by CodeRabbit