Skip to content

Commit

Permalink
#183 Add e2e tests for inputs page (#187)
Browse files Browse the repository at this point in the history
Co-authored-by: Bruno Menezes <brunodmenezes@gmail.com>
  • Loading branch information
nevendyulgerov and brunomenezes committed Jun 25, 2024
1 parent 72cfb78 commit 1f4385c
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 4 deletions.
10 changes: 9 additions & 1 deletion apps/web/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,20 @@ const generateConfig = (configs: CommonConfig[]): Generates => {
schema,
documents,
preset: "import-types",
plugins: ["typescript-operations", "typescript-urql"],
plugins: [
"typescript-operations",
"typescript-urql",
"named-operations-object",
],
presetConfig: {
typesPath: `.${sep}types`,
},
config: {
withHooks: false,
// named-operations-object plugin configs
enumAsTypes: true,
useConsts: true,
identifierName: "allOperations",
},
},
[join(path, "hooks", "queries.tsx")]: {
Expand Down
50 changes: 50 additions & 0 deletions apps/web/e2e/fixtures/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Page, Route, test as baseTest } from "@playwright/test";

/**
* For validations purposes if needed. e.g. check if API
* was called correctly.
*/
type CalledWith = Record<string, unknown>;

/**
* Function to register as an interceptor.
* Interceptions are per-operation, so multiple can be registered without the risk
* of overwriting one another.
* @param page {Page} playwright page client.
* @param operationName Graphql operation name.
* @param resp The expected return for the mock.
* @returns
*/
export async function interceptGQL(
page: Page,
operationName: string,
resp: Record<string, unknown>,
): Promise<CalledWith[]> {
const reqs: CalledWith[] = [];

await page.route("**/graphql", function (route: Route) {
const req = route.request().postDataJSON();

// Pass along to the previous handler in case the operation does not match.
if (req.operationName !== operationName) {
return route.fallback();
}

// Store what variables the API was called with;
reqs.push(req.variables);

return route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ data: resp }),
});
});

return reqs;
}

export const test = baseTest.extend<{ interceptGQL: typeof interceptGQL }>({
interceptGQL: async ({ browser }, use) => {
await use(interceptGQL);
},
});
12 changes: 10 additions & 2 deletions apps/web/e2e/pages/connections.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { expect, test } from "@playwright/test";
import { expect } from "@playwright/test";
import { Address } from "viem";
import { allOperations } from "../../src/graphql/rollups/operations";
import { test } from "../fixtures/test";
import { checkStatusSuccessResponse } from "../utils/checkStatus.data";
import { createConnection } from "../utils/connection";

