Skip to content

Commit 6a7a7ef

Browse files
ci(release): publish latest release
1 parent 6fdb9e4 commit 6a7a7ef

1,036 files changed

Lines changed: 43209 additions & 23150 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.cursor/rules/writing-tests.mdc

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
---
2+
description:
3+
globs:
4+
alwaysApply: true
5+
---
6+
# Frontend Testing Strategy
7+
8+
When writing tests for our frontend monorepo, follow these principles:
9+
10+
## Core Philosophy
11+
- Test behaviors, not implementations
12+
- Optimize for confidence, readability, and maintainability
13+
- Follow the testing pyramid: unit tests > integration tests > E2E tests
14+
- Reference existing tests for examples of our team's best practices. For example: [useBooleanState.test.ts](mdc:packages/utilities/src/react/useBooleanState.test.ts) [useSwapNetworkNotification.test.ts](mdc:packages/uniswap/src/features/transactions/swap/form/hooks/useSwapNetworkNotification.test.ts)
15+
16+
## Test Structure & Patterns
17+
18+
### Unit Tests
19+
- Test individual functions, hooks, and components in isolation
20+
- Use Jest and React Testing Library/React Native Testing Library
21+
- Follow Arrange-Act-Assert pattern
22+
- Mock dependencies appropriately
23+
- Name tests descriptively: `it('should [behavior] when [condition]')`
24+
25+
```typescript
26+
// Component test example
27+
test('should display error when form submission fails', async () => {
28+
// Arrange
29+
const errorMessage = 'Invalid credentials';
30+
const mockSubmit = jest.fn().mockRejectedValue(new Error(errorMessage));
31+
render(<LoginForm onSubmit={mockSubmit} />);
32+
33+
// Act
34+
await userEvent.type(screen.getByLabelText(/email/i), 'user@example.com');
35+
await userEvent.type(screen.getByLabelText(/password/i), 'password123');
36+
await userEvent.click(screen.getByRole('button', { name: /login/i }));
37+
38+
// Assert
39+
expect(await screen.findByText(errorMessage)).toBeInTheDocument();
40+
expect(mockSubmit).toHaveBeenCalledWith({
41+
email: 'user@example.com',
42+
password: 'password123'
43+
});
44+
});
45+
46+
// Hook test example
47+
test('should increment counter when increment function is called', () => {
48+
// Arrange
49+
const { result } = renderHook(() => useCounter(0));
50+
51+
// Act
52+
act(() => {
53+
result.current.increment();
54+
});
55+
56+
// Assert
57+
expect(result.current.count).toBe(1);
58+
});
59+
```
60+
61+
### Integration Tests
62+
- Test interactions between multiple components
63+
- Focus on user workflows and component communication
64+
- Use React Testing Library's user-event
65+
- Minimize mocking to test actual integrations
66+
67+
## Best Practices
68+
69+
### Test Data Management
70+
- Create factory functions for generating test data
71+
- Use TypeScript to ensure test data matches expected interfaces
72+
73+
```typescript
74+
const createUser = (overrides = {}): User => ({
75+
id: uuid(),
76+
name: 'Test User',
77+
email: 'test@example.com',
78+
role: 'user',
79+
...overrides
80+
});
81+
```
82+
83+
### Mocking Strategy
84+
- Prefer manual mocks over automatic mocks
85+
- Mock at the boundary of your system (API calls, third-party services)
86+
- For React Native, mock native modules using Jest's mock functions
87+
88+
```typescript
89+
jest.mock('packages/uniswap/...', () => ({
90+
fetchUserData: jest.fn().mockResolvedValue({
91+
id: '123',
92+
name: 'Test User',
93+
email: 'test@example.com'
94+
})
95+
}));
96+
```
97+
98+
### Coverage Guidelines
99+
- Aim for 80% coverage overall, 90%+ for critical business logic
100+
- When requested to write UI tests, cover all user-facing components with at least basic rendering tests
101+
- Test error states and edge cases; when unceratin about these states and cases, stop and ask for clarification before continuing
102+
- Focus on quality over quantity - 5 well-written tests > 20 poor tests
103+
104+
## Monorepo Considerations
105+
- Use the same path import strategy found in other files; everything should pass linting
106+
- Respect the testing configuration of each package
107+
- For shared components, test in their own package, not in consuming packages
108+
109+
## Implementation Checklist
110+
111+
When implementing tests, verify:
112+
113+
1. ✅ Tests focus on component/function behavior
114+
2. ✅ Tests are isolated and don't depend on each other
115+
3. ✅ Mocks are used appropriately and documented
116+
4. ✅ Error states and edge cases are covered
117+
5. ✅ Tests are readable and maintainable
118+
6. ✅ Tests fail when they should (verify with temporary bug)
119+
7. ✅ Test file structure matches source code structure
120+
8. ✅ Import paths follow monorepo conventions

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @uniswap/web-admins

