Skip to content

Commit

Permalink
feat(improvement): check duplicate name when changing a new seller AP…
Browse files Browse the repository at this point in the history
…I name
  • Loading branch information
KsiBart committed Nov 7, 2024
1 parent f14ec14 commit 071ef9f
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 2 deletions.
16 changes: 16 additions & 0 deletions kraken-app/kraken-app-portal/src/hooks/product/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
deleteAPIServer,
getAPIServers,
getComponentDetailV2,
getValidateServerName,
} from "@/services/products";
import { STALE_TIME } from "@/utils/constants/common";
import {
Expand Down Expand Up @@ -75,6 +76,7 @@ import { IEnvComponent } from "@/utils/types/envComponent.type";
import {
IApiMapperDeployment,
IDeploymentHistory,
IProductIdAndNameParams,
} from "@/utils/types/product.type";
import { useMutation, useQuery, useQueries } from "@tanstack/react-query";
import { AxiosResponse } from "axios";
Expand Down Expand Up @@ -127,6 +129,7 @@ export const PRODUCT_CACHE_KEYS = {
update_target_mapper: "update_target_mapper",
upgrade_mapping_template_production: "upgrade_mapping_template_production",
upgrade_mapping_template_stage: "upgrade_mapping_template_stage",
get_validate_api_server_name: "get_validate_api_server_name",
verify_product: "verify_product",
};

Expand Down Expand Up @@ -731,3 +734,16 @@ export const useRegenToken = () => {
},
});
};

export const useGetValidateServerName = () => {
return useMutation<any, Error, IProductIdAndNameParams>({
mutationKey: [PRODUCT_CACHE_KEYS.get_validate_api_server_name],
mutationFn: ({ productId, name }: IProductIdAndNameParams) =>
getValidateServerName(productId, name),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: [PRODUCT_CACHE_KEYS.get_validate_api_server_name],
});
}
});
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { render } from "@testing-library/react";
import { fireEvent, getAllByTestId, render } from "@testing-library/react";
import { QueryClientProvider } from "@tanstack/react-query";
import { queryClient } from "@/utils/helpers/reactQuery";
import { BrowserRouter } from "react-router-dom";
import NewAPIServer from "..";
import SelectAPIServer from '../components/SelectAPIServer';

test("test API new", () => {
const { container } = render(
<QueryClientProvider client={queryClient}>
Expand All @@ -13,3 +15,32 @@ test("test API new", () => {
);
expect(container).toBeInTheDocument();
});


test("test SelectApiServer", async () => {
vi.mock("@/hooks/product", async () => {
const actual = await vi.importActual("@/hooks/product");
return {
...actual,
useGetValidateServerName: vi.fn().mockResolvedValue({
mutateAsync: vi.fn().mockReturnValue({
data: false
}),
isLoading: false,
}),
};
});

const { container } = render(
<QueryClientProvider client={queryClient}>
<BrowserRouter>
<SelectAPIServer />
</BrowserRouter>
</QueryClientProvider>
);
expect(container).toBeInTheDocument();
const input = getAllByTestId(container, "api-seller-name-input")[0];
const formContainer = getAllByTestId(container, "api-seller-name-container")[0];
fireEvent.change(input, { target: { value: "test" } });
expect(formContainer).toBeInTheDocument();
});
Original file line number Diff line number Diff line change
@@ -1,29 +1,46 @@
import TitleIcon from "@/assets/title-icon.svg";
import Flex from "@/components/Flex";
import { Text } from "@/components/Text";
import { useGetValidateServerName } from '@/hooks/product';
import { useAppStore } from '@/stores/app.store';
import { isURL } from "@/utils/helpers/url";
import { Form, Input } from "antd";
import { isEmpty } from "lodash";

const SelectAPIServer = () => {
const { currentProduct } = useAppStore();
const { mutateAsync: validateName } = useGetValidateServerName();
return (
<>
<Flex gap={8} justifyContent="flex-start">
<TitleIcon />
<Text.NormalLarge>Seller API Server basics</Text.NormalLarge>
</Flex>
<Form.Item
data-testid="api-seller-name-container"
label="Seller API Server Name"
name="name"
rules={[
{
required: true,
message: "Please complete this field.",
},
{
validator: async (_, name) => {
const { data: isValid } = await validateName({ productId: currentProduct, name })
if (isValid) {
return Promise.resolve();
} else {
return Promise.reject(`The name ${name} is already taken`);
}
}
}
]}
validateDebounce={1000}
labelCol={{ span: 24 }}

>
<Input placeholder="Add API Server Name" style={{ width: "100%" }} />
<Input data-testid="api-seller-name-input" placeholder="Add API Server Name" style={{ width: "100%" }} />
</Form.Item>
<Form.Item label="Description" name="description" labelCol={{ span: 24 }}>
<Input placeholder="Add description" style={{ width: "100%" }} />
Expand Down
12 changes: 12 additions & 0 deletions kraken-app/kraken-app-portal/src/services/products.ts
Original file line number Diff line number Diff line change
Expand Up @@ -370,3 +370,15 @@ export const regenerateBuyerAccessToken = (productId: string, id: string) => {
method: "POST",
});
};

export const getValidateServerName = (
productId: string,
name: string
) => {
return request(
`/v2${PRODUCT}/${productId}/components/${productId}/api-servers/${name}`,
{
method: "GET",
}
);
};
5 changes: 5 additions & 0 deletions kraken-app/kraken-app-portal/src/utils/types/product.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,8 @@ export interface IApiUseCase {
componentName: string;
details: IRunningMapping[];
}

export interface IProductIdAndNameParams {
productId: string;
name: string;
}

0 comments on commit 071ef9f

Please sign in to comment.