github-pages-template icon indicating copy to clipboard operation
github-pages-template copied to clipboard

Add structured data testing

Open fulldecent opened this issue 1 year ago • 1 comments

Add structured-data-testing-tool

See example https://github.com/ThatGuySam/doesitarm/blob/6e11fbe8e79156282aa9c5d61f87808182814325/test/main.js#L8

Specifically, we want to ensure that any json+ld scripts in build/**/*.html will have the correct schema formats.


Before we start this, do a simple test across all our pages with like

find | exec yarn dlx structured-data-testing-tool test...

If there are some errors on any built page on our sites then setting up this testing will be a win


End result:

  • [ ] Add script to package.json to validate after build
  • [ ] Add it to our CI testing pipeline after build
  • [ ] Create test cases with expected failures and include that to CI build (see existing CI build and fixtures for to check HTML Validate rules are working)

fulldecent avatar Sep 12 '24 18:09 fulldecent

Ideas:

yarn add --dev structured-data-testing-tool
yarn

And make tests/build-structurd-data-validate

import { structuredDataTest } from "structured-data-testing-tool";
import { glob } from "glob";
import { readFileSync } from "fs";

// Find and sort all HTML files in the 'build' directory
const targets = glob.sync("build/**/*.html").sort();

// Synchronously validate each target file
const outcomes = targets.map((target) => {
  const html = readFileSync(target, "utf8");
  let success = true;

  try {
    structuredDataTest(html)
      .then((res) => {
        console.log("✅ " + target);
        console.log("⚠️  Warnings:\n", res);
      })
      .catch((err) => {
        console.log("❌ " + target);
        console.log("⚠️  Errors:\n", err);
        success = false;
      });
    return success;
  } catch (error) {
    console.error(`Error validating ${target}:`, error);
    success = false;
  }
  return success;
});
if (outcomes.every((outcome) => outcome)) {
  console.log("✨ All tests passed!\n");
} else {
  console.log("❌ Some tests failed.");
  process.exit(1);
}

