Skip to content

Commit f097d1f

Browse files
committed
#3414 webpage: add tests for head tags, blog items and rss feed
Signed-off-by: Patrizio Bekerle <[email protected]>
1 parent 553ee97 commit f097d1f

File tree

3 files changed

+325
-0
lines changed

3 files changed

+325
-0
lines changed

webpage/tests/blog.spec.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// @ts-check
2+
import { test, expect } from "./fixtures.js";
3+
4+
test("blog overview page", async ({ page, config }) => {
5+
await page.goto(config.baseURL + "/blog/");
6+
await expect(page).toHaveTitle(/Overview.*QOwnNotes/);
7+
await expect(
8+
page.getByRole("heading", { level: 1, name: "Blog" }),
9+
).toBeVisible();
10+
});
11+
12+
test("blog entry - AI support", async ({ page, config }) => {
13+
await page.goto(
14+
config.baseURL + "/blog/2024-05-17-AI-support-was-added-to-QOwnNotes.html",
15+
);
16+
await expect(page).toHaveTitle(/AI support was added to QOwnNotes/);
17+
await expect(
18+
page.getByRole("heading", {
19+
level: 1,
20+
name: "AI support was added to QOwnNotes",
21+
}),
22+
).toBeVisible();
23+
});
24+
25+
test("blog entry - Command-line snippet manager", async ({ page, config }) => {
26+
await page.goto(
27+
config.baseURL +
28+
"/blog/2021-11-23-QOwnNotes-command-line-snippet-manager.html",
29+
);
30+
await expect(page).toHaveTitle(/QOwnNotes command-line snippet manager/);
31+
await expect(
32+
page.getByRole("heading", {
33+
level: 1,
34+
name: "QOwnNotes command-line snippet manager",
35+
}),
36+
).toBeVisible();
37+
await expect(
38+
page.getByText("Use the QOwnNotes command-line snippet manager"),
39+
).toBeVisible();
40+
});
41+
42+
test("blog entry - Nextcloud Deck integration", async ({ page, config }) => {
43+
await page.goto(
44+
config.baseURL +
45+
"/blog/2023-06-17-Nextcloud-Deck-integration-in-QOwnNotes.html",
46+
);
47+
await expect(page).toHaveTitle(/Nextcloud Deck integration/);
48+
await expect(
49+
page.getByRole("heading", {
50+
level: 1,
51+
name: "Nextcloud Deck integration in QOwnNotes",
52+
}),
53+
).toBeVisible();
54+
});
55+
56+
test("blog entry - 1000th release", async ({ page, config }) => {
57+
await page.goto(
58+
config.baseURL + "/blog/2022-12-06-Happy-1000th-release-of-QOwnNotes.html",
59+
);
60+
await expect(page).toHaveTitle(/1000th release/);
61+
await expect(
62+
page.getByRole("heading", {
63+
level: 1,
64+
name: "Happy 1000th release of QOwnNotes",
65+
}),
66+
).toBeVisible();
67+
});
68+
69+
test("blog entry - Joplin import", async ({ page, config }) => {
70+
await page.goto(config.baseURL + "/blog/2021-07-18-Joplin-import.html");
71+
await expect(page).toHaveTitle(/Joplin import/);
72+
await expect(
73+
page.getByRole("heading", { level: 1, name: "Joplin import" }),
74+
).toBeVisible();
75+
await expect(page.getByText("Import your notes from Joplin")).toBeVisible();
76+
});