RELEASE

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,80 @@
1-
We are back with some new updates! Here’s the latest:
1+
IPFS hash of the deployment:
2+
- CIDv0: `QmeQNaiwpcq1CouKoDNgFD67b4rcw5YuLs3DSG1t5DLBxr`
3+
- CIDv1: `bafybeihov4kdcqzqfzh4p4n7o7o7z5p5xs3sdle6gc7zbfymyncoz24ma4`
24

3-
Search Improvements: Enjoy an improved search algorithm, with more relevant information. Recent history also now includes wallet search results.
5+
The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org).
6+
7+
You can also access the Uniswap Interface from an IPFS gateway.
8+
**BEWARE**: The Uniswap interface uses [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to remember your settings, such as which tokens you have imported.
9+
**You should always use an IPFS gateway that enforces origin separation**, or our hosted deployment of the latest release at [app.uniswap.org](https://app.uniswap.org).
10+
Your Uniswap settings are never remembered across different URLs.
11+
12+
IPFS gateways:
13+
- https://bafybeihov4kdcqzqfzh4p4n7o7o7z5p5xs3sdle6gc7zbfymyncoz24ma4.ipfs.dweb.link/
14+
- [ipfs://QmeQNaiwpcq1CouKoDNgFD67b4rcw5YuLs3DSG1t5DLBxr/](ipfs://QmeQNaiwpcq1CouKoDNgFD67b4rcw5YuLs3DSG1t5DLBxr/)
15+
16+
## 5.87.0 (2025-05-29)
17+
18+
19+
### Features
20+
21+
* **web:** change how we navigate to new TDP when tokens change (#20088) 3c515b3
22+
* **web:** clear text on search select (#19957) 519d18d
23+
* **web:** fiat offramp (#19241) 1654f80
24+
* **web:** fix language around swapping with passkey (#19805) cf90f72
25+
* **web:** react compiler on vite (#19825) fe989f5
26+
* **web:** remove EW view passphrase (#19640) fdc36d5
27+
* **web:** remove indicativeQuote endpoint in favor of quote w/ routingPreference.Fastest (#19982) c05ffb7
28+
* **web:** reworked connected no positions page (#20000) af0bf59
29+
* **web:** reworked disconnected your positions page (#19999) 3e56bb9
30+
* **web:** vite CSP injection (#19836) 7e16a6a
31+
32+
33+
### Bug Fixes
34+
35+
* **web:** [tdp] sort other chain balances (#20063) d032e9d
36+
* **web:** add submitting state to send form review modal (#20049) 112c892
37+
* **web:** bug in send form when sending Celo USDC (#20132) d7e717c
38+
* **web:** debugging csp error in production (#20058) 083c86c
39+
* **web:** fallback to currency info on testnet (#20120) 3ec79b7
40+
* **web:** handle 5792 v1 spec (#20097) 4df918c
41+
* **web:** handle errors in parseRestPosition function (#20062) 5de5253
42+
* **web:** make Range Bands indicator line more visible (#19891) 1aa70e1
43+
* **web:** make web logging synchronous (#20013) aa9d96c
44+
* **web:** pool index virtualized list dynamic heights (#20010) 70bee14
45+
* **web:** prevent extreme outliers from breaking Pool price history chart (#19914) 8cc189f
46+
* **web:** remove nfts from landing page (#20055) 28e7db8
47+
* **web:** removeFormatNumberOrString from web formatting (#20034) f06fefd
48+
* **web:** settings tooltips (#20059) 4406198
49+
* **web:** update max button border (#19981) c769943
50+
* **web:** update publishignore (#19864) ea21978
51+
* **web:** update search bar hover behavior (#19994) a7481ad
52+
* **web:** update unwrap TX on smart wallet accounts (#19954) 06f49bf
53+
* **web:** use current year for footer copy (#19939) 7c30ca8
54+
* **web:** vite storybook mock fix (#20012) e15b409
55+
* **web:** wrapped token issues in pool details page (#20085) b129d2a
56+
* **web): Revert "feat(web:** defer render of mini portfolio (#19442)" (#19958) 72ef6b8
57+
58+
59+
### Continuous Integration
60+
61+
* **web:** update sitemaps a6ea37d
62+
63+
64+
### Code Refactoring
65+
66+
* **web:** remove dialog component + content & customize limit error (#19911) 2331e94
67+
* **web:** rename dialogv2 -> dialog (#19912) 9fd421e
68+
69+
70+
### Tests
71+
72+
* **web:** fix Swap → should be able to swap token with FOT warning via TDP (#20024) 8fd03b5
73+
* **web:** migrate some TDP tests to playwright (#20087) 7e831d1
74+
* **web:** remove uniswapx cypress files (#19936) f057838
75+
* **web:** uniswapx test - activity (#19933) fb5a4c2
76+
* **web:** uniswapx test - cancel (#19929) 3502b54
77+
* **web:** uniswapx test - expired (#19928) a5cc4c1
78+
* **web:** uniswapx test (#19886) 32f8775
479

5-
Other changes:
680

7-
- Added haptics when repositioning favorited tokens and wallets
8-
- Improved token selector behavior, with more relevant network filtering, as well as an improved experience when flipping input and output.
9-
- Improvements to NFT spam detection
10-
- Various bug fixes and performance improvements

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
mobile/1.51.1
1+
web/5.87.0

apps/extension/.eslintrc.js

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const restrictedGlobals = require('confusing-browser-globals')
12
const rulesDirPlugin = require('eslint-plugin-rulesdir')
23
rulesDirPlugin.RULES_DIR = '../../packages/uniswap/eslint_rules'
34

@@ -24,7 +25,9 @@ module.exports = {
2425
ecmaVersion: 2018,
2526
sourceType: 'module',
2627
},
27-
rules: {},
28+
rules: {
29+
'rulesdir/i18n': 'error',
30+
},
2831
overrides: [
2932
{
3033
files: ['src/assets/index.ts', 'src/contentScript/index.tsx'],
@@ -44,20 +47,26 @@ module.exports = {
4447
},
4548
},
4649
{
47-
files: ['**/contentScript/injected.ts'],
50+
files: ['**/contentScript/**'],
4851
rules: {
4952
'no-restricted-syntax': [
5053
'error',
5154
{
5255
selector: 'CallExpression[callee.object.name="logger"][callee.property.name!=/^(debug)$/]',
5356
message:
54-
'Only logger.debug is allowed in this file. Please handle errors and info logs explicitly using ErrorLog and InfoLog message passing.',
57+
'Only `logger.debug` is allowed in the content scripts. Please handle errors logs explicitly using `ErrorLog` message passing via `logContentScriptError`.',
5558
},
5659
],
5760
},
5861
},
62+
{
63+
// We override this rule from the base config to allow access to `chrome`
64+
// in all Extension files except those in the `contentScript` folder.
65+
files: ['*.ts', '*.tsx'],
66+
excludedFiles: ['**/contentScript/**'],
67+
rules: {
68+
'no-restricted-globals': ['error'].concat(restrictedGlobals),
69+
},
70+
},
5971
],
60-
rules: {
61-
'rulesdir/i18n': 'error',
62-
},
6372
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
// Simple mock for expo-blur's BlurView
3+
// This is needed to avoid the Storybook Web compilation error related to `expo-blur`, something like:
4+
// Module parse failed: Unexpected token (29:12)
5+
// node_modules/expo-blur/build/BlurView.web.js 29:12
6+
// You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
7+
// We don't actually need to use `expo-blur` in the Web App, as we just use CSS; so, we can mock it out.
8+
9+
export const BlurView = (props) => <div {...props} />;
10+
11+
export default BlurView;

apps/extension/jest-setup.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,15 @@ globalThis.matchMedia =
4545

4646
require('react-native-reanimated').setUpTests()
4747

48-
global.chrome = chrome
48+
const MOCK_LANGUAGE = 'en-US'
49+
50+
global.chrome = {
51+
...chrome,
52+
i18n: {
53+
...global.chrome.i18n,
54+
getUILanguage: jest.fn().mockReturnValue(MOCK_LANGUAGE)
55+
}
56+
}
4957

5058
jest.mock('src/app/navigation/utils', () => ({
5159
useExtensionNavigation: () => ({
@@ -69,4 +77,3 @@ jest.mock('wallet/src/features/appearance/hooks', () => {
6977
useSelectedColorScheme: () => 'light',
7078
}
7179
})
72-

apps/extension/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"@uniswap/universal-router-sdk": "4.19.5",
2121
"@uniswap/v3-sdk": "3.25.2",
2222
"@uniswap/v4-sdk": "1.21.2",
23+
"confusing-browser-globals": "1.0.11",
2324
"dotenv-webpack": "8.0.1",
2425
"eslint-plugin-rulesdir": "0.2.2",
2526
"ethers": "5.7.2",
@@ -34,6 +35,7 @@
3435
"react-native-reanimated": "3.16.7",
3536
"react-native-svg": "15.10.1",
3637
"react-native-web": "0.19.13",
38+
"react-player": "2.16.0",
3739
"react-qr-code": "2.0.12",
3840
"react-redux": "8.0.5",
3941
"react-router-dom": "6.10.0",

0 commit comments

Comments
 (0)