Skip to content

Commit

Permalink
List tests page
Browse files Browse the repository at this point in the history
  • Loading branch information
AHarmlessPyro committed Aug 18, 2022
1 parent 6bc9840 commit 39bf933
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 10 deletions.
3 changes: 2 additions & 1 deletion backend/src/api/tests/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ export const listTests = async (req: Request, res: Response): Promise<void> => {
const { uuid } = req.params;

let resp = await AppDataSource.getRepository(ApiEndpointTest)
.createQueryBuilder()
.createQueryBuilder("test")
.select()
.leftJoinAndSelect("test.apiEndpoint", "apiEndpoint")
.getMany();

await ApiResponseHandler.success(res, resp);
Expand Down
4 changes: 2 additions & 2 deletions backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ app.post("/api/v1/update_connection", update_connection);
app.post("/api/v1/test/run", runTestHandler);

app.post("/api/v1/test/save", saveTest);
app.get("/api/v1/tests/list", listTests);
app.get("/api/v1/tests/list/:uuid", getTest);
app.get("/api/v1/test/list", listTests);
app.get("/api/v1/test/list/:uuid", getTest);

const main = async () => {
try {
Expand Down
9 changes: 9 additions & 0 deletions common/src/testing/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ApiEndpoint } from "../types";
import { RestMethod } from "../enums";
import { APIKeyAuthAddTo, AuthType, RequestBodyType } from "./enums";

Expand Down Expand Up @@ -66,3 +67,11 @@ export interface Test {
tags: string[];
requests: Request[];
}

export interface TestDetailed {
uuid: string;
name: string;
tags: string[];
requests: Request[];
apiEndpoint: ApiEndpoint;
}
6 changes: 5 additions & 1 deletion frontend/src/api/tests/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import axios from "axios";
import { getAPIURL } from "~/constants";
import { Test } from "@common/testing/types";
import { TestDetailed, Test } from "@common/testing/types";

export const runTest = async (test: Test) => {
const resp = await axios.post<any>(`${getAPIURL()}/test/run`, {
test,
});
};

export const listTests = async () => {
const resp = await axios.get<Array<TestDetailed>>(`${getAPIURL()}/test/list`);
return resp;
};

export const saveTest = async (test: Test, endpoint_uuid: string) => {
const resp = await axios.post<any>(`${getAPIURL()}/test/save`, {
Expand Down
88 changes: 88 additions & 0 deletions frontend/src/components/TestList/List.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React from "react";
import { useRouter } from "next/router";
import { Badge, Text, useColorMode, VStack } from "@chakra-ui/react";
import DataTable, { TableColumn } from "react-data-table-component";
import { getCustomStyles, rowStyles } from "components/utils/TableUtils";
import { TestDetailed } from "@common/testing/types";
import { RISK_TO_COLOR } from "~/constants";

interface TestListProps {
tests: TestDetailed[];
}

const TestList: React.FC<TestListProps> = React.memo(({ tests }) => {
const router = useRouter();
const colorMode = useColorMode();
const onRowClicked = (
row: TestDetailed,
e: React.MouseEvent<Element, MouseEvent>
) => {
router.push(`/test/${row.uuid}`);
};
const columns: TableColumn<TestDetailed>[] = [
{
name: "Name",
sortable: true,
selector: (row: TestDetailed) => row.name || "",
id: "name",
},
{
name: "Tags",
sortable: true,
selector: (row: TestDetailed) => row.tags?.join(", ") || "",
cell: (row: TestDetailed) => (
<VStack alignItems="flex-start" py="2">
{row.tags?.map((tag, idx) => (
<Badge key={idx}>{tag}</Badge>
))}
</VStack>
),
id: "hosts",
},
{
name: "Requests",
sortable: true,
selector: (row: TestDetailed) => row.tags?.join(", ") || "",
cell: (row: TestDetailed) => (
<VStack
alignItems="flex-start"
py="2"
overflow={"hidden"}
textOverflow={"ellipsis"}
>
{row.requests?.map((req, idx) => (
<Badge key={idx}>{req.url}</Badge>
))}
</VStack>
),
id: "requests",
},
{
name: "Endpoint Risk",
sortable: true,
selector: (row: TestDetailed) => row.apiEndpoint.riskScore || "",
cell: (row: TestDetailed) => (
<Badge
p="1"
fontSize="sm"
colorScheme={RISK_TO_COLOR[row.apiEndpoint.riskScore]}
pointerEvents="none"
>
{row.apiEndpoint.riskScore}
</Badge>
),
id: "endpointRisk",
},
];
return (
<DataTable
style={rowStyles}
columns={columns}
data={tests}
onRowClicked={onRowClicked}
customStyles={getCustomStyles(colorMode.colorMode)}
/>
);
});

export default TestList;
23 changes: 23 additions & 0 deletions frontend/src/components/TestList/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";
import { Box, VStack } from "@chakra-ui/react";
import List from "./List";
import { Test, TestDetailed } from "@common/testing/types";

const ListTests: React.FC<{ tests: Array<TestDetailed> }> = React.memo(
({ tests }) => (
<VStack
w="full"
alignItems="flex-start"
borderWidth="1px"
rounded="md"
spacing="0"
overflow="hidden"
>
<Box w="full">
<List tests={tests} />
</Box>
</VStack>
)
);

export default ListTests;
22 changes: 16 additions & 6 deletions frontend/src/pages/tests.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
import { Heading, VStack } from "@chakra-ui/react";
import { SideNavLinkDestination } from "components/Sidebar/NavLinkUtils";
import { GetServerSideProps } from "next";
import { listTests } from "~/api/tests";
import { SidebarLayoutShell } from "~/components/SidebarLayoutShell";
import ListTests from "~/components/TestList";
import { ContentContainer } from "~/components/utils/ContentContainer";
import superjson from "superjson";

const Tests = () => (
<SidebarLayoutShell
title="Tests"
currentTab={SideNavLinkDestination.Tests}
>
export const getServerSideProps: GetServerSideProps = async (context) => {
const tests = await listTests();
return {
props: {
tests: superjson.stringify(tests.data),
},
};
};

const Tests = ({ tests }) => (
<SidebarLayoutShell title="Tests" currentTab={SideNavLinkDestination.Tests}>
<ContentContainer>
<VStack w="full" alignItems="flex-start">
<Heading fontWeight="medium" size="xl" mb="8">
Tests
</Heading>
<ListTests tests={superjson.parse(tests)} />
</VStack>
</ContentContainer>
</SidebarLayoutShell>
);

export default Tests;

0 comments on commit 39bf933

Please sign in to comment.