Skip to content

Commit

Permalink
test: add stories for auth recipe screens
Browse files Browse the repository at this point in the history
  • Loading branch information
porcellus committed Dec 6, 2023
1 parent 6cb22bd commit 2a412d4
Show file tree
Hide file tree
Showing 7 changed files with 655 additions and 11 deletions.
47 changes: 39 additions & 8 deletions stories/authPage.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { RoutingComponent } from "../lib/ts/components/routingComponent";
import { passwordlessFactors } from "../lib/ts/recipe/passwordless/recipe";
import { ErrorBoundary } from "./errorBoundary";

const meta: Meta<{
export type Args = {
usesDynamicLoginMethods: boolean;
"multifactorauth.initialized": boolean;
"multifactorauth.firstFactors": FirstFactor[] | undefined;
Expand All @@ -17,6 +17,7 @@ const meta: Meta<{
"multitenancy.providers": ProviderId[];
"emailpassword.initialized": boolean;
"emailpassword.disableDefaultUISignInUp": boolean;
"emailpassword.defaultToSignUp": boolean;
"thirdparty.initialized": boolean;
"thirdparty.disableDefaultUISignInUp": boolean;
"thirdparty.providers": ProviderId[];
Expand All @@ -27,28 +28,38 @@ const meta: Meta<{
"thirdpartyemailpassword.disableDefaultUISignInUp": boolean;
"thirdpartyemailpassword.providers": ProviderId[] | undefined;
"thirdpartyemailpassword.disableEmailPassword": boolean;
"thirdpartyemailpassword.defaultToSignUp": boolean;
"thirdpartypasswordless.initialized": boolean;
"thirdpartypasswordless.disableDefaultUISignInUp": boolean;
"thirdpartypasswordless.providers": ProviderId[] | undefined;
"thirdpartypasswordless.contactMethod": "PHONE" | "EMAIL" | "EMAIL_OR_PHONE";
"thirdpartypasswordless.disablePasswordless": boolean;
}> = {
path?: string;
query?: string;
hash?: string;
};

const meta: Meta<Args> = {
title: "Auth page",
render: (args, { loaded: { featureState } }) => {
render: (args, { loaded: { path, funcOverrides } }) => {
const { prebuiltUIs, key } = useMemo(() => {
const { prebuiltUIs, recipeList } = buildInit(unflattenArgs(args));
const { prebuiltUIs, recipeList } = buildInit(unflattenArgs(args), funcOverrides);
for (const ui of prebuiltUIs) {
ui.reset();
}
resetAndInitST(recipeList, args.usesDynamicLoginMethods);
resetAndInitST(recipeList, args.usesDynamicLoginMethods, {
path: args.path,
query: args.query,
hash: args.hash,
});
return { prebuiltUIs, key: JSON.stringify(args) };
}, [args]);

return (
<ErrorBoundary key={key}>
<RoutingComponent
key={key}
path="/auth"
path={args.path ?? path ?? "/auth"}
preBuiltUIList={prebuiltUIs.map((c) => c.getInstanceOrInitAndGetInstance())}
getReactRouterDomWithCustomHistory={() => undefined}
/>
Expand All @@ -65,6 +76,7 @@ const meta: Meta<{
"multitenancy.providers": ["github", "google"],
"emailpassword.initialized": true,
"emailpassword.disableDefaultUISignInUp": false,
"emailpassword.defaultToSignUp": false,
"thirdparty.initialized": true,
"thirdparty.disableDefaultUISignInUp": false,
"thirdparty.providers": ["github", "google"],
Expand All @@ -73,6 +85,7 @@ const meta: Meta<{
"passwordless.disableDefaultUISignInUp": false,
"thirdpartyemailpassword.initialized": true,
"thirdpartyemailpassword.disableDefaultUISignInUp": false,
"thirdpartyemailpassword.defaultToSignUp": false,
"thirdpartyemailpassword.providers": ["github", "google"],
"thirdpartyemailpassword.disableEmailPassword": false,
"thirdpartypasswordless.initialized": true,
Expand Down Expand Up @@ -154,6 +167,15 @@ const meta: Meta<{
truthy: true,
},
},
"emailpassword.defaultToSignUp": {
table: {
category: "emailpassword",
},
if: {
arg: "emailpassword.initialized",
truthy: true,
},
},
"thirdparty.initialized": {
table: {
category: "thirdparty",
Expand Down Expand Up @@ -222,6 +244,15 @@ const meta: Meta<{
truthy: true,
},
},
"thirdpartyemailpassword.defaultToSignUp": {
table: {
category: "thirdpartyemailpassword",
},
if: {
arg: "thirdpartyemailpassword.initialized",
truthy: true,
},
},
"thirdpartyemailpassword.providers": {
table: {
category: "thirdpartyemailpassword",
Expand Down Expand Up @@ -289,6 +320,6 @@ const meta: Meta<{
};

export default meta;
type Story = StoryObj<typeof Page>;
type Story = StoryObj<Args>;

export const AllRecipes: Story = {};
export const Playground: Story = {};
68 changes: 68 additions & 0 deletions stories/emailpassword.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import type { Meta, StoryObj } from "@storybook/react";
import { userEvent, waitFor, within } from "@storybook/testing-library";
import meta, { Args } from "./authPage.stories";

type Story = StoryObj<Args>;

export default {
...meta,
title: "EmailPassword/Auth",
};

export const SignIn: Story = {
args: {
"multifactorauth.firstFactors": ["emailpassword"],
},
};
export const SignUp: Story = {
args: {
path: "/auth",
"multifactorauth.firstFactors": ["emailpassword"],
"emailpassword.defaultToSignUp": true,
},
};
export const SignUpFieldErrors: Story = {
args: {
path: "/auth",
"multifactorauth.firstFactors": ["emailpassword"],
"emailpassword.defaultToSignUp": true,
},
play: async ({ canvasElement }) => {
// Assigns canvas to the component root element
const canvas = within(canvasElement);

const emailInput = await canvas.findByPlaceholderText("Email address");
await new Promise((res) => setTimeout(res, 100));
await userEvent.type(emailInput, "asdf");
const passwordInput = await canvas.findByPlaceholderText("Password");

await userEvent.type(passwordInput, "pw");
// See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel
const submitButton = await waitFor(() => canvasElement.querySelector("button[type=submit]"))!;

await userEvent.click(canvasElement, { delay: 200 });
},
};
export const SignUpGeneralErrors: Story = {
args: {
path: "/auth",
query: "error=asdf",
"multifactorauth.firstFactors": ["emailpassword"],
"emailpassword.defaultToSignUp": true,
},
};

export const ResetPassword: Story = {
args: {
"multifactorauth.firstFactors": ["emailpassword"],
path: "/auth/reset-password",
},
};

export const ResetPasswordLinkClicked: Story = {
args: {
"multifactorauth.firstFactors": ["emailpassword"],
path: "/auth/reset-password",
query: "token=asdf",
},
};
185 changes: 185 additions & 0 deletions stories/passwordless.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import type { Meta, StoryObj } from "@storybook/react";
import meta, { Args } from "./authPage.stories";
import { overridePWlessWithLoginAttempt } from "./utils";

type Story = StoryObj<Args>;

export default {
...meta,
title: "Passwordless/Auth",
};

export const ContactFormCombined: Story = {
args: {
"multifactorauth.firstFactors": ["otp-email", "otp-phone"],
},
};

export const ContactFormEmail: Story = {
args: {
"multifactorauth.firstFactors": ["otp-email"],
},
};
export const ContactFormPhone: Story = {
args: {
"multifactorauth.firstFactors": ["otp-phone"],
},
};

export const OTPFormPhone: Story = {
args: {
"multifactorauth.firstFactors": ["otp-email", "otp-phone"],
},
loaders: [
async () => ({
funcOverrides: {
passwordless: overridePWlessWithLoginAttempt({
contactInfo: "+36701234567",
contactMethod: "PHONE",
flowType: "USER_INPUT_CODE",
lastResend: Date.now(),
deviceId: "asdf",
preAuthSessionId: "asdf",
}),
},
}),
],
};

export const OTPFormEmail: Story = {
args: {
"multifactorauth.firstFactors": ["otp-email", "otp-phone"],
},
loaders: [
async () => ({
funcOverrides: {
passwordless: overridePWlessWithLoginAttempt({
contactInfo: "[email protected]",
contactMethod: "EMAIL",
flowType: "USER_INPUT_CODE",
lastResend: Date.now(),
deviceId: "asdf",
preAuthSessionId: "asdf",
}),
},
}),
],
};
export const OTPOrLinkEmail: Story = {
args: {
"multifactorauth.firstFactors": ["otp-email", "otp-phone"],
},
loaders: [
async () => ({
funcOverrides: {
passwordless: overridePWlessWithLoginAttempt({
contactInfo: "[email protected]",
contactMethod: "EMAIL",
flowType: "USER_INPUT_CODE_AND_MAGIC_LINK",
lastResend: Date.now(),
deviceId: "asdf",
preAuthSessionId: "asdf",
}),
},
}),
],
};

export const OTPOrLinkPhone: Story = {
args: {
"multifactorauth.firstFactors": ["otp-email", "otp-phone"],
},
loaders: [
async () => ({
funcOverrides: {
passwordless: overridePWlessWithLoginAttempt({
contactInfo: "+36701234567",
contactMethod: "PHONE",
flowType: "USER_INPUT_CODE_AND_MAGIC_LINK",
lastResend: Date.now(),
deviceId: "asdf",
preAuthSessionId: "asdf",
}),
},
}),
],
};

export const LinkSentEmail: Story = {
args: {
"multifactorauth.firstFactors": ["otp-email", "otp-phone"],
},
loaders: [
async () => ({
funcOverrides: {
passwordless: overridePWlessWithLoginAttempt({
contactInfo: "+36701234567",
contactMethod: "PHONE",
flowType: "MAGIC_LINK",
lastResend: Date.now(),
deviceId: "asdf",
preAuthSessionId: "asdf",
}),
},
}),
],
};

export const LinkSentPhone: Story = {
args: {
"multifactorauth.firstFactors": ["otp-email", "otp-phone"],
},
loaders: [
async () => ({
funcOverrides: {
passwordless: overridePWlessWithLoginAttempt({
contactInfo: "+36701234567",
contactMethod: "PHONE",
flowType: "MAGIC_LINK",
lastResend: Date.now(),
deviceId: "asdf",
preAuthSessionId: "asdf",
}),
},
}),
],
};

export const OTPResend: Story = {
args: {
"multifactorauth.firstFactors": ["otp-email", "otp-phone"],
},
loaders: [
async () => ({
funcOverrides: {
passwordless: overridePWlessWithLoginAttempt({
contactInfo: "+36701234567",
contactMethod: "PHONE",
flowType: "USER_INPUT_CODE",
lastResend: Date.now() - 3600000,
deviceId: "asdf",
preAuthSessionId: "asdf",
}),
},
}),
],
};
export const LinkResend: Story = {
args: {
"multifactorauth.firstFactors": ["otp-email", "otp-phone"],
},
loaders: [
async () => ({
funcOverrides: {
passwordless: overridePWlessWithLoginAttempt({
contactInfo: "+36701234567",
contactMethod: "PHONE",
flowType: "MAGIC_LINK",
lastResend: Date.now() - 3600000,
deviceId: "asdf",
preAuthSessionId: "asdf",
}),
},
}),
],
};
Loading

0 comments on commit 2a412d4

Please sign in to comment.