Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Push to prod #815

Merged
merged 4 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ android {
applicationId "com.mutinywallet.mutinywallet"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 44
versionName "0.5.2"
versionCode 45
versionName "0.5.3"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
Expand Down
154 changes: 154 additions & 0 deletions e2e/fedimint.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { expect, test } from "@playwright/test";

const SIGNET_INVITE_CODE =
"fed11qgqzc2nhwden5te0vejkg6tdd9h8gepwvejkg6tdd9h8garhduhx6at5d9h8jmn9wshxxmmd9uqqzgxg6s3evnr6m9zdxr6hxkdkukexpcs3mn7mj3g5pc5dfh63l4tj6g9zk4er";

test.beforeEach(async ({ page }) => {
await page.goto("http://localhost:3420/");
});

test("fedmint join, receive, send", async ({ 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);

// Navigate to settings
const settingsLink = await page.getByRole("link", { name: "Settings" });

settingsLink.click();

// Wait for settings to load
await page.waitForSelector("text=Settings");

// Click "Manage Federations" link
await page.click("text=Manage Federations");

// Fill the input with the federation code
await page.fill("input[name='federation_code']", SIGNET_INVITE_CODE);

const addButton = await page.getByRole("button", { name: "Add" });

// Click the "Add" button
await addButton.click();

// Wait for a header to appear with the text "MutinySignetFederation"
await page.waitForSelector("text=MutinySignetFederation");

// Navigate back home
await page.goBack();
await page.goBack();

// Make sure there's a fedimint icon
await expect(page.getByRole("img", { name: "community" })).toBeVisible();

// 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"]);

// Type 100 into the input
await page.locator("#sats-input").pressSequentially("100");

// Now the h1 should show "100,000 sats"
await expect(page.locator("h1")).toContainText(["100 SATS"]);

// 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");

// Make sure we have 100 sats in the fedimint balance
await expect(
page
.locator("div")
.filter({ hasText: /^100 SATS$/ })
.nth(1)
).toBeVisible();

// Now we send
await page.click("text=Send");

// type [email protected]
const sendInput = await page.locator("input");
await sendInput.fill("[email protected]");

await page.click("text=Continue");

// Wait two seconds (the destination doesn't show up immediately)
// TODO: figure out how to not get an error without waiting
await page.waitForTimeout(2000);

// Type 90 into the input
await page.locator("#sats-input").fill("90");

// Now the h1 should show "90 sats"
await expect(page.locator("h1")).toContainText(["90 SATS"]);

// There should be a button with the text "Confirm Send" and it should not be disabled
const confirmButton = await page.locator("button", {
hasText: "Confirm Send"
});
await expect(confirmButton).not.toBeDisabled();

confirmButton.click();

// Wait for an h1 to appear in the dom that says "Payment Sent"
await page.waitForSelector("text=Payment Sent", { timeout: 30000 });
});
89 changes: 50 additions & 39 deletions e2e/roundtrip.spec.ts
Original file line number Diff line number Diff line change
@@ -1,67 +1,69 @@
import { test, expect } from "@playwright/test";
import { expect, test } from "@playwright/test";

test.beforeEach(async ({ page }) => {
await page.goto("http://localhost:3420/");
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"

// Type 100000 into the input
await page.locator("#sats-input").pressSequentially("100000");

// Now the h1 should show "100,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" });
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
})
});
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 });
Expand All @@ -73,20 +75,29 @@ test("rountrip receive and send", async ({ page }) => {
await page.click("text=Send");

// In the textarea with the placeholder "bitcoin:..." type [email protected]
const sendInput = await page.locator("textarea");
const sendInput = await page.locator("input");
await sendInput.fill("[email protected]");

await page.click("text=Continue");

await page.click("text=Set Amount");
// Wait two seconds (the destination doesn't show up immediately)
// TODO: figure out how to not get an error without waiting
await page.waitForTimeout(2000);

await page.click("text=10k");
// Type 10000 into the input
await page.locator("#sats-input").fill("10000");

await page.click("text=Set Amount");
// Now the h1 should show "100,000 sats"
await expect(page.locator("h1")).toContainText(["10,000 SATS"]);

await page.click("text=Confirm Send");
// There should be a button with the text "Confirm Send" and it should not be disabled
const confirmButton = await page.locator("button", {
hasText: "Confirm Send"
});
await expect(confirmButton).not.toBeDisabled();

// Wait for an h1 to appear in the dom that says "Payment Received"
confirmButton.click();

// Wait for an h1 to appear in the dom that says "Payment Sent"
await page.waitForSelector("text=Payment Sent", { timeout: 30000 });
});

});
4 changes: 3 additions & 1 deletion e2e/routes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@ test("visit each route", async ({ page }) => {

// Swap
await page.goto("http://localhost:3420/swap");
await expect(page.locator("h1")).toHaveText("Swap to Lightning");
await expect(
page.getByRole("heading", { name: "Swap to Lightning" })
).toBeVisible();
checklist.set("/swap", true);

// Gift
Expand Down
4 changes: 2 additions & 2 deletions ios/App/App.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.finance";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.5.2;
MARKETING_VERSION = 1.5.3;
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = com.mutinywallet.mutiny;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -387,7 +387,7 @@
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.finance";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.5.2;
MARKETING_VERSION = 1.5.3;
PRODUCT_BUNDLE_IDENTIFIER = com.mutinywallet.mutiny;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down
9 changes: 3 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mutiny-wallet",
"version": "0.5.2",
"version": "0.5.3",
"license": "MIT",
"packageManager": "[email protected]",
"scripts": {
Expand Down Expand Up @@ -55,19 +55,16 @@
"@kobalte/core": "^0.9.8",
"@kobalte/tailwindcss": "^0.5.0",
"@modular-forms/solid": "^0.18.1",
"@mutinywallet/mutiny-wasm": "0.5.2",
"@mutinywallet/mutiny-wasm": "0.5.3",
"@mutinywallet/waila-wasm": "^0.2.6",
"@solid-primitives/upload": "^0.0.111",
"@solid-primitives/websocket": "^1.2.0",
"@solidjs/meta": "^0.29.1",
"@solidjs/router": "^0.9.0",
"@thisbeyond/solid-select": "^0.14.0",
"i18next": "^22.5.1",
"i18next-browser-languagedetector": "^7.1.0",
"qr-scanner": "^1.4.2",
"solid-js": "^1.8.5",
"solid-qr-code": "^0.0.8",
"undici": "^5.27.1"
"solid-qr-code": "^0.0.8"
},
"engines": {
"node": ">=18"
Expand Down
Loading
Loading