Skip to content

Commit

Permalink
#186 Add input completion status (#198)
Browse files Browse the repository at this point in the history
  • Loading branch information
nevendyulgerov authored Jul 14, 2024
1 parent 39e1921 commit 30e4df3
Show file tree
Hide file tree
Showing 14 changed files with 450 additions and 13 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,12 @@ jobs:

- name: Run e2e tests
run: yarn test:e2e
id: e2e
continue-on-error: true
env:
E2E_BASE_URL: ${{ github.event.deployment_status.environment_url }}

- name: Update check status to the outcome
run: yarn node reportGitHubCheckStatus.mjs "End-to-end (${{ github.event.deployment_status.environment }})" ${{ github.sha }} ${{ steps.e2e.outcome }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6 changes: 4 additions & 2 deletions apps/web/e2e/menu.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ test.describe("Navigations", () => {

// Verify that table with correct columns is visible
await expect(
page.getByRole("row", { name: "From To Method Index Age Data" }),
page.getByRole("row", {
name: "From To Method Index Status Age Data",
}),
).toBeVisible();

// Verify table rows' count. For each input row it actually inserts 3 <tr>
Expand Down Expand Up @@ -152,7 +154,7 @@ test.describe("Navigations", () => {
// Verify that table with correct columns is visible
await expect(
page.getByRole("row", {
name: "From To Method Index Age Data",
name: "From To Method Index Status Age Data",
}),
).toBeVisible();

Expand Down
6 changes: 3 additions & 3 deletions apps/web/e2e/pages/applicationInputs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ test("should have correct title", async ({ page }) => {

test("should display inputs table", async ({ page }) => {
await expect(
page.getByRole("row", { name: "From To Method Index Age Data" }),
page.getByRole("row", { name: "From To Method Index Status Age Data" }),
).toBeVisible();
await expect(page.getByRole("row")).toHaveCount(31);
});
Expand All @@ -26,15 +26,15 @@ test("should toggle date column", async ({ page }) => {

await expect(
page.getByRole("row", {
name: "From To Method Index Timestamp (UTC) Data",
name: "From To Method Index Status Timestamp (UTC) Data",
}),
).toBeVisible();

const timestampHeaderColumn = page.getByText("Timestamp (UTC)");
await timestampHeaderColumn.click();

await expect(
page.getByRole("row", { name: "From To Method Index Age Data" }),
page.getByRole("row", { name: "From To Method Index Status Age Data" }),
).toBeVisible();
});

Expand Down
2 changes: 1 addition & 1 deletion apps/web/e2e/pages/inputs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ test("should have correct title", async ({ page }) => {

test("should display 'All inputs' table", async ({ page }) => {
await expect(
page.getByRole("row", { name: "From To Method Index Age Data" }),
page.getByRole("row", { name: "From To Method Index Status Age Data" }),
).toBeVisible();
await expect(page.getByRole("row")).toHaveCount(31);
});
Expand Down
7 changes: 6 additions & 1 deletion apps/web/graphql/rollups/queries.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ query inputDetails (
}
}


query checkStatus {
inputs {
totalCount
Expand All @@ -97,4 +96,10 @@ query checkStatus {
notices {
totalCount
}
}

query inputStatus($index: Int!) {
input(index: $index) {
status
}
}
51 changes: 51 additions & 0 deletions apps/web/src/components/connection/connectionInputStatusBadge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"use client";
import { Badge, Loader } from "@mantine/core";
import React, { FC, useMemo } from "react";
import { useQuery } from "urql";
import {
InputStatusDocument,
InputStatusQuery,
InputStatusQueryVariables,
} from "../../graphql/rollups/operations";

interface ConnectionInputStatusBadgeProps {
graphqlUrl: string;
index: number;
}

const ConnectionInputStatusBadge: FC<ConnectionInputStatusBadgeProps> = ({
graphqlUrl,
index,
}) => {
const [result] = useQuery<InputStatusQuery, InputStatusQueryVariables>({
context: useMemo(
() => ({
url: graphqlUrl,
}),
[graphqlUrl],
),
query: InputStatusDocument,
variables: {
index,
},
});

return (
<>
{result.fetching ? (
<Loader
data-testid="connection-input-status-loader"
size="xs"
/>
) : result.data?.input.status ? (
<Badge variant="default" style={{ textTransform: "none" }}>
{result.data.input.status}
</Badge>
) : (
"N/A"
)}
</>
);
};

export default ConnectionInputStatusBadge;
30 changes: 28 additions & 2 deletions apps/web/src/components/inputs/inputRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,20 @@ import {
Paper,
Table,
Text,
Tooltip,
} from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import prettyMilliseconds from "pretty-ms";
import { FC } from "react";
import { TbArrowRight, TbFileText, TbX } from "react-icons/tb";
import React, { FC } from "react";
import { TbArrowRight, TbFileText, TbQuestionMark, TbX } from "react-icons/tb";
import { Address as AddressType, formatUnits } from "viem";
import { InputItemFragment } from "../../graphql/explorer/operations";
import Address from "../address";
import InputDetailsView from "./inputDetailsView";
import { methodResolver } from "../../lib/methodResolver";
import { useConnectionConfig } from "../../providers/connectionConfig/hooks";
import { Connection } from "../../providers/connectionConfig/types";
import ConnectionInputStatusBadge from "../connection/connectionInputStatusBadge";

export type InputRowProps = {
input: InputItemFragment;
Expand All @@ -33,6 +37,8 @@ const InputRow: FC<InputRowProps> = ({
const [opened, { toggle }] = useDisclosure(false);
const from = input.msgSender as AddressType;
const to = input.application.id as AddressType;
const { getConnection, hasConnection, showConnectionModal } =
useConnectionConfig();

const erc20Deposit = (input: InputItemFragment) =>
input.erc20Deposit ? (
Expand Down Expand Up @@ -119,6 +125,26 @@ const InputRow: FC<InputRowProps> = ({
<Table.Td>
<Text>{input.index}</Text>
</Table.Td>
<Table.Td>
{hasConnection(to) ? (
<ConnectionInputStatusBadge
graphqlUrl={(getConnection(to) as Connection).url}
index={input.index}
/>
) : (
<Tooltip label="Click to add a connection and inspect the input status.">
<ActionIcon
size="xs"
radius={50}
ml={4}
data-testid="show-connection-modal"
onClick={() => showConnectionModal(to)}
>
<TbQuestionMark />
</ActionIcon>
</Tooltip>
)}
</Table.Td>
<Table.Td>
<Box
display="flex"
Expand Down
16 changes: 16 additions & 0 deletions apps/web/src/components/inputs/inputsTable.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
"use client";
import {
ActionIcon,
Button,
Flex,
Loader,
Table,
Text,
Tooltip,
Transition,
useMantineColorScheme,
useMantineTheme,
} from "@mantine/core";
import { FC, useCallback, useRef, useState } from "react";
import { TbQuestionMark } from "react-icons/tb";
import type { InputItemFragment } from "../../graphql/explorer/operations";
import { useElementVisibility } from "../../hooks/useElementVisibility";
import TableResponsiveWrapper from "../tableResponsiveWrapper";
Expand Down Expand Up @@ -47,6 +51,18 @@ const InputsTable: FC<InputsTableProps> = ({
<Table.Th>To</Table.Th>
<Table.Th>Method</Table.Th>
<Table.Th>Index</Table.Th>
<Table.Th>
<Tooltip label="Check the status by adding a connection. Click the ? in the row to add a connection.">
<Flex align="center">
<Text size="sm" fw={600}>
Status
</Text>
<ActionIcon size="xs" radius={50} ml={4}>
<TbQuestionMark />
</ActionIcon>
</Flex>
</Tooltip>
</Table.Th>
<Table.Th>
<Button
variant="transparent"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { describe, it, beforeEach, expect } from "vitest";
import { render, screen } from "@testing-library/react";
import { useQuery } from "urql";
import ConnectionInputStatusBadge from "../../../src/components/connection/connectionInputStatusBadge";
import { withMantineTheme } from "../../utils/WithMantineTheme";

vi.mock("urql");
const useQueryMock = vi.mocked(useQuery, true);

const Component = withMantineTheme(ConnectionInputStatusBadge);

const defaultProps = {
graphqlUrl: "https://drawingcanvas.fly.dev/graphql",
index: 0,
};

const defaultData = {
input: {
status: "ACTIVE",
},
};

describe("ConnectionInputStatusBadge component", () => {
beforeEach(() => {
useQueryMock.mockReturnValue([
{
fetching: false,
data: defaultData,
},
] as any);
});

afterEach(() => {
vi.clearAllMocks();
});

it("should display loading UI while fetching data", () => {
useQueryMock.mockReturnValue([
{
fetching: true,
},
] as any);
render(<Component {...defaultProps} />);

expect(
screen.getByTestId("connection-input-status-loader"),
).toBeInTheDocument();
});

it("should display correct status", () => {
render(<Component {...defaultProps} />);
expect(screen.getByText(defaultData.input.status)).toBeInTheDocument();
});

it("should display not available label when status is unavailable", () => {
useQueryMock.mockReturnValue([
{
fetching: false,
data: {
input: {
status: undefined,
},
},
},
] as any);
render(<Component {...defaultProps} />);
expect(screen.getByText("N/A")).toBeInTheDocument();
});
});
Loading

0 comments on commit 30e4df3

Please sign in to comment.