Skip to content

Commit e655714

Browse files
committed
feat: added automated test for passkey paymaster
1 parent 1157566 commit e655714

File tree

4 files changed

+112
-3
lines changed

4 files changed

+112
-3
lines changed

examples/demo-app/pages/web-sdk-test.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@
334334
class="mb-4 p-3 bg-white rounded border border-teal-300"
335335
>
336336
<div class="text-sm">
337-
<strong>Smart Account Address:</strong>
337+
<strong>Address:</strong>
338338
<code class="block mt-1 px-2 py-1 bg-gray-100 rounded text-xs font-mono break-all">{{ deploymentResult.address }}</code>
339339
</div>
340340
</div>

examples/demo-app/playwright-erc4337.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export default defineConfig({
1616
/* Retry on CI only */
1717
retries: process.env.CI ? 2 : 0,
1818
/* Opt out of parallel tests on CI. */
19-
workers: process.env.CI ? 1 : undefined,
19+
workers: 1,
2020
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
2121
reporter: "html",
2222
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */

examples/demo-app/project.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@
181181
]
182182
}
183183
},
184+
"e2e:erc4337:no-deploy": {
185+
"executor": "nx:run-commands",
186+
"options": {
187+
"cwd": "examples/demo-app",
188+
"command": "PW_TEST_HTML_REPORT_OPEN=never playwright test --config=playwright-erc4337.config.ts"
189+
}
190+
},
184191
"e2e:erc4337": {
185192
"executor": "nx:run-commands",
186193
"options": {

examples/demo-app/tests/web-sdk-test.spec.ts

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ test("Deploy with passkey and send transaction using passkey", async ({ page })
252252
await page.getByRole("button", { name: "Send with Passkey" }).click();
253253

254254
// Wait for transaction to complete
255-
await expect(page.getByText("Transaction successful! Tx hash:")).toBeVisible({ timeout: 60000 });
255+
await expect(page.getByText("Transaction confirmed! UserOp hash:")).toBeVisible({ timeout: 60000 });
256256
await expect(page.getByText("Transaction failed: Failed to submit UserOperation:")).not.toBeVisible();
257257

258258
// Verify we have a transaction hash for the send
@@ -694,3 +694,105 @@ test("Deploy account with session validator pre-installed", async ({ page }) =>
694694

695695
console.log("✅ Deploy with session validator test completed!");
696696
});
697+
698+
test("Deploy with passkey and send transaction using passkey with paymaster", async ({ page }) => {
699+
// Use Anvil account #8 for this test to avoid nonce conflicts
700+
await page.goto("/web-sdk-test?fundingAccount=8");
701+
await expect(page.getByText("ZKSync SSO Web SDK Test")).toBeVisible();
702+
703+
// Wait for SDK to load
704+
await expect(page.getByText("SDK Loaded:")).toBeVisible();
705+
await expect(page.getByText("Yes")).toBeVisible({ timeout: 10000 });
706+
707+
console.log("Step 1: Enabling passkey configuration...");
708+
709+
// Enable passkey deployment
710+
const passkeyCheckbox = page.getByLabel("Enable Passkey Deployment");
711+
await expect(passkeyCheckbox).toBeVisible();
712+
await passkeyCheckbox.check();
713+
714+
console.log("Step 2: Creating WebAuthn passkey...");
715+
716+
// Create a virtual authenticator for testing
717+
const client = await page.context().newCDPSession(page);
718+
await client.send("WebAuthn.enable");
719+
await client.send("WebAuthn.addVirtualAuthenticator", {
720+
options: {
721+
protocol: "ctap2",
722+
transport: "usb",
723+
hasResidentKey: true,
724+
hasUserVerification: true,
725+
isUserVerified: true,
726+
},
727+
});
728+
729+
// Click Create New WebAuthn Passkey button
730+
await page.getByRole("button", { name: "Create New WebAuthn Passkey" }).click();
731+
732+
// Wait for passkey creation to complete
733+
await expect(page.getByText("Passkey created successfully!")).toBeVisible({ timeout: 10000 });
734+
735+
console.log("✓ WebAuthn passkey created successfully");
736+
737+
// Step 3: Deploy Account with Passkey
738+
console.log("Step 3: Deploying smart account with passkey...");
739+
await page.getByRole("button", { name: "Deploy Account" }).click();
740+
741+
// Wait for deployment to complete
742+
await expect(page.getByText("Account Deployed Successfully!")).toBeVisible({ timeout: 30000 });
743+
744+
// Verify passkey is enabled in deployment result
745+
await expect(page.getByText("Passkey Enabled: Yes")).toBeVisible();
746+
747+
console.log("✓ Smart account with passkey deployed successfully");
748+
749+
// Step 4: Fund Smart Account
750+
console.log("Step 4: Funding smart account...");
751+
752+
const amountInput = page.locator("input[placeholder=\"0.1\"]");
753+
await expect(amountInput).toBeVisible();
754+
await amountInput.fill("0.1");
755+
756+
await page.getByRole("button", { name: "Fund Smart Account" }).click();
757+
758+
// Wait for funding transaction to complete
759+
await expect(page.getByText("Transaction Hash:"), "Funding failed").toBeVisible({ timeout: 30000 });
760+
761+
console.log("✓ Smart account funded successfully");
762+
763+
// Step 5: Send Transaction using Passkey with Paymaster
764+
console.log("Step 5: Sending transaction using passkey with paymaster...");
765+
766+
// Scroll to the paymaster section
767+
await page.evaluate(() => {
768+
const headings = Array.from(document.querySelectorAll("h2"));
769+
const paymasterHeading = headings.find((h) => h.textContent?.includes("Send Transaction with Paymaster (Passkey)"));
770+
if (paymasterHeading) {
771+
paymasterHeading.scrollIntoView({ behavior: "smooth", block: "center" });
772+
}
773+
});
774+
775+
await page.waitForTimeout(500); // Wait for scroll to complete
776+
777+
// Wait for the paymaster section to be visible
778+
await expect(page.getByText("Send Transaction with Paymaster (Passkey)")).toBeVisible();
779+
780+
// Fill in amount for paymaster transaction
781+
// Find all inputs with the 0.01 placeholder and use the last one (paymaster section)
782+
const paymasterAmountInputs = page.locator("input[placeholder=\"0.01\"]");
783+
const paymasterAmountInput = paymasterAmountInputs.last();
784+
await expect(paymasterAmountInput).toBeVisible();
785+
await paymasterAmountInput.fill("0.001");
786+
787+
// Click Send with Paymaster (Passkey) button
788+
await page.getByRole("button", { name: "Send with Paymaster (Passkey)" }).click();
789+
790+
// Wait for transaction to complete - look for success message
791+
await expect(page.getByText("Transaction confirmed! UserOp hash:"), "Paymaster transaction failed").toBeVisible({ timeout: 60000 });
792+
793+
// Verify we don't have an error message
794+
await expect(page.getByText("Failed to submit UserOperation:")).not.toBeVisible();
795+
796+
console.log("✓ Transaction sent using passkey with paymaster successfully");
797+
console.log("✅ All passkey + paymaster steps completed successfully!");
798+
});

0 commit comments

Comments
 (0)