webpage/tests/head-tags.spec.js

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
// @ts-check
2+
import { test, expect } from "./fixtures.js";
3+
4+
test("blog head tags - meta description", async ({ page, config }) => {
5+
await page.goto(
6+
config.baseURL + "/blog/2024-05-17-AI-support-was-added-to-QOwnNotes.html",
7+
);
8+
9+
const metaDescription = page.locator('meta[name="description"]');
10+
await expect(metaDescription).toHaveAttribute(
11+
"content",
12+
"QOwnNotes now has AI support, currently for Groq and OpenAI!",
13+
);
14+
});
15+
16+
test("blog head tags - Open Graph meta tags", async ({ page, config }) => {
17+
await page.goto(
18+
config.baseURL + "/blog/2024-05-17-AI-support-was-added-to-QOwnNotes.html",
19+
);
20+
21+
// Check Open Graph title
22+
const ogTitle = page.locator('meta[property="og:title"]');
23+
await expect(ogTitle).toHaveAttribute(
24+
"content",
25+
"AI support was added to QOwnNotes",
26+
);
27+
28+
// Check Open Graph description
29+
const ogDescription = page.locator('meta[property="og:description"]');
30+
await expect(ogDescription).toHaveAttribute(
31+
"content",
32+
"QOwnNotes now has AI support, currently for Groq and OpenAI!",
33+
);
34+
35+
// Check Open Graph type
36+
const ogType = page.locator('meta[property="og:type"]');
37+
await expect(ogType).toHaveAttribute("content", "article");
38+
39+
// Check Open Graph URL
40+
const ogUrl = page.locator('meta[property="og:url"]');
41+
await expect(ogUrl).toHaveAttribute(
42+
"content",
43+
"https://www.qownnotes.org/blog/2024-05-17-AI-support-was-added-to-QOwnNotes.html",
44+
);
45+
46+
// Check Open Graph image
47+
const ogImage = page.locator('meta[property="og:image"]');
48+
await expect(ogImage).toHaveAttribute(
49+
"content",
50+
"https://www.qownnotes.org/assets/img/robot-taking-notes.jpg",
51+
);
52+
});
53+
54+
test("blog head tags - Twitter Card meta tags", async ({ page, config }) => {
55+
await page.goto(
56+
config.baseURL + "/blog/2024-05-17-AI-support-was-added-to-QOwnNotes.html",
57+
);
58+
59+
// Check Twitter card type
60+
const twitterCard = page.locator('meta[name="twitter:card"]');
61+
await expect(twitterCard).toHaveAttribute("content", "summary_large_image");
62+
63+
// Check Twitter title
64+
const twitterTitle = page.locator('meta[name="twitter:title"]');
65+
await expect(twitterTitle).toHaveAttribute(
66+
"content",
67+
"AI support was added to QOwnNotes",
68+
);
69+
70+
// Check Twitter description
71+
const twitterDescription = page.locator('meta[name="twitter:description"]');
72+
await expect(twitterDescription).toHaveAttribute(
73+
"content",
74+
"QOwnNotes now has AI support, currently for Groq and OpenAI!",
75+
);
76+
77+
// Check Twitter image
78+
const twitterImage = page.locator('meta[name="twitter:image"]');
79+
await expect(twitterImage).toHaveAttribute(
80+
"content",
81+
"https://www.qownnotes.org/assets/img/robot-taking-notes.jpg",
82+
);
83+
84+
// Check Twitter creator
85+
const twitterCreator = page.locator('meta[name="twitter:creator"]');
86+
await expect(twitterCreator).toHaveAttribute("content", "@PatrizioBekerle");
87+
});
88+
89+
test("blog head tags - favicon link", async ({ page, config }) => {
90+
await page.goto(
91+
config.baseURL + "/blog/2024-05-17-AI-support-was-added-to-QOwnNotes.html",
92+
);
93+
94+
const favicon = page.locator('link[rel="icon"]');
95+
await expect(favicon).toHaveAttribute("href", "/favicon.png");
96+
await expect(favicon).toHaveAttribute("type", "image/png");
97+
});
98+
99+
test("blog head tags - RSS feed links", async ({ page, config }) => {
100+
await page.goto(
101+
config.baseURL + "/blog/2024-05-17-AI-support-was-added-to-QOwnNotes.html",
102+
);
103+
104+
// Check RSS feed link
105+
const rssFeed = page.locator('link[rel="alternate"][href*="rss.xml"]');
106+
await expect(rssFeed).toHaveAttribute(
107+
"href",
108+
"https://www.qownnotes.org/rss.xml",
109+
);
110+
await expect(rssFeed).toHaveAttribute("type", "application/rss+xml");
111+
112+
// Check Atom feed link
113+
const atomFeed = page.locator('link[rel="alternate"][href*="feed.atom"]');
114+
await expect(atomFeed).toHaveAttribute(
115+
"href",
116+
"https://www.qownnotes.org/feed.atom",
117+
);
118+
await expect(atomFeed).toHaveAttribute("type", "application/atom+xml");
119+
120+
// Check JSON feed link
121+
const jsonFeed = page.locator('link[rel="alternate"][href*="feed.json"]');
122+
await expect(jsonFeed).toHaveAttribute(
123+
"href",
124+
"https://www.qownnotes.org/feed.json",
125+
);
126+
await expect(jsonFeed).toHaveAttribute("type", "application/json");
127+
});
128+
129+
test("blog head tags - viewport meta tag", async ({ page, config }) => {
130+
await page.goto(
131+
config.baseURL + "/blog/2024-05-17-AI-support-was-added-to-QOwnNotes.html",
132+
);
133+
134+
const viewport = page.locator('meta[name="viewport"]');
135+
await expect(viewport).toHaveAttribute(
136+
"content",
137+
"width=device-width, initial-scale=1.0",
138+
);
139+
});
140+
141+
test("blog head tags - theme color", async ({ page, config }) => {
142+
await page.goto(
143+
config.baseURL + "/blog/2024-05-17-AI-support-was-added-to-QOwnNotes.html",
144+
);
145+
146+
const themeColor = page.locator('meta[name="theme-color"]');
147+
await expect(themeColor).toHaveAttribute("content", "#3eaf7c");
148+
});
149+
150+
test("blog head tags - social profile links", async ({ page, config }) => {
151+
await page.goto(
152+
config.baseURL + "/blog/2024-05-17-AI-support-was-added-to-QOwnNotes.html",
153+
);
154+
155+
// Check for rel="me" links (social profile verification)
156+
const socialLinks = page.locator('link[rel="me"]');
157+
await expect(socialLinks).toHaveCount(2);
158+
159+
// Check for Mastodon link
160+
const mastodonLink = page.locator(
161+
'link[rel="me"][href*="social.qownnotes.org/@qownnotes"]',
162+
);
163+
await expect(mastodonLink).toHaveAttribute(
164+
"href",
165+
"https://social.qownnotes.org/@qownnotes",
166+
);
167+
});