And test with index.html:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <title>My first website about horses</title>
    <link rel="canonical" href="https://localhost/">
  </head>

  <body>
    <nav class="navbar navbar-dark bg-dark">
      <div class="container">
        <h1 class="navbar-brand mb-0">My first website about horses</h1>
      </div>
    </nav>

    <section class="jumbotron text-center">
      <div class="container">
        <h1 class="jumbotron-heading">Album example</h1>
        <p class="lead text-muted">
          Something short and leading about the collection below—its contents, the creator, etc. Make it short and
          sweet, but not too short so folks don't simply skip over it entirely.
        </p>
        <p>
          <a href="/" class="btn btn-primary">Main call to action</a>
          <a href="/" class="btn btn-outline-secondary bg-white">Secondary action</a>
        </p>
      </div>
    </section>

    <div class="album text-muted">
      <div class="container">
        <div class="row">
          <div class="col">
            <img
              src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAACklEQVR4AWNgAAAAAgABc3UBGAAAAABJRU5ErkJggg=="
              alt="Card image cap"
              width="350"
              height="150"
            >

            <p class="card-text">
              This is a wider card with supporting text below as a natural lead-in to additional content. This content
              is a little bit longer.
            </p>
          </div>
          <div class="col">
            <img
              src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAACklEQVR4AWNgAAAAAgABc3UBGAAAAABJRU5ErkJggg=="
              alt="Card image cap"
              width="350"
              height="150"
            >

            <p class="card-text">
              This is a wider card with supporting text below as a natural lead-in to additional content. This content
              is a little bit longer.
            </p>
          </div>
        </div>
        <div class="row">
          <div class="col">
            <img
              src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAACklEQVR4AWNgAAAAAgABc3UBGAAAAABJRU5ErkJggg=="
              alt="Card image cap"
              width="350"
              height="150"
            >

            <p class="card-text">
              This is a wider card with supporting text below as a natural lead-in to additional content. This content
              is a little bit longer.
            </p>
          </div>
          <div class="col">
            <img
              src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAACklEQVR4AWNgAAAAAgABc3UBGAAAAABJRU5ErkJggg=="
              alt="Card image cap"
              width="350"
              height="150"
            >

            <p class="card-text">
              This is a wider card with supporting text below as a natural lead-in to additional content. This content
              is a little bit longer.
            </p>
          </div>
          <div class="col">
            <img
              src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAACklEQVR4AWNgAAAAAgABc3UBGAAAAABJRU5ErkJggg=="
              alt="Card image cap"
              width="350"
              height="150"
            >

            <p class="card-text">
              This is a wider card with supporting text below as a natural lead-in to additional content. This content
              is a little bit longer.
            </p>
          </div>
          <div class="col">
            <img
              src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAACklEQVR4AWNgAAAAAgABc3UBGAAAAABJRU5ErkJggg=="
              alt="Card image cap"
              width="350"
              height="150"
            >

            <p class="card-text">
              This is a wider card with supporting text below as a natural lead-in to additional content. This content
              is a little bit longer.
            </p>
          </div>
        </div>
        <div class="row">
          <div class="col">
            <img
              src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAACklEQVR4AWNgAAAAAgABc3UBGAAAAABJRU5ErkJggg=="
              alt="Card image cap"
              width="350"
              height="150"
            >

            <p class="card-text">
              This is a wider card with supporting text below as a natural lead-in to additional content. This content
              is a little bit longer.
            </p>
          </div>
          <div class="col">
            <img
              src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAACklEQVR4AWNgAAAAAgABc3UBGAAAAABJRU5ErkJggg=="
              alt="Card image cap"
              width="350"
              height="150"
            >

            <p class="card-text">
              This is a wider card with supporting text below as a natural lead-in to additional content. This content
              is a little bit longer.
            </p>
          </div>
          <div class="col">
            <img
              src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAACklEQVR4AWNgAAAAAgABc3UBGAAAAABJRU5ErkJggg=="
              alt="Card image cap"
              width="350"
              height="150"
            >

            <p class="card-text">
              This is a wider card with supporting text below as a natural lead-in to additional content. This content
              is a little bit longer.
            </p>
          </div>
        </div>
      </div>
    </div>

    <hr>
    <footer class="text-muted">
      <div class="container">
        <p>This web page was made with love and admiration by A Horse Lover.</p>
      </div>
    </footer>

    <script type="application/ld+json">
      {
        a"@context": "http://schema.org",
        "@type": "ReportageNewsArticle",
        "url": "https://www.bbc.co.uk/news/world-us-canada-49060410",
        "publisher": {
          "@type": "NewsMediaOrganization",
          "name": "BBC News",
          "publishingPrinciples": "http://www.bbc.co.uk/news/help-41670342",
          "logo": {
            "@type": "ImageObject",
            "url": "https://static.files.bbci.co.uk/ws/simorgh-assets/public/news/images/metadata/poster-1024x576.png"
          }
        },
        "datePublished": "2019-07-20T23:07:27.000Z",
        "dateModified": "2019-07-21T00:41:12.000Z",
        "description": "On 20 July 1969, Apollo 11 landed - and hours later Neil Armstrong took his historic first steps.",
        "headline": "Apollo 11: World celebrates 50th anniversary of first Moon landing",
        "image": {
          "@type": "ImageObject",
          "width": 1200,
          "height": 675,
          "url": "https://ichef.bbci.co.uk/ace/branded_news/1200/cpsprodpb/5509/production/_107896712_moonlanding3getty.jpg"
        },
        "thumbnailUrl": "https://ichef.bbci.co.uk/ace/branded_news/1200/cpsprodpb/5509/production/_107896712_moonlanding3getty.jpg",
        "mainEntityOfPage": "https://www.bbc.co.uk/news/world-us-canada-49060410",
        "author": {
          "@type": "NewsMediaOrganization",
          "name": "BBC News",
          "noBylinesPolicy": "http://www.bbc.co.uk/news/help-41670342#authorexpertise",
          "logo": {
            "@type": "ImageObject",
            "url": "https://static.files.bbci.co.uk/ws/simorgh-assets/public/news/images/metadata/poster-1024x576.png"
          }
        }
      }
    </script>
  </body>
</html>

!!! Notice a before @context.

This should print as an error. But it does not.

Otherwise, this is successfully testing the schema format.

fulldecent avatar Apr 17 '25 18:04 fulldecent