Skip to content

Commit 6794b70

Browse files
committed
merge main
2 parents 2e677ea + 8e46b07 commit 6794b70

278 files changed

Lines changed: 11495 additions & 3676 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.

.agents/skills/e2e-test/SKILL.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ name: e2e-test
33
description:
44
Add and fix Detox E2E tests (smoke and regression) for MetaMask Mobile using
55
withFixtures, Page Objects, and tests/framework. Use when creating a new spec,
6-
fixing a failing E2E test, or adding page objects and selectors.
6+
fixing a failing E2E test, adding page objects and selectors, or adding
7+
MetaMetrics analytics expectations (analyticsExpectations).
78
---
89

910
# E2E Test Builder — Skill
@@ -44,6 +45,10 @@ Task → What do you need?
4445
│ → Open references/mocking.md (testSpecificMock, setupRemoteFeatureFlagsMock, setupMockRequest)
4546
│ → When writing the spec: open references/writing-tests.md
4647
48+
├─ MetaMetrics / Segment analytics assertions (`analyticsExpectations` on `withFixtures`)
49+
│ → Open [tests/docs/analytics-e2e.md](../../../tests/docs/analytics-e2e.md) (config shape, teardown order, presets under `tests/helpers/analytics/expectations/`, `runAnalyticsExpectations`)
50+
│ → When wiring a spec: still follow references/writing-tests.md for `withFixtures` usage
51+
4752
└─ Run tests, debug failures, or self-review
4853
→ Open references/running-tests.md (build check, detox commands, common failures, retry patterns)
4954
```
@@ -84,9 +89,10 @@ Step 5 → Iterate (fix → lint → run) until green
8489

8590
Documentation is split by **action**. Open only the reference that matches what you are doing.
8691

87-
| Action | File | When to open it |
88-
| --------------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
89-
| **Writing or updating a spec** | [references/writing-tests.md](references/writing-tests.md) | New spec file, spec structure, FixtureBuilder patterns, smoke/regression templates. |
90-
| **Page Objects and selectors** | [references/page-objects.md](references/page-objects.md) | Create or update POM classes, selector/testId conventions, Matchers/Gestures/Assertions API. |
91-
| **API and feature flag mocking** | [references/mocking.md](references/mocking.md) | testSpecificMock, setupRemoteFeatureFlagsMock, setupMockRequest, shared mock files. |
92-
| **Running tests, debugging, fixing failures** | [references/running-tests.md](references/running-tests.md) | Build check, detox run commands, lint/tsc, common failures table, retry patterns, iteration loop. |
92+
| Action | File | When to open it |
93+
| --------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
94+
| **Writing or updating a spec** | [references/writing-tests.md](references/writing-tests.md) | New spec file, spec structure, FixtureBuilder patterns, smoke/regression templates. |
95+
| **Page Objects and selectors** | [references/page-objects.md](references/page-objects.md) | Create or update POM classes, selector/testId conventions, Matchers/Gestures/Assertions API. |
96+
| **API and feature flag mocking** | [references/mocking.md](references/mocking.md) | testSpecificMock, setupRemoteFeatureFlagsMock, setupMockRequest, shared mock files. |
97+
| **MetaMetrics / analytics expectations** | [tests/docs/analytics-e2e.md](../../../tests/docs/analytics-e2e.md) | `analyticsExpectations` on `withFixtures`, declarative checks, presets in `tests/helpers/analytics/expectations/`. |
98+
| **Running tests, debugging, fixing failures** | [references/running-tests.md](references/running-tests.md) | Build check, detox run commands, lint/tsc, common failures table, retry patterns, iteration loop. |

.github/CODEOWNERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ app/components/UI/Perps/ @MetaMask/perps
168168
app/components/UI/WalletAction/*perps* @MetaMask/perps
169169
app/core/Engine/controllers/perps-controller @MetaMask/perps
170170
app/core/Engine/messengers/perps-controller-messenger @MetaMask/perps
171+
app/core/Engine/controllers/compliance/ @MetaMask/perps
172+
app/core/Engine/messengers/compliance/ @MetaMask/perps
171173
app/core/DeeplinkManager/Handlers/handlePerpsUrl.ts @MetaMask/perps
172174
app/core/AgenticService/ @MetaMask/perps
173175
**/Perps/** @MetaMask/perps

.github/actions/smart-e2e-selection/action.yml

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,13 @@ inputs:
3030
required: false
3131
default: 'false'
3232
base-ref:
33-
description: 'Base branch ref (must be main for analysis to run)'
33+
description: 'Base branch ref (must be main or release/* for analysis to run)'
3434
required: false
3535
default: ''
36+
is-draft:
37+
description: 'Whether the PR is a draft'
38+
required: false
39+
default: 'false'
3640

3741
outputs:
3842
ai_e2e_test_tags:
@@ -80,14 +84,14 @@ runs:
8084
git sparse-checkout disable
8185
git checkout HEAD -- .
8286
83-
- name: Fetch main branch for comparison
87+
- name: Fetch base branch for comparison
8488
if: steps.check-skip-label.outputs.SKIP != 'true'
8589
shell: bash
8690
run: |
8791
# Unshallow the repository first (if it's shallow)
8892
git fetch --unshallow 2>/dev/null || true
89-
# Fetch main branch for diff comparison
90-
git fetch origin main 2>/dev/null || true
93+
# Fetch the base branch for diff comparison (main or release/*)
94+
git fetch origin "${{ inputs.base-ref || 'main' }}" 2>/dev/null || true
9195
9296
- name: Setup Node.js
9397
if: steps.check-skip-label.outputs.SKIP != 'true'
@@ -131,6 +135,7 @@ runs:
131135
GITHUB_REPOSITORY: ${{ inputs.repository }}
132136
GITHUB_RUN_ID: ${{ github.run_id }}
133137
BASE_REF: ${{ inputs.base-ref }}
138+
IS_DRAFT: ${{ inputs.is-draft }}
134139
run: |
135140
echo "ai_e2e_test_tags=[\"ALL\"]" >> "$GITHUB_OUTPUT"
136141
echo "ai_confidence=0" >> "$GITHUB_OUTPUT"
@@ -142,14 +147,17 @@ runs:
142147
if [[ "$EVENT_NAME" != "pull_request" ]]; then
143148
SHOULD_SKIP=true
144149
SKIP_REASON="only runs on PRs"
145-
elif [[ "$BASE_REF" != "main" ]]; then
146-
SHOULD_SKIP=true
147-
SKIP_REASON="base branch is not main (base: $BASE_REF)"
148150
elif [[ -n "${{ steps.check-skip-label.outputs.SKIP }}" ]] && [[ "${{ steps.check-skip-label.outputs.SKIP }}" == "true" ]]; then
149151
SHOULD_SKIP=true
150152
SKIP_REASON="skip-smart-e2e-selection label found"
151153
FORCE_RUN=true
152154
echo "ai_confidence=100" >> "$GITHUB_OUTPUT"
155+
elif [[ "$IS_DRAFT" == "true" ]]; then
156+
SHOULD_SKIP=true
157+
SKIP_REASON="draft PR"
158+
elif [[ "$BASE_REF" != "main" && "$BASE_REF" != release/* ]]; then
159+
SHOULD_SKIP=true
160+
SKIP_REASON="base branch is not main or a release branch (base: $BASE_REF)"
153161
fi
154162
155163
# Export skip status, reason, and force run flag for downstream jobs
@@ -245,7 +253,7 @@ runs:
245253
fi
246254
247255
- name: Apply risk label to PR
248-
if: inputs.pr-number != '' && inputs.github-token != ''
256+
if: inputs.pr-number != '' && inputs.github-token != '' && inputs.is-draft != 'true' && (inputs.base-ref == 'main' || startsWith(inputs.base-ref, 'release/'))
249257
shell: bash
250258
env:
251259
GH_TOKEN: ${{ inputs.github-token }}

.github/scripts/e2e-smart-selection.mjs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const env = {
1111
PR_NUMBER: process.env.PR_NUMBER || '',
1212
GITHUB_OUTPUT: process.env.GITHUB_OUTPUT || '',
1313
GITHUB_STEP_SUMMARY: process.env.GITHUB_STEP_SUMMARY || '',
14+
BASE_REF: process.env.BASE_REF || 'main',
1415
};
1516

1617
const PR_COMMENT_FILE = 'pr_comment.md';
@@ -77,9 +78,11 @@ async function main() {
7778
return;
7879
}
7980

80-
// Build command - always uses origin/main as base (job only runs on PRs targeting main)
81-
const baseCmd = `node -r esbuild-register tests/tools/e2e-ai-analyzer --mode select-tags --pr ${env.PR_NUMBER}`;
82-
console.log(`🎯 Analyzing PR against origin/main`);
81+
// Build command - uses GitHub API (PR number) for changed files list; -b ensures
82+
// file diffs are computed against the correct base branch (main or release/*)
83+
const baseBranch = `origin/${env.BASE_REF}`;
84+
const baseCmd = `node -r esbuild-register tests/tools/e2e-ai-analyzer --mode select-tags --pr ${env.PR_NUMBER} -b ${baseBranch}`;
85+
console.log(`🎯 Analyzing PR #${env.PR_NUMBER} against base branch: ${baseBranch}`);
8386

