Skip to content

Commit

Permalink
Merge pull request #4085 from LedgerHQ/support/deflakify-swap-verify-…
Browse files Browse the repository at this point in the history
…test

fix: removed screenshot swap checks in favour of text check and tidied up services page objects and tests
  • Loading branch information
ggilchrist-ledger authored Jul 24, 2023
2 parents b4071d2 + 8ed995a commit 27d522a
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ const SwapOperationDetails = ({
val={normalisedFromAmount}
fontSize={6}
disableRounding
data-test-id="swap-amount-from"
/>
</Box>
<Box my={1} color={"palette.text.shade50"}>
Expand All @@ -183,6 +184,7 @@ const SwapOperationDetails = ({
fontSize={6}
disableRounding
color={statusColor}
data-test-id="swap-amount-to"
/>
</Box>
</Box>
Expand Down Expand Up @@ -280,7 +282,7 @@ const SwapOperationDetails = ({
<Box mr={1} alignItems={"center"}>
<CryptoCurrencyIcon size={16} currency={fromCurrency} />
</Box>
<Box flex={1} color={"palette.text.shade100"}>
<Box flex={1} color={"palette.text.shade100"} data-test-id="swap-account-from">
<Ellipsis>
<Link onClick={() => openAccount(fromAccount)}>{getAccountName(fromAccount)}</Link>
</Ellipsis>
Expand Down Expand Up @@ -322,7 +324,7 @@ const SwapOperationDetails = ({
<Box mr={1} alignItems={"center"}>
<CryptoCurrencyIcon size={16} currency={toCurrency} />
</Box>
<Box flex={1} color={"palette.text.shade100"}>
<Box flex={1} color={"palette.text.shade100"} data-test-id="swap-account-to">
<Ellipsis>
<Link onClick={() => openAccount(toAccount)}>{getAccountName(toAccount)}</Link>
</Ellipsis>
Expand Down
21 changes: 0 additions & 21 deletions apps/ledger-live-desktop/tests/models/DiscoverPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,13 @@ import { Page, Locator } from "@playwright/test";

export class DiscoverPage {
readonly page: Page;
readonly discoverTitle: Locator;
readonly discoverMenuButton: Locator;
readonly testAppCatalogItem: Locator;
readonly disclaimerTitle: Locator;
readonly disclaimerText: Locator;
readonly liveAppTitle: Locator;
readonly liveAppLoadingSpinner: Locator;
readonly getAllAccountsButton: Locator;
readonly requestAccountButton: Locator;
readonly selectAssetTitle: Locator;
readonly selectAssetSearchBar: Locator;
readonly selectAccountTitle: Locator;
readonly selectBtcAsset: Locator;
readonly selectBtcAccount: Locator;
readonly disclaimerCheckbox: Locator;
readonly signNetworkWarning: Locator;
readonly signContinueButton: Locator;
readonly confirmText: Locator;
readonly webview: Locator;

constructor(page: Page) {
this.page = page;
this.webview = page.locator("webview");
this.discoverMenuButton = page.locator("data-test-id=drawer-catalog-button");
this.discoverTitle = page.locator("data-test-id=discover-title");
this.testAppCatalogItem = page.locator("#platform-catalog-app-dummy-live-app");
this.disclaimerTitle = page.locator("data-test-id=live-app-disclaimer-drawer-title");
this.disclaimerText = page.locator("text=External Application");
}

async openTestApp() {
Expand Down
21 changes: 21 additions & 0 deletions apps/ledger-live-desktop/tests/models/Drawer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ export class Drawer {
readonly closeButton: Locator;
readonly currencyButton: (currency: string) => Locator;
readonly accountButton: (accountName: string, index: number) => Locator;
readonly selectAssetTitle: Locator;
readonly selectAssetSearchBar: Locator;
readonly selectAccountTitle: Locator;
readonly disclaimerCheckbox: Locator;
readonly swapAmountFrom: Locator;
readonly swapAmountTo: Locator;
readonly swapAccountFrom: Locator;
readonly swapAccountTo: Locator;

constructor(page: Page) {
this.page = page;
Expand All @@ -19,6 +27,14 @@ export class Drawer {
page.locator(`data-test-id=currency-row-${currency.toLowerCase()}`);
this.accountButton = (accountName, index) =>
page.locator(`data-test-id=account-row-${accountName.toLowerCase()}-${index}`).first();
this.selectAssetTitle = page.locator("data-test-id=select-asset-drawer-title");
this.selectAssetSearchBar = page.locator("data-test-id=select-asset-drawer-search-input");
this.selectAccountTitle = page.locator("data-test-id=select-account-drawer-title");
this.disclaimerCheckbox = page.locator("data-test-id=dismiss-disclaimer");
this.swapAmountFrom = page.locator("data-test-id=swap-amount-from").first();
this.swapAmountTo = page.locator("data-test-id=swap-amount-to").first();
this.swapAccountFrom = page.locator("data-test-id=swap-account-from").first();
this.swapAccountTo = page.locator("data-test-id=swap-account-to").first();
}

async continue() {
Expand Down Expand Up @@ -49,4 +65,9 @@ export class Drawer {
async selectAccount(accountName: string, index = 0) {
await this.accountButton(accountName, index).click();
}

async verifyAssetIsReady() {
await this.selectAssetTitle.isVisible();
await this.selectAssetSearchBar.isEnabled();
}
}
41 changes: 1 addition & 40 deletions apps/ledger-live-desktop/tests/models/LiveAppWebview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,19 @@ export class LiveAppWebview {
readonly page: Page;
readonly liveAppTitle: Locator;
readonly liveAppLoadingSpinner: Locator;
readonly getAllAccountsButton: Locator;
readonly requestAccountButton: Locator;
readonly webview: Locator;
readonly selectAssetTitle: Locator;
readonly selectAssetSearchBar: Locator;
readonly selectAccountTitle: Locator;
readonly selectBtcAsset: Locator;
readonly selectBtcAccount: Locator;
readonly disclaimerCheckbox: Locator;
readonly signNetworkWarning: Locator;
readonly signContinueButton: Locator;
readonly confirmText: Locator;
readonly webview: Locator;

constructor(page: Page) {
this.page = page;
this.webview = page.locator("webview");
this.liveAppTitle = page.locator("data-test-id=live-app-title");
this.liveAppLoadingSpinner = page.locator("data-test-id=live-app-loading-spinner");
this.getAllAccountsButton = page.locator("data-test-id=get-all-accounts-button"); // TODO: make this into its own model
this.requestAccountButton = page.locator("data-test-id=request-single-account-button");
this.selectAssetTitle = page.locator("data-test-id=select-asset-drawer-title");
this.selectAssetSearchBar = page.locator("data-test-id=select-asset-drawer-search-input");
this.selectAccountTitle = page.locator("data-test-id=select-account-drawer-title");
this.selectBtcAsset = page.locator("text=Bitcoin").first();
this.selectBtcAccount = page.locator("text=Bitcoin 1 (legacy)").first();
this.disclaimerCheckbox = page.locator("data-test-id=dismiss-disclaimer");
this.signNetworkWarning = page.locator("text=Network fees are above 10% of the amount").first();
this.signContinueButton = page.locator("text=Continue");
this.confirmText = page.locator(
"text=Please confirm the operation on your device to finalize it",
);
}

static async startLiveApp(
Expand Down Expand Up @@ -95,18 +77,6 @@ export class LiveAppWebview {

async requestAsset() {
await this.clickWebviewElement("[data-test-id=request-single-account-button]");
await this.selectAssetTitle.isVisible();
await this.selectAssetSearchBar.isEnabled();
}

async selectAsset() {
await this.selectBtcAsset.click();
}

async selectAccount() {
await this.selectAccountTitle.isVisible();
// TODO: make this dynamic with passed in variable
await this.selectBtcAccount.click();
}

async verifyAddress() {
Expand All @@ -119,15 +89,6 @@ export class LiveAppWebview {

async signTransaction() {
await this.clickWebviewElement("[data-test-id=sign-transaction-button]");
await this.signNetworkWarning.waitFor({ state: "visible" });
}

async continueToSignTransaction() {
await this.signContinueButton.click({ force: true });
}

async waitForConfirmationScreenToBeDisplayed() {
await this.confirmText.waitFor({ state: "visible" });
}

async clickWebviewElement(elementName: string) {
Expand Down
16 changes: 16 additions & 0 deletions apps/ledger-live-desktop/tests/models/Modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export class Modal {
readonly backButton: Locator;
readonly stakeProviderContainer: (stakeProvider: string) => Locator;
readonly stakeProviderSupportLink: (stakeProvider: string) => Locator;
readonly signNetworkWarning: Locator;
readonly signContinueButton: Locator;
readonly confirmText: Locator;

constructor(page: Page) {
this.page = page;
Expand All @@ -37,6 +40,11 @@ export class Modal {
page.locator(`data-test-id=stake-provider-container-${stakeProviderID}`);
this.stakeProviderSupportLink = stakeProviderID =>
page.locator(`data-test-id=stake-provider-support-link-${stakeProviderID}`);
this.signNetworkWarning = page.locator("text=Network fees are above 10% of the amount").first();
this.signContinueButton = page.locator("text=Continue");
this.confirmText = page.locator(
"text=Please confirm the operation on your device to finalize it",
);
}

async continue() {
Expand Down Expand Up @@ -83,4 +91,12 @@ export class Modal {
async chooseStakeSupportLink(stakeProvider: string) {
await this.stakeProviderSupportLink(stakeProvider).dispatchEvent("click");
}

async continueToSignTransaction() {
await this.signContinueButton.click({ force: true });
}

async waitForConfirmationScreenToBeDisplayed() {
await this.confirmText.waitFor({ state: "visible" });
}
}
7 changes: 3 additions & 4 deletions apps/ledger-live-desktop/tests/models/SwapPage.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Page, Locator } from "@playwright/test";
import { waitFor } from "tests/utils/waitFor";
import { waitFor } from "../utils/waitFor";

export class SwapPage {
readonly page: Page;
Expand Down Expand Up @@ -170,17 +170,16 @@ export class SwapPage {
await this.exchangeButton.click();
}

async verifySuccessfulExchange() {
async waitForSuccessfulExchange() {
await this.swapId.waitFor({ state: "visible" });
return this.swapId.innerText();
}

async navigateToExchangeDetails() {
await this.seeDetailsButton.click();
await this.swapId.waitFor({ state: "hidden" }); // for some reason the detailsSwapId visible check below is not sufficient and we need to check that this element is gone before checking the new page is available.
}

async verifyExchangeDetails() {
async waitForExchangeDetails() {
await this.detailsSwapId.waitFor({ state: "visible" });
return this.detailsSwapId.innerText();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ test.use({
},
});

test("Ethereum staking flows via portfolio, asset page and market page", async ({ page }) => {
test("Ethereum staking flows via portfolio, asset page and market page @smoke", async ({
page,
}) => {
const portfolioPage = new PortfolioPage(page);
const drawer = new Drawer(page);
const modal = new Modal(page);
Expand Down Expand Up @@ -118,7 +120,7 @@ test("Ethereum staking flows via portfolio, asset page and market page", async (
await analyticsPromise;
await liveAppWebview.waitForCorrectTextInWebview("Ethereum 2");
const dappURL = await liveAppWebview.getLiveAppDappURL();
await expect(await liveAppWebview.getLiveAppTitle()).toBe("Kiln");
expect(await liveAppWebview.getLiveAppTitle()).toBe("Kiln");
expect(dappURL).toContain("?focus=dedicated");
await expect.soft(page).toHaveScreenshot("stake-provider-dapp-has-opened.png", {
mask: [page.locator("webview")],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,18 @@ test("Live App SDK methods @smoke", async ({ page }) => {

await test.step("Request Account drawer - open", async () => {
await liveAppWebview.requestAsset();
await drawer.verifyAssetIsReady();
await expect(liveAppWebview.selectAssetTitle).toBeVisible();
});

await test.step("Request Account - select asset", async () => {
await liveAppWebview.selectAsset();
await drawer.selectCurrency("Bitcoin");
await expect(liveAppWebview.selectAccountTitle).toBeVisible();
await expect(liveAppWebview.selectAssetSearchBar).toBeEnabled();
});

await test.step("Request Account - select BTC", async () => {
await liveAppWebview.selectAccount();
await drawer.selectAccount("Bitcoin", 0);
await drawer.waitForDrawerToDisappear();
await liveAppWebview.waitForCorrectTextInWebview("mock:1:bitcoin:true_bitcoin_0:");
});
Expand Down Expand Up @@ -99,9 +100,9 @@ test("Live App SDK methods @smoke", async ({ page }) => {
});

await test.step("Sign Transaction - confirmation modal", async () => {
await liveAppWebview.continueToSignTransaction();
await modal.continueToSignTransaction();
await layout.waitForLoadingSpinnerToHaveDisappeared();
await liveAppWebview.waitForConfirmationScreenToBeDisplayed();
await modal.waitForConfirmationScreenToBeDisplayed();
await expect(page.locator("text=0.0000123")).toBeVisible();
await expect(page.locator("text=0.0000025")).toBeVisible();
// This screenshot is flaky as the loading spinner appears again after this confirm modal, and on slow CI runners the screenshot can take a picture of this instead of the confirm.
Expand Down
19 changes: 11 additions & 8 deletions apps/ledger-live-desktop/tests/specs/services/swap.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,6 @@ test.describe.parallel("Swap", () => {
const drawer = new Drawer(page);
const layout = new Layout(page);

let swapId: string;
let detailsSwapId: string;

await page.route("https://swap.ledger.com/v4/providers**", async route => {
const mockProvidersResponse = getProvidersMock();
route.fulfill({ headers: { teststatus: "mocked" }, body: mockProvidersResponse });
Expand Down Expand Up @@ -221,16 +218,22 @@ test.describe.parallel("Swap", () => {
await test.step("Confirm swap with Nano App", async () => {
await deviceAction.confirmSwap();
await deviceAction.silentSign();
const originalSwapId = await swapPage.verifySuccessfulExchange();
swapId = originalSwapId.replace("#", "");
await swapPage.waitForSuccessfulExchange();
await expect.soft(swapPage.swapId).toHaveText("#12345");
await expect.soft(drawer.content).toHaveScreenshot("confirmed-swap.png");
});

await test.step("Verify Swap details are present in the exchange drawer", async () => {
await swapPage.navigateToExchangeDetails();
detailsSwapId = await swapPage.verifyExchangeDetails();
await expect(detailsSwapId).toEqual(swapId);
await expect.soft(drawer.content).toHaveScreenshot("verify-swap-details.png");
await swapPage.waitForExchangeDetails();
await expect.soft(swapPage.detailsSwapId).toHaveText("12345");
await expect.soft(drawer.swapAmountFrom).toContainText("-1.280"); // regex /-1.280\d+ BTC/ not working with toHaveText() and value can change after the first 3 decimals so this will have to do for now - see LIVE-8642
await expect.soft(drawer.swapAmountTo).toContainText("+17.898");
await expect.soft(drawer.swapAccountFrom).toHaveText("Bitcoin 2 (legacy)");
await expect.soft(drawer.swapAccountTo).toHaveText("Ethereum 2");

// Flaky due to LIVE-8642 - the formatting is sometimes different values - therefore we are doing the above text checks
// await expect.soft(drawer.content).toHaveScreenshot("verify-swap-details.png");
});

await test.step("Verify Swap details are present in the swap history", async () => {
Expand Down

1 comment on commit 27d522a

@vercel
Copy link

@vercel vercel bot commented on 27d522a Jul 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.