test.beforeEach(async ({ page }) => {
test.beforeEach(async ({ page, interceptGQL }) => {
await page.goto("/connections");
await interceptGQL(
page,
allOperations.Query.checkStatus,
checkStatusSuccessResponse,
);
});

test("should have correct page title", async ({ page }) => {
Expand Down
82 changes: 82 additions & 0 deletions apps/web/e2e/pages/inputs.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { expect, test } from "@playwright/test";

test.beforeEach(async ({ page }) => {
await page.goto("inputs");
});

test("should have correct page title", async ({ page }) => {
await expect(page).toHaveTitle(/Inputs \| CartesiScan/);
});

test("should have correct title", async ({ page }) => {
const title = page.getByRole("heading", { name: "Inputs" });
await expect(title.first()).toBeVisible();
});

test("should display 'All inputs' table", async ({ page }) => {
await expect(
page.getByRole("row", { name: "From To Method Index Age Data" }),
).toBeVisible();
await expect(page.getByRole("row")).toHaveCount(31);
});

test("should open application inputs page", async ({ page }) => {
await expect(page.getByTestId("inputs-table-spinner")).not.toBeVisible();
const applicationSummaryLinks = page
.getByTestId("application-inputs-link")
.getByRole("link");

const firstLink = applicationSummaryLinks.first();
const href = (await firstLink.getAttribute("href")) as string;
const [hrefPart] = href
.split(/applications|inputs|\//)
.filter((p) => p !== "");

await firstLink.click();

await page.waitForURL(`/applications/${hrefPart}/inputs`);
});

test("should open input details", async ({ page }) => {
await expect(page.getByTestId("inputs-table-spinner")).not.toBeVisible();
const inputRowToggle = await page.getByTestId("input-row-toggle");

const firstInputRowToggle = inputRowToggle.first();
await firstInputRowToggle.click();
await expect(page.getByText("Notices")).toBeVisible();
await expect(page.getByText("Reports")).toBeVisible();
await expect(page.getByText("Vouchers")).toBeVisible();
await expect(page.getByText("Raw")).toBeVisible();
await expect(page.getByText("As Text")).toBeVisible();
await expect(page.getByText("As JSON")).toBeVisible();
});

test("should search for specific input", async ({ page }) => {
await expect(page.getByTestId("inputs-table-spinner")).not.toBeVisible();
let fromAddress = page
.getByTestId("application-from-address")
.getByRole("paragraph");

const firstLink = fromAddress.first();
const href = (await firstLink.textContent()) as string;
const [addressPrefix] = href.split("...");

const search = await page.getByTestId("search-input");
await search.focus();
await page.keyboard.type(addressPrefix);
await page.keyboard.press("Enter");
await page.waitForTimeout(2000);

fromAddress = page
.getByTestId("application-from-address")
.getByRole("paragraph");

const addresses = await fromAddress.all();
addresses.map(async (address) => {
const linkHref = (await address.textContent()) as string;

expect(
linkHref.toLowerCase().startsWith(addressPrefix.toLowerCase()),
).toBe(true);
});
});
14 changes: 14 additions & 0 deletions apps/web/e2e/utils/checkStatus.data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const checkStatusSuccessResponse = {
inputs: {
totalCount: 41,
},
vouchers: {
totalCount: 0,
},
reports: {
totalCount: 41,
},
notices: {
totalCount: 0,
},
};
2 changes: 1 addition & 1 deletion apps/web/e2e/utils/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Address } from "viem";
export const createConnection = async (
page: Page,
address: Address,
url = "https://honeypot.sepolia.rollups.staging.cartesi.io/graphql",
url = "http://rollups-mocked.calls.to/graphql",
) => {
// Find and click the button for displaying the connection modal
const button = page.getByTestId("add-connection");
Expand Down
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"@graphql-codegen/cli": "^5",
"@graphql-codegen/client-preset": "^4",
"@graphql-codegen/import-types-preset": "^3.0.0",
"@graphql-codegen/named-operations-object": "^3.0.0",
"@graphql-codegen/typed-document-node": "^5",
"@graphql-codegen/typescript": "^4",
"@graphql-codegen/typescript-operations": "^4",
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/components/inputs/inputRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ const InputRow: FC<InputRowProps> = ({
alignItems: "center",
justifyContent: "center",
}}
data-testid="application-inputs-link"
>
<Address
value={to}
Expand Down
9 changes: 9 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2258,6 +2258,15 @@
"@graphql-codegen/visitor-plugin-common" "2.13.1"
tslib "~2.6.0"

"@graphql-codegen/named-operations-object@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@graphql-codegen/named-operations-object/-/named-operations-object-3.0.0.tgz#2b5f718ffcfdd3202243c4a83bbc727cd914c8be"
integrity sha512-M9MKeTd7GINJQDV2iDvVjOJrLusU9om9rkizl6+z7xRiABA1cVz7s/trwi1hRHOpAE7Qe/k7ykRopRHysqzw5A==
dependencies:
"@graphql-codegen/plugin-helpers" "^3.0.0"
change-case-all "1.0.15"
tslib "~2.6.0"

"@graphql-codegen/plugin-helpers@^2.7.2":
version "2.7.2"
resolved "https://registry.yarnpkg.com/@graphql-codegen/plugin-helpers/-/plugin-helpers-2.7.2.tgz#6544f739d725441c826a8af6a49519f588ff9bed"
Expand Down

0 comments on commit 1f4385c

Please sign in to comment.