test: test Deployment and Tx Fee authorizations#2109
test: test Deployment and Tx Fee authorizations#2109stalniy merged 2 commits intoakash-network:mainfrom
Conversation
WalkthroughAdds ARIA labels and small JSX formatting changes, introduces Playwright page objects and new end-to-end authorization tests, updates test fixtures and wallet-extension popup handling (race between popup and extension page), refactors testing helpers, extracts an address-shortening helper, and increases some test timeouts. Changes
Sequence Diagram(s)sequenceDiagram
participant Test as Test Runner
participant Fixture as Fixture
participant LeapExt as LeapExt helper
participant AuthPage as AuthorizationsPage
participant App as Deploy Web App
participant Extension as Wallet Extension
Test->>Fixture: launch browser (clipboard perms), prepare context
Fixture->>LeapExt: construct LeapExt(context, page)
Test->>AuthPage: goto()
AuthPage->>App: click Grant (by label), fill grantee & limit, submit
App->>LeapExt: triggers wallet popup
alt popup via context event
LeapExt->>Extension: acceptTransaction(context) -> approve
else extension page resolved by id
Fixture->>Extension: getExtensionPage(extensionId) -> approve
end
Extension->>App: wallet approval confirmed
App->>AuthPage: update authorization list (uses shortenAddress)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (15)
🚧 Files skipped from review as they are similar to previous changes (9)
🧰 Additional context used📓 Path-based instructions (3)**/*.spec.{ts,tsx}📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)
Files:
**/*.{ts,tsx}📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
Files:
**/*.{js,ts,tsx}📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
Files:
🧠 Learnings (5)📓 Common learnings📚 Learning: 2025-10-15T16:39:55.348ZApplied to files:
📚 Learning: 2025-07-21T08:24:27.953ZApplied to files:
📚 Learning: 2025-10-31T11:26:42.138ZApplied to files:
📚 Learning: 2025-06-05T21:07:51.985ZApplied to files:
🧬 Code graph analysis (3)apps/deploy-web/tests/ui/disconnect-wallet.spec.ts (1)
apps/deploy-web/tests/ui/authorize-spending.spec.ts (6)
apps/deploy-web/tests/ui/fixture/context-with-extension.ts (3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
🔇 Additional comments (7)
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.
Actionable comments posted: 4
🧹 Nitpick comments (6)
apps/deploy-web/src/components/authorizations/GrantModal.tsx (1)
192-192: ARIA labels on inputs with existing label props.The
aria-labelattributes on these FormInput components duplicate the visiblelabelprop values. If FormInput properly associates the label with the input (via htmlFor), the aria-label is redundant since the label text already provides the accessible name. However, this is not harmful and may provide defensive accessibility if the label association isn't perfect.Also applies to: 204-204
apps/deploy-web/src/components/authorizations/AllowanceModal.tsx (1)
147-147: ARIA labels on inputs with existing label props.Similar to GrantModal.tsx, these
aria-labelattributes duplicate the visiblelabelprop values. While potentially redundant if FormInput properly associates labels with inputs, this provides defensive accessibility and maintains consistency with the other authorization modals.Also applies to: 159-159
apps/deploy-web/src/components/authorizations/Authorizations.tsx (2)
226-229: ARIA label duplicates visible button text.This button already has visible text content ("Authorize Spend"), which automatically provides the accessible name. The aria-label duplicates this visible text, making it redundant but not harmful. Consider removing the aria-label since the visible text is sufficient for accessibility.
338-349: ARIA label duplicates visible button text.Similar to the "Authorize Spend" button, this button has visible text content ("Authorize Fee Spend") that already provides an accessible name. The aria-label is redundant but not harmful.
apps/deploy-web/tests/ui/authorize-spending.spec.ts (2)
17-53: Consider restructuring to follow test guidelines.The current parametric test approach with
runAuthorizationTestis functional but doesn't align with the coding guidelines which specify:
- "Use
setupfunction instead ofbeforeEachin test files"- "
setupfunction must be at the bottom of the rootdescribeblock in test files"The current structure calls
setup()directly in each test rather than using abeforeEach-style pattern, and thesetupfunction is at module level rather than within adescribeblock.Consider this structure for better guideline compliance:
test.describe("Deployment Authorizations", () => { test("can authorize spending", async ({ page, context, extensionId }) => { test.setTimeout(5 * 60 * 1000); const { authorizationsPage, address } = setup({ page, context, extensionId }); const buttonLabel: AuthorizeButtonLabel = "Authorize Spend"; const listLabel: AuthorizationListLabel = "Deployment Authorization List"; await authorizationsPage.authorizeSpending(address, buttonLabel); const shortenedAddress = shortenAddress(address); const grantList = authorizationsPage.page.getByLabel(listLabel); await expect(grantList.locator("tr", { hasText: shortenedAddress })).toBeVisible(); }); // ... other tests function setup({ page, context, extensionId }: SetupProps) { // setup logic } });Alternatively, if you want to maintain the parametric approach, document why this pattern was chosen over the standard guidelines.
19-27: Test timeout set per test instead of using fixture configuration.The 5-minute timeout is set individually in each test case, but the fixture already configures this timeout (line 77 in context-with-extension.ts). This creates redundancy.
Consider removing the per-test timeout since the fixture already handles it:
test("can authorize spending", async ({ page, context, extensionId }) => { - test.setTimeout(5 * 60 * 1000); - const { authorizationsPage, address } = await setup({ page, context, extensionId, buttonLabel });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
apps/deploy-web/src/components/authorizations/AllowanceIssuedRow.tsx(1 hunks)apps/deploy-web/src/components/authorizations/AllowanceModal.tsx(2 hunks)apps/deploy-web/src/components/authorizations/Authorizations.tsx(2 hunks)apps/deploy-web/src/components/authorizations/DeploymentGrantTable.tsx(2 hunks)apps/deploy-web/src/components/authorizations/FeeGrantTable.tsx(1 hunks)apps/deploy-web/src/components/authorizations/GrantModal.tsx(2 hunks)apps/deploy-web/tests/ui/authorize-spending.spec.ts(1 hunks)apps/deploy-web/tests/ui/change-wallets.spec.ts(1 hunks)apps/deploy-web/tests/ui/disconnect-wallet.spec.ts(1 hunks)apps/deploy-web/tests/ui/fixture/context-with-extension.ts(2 hunks)apps/deploy-web/tests/ui/fixture/testing-helpers.ts(2 hunks)apps/deploy-web/tests/ui/pages/AuthorizationsPage.tsx(1 hunks)apps/deploy-web/tests/ui/pages/LeapExt.tsx(1 hunks)apps/deploy-web/tests/ui/uiState/isWalletConnected.ts(1 hunks)packages/ui/components/custom/address.tsx(2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
Never use type any or cast to type any. Always define the proper TypeScript types.
Files:
apps/deploy-web/src/components/authorizations/Authorizations.tsxapps/deploy-web/tests/ui/pages/LeapExt.tsxapps/deploy-web/tests/ui/fixture/testing-helpers.tsapps/deploy-web/src/components/authorizations/GrantModal.tsxpackages/ui/components/custom/address.tsxapps/deploy-web/tests/ui/change-wallets.spec.tsapps/deploy-web/src/components/authorizations/AllowanceIssuedRow.tsxapps/deploy-web/src/components/authorizations/FeeGrantTable.tsxapps/deploy-web/tests/ui/uiState/isWalletConnected.tsapps/deploy-web/tests/ui/disconnect-wallet.spec.tsapps/deploy-web/src/components/authorizations/AllowanceModal.tsxapps/deploy-web/src/components/authorizations/DeploymentGrantTable.tsxapps/deploy-web/tests/ui/pages/AuthorizationsPage.tsxapps/deploy-web/tests/ui/authorize-spending.spec.tsapps/deploy-web/tests/ui/fixture/context-with-extension.ts
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{js,ts,tsx}: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code
Files:
apps/deploy-web/src/components/authorizations/Authorizations.tsxapps/deploy-web/tests/ui/pages/LeapExt.tsxapps/deploy-web/tests/ui/fixture/testing-helpers.tsapps/deploy-web/src/components/authorizations/GrantModal.tsxpackages/ui/components/custom/address.tsxapps/deploy-web/tests/ui/change-wallets.spec.tsapps/deploy-web/src/components/authorizations/AllowanceIssuedRow.tsxapps/deploy-web/src/components/authorizations/FeeGrantTable.tsxapps/deploy-web/tests/ui/uiState/isWalletConnected.tsapps/deploy-web/tests/ui/disconnect-wallet.spec.tsapps/deploy-web/src/components/authorizations/AllowanceModal.tsxapps/deploy-web/src/components/authorizations/DeploymentGrantTable.tsxapps/deploy-web/tests/ui/pages/AuthorizationsPage.tsxapps/deploy-web/tests/ui/authorize-spending.spec.tsapps/deploy-web/tests/ui/fixture/context-with-extension.ts
**/*.spec.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)
Don't use
jest.mock()to mock dependencies in test files. Instead, usejest-mock-extendedto create mocks and pass mocks as dependencies to the service under test.
**/*.spec.{ts,tsx}: Usesetupfunction instead ofbeforeEachin test files
setupfunction must be at the bottom of the rootdescribeblock in test files
setupfunction creates an object under test and returns it
setupfunction should accept a single parameter with inline type definition
Don't use shared state insetupfunction
Don't specify return type ofsetupfunction
Files:
apps/deploy-web/tests/ui/change-wallets.spec.tsapps/deploy-web/tests/ui/disconnect-wallet.spec.tsapps/deploy-web/tests/ui/authorize-spending.spec.ts
🧠 Learnings (1)
📚 Learning: 2025-10-15T16:39:55.348Z
Learnt from: jzsfkzm
PR: akash-network/console#2039
File: apps/deploy-web/tests/ui/change-wallets.spec.ts:4-10
Timestamp: 2025-10-15T16:39:55.348Z
Learning: In the Akash Console E2E tests using the context-with-extension fixture, the first wallet is automatically created during fixture setup via `importWalletToLeap` in `apps/deploy-web/tests/ui/fixture/wallet-setup.ts`, so tests that call `frontPage.createWallet()` are creating a second wallet to test wallet switching functionality.
Applied to files:
apps/deploy-web/tests/ui/change-wallets.spec.tsapps/deploy-web/tests/ui/disconnect-wallet.spec.tsapps/deploy-web/tests/ui/authorize-spending.spec.ts
🧬 Code graph analysis (6)
apps/deploy-web/tests/ui/change-wallets.spec.ts (1)
apps/deploy-web/tests/ui/pages/LeapExt.tsx (1)
LeapExt(9-46)
apps/deploy-web/tests/ui/disconnect-wallet.spec.ts (1)
apps/deploy-web/tests/ui/pages/LeapExt.tsx (1)
LeapExt(9-46)
apps/deploy-web/src/components/authorizations/AllowanceModal.tsx (1)
packages/ui/components/input.tsx (1)
FormInput(123-123)
apps/deploy-web/tests/ui/pages/AuthorizationsPage.tsx (2)
apps/deploy-web/tests/ui/fixture/test-env.config.ts (1)
testEnvConfig(12-16)packages/ui/components/custom/address.tsx (1)
shortenAddress(11-13)
apps/deploy-web/tests/ui/authorize-spending.spec.ts (6)
apps/deploy-web/tests/ui/pages/AuthorizationsPage.tsx (3)
AuthorizeButtonLabel(6-6)AuthorizationListLabel(7-7)AuthorizationsPage(9-55)apps/deploy-web/tests/ui/fixture/context-with-extension.ts (2)
test(12-79)expect(81-81)packages/ui/components/custom/address.tsx (1)
shortenAddress(11-13)apps/deploy-web/tests/ui/pages/LeapExt.tsx (1)
LeapExt(9-46)apps/deploy-web/tests/ui/fixture/testing-helpers.ts (1)
clickCopyAddressButton(36-45)apps/deploy-web/tests/ui/fixture/wallet-setup.ts (1)
getExtensionPage(15-27)
apps/deploy-web/tests/ui/fixture/context-with-extension.ts (3)
apps/deploy-web/tests/ui/fixture/wallet-setup.ts (4)
getExtensionPage(15-27)setupWallet(29-34)connectWalletViaLeap(46-57)awaitWalletAndApprove(59-63)apps/deploy-web/tests/ui/fixture/base-test.ts (1)
injectUIConfig(16-25)apps/deploy-web/tests/ui/actions/selectChainNetwork.ts (1)
selectChainNetwork(6-20)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: test-build
- GitHub Check: test-build
- GitHub Check: Validate local packages
🔇 Additional comments (15)
apps/deploy-web/tests/ui/uiState/isWalletConnected.ts (1)
7-7: Document why 30s timeout is needed for authorization workflow.The timeout increase from 10s to 30s is intentional for your authorization workflow testing with wallet extensions. However, this is significantly longer than other wallet operations in the codebase (which use 20s max) and lacks explanation. Add a code comment clarifying why the extended timeout is necessary, or verify that this timeout is appropriate for your CI environment. Consider whether the 30s timeout addresses a real performance need or masks underlying test flakiness.
apps/deploy-web/src/components/authorizations/FeeGrantTable.tsx (1)
66-66: LGTM!Adding an aria-label to the Table component improves accessibility for screen reader users by providing context about the table's purpose.
apps/deploy-web/tests/ui/disconnect-wallet.spec.ts (1)
6-7: LGTM!The variable rename from
frontPagetoextensionbetter reflects that this is a LeapExt instance representing wallet extension interactions, improving code clarity.apps/deploy-web/tests/ui/change-wallets.spec.ts (1)
9-11: LGTM!Consistent with the refactoring in disconnect-wallet.spec.ts, the rename from
frontPagetoextensionimproves code clarity and naming consistency across the test suite.apps/deploy-web/src/components/authorizations/AllowanceIssuedRow.tsx (1)
56-59: LGTM!Adding aria-labels to these icon-only buttons is essential for accessibility. Screen reader users will now understand the purpose of these action buttons.
apps/deploy-web/src/components/authorizations/DeploymentGrantTable.tsx (2)
133-136: LGTM!Adding aria-labels to these icon-only Edit and Revoke buttons provides essential accessible names for screen reader users.
167-167: LGTM!The aria-label on the Table component improves accessibility by providing screen reader users with context about the table's purpose.
packages/ui/components/custom/address.tsx (1)
28-28: LGTM! Good refactor to use the centralized helper.The change correctly delegates address formatting to the new
shortenAddresshelper, maintaining consistent behavior while improving code reusability.apps/deploy-web/tests/ui/fixture/context-with-extension.ts (2)
30-31: LGTM! Clipboard permissions support the new test helpers.The addition of clipboard read/write permissions enables the
clickCopyAddressButtonhelper to read clipboard contents during tests.
46-78: LGTM! Appropriate fixture scope and timeout configuration.The tuple format correctly specifies
scope: "test"(isolated per test) and a 5-minute timeout, which is reasonable given the fixture performs wallet setup, network selection, and wallet connection. The fallback logic for non-functional networks is a good defensive measure.apps/deploy-web/tests/ui/fixture/testing-helpers.ts (2)
18-18: LGTM! Simplified by removing unnecessary intermediate await.The direct return of the fill operation is correct and more concise.
36-45: LGTM! Clipboard reading logic is correct.The helper properly handles the null case from
getCopyAddressButtonand uses the Playwright evaluate API to read clipboard contents.apps/deploy-web/tests/ui/authorize-spending.spec.ts (1)
62-77: Verify the setup creates a second wallet as intended.The
setupfunction callsextension.createWallet(extensionId)on line 65. Based on learnings, the first wallet is automatically created during fixture setup, so this creates a second wallet for authorization testing.Confirm this is intentional behavior - creating a second wallet to test authorizations between different wallet addresses. If so, consider adding a comment explaining this:
const setup = async ({ page, context, extensionId, buttonLabel }: SetupProps) => { const extension = new LeapExt(context, page); const address = await clickCopyAddressButton(await getExtensionPage(context, extensionId)); // Create a second wallet to test cross-wallet authorizations await extension.createWallet(extensionId); // ... rest of setup };Based on learnings
apps/deploy-web/tests/ui/pages/AuthorizationsPage.tsx (2)
6-7: LGTM! Clear type definitions for authorization UI elements.The string literal union types provide type safety and document the exact labels used in the UI.
32-40: Good use of shortenAddress for consistent address matching.The page object correctly uses
shortenAddress()to format addresses for UI element selection, ensuring consistency with how addresses are displayed in the authorization lists.
| async authorizeSpending(address: string, buttonLabel: AuthorizeButtonLabel) { | ||
| await this.page.getByLabel(buttonLabel).click(); | ||
| await this.page.getByLabel("Spending Limit").fill("5"); | ||
| await this.page.getByLabel("Grantee Address").fill(address); | ||
|
|
||
| this.context.on("page", this.acceptTransaction.bind(this)); | ||
| await this.clickGrantButton(); | ||
| } |
There was a problem hiding this comment.
Critical: Event listener won't be unregistered due to mismatched function references.
The same issue identified in LeapExt.tsx applies here. Each call to bind(this) creates a new function reference, so the listener registered on line 28 won't be properly removed by the off() call in acceptTransaction() (line 53).
Apply this diff to fix the binding issue:
export class AuthorizationsPage {
+ private boundAcceptTransaction?: () => Promise<void>;
+
constructor(
readonly context: Context,
readonly page: Page
) {}
// ... other methods
async authorizeSpending(address: string, buttonLabel: AuthorizeButtonLabel) {
await this.page.getByLabel(buttonLabel).click();
await this.page.getByLabel("Spending Limit").fill("5");
await this.page.getByLabel("Grantee Address").fill(address);
- this.context.on("page", this.acceptTransaction.bind(this));
+ this.boundAcceptTransaction = this.acceptTransaction.bind(this);
+ this.context.on("page", this.boundAcceptTransaction);
await this.clickGrantButton();
}
async editSpending(address: string, listLabel: AuthorizationListLabel) {
const shortenedAddress = shortenAddress(address);
await this.page.getByLabel(listLabel).locator("tr", { hasText: shortenedAddress }).getByLabel("Edit Authorization").click();
await this.page.getByLabel("Spending Limit").fill("10");
- this.context.on("page", this.acceptTransaction.bind(this));
+ this.boundAcceptTransaction = this.acceptTransaction.bind(this);
+ this.context.on("page", this.boundAcceptTransaction);
await this.clickGrantButton();
}
async revokeSpending(address: string, listLabel: AuthorizationListLabel) {
const shortenedAddress = shortenAddress(address);
await this.page.getByLabel(listLabel).locator("tr", { hasText: shortenedAddress }).getByLabel("Revoke Authorization").click();
- this.context.on("page", this.acceptTransaction.bind(this));
+ this.boundAcceptTransaction = this.acceptTransaction.bind(this);
+ this.context.on("page", this.boundAcceptTransaction);
await this.page.getByTestId("confirm-button").click();
}
async acceptTransaction() {
await this.page.waitForLoadState("domcontentloaded");
await this.page.getByTestId("btn-connect-wallet").click();
- this.context.off("page", this.acceptTransaction.bind(this));
+ if (this.boundAcceptTransaction) {
+ this.context.off("page", this.boundAcceptTransaction);
+ this.boundAcceptTransaction = undefined;
+ }
}
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In apps/deploy-web/tests/ui/pages/AuthorizationsPage.tsx around lines 23 to 30,
the event listener is registered with this.acceptTransaction.bind(this) which
creates a new function reference and prevents removal later; create a persistent
bound handler (e.g., store const boundAcceptTransaction =
this.acceptTransaction.bind(this) in a local variable or class property) and use
that same boundAcceptTransaction when calling this.context.on(...) and ensure
acceptTransaction() uses this.context.off(boundAcceptTransaction) to unregister
the exact same reference.
| async acceptTransaction() { | ||
| await this.page.waitForLoadState("domcontentloaded"); | ||
| await this.page.getByTestId("btn-connect-wallet").click(); | ||
| this.context.off("page", this.acceptTransaction.bind(this)); | ||
| } |
There was a problem hiding this comment.
Critical: Event listener won't be unregistered due to mismatched function references.
Each call to bind(this) creates a new function reference. When you register the listener with this.context.on("page", this.acceptTransaction.bind(this)) and then try to unregister with this.context.off("page", this.acceptTransaction.bind(this)), you're using different function references, so the listener remains attached.
Apply this diff to fix the binding issue:
+ private boundAcceptTransaction?: () => Promise<void>;
+
async acceptTransaction() {
await this.page.waitForLoadState("domcontentloaded");
await this.page.getByTestId("btn-connect-wallet").click();
- this.context.off("page", this.acceptTransaction.bind(this));
+ if (this.boundAcceptTransaction) {
+ this.context.off("page", this.boundAcceptTransaction);
+ this.boundAcceptTransaction = undefined;
+ }
}Then when registering the listener (where this method is called from), use:
this.boundAcceptTransaction = this.acceptTransaction.bind(this);
this.context.on("page", this.boundAcceptTransaction);Note: I see this same pattern is used in AuthorizationsPage.tsx. The same fix is needed there as well.
🤖 Prompt for AI Agents
In apps/deploy-web/tests/ui/pages/LeapExt.tsx around lines 41 to 45, the
off("page", this.acceptTransaction.bind(this)) call uses a different function
reference than the one passed to on(), so the listener is never removed; fix by
creating and using a stored bound function: add an instance property (e.g.,
this.boundAcceptTransaction = this.acceptTransaction.bind(this)) where the
listener is registered and use this.context.on("page",
this.boundAcceptTransaction) and here replace the off call with
this.context.off("page", this.boundAcceptTransaction); apply the same pattern to
AuthorizationsPage.tsx where the same bind/unbind mistake exists.
| export const shortenAddress = (address: string) => { | ||
| return [address?.slice(0, 8), "...", address?.slice(address?.length - 5)].join(""); | ||
| }; |
There was a problem hiding this comment.
Guard against null/undefined address values.
The optional chaining on address?.slice() will return undefined if address is null/undefined, but the join("") will still execute, producing output like "undefined...undefined". Consider adding an early return or guard condition.
Apply this diff to handle null/undefined addresses:
export const shortenAddress = (address: string) => {
+ if (!address) return "";
return [address?.slice(0, 8), "...", address?.slice(address?.length - 5)].join("");
};Alternatively, remove the optional chaining if the function expects a valid string:
-export const shortenAddress = (address: string) => {
- return [address?.slice(0, 8), "...", address?.slice(address?.length - 5)].join("");
+export const shortenAddress = (address: string): string => {
+ return `${address.slice(0, 8)}...${address.slice(-5)}`;
};📝 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 const shortenAddress = (address: string) => { | |
| return [address?.slice(0, 8), "...", address?.slice(address?.length - 5)].join(""); | |
| }; | |
| export const shortenAddress = (address: string): string => { | |
| return `${address.slice(0, 8)}...${address.slice(-5)}`; | |
| }; |
🤖 Prompt for AI Agents
In packages/ui/components/custom/address.tsx around lines 11 to 13, the
shortenAddress function uses optional chaining on address.slice which yields
"undefined...undefined" when address is null/undefined; add an early guard that
returns an empty string (or the original value) when address is falsy, or
explicitly throw/validate if a string is required, then remove the optional
chaining and safely call slice on the confirmed string so join("") cannot
produce "undefined" parts.
There was a problem hiding this comment.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
apps/deploy-web/src/components/authorizations/AllowanceModal.tsx
Outdated
Show resolved
Hide resolved
apps/deploy-web/src/components/authorizations/AllowanceModal.tsx
Outdated
Show resolved
Hide resolved
apps/deploy-web/src/components/authorizations/Authorizations.tsx
Outdated
Show resolved
Hide resolved
apps/deploy-web/src/components/authorizations/Authorizations.tsx
Outdated
Show resolved
Hide resolved
| export const shortenAddress = (address: string) => { | ||
| return [address?.slice(0, 8), "...", address?.slice(address?.length - 5)].join(""); | ||
| }; |
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
packages/ui/components/custom/address.tsx (1)
11-13: Add guard for null/undefined address values (unresolved from past review).The function signature expects a valid string, but there's no runtime validation. A previous review suggested adding a guard condition, and a maintainer agreed it should be applied. The change from optional chaining indicates an intent to require valid strings, but without a guard, null/undefined values will cause runtime errors.
Apply this diff to add proper validation:
-export const shortenAddress = (address: string) => { - return `${address.slice(0, 8)}...${address.slice(-5)}`; +export const shortenAddress = (address: string): string => { + if (!address) return ""; + return `${address.slice(0, 8)}...${address.slice(-5)}`; };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
apps/deploy-web/src/components/authorizations/Authorizations.tsx(1 hunks)apps/deploy-web/tests/ui/authorize-spending.spec.ts(1 hunks)apps/deploy-web/tests/ui/fixture/context-with-extension.ts(2 hunks)apps/deploy-web/tests/ui/fixture/testing-helpers.ts(2 hunks)apps/deploy-web/tests/ui/fixture/wallet-setup.ts(1 hunks)apps/deploy-web/tests/ui/pages/AuthorizationsPage.tsx(1 hunks)apps/deploy-web/tests/ui/pages/LeapExt.tsx(2 hunks)packages/ui/components/custom/address.tsx(2 hunks)packages/ui/components/input.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- apps/deploy-web/src/components/authorizations/Authorizations.tsx
- apps/deploy-web/tests/ui/authorize-spending.spec.ts
- apps/deploy-web/tests/ui/fixture/testing-helpers.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
Never use type any or cast to type any. Always define the proper TypeScript types.
Files:
apps/deploy-web/tests/ui/fixture/wallet-setup.tsapps/deploy-web/tests/ui/pages/LeapExt.tsxapps/deploy-web/tests/ui/fixture/context-with-extension.tspackages/ui/components/input.tsxpackages/ui/components/custom/address.tsxapps/deploy-web/tests/ui/pages/AuthorizationsPage.tsx
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{js,ts,tsx}: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code
Files:
apps/deploy-web/tests/ui/fixture/wallet-setup.tsapps/deploy-web/tests/ui/pages/LeapExt.tsxapps/deploy-web/tests/ui/fixture/context-with-extension.tspackages/ui/components/input.tsxpackages/ui/components/custom/address.tsxapps/deploy-web/tests/ui/pages/AuthorizationsPage.tsx
🧠 Learnings (1)
📚 Learning: 2025-10-15T16:39:55.348Z
Learnt from: jzsfkzm
PR: akash-network/console#2039
File: apps/deploy-web/tests/ui/change-wallets.spec.ts:4-10
Timestamp: 2025-10-15T16:39:55.348Z
Learning: In the Akash Console E2E tests using the context-with-extension fixture, the first wallet is automatically created during fixture setup via `importWalletToLeap` in `apps/deploy-web/tests/ui/fixture/wallet-setup.ts`, so tests that call `frontPage.createWallet()` are creating a second wallet to test wallet switching functionality.
Applied to files:
apps/deploy-web/tests/ui/fixture/wallet-setup.tsapps/deploy-web/tests/ui/pages/LeapExt.tsx
🧬 Code graph analysis (4)
apps/deploy-web/tests/ui/pages/LeapExt.tsx (1)
apps/deploy-web/tests/ui/fixture/wallet-setup.ts (1)
approveWalletOperation(68-95)
apps/deploy-web/tests/ui/fixture/context-with-extension.ts (3)
apps/deploy-web/tests/ui/fixture/wallet-setup.ts (4)
getExtensionPage(15-27)setupWallet(29-34)connectWalletViaLeap(46-57)awaitWalletAndApprove(59-66)apps/deploy-web/tests/ui/fixture/base-test.ts (1)
injectUIConfig(16-25)apps/deploy-web/tests/ui/actions/selectChainNetwork.ts (1)
selectChainNetwork(6-20)
packages/ui/components/input.tsx (2)
packages/ui/components/form.tsx (1)
FormLabel(133-133)packages/ui/components/label.tsx (1)
Label(17-17)
apps/deploy-web/tests/ui/pages/AuthorizationsPage.tsx (2)
apps/deploy-web/tests/ui/fixture/test-env.config.ts (1)
testEnvConfig(12-16)packages/ui/components/custom/address.tsx (1)
shortenAddress(11-13)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: test-build
- GitHub Check: test-build
- GitHub Check: Validate local packages
🔇 Additional comments (8)
apps/deploy-web/tests/ui/pages/LeapExt.tsx (2)
2-2: LGTM! Type imports aligned with usage.The updates correctly import
BrowserContextandapproveWalletOperation, and the constructor parameter type is now explicit and consistent with Playwright's types.Also applies to: 7-7, 11-11
41-44: LGTM! Clean implementation avoids event listener complexity.This straightforward implementation waits for the popup page and approves the wallet operation without the event listener registration/cleanup pattern that was problematic in earlier iterations. The simpler approach is more maintainable.
apps/deploy-web/tests/ui/fixture/context-with-extension.ts (1)
30-31: LGTM! Clipboard permissions support copy operations in tests.The clipboard permissions are appropriate for E2E tests that need to verify address copying functionality.
apps/deploy-web/tests/ui/pages/AuthorizationsPage.tsx (4)
1-13: LGTM! Clean page object setup with type-safe label constraints.The type aliases for
AuthorizeButtonLabelandAuthorizationListLabelprovide compile-time safety for UI interaction selectors, following best practices for the page object pattern.
23-28: LGTM! Authorization flow correctly delegates wallet approval to caller.The method performs the UI interactions for setting up authorization without attempting to handle the wallet approval popup. Past reviews flagged event listener issues, but the current implementation correctly separates concerns by letting the test orchestrate the approval step externally (as seen in LeapExt.acceptTransaction).
30-35: LGTM! Edit flow correctly uses shortened address for matching.The method properly shortens the address to match the displayed format in the table, ensuring reliable element location.
37-41: LGTM! Revoke flow follows consistent pattern.The revocation flow correctly implements a two-step confirmation pattern and matches rows using the shortened address format.
apps/deploy-web/tests/ui/fixture/wallet-setup.ts (1)
59-66: All callers have been updated with theextensionIdparameter.The verification confirms that the only caller at
apps/deploy-web/tests/ui/fixture/context-with-extension.ts:71is already passing all three required parameters:context,page, andextensionId. The implementation correctly uses this parameter in thegetExtensionPage()call. No issues found.
| page: [ | ||
| async ({ context, extensionId }, use) => { | ||
| try { | ||
| await context.waitForEvent("page", { timeout: 5000 }); | ||
| } catch { | ||
| // ignore timeout error | ||
| } | ||
|
|
||
| const extPage = await getExtensionPage(context, extensionId); | ||
| const extPage = await getExtensionPage(context, extensionId); | ||
|
|
||
| await setupWallet(context, extPage); | ||
| await extPage.close(); | ||
| const page = await context.newPage(); | ||
| await injectUIConfig(page); | ||
| await setupWallet(context, extPage); | ||
| await extPage.close(); | ||
| const page = await context.newPage(); | ||
| await injectUIConfig(page); | ||
|
|
||
| if (testEnvConfig.NETWORK_ID !== "mainnet") { | ||
| try { | ||
| await page.goto(testEnvConfig.BASE_URL); | ||
| await connectWalletViaLeap(context, page); | ||
| await selectChainNetwork(page, testEnvConfig.NETWORK_ID); | ||
| await connectWalletViaLeap(context, page); | ||
| } catch { | ||
| // Fallback in case the default network is non-functional. | ||
| // E.g., during network upgrade when sandbox is already on a different version from mainnet | ||
| await page.goto(`${testEnvConfig.BASE_URL}?network=${testEnvConfig.NETWORK_ID}`); | ||
| await awaitWalletAndApprove(context, page); | ||
| if (testEnvConfig.NETWORK_ID !== "mainnet") { | ||
| try { | ||
| await page.goto(testEnvConfig.BASE_URL); | ||
| await connectWalletViaLeap(context, page); | ||
| await selectChainNetwork(page, testEnvConfig.NETWORK_ID); | ||
| await connectWalletViaLeap(context, page); | ||
| } catch { | ||
| // Fallback in case the default network is non-functional. | ||
| // E.g., during network upgrade when sandbox is already on a different version from mainnet | ||
| await page.goto(`${testEnvConfig.BASE_URL}?network=${testEnvConfig.NETWORK_ID}`); | ||
| await awaitWalletAndApprove(context, page, extensionId); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| await use(page); | ||
| } | ||
| await use(page); | ||
| }, | ||
| { scope: "test", timeout: 5 * 60 * 1000 } | ||
| ] |
There was a problem hiding this comment.
🧩 Analysis chain
Verify the 5-minute timeout is necessary.
The page fixture now has explicit scope and timeout configuration. The test scope is appropriate for isolation, but the 5-minute timeout seems quite long for fixture setup.
Is the 5-minute timeout necessary for your test environment? Consider whether a shorter timeout (e.g., 2-3 minutes) would be sufficient, as excessively long timeouts can mask real issues with slow setup operations.
🌐 Web query:
What is a typical timeout for Playwright page fixtures in E2E tests?
💡 Result:
- Default: Playwright’s per-test timeout is 30,000 ms (30s), and fixtures share that timeout by default. [1]
- Common practice: keep quick page fixtures within the default 30s; for slower (worker-scoped or heavy) page fixtures people commonly set a separate fixture timeout of 60,000 ms (60s) or similar. Example:
{ timeout: 60000 }on the fixture. [1][2]
References:
[1] Playwright Test — Timeouts (defaults and fixture behavior).
[2] Playwright docs/examples showing fixture timeout usage (example uses 60000 ms).
Reduce fixture timeout from 5 minutes to align with best practices.
The 5-minute timeout (300,000 ms) is significantly excessive. Playwright's default per-test timeout is 30 seconds, and even for slower or heavy fixtures, common practice is to use a separate fixture timeout of around 60 seconds.
Set the timeout to 60,000 ms (1 minute) or 90,000 ms if the wallet setup consistently requires that duration. Overly long timeouts mask real issues with slow operations.
🤖 Prompt for AI Agents
In apps/deploy-web/tests/ui/fixture/context-with-extension.ts around lines 46 to
78, the fixture timeout is set to 5 * 60 * 1000 (300000 ms) which is excessive;
change the timeout value in the fixture options to 60000 (60,000 ms) to align
with best practices (or 90000 if you have measured that the wallet setup
consistently needs more time), keeping the same scope and behavior otherwise.
| return ( | ||
| <div className={cn("space-y-1", className)}> | ||
| {label && (formField.id ? <FormLabel>{label}</FormLabel> : <Label htmlFor={`${finalId}-input`}>{label}</Label>)} | ||
| {label && (formField.id ? <FormLabel htmlFor={`${finalId}-input`}>{label}</FormLabel> : <Label htmlFor={`${finalId}-input`}>{label}</Label>)} |
There was a problem hiding this comment.
🧩 Analysis chain
Good accessibility improvement; verify consistency with Textarea.
The addition of {label} as children to FormLabel and the htmlFor attribute improves accessibility by ensuring the label renders correctly and explicitly links to the input.
However, the Textarea component at line 107 uses FormLabel without the htmlFor attribute. For consistency, verify whether Textarea's FormLabel should also include htmlFor={${formField.id ? formField.id : id}-input} to match this pattern.
🏁 Script executed:
#!/bin/bash
# Verify if FormLabel in other similar components should also have htmlFor attribute
rg -n -C3 -P '<FormLabel[^>]*>.*?</FormLabel>' --type=tsx --type=tsLength of output: 27
---
🏁 Script executed:
```shell
#!/bin/bash
# Alternative approach: find and examine the input.tsx file directly
echo "=== Examining input.tsx file ==="
fd -e tsx -e ts input.tsx
Length of output: 177
🏁 Script executed:
#!/bin/bash
# Search for FormLabel patterns using file glob instead of type
rg -n -C3 '<FormLabel' packages/ui/ Length of output: 1199
🏁 Script executed:
#!/bin/bash
# Look for all tsx files in the ui components directory
fd -e tsx packages/ui/components/Length of output: 397
---
🏁 Script executed:
```shell
#!/bin/bash
# Examine the full input.tsx file to understand context around both components
cat packages/ui/components/input.tsx
Length of output: 4778
Add htmlFor attribute to Textarea's FormLabel for consistency with Input component.
The accessibility improvement at line 59 (adding htmlFor to Input's FormLabel) is good. However, Textarea at line 107 uses FormLabel without the htmlFor attribute. Both components follow identical patterns when formField.id exists, so Textarea's FormLabel should also include htmlFor={${formField.id ? formField.id : id}-input} to maintain consistent accessibility.
Update line 107:
{label && (formField.id ? <FormLabel htmlFor={`${formField.id ? formField.id : id}-input`}>{label}</FormLabel> : <Label htmlFor={`${id}-input`}>{label}</Label>)}
🤖 Prompt for AI Agents
In packages/ui/components/input.tsx around lines 59 and 107, the Textarea
component's FormLabel is missing the htmlFor attribute (unlike the Input
component), so add htmlFor using the same id expression as Input: set
FormLabel's htmlFor to `${formField.id ? formField.id : id}-input` and keep the
existing Label fallback using `${id}-input`; this ensures consistent accessible
labeling for both Input and Textarea.
5691c7d to
f0c3880
Compare
Codecov Report❌ Patch coverage is
❌ Your patch status has failed because the patch coverage (0.00%) is below the target coverage (50.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #2109 +/- ##
==========================================
- Coverage 46.82% 46.47% -0.35%
==========================================
Files 1015 1005 -10
Lines 28800 28451 -349
Branches 7482 7453 -29
==========================================
- Hits 13485 13223 -262
+ Misses 14124 14046 -78
+ Partials 1191 1182 -9
*This pull request uses carry forward flags. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
apps/deploy-web/src/components/authorizations/AllowanceIssuedRow.tsx(1 hunks)apps/deploy-web/src/components/authorizations/Authorizations.tsx(1 hunks)apps/deploy-web/src/components/authorizations/DeploymentGrantTable.tsx(2 hunks)apps/deploy-web/src/components/authorizations/FeeGrantTable.tsx(1 hunks)apps/deploy-web/tests/ui/authorize-spending.spec.ts(1 hunks)apps/deploy-web/tests/ui/change-wallets.spec.ts(1 hunks)apps/deploy-web/tests/ui/disconnect-wallet.spec.ts(1 hunks)apps/deploy-web/tests/ui/fixture/context-with-extension.ts(2 hunks)apps/deploy-web/tests/ui/fixture/testing-helpers.ts(2 hunks)apps/deploy-web/tests/ui/fixture/wallet-setup.ts(1 hunks)apps/deploy-web/tests/ui/pages/AuthorizationsPage.tsx(1 hunks)apps/deploy-web/tests/ui/pages/LeapExt.tsx(2 hunks)apps/deploy-web/tests/ui/uiState/isWalletConnected.ts(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- apps/deploy-web/src/components/authorizations/Authorizations.tsx
🚧 Files skipped from review as they are similar to previous changes (7)
- apps/deploy-web/src/components/authorizations/DeploymentGrantTable.tsx
- apps/deploy-web/tests/ui/authorize-spending.spec.ts
- apps/deploy-web/tests/ui/uiState/isWalletConnected.ts
- apps/deploy-web/tests/ui/change-wallets.spec.ts
- apps/deploy-web/src/components/authorizations/AllowanceIssuedRow.tsx
- apps/deploy-web/src/components/authorizations/FeeGrantTable.tsx
- apps/deploy-web/tests/ui/disconnect-wallet.spec.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
Never use type any or cast to type any. Always define the proper TypeScript types.
Files:
apps/deploy-web/tests/ui/pages/LeapExt.tsxapps/deploy-web/tests/ui/fixture/context-with-extension.tsapps/deploy-web/tests/ui/pages/AuthorizationsPage.tsxapps/deploy-web/tests/ui/fixture/testing-helpers.tsapps/deploy-web/tests/ui/fixture/wallet-setup.ts
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{js,ts,tsx}: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code
Files:
apps/deploy-web/tests/ui/pages/LeapExt.tsxapps/deploy-web/tests/ui/fixture/context-with-extension.tsapps/deploy-web/tests/ui/pages/AuthorizationsPage.tsxapps/deploy-web/tests/ui/fixture/testing-helpers.tsapps/deploy-web/tests/ui/fixture/wallet-setup.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: baktun14
Repo: akash-network/console PR: 1725
File: apps/api/src/utils/constants.ts:5-5
Timestamp: 2025-07-24T17:00:52.361Z
Learning: In the Akash Network Console project, when cross-cutting concerns or broader refactoring issues are identified during PR review, the preferred approach is to create a separate GitHub issue to track the work rather than expanding the scope of the current PR. This maintains focus and allows for proper planning of architectural improvements.
Learnt from: jzsfkzm
Repo: akash-network/console PR: 2039
File: apps/deploy-web/tests/ui/change-wallets.spec.ts:4-10
Timestamp: 2025-10-15T16:39:55.348Z
Learning: In the Akash Console E2E tests using the context-with-extension fixture, the first wallet is automatically created during fixture setup via `importWalletToLeap` in `apps/deploy-web/tests/ui/fixture/wallet-setup.ts`, so tests that call `frontPage.createWallet()` are creating a second wallet to test wallet switching functionality.
📚 Learning: 2025-10-15T16:39:55.348Z
Learnt from: jzsfkzm
Repo: akash-network/console PR: 2039
File: apps/deploy-web/tests/ui/change-wallets.spec.ts:4-10
Timestamp: 2025-10-15T16:39:55.348Z
Learning: In the Akash Console E2E tests using the context-with-extension fixture, the first wallet is automatically created during fixture setup via `importWalletToLeap` in `apps/deploy-web/tests/ui/fixture/wallet-setup.ts`, so tests that call `frontPage.createWallet()` are creating a second wallet to test wallet switching functionality.
Applied to files:
apps/deploy-web/tests/ui/pages/LeapExt.tsxapps/deploy-web/tests/ui/fixture/context-with-extension.tsapps/deploy-web/tests/ui/fixture/testing-helpers.tsapps/deploy-web/tests/ui/fixture/wallet-setup.ts
📚 Learning: 2025-10-31T11:26:42.138Z
Learnt from: stalniy
Repo: akash-network/console PR: 2138
File: apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts:379-382
Timestamp: 2025-10-31T11:26:42.138Z
Learning: In TypeScript/JavaScript, the pattern of checking a cached value and then performing an async operation to fetch it without proper synchronization is race condition unsafe:
```typescript
private async getAddress() {
if (!this.address) {
this.address = await this.wallet.getFirstAddress();
}
return this.address;
}
```
Multiple concurrent calls can all pass the `if (!this.address)` check before any of them sets the value, leading to duplicate async operations. This should be flagged as a race condition. Proper synchronization (mutex, atomic promise caching, or guaranteed single-threaded execution) is required.
Applied to files:
apps/deploy-web/tests/ui/pages/LeapExt.tsxapps/deploy-web/tests/ui/pages/AuthorizationsPage.tsxapps/deploy-web/tests/ui/fixture/testing-helpers.ts
🧬 Code graph analysis (3)
apps/deploy-web/tests/ui/pages/LeapExt.tsx (1)
apps/deploy-web/tests/ui/fixture/wallet-setup.ts (1)
approveWalletOperation(68-95)
apps/deploy-web/tests/ui/fixture/context-with-extension.ts (4)
apps/deploy-web/tests/ui/fixture/wallet-setup.ts (4)
getExtensionPage(15-27)setupWallet(29-34)connectWalletViaLeap(46-57)awaitWalletAndApprove(59-66)apps/deploy-web/tests/ui/fixture/base-test.ts (1)
injectUIConfig(16-25)apps/deploy-web/tests/ui/fixture/test-env.config.ts (1)
testEnvConfig(12-16)apps/deploy-web/tests/ui/actions/selectChainNetwork.ts (1)
selectChainNetwork(6-20)
apps/deploy-web/tests/ui/pages/AuthorizationsPage.tsx (2)
apps/deploy-web/tests/ui/fixture/test-env.config.ts (1)
testEnvConfig(12-16)packages/ui/components/custom/address.tsx (1)
shortenAddress(11-13)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: test-build
- GitHub Check: test-build
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: Validate local packages
🔇 Additional comments (2)
apps/deploy-web/tests/ui/fixture/testing-helpers.ts (1)
17-19: Streamlined fill helper looks good.Removing the extra wait/variable keeps the helper lean without changing behavior.
apps/deploy-web/tests/ui/pages/LeapExt.tsx (1)
41-44: Nice reuse of the shared approval flow.Hooking into
approveWalletOperationkeeps LeapExt aligned with the fixture helpers.
| export const clickCopyAddressButton = async (page: Page) => { | ||
| await page.getByRole("button", { name: /akash\.\.\.[a-z0-9]{5}/ }).click(); | ||
|
|
||
| const clipboardContents = await page.evaluate(async () => { | ||
| return await navigator.clipboard.readText(); | ||
| }); | ||
|
|
||
| return clipboardContents; | ||
| }; |
There was a problem hiding this comment.
Regex misses real button labels.
shortenAddress now renders labels like akash1ab...vwxyz, so this pattern never matches (it insists on akash...). The click will hang as soon as the prefix includes digits, breaking every test case with a real address.
Loosen the regex so it tolerates the characters between akash and the ellipsis.
-export const clickCopyAddressButton = async (page: Page) => {
- await page.getByRole("button", { name: /akash\.\.\.[a-z0-9]{5}/ }).click();
-
- const clipboardContents = await page.evaluate(async () => {
- return await navigator.clipboard.readText();
- });
-
- return clipboardContents;
-};
+export const clickCopyAddressButton = async (page: Page) => {
+ const copyButton = page.getByRole("button", { name: /akash.*\.\.\.[a-z0-9]{5}/i });
+ await copyButton.click();
+
+ const clipboardContents = await page.evaluate(async () => {
+ return await navigator.clipboard.readText();
+ });
+
+ return clipboardContents;
+};🤖 Prompt for AI Agents
In apps/deploy-web/tests/ui/fixture/testing-helpers.ts around lines 31 to 39,
the button role selector uses a regex that expects "akash\.\.\.[a-z0-9]{5}" and
fails when there are characters (including digits) between "akash" and the
ellipsis; update the regex to allow any lowercase alphanumeric characters
between "akash" and the "..." (for example change it to something like
/akash[a-z0-9]*\.\.\.[a-z0-9]{5}/) so the selector matches labels like
"akash1ab...vwxyz" and ensure the literal dots are escaped in the pattern.
| export async function awaitWalletAndApprove(context: BrowserContext, page: Page, extensionId: string) { | ||
| const popupPage = await Promise.race([ | ||
| context.waitForEvent("page", { timeout: 5_000 }), | ||
| getExtensionPage(context, extensionId), | ||
| ]); | ||
| await approveWalletOperation(popupPage); | ||
| await isWalletConnected(page); | ||
| } |
There was a problem hiding this comment.
Prevent timeout rejection from breaking the fallback.
If no popup arrives within 5 s, context.waitForEvent rejects first, so the whole Promise.race throws and skips the extension-page fallback. The loser promise also rejects unhandled, so the test flakes even when getExtensionPage would succeed milliseconds later.
Cache the extension-page promise and catch the timeout so you always settle with a Page.
export async function awaitWalletAndApprove(context: BrowserContext, page: Page, extensionId: string) {
- const popupPage = await Promise.race([
- context.waitForEvent("page", { timeout: 5_000 }),
- getExtensionPage(context, extensionId),
- ]);
+ const extensionPagePromise = getExtensionPage(context, extensionId);
+ const popupPage =
+ (await Promise.race([
+ context.waitForEvent("page", { timeout: 5_000 }),
+ extensionPagePromise
+ ]).catch(async () => await extensionPagePromise)) ?? (await extensionPagePromise);
await approveWalletOperation(popupPage);
await isWalletConnected(page);
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In apps/deploy-web/tests/ui/fixture/wallet-setup.ts around lines 59 to 66, the
Promise.race currently rejects when context.waitForEvent times out and prevents
the getExtensionPage fallback from ever resolving; to fix it, cache the
getExtensionPage(context, extensionId) promise in a variable, replace the raw
waitForEvent timeout with a non-throwing wrapper (e.g., a promise that resolves
to null on timeout or catches the rejection), then race the two so that a
rejected waitForEvent won’t abort the race or create an unhandled rejection;
finally, after the race ensure you always have a Page by using the cached
extension promise if the timeout path returned null and then proceed to
approveWalletOperation and isWalletConnected.
f0c3880 to
a65f1cc
Compare
|
@jzsfkzm just for the future, the title of commit is wrong. This is not "test" only, because you modified deploy-web sources, this requires a new build. Otherwise test wont pass |
refs #2006
Summary by CodeRabbit
Accessibility
Bug Fixes
Tests
UX