Skip to content

Commit

Permalink
#286 Add e2e tests for specifications pages (#298)
Browse files Browse the repository at this point in the history
  • Loading branch information
nevendyulgerov authored Jan 21, 2025
1 parent 72ec8fd commit d606826
Show file tree
Hide file tree
Showing 3 changed files with 267 additions and 1 deletion.
34 changes: 34 additions & 0 deletions apps/web/e2e/pages/specifications.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { expect, test } from "@playwright/test";

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

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

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

test("should display empty state", async ({ page }) => {
await expect(page.getByText("No Specifications Found!")).toBeVisible();
await expect(page.getByText("Create one")).toBeVisible();
await expect(page.getByText("Import specifications")).toBeVisible();
});

test("should open file chooser when 'Import Specifications' is clicked", async ({
page,
}) => {
const importSpecificationsButton = page.getByText("Import specifications");
await expect(importSpecificationsButton).toBeVisible();

const fileChooserPromise = page.waitForEvent("filechooser");
await importSpecificationsButton.click();

const fileChooser = await fileChooserPromise;

expect(fileChooser.isMultiple()).toBe(false);
});
231 changes: 231 additions & 0 deletions apps/web/e2e/pages/specificationsNew.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
import { expect, test } from "@playwright/test";

test.beforeEach(async ({ page }) => {
await page.goto("/specifications/new");
});

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

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

test("should create JSON ABI spec", async ({ page }) => {
const name = "My E2E JSON ABI spec";
const nameInput = page.getByTestId("specification-name-input");
await nameInput.focus();
await page.keyboard.type(name);

const jsonAbiTextarea = page.getByTestId("human-readable-abi-input");
await jsonAbiTextarea.focus();

const jsonAbiSpec =
"struct User { string name; uint amount; address}\n" +
"function createAccount(User user, string role)\n" +
"function deposit(User user, address from, string reason)";
await page.keyboard.type(jsonAbiSpec);

const saveButton = page.getByTestId("specification-form-save");
await saveButton.click();

await expect(page.getByText(`Specification ${name} Saved!`)).toBeVisible();
await page.goto("/specifications");
await expect(page.getByText(name)).toBeVisible();
});

test("should create ABI Parameters spec", async ({ page }) => {
const abiParametersTab = page.getByText("ABI Parameters");
await abiParametersTab.click();

const name = "My ABI Parameters spec";
const nameInput = page.getByTestId("specification-name-input");
await nameInput.focus();
await page.keyboard.type(name);

const abiParameterInput = page.getByPlaceholder(
"address to, uint256 amount, bool succ",
);
await abiParameterInput.focus();

const abiParametersSpec =
"address to, uint256 amount, (uint256 counter, string name) structy";
await page.keyboard.type(abiParametersSpec);

const addButton = page.getByTestId("abi-parameter-add-button");
await addButton.click();

const saveButton = page.getByTestId("specification-form-save");
await saveButton.click();

await expect(page.getByText(`Specification ${name} Saved!`)).toBeVisible();
await page.goto("/specifications");
await expect(page.getByText(name)).toBeVisible();
});

test("should validate JSON ABI spec", async ({ page }) => {
const saveButton = page.getByTestId("specification-form-save");
await saveButton.click();

await expect(page.getByText("Name is required.")).toBeVisible();
await expect(
page.getByText("The ABI is required on JSON ABI mode."),
).toBeVisible();

const name = "My JSON ABI spec";
const nameInput = page.getByTestId("specification-name-input");
await nameInput.focus();
await page.keyboard.type(name);

const jsonAbiSpec = "invalid abi spec";
const jsonAbiTextarea = page.getByTestId("human-readable-abi-input");
await jsonAbiTextarea.focus();
await page.keyboard.type(jsonAbiSpec);

await expect(
page.getByText(
`Unknown signature. Details: ${jsonAbiSpec} Version: [email protected]`,
),
).toBeVisible();

await saveButton.click();

await expect(
page.getByText("The ABI is required on JSON ABI mode."),
).toBeVisible();

await expect(
page.getByText(`Specification ${name} Saved!`),
).not.toBeVisible({
timeout: 300,
});
});

