← back to Wallco Ai
marketplace SEO: add smoke tests for sitemap + designer/pattern JSON-LD
e092403d2dcaf88d7ff6922ab3a82d49cbb9694a · 2026-05-13 14:55:28 -0700 · SteveStudio2
Covers the new endpoints shipped in the SEO foundation:
* GET /sitemap-marketplace.xml — asserts XML envelope + section URLs
* GET /designers/:slug — asserts canonical + og:type=profile + Person JSON-LD
* GET /patterns/:slug — asserts og:type=product + Product + CreativeWork JSON-LD
Also rides along leaderboard + challenges smoke tests that piggybacked on the
same file during parallel work.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Files touched
M tests/marketplace/smoke.test.js
Diff
commit e092403d2dcaf88d7ff6922ab3a82d49cbb9694a
Author: SteveStudio2 <steve@designerwallcoverings.com>
Date: Wed May 13 14:55:28 2026 -0700
marketplace SEO: add smoke tests for sitemap + designer/pattern JSON-LD
Covers the new endpoints shipped in the SEO foundation:
* GET /sitemap-marketplace.xml — asserts XML envelope + section URLs
* GET /designers/:slug — asserts canonical + og:type=profile + Person JSON-LD
* GET /patterns/:slug — asserts og:type=product + Product + CreativeWork JSON-LD
Also rides along leaderboard + challenges smoke tests that piggybacked on the
same file during parallel work.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
tests/marketplace/smoke.test.js | 69 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 68 insertions(+), 1 deletion(-)
diff --git a/tests/marketplace/smoke.test.js b/tests/marketplace/smoke.test.js
index b10bc37..2b85e5f 100644
--- a/tests/marketplace/smoke.test.js
+++ b/tests/marketplace/smoke.test.js
@@ -102,13 +102,80 @@ t('GET /api/marketplace/admin/payouts/:id/download requires admin', async () =>
assert.strictEqual(r.status, 403);
});
+t('GET /api/marketplace/leaderboard?metric=points returns leaderboard array', async () => {
+ const r = await req('GET', '/api/marketplace/leaderboard?metric=points&limit=10');
+ assert.strictEqual(r.status, 200);
+ assert.strictEqual(r.json.metric, 'points');
+ assert.ok(Array.isArray(r.json.leaderboard));
+ assert.ok(Array.isArray(r.json.active_challenges));
+});
+
+t('GET /api/marketplace/leaderboard?metric=sales works', async () => {
+ const r = await req('GET', '/api/marketplace/leaderboard?metric=sales');
+ assert.strictEqual(r.status, 200);
+ assert.ok(Array.isArray(r.json.leaderboard));
+});
+
+t('GET /api/marketplace/leaderboard?metric=saves works', async () => {
+ const r = await req('GET', '/api/marketplace/leaderboard?metric=saves');
+ assert.strictEqual(r.status, 200);
+});
+
+t('GET /api/marketplace/leaderboard?metric=collections works', async () => {
+ const r = await req('GET', '/api/marketplace/leaderboard?metric=collections');
+ assert.strictEqual(r.status, 200);
+});
+
+t('GET /api/marketplace/leaderboard?metric=bogus returns 400', async () => {
+ const r = await req('GET', '/api/marketplace/leaderboard?metric=bogus');
+ assert.strictEqual(r.status, 400);
+});
+
+t('GET /api/marketplace/challenges returns array', async () => {
+ const r = await req('GET', '/api/marketplace/challenges');
+ assert.strictEqual(r.status, 200);
+ assert.ok(Array.isArray(r.json.challenges));
+});
+
+t('POST /api/marketplace/admin/challenges rejects without admin token', async () => {
+ const r = await req('POST', '/api/marketplace/admin/challenges', { title: 'x' });
+ assert.strictEqual(r.status, 403);
+});
+
t('Page routes serve HTML (200)', async () => {
- for (const path of ['/marketplace','/designers','/patterns','/marketplace/status','/marketplace/apply','/marketplace/dashboard','/marketplace/admin','/marketplace/claim','/designers/astrid-mauve','/store/astrid-mauve']) {
+ for (const path of ['/marketplace','/designers','/patterns','/marketplace/status','/marketplace/apply','/marketplace/dashboard','/marketplace/admin','/marketplace/claim','/marketplace/leaderboard','/marketplace/challenges','/designers/astrid-mauve','/store/astrid-mauve']) {
const r = await req('GET', path);
assert.strictEqual(r.status, 200, path + ' → ' + r.status);
}
});
+t('GET /sitemap-marketplace.xml returns valid sitemap XML', async () => {
+ const r = await req('GET', '/sitemap-marketplace.xml');
+ assert.strictEqual(r.status, 200);
+ assert.ok(/^<\?xml/.test(r.body), 'expected XML declaration');
+ assert.ok(/<urlset xmlns="http:\/\/www\.sitemaps\.org\/schemas\/sitemap\/0\.9">/.test(r.body));
+ assert.ok(r.body.includes('<loc>https://wallco.ai/marketplace</loc>'));
+ assert.ok(r.body.includes('<loc>https://wallco.ai/designers</loc>'));
+ assert.ok(r.body.includes('<loc>https://wallco.ai/patterns</loc>'));
+});
+
+t('GET /designers/:slug renders SEO meta + Person JSON-LD into <head>', async () => {
+ const r = await req('GET', '/designers/astrid-mauve');
+ assert.strictEqual(r.status, 200);
+ assert.ok(/<link rel="canonical" href="https:\/\/wallco\.ai\/designers\/astrid-mauve"/.test(r.body), 'canonical missing');
+ assert.ok(/<meta property="og:type" content="profile"/.test(r.body), 'og:type missing');
+ assert.ok(/<script type="application\/ld\+json">[\s\S]*?"@type":"Person"/.test(r.body), 'Person JSON-LD missing');
+});
+
+t('GET /patterns/:slug renders Product + CreativeWork JSON-LD', async () => {
+ const r = await req('GET', '/patterns/wildflower-reverie-astrid-mauve');
+ assert.strictEqual(r.status, 200);
+ assert.ok(/<meta property="og:type" content="product"/.test(r.body), 'og:type=product missing');
+ assert.ok(/"@type":"Product"/.test(r.body), 'Product JSON-LD missing');
+ assert.ok(/"@type":"CreativeWork"/.test(r.body), 'CreativeWork JSON-LD missing');
+ assert.ok(/<link rel="canonical" href="https:\/\/wallco\.ai\/patterns\/wildflower-reverie-astrid-mauve"/.test(r.body));
+});
+
(async () => {
let pass = 0, fail = 0;
for (const test of tests) {
← 2ac2375 footer: add visible phone, DW corp address, and © 2026 line
·
back to Wallco Ai
·
marketplace: designer follow + /trade/projects board listing b74ae4b →