8487
try {
8588
execSync(baseCmd, {

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@ jobs:
465465
repository: ${{ github.repository }}
466466
post-comment: 'true'
467467
base-ref: ${{ github.event.pull_request.base.ref }}
468+
is-draft: ${{ github.event.pull_request.draft }}
468469

469470
# Main E2E tests
470471

.github/workflows/nightly-build.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ jobs:
197197

198198
- name: Upload to TestFlight
199199
run: |
200+
# Group arg is required as positional placeholder for the 5th arg (distribute_external=false).
201+
# With distribute_external=false the build is uploaded but NOT distributed to external testers.
200202
bash scripts/upload-to-testflight.sh \
201203
"github_actions_main-rc" \
202204
"${{ github.ref_name }}" \

.yarn/patches/@metamask-assets-controllers-npm-100.2.1-4f7a0c8320.patch

Lines changed: 0 additions & 48 deletions
This file was deleted.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/**
2+
* Manual mock for @metamask/compliance-controller.
3+
*
4+
* The npm package is published but dist/ artifacts may not yet be available.
5+
* This mock provides the public API surface needed for tests and TypeScript
6+
* compilation within the mobile repo.
7+
*/
8+
9+
export class ComplianceService {
10+
readonly name = 'ComplianceService';
11+
}
12+
13+
export class ComplianceController {
14+
readonly name = 'ComplianceController';
15+
state: Record<string, unknown>;
16+
17+
constructor(args: Record<string, unknown>) {
18+
this.state = (args.state ?? {}) as Record<string, unknown>;
19+
}
20+
21+
async init(): Promise<void> {
22+
// noop
23+
}
24+
25+
async checkWalletCompliance(
26+
address: string,
27+
): Promise<{ address: string; blocked: boolean; checkedAt: string }> {
28+
return { address, blocked: false, checkedAt: new Date().toISOString() };
29+
}
30+
31+
async checkWalletsCompliance(
32+
addresses: string[],
33+
): Promise<{ address: string; blocked: boolean; checkedAt: string }[]> {
34+
return addresses.map((a) => ({
35+
address: a,
36+
blocked: false,
37+
checkedAt: new Date().toISOString(),
38+
}));
39+
}
40+
41+
async updateBlockedWallets(): Promise<{
42+
addresses: string[];
43+
sources: { ofac: number; remote: number };
44+
lastUpdated: string;
45+
fetchedAt: string;
46+
}> {
47+
return {
48+
addresses: [],
49+
sources: { ofac: 0, remote: 0 },
50+
lastUpdated: new Date().toISOString(),
51+
fetchedAt: new Date().toISOString(),
52+
};
53+
}
54+
55+
clearComplianceState(): void {
56+
// noop
57+
}
58+
}
59+
60+
export function getDefaultComplianceControllerState() {
61+
return {
62+
walletComplianceStatusMap: {},
63+
blockedWallets: null,
64+
blockedWalletsLastFetched: 0,
65+
lastCheckedAt: null,
66+
};
67+
}
68+
69+
export function selectIsWalletBlocked(address: string) {
70+
return (state: {
71+
blockedWallets?: { addresses: string[] } | null;
72+
walletComplianceStatusMap?: Record<
73+
string,
74+
{ blocked: boolean } | undefined
75+
>;
76+
}): boolean => {
77+
if (state.blockedWallets?.addresses.includes(address)) {
78+
return true;
79+
}
80+
return state.walletComplianceStatusMap?.[address]?.blocked ?? false;
81+
};
82+
}

0 commit comments

Comments
 (0)