diff --git a/src/markup-components/components.ts b/src/markup-components/components.ts index 07a74e7a6..f04f94a3c 100644 --- a/src/markup-components/components.ts +++ b/src/markup-components/components.ts @@ -46,6 +46,7 @@ import { UserAuthForm as userAuthForm, UserAuthFormProps, UserConsentCard as userConsentCard, + UserLogoutCard as userLogoutCard, UserConsentCardProps, UserErrorCard as userErrorCard, UserErrorCardProps, @@ -53,6 +54,7 @@ import { UserSettingsCardProps, WebAuthnSettingsProps, WebAuthnSettingsSection as webAuthnSettingsSection, + UserLogoutCardProps, } from "../react-components" import { CodeBoxProps } from "../react-components/codebox" import { ComponentWrapper } from "./component-wrapper" @@ -162,6 +164,9 @@ export const LookupSecretSettingsSection = ( export const UserConsentCard = (props: UserConsentCardProps) => ComponentWrapper(userConsentCard(props)) +export const UserLogoutCard = (props: UserLogoutCardProps) => + ComponentWrapper(userLogoutCard(props)) + export type { ButtonLinkProps, ButtonProps, @@ -187,6 +192,7 @@ export type { UserAuthCardProps, UserAuthFormProps, UserConsentCardProps, + UserLogoutCardProps, UserErrorCardProps, UserSettingsCardProps, UserSettingsFlowType, diff --git a/src/react-components/checkbox.tsx b/src/react-components/checkbox.tsx index 7d32c5f01..847ccf4f6 100644 --- a/src/react-components/checkbox.tsx +++ b/src/react-components/checkbox.tsx @@ -26,7 +26,7 @@ export const Checkbox = ({ dataTestid, ...props }: CheckboxProps): JSX.Element => { - const id = Math.random().toString(36).substring(2) + const id = props.id ?? Math.random().toString(36).substring(2) return (
{requested_scope.map((scope) => ( - + ))}
@@ -65,12 +70,12 @@ export const UserConsentCard = ({
{client?.policy_uri && ( - + Privacy Policy )} {client?.tos_uri && ( - + Terms of Service )} @@ -78,7 +83,7 @@ export const UserConsentCard = ({
diff --git a/src/react-components/ory/user-logout-card.spec.tsx b/src/react-components/ory/user-logout-card.spec.tsx new file mode 100644 index 000000000..badb30d10 --- /dev/null +++ b/src/react-components/ory/user-logout-card.spec.tsx @@ -0,0 +1,43 @@ +import { expect, test } from "@playwright/experimental-ct-react" +import { Locator, Request } from "@playwright/test" +import { UserLogoutCard } from "./user-logout-card" + +let component: Locator + +test.beforeEach(async ({ mount }) => { + component = await mount( + , + ) +}) + +async function submitForm(buttonText: RegExp): Promise { + const requestPromise = component + .page() + .waitForRequest("https://example.com/logout") + await component.locator("button", { hasText: buttonText }).click() + return requestPromise +} + +test("submits when user clicks 'Yes'", async () => { + const request = await submitForm(/yes/i) + + expect(request.method()).toBe("POST") + const data = request.postDataJSON() + expect(data).toHaveProperty("_csrf", "CSRF token") + expect(data).toHaveProperty("challenge", "logout challenge") + expect(data).toHaveProperty("submit", "Yes") +}) + +test("submits when user clicks 'No'", async () => { + const request = await submitForm(/no/i) + + expect(request.method()).toBe("POST") + const data = request.postDataJSON() + expect(data).toHaveProperty("_csrf", "CSRF token") + expect(data).toHaveProperty("challenge", "logout challenge") + expect(data).toHaveProperty("submit", "No") +}) diff --git a/src/react-components/ory/user-logout-card.tsx b/src/react-components/ory/user-logout-card.tsx new file mode 100644 index 000000000..5283d5f26 --- /dev/null +++ b/src/react-components/ory/user-logout-card.tsx @@ -0,0 +1,60 @@ +import { gridStyle } from "../../theme" +import { Button } from "../button" +import { Card } from "../card" +import { Typography } from "../typography" + +export type UserLogoutCardProps = { + csrfToken: string + challenge: string + action: string + className?: string + cardImage?: string | React.ReactElement +} + +export const UserLogoutCard = ({ + csrfToken, + challenge, + action, + className, + cardImage, +}: UserLogoutCardProps) => { + return ( + + Do you wish to log out? +
+ } + image={cardImage} + > +
+ + +
+
+
+
+
+ + ) +} diff --git a/src/stories/Ory/Logout.stories.tsx b/src/stories/Ory/Logout.stories.tsx new file mode 100644 index 000000000..cc20ebd5b --- /dev/null +++ b/src/stories/Ory/Logout.stories.tsx @@ -0,0 +1,22 @@ +import { ComponentProps } from "react" +import { ComponentMeta, Story } from "@storybook/react" + +import { Container } from "../storyhelper" +import { UserLogoutCard } from "../../react-components" +import logo from "../assets/logo.svg" + +export default { + title: "Ory/UserLogoutCard", + component: UserLogoutCard, +} as ComponentMeta + +const Template: Story> = (args) => ( + + + +) + +export const LogoutCard = Template.bind({}) +LogoutCard.args = { + cardImage: logo, +}