diff --git a/.github/workflows/cleanup.yml b/.github/workflows/cleanup.yml
new file mode 100644
index 0000000..5c0c19b
--- /dev/null
+++ b/.github/workflows/cleanup.yml
@@ -0,0 +1,17 @@
+name: 🗑 Cleanup session files
+# Hitting the API checks for inactive sessions and cleans up any orphaned files.
+# This action runs on an hourly schedule to make sure this cleanup happens at least
+# once an hour.
+
+on:
+ schedule:
+ # * is a special character in YAML so you have to quote this string
+ - cron: '0 * * * *'
+
+jobs:
+ cleanup:
+ name: 🗑 Cleanup
+ runs-on: ubuntu-latest
+ steps:
+ - name: Cleanup
+ run: curl https://seroviz.seroanalytics.org/api/
diff --git a/test/components/FAQ.test.tsx b/test/components/FAQ.test.tsx
new file mode 100644
index 0000000..75a10ee
--- /dev/null
+++ b/test/components/FAQ.test.tsx
@@ -0,0 +1,12 @@
+import React from "react";
+import {render, screen} from "@testing-library/react";
+import FAQ from "../../src/components/FAQ";
+
+describe("", () => {
+ test("renders FAQ", async () => {
+
+ render();
+ const list = await screen.findAllByRole("listitem");
+ expect(list.length).toBe(5);
+ });
+});
diff --git a/test/components/TopNav.test.tsx b/test/components/TopNav.test.tsx
index 6b36e56..a6db049 100644
--- a/test/components/TopNav.test.tsx
+++ b/test/components/TopNav.test.tsx
@@ -8,6 +8,12 @@ import {
} from "../../src/RootContext";
import TopNav from "../../src/components/TopNav";
+test("Displays FAQ link", async () => {
+ render();
+ const faq = screen.getByText("FAQ") as HTMLAnchorElement;
+ expect(faq.href).toBe("http://localhost/faq");
+});
+
test("user can end session", async () => {
mockAxios.onDelete(`/session/`)
.reply(200, mockSuccess("OK"));