Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/web-app/__mocks__/@reown-appkit-react.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
useAppKit: () => ({ open: () => {} }),
};
Comment on lines +1 to +3
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Inconsistent mock: use jest.fn() for testability.

This mock file returns open: () => {} (a no-op function), but app/web-app/jest.setup.js (line 13) mocks the same module with open: jest.fn(). Using jest.fn() allows tests to assert whether open was called and with what arguments.

Apply this diff:

 module.exports = {
-  useAppKit: () => ({ open: () => {} }),
+  useAppKit: () => ({ open: jest.fn() }),
 };

Note: Verify whether this __mocks__ file is actually loaded, as jest.setup.js may override it with a jest.mock() call.

📝 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.

Suggested change
module.exports = {
useAppKit: () => ({ open: () => {} }),
};
module.exports = {
useAppKit: () => ({ open: jest.fn() }),
};
🤖 Prompt for AI Agents
In app/web-app/__mocks__/@reown-appkit-react.js around lines 1 to 3, the mock
exports open as a plain no-op function which prevents tests from asserting
calls; replace open: () => {} with open: jest.fn() so tests can spy on
invocations, and confirm whether this manual __mocks__ file is actually used or
if app/web-app/jest.setup.js's jest.mock() overrides it.

9 changes: 9 additions & 0 deletions app/web-app/__mocks__/lucide-react.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const React = require('react');

// Return a simple SVG React component for any named export
module.exports = new Proxy({}, {
get: (_target, prop) => {
if (prop === '__esModule') return true;
return (props) => React.createElement('svg', { ...props, 'data-icon': String(prop) });
},
});
6 changes: 6 additions & 0 deletions app/web-app/e2e/home.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { test, expect } from '@playwright/test';

