Skip to content

Commit 874b5b7

Browse files
committed
test(cli): validate hyphenated collections via SSR output
Review feedback on #1716: prefer validating content collections through a prerendered component's output over asserting on the x-content-key wire format. Mirrors build.config.prerender-collections with a hyphenated collection (my-posts) and route (/my-blog), asserting the rendered links and the emitted data-*.json query files. Fails against the unfixed key parsing (collection resolves to zero pages). Refs #1715
1 parent 288136d commit 874b5b7

8 files changed

Lines changed: 235 additions & 0 deletions

File tree

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Use Case
3+
* Run Greenwood build command with prerender and active content, using Content as Data APIs
4+
* with a hyphenated collection name ("my-posts") and a hyphenated route ("/my-blog"), rendered
5+
* through SSR'd custom elements.
6+
*
7+
* User Result
8+
* Should generate a Greenwood build where the prerendered components list the pages of the
9+
* hyphenated collection / route, and the emitted data-*.json query files contain those pages
10+
* (regression for content keys being split on every hyphen).
11+
*
12+
* User Command
13+
* greenwood build
14+
*
15+
* User Config
16+
* {
17+
* activeContent: true,
18+
* prerender: true
19+
* }
20+
*
21+
* User Workspace
22+
* src/
23+
* components/
24+
* posts-list.js (getContentByCollection("my-posts"))
25+
* routes-list.js (getContentByRoute("/my-blog"))
26+
* pages/
27+
* my-blog/
28+
* first.html (collection: my-posts)
29+
* second.html (collection: my-posts)
30+
* index.html
31+
*/
32+
33+
// https://github.com/ProjectEvergreen/greenwood/issues/1715
34+
import fs from "node:fs/promises";
35+
import { expect } from "chai";
36+
import { JSDOM } from "jsdom";
37+
import path from "node:path";
38+
import { runSmokeTest } from "../../../../../test/smoke-test.js";
39+
import { getOutputTeardownFiles } from "../../../../../test/utils.js";
40+
import { Runner } from "gallinago";
41+
import { fileURLToPath } from "node:url";
42+
43+
describe("Build Greenwood With: ", function () {
44+
const LABEL =
45+
"Prerender Configuration turned on using Content as Data with a hyphenated collection";
46+
const cliPath = path.join(process.cwd(), "packages/cli/src/bin.js");
47+
const outputPath = fileURLToPath(new URL(".", import.meta.url));
48+
let runner;
49+
50+
before(function () {
51+
this.context = {
52+
publicDir: path.join(outputPath, "public"),
53+
};
54+
runner = new Runner();
55+
});
56+
57+
describe(LABEL, function () {
58+
before(async function () {
59+
await runner.setup(outputPath);
60+
await runner.runCommand(cliPath, "build");
61+
});
62+
63+
runSmokeTest(["public", "index"], LABEL);
64+
65+
describe("Default output for index.html with hyphenated collection content", function () {
66+
let dom;
67+
68+
before(async function () {
69+
dom = await JSDOM.fromFile(path.resolve(this.context.publicDir, "./index.html"));
70+
});
71+
72+
describe("post links from getContentByCollection('my-posts')", function () {
73+
let postLinks;
74+
75+
before(function () {
76+
postLinks = dom.window.document.querySelectorAll("ol li a");
77+
});
78+
79+
it("should have the expected number of post links from all pages in the collection", function () {
80+
expect(postLinks.length).to.equal(2);
81+
});
82+
83+
it("should have the expected link content from all pages in the collection", function () {
84+
expect(postLinks[0].getAttribute("href")).to.equal("/my-blog/first/");
85+
expect(postLinks[0].getAttribute("title")).to.equal("First Post");
86+
expect(postLinks[0].textContent).to.equal("First");
87+
88+
expect(postLinks[1].getAttribute("href")).to.equal("/my-blog/second/");
89+
expect(postLinks[1].getAttribute("title")).to.equal("Second Post");
90+
expect(postLinks[1].textContent).to.equal("Second");
91+
});
92+
});
93+
94+
describe("page links from getContentByRoute('/my-blog')", function () {
95+
let pageLinks;
96+
97+
before(function () {
98+
pageLinks = dom.window.document.querySelectorAll("ul li a");
99+
});
100+
101+
it("should have the expected number of page links for the hyphenated route", function () {
102+
expect(pageLinks.length).to.equal(2);
103+
});
104+
105+
it("should have the expected link content for the hyphenated route", function () {
106+
expect(pageLinks[0].getAttribute("href")).to.equal("/my-blog/first/");
107+
expect(pageLinks[1].getAttribute("href")).to.equal("/my-blog/second/");
108+
});
109+
});
110+
});
111+
112+
describe("Emitted data query files for the hyphenated content keys", function () {
113+
it("should emit a collection query file with the pages of the hyphenated collection", async function () {
114+
const collectionData = JSON.parse(
115+
await fs.readFile(
116+
path.resolve(this.context.publicDir, "./data-collection-my-posts.json"),
117+
"utf-8",
118+
),
119+
);
120+
const routes = collectionData.map((page) => page.route).sort();
121+
122+
expect(collectionData.length).to.equal(2);
123+
expect(routes).to.deep.equal(["/my-blog/first/", "/my-blog/second/"]);
124+
});
125+
126+
it("should emit a route query file with the pages of the hyphenated route", async function () {
127+
const routeData = JSON.parse(
128+
await fs.readFile(
129+
path.resolve(this.context.publicDir, "./data-route-_my-blog.json"),
130+
"utf-8",
131+
),
132+
);
133+
const routes = routeData.map((page) => page.route).sort();
134+
135+
expect(routeData.length).to.equal(2);
136+
expect(routes).to.deep.equal(["/my-blog/first/", "/my-blog/second/"]);
137+
});
138+
});
139+
});
140+
141+
after(async function () {
142+
await runner.teardown(getOutputTeardownFiles(outputPath));
143+
});
144+
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export default {
2+
activeContent: true,
3+
prerender: true,
4+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"type": "module"
3+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { getContentByCollection } from "@greenwood/cli/src/data/client.js";
2+
3+
export default class MyPostsList extends HTMLElement {
4+
async connectedCallback() {
5+
const posts = (await getContentByCollection("my-posts")).sort((a, b) =>
6+
a.data.order > b.data.order ? 1 : -1,
7+
);
8+
9+
this.innerHTML = `
10+
<ol>
11+
${posts
12+
.map((post) => {
13+
const { route, label, title } = post;
14+
15+
return `
16+
<li><a href="${route}" title="${title}">${label}</a></li>
17+
`;
18+
})
19+
.join("")}
20+
</ol>
21+
`;
22+
}
23+
}
24+
25+
customElements.define("x-my-posts-list", MyPostsList);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { getContentByRoute } from "@greenwood/cli/src/data/client.js";
2+
3+
export default class MyBlogRoutes extends HTMLElement {
4+
async connectedCallback() {
5+
const pages = (await getContentByRoute("/my-blog")).sort((a, b) =>
6+
a.data.order > b.data.order ? 1 : -1,
7+
);
8+
9+
this.innerHTML = `
10+
<ul>
11+
${pages
12+
.map((page) => {
13+
const { route, label, title } = page;
14+
15+
return `
16+
<li><a href="${route}" title="${title}">${label}</a></li>
17+
`;
18+
})
19+
.join("")}
20+
</ul>
21+
`;
22+
}
23+
}
24+
25+
customElements.define("x-my-blog-routes", MyBlogRoutes);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<html>
2+
<head>
3+
<script type="module" src="../components/posts-list.js" data-gwd-opt="static"></script>
4+
<script type="module" src="../components/routes-list.js" data-gwd-opt="static"></script>
5+
</head>
6+
7+
<body>
8+
<h1>Home Page</h1>
9+
<x-my-posts-list></x-my-posts-list>
10+
<x-my-blog-routes></x-my-blog-routes>
11+
</body>
12+
</html>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
collection: my-posts
3+
title: First Post
4+
order: 1
5+
---
6+
7+
<html>
8+
<body>
9+
<h1>First Post</h1>
10+
</body>
11+
</html>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
collection: my-posts
3+
title: Second Post
4+
order: 2
5+
---
6+
7+
<html>
8+
<body>
9+
<h1>Second Post</h1>
10+
</body>
11+
</html>

0 commit comments

Comments
 (0)