// TODO: Resume using this test after https://github.com/cartesi/rollups-explorer/issues/297 is tackled
test.skip("should validate ABI Parameters spec", async ({ page }) => {
const abiParametersTab = page.getByText("ABI Parameters");
await abiParametersTab.click();

const saveButton = page.getByTestId("specification-form-save");
await saveButton.click();

await expect(page.getByText("Name is required.")).toBeVisible();
await expect(
page.getByText(
"At least one ABI parameter is required when not defining the byte range slices.",
),
).toBeVisible();

const name = "My ABI Parameters spec";
const nameInput = page.getByTestId("specification-name-input");
await nameInput.focus();
await page.keyboard.type(name);

const abiParameterInput = page.getByPlaceholder(
"address to, uint256 amount, bool succ",
);
await abiParameterInput.focus();

const abiParametersSpec = "invalid-abi-parameter";
await page.keyboard.type(abiParametersSpec);

const addButton = page.getByTestId("abi-parameter-add-button");
await addButton.click();

await expect(
page.getByText(
`Invalid ABI parameter. Details: ${abiParametersSpec} Version: [email protected]`,
),
).toBeVisible();

await saveButton.click();
await expect(
page.getByText(`Specification ${name} Saved!`),
).not.toBeVisible({
timeout: 300,
});
});

test("should be able to edit JSON ABI spec", async ({ page }) => {
const name = "My E2E JSON ABI spec";
const nameInput = page.getByTestId("specification-name-input");
await nameInput.focus();
await page.keyboard.type(name);

const jsonAbiTextarea = page.getByTestId("human-readable-abi-input");
await jsonAbiTextarea.focus();

const jsonAbiSpec =
"struct User { string name; uint amount; address}\n" +
"function createAccount(User user, string role)\n" +
"function deposit(User user, address from, string reason)";
await page.keyboard.type(jsonAbiSpec);

const saveButton = page.getByTestId("specification-form-save");
await saveButton.click();

await expect(page.getByText(`Specification ${name} Saved!`)).toBeVisible();
await page.goto("/specifications");
await expect(page.getByText(name)).toBeVisible();

const gridCell = page.getByRole("gridcell");
const testId = await gridCell.getAttribute("data-testid");
const specId = testId
?.replace("specification", "")
.replace("card", "")
.slice(1)
.slice(0, -1);

const editButton = page.getByTestId(`edit-specification-${specId}`);
await editButton.click();
await page.waitForURL(`/specifications/edit/${specId}`);

const savedNameInput = await page
.getByTestId("specification-name-input")
.inputValue();

expect(savedNameInput).toBe(name);
});

test("should be able to delete JSON ABI spec", async ({ page }) => {
const name = "My E2E JSON ABI spec";
const nameInput = page.getByTestId("specification-name-input");
await nameInput.focus();
await page.keyboard.type(name);

const jsonAbiTextarea = page.getByTestId("human-readable-abi-input");
await jsonAbiTextarea.focus();

const jsonAbiSpec =
"struct User { string name; uint amount; address}\n" +
"function createAccount(User user, string role)\n" +
"function deposit(User user, address from, string reason)";
await page.keyboard.type(jsonAbiSpec);

const saveButton = page.getByTestId("specification-form-save");
await saveButton.click();

await expect(page.getByText(`Specification ${name} Saved!`)).toBeVisible();
await page.goto("/specifications");
await expect(page.getByText(name)).toBeVisible();

let gridCell = page.getByRole("gridcell");
const testId = await gridCell.getAttribute("data-testid");
const specId = testId
?.replace("specification", "")
.replace("card", "")
.slice(1)
.slice(0, -1);

const deleteButton = page.getByTestId(`remove-specification-${specId}`);
await deleteButton.click();

await expect(page.getByText("Delete specification?")).toBeVisible();
await page.getByText("Confirm").click();

await expect(gridCell).not.toBeVisible();
});
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,6 @@ export const SpecificationListView: FC = () => {
</Button>
</Group>
</Modal>

<Stack>
<Flex justify="stretch">
<Group mr="auto">
Expand Down Expand Up @@ -377,12 +376,14 @@ export const SpecificationListView: FC = () => {
justify="flex-start"
align="stretch"
data-testid="specs-grid"
role="grid"
>
{filteredSpecs?.map((spec, idx) => (
<Grid.Col span={{ base: 12, md: 6 }} key={spec.id}>
<Card
style={{ minHeight: CARD_MIN_HEIGHT }}
data-testid={`specification-${spec.id}-card`}
role="gridcell"
>
<Card.Section
inheritPadding
Expand Down

0 comments on commit d606826

Please sign in to comment.