-
Notifications
You must be signed in to change notification settings - Fork 282
/
test-generic-post.js
202 lines (183 loc) · 7.25 KB
/
test-generic-post.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
const assert = require("assert").strict;
const expect = require("expect.js");
const { JSDOM } = require("jsdom");
const readFileSync = require("fs").readFileSync;
const existsSync = require("fs").existsSync;
const metadata = require("../_data/metadata.json");
const GA_ID = require("../_data/googleanalytics.js")();
/**
* These tests kind of suck and they are kind of useful.
*
* They suck, because they need to be changed when the hardcoded post changes.
* They are useful because I tend to break the things they test al the time.
*/
describe("check build output for a generic post", () => {
describe("sample post", () => {
const POST_FILENAME = "_site/posts/firstpost/index.html";
const URL = metadata.url;
const POST_URL = URL + "/posts/firstpost/";
if (!existsSync(POST_FILENAME)) {
it("WARNING skipping tests because POST_FILENAME does not exist", () => {});
return;
}
let dom;
let html;
let doc;
function select(selector, opt_attribute) {
const element = doc.querySelector(selector);
assert(element, "Expected to find: " + selector);
if (opt_attribute) {
return element.getAttribute(opt_attribute);
}
return element.textContent;
}
before(() => {
html = readFileSync(POST_FILENAME);
dom = new JSDOM(html);
doc = dom.window.document;
});
it("should have metadata", () => {
assert.equal(select("title"), "This is my first post.");
expect(select("meta[property='og:image']", "content")).to.match(
/\/img\/remote\/\w+.jpg/
);
assert.equal(select("link[rel='canonical']", "href"), POST_URL);
assert.equal(
select("meta[name='description']", "content"),
"This is a post on My Blog about agile frameworks."
);
});
it("should have inlined css", () => {
const css = select("style");
expect(css).to.match(/header nav/);
expect(css).to.not.match(/test-dead-code-elimination-sentinel/);
});
it("should have script elements", () => {
const scripts = doc.querySelectorAll("script[src]");
expect(scripts).to.have.length(GA_ID ? 2 : 1);
expect(scripts[0].getAttribute("src")).to.match(
/^\/js\/min\.js\?hash=\w+/
);
});
it("should have GA a setup", () => {
if (!GA_ID) {
return;
}
const scripts = doc.querySelectorAll("script[src]");
expect(scripts[1].getAttribute("src")).to.match(
/^\/js\/cached\.js\?hash=\w+/
);
const noscript = doc.querySelectorAll("noscript");
expect(noscript.length).to.be.greaterThan(0);
let count = 0;
for (let n of noscript) {
if (n.textContent.includes("/.netlify/functions/ga")) {
count++;
expect(n.textContent).to.contain(GA_ID);
}
}
expect(count).to.equal(1);
});
it("should have a good CSP", () => {
const csp = select(
"meta[http-equiv='Content-Security-Policy']",
"content"
);
expect(csp).to.contain(";object-src 'none';");
expect(csp).to.match(/^default-src 'self';/);
});
it("should have accessible buttons", () => {
const buttons = doc.querySelectorAll("button");
for (let b of buttons) {
expect(
(b.firstElementChild === null && b.textContent.trim()) ||
b.getAttribute("aria-label") != null
).to.be.true;
}
});
it("should have a share widget", () => {
expect(select("share-widget button", "href")).to.equal(POST_URL);
});
it("should have a header", () => {
expect(select("header > h1")).to.equal("This is my first post.");
expect(select("header aside")).to.match(/\d+ min read./);
expect(select("header dialog", "id")).to.equal("message");
});
it("should have a published date", () => {
expect(select("article time")).to.equal("01 May 2018");
expect(select("article time", "datetime")).to.equal("2018-05-01");
});
it("should link to twitter with noopener", () => {
const twitterLinks = Array.from(doc.querySelectorAll("a")).filter((a) =>
a.href.startsWith("https://twitter.com")
);
for (let a of twitterLinks) {
expect(a.rel).to.contain("noopener");
expect(a.target).to.equal("_blank");
}
});
describe("body", () => {
it("should have images", () => {
const images = Array.from(
doc.querySelectorAll("article :not(aside) picture img")
);
const pictures = Array.from(
doc.querySelectorAll("article :not(aside) picture")
);
const metaImage = select("meta[property='og:image']", "content");
expect(images.length).to.greaterThan(0);
expect(pictures.length).to.greaterThan(0);
const img = images[0];
const picture = pictures[0];
const sources = Array.from(picture.querySelectorAll("source"));
expect(sources).to.have.length(2);
expect(img.src).to.match(/\/img\/remote\/\w+\.jpg/);
expect(metaImage).to.equal(URL + img.src);
// Comment back in when avif is stable enough.
//const avif = sources.shift();
const webp = sources.shift();
const jpg = sources.shift();
expect(jpg.srcset).to.match(
/\/img\/remote\/\w+-1920w.jpg 1920w, \/img\/remote\/\w+-1280w.jpg 1280w, \/img\/remote\/\w+-640w.jpg 640w, \/img\/remote\/\w+-320w.jpg 320w/
);
expect(webp.srcset).to.match(
/\/img\/remote\/\w+-1920w.webp 1920w, \/img\/remote\/\w+-1280w.webp 1280w, \/img\/remote\/\w+-640w.webp 640w, \/img\/remote\/\w+-320w.webp 320w/
);
//expect(avif.srcset).to.match(
// /\/img\/remote\/\w+-1920w.avif 1920w, \/img\/remote\/\w+-1280w.avif 1280w, \/img\/remote\/\w+-640w.avif 640w, \/img\/remote\/\w+-320w.avif 320w/
//);
expect(jpg.type).to.equal("image/jpeg");
expect(webp.type).to.equal("image/webp");
//expect(avif.type).to.equal("image/avif");
expect(jpg.sizes).to.equal("(max-width: 608px) 100vw, 608px");
expect(webp.sizes).to.equal("(max-width: 608px) 100vw, 608px");
expect(img.height).to.equal(850);
expect(img.width).to.equal(1280);
expect(img.getAttribute("loading")).to.equal("lazy");
expect(img.getAttribute("decoding")).to.equal("async");
// JSDom fails to parse the style attribute properly
expect(img.outerHTML).to.match(/svg/);
expect(img.outerHTML).to.match(/filter/);
});
it("should have json-ld", () => {
const json = select("script[type='application/ld+json']");
const images = Array.from(
doc.querySelectorAll("article :not(aside) img")
);
const obj = JSON.parse(json);
expect(obj.url).to.equal(POST_URL);
expect(obj.description).to.equal(
"Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster..."
);
expect(obj.image.length).to.be.greaterThan(0);
obj.image.forEach((url, index) => {
expect(url).to.equal(URL + images[index].src);
});
});
it("should have paragraphs", () => {
const images = Array.from(doc.querySelectorAll("article > p"));
expect(images.length).to.greaterThan(0);
});
});
});
});