Skip to content
Closed
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
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { LocalCert } from "@src/context/CertificateProvider";
import type { LocalToken } from "@src/hooks/useJwt";
import type { Props as CreateCertificateButtonProps } from "./CreateCertificateButton";
import { CreateCertificateButton, DEPENDENCIES as CREATE_CERTIFICATE_BUTTON_DEPENDENCIES } from "./CreateCertificateButton";

Expand All @@ -11,6 +12,12 @@ describe(CreateCertificateButton.name, () => {
expect(screen.queryByRole("alert")).toHaveTextContent(/You need to create a certificate to view deployment details./);
});

it("renders create token button", () => {
setup({ isJwtEnabled: true });
expect(screen.getByRole("button", { name: /create token/i })).toBeInTheDocument();
expect(screen.queryByRole("alert")).toHaveTextContent(/You need to create a token to view deployment details./);
});

it("calls createCertificate when clicked", async () => {
const createCertificate = jest.fn(async () => {});
setup({ createCertificate });
Expand All @@ -21,6 +28,16 @@ describe(CreateCertificateButton.name, () => {
expect(createCertificate).toHaveBeenCalled();
});

it("calls createToken when clicked", async () => {
const createToken = jest.fn(async () => {});
setup({ createToken, isJwtEnabled: true });

const button = screen.getByRole("button", { name: /create token/i });
fireEvent.click(button);

expect(createToken).toHaveBeenCalled();
});

it("displays warning text if certificate is expired", () => {
setup({
localCert: {
Expand All @@ -33,16 +50,43 @@ describe(CreateCertificateButton.name, () => {
expect(screen.queryByRole("alert")).toHaveTextContent(/Your certificate has expired. Please create a new one./);
});

it("displays warning text if token is expired", () => {
setup({
localToken: {
token: "expired",
address: "akash1234567890"
},
isLocalTokenExpired: true,
isJwtEnabled: true
});
expect(screen.queryByRole("alert")).toHaveTextContent(/Your token has expired. Please create a new one./);
});

function setup(
input?: CreateCertificateButtonProps & {
createCertificate?: () => Promise<void>;
createToken?: () => Promise<void>;
isCreatingCert?: boolean;
isLocalCertExpired?: boolean;
isLocalTokenExpired?: boolean;
localCert?: LocalCert;
localToken?: LocalToken;
isBlockchainDown?: boolean;
isJwtEnabled?: boolean;
}
) {
const { createCertificate, isCreatingCert, isLocalCertExpired, localCert, isBlockchainDown, ...props } = input ?? {};
const {
createCertificate,
createToken,
isCreatingCert,
isLocalCertExpired,
isLocalTokenExpired,
localCert,
localToken,
isBlockchainDown,
isJwtEnabled,
...props
} = input ?? {};

return render(
<CreateCertificateButton
Expand Down Expand Up @@ -70,6 +114,20 @@ describe(CreateCertificateButton.name, () => {
isSettingsInit: true,
refreshNodeStatuses: jest.fn(),
isRefreshingNodeStatus: false
}),
useJwt: () => ({
isCreatingToken: false,
createToken: createToken ?? jest.fn(() => Promise.resolve()),
isLocalTokenExpired: isLocalTokenExpired ?? false,
localToken: localToken ?? null,
setLocalToken: jest.fn()
}),
useFlag: jest.fn().mockImplementation(flag => {
if (flag === "jwt_instead_of_cert") {
return isJwtEnabled ?? false;
}

return false;
})
}}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ import { cn } from "@akashnetwork/ui/utils";

import { useCertificate } from "@src/context/CertificateProvider";
import { useSettings } from "@src/context/SettingsProvider";
import { useFlag } from "@src/hooks/useFlag";
import { useJwt } from "@src/hooks/useJwt";

export const DEPENDENCIES = {
Alert,
Button,
Spinner,
useCertificate,
useSettings
useJwt,
useSettings,
useFlag
};

export interface Props extends Omit<ButtonProps, "onClick"> {
Expand All @@ -22,33 +26,62 @@ export interface Props extends Omit<ButtonProps, "onClick"> {
}

export const CreateCertificateButton: FC<Props> = ({ afterCreate, containerClassName, dependencies: d = DEPENDENCIES, ...buttonProps }) => {
const isJwtEnabled = d.useFlag("jwt_instead_of_cert");
const { settings } = d.useSettings();
const { isCreatingCert, createCertificate, isLocalCertExpired, localCert } = d.useCertificate();
const { isCreatingToken, createToken, isLocalTokenExpired, localToken } = d.useJwt();

const _createCertificate = useCallback(async () => {
await createCertificate();
afterCreate?.();
}, [createCertificate, afterCreate]);
const _createToken = useCallback(async () => {
await createToken();
afterCreate?.();
}, [createToken, afterCreate]);
const warningText = useMemo(() => {
if (isJwtEnabled) {
if (isLocalTokenExpired) return "Your token has expired. Please create a new one.";
if (!localToken) return "You need to create a token to view deployment details.";
}

if (isLocalCertExpired) return "Your certificate has expired. Please create a new one.";
if (!localCert) return "You need to create a certificate to view deployment details.";

return undefined;
}, [isLocalCertExpired, isCreatingCert, localCert]);
const buttonText = useMemo(() => (isLocalCertExpired ? "Regenerate Certificate" : "Create Certificate"), [isLocalCertExpired]);
}, [isJwtEnabled, isLocalCertExpired, isLocalTokenExpired, localCert, localToken]);
const buttonText = useMemo(() => {
if (isJwtEnabled) {
return isLocalTokenExpired ? "Regenerate Token" : "Create Token";
}

return isLocalCertExpired ? "Regenerate Certificate" : "Create Certificate";
}, [isJwtEnabled, isLocalCertExpired, isLocalTokenExpired]);

return (
<div className={containerClassName}>
<d.Alert variant="warning" className={cn({ "py-2 text-sm": buttonProps?.size === "sm" }, "truncate")}>
{warningText}
</d.Alert>
<d.Button
className={warningText ? "mt-4" : ""}
{...buttonProps}
disabled={buttonProps?.disabled || settings.isBlockchainDown || isCreatingCert}
onClick={_createCertificate}
>
{isCreatingCert ? <d.Spinner size="small" /> : buttonText}
</d.Button>
{isJwtEnabled ? (
<d.Button
className={cn("ml-2", warningText ? "mt-4" : "")}
{...buttonProps}
disabled={buttonProps?.disabled || settings.isBlockchainDown || isCreatingToken}
onClick={_createToken}
>
{isCreatingToken ? <d.Spinner size="small" /> : buttonText}
</d.Button>
) : (
<d.Button
className={warningText ? "mt-4" : ""}
{...buttonProps}
disabled={buttonProps?.disabled || settings.isBlockchainDown || isCreatingCert}
onClick={_createCertificate}
>
{isCreatingCert ? <d.Spinner size="small" /> : buttonText}
</d.Button>
)}
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export type Settings = {
isBlockchainDown: boolean;
};

type ContextType = {
export type ContextType = {
settings: Settings;
setSettings: React.Dispatch<React.SetStateAction<Settings>>;
isLoadingSettings: boolean;
Expand Down
Loading
Loading