diff --git a/frontends/jest.jsdom.config.ts b/frontends/jest.jsdom.config.ts index 6c7ce2b08f..246e6514bd 100644 --- a/frontends/jest.jsdom.config.ts +++ b/frontends/jest.jsdom.config.ts @@ -1,6 +1,8 @@ import { resolve } from "path" import type { Config } from "@jest/types" +process.env.SITE_NAME = "MIT Open" + /** * Base configuration for jest tests. */ diff --git a/frontends/mit-open/src/pages/AboutPage/AboutPage.test.tsx b/frontends/mit-open/src/pages/AboutPage/AboutPage.test.tsx index 8aada28166..07c2d1f9f6 100644 --- a/frontends/mit-open/src/pages/AboutPage/AboutPage.test.tsx +++ b/frontends/mit-open/src/pages/AboutPage/AboutPage.test.tsx @@ -18,7 +18,7 @@ describe("AboutPage", () => { url: commonUrls.ABOUT, }) await waitFor(() => { - expect(document.title).toBe("About Us") + expect(document.title).toBe("About Us | MIT Open") }) screen.getByRole("heading", { name: "About Us", diff --git a/frontends/mit-open/src/pages/AboutPage/AboutPage.tsx b/frontends/mit-open/src/pages/AboutPage/AboutPage.tsx index 7eadf4aac2..402ef18df5 100644 --- a/frontends/mit-open/src/pages/AboutPage/AboutPage.tsx +++ b/frontends/mit-open/src/pages/AboutPage/AboutPage.tsx @@ -79,9 +79,7 @@ const AboutPage: React.FC = () => { return ( - - About Us - + { screen.getByText(article.html) await waitFor(() => { - expect(document.title).toBe(article.title) + expect(document.title).toBe(`${article.title} | MIT Open`) }) }) diff --git a/frontends/mit-open/src/pages/ArticleDetailsPage/ArticleDetailsPage.tsx b/frontends/mit-open/src/pages/ArticleDetailsPage/ArticleDetailsPage.tsx index fc4d5d4839..7c6fde5f07 100644 --- a/frontends/mit-open/src/pages/ArticleDetailsPage/ArticleDetailsPage.tsx +++ b/frontends/mit-open/src/pages/ArticleDetailsPage/ArticleDetailsPage.tsx @@ -26,9 +26,7 @@ const ArticlesDetailPage: React.FC = () => { src="/static/images/course_search_banner.png" className="articles-detail-page" > - - {article.data?.title} - + diff --git a/frontends/mit-open/src/pages/ArticleUpsertPages/ArticleEditPage.test.tsx b/frontends/mit-open/src/pages/ArticleUpsertPages/ArticleEditPage.test.tsx index 127a358f7a..f122151b12 100644 --- a/frontends/mit-open/src/pages/ArticleUpsertPages/ArticleEditPage.test.tsx +++ b/frontends/mit-open/src/pages/ArticleUpsertPages/ArticleEditPage.test.tsx @@ -41,7 +41,7 @@ describe("ArticleEditPage", () => { expect(bodyInput).toBeInstanceOf(HTMLTextAreaElement) await waitFor(() => { - expect(document.title).toBe(`Editing: ${article.title}`) + expect(document.title).toBe(`${article.title} | Edit | MIT Open`) }) }) diff --git a/frontends/mit-open/src/pages/ArticleUpsertPages/ArticleEditPage.tsx b/frontends/mit-open/src/pages/ArticleUpsertPages/ArticleEditPage.tsx index 708f39ef22..01a7920536 100644 --- a/frontends/mit-open/src/pages/ArticleUpsertPages/ArticleEditPage.tsx +++ b/frontends/mit-open/src/pages/ArticleUpsertPages/ArticleEditPage.tsx @@ -21,7 +21,7 @@ const ArticleEditPage: React.FC = () => { [navigate, id], ) const goHome = useCallback(() => navigate("/"), [navigate]) - const title = `Editing: ${article.data?.title ?? ""}` + const title = article.data?.title ? `${article.data?.title} | Edit` : "Edit" return ( = ({ }) => { return ( - - {title} - + {children} diff --git a/frontends/mit-open/src/pages/DashboardPage/Dashboard.test.tsx b/frontends/mit-open/src/pages/DashboardPage/Dashboard.test.tsx index d93e184c76..099bd581da 100644 --- a/frontends/mit-open/src/pages/DashboardPage/Dashboard.test.tsx +++ b/frontends/mit-open/src/pages/DashboardPage/Dashboard.test.tsx @@ -191,7 +191,7 @@ describe("DashboardPage", () => { setupAPIs() renderWithProviders() await waitFor(() => { - expect(document.title).toBe("User Home") + expect(document.title).toBe("Your MIT Learning Journey | MIT Open") }) screen.getByRole("heading", { name: "Your MIT Learning Journey", diff --git a/frontends/mit-open/src/pages/DashboardPage/DashboardPage.tsx b/frontends/mit-open/src/pages/DashboardPage/DashboardPage.tsx index d99dec8f2d..e7fdc00654 100644 --- a/frontends/mit-open/src/pages/DashboardPage/DashboardPage.tsx +++ b/frontends/mit-open/src/pages/DashboardPage/DashboardPage.tsx @@ -415,9 +415,7 @@ const DashboardPage: React.FC = () => { - - User Home - + diff --git a/frontends/mit-open/src/pages/DepartmentListingPage/DepartmentListingPage.test.tsx b/frontends/mit-open/src/pages/DepartmentListingPage/DepartmentListingPage.test.tsx index 2140ed2289..7d67007d27 100644 --- a/frontends/mit-open/src/pages/DepartmentListingPage/DepartmentListingPage.test.tsx +++ b/frontends/mit-open/src/pages/DepartmentListingPage/DepartmentListingPage.test.tsx @@ -82,11 +82,11 @@ describe("DepartmentListingPage", () => { } } - it("Has a page title", async () => { + it("Has correct page title", async () => { setupApis() renderWithProviders() await waitFor(() => { - expect(document.title).toBe("MIT Open | Departments") + expect(document.title).toBe("Departments | MIT Open") }) screen.getByRole("heading", { name: "Departments" }) }) diff --git a/frontends/mit-open/src/pages/DepartmentListingPage/DepartmentListingPage.tsx b/frontends/mit-open/src/pages/DepartmentListingPage/DepartmentListingPage.tsx index 0bb679af79..90a4beed94 100644 --- a/frontends/mit-open/src/pages/DepartmentListingPage/DepartmentListingPage.tsx +++ b/frontends/mit-open/src/pages/DepartmentListingPage/DepartmentListingPage.tsx @@ -215,9 +215,7 @@ const DepartmentListingPage: React.FC = () => { return ( - - MIT Open | Departments - + { - expect(document.title).toBe("Not Allowed") + expect(document.title).toBe("Not Allowed | MIT Open") }) }, ) @@ -54,7 +54,7 @@ test("ErrorPage shows NotFound on API 404 errors", async () => { allowConsoleErrors() setup(404) await waitFor(() => { - expect(document.title).toBe("Not Found") + expect(document.title).toBe("Not Found | MIT Open") }) }) @@ -62,7 +62,7 @@ test("ErrorPage shows NotFound on frontend routing 404 errors", async () => { allowConsoleErrors() renderTestApp({ url: "/some-fake-route" }) await waitFor(() => { - expect(document.title).toBe("Not Found") + expect(document.title).toBe("Not Found | MIT Open") }) }) @@ -87,7 +87,7 @@ test("ErrorPage shows ForbiddenPage on restricted routes.", async () => { { user: { is_authenticated: true } }, ) await waitFor(() => { - expect(document.title).toBe("Not Allowed") + expect(document.title).toBe("Not Allowed | MIT Open") }) }) @@ -107,7 +107,7 @@ test("ErrorPage shows fallback and logs unexpected errors", async () => { { user: { is_authenticated: true } }, ) await waitFor(() => { - expect(document.title).toBe("Not Allowed") + expect(document.title).toBe("Not Allowed | MIT Open") }) expect(consoleError).toHaveBeenCalledWith(Error("Some Error")) }) diff --git a/frontends/mit-open/src/pages/ErrorPage/ErrorPageTemplate.tsx b/frontends/mit-open/src/pages/ErrorPage/ErrorPageTemplate.tsx index fa14bc1080..f3a889d8fd 100644 --- a/frontends/mit-open/src/pages/ErrorPage/ErrorPageTemplate.tsx +++ b/frontends/mit-open/src/pages/ErrorPage/ErrorPageTemplate.tsx @@ -21,9 +21,8 @@ const ErrorPageTemplate: React.FC = ({ return ( - + - {title} {children} diff --git a/frontends/mit-open/src/pages/ErrorPage/ForbiddenPage.test.tsx b/frontends/mit-open/src/pages/ErrorPage/ForbiddenPage.test.tsx index f5b428e779..decd9931f2 100644 --- a/frontends/mit-open/src/pages/ErrorPage/ForbiddenPage.test.tsx +++ b/frontends/mit-open/src/pages/ErrorPage/ForbiddenPage.test.tsx @@ -31,7 +31,7 @@ test("The ForbiddenPage loads with meta", async () => { }) renderWithProviders() await waitFor(() => { - expect(document.title).toBe("Not Allowed") + expect(document.title).toBe("Not Allowed | MIT Open") }) const meta = document.head.querySelector('meta[name="robots"]') diff --git a/frontends/mit-open/src/pages/FieldPage/EditFieldPage.tsx b/frontends/mit-open/src/pages/FieldPage/EditFieldPage.tsx index 52e0c0019b..f2cc45800b 100644 --- a/frontends/mit-open/src/pages/FieldPage/EditFieldPage.tsx +++ b/frontends/mit-open/src/pages/FieldPage/EditFieldPage.tsx @@ -38,9 +38,7 @@ const EditFieldPage: React.FC = () => { name={field.data?.name} channelType={field.data?.channel_type} > - - Edit {field.data.title} Channel - + {field.data.is_moderator ? (
diff --git a/frontends/mit-open/src/pages/FieldPage/FieldPageSkeleton.tsx b/frontends/mit-open/src/pages/FieldPage/FieldPageSkeleton.tsx index 4e08e79213..a113d85d33 100644 --- a/frontends/mit-open/src/pages/FieldPage/FieldPageSkeleton.tsx +++ b/frontends/mit-open/src/pages/FieldPage/FieldPageSkeleton.tsx @@ -9,6 +9,7 @@ import { Box, Breadcrumbs, } from "ol-components" +import { MetaTags } from "ol-utilities" import { SearchSubscriptionToggle } from "@/page-components/SearchSubscriptionToggle/SearchSubscriptionToggle" import { ChannelDetails } from "@/page-components/ChannelDetails/ChannelDetails" import { useChannelDetail } from "api/hooks/fields" @@ -101,89 +102,110 @@ const FieldSkeletonProps: React.FC = ({ ] return ( - - - - {field.data && ( - + <> + + + + + {field.data && ( ({ + flexDirection="column" + alignItems="start" + sx={{ flexGrow: 1, flexShrink: 0, order: 1, - py: "24px", - - [theme.breakpoints.down("md")]: { - py: 0, - pb: "8px", - }, - })} + width: "50%", + }} > - {displayConfiguration?.logo ? ( - + ({ + flexGrow: 1, + flexShrink: 0, + order: 1, + py: "24px", + + [theme.breakpoints.down("md")]: { + py: 0, + pb: "8px", + }, + })} + > + {displayConfiguration?.logo ? ( + + ) : ( + + + {field.data.title} + + + )} + + {displayConfiguration.heading ? ( + + + {displayConfiguration.heading} + + ) : ( - - - {field.data.title} - - + <> )} - - {displayConfiguration.heading ? ( = ({ my: 1, }} > - - {displayConfiguration.heading} + + {displayConfiguration.sub_heading} - ) : ( - <> - )} - - - {displayConfiguration.sub_heading} - + {channelType === "unit" ? ( + + + {field.data?.search_filter ? ( + + ) : null} + {field.data?.is_moderator ? ( + + ) : null} + + + ) : null} {channelType === "unit" ? ( + + + + ) : ( @@ -248,69 +299,24 @@ const FieldSkeletonProps: React.FC = ({ ) : null} - ) : null} + )} - {channelType === "unit" ? ( - - - - ) : ( - - - {field.data?.search_filter ? ( - - ) : null} - {field.data?.is_moderator ? ( - - ) : null} - - - )} - - )} - - - } - > - {channelType === "unit" ? ( - - - - ) : null} - {children} - + )} + + + } + > + {channelType === "unit" ? ( + + + + ) : null} + {children} + + ) } diff --git a/frontends/mit-open/src/pages/HomePage/HomePage.tsx b/frontends/mit-open/src/pages/HomePage/HomePage.tsx index 8872ff9c03..bf90af1250 100644 --- a/frontends/mit-open/src/pages/HomePage/HomePage.tsx +++ b/frontends/mit-open/src/pages/HomePage/HomePage.tsx @@ -1,5 +1,6 @@ import React from "react" import { Container, styled } from "ol-components" +import { MetaTags } from "ol-utilities" import HeroSearch from "./HeroSearch" import BrowseTopicsSection from "./BrowseTopicsSection" import NewsEventsSection from "./NewsEventsSection" @@ -35,6 +36,7 @@ const MediaCarousel = styled(ResourceCarousel)(({ theme }) => ({ const HomePage: React.FC = () => { return ( <> + diff --git a/frontends/mit-open/src/pages/LearningPathListingPage/LearningPathListingPage.test.tsx b/frontends/mit-open/src/pages/LearningPathListingPage/LearningPathListingPage.test.tsx index 4afee0591f..75fac9d5b7 100644 --- a/frontends/mit-open/src/pages/LearningPathListingPage/LearningPathListingPage.test.tsx +++ b/frontends/mit-open/src/pages/LearningPathListingPage/LearningPathListingPage.test.tsx @@ -37,7 +37,9 @@ describe("LearningPathListingPage", () => { it("Has title 'Learning Paths'", async () => { setup() screen.getByRole("heading", { name: "Learning Paths" }) - await waitFor(() => expect(document.title).toBe("Learning Paths")) + await waitFor(() => + expect(document.title).toBe("Learning Paths | MIT Open"), + ) }) it("Renders a card for each learning path", async () => { diff --git a/frontends/mit-open/src/pages/LearningPathListingPage/LearningPathListingPage.tsx b/frontends/mit-open/src/pages/LearningPathListingPage/LearningPathListingPage.tsx index 604c428f58..5802a15c5e 100644 --- a/frontends/mit-open/src/pages/LearningPathListingPage/LearningPathListingPage.tsx +++ b/frontends/mit-open/src/pages/LearningPathListingPage/LearningPathListingPage.tsx @@ -93,9 +93,7 @@ const LearningPathListingPage: React.FC = () => { src="/static/images/course_search_banner.png" className="learningpaths-page" > - - Learning Paths - + diff --git a/frontends/mit-open/src/pages/ListDetailsPage/ListDetailsPage.test.ts b/frontends/mit-open/src/pages/ListDetailsPage/ListDetailsPage.test.ts index b5d7082a69..1b7ba69ac3 100644 --- a/frontends/mit-open/src/pages/ListDetailsPage/ListDetailsPage.test.ts +++ b/frontends/mit-open/src/pages/ListDetailsPage/ListDetailsPage.test.ts @@ -71,7 +71,7 @@ describe("ListDetailsPage", () => { const path = factories.learningResources.learningPath() setup({ path }) await screen.findByRole("heading", { name: path.title }) - await waitFor(() => expect(document.title).toBe(path.title)) + await waitFor(() => expect(document.title).toBe(`${path.title} | MIT Open`)) }) test.each([ diff --git a/frontends/mit-open/src/pages/ListDetailsPage/ListDetailsPage.tsx b/frontends/mit-open/src/pages/ListDetailsPage/ListDetailsPage.tsx index dd52015a22..4c78a70a6c 100644 --- a/frontends/mit-open/src/pages/ListDetailsPage/ListDetailsPage.tsx +++ b/frontends/mit-open/src/pages/ListDetailsPage/ListDetailsPage.tsx @@ -114,9 +114,7 @@ const ListDetailsPage: React.FC = ({ src="/static/images/course_search_banner.png" className="learningpaths-page" > - - {title} - + { return activeStep < NUM_STEPS ? ( - - Onboarding - +
diff --git a/frontends/mit-open/src/pages/PrivacyPage/PrivacyPage.test.tsx b/frontends/mit-open/src/pages/PrivacyPage/PrivacyPage.test.tsx index 201ec15e7c..c354c1dd61 100644 --- a/frontends/mit-open/src/pages/PrivacyPage/PrivacyPage.test.tsx +++ b/frontends/mit-open/src/pages/PrivacyPage/PrivacyPage.test.tsx @@ -18,7 +18,7 @@ describe("PrivacyPage", () => { url: commonUrls.PRIVACY, }) await waitFor(() => { - expect(document.title).toBe("Privacy Policy") + expect(document.title).toBe("Privacy Policy | MIT Open") }) screen.getByRole("heading", { name: "Privacy Policy", diff --git a/frontends/mit-open/src/pages/PrivacyPage/PrivacyPage.tsx b/frontends/mit-open/src/pages/PrivacyPage/PrivacyPage.tsx index 77a025c459..dc4ea0b08a 100644 --- a/frontends/mit-open/src/pages/PrivacyPage/PrivacyPage.tsx +++ b/frontends/mit-open/src/pages/PrivacyPage/PrivacyPage.tsx @@ -55,9 +55,7 @@ const PrivacyPage: React.FC = () => { return ( - - Privacy Policy - + { return ( <> - - Search - + diff --git a/frontends/mit-open/src/pages/TermsPage/TermsPage.test.tsx b/frontends/mit-open/src/pages/TermsPage/TermsPage.test.tsx index e2fa01ea5d..21d37d92da 100644 --- a/frontends/mit-open/src/pages/TermsPage/TermsPage.test.tsx +++ b/frontends/mit-open/src/pages/TermsPage/TermsPage.test.tsx @@ -18,7 +18,7 @@ describe("TermsPage", () => { url: commonUrls.TERMS, }) await waitFor(() => { - expect(document.title).toBe("Terms of Service") + expect(document.title).toBe("Terms of Service | MIT Open") }) screen.getByRole("heading", { name: "Terms of Service", diff --git a/frontends/mit-open/src/pages/TermsPage/TermsPage.tsx b/frontends/mit-open/src/pages/TermsPage/TermsPage.tsx index 316d29bb06..635844e448 100644 --- a/frontends/mit-open/src/pages/TermsPage/TermsPage.tsx +++ b/frontends/mit-open/src/pages/TermsPage/TermsPage.tsx @@ -59,9 +59,7 @@ const TermsPage: React.FC = () => { return ( - - Terms of Service - + { setupApis() renderWithProviders() await waitFor(() => { - expect(document.title).toBe("MIT Open | Topics") + expect(document.title).toBe("Topics | MIT Open") }) screen.getByRole("heading", { name: "Topics" }) }) diff --git a/frontends/mit-open/src/pages/TopicListingPage/TopicsListingPage.tsx b/frontends/mit-open/src/pages/TopicListingPage/TopicsListingPage.tsx index 705c307d1d..cf3644a0bd 100644 --- a/frontends/mit-open/src/pages/TopicListingPage/TopicsListingPage.tsx +++ b/frontends/mit-open/src/pages/TopicListingPage/TopicsListingPage.tsx @@ -278,9 +278,7 @@ const ToopicsListingPage: React.FC = () => { }, [topicsQuery.data?.results, courseQuery.data, programQuery.data]) return ( - - MIT Open | Topics - + { setupApis() renderWithProviders() await waitFor(() => { - expect(document.title).toBe("MIT Open | Units") + expect(document.title).toBe("Units | MIT Open") }) screen.getByRole("heading", { name: "Academic & Professional Learning" }) }) diff --git a/frontends/mit-open/src/pages/UnitsListingPage/UnitsListingPage.tsx b/frontends/mit-open/src/pages/UnitsListingPage/UnitsListingPage.tsx index e27489140a..2506991e80 100644 --- a/frontends/mit-open/src/pages/UnitsListingPage/UnitsListingPage.tsx +++ b/frontends/mit-open/src/pages/UnitsListingPage/UnitsListingPage.tsx @@ -405,9 +405,7 @@ const UnitsListingPage: React.FC = () => { return ( - - MIT Open | Units - + { - it("Has title 'User Lists'", async () => { + it("Has heading 'User Lists' and correct page title", async () => { setup() screen.getByRole("heading", { name: "User Lists" }) - await waitFor(() => expect(document.title).toBe("User Lists")) + await waitFor(() => expect(document.title).toBe("My Lists | MIT Open")) }) it("Renders a card for each user list", async () => { diff --git a/frontends/mit-open/src/pages/UserListListingPage/UserListListingPage.tsx b/frontends/mit-open/src/pages/UserListListingPage/UserListListingPage.tsx index 249bd03057..4f783cf40f 100644 --- a/frontends/mit-open/src/pages/UserListListingPage/UserListListingPage.tsx +++ b/frontends/mit-open/src/pages/UserListListingPage/UserListListingPage.tsx @@ -164,9 +164,7 @@ const UserListListingPage: React.FC = () => { src="/static/images/course_search_banner.png" className="learningpaths-page" > - - User Lists - + { // within app, define process.env.VAR_NAME with default from cleanEnv MITOPEN_AXIOS_BASE_PATH, ENVIRONMENT, + SITE_NAME, }), ] .concat( diff --git a/frontends/ol-utilities/src/components/MetaTags.tsx b/frontends/ol-utilities/src/components/MetaTags.tsx index 7c94129e86..6564a0a933 100644 --- a/frontends/ol-utilities/src/components/MetaTags.tsx +++ b/frontends/ol-utilities/src/components/MetaTags.tsx @@ -2,6 +2,7 @@ import React from "react" import { Helmet } from "react-helmet-async" type MetaTagsProps = { + title?: string | string[] canonicalLink?: string children?: React.ReactNode } @@ -17,14 +18,22 @@ const getCanonicalUrl = (url: string): string => { /** * Renders a Helmet component to customize meta tags */ -const MetaTags: React.FC = ({ children, canonicalLink }) => - children || canonicalLink ? ( +const MetaTags: React.FC = ({ + title, + children, + canonicalLink, +}) => { + title = title ? (Array.isArray(title) ? title : [title]) : [] + + return ( + {[...title, process.env.SITE_NAME].join(" | ")} {children} {canonicalLink ? ( ) : null} - ) : null + ) +} export default MetaTags