diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md index a1595923..503aa577 100644 --- a/TROUBLESHOOTING.md +++ b/TROUBLESHOOTING.md @@ -304,6 +304,22 @@ Given `npm install` / `npm ci` floods the terminal with `npm warn deprecated … 3. Prefer fixing/removing those roots over adding an `override` per leaf package; 4. Keep using Node 18 + `npm install --legacy-peer-deps` for this stack. +## Jest PropTypes: SEO required `description` undefined + +Given the browser console shows: + +``` +Warning: Failed prop type: The prop `description` is marked as required in `SEO`, but its value is `undefined`. + at SEO (…/metax/…) + at SEO (src/components/SEO/…) + at IndexTemplate (src/templates/index.js) +``` + +1. Ensure `src/components/SEO` defaults `description` (and `title`) from `useSiteMetadata()` when omitted; +2. Prefer page-specific `description` on important routes (e.g. home `IndexTemplate`); +3. Upstream: [muy/muy#154](https://github.com/muy/muy/issues/154) / PR for `metax` `mergeProps` fallback; +4. See #455. + ## Gatsby HMR eslint-loader: unused vars / anonymous page exports Given the browser console (or terminal) shows eslint-loader module warnings such as: diff --git a/src/components/SEO/index.js b/src/components/SEO/index.js index 1e6690d1..445b6def 100644 --- a/src/components/SEO/index.js +++ b/src/components/SEO/index.js @@ -2,74 +2,80 @@ import React from "react" import { SEO as MetaxSEO } from "metax" import useSiteMetadata from "../../hooks/useSiteMetadata" -const SEO = (props) => ( - -) +const SEO = ({ description, title, ...props }) => { + const siteMetadata = useSiteMetadata() + + return ( + + ) +} export default SEO diff --git a/src/components/SEO/index.test.js b/src/components/SEO/index.test.js new file mode 100644 index 00000000..3860a3e4 --- /dev/null +++ b/src/components/SEO/index.test.js @@ -0,0 +1,65 @@ +import React from "react" +import { render } from "@testing-library/react" +import SEO from "." + +jest.mock("../../hooks/useSiteMetadata", () => () => ({ + description: "Site default description", + title: "Multei!", + titleTemplate: "%s | Multei!", +})) + +const mockMetaxSEO = jest.fn(() => null) + +jest.mock("metax", () => ({ + SEO: (props) => { + mockMetaxSEO(props) + return null + }, +})) + +describe("", () => { + beforeEach(() => { + mockMetaxSEO.mockClear() + }) + + it("defaults description and title from site metadata", () => { + const consoleError = jest + .spyOn(console, "error") + .mockImplementation(() => {}) + + render() + + expect(mockMetaxSEO).toHaveBeenCalledWith( + expect.objectContaining({ + description: "Site default description", + title: "Multei!", + }) + ) + + const descriptionWarnings = consoleError.mock.calls.filter((args) => + args.some( + (arg) => + typeof arg === "string" && + arg.includes("prop `description` is marked as required") + ) + ) + expect(descriptionWarnings).toHaveLength(0) + consoleError.mockRestore() + }) + + it("prefers explicit description and title props", () => { + render( + + ) + + expect(mockMetaxSEO).toHaveBeenCalledWith( + expect.objectContaining({ + description: "Page-specific description", + title: "Denunciar estacionamento irregular", + }) + ) + }) +}) diff --git a/src/templates/index.js b/src/templates/index.js index e1beb617..f4c430fa 100644 --- a/src/templates/index.js +++ b/src/templates/index.js @@ -15,6 +15,7 @@ const IndexTemplate = () => { return (