Skip to content

Commit

Permalink
Use page objects in SelectNetworkDropdown.spec.ts (#6415)
Browse files Browse the repository at this point in the history
# Motivation

Make the test easier to read and maintain.

# Changes

1. Add `SelectNetworkDropdownPo` which just extends `DropdownPo`.
2. Add extra functionality to `DropdownPo`.
3. Use `SelectNetworkDropdownPo` in `SelectNetworkDropdown.spec.ts`.

# Tests

<!-- Please provide any information or screenshots about the tests that
have been done -->

# Todos

- [ ] Add entry to changelog (if necessary).
not necessary
  • Loading branch information
dskloetd authored Feb 13, 2025
1 parent 3d3d3f9 commit 3021c34
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,135 +4,140 @@ import {
CKTESTBTC_UNIVERSE_CANISTER_ID,
} from "$lib/constants/ckbtc-canister-ids.constants";
import { TransactionNetwork } from "$lib/types/transaction";
import type { UniverseCanisterId } from "$lib/types/universe";
import {
mockBTCAddressMainnet,
mockBTCAddressTestnet,
mockCkBTCAddress,
} from "$tests/mocks/ckbtc-accounts.mock";
import en from "$tests/mocks/i18n.mock";
import { fireEvent, render, waitFor } from "@testing-library/svelte";
import { SelectNetworkDropdownPo } from "$tests/page-objects/SelectNetworkDropdown.page-object";
import { JestPageObjectElement } from "$tests/page-objects/jest.page-object";
import { render } from "@testing-library/svelte";
import { get, writable, type Writable } from "svelte/store";

describe("SelectNetworkDropdown", () => {
const props = { universeId: CKBTC_UNIVERSE_CANISTER_ID };

it("should render a select component", () => {
const { getByTestId } = render(SelectNetworkDropdown, { props });
const renderComponent = ({
universeId,
selectedDestinationAddress,
selectedNetwork,
}: {
universeId: UniverseCanisterId;
selectedDestinationAddress?: string;
selectedNetwork?: Writable<TransactionNetwork>;
}) => {
const { container, component } = render(SelectNetworkDropdown, {
props: {
universeId,
selectedDestinationAddress,
selectedNetwork: get(selectedNetwork),
},
});

expect(getByTestId("select-network-dropdown")).not.toBeNull();
});
const updateSelectedNetwork = () => {
selectedNetwork.set(
component.$$.ctx[component.$$.props["selectedNetwork"]]
);
};

it("should display a disable placeholder", () => {
const { container } = render(SelectNetworkDropdown, { props });
if (selectedNetwork) {
component.$$.update = updateSelectedNetwork;
updateSelectedNetwork();
}

const option = container.querySelector("option[disabled]");
selectedNetwork?.subscribe((network) => {
component.$set({ selectedNetwork: network });
});

expect(option).not.toBeNull();
expect(option?.getAttribute("value")).toEqual("");
});
return SelectNetworkDropdownPo.under(new JestPageObjectElement(container));
};

it("should display an option to select ICP", () => {
const { container } = render(SelectNetworkDropdown, { props });
it("should render a select component", async () => {
const po = renderComponent(props);

const option = container.querySelector("option[value='network_icp']");
expect(await po.isPresent()).toBe(true);
});

expect(option).not.toBeNull();
expect(option.innerHTML).toEqual(en.accounts.network_icp);
it("should display a disable placeholder", async () => {
const po = renderComponent(props);

expect(await po.isDisabled(0)).toBe(true);
expect(await po.getOptionValue(0)).toBe("");
});

it("should display an option to select bitcoin", () => {
const { container } = render(SelectNetworkDropdown, { props });
it("should display an option to select ICP", async () => {
const po = renderComponent(props);

const option = container.querySelector(
"option[value='network_btc_mainnet']"
);
expect(await po.getOption(1)).toBe("Internet Computer");
expect(await po.isDisabled(1)).toBe(false);
expect(await po.getOptionValue(1)).toBe("network_icp");
});

it("should display an option to select bitcoin", async () => {
const po = renderComponent(props);

expect(option).not.toBeNull();
expect(option.innerHTML).toEqual(en.accounts.network_btc_mainnet);
expect(await po.getOption(2)).toBe("Bitcoin");
expect(await po.isDisabled(2)).toBe(false);
expect(await po.getOptionValue(2)).toBe("network_btc_mainnet");
});

it("should bind select to selected network", async () => {
const { getByTestId, component, container } = render(
SelectNetworkDropdown,
{ props }
);
const selectedNetwork = writable<TransactionNetwork>(undefined);
const po = renderComponent({
...props,
selectedNetwork,
});

const optionDefault = container.querySelector("option[disabled]");
expect(optionDefault).not.toBeNull();

const selectElement = getByTestId(
"select-network-dropdown"
) as HTMLSelectElement | null;
selectElement &&
fireEvent.change(selectElement, {
target: { value: TransactionNetwork.ICP },
});

await waitFor(() =>
expect(component.$$.ctx[component.$$.props["selectedNetwork"]]).toEqual(
TransactionNetwork.ICP
)
);
expect(get(selectedNetwork)).toBe(undefined);
await po.select("Internet Computer");
expect(get(selectedNetwork)).toBe(TransactionNetwork.ICP);
});

it("should auto select ckBTC network", async () => {
const { component } = render(SelectNetworkDropdown, {
props: {
...props,
selectedDestinationAddress: mockCkBTCAddress,
},
it("should auto select ICP network", async () => {
const selectedNetwork = writable<TransactionNetwork>(undefined);
renderComponent({
...props,
selectedDestinationAddress: mockCkBTCAddress,
selectedNetwork,
});

await waitFor(() =>
expect(component.$$.ctx[component.$$.props["selectedNetwork"]]).toEqual(
TransactionNetwork.ICP
)
);
expect(get(selectedNetwork)).toBe(TransactionNetwork.ICP);
});

it("should auto select BTC testnet network", async () => {
const { component } = render(SelectNetworkDropdown, {
props: {
...props,
universeId: CKTESTBTC_UNIVERSE_CANISTER_ID,
selectedDestinationAddress: mockBTCAddressTestnet,
},
const selectedNetwork = writable<TransactionNetwork>(undefined);
renderComponent({
...props,
universeId: CKTESTBTC_UNIVERSE_CANISTER_ID,
selectedDestinationAddress: mockBTCAddressTestnet,
selectedNetwork,
});

await waitFor(() =>
expect(component.$$.ctx[component.$$.props["selectedNetwork"]]).toEqual(
TransactionNetwork.BTC_TESTNET
)
);
expect(get(selectedNetwork)).toBe(TransactionNetwork.BTC_TESTNET);
});

it("should auto select BTC mainnet network", async () => {
const { component } = render(SelectNetworkDropdown, {
props: {
...props,
selectedDestinationAddress: mockBTCAddressMainnet,
},
const selectedNetwork = writable<TransactionNetwork>(undefined);
renderComponent({
...props,
selectedDestinationAddress: mockBTCAddressMainnet,
selectedNetwork,
});

await waitFor(() =>
expect(component.$$.ctx[component.$$.props["selectedNetwork"]]).toEqual(
TransactionNetwork.BTC_MAINNET
)
);
expect(get(selectedNetwork)).toBe(TransactionNetwork.BTC_MAINNET);
});

it("should auto not select BTC mainnet network", async () => {
const { component } = render(SelectNetworkDropdown, {
props: {
...props,
selectedNetwork: TransactionNetwork.ICP,
selectedDestinationAddress: mockBTCAddressMainnet,
},
const selectedNetwork = writable<TransactionNetwork>(
TransactionNetwork.ICP
);
renderComponent({
...props,
selectedDestinationAddress: mockBTCAddressMainnet,
selectedNetwork,
});

await waitFor(() =>
expect(
component.$$.ctx[component.$$.props["selectedNetwork"]]
).not.toEqual(TransactionNetwork.BTC_MAINNET)
);
expect(get(selectedNetwork)).toBe(TransactionNetwork.ICP);
});
});
19 changes: 19 additions & 0 deletions frontend/src/tests/page-objects/Dropdown.page-object.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BasePageObject } from "$tests/page-objects/base.page-object";
import type { PageObjectElement } from "$tests/types/page-object.types";
import { nonNullish } from "@dfinity/utils";

export class DropdownPo extends BasePageObject {
private static readonly TID = "dropdown-component";
Expand All @@ -20,4 +21,22 @@ export class DropdownPo extends BasePageObject {
async waitForOption(testId: string): Promise<void> {
return this.root.byTestId(testId).waitFor();
}

private getOptionElement(optionIndex: number): PageObjectElement {
return this.root.querySelector(`option:nth-child(${optionIndex + 1})`);
}

async getOption(optionIndex: number): Promise<string> {
return await this.getOptionElement(optionIndex).getText();
}

async isDisabled(optionIndex: number): Promise<boolean> {
const value =
await this.getOptionElement(optionIndex).getAttribute("disabled");
return nonNullish(value);
}

async getOptionValue(optionIndex: number): Promise<string> {
return await this.getOptionElement(optionIndex).getAttribute("value");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { DropdownPo } from "$tests/page-objects/Dropdown.page-object";

export class SelectNetworkDropdownPo extends DropdownPo {}

0 comments on commit 3021c34

Please sign in to comment.