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

#183 Add e2e tests for inputs page #187

Merged
merged 4 commits into from
Jun 25, 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
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 @@ -50,6 +50,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
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ RUN apk add --no-cache libc6-compat
RUN apk update

WORKDIR /app
RUN yarn global add turbo
RUN yarn global add turbo@1.13.3
COPY . .
RUN turbo prune --scope=web --docker

Expand Down
9 changes: 9 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2262,6 +2262,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
Loading