test('homepage shows brand', async ({ page }) => {
await page.goto('http://localhost:3000');
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Use baseURL from Playwright config instead of hardcoded URL.

The test uses a hardcoded http://localhost:3000 URL, which reduces portability across environments (CI, staging, different ports).

Add baseURL to your Playwright config at app/web-app/playwright.config.ts:

 export default defineConfig({
   testDir: './e2e',
+  use: {
+    baseURL: 'http://localhost:3000',
-  use: {
     headless: true,

Then update the test to use relative URLs:

-  await page.goto('http://localhost:3000');
+  await page.goto('/');
📝 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.

Suggested change
await page.goto('http://localhost:3000');
await page.goto('/');
🤖 Prompt for AI Agents
In app/web-app/e2e/home.spec.ts around line 4 the test uses a hardcoded URL
(await page.goto('http://localhost:3000')); — replace that with a relative path
(e.g., await page.goto('/')) and configure Playwright's baseURL in
app/web-app/playwright.config.ts (set baseURL to the appropriate root like
http://localhost:3000 for local/CI) so tests use baseURL + relative routes and
become portable across environments.

await expect(page.locator('text=FairFund')).toBeVisible();
});
18 changes: 18 additions & 0 deletions app/web-app/jest.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const nextJest = require('next/jest');

const createJestConfig = nextJest({ dir: './' });

const customJestConfig = {
roots: ['<rootDir>/src'],
setupFiles: ['<rootDir>/jest.mocks.js'],
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
moduleNameMapper: {
'\\.(css|less|scss|sass)$': 'identity-obj-proxy',
'^lucide-react(.*)$': '<rootDir>/__mocks__/lucide-react.js',
'^@reown/appkit/react$': '<rootDir>/__mocks__/@reown-appkit-react.js',
},
};

module.exports = createJestConfig(customJestConfig);

24 changes: 24 additions & 0 deletions app/web-app/jest.mocks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Mocks to run before modules are imported

// Mock wagmi hooks used in components
jest.mock('wagmi', () => ({
useAccount: () => ({ isConnected: false }),
useWalletClient: () => ({ data: null }),
useChainId: () => undefined,
}));

// Mock @reown/appkit react hook used for wallet modal
jest.mock('@reown/appkit/react', () => ({
useAppKit: () => ({ open: jest.fn() }),
}));
Comment on lines +11 to +13
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Duplicate mocking strategy for @reown/appkit/react.

This module is mocked here with jest.mock() and also mapped via moduleNameMapper in jest.config.cjs (line 13) to __mocks__/@reown-appkit-react.js. Having both mechanisms can cause confusion about which mock is active and makes the configuration harder to maintain.

Recommend consolidating to a single approach—either use jest.mock() in setupFiles OR use moduleNameMapper with __mocks__/ files, but not both for the same module.

Apply this diff to remove the duplicate mock (keep only moduleNameMapper):

-// Mock @reown/appkit react hook used for wallet modal
-jest.mock('@reown/appkit/react', () => ({
-  useAppKit: () => ({ open: jest.fn() }),
-}));
-
📝 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.

Suggested change
jest.mock('@reown/appkit/react', () => ({
useAppKit: () => ({ open: jest.fn() }),
}));
// (previous lines of setup...)
// jest.mock() removed - @reown/appkit/react is now mocked via moduleNameMapper in jest.config.cjs
🤖 Prompt for AI Agents
In app/web-app/jest.mocks.js around lines 11 to 13, there is a duplicate mock
for '@reown/appkit/react' created with jest.mock() while the same module is
already mapped to __mocks__/@reown-appkit-react.js via moduleNameMapper in
jest.config.cjs; remove the jest.mock(...) call from these lines so the mock is
resolved exclusively via moduleNameMapper/__mocks__, leaving any other unrelated
mocks intact and ensuring tests use the single canonical mock file.


// Mock lucide-react icons (ESM) to prevent ESM parsing issues in Jest
jest.mock('lucide-react', () => {
const React = require('react');
return new Proxy({}, {
get: (_target, prop) => {
if (prop === '__esModule') return true;
return (props) => React.createElement('svg', { ...props, 'data-icon': String(prop) });
},
});
});
Comment on lines +16 to +24
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Duplicate mocking strategy for lucide-react.

This module is mocked here with jest.mock() and also mapped via moduleNameMapper in jest.config.cjs (line 12) to __mocks__/lucide-react.js. This creates the same duplication issue as with @reown/appkit/react.

Consolidate to a single mocking approach to avoid confusion and potential conflicts.

Apply this diff to remove the duplicate mock (keep only moduleNameMapper):

-// Mock lucide-react icons (ESM) to prevent ESM parsing issues in Jest
-jest.mock('lucide-react', () => {
-  const React = require('react');
-  return new Proxy({}, {
-    get: (_target, prop) => {
-      if (prop === '__esModule') return true;
-      return (props) => React.createElement('svg', { ...props, 'data-icon': String(prop) });
-    },
-  });
-});
📝 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.

Suggested change
jest.mock('lucide-react', () => {
const React = require('react');
return new Proxy({}, {
get: (_target, prop) => {
if (prop === '__esModule') return true;
return (props) => React.createElement('svg', { ...props, 'data-icon': String(prop) });
},
});
});
🤖 Prompt for AI Agents
In app/web-app/jest.mocks.js around lines 16 to 24, there is a duplicate
jest.mock for 'lucide-react' that conflicts with the moduleNameMapper mapping to
__mocks__/lucide-react.js; remove the jest.mock block (lines 16–24) entirely so
the mock is provided only via moduleNameMapper and ensure no other code depends
on the removed inline mock.

25 changes: 25 additions & 0 deletions app/web-app/jest.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Setup file executed before tests to mock environment and modules
require('@testing-library/jest-dom');

// Mock wagmi hooks used in components
jest.mock('wagmi', () => ({
useAccount: () => ({ isConnected: false }),
useWalletClient: () => ({ data: null }),
useChainId: () => undefined,
}));

// Mock @reown/appkit react hook used for wallet modal
jest.mock('@reown/appkit/react', () => ({
useAppKit: () => ({ open: jest.fn() }),
}));

// Mock lucide-react icons (ESM) to prevent ESM parsing issues in Jest
jest.mock('lucide-react', () => {
const React = require('react');
return new Proxy({}, {
get: (_target, prop) => {
if (prop === '__esModule') return true;
return (props) => React.createElement('svg', { ...props, 'data-icon': String(prop) });
},
});
});
Comment on lines +17 to +25
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Duplicate mock: consolidate lucide-react mocking.

This Proxy-based lucide-react mock is identical to the one in app/web-app/__mocks__/lucide-react.js (lines 1-9). Duplicating mocks across setup files and __mocks__ directories creates maintenance burden and can cause confusion about which mock is active.

Recommended approach:

  1. Remove this jest.mock('lucide-react', ...) block (lines 17-25)
  2. Keep the manual mock in __mocks__/lucide-react.js
  3. Ensure Jest's config or auto-mocking loads the __mocks__ version

Jest automatically uses manual mocks from __mocks__/ when modules are imported, so the explicit jest.mock() call here may be redundant.

🤖 Prompt for AI Agents
In app/web-app/jest.setup.js around lines 17 to 25, remove the explicit
jest.mock('lucide-react', ...) Proxy-based mock because it duplicates the manual
mock already provided in app/web-app/__mocks__/lucide-react.js; delete the
entire jest.mock block, ensure the manual mock file remains in __mocks__, and
verify Jest configuration (moduleDirectories/automaticMocking) will pick up
manual mocks so tests continue using the single consolidated mock.

2 changes: 2 additions & 0 deletions app/web-app/jest.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import '@testing-library/jest-dom';

14 changes: 14 additions & 0 deletions app/web-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
"start": "next start",
"lint": "next lint",
"format": "prettier --write .",
"test": "jest --passWithNoTests",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"e2e": "playwright test",
"e2e:headed": "playwright test --headed",
"addMockSpaces": "ts-node --compiler-options '{\"module\":\"CommonJS\"}' src/mocks/add-spaces.ts",
"cleanDB": "ts-node --compiler-options '{\"module\":\"CommonJS\"}' src/mocks/remove.ts"
},
Expand Down Expand Up @@ -52,6 +57,15 @@
"zod": "^3.23.8"
},
"devDependencies": {
"@testing-library/jest-dom": "^6.0.1",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"@types/jest": "^29.5.3",
"jest-environment-jsdom": "^28.0.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
"ts-jest": "^29.1.0",
"@playwright/test": "^1.43.0",
Comment on lines +60 to +68
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n app/web-app/package.json | sed -n '55,75p'

Repository: StabilityNexus/FairFund

Length of output: 927


🌐 Web query:

jest-environment-jsdom jest 29 compatibility version

💡 Result:

Use the jest-environment-jsdom package that matches Jest 29 (i.e., any 29.x release). Jest 29’s environment package (jest-environment-jsdom@29.x) upgrades jsdom to v20, so install the 29.x variant:

npm install --save-dev jest@29 jest-environment-jsdom@29

Reference: Jest v29 upgrade notes (jest-environment-jsdom -> jsdom v20). [1][2]

Sources

  • Jest: Upgrading to Jest 29 (JSDOM upgrade). [1]
  • GitHub issue discussing jest-environment-jsdom@29 pulling jsdom v20. [2]

Version mismatch: upgrade jest-environment-jsdom to match Jest 29.

Line 64 specifies jest-environment-jsdom version ^28.0.0, but Jest is at version ^29.7.0 (line 66). Jest 29 requires jest-environment-jsdom@29, which upgrades jsdom to v20. Mismatched major versions can cause test environment failures and unexpected behavior.

Apply this diff:

     "@testing-library/react": "^14.0.0",
     "@testing-library/user-event": "^14.4.3",
     "@types/jest": "^29.5.3",
-    "jest-environment-jsdom": "^28.0.0",
+    "jest-environment-jsdom": "^29.7.0",
     "identity-obj-proxy": "^3.0.0",
     "jest": "^29.7.0",
📝 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.

Suggested change
"@testing-library/jest-dom": "^6.0.1",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"@types/jest": "^29.5.3",
"jest-environment-jsdom": "^28.0.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
"ts-jest": "^29.1.0",
"@playwright/test": "^1.43.0",
"@testing-library/jest-dom": "^6.0.1",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"@types/jest": "^29.5.3",
"jest-environment-jsdom": "^29.7.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
"ts-jest": "^29.1.0",
"@playwright/test": "^1.43.0",
🤖 Prompt for AI Agents
In app/web-app/package.json around lines 60 to 68, the jest-environment-jsdom
version is set to ^28.0.0 while jest is ^29.7.0; update jest-environment-jsdom
to a compatible ^29.x version to match Jest 29 (e.g., ^29.0.0) and then run
install/update (npm/yarn) to ensure jsdom v20 is pulled and lockfile is updated.

"@faker-js/faker": "^8.4.1",
"@types/node": "^20",
"@types/react": "^18",
Expand Down
16 changes: 16 additions & 0 deletions app/web-app/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { defineConfig } from '@playwright/test';

export default defineConfig({
testDir: './e2e',
use: {
headless: true,
viewport: { width: 1280, height: 720 },
actionTimeout: 0,
navigationTimeout: 30000,
},
Comment on lines +5 to +10
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Set a finite actionTimeout and add baseURL.

Line 8 sets actionTimeout: 0, which means actions wait indefinitely. This can cause tests to hang forever if an element never appears, making CI unreliable.

Apply this diff:

   use: {
     headless: true,
     viewport: { width: 1280, height: 720 },
-    actionTimeout: 0,
+    baseURL: 'http://localhost:3000',
+    actionTimeout: 10000,
     navigationTimeout: 30000,
   },

This sets a 10-second action timeout (adjust as needed) and adds baseURL so tests can use relative paths like page.goto('/').

🤖 Prompt for AI Agents
In app/web-app/playwright.config.ts around lines 5 to 10 the configuration sets
actionTimeout: 0 (infinite) and lacks a baseURL; change actionTimeout to a
finite value such as 10000 (10 seconds) to prevent tests from hanging and add a
baseURL (e.g., process.env.BASE_URL || 'http://localhost:3000') so tests can use
relative paths like page.goto('/'); update the export to use these values and
ensure any env var fallback is documented or set in CI.

webServer: {
command: 'npm run dev',
port: 3000,
reuseExistingServer: true,
}
});
15 changes: 15 additions & 0 deletions app/web-app/src/components/__tests__/navbar.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { render, screen } from '@testing-library/react';

// Mocks for next/navigation and next-auth
jest.mock('next/navigation', () => ({ usePathname: () => '/' }));
jest.mock('next-auth/react', () => ({ useSession: () => ({ data: null }) }));

import Navbar from '../navbar';

describe('Navbar', () => {
it('renders the brand', () => {
render(<Navbar />);
expect(screen.getByText(/FairFund/i)).toBeInTheDocument();
});
});