Skip to content
This repository has been archived by the owner on Sep 10, 2024. It is now read-only.

Commit

Permalink
Rename 'Emails' route to 'Profile' (#1567)
Browse files Browse the repository at this point in the history
* 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?
  • Loading branch information
Kerry authored Aug 25, 2023
1 parent 70e6489 commit c7311ee
Show file tree
Hide file tree
Showing 15 changed files with 382 additions and 23 deletions.
78 changes: 78 additions & 0 deletions frontend/src/Router.test.tsx
Original file line number Diff line number Diff line change
@@ -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 });
});
});
});
20 changes: 10 additions & 10 deletions frontend/src/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type Location = {
};

type HomeRoute = { type: "home" };
type EmailListRoute = { type: "email-list" };
type ProfileRoute = { type: "profile" };
type OAuth2ClientRoute = { type: "client"; id: string };
type OAuth2SessionList = { type: "oauth2-session-list" };
type BrowserSessionRoute = { type: "session"; id: string };
Expand All @@ -36,7 +36,7 @@ type UnknownRoute = { type: "unknown"; segments: string[] };

export type Route =
| HomeRoute
| EmailListRoute
| ProfileRoute
| OAuth2ClientRoute
| OAuth2SessionList
| BrowserSessionRoute
Expand All @@ -49,8 +49,8 @@ const routeToSegments = (route: Route): string[] => {
switch (route.type) {
case "home":
return [];
case "email-list":
return ["emails"];
case "profile":
return ["profile"];
case "verify-email":
return ["emails", route.id, "verify"];
case "client":
Expand Down Expand Up @@ -90,7 +90,7 @@ const segmentMatches = (
return true;
};

const segmentsToRoute = (segments: string[]): Route => {
export const segmentsToRoute = (segments: string[]): Route => {
const matches = (...pattern: PatternItem[]): boolean =>
segmentMatches(segments, ...pattern);

Expand All @@ -99,8 +99,8 @@ const segmentsToRoute = (segments: string[]): Route => {
return { type: "home" };
}

if (matches("emails")) {
return { type: "email-list" };
if (matches("profile")) {
return { type: "profile" };
}

if (matches("sessions")) {
Expand Down Expand Up @@ -169,7 +169,7 @@ export const routeAtom = atom(
);

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 BrowserSession = lazy(() => import("./pages/BrowserSession"));
const BrowserSessionList = lazy(() => import("./pages/BrowserSessionList"));
Expand All @@ -183,8 +183,8 @@ const InnerRouter: React.FC = () => {
switch (route.type) {
case "home":
return <Home />;
case "email-list":
return <EmailList />;
case "profile":
return <Profile />;
case "oauth2-session-list":
return <OAuth2SessionList />;
case "browser-session-list":
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/__snapshots__/Router.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Router > routes 1`] = `"Loading..."`;
79 changes: 79 additions & 0 deletions frontend/src/components/Layout.test.tsx
Original file line number Diff line number Diff line change
@@ -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();
});
});
2 changes: 1 addition & 1 deletion frontend/src/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const Layout: React.FC<{ children?: React.ReactNode }> = ({ children }) => {

<NavBar>
<NavItem route={{ type: "home" }}>Home</NavItem>
<NavItem route={{ type: "email-list" }}>Emails</NavItem>
<NavItem route={{ type: "profile" }}>Profile</NavItem>
</NavBar>

<main>{children}</main>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/NavBar/NavBar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const meta = {
<WithHomePage>
<NavBar {...props}>
<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>
</NavBar>
</WithHomePage>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/NavItem/NavItem.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const Active: Story = {

export const Inactive: Story = {
args: {
route: { type: "email-list" },
children: "Emails",
route: { type: "profile" },
children: "Profile",
},
};
2 changes: 1 addition & 1 deletion frontend/src/components/NavItem/NavItem.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ describe("NavItem", () => {
it("renders a different route", () => {
const component = create(
<WithLocation path="/">
<NavItem route={{ type: "email-list" }}>Emails</NavItem>
<NavItem route={{ type: "profile" }}>Emails</NavItem>
</WithLocation>,
);
const tree = component.toJSON();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ exports[`NavItem > renders a different route 1`] = `
>
<a
className="_navItem_8603fc"
href="/emails"
href="/profile"
onClick={[Function]}
>
Emails
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/UserHome/UserHome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const UserHome: React.FC<{
{data.unverifiedEmails.totalCount > 0 && !dismiss && (
<Alert type="critical" title="Unverified email" onClose={doDismiss}>
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>
)}

Expand All @@ -78,7 +78,7 @@ const UserHome: React.FC<{
{data.confirmedEmails.totalCount > 1 && (
<Body>
{data.confirmedEmails.totalCount - 1} additional emails.{" "}
<Link route={{ type: "email-list" }}>View all</Link>
<Link route={{ type: "profile" }}>View all</Link>
</Body>
)}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ exports[`UserHome > render a <UserHome /> with additional emails 1`] = `
additional emails.
<a
href="/emails"
href="/profile"
onClick={[Function]}
>
View all
Expand Down Expand Up @@ -128,7 +128,7 @@ exports[`UserHome > render a <UserHome /> with an unverified email 1`] = `
1
unverified email address(es).
<a
href="/emails"
href="/profile"
onClick={[Function]}
>
Check
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/VerifyEmail/VerifyEmail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ const VerifyEmail: React.FC<{
e.currentTarget?.reset();

if (result.data?.verifyEmail.status === "VERIFIED") {
setRoute({ type: "email-list" });
setRoute({ type: "profile" });
} else {
fieldRef.current?.focus();
fieldRef.current?.select();
Expand Down
Loading

0 comments on commit c7311ee

Please sign in to comment.