webpage/tests/rss.spec.js

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// @ts-check
2+
import { test, expect } from "./fixtures.js";
3+
4+
test("RSS feed is accessible", async ({ page, config }) => {
5+
const response = await page.goto(config.baseURL + "/rss.xml");
6+
expect(response.status()).toBe(200);
7+
});
8+
9+
test("RSS feed has correct content type", async ({ page, config }) => {
10+
const response = await page.goto(config.baseURL + "/rss.xml");
11+
const contentType = response.headers()["content-type"];
12+
expect(contentType).toMatch(/(xml|rss)/i);
13+
});
14+
15+
test("RSS feed has valid RSS structure", async ({ page, config }) => {
16+
await page.goto(config.baseURL + "/rss.xml");
17+
const content = await page.content();
18+
19+
// Check for basic RSS structure
20+
expect(content).toContain("<rss");
21+
expect(content).toContain('version="2.0"');
22+
expect(content).toContain("<channel>");
23+
expect(content).toContain("</channel>");
24+
expect(content).toContain("</rss>");
25+
});
26+
27+
test("RSS feed has channel metadata", async ({ page, config }) => {
28+
await page.goto(config.baseURL + "/rss.xml");
29+
const content = await page.content();
30+
31+
// Check channel metadata
32+
expect(content).toContain("<title>QOwnNotes Blog</title>");
33+
expect(content).toContain("<link>https://www.qownnotes.org</link>");
34+
expect(content).toContain("<description>News about QOwnNotes");
35+
expect(content).toContain("<lastBuildDate>");
36+
expect(content).toContain("</lastBuildDate>");
37+
});
38+
39+
test("RSS feed contains blog items", async ({ page, config }) => {
40+
await page.goto(config.baseURL + "/rss.xml");
41+
const content = await page.content();
42+
43+
// Check that there are items
44+
expect(content).toContain("<item>");
45+
expect(content).toContain("</item>");
46+
});
47+
48+
test("RSS feed items have required fields", async ({ page, config }) => {
49+
await page.goto(config.baseURL + "/rss.xml");
50+
const content = await page.content();
51+
52+
// Each item should have title, link, guid, and pubDate
53+
const itemMatches = content.match(/<item>/g);
54+
expect(itemMatches).not.toBeNull();
55+
expect(itemMatches.length).toBeGreaterThan(0);
56+
57+
// Check for required fields in items
58+
expect(content).toContain("<title>");
59+
expect(content).toContain("<link>");
60+
expect(content).toContain("<guid>");
61+
expect(content).toContain("<pubDate>");
62+
});
63+
64+
test("RSS feed contains specific blog entries", async ({ page, config }) => {
65+
await page.goto(config.baseURL + "/rss.xml");
66+
const content = await page.content();
67+
68+
// Check for some known blog entries
69+
expect(content).toContain("Universal binary for macOS");
70+
expect(content).toContain("AI support was added to QOwnNotes");
71+
expect(content).toContain("QOwnNotes command-line snippet manager");
72+
});
73+
74+
test("RSS feed atom link is present", async ({ page, config }) => {
75+
await page.goto(config.baseURL + "/rss.xml");
76+
const content = await page.content();
77+
78+
// Check for atom:link
79+
expect(content).toContain("<atom:link");
80+
expect(content).toContain('href="https://www.qownnotes.org/feed.atom"');
81+
expect(content).toContain('type="application/rss+xml"');
82+
});

0 commit comments

Comments
 (0)