Skip to content

Commit

Permalink
Feat/form application piped v1 (#5516)
Browse files Browse the repository at this point in the history
* Add DialogConfirm component

Signed-off-by: kypham <[email protected]>

* Add application-form-v1 component

Signed-off-by: kypham <[email protected]>

* Fix application list should refresh affter create an application

Signed-off-by: kypham <[email protected]>

* Split Form Select input to seperate component

Signed-off-by: kypham <[email protected]>

* Add loading attribute for Dialog Confirm

Signed-off-by: kypham <[email protected]>

* Split form by version and refactor application form

Signed-off-by: kypham <[email protected]>

* Update add application request payload, disable app list item piped v1

Signed-off-by: kypham <[email protected]>

* Add test for application forms

Signed-off-by: kypham <[email protected]>

* Add application-form-manual-v1

Signed-off-by: kypham <[email protected]>

---------

Signed-off-by: kypham <[email protected]>
  • Loading branch information
hongky-1994 authored Feb 6, 2025
1 parent d24e16b commit db1d74e
Show file tree
Hide file tree
Showing 22 changed files with 2,511 additions and 914 deletions.
46 changes: 46 additions & 0 deletions web/src/__fixtures__/dummy-application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,52 @@ export const dummyApplication: Application.AsObject = {
deploying: false,
};

export const dummyApplicationPipedV1: Application.AsObject = {
id: randomUUID(),
cloudProvider: "",
platformProvider: "",
deployTargetsList: ["kubernetes-default"],
disabled: false,
gitPath: {
configFilename: "",
path: "dir/dir1",
url: "",
repo: dummyRepo,
},
kind: ApplicationKind.KUBERNETES,
name: "DemoAppForPipedV1",
pipedId: dummyPiped.id,
projectId: "project-1",
description: "",
labelsMap: [],
mostRecentlySuccessfulDeployment: {
deploymentId: "deployment-1",
completedAt: 0,
summary: "",
startedAt: startedAt.unix(),
version: "v1",
trigger: dummyTrigger,
configFilename: "",
versionsList: [],
},
mostRecentlyTriggeredDeployment: {
deploymentId: "deployment-1",
completedAt: 0,
summary: "summary",
startedAt: startedAt.unix(),
version: "v1",
trigger: dummyTrigger,
configFilename: "",
versionsList: [],
},
syncState: dummyApplicationSyncState,
updatedAt: updatedAt.unix(),
deletedAt: 0,
createdAt: createdAt.unix(),
deleted: false,
deploying: false,
};

export const dummyApps: Record<ApplicationKind, Application.AsObject> = {
[ApplicationKind.KUBERNETES]: dummyApplication,
[ApplicationKind.TERRAFORM]: {
Expand Down
32 changes: 22 additions & 10 deletions web/src/api/applications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,19 @@ export const addApplication = async ({
kind,
gitPath,
labelsMap,
}: Required<AddApplicationRequest.AsObject>): Promise<
AddApplicationResponse.AsObject
> => {
}: Required<Omit<AddApplicationRequest.AsObject, "platformProvider" | "kind">> &
Partial<
Pick<AddApplicationRequest.AsObject, "platformProvider" | "kind">
>): Promise<AddApplicationResponse.AsObject> => {
const req = new AddApplicationRequest();
req.setName(name);
req.setPipedId(pipedId);
req.setPlatformProvider(platformProvider);
req.setKind(kind);
if (platformProvider !== undefined) {
req.setPlatformProvider(platformProvider);
}
if (kind !== undefined) {
req.setKind(kind);
}
const appGitPath = new ApplicationGitPath();
const repository = new ApplicationGitRepository();
if (gitPath.repo) {
Expand Down Expand Up @@ -143,15 +148,22 @@ export const updateApplication = async ({
name,
pipedId,
configFilename,
}: Required<UpdateApplicationRequest.AsObject>): Promise<
UpdateApplicationResponse.AsObject
> => {
}: Required<
Omit<UpdateApplicationRequest.AsObject, "platformProvider" | "kind">
> &
Partial<
Pick<UpdateApplicationRequest.AsObject, "platformProvider" | "kind">
>): Promise<UpdateApplicationResponse.AsObject> => {
const req = new UpdateApplicationRequest();
req.setApplicationId(applicationId);
req.setName(name);
req.setPipedId(pipedId);
req.setPlatformProvider(platformProvider);
req.setKind(kind);
if (platformProvider !== undefined) {
req.setPlatformProvider(platformProvider);
}
if (kind !== undefined) {
req.setKind(kind);
}
req.setConfigFilename(configFilename);
return apiRequest(req, apiClient.updateApplication);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import { UI_TEXT_CANCEL, UI_TEXT_SAVE } from "~/constants/ui-text";
import ApplicationFormManualV0 from ".";
import { createStore, render, screen } from "~~/test-utils";
import { server } from "~/mocks/server";
import { dummyApplication } from "~/__fixtures__/dummy-application";
import { dummyPiped } from "~/__fixtures__/dummy-piped";
import { AppState } from "~/store";

const onClose = jest.fn();
const onFinished = jest.fn();
const TITLE = "title";

beforeAll(() => {
server.listen();
});

afterEach(() => {
server.resetHandlers();
});

afterAll(() => {
server.close();
});

const baseState: Partial<AppState> = {
pipeds: {
entities: {
[dummyPiped.id]: dummyPiped,
},
ids: [dummyPiped.id],
registeredPiped: null,
updating: false,
releasedVersions: [],
breakingChangesNote: "",
},
};

describe("ApplicationFormManualV0", () => {
it("renders without crashing", () => {
render(
<ApplicationFormManualV0
onClose={onClose}
onFinished={onFinished}
title="title"
/>,
{}
);
});

describe("Test ui create application", () => {
const store = createStore(baseState);
beforeEach(() => {
render(
<ApplicationFormManualV0
onClose={onClose}
onFinished={onFinished}
title={TITLE}
/>,
{ store }
);
});

it("should have correct title", () => {
expect(screen.getByText(TITLE)).toBeInTheDocument();
});

it("calls onClose when cancel button is clicked", () => {
const button = screen.getByRole("button", { name: UI_TEXT_CANCEL });
button.click();
expect(onClose).toHaveBeenCalledTimes(1);
});

it("button save is disabled initially", () => {
const button = screen.getByRole("button", { name: UI_TEXT_SAVE });
expect(button).toBeDisabled();
});

it('form contain input label "Name" and not disabled initially', () => {
const input = screen.getByLabelText(/^Name/i);
expect(input).toBeInTheDocument();
expect(input).not.toBeDisabled();
});

it('form contain input label "Kind" and not disabled initially', () => {
const input = screen.getByLabelText(/^Kind/i);
expect(input).toBeInTheDocument();
expect(input).not.toBeDisabled();
});

it('form contain input label "Piped" and not disabled initially', () => {
const input = screen.getByRole("button", { name: "Piped" });
expect(input).toBeInTheDocument();
expect(input).not.toHaveAttribute("aria-disabled", "true");
});

it('form contain input label "Platform Provider" and disabled', () => {
const input = screen.getByRole("button", { name: "Platform Provider" });
expect(input).toBeInTheDocument();
expect(input).toHaveAttribute("aria-disabled", "true");
});

it('form contain input label "Repository" and disabled', () => {
const input = screen.getByRole("button", { name: "Repository" });
expect(input).toBeInTheDocument();
expect(input).toHaveAttribute("aria-disabled", "true");
});

it('form contain input label "Path" and disabled', () => {
const input = screen.getByLabelText(/^Path/i);
expect(input).toBeInTheDocument();
expect(input).toBeDisabled();
});

it('form contain input label "Config Filename" disabled and init value = app.pipecd.yaml', () => {
const input = screen.getByLabelText(/^Config Filename/i);
expect(input).toBeInTheDocument();
expect(input).toHaveValue("app.pipecd.yaml");
expect(input).toBeDisabled();
});
});

describe("Test ui edit application", () => {
beforeEach(() => {
const store = createStore(baseState);
render(
<ApplicationFormManualV0
onClose={onClose}
onFinished={onFinished}
title={TITLE}
detailApp={dummyApplication}
/>,
{ store }
);
});

it("should have correct title", () => {
expect(screen.getByText(TITLE)).toBeInTheDocument();
});

it("calls onClose when cancel button is clicked", () => {
const button = screen.getByRole("button", { name: UI_TEXT_CANCEL });
button.click();
expect(onClose).toHaveBeenCalledTimes(1);
});

it("button save is disabled initially", () => {
const button = screen.getByRole("button", { name: UI_TEXT_SAVE });
expect(button).toBeDisabled();
});

it('form contain input label "Name" and disabled initially', () => {
const input = screen.getByLabelText(/^Name/i);
expect(input).toBeInTheDocument();
expect(input).toBeDisabled();
});

it('form contain input label "Kind" and disabled initially', () => {
const input = screen.getByRole("button", { name: "Kind" });
expect(input).toBeInTheDocument();
expect(input).toHaveAttribute("aria-disabled", "true");
});

it('form contain input label "Piped"', () => {
const input = screen.getByRole("button", { name: "Piped" });
expect(input).toBeInTheDocument();
expect(input).not.toHaveAttribute("aria-disabled", "true");
});

it('form contain input label "Platform Provider"', () => {
const input = screen.getByRole("button", { name: "Platform Provider" });
expect(input).toBeInTheDocument();
expect(input).not.toHaveAttribute("aria-disabled", "true");
});

it('form contain input label "Repository" and disabled initially', () => {
const input = screen.getByLabelText(/^Repository/i);
expect(input).toBeInTheDocument();
expect(input).toHaveAttribute("aria-disabled", "true");
});

it('form contain input label "Path" and disabled initially', () => {
const input = screen.getByLabelText(/^Path/i);
expect(input).toBeInTheDocument();
expect(input).toBeDisabled();
});

it('form contain input label "Config Filename"', () => {
const input = screen.getByLabelText(/^Config Filename/i);
expect(input).toBeInTheDocument();
});
});
});
Loading

0 comments on commit db1d74e

Please sign in to comment.