From 4ccf4b824228e948c6c5e02e8f349d1aa1e80283 Mon Sep 17 00:00:00 2001 From: arsam Date: Fri, 18 Sep 2026 23:23:44 +0330 Subject: [PATCH] Import source: app/scripts/production-smoke.mjs Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality. --- app/scripts/production-smoke.mjs | 50 ++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 app/scripts/production-smoke.mjs diff --git a/app/scripts/production-smoke.mjs b/app/scripts/production-smoke.mjs new file mode 100644 index 0000000..2b21cca --- /dev/null +++ b/app/scripts/production-smoke.mjs @@ -0,0 +1,50 @@ +const SITE_URL = (process.env.TEKNAV_SMOKE_URL || process.env.TEKNAV_SITE_URL || 'https://www.teknav.ir').replace(/\/$/, ''); +const ARTICLE_PATHS = (process.env.TEKNAV_SMOKE_ARTICLES || '/article/agentic-ai-production,/article/ai-clean-data') + .split(',') + .map((item) => item.trim()) + .filter(Boolean); + +async function request(path) { + const url = `${SITE_URL}${path}`; + const res = await fetch(url, { redirect: 'manual' }); + const body = await res.text().catch(() => ''); + return { url, status: res.status, headers: res.headers, body }; +} + +function pass(label, detail = '') { + console.log(`PASS ${label}${detail ? ` - ${detail}` : ''}`); +} + +function fail(label, detail = '') { + throw new Error(`FAIL ${label}${detail ? ` - ${detail}` : ''}`); +} + +async function expectOk(path, label) { + const res = await request(path); + if (res.status < 200 || res.status >= 300) fail(label, `${res.url} returned ${res.status}`); + pass(label, `${res.status}`); + return res; +} + +await expectOk('/api/v1/health', 'backend health'); +await expectOk('/sitemap.xml', 'sitemap available'); +await expectOk('/robots.txt', 'robots available'); +await expectOk('/feed.xml', 'rss feed available'); +await expectOk('/feeds/topic-ai.xml', 'topic rss feed available'); +await expectOk('/newsletter', 'newsletter archive available'); +await expectOk('/tag/AI', 'tag page available'); + +const blocked = await request('/ACCOUNTS.md'); +if (![403, 404].includes(blocked.status)) fail('ACCOUNTS.md blocked', `${blocked.url} returned ${blocked.status}`); +pass('ACCOUNTS.md blocked', `${blocked.status}`); + +for (const path of ARTICLE_PATHS) { + const res = await expectOk(path, `article page ${path}`); + const canonical = `${SITE_URL}${path}`; + if (!res.body.includes('rel="canonical"') && !res.body.includes(canonical)) { + fail(`canonical present ${path}`, 'canonical link or URL was not found in HTML'); + } + pass(`canonical present ${path}`); +} + +console.log(`Production smoke checks completed for ${SITE_URL}`);