Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 7s
Build & Deploy / 🧪 QA (push) Successful in 2m4s
Build & Deploy / 🏗️ Build (push) Successful in 11m17s
Build & Deploy / 🚀 Deploy (push) Failing after 8s
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s
105 lines
2.9 KiB
TypeScript
105 lines
2.9 KiB
TypeScript
const BASE_URL = process.env.TEST_URL || "http://localhost:3000";
|
|
|
|
console.log(`\n🚀 Starting Dynamic OG Image Verification for ${BASE_URL}\n`);
|
|
|
|
const pages = ["/", "/about", "/contact"];
|
|
|
|
async function getOgImageUrl(pagePath: string): Promise<string | null> {
|
|
const url = `${BASE_URL}${pagePath}`;
|
|
try {
|
|
const response = await fetch(url);
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to fetch page: ${response.status}`);
|
|
}
|
|
const html = await response.text();
|
|
|
|
// Extract og:image content
|
|
const match = html.match(/property="og:image"\s+content="([^"]+)"/);
|
|
if (!match || !match[1]) {
|
|
// Try name="twitter:image" as fallback or check if it's there
|
|
const twitterMatch = html.match(
|
|
/name="twitter:image"\s+content="([^"]+)"/,
|
|
);
|
|
return twitterMatch ? twitterMatch[1] : null;
|
|
}
|
|
return match[1];
|
|
} catch (error) {
|
|
console.error(` ❌ Failed to discover OG image for ${pagePath}:`, error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async function verifyImage(
|
|
imageUrl: string,
|
|
pagePath: string,
|
|
): Promise<boolean> {
|
|
// If the image URL is absolute and contains mintel.me (base domain),
|
|
// we replace it with our BASE_URL to test the current environment's generated image
|
|
let testUrl = imageUrl;
|
|
if (imageUrl.startsWith("https://mintel.me")) {
|
|
testUrl = imageUrl.replace("https://mintel.me", BASE_URL);
|
|
} else if (imageUrl.startsWith("/")) {
|
|
testUrl = `${BASE_URL}${imageUrl}`;
|
|
}
|
|
|
|
const start = Date.now();
|
|
try {
|
|
const response = await fetch(testUrl);
|
|
const duration = Date.now() - start;
|
|
|
|
console.log(`Checking OG Image for ${pagePath}: ${testUrl}...`);
|
|
|
|
const body = await response.clone().text();
|
|
const contentType = response.headers.get("content-type");
|
|
|
|
if (response.status !== 200) {
|
|
throw new Error(`Status: ${response.status}`);
|
|
}
|
|
|
|
if (!contentType?.includes("image/")) {
|
|
throw new Error(`Content-Type: ${contentType}`);
|
|
}
|
|
|
|
const buffer = await response.arrayBuffer();
|
|
const bytes = new Uint8Array(buffer);
|
|
|
|
if (bytes.length < 1000) {
|
|
throw new Error(`Image too small (${bytes.length} bytes)`);
|
|
}
|
|
|
|
console.log(` ✅ OK (${bytes.length} bytes, ${duration}ms)`);
|
|
return true;
|
|
} catch (error: unknown) {
|
|
console.error(` ❌ FAILED:`, error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
async function run() {
|
|
let allOk = true;
|
|
|
|
for (const page of pages) {
|
|
console.log(`Discovering OG image for ${page}...`);
|
|
const ogUrl = await getOgImageUrl(page);
|
|
|
|
if (!ogUrl) {
|
|
console.error(` ❌ No OG image meta tag found for ${page}`);
|
|
allOk = false;
|
|
continue;
|
|
}
|
|
|
|
const ok = await verifyImage(ogUrl, page);
|
|
if (!ok) allOk = false;
|
|
}
|
|
|
|
if (allOk) {
|
|
console.log("\n✨ All OG images verified successfully!\n");
|
|
process.exit(0);
|
|
} else {
|
|
console.error("\n❌ Some OG images failed verification.\n");
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
run();
|