mirror of
https://github.com/aljazceru/mutiny-web.git
synced 2026-02-22 22:54:28 +01:00
test all routes, test send + receive
This commit is contained in:
committed by
Tony Giorgio
parent
d38f0d61a2
commit
8a427c62e8
2
.github/workflows/playwright.yml
vendored
2
.github/workflows/playwright.yml
vendored
@@ -64,7 +64,7 @@ jobs:
|
||||
VITE_FEEDBACK: https://feedback-staging.mutinywallet.com
|
||||
VITE_SCORER: https://scorer-staging.mutinywallet.com
|
||||
VITE_PRIMAL: https://primal-cache.mutinywallet.com/api
|
||||
run: pnpm exec playwright test
|
||||
run: pnpm exec playwright test --grep-invert @slow
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
|
||||
@@ -21,55 +21,3 @@ test("initial load", async ({ page }) => {
|
||||
console.log("Page loaded.");
|
||||
});
|
||||
|
||||
test("first receive", async ({ page }) => {
|
||||
// Click the receive button
|
||||
await page.click("text=Receive");
|
||||
|
||||
// Expect the url to conain receive
|
||||
await expect(page).toHaveURL(/.*receive/);
|
||||
|
||||
// At least one h1 should show "0 sats"
|
||||
await expect(page.locator("h1")).toContainText(["0 SATS"]);
|
||||
|
||||
// At least one h2 should show "0 USD"
|
||||
await expect(page.locator("h2")).toContainText(["$0 USD"]);
|
||||
|
||||
// Click the 10k button
|
||||
await page.click("text=10k");
|
||||
|
||||
// Now the h1 should show "10,000 sats"
|
||||
await expect(page.locator("h1")).toContainText(["10,000 SATS"]);
|
||||
|
||||
// Click the "Set Amount" button
|
||||
await page.click("text=Set Amount");
|
||||
|
||||
// There should be a button with the text "Continue" and it should not be disabled
|
||||
const continueButton = await page.locator("button", { hasText: "Continue" });
|
||||
await expect(continueButton).not.toBeDisabled();
|
||||
|
||||
// Wait one second
|
||||
// TODO: figure out how to not get an error without waiting
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
continueButton.click();
|
||||
|
||||
await expect(
|
||||
page.getByText("Keep Mutiny open to complete the payment.")
|
||||
).toBeVisible();
|
||||
|
||||
// Locate an SVG inside a div with id "qr"
|
||||
const qrCode = await page.locator("#qr > svg");
|
||||
|
||||
await expect(qrCode).toBeVisible();
|
||||
|
||||
const value = await qrCode.getAttribute("value");
|
||||
|
||||
// The SVG's value property includes "bitcoin:t"
|
||||
expect(value).toContain("bitcoin:t");
|
||||
|
||||
// Now click thie "Edit" button
|
||||
await page.click("text=Edit");
|
||||
|
||||
// There should not be an h1 that says "Error"
|
||||
await expect(page.locator("h1")).not.toContainText(["Error"]);
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ test.beforeEach(async ({ page }) => {
|
||||
await page.goto("http://localhost:3420/");
|
||||
});
|
||||
|
||||
test("restore from seed", async ({ page }) => {
|
||||
test("restore from seed @slow", async ({ page }) => {
|
||||
// should have 100k sats on-chain
|
||||
const TEST_SEED_WORDS =
|
||||
"rival hood review write spoon tide orange ill opera enrich clip acoustic";
|
||||
|
||||
92
e2e/roundtrip.spec.ts
Normal file
92
e2e/roundtrip.spec.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto("http://localhost:3420/");
|
||||
});
|
||||
|
||||
test("rountrip receive and send", async ({ page }) => {
|
||||
// Click the receive button
|
||||
await page.click("text=Receive");
|
||||
|
||||
// Expect the url to conain receive
|
||||
await expect(page).toHaveURL(/.*receive/);
|
||||
|
||||
// At least one h1 should show "0 sats"
|
||||
await expect(page.locator("h1")).toContainText(["0 SATS"]);
|
||||
|
||||
// At least one h2 should show "0 USD"
|
||||
await expect(page.locator("h2")).toContainText(["$0 USD"]);
|
||||
|
||||
// Click the 100k button
|
||||
await page.click("text=100k");
|
||||
|
||||
// Now the h1 should show "10,000 sats"
|
||||
await expect(page.locator("h1")).toContainText(["100,000 SATS"]);
|
||||
|
||||
// Click the "Set Amount" button
|
||||
await page.click("text=Set Amount");
|
||||
|
||||
// There should be a button with the text "Continue" and it should not be disabled
|
||||
const continueButton = await page.locator("button", { hasText: "Continue" });
|
||||
await expect(continueButton).not.toBeDisabled();
|
||||
|
||||
// Wait one second
|
||||
// TODO: figure out how to not get an error without waiting
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
continueButton.click();
|
||||
|
||||
await expect(
|
||||
page.getByText("Keep Mutiny open to complete the payment.")
|
||||
).toBeVisible();
|
||||
|
||||
// Locate an SVG inside a div with id "qr"
|
||||
const qrCode = await page.locator("#qr > svg");
|
||||
|
||||
await expect(qrCode).toBeVisible();
|
||||
|
||||
const value = await qrCode.getAttribute("value");
|
||||
|
||||
// The SVG's value property includes "bitcoin:t"
|
||||
expect(value).toContain("bitcoin:t");
|
||||
|
||||
const lightningInvoice = value?.split("lightning=")[1];
|
||||
|
||||
// Post the lightning invoice to the server
|
||||
const _response = await fetch("https://faucet.mutinynet.com/api/lightning", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
bolt11: lightningInvoice
|
||||
})
|
||||
});
|
||||
|
||||
// Wait for an h1 to appear in the dom that says "Payment Received"
|
||||
await page.waitForSelector("text=Payment Received", { timeout: 30000 });
|
||||
|
||||
// Click the "Nice" button
|
||||
await page.click("text=Nice");
|
||||
|
||||
// Now we send
|
||||
await page.click("text=Send");
|
||||
|
||||
// In the textarea with the placeholder "bitcoin:..." type refund@lnurl-staging.mutinywallet.com
|
||||
const sendInput = await page.locator("textarea");
|
||||
await sendInput.fill("refund@lnurl-staging.mutinywallet.com");
|
||||
|
||||
await page.click("text=Continue");
|
||||
|
||||
await page.click("text=Set Amount");
|
||||
|
||||
await page.click("text=10k");
|
||||
|
||||
await page.click("text=Set Amount");
|
||||
|
||||
await page.click("text=Confirm Send");
|
||||
|
||||
// Wait for an h1 to appear in the dom that says "Payment Received"
|
||||
await page.waitForSelector("text=Payment Sent", { timeout: 30000 });
|
||||
});
|
||||
|
||||
207
e2e/routes.spec.ts
Normal file
207
e2e/routes.spec.ts
Normal file
@@ -0,0 +1,207 @@
|
||||
import { expect, Page, test } from "@playwright/test";
|
||||
|
||||
const routes = [
|
||||
"/",
|
||||
"/activity",
|
||||
"/feedback",
|
||||
"/gift",
|
||||
"/receive",
|
||||
"/redshift",
|
||||
"/scanner",
|
||||
"/send",
|
||||
"/swap",
|
||||
"/settings"
|
||||
];
|
||||
|
||||
const settingsRoutes = [
|
||||
"/admin",
|
||||
"/backup",
|
||||
"/channels",
|
||||
"/connections",
|
||||
"/currency",
|
||||
"/emergencykit",
|
||||
"/encrypt",
|
||||
"/gift",
|
||||
"/lnurlauth",
|
||||
"/plus",
|
||||
"/restore",
|
||||
"/servers",
|
||||
"/syncnostrcontacts"
|
||||
];
|
||||
|
||||
const settingsRoutesPrefixed = settingsRoutes.map((route) => {
|
||||
return "/settings" + route;
|
||||
});
|
||||
|
||||
const allRoutes = routes.concat(settingsRoutesPrefixed);
|
||||
|
||||
// Create a JS Map of all routes so we can check them off one by one
|
||||
const checklist = new Map();
|
||||
allRoutes.forEach((route) => {
|
||||
checklist.set(route, false);
|
||||
});
|
||||
|
||||
// Only works if there's a link to the route on the page
|
||||
async function checkRoute(
|
||||
page: Page,
|
||||
route: string,
|
||||
expectedHeader: string,
|
||||
checklist: Map<string, boolean>
|
||||
) {
|
||||
await page.locator(`a[href='${route}']`).first().click();
|
||||
await expect(page.locator("h1").first()).toHaveText(expectedHeader);
|
||||
checklist.set(route, true);
|
||||
}
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto("http://localhost:3420/");
|
||||
});
|
||||
|
||||
test("visit each route", async ({ page }) => {
|
||||
// Start on the home page
|
||||
// Expect a title "to contain" a substring.
|
||||
await expect(page).toHaveTitle(/Mutiny Wallet/);
|
||||
|
||||
// Wait for an element matching the selector to appear in DOM.
|
||||
await page.waitForSelector("text=0 SATS");
|
||||
|
||||
console.log("Page loaded.");
|
||||
|
||||
// Wait for a while just to make sure we can load everything
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
checklist.set("/", true);
|
||||
|
||||
await checkRoute(page, "/activity", "Activity", checklist);
|
||||
await page.goBack();
|
||||
|
||||
// Navigate to settings
|
||||
await checkRoute(page, "/settings", "Settings", checklist);
|
||||
|
||||
// Mutiny+
|
||||
await checkRoute(page, "/settings/plus", "Mutiny+", checklist);
|
||||
await page.goBack();
|
||||
|
||||
// Lightning Channels
|
||||
await checkRoute(
|
||||
page,
|
||||
"/settings/channels",
|
||||
"Lightning Channels",
|
||||
checklist
|
||||
);
|
||||
await page.goBack();
|
||||
|
||||
// Backup
|
||||
await checkRoute(page, "/settings/backup", "Backup", checklist);
|
||||
await page.goBack();
|
||||
|
||||
// Restore
|
||||
await checkRoute(page, "/settings/restore", "Restore", checklist);
|
||||
await page.goBack();
|
||||
|
||||
// Currency
|
||||
await checkRoute(page, "/settings/currency", "Currency", checklist);
|
||||
await page.goBack();
|
||||
|
||||
// Servers
|
||||
await checkRoute(page, "/settings/servers", "Servers", checklist);
|
||||
await page.goBack();
|
||||
|
||||
// Connections
|
||||
await checkRoute(
|
||||
page,
|
||||
"/settings/connections",
|
||||
"Wallet Connections",
|
||||
checklist
|
||||
);
|
||||
await page.goBack();
|
||||
|
||||
// LNURL Auth
|
||||
await checkRoute(page, "/settings/lnurlauth", "LNURL Auth", checklist);
|
||||
await page.goBack();
|
||||
|
||||
// Sync Nostr Contacts
|
||||
await checkRoute(
|
||||
page,
|
||||
"/settings/syncnostrcontacts",
|
||||
"Sync Nostr Contacts",
|
||||
checklist
|
||||
);
|
||||
await page.goBack();
|
||||
|
||||
// Emergency Kit
|
||||
await checkRoute(
|
||||
page,
|
||||
"/settings/emergencykit",
|
||||
"Emergency Kit",
|
||||
checklist
|
||||
);
|
||||
await page.goBack();
|
||||
|
||||
// Admin
|
||||
await checkRoute(page, "/settings/admin", "Secret Debug Tools", checklist);
|
||||
await page.goBack();
|
||||
|
||||
// Go back home
|
||||
await page.goBack();
|
||||
|
||||
// Feedback
|
||||
await checkRoute(page, "/feedback", "Give us feedback!", checklist);
|
||||
await page.goBack();
|
||||
|
||||
// Receive is covered in another test
|
||||
checklist.set("/receive", true);
|
||||
|
||||
// Send is covered in another test
|
||||
checklist.set("/send", true);
|
||||
|
||||
// Scanner
|
||||
await page.locator(`a[href='/scanner']`).first().click();
|
||||
await expect(page.locator("button").first()).toHaveText("Paste Something");
|
||||
checklist.set("/scanner", true);
|
||||
|
||||
// Now we have to check routes that aren't linked to directly for whatever reason
|
||||
await page.goto(
|
||||
"http://localhost:3420/gift?amount=50000&nwc_uri=nostr%2Bwalletconnect%3A%2F%2Ff6d55dff6da0f23e0d609121905aaa8da5d2bad7759459402e2bee1162912556%3Frelay%3Dwss%253A%252F%252Fnostr.mutinywallet.com%252F%26secret%3D8a2d579a182e9091d36d5668eb1c3b301d98bc792d94e866526123df79568355"
|
||||
);
|
||||
await expect(page.locator("h2").nth(1)).toHaveText(
|
||||
"You've been gifted some sats!"
|
||||
);
|
||||
checklist.set("/gift", true);
|
||||
|
||||
// Visit connections with AutoZap params
|
||||
const autoZapParams =
|
||||
"/settings/connections?return_to=https%3A%2F%2Fwww.zapplepay.com%2Fautozap%2Fnpub1xtscya34g58tk0z605fvr788k263gsu6cy9x0mhnm87echrgufzsevkk5s&name=AutoZap-jb55&budget_renewal=day&max_amount=420";
|
||||
await page.goto("http://localhost:3420" + autoZapParams);
|
||||
await expect(page.locator('[role="dialog"] h2 header').first()).toHaveText(
|
||||
"Add Connection"
|
||||
);
|
||||
|
||||
// Redshift
|
||||
await page.goto("http://localhost:3420/redshift");
|
||||
await expect(page.locator("h1")).toHaveText("Redshift (coming soon)");
|
||||
checklist.set("/redshift", true);
|
||||
await page.goBack();
|
||||
|
||||
// Swap
|
||||
await page.goto("http://localhost:3420/swap");
|
||||
await expect(page.locator("h1")).toHaveText("Swap to Lightning");
|
||||
checklist.set("/swap", true);
|
||||
|
||||
// Gift
|
||||
await page.goto("http://localhost:3420/settings/gift");
|
||||
await expect(page.locator("h1")).toHaveText("Create Gift");
|
||||
checklist.set("/settings/gift", true);
|
||||
|
||||
// Encrypt
|
||||
await page.goto("http://localhost:3420/settings/encrypt");
|
||||
await expect(page.locator("h1")).toHaveText(
|
||||
"Encrypt your seed words (optional)"
|
||||
);
|
||||
checklist.set("/settings/encrypt", true);
|
||||
|
||||
// print how many routes we've visited
|
||||
checklist.forEach((value, key) => {
|
||||
console.log(`${key}: ${value}`);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user