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

A single ftux integration test #84

Merged
merged 2 commits into from
May 9, 2023
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
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18.15'
node-version: '18.16'
cache: 'yarn'
- run: |
corepack enable
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:18.15-slim AS builder
FROM node:18.16-slim AS builder

ARG VITE_AUTH_URL=https://auth.aptible.com
ARG VITE_BILLING_URL=https://goldenboy.aptible.com
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
"@tailwindcss/forms": "^0.5.3",
"@tailwindcss/line-clamp": "^0.4.2",
"@tailwindcss/typography": "^0.5.9",
"@testing-library/dom": "^9.2.0",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"@types/debug": "^4.1.7",
"@types/node": "^18.11.18",
"@types/react": "^18.0.25",
Expand All @@ -40,6 +42,7 @@
"debug": "^4.3.4",
"history": "^5.3.0",
"jsdom": "^21.1.0",
"msw": "^1.2.1",
"postcss": "^8.4.21",
"qrcode.react": "^3.1.0",
"query-string": "^8.1.0",
Expand Down
2 changes: 1 addition & 1 deletion src/app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ftuxRouter, router } from "./router";
import { selectOrigin } from "@app/env";
import { RouterProvider } from "react-router";

const AppRouter = () => {
export const AppRouter = () => {
const origin = useSelector(selectOrigin);
return (
<div className="h-full w-full">
Expand Down
22 changes: 11 additions & 11 deletions src/app/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,12 @@ import {
} from "@app/ui";
import { ReactRouterErrorElement } from "@app/ui/shared/error-boundary";

const ftuxRoutes: RouteObject[] = [
const errorPatch = (appRoute: RouteObject) => ({
...appRoute,
errorElement: <ReactRouterErrorElement />,
});

export const ftuxRoutes: RouteObject[] = [
{
path: routes.HOME_PATH,
element: <AuthRequired />,
Expand Down Expand Up @@ -188,9 +193,9 @@ const ftuxRoutes: RouteObject[] = [
path: "*",
element: <NotFoundPage />,
},
];
].map(errorPatch);

const appRoutes: RouteObject[] = [
export const appRoutes: RouteObject[] = [
{
path: routes.HOME_PATH,
element: <AuthRequired />,
Expand Down Expand Up @@ -470,12 +475,7 @@ const appRoutes: RouteObject[] = [
path: "*",
element: <NotFoundPage />,
},
];

const errorPatch = (appRoute: RouteObject) => ({
...appRoute,
errorElement: <ReactRouterErrorElement />,
});
].map(errorPatch);

export const ftuxRouter = createBrowserRouter(ftuxRoutes.map(errorPatch));
export const router = createBrowserRouter(appRoutes.map(errorPatch));
export const ftuxRouter = createBrowserRouter(ftuxRoutes);
export const router = createBrowserRouter(appRoutes);
84 changes: 84 additions & 0 deletions src/app/test/create-project.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { act, fireEvent, render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

import { setupAppIntegrationTest } from "@app/test";

describe("Create project flow", () => {
describe("existing user with ssh keys", () => {
it("should successfully provision resources within an environment", async () => {
const { App } = setupAppIntegrationTest({
initEntries: ["/create"],
});
render(<App />);

// deploy code landing page
const el = await screen.findByRole("button");
expect(el.textContent).toEqual("Deploy your code");
// go to next page
fireEvent.click(el);

// create environment page
const nameInput = await screen.findByRole("textbox", { name: "name" });
await act(async () => {
await userEvent.type(nameInput, "test-project");
});

const btn = await screen.findByRole("button", {
name: /Create Environment/,
});
// go to next page
fireEvent.click(btn);

// push your code page
await screen.findByText(/Push your code to continue/);

// settings page
await screen.findByText(/Review your Settings/);

const banner = await screen.findByRole("status");
expect(banner.textContent).toMatch(/Your code has a Dockerfile/);

const dbBtn = await screen.findByRole("button", {
name: /New Database/,
});
fireEvent.click(dbBtn);

const dbSelector = await screen.findByRole("combobox");
userEvent.selectOptions(dbSelector, "postgres:14");
const dbEnvVar = await screen.findByRole("textbox", { name: "envvar" });
expect(dbEnvVar).toHaveDisplayValue("DATABASE_URL");

const saveBtn = await screen.findByRole("button", {
name: /Save & Deploy/,
});

// go to next page
fireEvent.click(saveBtn);

// status page
await screen.findByRole("button", {
name: "View Environment",
});
const status = await screen.findByText(/Deployed today/);
expect(status).toBeInTheDocument();

await screen.findByText("Initial configuration");
await screen.findByText("App deployment");
await screen.findByText("Database provision test-app-1-postgres");
let ops = await screen.findAllByText("DONE");
expect(ops.length).toEqual(3);

// create https endpoint
await screen.findByText("Which service needs an endpoint?");

const vhostSelector = await screen.findAllByRole("radio");
fireEvent.click(vhostSelector[0]);
const httpBtn = await screen.findByText("Create endpoint");
fireEvent.click(httpBtn);

await screen.findByText("HTTPS endpoint provision");
ops = await screen.findAllByText("DONE");
expect(ops.length).toEqual(4);
});
});
});
35 changes: 33 additions & 2 deletions src/deploy/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ import {
} from "../environment";
import { deserializeImage } from "../image";
import { deserializeDeployOperation, waitForOperation } from "../operation";
import { DeployServiceResponse } from "../service";
import { selectDeploy } from "../slice";

export * from "./utils";

export interface DeployAppResponse {
id: string;
id: number;
handle: string;
git_repo: string;
created_at: string;
Expand All @@ -40,13 +41,43 @@ export interface DeployAppResponse {
};
_embedded: {
// TODO: fill in
services: { id: number }[];
services: DeployServiceResponse[];
current_image: any;
last_deploy_operation: any;
last_operation: any;
};
_type: "app";
}

export const defaultAppResponse = (
p: Partial<DeployAppResponse> = {},
): DeployAppResponse => {
const now = new Date().toISOString();
return {
id: 1,
handle: "",
git_repo: "",
created_at: now,
updated_at: now,
deployment_method: "",
status: "provisioned",
_links: {
account: { href: "" },
current_configuration: { href: "" },
...p._links,
},
_embedded: {
services: [],
current_image: null,
last_deploy_operation: null,
last_operation: null,
...p._embedded,
},
...p,
_type: "app",
};
};

export const deserializeDeployApp = (payload: DeployAppResponse): DeployApp => {
const serviceIds: string[] = payload._embedded.services.map((s) => `${s.id}`);
const links = payload._links;
Expand Down
18 changes: 17 additions & 1 deletion src/deploy/code-scan-result/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,29 @@ export interface DeployCodeScanResponse {
dockerfile_present: boolean;
procfile_present: boolean;
_links: {
self: LinkResponse;
app: LinkResponse;
operation: LinkResponse;
};
_type: "code_scan_result";
}

export const defaultCodeScanResponse = (
c: Partial<DeployCodeScanResponse> = {},
): DeployCodeScanResponse => {
return {
id: 0,
aptible_yml_present: false,
dockerfile_present: false,
procfile_present: false,
_links: {
app: { href: "" },
operation: { href: "" },
},
_type: "code_scan_result",
...c,
};
};

export const fetchCodeScanResult = api.get<{ id: string }>(
"/code_scan_results/:id",
api.cache(),
Expand Down
20 changes: 20 additions & 0 deletions src/deploy/database-images/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,26 @@ export interface DeployDatabaseImageResponse {
_type: "database_image";
}

export const defaultDatabaseImageResponse = (
i: Partial<DeployDatabaseImageResponse> = {},
): DeployDatabaseImageResponse => {
const now = new Date().toISOString();
return {
id: 0,
default: true,
description: "",
discoverable: true,
docker_repo: "",
type: "",
version: "",
visible: true,
created_at: now,
updated_at: now,
_type: "database_image",
...i,
};
};

export const deserializeDeployDatabaseImage = (
payload: DeployDatabaseImageResponse,
): DeployDatabaseImage => {
Expand Down
33 changes: 33 additions & 0 deletions src/deploy/database/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export interface DeployDatabaseResponse {
disk: any;
last_operation: any;
};
_type: "database";
}

export interface BackupResponse {
Expand All @@ -85,6 +86,38 @@ export interface HalBackups {
backups: BackupResponse[];
}

export const defaultDatabaseResponse = (
d: Partial<DeployDatabaseResponse> = {},
): DeployDatabaseResponse => {
const now = new Date().toISOString();
return {
id: 1,
handle: "",
provisioned: true,
type: "",
status: "provisioned",
docker_repo: "",
current_kms_arn: "",
connection_url: "",
created_at: now,
updated_at: now,
_links: {
account: { href: "" },
service: { href: "" },
database_image: { href: "" },
initialize_from: { href: "" },
...d._links,
},
_embedded: {
disk: null,
last_operation: null,
...d._embedded,
},
_type: "database",
...d,
};
};

export const deserializeDeployDatabase = (
payload: DeployDatabaseResponse,
): DeployDatabase => {
Expand Down
Loading