You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2026-01-03 17:02:28 +03:00
Rename 'Emails' route to 'Profile' (#1567)
* rename /account/emails route to profile * remove support for /emails * bad unit test for Layout * update snapshots, fix layout test * fix snapshots from old version of compound * better layout test * coverage?
This commit is contained in:
78
frontend/src/Router.test.tsx
Normal file
78
frontend/src/Router.test.tsx
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { describe, it, expect } from "vitest";
|
||||||
|
|
||||||
|
import { segmentsToRoute } from "./Router";
|
||||||
|
|
||||||
|
describe("Router", () => {
|
||||||
|
describe("segmentsToRoute", () => {
|
||||||
|
it("returns home for route with no segments", () => {
|
||||||
|
const segments: string[] = [];
|
||||||
|
expect(segmentsToRoute(segments)).toEqual({ type: "home" });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns home for route with and empty string segment", () => {
|
||||||
|
const segments: string[] = [""];
|
||||||
|
expect(segmentsToRoute(segments)).toEqual({ type: "home" });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns profile for route with profile", () => {
|
||||||
|
const segments: string[] = ["profile"];
|
||||||
|
expect(segmentsToRoute(segments)).toEqual({ type: "profile" });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns browser session list for sessions", () => {
|
||||||
|
const segments: string[] = ["sessions"];
|
||||||
|
expect(segmentsToRoute(segments)).toEqual({
|
||||||
|
type: "browser-session-list",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns compat session list for compat-sessions", () => {
|
||||||
|
const segments: string[] = ["compat-sessions"];
|
||||||
|
expect(segmentsToRoute(segments)).toEqual({
|
||||||
|
type: "compat-session-list",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns oauth session list for oauth2-sessions", () => {
|
||||||
|
const segments: string[] = ["oauth2-sessions"];
|
||||||
|
expect(segmentsToRoute(segments)).toEqual({
|
||||||
|
type: "oauth2-session-list",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns client detail route correctly", () => {
|
||||||
|
const segments: string[] = ["clients", "client-id"];
|
||||||
|
expect(segmentsToRoute(segments)).toEqual({
|
||||||
|
type: "client",
|
||||||
|
id: "client-id",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns session detail route correctly", () => {
|
||||||
|
const segments: string[] = ["sessions", "session-id"];
|
||||||
|
expect(segmentsToRoute(segments)).toEqual({
|
||||||
|
type: "session",
|
||||||
|
id: "session-id",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns unknown for other segments", () => {
|
||||||
|
const segments: string[] = ["just", "testing"];
|
||||||
|
expect(segmentsToRoute(segments)).toEqual({ type: "unknown", segments });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -25,7 +25,7 @@ type Location = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type HomeRoute = { type: "home" };
|
type HomeRoute = { type: "home" };
|
||||||
type EmailListRoute = { type: "email-list" };
|
type ProfileRoute = { type: "profile" };
|
||||||
type OAuth2ClientRoute = { type: "client"; id: string };
|
type OAuth2ClientRoute = { type: "client"; id: string };
|
||||||
type OAuth2SessionList = { type: "oauth2-session-list" };
|
type OAuth2SessionList = { type: "oauth2-session-list" };
|
||||||
type BrowserSessionRoute = { type: "session"; id: string };
|
type BrowserSessionRoute = { type: "session"; id: string };
|
||||||
@@ -36,7 +36,7 @@ type UnknownRoute = { type: "unknown"; segments: string[] };
|
|||||||
|
|
||||||
export type Route =
|
export type Route =
|
||||||
| HomeRoute
|
| HomeRoute
|
||||||
| EmailListRoute
|
| ProfileRoute
|
||||||
| OAuth2ClientRoute
|
| OAuth2ClientRoute
|
||||||
| OAuth2SessionList
|
| OAuth2SessionList
|
||||||
| BrowserSessionRoute
|
| BrowserSessionRoute
|
||||||
@@ -49,8 +49,8 @@ const routeToSegments = (route: Route): string[] => {
|
|||||||
switch (route.type) {
|
switch (route.type) {
|
||||||
case "home":
|
case "home":
|
||||||
return [];
|
return [];
|
||||||
case "email-list":
|
case "profile":
|
||||||
return ["emails"];
|
return ["profile"];
|
||||||
case "verify-email":
|
case "verify-email":
|
||||||
return ["emails", route.id, "verify"];
|
return ["emails", route.id, "verify"];
|
||||||
case "client":
|
case "client":
|
||||||
@@ -90,7 +90,7 @@ const segmentMatches = (
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const segmentsToRoute = (segments: string[]): Route => {
|
export const segmentsToRoute = (segments: string[]): Route => {
|
||||||
const matches = (...pattern: PatternItem[]): boolean =>
|
const matches = (...pattern: PatternItem[]): boolean =>
|
||||||
segmentMatches(segments, ...pattern);
|
segmentMatches(segments, ...pattern);
|
||||||
|
|
||||||
@@ -99,8 +99,8 @@ const segmentsToRoute = (segments: string[]): Route => {
|
|||||||
return { type: "home" };
|
return { type: "home" };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matches("emails")) {
|
if (matches("profile")) {
|
||||||
return { type: "email-list" };
|
return { type: "profile" };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matches("sessions")) {
|
if (matches("sessions")) {
|
||||||
@@ -169,7 +169,7 @@ export const routeAtom = atom(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const Home = lazy(() => import("./pages/Home"));
|
const Home = lazy(() => import("./pages/Home"));
|
||||||
const EmailList = lazy(() => import("./pages/EmailList"));
|
const Profile = lazy(() => import("./pages/Profile"));
|
||||||
const OAuth2Client = lazy(() => import("./pages/OAuth2Client"));
|
const OAuth2Client = lazy(() => import("./pages/OAuth2Client"));
|
||||||
const BrowserSession = lazy(() => import("./pages/BrowserSession"));
|
const BrowserSession = lazy(() => import("./pages/BrowserSession"));
|
||||||
const BrowserSessionList = lazy(() => import("./pages/BrowserSessionList"));
|
const BrowserSessionList = lazy(() => import("./pages/BrowserSessionList"));
|
||||||
@@ -183,8 +183,8 @@ const InnerRouter: React.FC = () => {
|
|||||||
switch (route.type) {
|
switch (route.type) {
|
||||||
case "home":
|
case "home":
|
||||||
return <Home />;
|
return <Home />;
|
||||||
case "email-list":
|
case "profile":
|
||||||
return <EmailList />;
|
return <Profile />;
|
||||||
case "oauth2-session-list":
|
case "oauth2-session-list":
|
||||||
return <OAuth2SessionList />;
|
return <OAuth2SessionList />;
|
||||||
case "browser-session-list":
|
case "browser-session-list":
|
||||||
|
|||||||
3
frontend/src/__snapshots__/Router.test.tsx.snap
Normal file
3
frontend/src/__snapshots__/Router.test.tsx.snap
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
|
exports[`Router > routes 1`] = `"Loading..."`;
|
||||||
79
frontend/src/components/Layout.test.tsx
Normal file
79
frontend/src/components/Layout.test.tsx
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
// Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// @vitest-environment happy-dom
|
||||||
|
|
||||||
|
import { render } from "@testing-library/react";
|
||||||
|
import { Provider } from "jotai";
|
||||||
|
import { useHydrateAtoms } from "jotai/utils";
|
||||||
|
import { Suspense } from "react";
|
||||||
|
import { describe, expect, it, vi, afterAll, beforeEach } from "vitest";
|
||||||
|
|
||||||
|
import { appConfigAtom, locationAtom } from "../Router";
|
||||||
|
import { currentUserIdAtom, GqlResult } from "../atoms";
|
||||||
|
|
||||||
|
import Layout from "./Layout";
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
// For some reason, the locationAtom gets updated with `about:black` on render,
|
||||||
|
// so we need to set a "real" location and wait for the next tick
|
||||||
|
window.location.assign("https://example.com/");
|
||||||
|
// Wait the next tick for the location to update
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||||
|
});
|
||||||
|
|
||||||
|
const HydrateLocation: React.FC<React.PropsWithChildren<{ path: string }>> = ({
|
||||||
|
children,
|
||||||
|
path,
|
||||||
|
}) => {
|
||||||
|
useHydrateAtoms([
|
||||||
|
[appConfigAtom, { root: "/" }],
|
||||||
|
[locationAtom, { pathname: path }],
|
||||||
|
]);
|
||||||
|
return <>{children}</>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const WithLocation: React.FC<React.PropsWithChildren<{ path: string }>> = ({
|
||||||
|
children,
|
||||||
|
path,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Provider>
|
||||||
|
<Suspense>
|
||||||
|
<HydrateLocation path={path}>{children}</HydrateLocation>
|
||||||
|
</Suspense>
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("<Layout />", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.spyOn(currentUserIdAtom, "read").mockResolvedValue(
|
||||||
|
"abc123" as unknown as GqlResult<string | null>,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
afterAll(() => {
|
||||||
|
vi.restoreAllMocks();
|
||||||
|
});
|
||||||
|
it("renders app navigation correctly", async () => {
|
||||||
|
const component = render(
|
||||||
|
<WithLocation path="/account">
|
||||||
|
<Layout />
|
||||||
|
</WithLocation>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(await component.findByText("Profile")).toMatchSnapshot();
|
||||||
|
expect(await component.findByText("Home")).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -43,7 +43,7 @@ const Layout: React.FC<{ children?: React.ReactNode }> = ({ children }) => {
|
|||||||
|
|
||||||
<NavBar>
|
<NavBar>
|
||||||
<NavItem route={{ type: "home" }}>Home</NavItem>
|
<NavItem route={{ type: "home" }}>Home</NavItem>
|
||||||
<NavItem route={{ type: "email-list" }}>Emails</NavItem>
|
<NavItem route={{ type: "profile" }}>Profile</NavItem>
|
||||||
</NavBar>
|
</NavBar>
|
||||||
|
|
||||||
<main>{children}</main>
|
<main>{children}</main>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const meta = {
|
|||||||
<WithHomePage>
|
<WithHomePage>
|
||||||
<NavBar {...props}>
|
<NavBar {...props}>
|
||||||
<NavItem route={{ type: "home" }}>Home</NavItem>
|
<NavItem route={{ type: "home" }}>Home</NavItem>
|
||||||
<NavItem route={{ type: "email-list" }}>Emails</NavItem>
|
<NavItem route={{ type: "profile" }}>Emails</NavItem>
|
||||||
<ExternalLink href="https://example.com">External</ExternalLink>
|
<ExternalLink href="https://example.com">External</ExternalLink>
|
||||||
</NavBar>
|
</NavBar>
|
||||||
</WithHomePage>
|
</WithHomePage>
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export const Active: Story = {
|
|||||||
|
|
||||||
export const Inactive: Story = {
|
export const Inactive: Story = {
|
||||||
args: {
|
args: {
|
||||||
route: { type: "email-list" },
|
route: { type: "profile" },
|
||||||
children: "Emails",
|
children: "Profile",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ describe("NavItem", () => {
|
|||||||
it("renders a different route", () => {
|
it("renders a different route", () => {
|
||||||
const component = create(
|
const component = create(
|
||||||
<WithLocation path="/">
|
<WithLocation path="/">
|
||||||
<NavItem route={{ type: "email-list" }}>Emails</NavItem>
|
<NavItem route={{ type: "profile" }}>Emails</NavItem>
|
||||||
</WithLocation>,
|
</WithLocation>,
|
||||||
);
|
);
|
||||||
const tree = component.toJSON();
|
const tree = component.toJSON();
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ exports[`NavItem > renders a different route 1`] = `
|
|||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
className="_navItem_8603fc"
|
className="_navItem_8603fc"
|
||||||
href="/emails"
|
href="/profile"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
>
|
>
|
||||||
Emails
|
Emails
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ const UserHome: React.FC<{
|
|||||||
{data.unverifiedEmails.totalCount > 0 && !dismiss && (
|
{data.unverifiedEmails.totalCount > 0 && !dismiss && (
|
||||||
<Alert type="critical" title="Unverified email" onClose={doDismiss}>
|
<Alert type="critical" title="Unverified email" onClose={doDismiss}>
|
||||||
You have {data.unverifiedEmails.totalCount} unverified email
|
You have {data.unverifiedEmails.totalCount} unverified email
|
||||||
address(es). <Link route={{ type: "email-list" }}>Check</Link>
|
address(es). <Link route={{ type: "profile" }}>Check</Link>
|
||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ const UserHome: React.FC<{
|
|||||||
{data.confirmedEmails.totalCount > 1 && (
|
{data.confirmedEmails.totalCount > 1 && (
|
||||||
<Body>
|
<Body>
|
||||||
{data.confirmedEmails.totalCount - 1} additional emails.{" "}
|
{data.confirmedEmails.totalCount - 1} additional emails.{" "}
|
||||||
<Link route={{ type: "email-list" }}>View all</Link>
|
<Link route={{ type: "profile" }}>View all</Link>
|
||||||
</Body>
|
</Body>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ exports[`UserHome > render a <UserHome /> with additional emails 1`] = `
|
|||||||
additional emails.
|
additional emails.
|
||||||
|
|
||||||
<a
|
<a
|
||||||
href="/emails"
|
href="/profile"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
>
|
>
|
||||||
View all
|
View all
|
||||||
@@ -128,7 +128,7 @@ exports[`UserHome > render a <UserHome /> with an unverified email 1`] = `
|
|||||||
1
|
1
|
||||||
unverified email address(es).
|
unverified email address(es).
|
||||||
<a
|
<a
|
||||||
href="/emails"
|
href="/profile"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
>
|
>
|
||||||
Check
|
Check
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ const VerifyEmail: React.FC<{
|
|||||||
e.currentTarget?.reset();
|
e.currentTarget?.reset();
|
||||||
|
|
||||||
if (result.data?.verifyEmail.status === "VERIFIED") {
|
if (result.data?.verifyEmail.status === "VERIFIED") {
|
||||||
setRoute({ type: "email-list" });
|
setRoute({ type: "profile" });
|
||||||
} else {
|
} else {
|
||||||
fieldRef.current?.focus();
|
fieldRef.current?.focus();
|
||||||
fieldRef.current?.select();
|
fieldRef.current?.select();
|
||||||
|
|||||||
@@ -0,0 +1,179 @@
|
|||||||
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
|
exports[`<VerifyEmail /> > renders an active session 1`] = `
|
||||||
|
[
|
||||||
|
<header
|
||||||
|
className="_header_07ded5"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="_icon_07ded5"
|
||||||
|
fill="currentColor"
|
||||||
|
height="1em"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="1em"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M9.55 17.575c-.133 0-.258-.02-.375-.063a.878.878 0 0 1-.325-.212L4.55 13c-.183-.183-.27-.42-.263-.713.009-.291.105-.529.288-.712a.948.948 0 0 1 .7-.275.95.95 0 0 1 .7.275L9.55 15.15l8.475-8.475c.183-.183.42-.275.713-.275.291 0 .529.092.712.275.183.183.275.42.275.713 0 .291-.092.529-.275.712l-9.2 9.2c-.1.1-.208.17-.325.212a1.106 1.106 0 0 1-.375.063Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<h1
|
||||||
|
className="_title_07ded5"
|
||||||
|
>
|
||||||
|
Verify your email
|
||||||
|
</h1>
|
||||||
|
<p
|
||||||
|
className="_tagline_07ded5"
|
||||||
|
>
|
||||||
|
Enter the 6-digit code sent to
|
||||||
|
|
||||||
|
<span
|
||||||
|
className="_email_07ded5"
|
||||||
|
>
|
||||||
|
ernie@sesame.st
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</header>,
|
||||||
|
<form
|
||||||
|
className="_root_xzzw3_23 _form_07ded5"
|
||||||
|
onInvalid={[Function]}
|
||||||
|
onReset={[Function]}
|
||||||
|
onSubmit={[Function]}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="_field_xzzw3_32"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
className="_label_xzzw3_41"
|
||||||
|
htmlFor="radix-:r0:"
|
||||||
|
onMouseDown={[Function]}
|
||||||
|
>
|
||||||
|
6-digit code
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
className="_control_xzzw3_55"
|
||||||
|
id="radix-:r0:"
|
||||||
|
inputMode="numeric"
|
||||||
|
name="code"
|
||||||
|
onChange={[Function]}
|
||||||
|
onInvalid={[Function]}
|
||||||
|
placeholder="xxxxxx"
|
||||||
|
title=""
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
className="_button_lls7s_17 _submitButton_07ded5 _submitButton_07ded5"
|
||||||
|
data-kind="primary"
|
||||||
|
data-size="lg"
|
||||||
|
disabled={false}
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Continue
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="_button_lls7s_17"
|
||||||
|
data-kind="tertiary"
|
||||||
|
data-size="lg"
|
||||||
|
disabled={false}
|
||||||
|
onClick={[Function]}
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
>
|
||||||
|
Resend email
|
||||||
|
</button>
|
||||||
|
</form>,
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`<VerifyEmail /> > renders verify screen for email 1`] = `
|
||||||
|
[
|
||||||
|
<header
|
||||||
|
className="_header_07ded5"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="_icon_07ded5"
|
||||||
|
fill="currentColor"
|
||||||
|
height="1em"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="1em"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M9.55 17.575c-.133 0-.258-.02-.375-.063a.878.878 0 0 1-.325-.212L4.55 13c-.183-.183-.27-.42-.263-.713.009-.291.105-.529.288-.712a.948.948 0 0 1 .7-.275.95.95 0 0 1 .7.275L9.55 15.15l8.475-8.475c.183-.183.42-.275.713-.275.291 0 .529.092.712.275.183.183.275.42.275.713 0 .291-.092.529-.275.712l-9.2 9.2c-.1.1-.208.17-.325.212a1.106 1.106 0 0 1-.375.063Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<h1
|
||||||
|
className="_title_07ded5"
|
||||||
|
>
|
||||||
|
Verify your email
|
||||||
|
</h1>
|
||||||
|
<p
|
||||||
|
className="_tagline_07ded5"
|
||||||
|
>
|
||||||
|
Enter the 6-digit code sent to
|
||||||
|
|
||||||
|
<span
|
||||||
|
className="_email_07ded5"
|
||||||
|
>
|
||||||
|
ernie@sesame.st
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</header>,
|
||||||
|
<form
|
||||||
|
className="_root_xzzw3_23 _form_07ded5"
|
||||||
|
onInvalid={[Function]}
|
||||||
|
onReset={[Function]}
|
||||||
|
onSubmit={[Function]}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="_field_xzzw3_32"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
className="_label_xzzw3_41"
|
||||||
|
htmlFor="radix-:r0:"
|
||||||
|
onMouseDown={[Function]}
|
||||||
|
>
|
||||||
|
6-digit code
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
className="_control_xzzw3_55"
|
||||||
|
id="radix-:r0:"
|
||||||
|
inputMode="numeric"
|
||||||
|
name="code"
|
||||||
|
onChange={[Function]}
|
||||||
|
onInvalid={[Function]}
|
||||||
|
placeholder="xxxxxx"
|
||||||
|
title=""
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
className="_button_lls7s_17 _submitButton_07ded5 _submitButton_07ded5"
|
||||||
|
data-kind="primary"
|
||||||
|
data-size="lg"
|
||||||
|
disabled={false}
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Continue
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="_button_lls7s_17"
|
||||||
|
data-kind="tertiary"
|
||||||
|
data-size="lg"
|
||||||
|
disabled={false}
|
||||||
|
onClick={[Function]}
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
>
|
||||||
|
Resend email
|
||||||
|
</button>
|
||||||
|
</form>,
|
||||||
|
]
|
||||||
|
`;
|
||||||
20
frontend/src/components/__snapshots__/Layout.test.tsx.snap
Normal file
20
frontend/src/components/__snapshots__/Layout.test.tsx.snap
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
|
exports[`<Layout /> > renders app navigation correctly 1`] = `
|
||||||
|
<a
|
||||||
|
class="_navItem_8603fc"
|
||||||
|
href="/profile"
|
||||||
|
>
|
||||||
|
Profile
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`<Layout /> > renders app navigation correctly 2`] = `
|
||||||
|
<a
|
||||||
|
aria-current="page"
|
||||||
|
class="_navItem_8603fc"
|
||||||
|
href="/"
|
||||||
|
>
|
||||||
|
Home
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
@@ -20,7 +20,7 @@ import NotLoggedIn from "../components/NotLoggedIn";
|
|||||||
import UserEmailList from "../components/UserEmailList";
|
import UserEmailList from "../components/UserEmailList";
|
||||||
import { isErr, unwrapErr, unwrapOk } from "../result";
|
import { isErr, unwrapErr, unwrapOk } from "../result";
|
||||||
|
|
||||||
const EmailList: React.FC = () => {
|
const Profile: React.FC = () => {
|
||||||
const result = useAtomValue(currentUserIdAtom);
|
const result = useAtomValue(currentUserIdAtom);
|
||||||
if (isErr(result)) return <GraphQLError error={unwrapErr(result)} />;
|
if (isErr(result)) return <GraphQLError error={unwrapErr(result)} />;
|
||||||
|
|
||||||
@@ -30,4 +30,4 @@ const EmailList: React.FC = () => {
|
|||||||
return <UserEmailList userId={userId} />;
|
return <UserEmailList userId={userId} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default EmailList;
|
export default Profile;
|
||||||
Reference in New Issue
Block a user