Enhancement: signout button (#6962)

This commit is contained in:
shamoon
2026-08-07 11:11:09 -07:00
committed by GitHub
parent 6da79e9259
commit 525d476e14
4 changed files with 66 additions and 0 deletions
+3
View File
@@ -20,6 +20,9 @@
"minutes": "m",
"seconds": "s"
},
"auth": {
"signout": "Sign out"
},
"widget": {
"missing_type": "Missing Widget Type: {{type}}",
"api_error": "API Error",
+21
View File
@@ -0,0 +1,21 @@
import { signOut, useSession } from "next-auth/react";
import { useTranslation } from "next-i18next/pages";
import { MdLogout } from "react-icons/md";
export default function SignOut() {
const { t } = useTranslation();
const { status } = useSession();
if (status !== "authenticated") {
return null;
}
return (
<div id="signout" className="rounded-full flex align-middle self-center mr-3">
<button type="button" onClick={() => signOut({ callbackUrl: "/" })} className="outline-hidden">
<MdLogout className="text-theme-800 dark:text-theme-200 w-6 h-6 cursor-pointer" aria-hidden="true" />
<span className="sr-only">{t("auth.signout")}</span>
</button>
</div>
);
}
+37
View File
@@ -0,0 +1,37 @@
// @vitest-environment jsdom
import { fireEvent, render } from "@testing-library/react";
import { beforeEach, describe, expect, it, vi } from "vitest";
const { signOut, useSession } = vi.hoisted(() => ({
signOut: vi.fn(),
useSession: vi.fn(),
}));
vi.mock("next-auth/react", () => ({ signOut, useSession }));
vi.mock("next-i18next/pages", () => ({ useTranslation: () => ({ t: (key) => key }) }));
import SignOut from "./signout";
describe("components/toggles/signout", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it.each(["unauthenticated", "loading"])("renders nothing when session status is %s", (status) => {
useSession.mockReturnValue({ status });
const { container } = render(<SignOut />);
expect(container).toBeEmptyDOMElement();
});
it("renders and signs out when authenticated", () => {
useSession.mockReturnValue({ status: "authenticated" });
const { getByRole } = render(<SignOut />);
fireEvent.click(getByRole("button"));
expect(signOut).toHaveBeenCalledWith({ callbackUrl: "/" });
});
});
+5
View File
@@ -35,6 +35,10 @@ const ColorToggle = dynamic(() => import("components/toggles/color"), {
ssr: false,
});
const SignOut = dynamic(() => import("components/toggles/signout"), {
ssr: false,
});
const Version = dynamic(() => import("components/version"), {
ssr: false,
});
@@ -502,6 +506,7 @@ function Home({ initialSettings }) {
<div id="style" className="flex w-full justify-end">
{!settings?.color && <ColorToggle />}
<Revalidate />
<SignOut />
{!settings.theme && <ThemeToggle />}
</div>