Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ Perform website testing (you must have already [built the site](#build-the-site)
yarn test
```

#### Structured Data Testing

Test structured data (JSON-LD) validation specifically:

```sh
yarn test-structured-data
```

This validates that any `application/ld+json` scripts in `build/**/*.html` files have correct schema.org formats and valid JSON syntax.

## Notes for VS Code

Open this folder in VS Code, allow the "Reopen in Container" and install recommended extensions.
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
"html-validate": "^10.0.0",
"markdownlint-cli2": "^0.18.1",
"prettier": "^3.6.2",
"shell-quote": "^1.8.3"
"shell-quote": "^1.8.3",
"structured-data-testing-tool": "^4.5.0"
},
"scripts": {
"test": "node test/fixtures-html-validate-should-fail.mjs && node test/build-html-validate.mjs && node test/dirty-words-checker.mjs && node test/dirty-file-paths-checker.mjs",
"test": "yarn node test/fixtures-html-validate-should-fail.mjs && yarn node test/fixtures-structured-data-should-fail.mjs && yarn node test/build-html-validate.mjs && yarn node test/dirty-words-checker.mjs && yarn node test/dirty-file-paths-checker.mjs && yarn node test/build-structured-data-validate.mjs",
"test-structured-data": "yarn node test/build-structured-data-validate.mjs",
"lint": "yarn prettier-check && yarn markdownlint-check",
"lint-fix": "yarn prettier-fix && yarn markdownlint-fix",
"generate-sitemap": "node scripts/generate-sitemap.mjs",
Expand Down
65 changes: 65 additions & 0 deletions test/build-structured-data-validate.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { glob } from "glob";
import { execSync } from "child_process";
import fs from "fs";
import path from "path";

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

if (targets.length === 0) {
console.log("⚠️ No HTML files found in build directory");
console.log(" Make sure to build the site first");
process.exit(0);
}

console.log(`🧪 Validating structured data in ${targets.length} files...`);

let hasErrors = false;

// Validate each target file
for (const target of targets) {
try {
// Use structured-data-testing-tool CLI to test the file
const result = execSync(`yarn dlx structured-data-testing-tool --file "${target}"`, {
encoding: "utf8",
stdio: "pipe",
});

// Check if there are JSON-LD parse errors or failed tests in the output
if (result.includes("Error in jsonld parse") || (result.includes("Failed:") && !result.includes("Failed: 0"))) {
console.log("❌ " + target);
console.log(result);
hasErrors = true;
} else {
console.log("✅ " + target);
// Show a summary of structured data found
const lines = result.split("\n");
const schemaLine = lines.find((line) => line.includes("Schema.org schemas:"));
if (schemaLine && !schemaLine.includes("Schema.org schemas: 0")) {
console.log(` 📋 ${schemaLine.trim()}`);
}
// Only show detailed output if there are warnings
if (result.includes("Warnings:") && !result.includes("Warnings: 0")) {
console.log("⚠️ Warnings found:");
console.log(result);
}
}
} catch (error) {
console.log("❌ " + target);
console.log("⚠️ Error testing file:", error.message);
if (error.stdout) {
console.log(error.stdout);
}
if (error.stderr) {
console.error(error.stderr);
}
hasErrors = true;
}
}

if (hasErrors) {
console.log("❌ Some tests failed.");
process.exit(1);
} else {
console.log("✨ All tests passed!\n");
}
58 changes: 58 additions & 0 deletions test/fixtures-structured-data-should-fail.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { execSync } from "child_process";
import path from "path";

console.log("🧪 Testing structured data fixtures");

const fixtures = [
{
file: "test/fixtures/valid-jsonld.html",
shouldPass: true,
description: "valid JSON-LD",
},
{
file: "test/fixtures/invalid-jsonld.html",
shouldPass: false,
description: "invalid JSON-LD (syntax error)",
},
];

let allTestsPassed = true;

for (const fixture of fixtures) {
try {
const result = execSync(`yarn dlx structured-data-testing-tool --file "${fixture.file}"`, {
encoding: "utf8",
stdio: "pipe",
});

const hasError =
result.includes("Error in jsonld parse") || (result.includes("Failed:") && !result.includes("Failed: 0"));

const actuallyPassed = !hasError;

if (actuallyPassed === fixture.shouldPass) {
console.log(`✅ ${fixture.file}: ${fixture.description} - ${actuallyPassed ? "passed" : "failed"} as expected`);
} else {
console.error(
`❌ ${fixture.file}: ${fixture.description} - expected ${fixture.shouldPass ? "pass" : "fail"} but got ${actuallyPassed ? "pass" : "fail"}`,
);
console.error("Output:", result);
allTestsPassed = false;
}
} catch (error) {
// execSync throws on non-zero exit codes, but structured-data-testing-tool doesn't always exit with error codes
console.error(`❌ ${fixture.file}: ${fixture.description} - execution error`);
console.error("Error:", error.message);
if (error.stdout) {
console.error("Stdout:", error.stdout);
}
allTestsPassed = false;
}
}

if (allTestsPassed) {
console.log("✨ All fixtures produced expected results!\n");
} else {
console.error("❌ Some fixture tests failed.");
process.exit(1);
}
49 changes: 49 additions & 0 deletions test/fixtures/invalid-jsonld.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test page with invalid JSON-LD</title>
</head>
<body>
<h1>Test page with invalid JSON-LD</h1>
<p>This page has invalid JSON-LD structured data.</p>

<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>
49 changes: 49 additions & 0 deletions test/fixtures/valid-jsonld.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test page with valid JSON-LD</title>
</head>
<body>
<h1>Test page with valid JSON-LD</h1>
<p>This page has valid JSON-LD structured data.</p>

<script type="application/ld+json">
{
"@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>
Loading
Loading