Files
CompanySite/tests/blog.spec.ts
T
Clintchiz d402256547
Deploy to Production / Build & Verify (push) Failing after 5m56s
Ping Search Engines / Notify Search Engines (push) Successful in 2s
Deploy to Production / Pre-Deploy Tests (push) Has been skipped
Deploy to Production / Deploy to Railway (push) Has been skipped
Deploy to Production / Deploy to Render (push) Has been skipped
Deploy to Production / Deploy to VPS (PM2) (push) Has been skipped
Deploy to Production / Deploy to Fly.io (push) Has been skipped
Deploy to Production / Post-Deploy Verification (push) Has been skipped
Deploy to Production / Notify on Failure (push) Successful in 2s
E2E Test Suite / Critical User Journeys (push) Has been skipped
E2E Test Suite / API Integration Tests (push) Has been skipped
E2E Test Suite / Smoke Tests (P0) (push) Failing after 11m26s
E2E Test Suite / Form Interaction Tests (push) Failing after 11m42s
E2E Test Suite / Destructive & Chaos Tests (push) Failing after 12m2s
E2E Test Suite / Cross-Browser Regression (chromium) (push) Failing after 16m14s
E2E Test Suite / Cross-Browser Regression (webkit) (push) Failing after 17m45s
E2E Test Suite / Cross-Browser Regression (firefox) (push) Failing after 25m23s
E2E Test Suite / Security Header Tests (push) Failing after 7m55s
E2E Test Suite / Test Report Summary (push) Failing after 20s
E2E Test Suite / Mobile Device Tests (push) Failing after 2h49m9s
Uptime Monitor / Health & Response Time (push) Failing after 2s
Uptime Monitor / SSL Certificate (push) Successful in 2s
Uptime Monitor / Send Alerts (push) Failing after 3s
Uptime Monitor / Record Uptime Success (push) Has been skipped
First Init
2026-03-21 16:46:46 +05:30

181 lines
6.2 KiB
TypeScript

import { test, expect } from '@playwright/test';
test.describe('Blog Listing Tests', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/blog');
});
test('blog page displays posts', async ({ page }) => {
// Look for blog post cards/articles
const posts = page.locator('article, [class*="post"], [class*="card"], [class*="blog"]').filter({ hasText: /./ });
const count = await posts.count();
expect(count).toBeGreaterThan(0);
});
test('blog posts have required elements', async ({ page }) => {
const firstPost = page.locator('article, [class*="post"], [class*="card"]').first();
if (await firstPost.isVisible()) {
// Check for title
const title = firstPost.locator('h1, h2, h3, [class*="title"]');
await expect(title).toBeVisible();
// Check for date or metadata
const hasMeta = await firstPost.locator('time, [class*="date"], [class*="meta"]').count() > 0;
expect(hasMeta).toBeTruthy();
}
});
test('blog posts link to detail pages', async ({ page }) => {
const postLink = page.locator('article a, [class*="post"] a, [class*="card"] a').first();
if (await postLink.isVisible()) {
const href = await postLink.getAttribute('href');
expect(href).toContain('/blog/');
}
});
test('clicking blog post navigates to detail', async ({ page }) => {
const postLink = page.locator('article a, [class*="post"] a, [class*="card"] a').first();
if (await postLink.isVisible()) {
await postLink.click();
await expect(page).toHaveURL(/\/blog\//);
}
});
});
test.describe('Blog Post Detail Tests', () => {
test('blog post page renders markdown content', async ({ page }) => {
// Navigate directly to a known blog post
await page.goto('/blog/getting-started-with-astro');
// Check for article content
const article = page.locator('article, main, [class*="content"], [class*="prose"]').first();
await expect(article).toBeVisible();
// Check for heading
const heading = page.locator('h1');
await expect(heading).toBeVisible();
// Check for paragraphs (markdown content)
const paragraphs = page.locator('p');
const pCount = await paragraphs.count();
expect(pCount).toBeGreaterThan(0);
});
test('blog post has proper typography', async ({ page }) => {
// Navigate directly to a known blog post
await page.goto('/blog/getting-started-with-astro');
// Check for prose or typography classes
const proseContent = page.locator('[class*="prose"], [class*="typography"], article').first();
await expect(proseContent).toBeVisible();
// Check text is readable (not too small)
const paragraph = page.locator('p').first();
if (await paragraph.isVisible()) {
const fontSize = await paragraph.evaluate((el) => {
return parseFloat(window.getComputedStyle(el).fontSize);
});
expect(fontSize).toBeGreaterThanOrEqual(14); // Minimum readable size
}
});
test('code blocks render correctly', async ({ page }) => {
// Navigate directly to a known blog post that should have code blocks
await page.goto('/blog/getting-started-with-astro');
// Check for code blocks (if present in the post)
const codeBlocks = page.locator('pre, code, [class*="shiki"], [class*="highlight"]');
const codeCount = await codeBlocks.count();
if (codeCount > 0) {
// Code blocks should have monospace font
const fontFamily = await codeBlocks.first().evaluate((el) => {
return window.getComputedStyle(el).fontFamily;
});
expect(fontFamily.toLowerCase()).toMatch(/mono|consolas|courier|ui-monospace/);
}
});
test('blog post images load', async ({ page }) => {
// Navigate directly to a known blog post
await page.goto('/blog/getting-started-with-astro');
// Wait for page to fully load
await page.waitForLoadState('networkidle');
// Check for any visible images on the blog post page
const images = page.locator('img');
const imgCount = await images.count();
// Check at least some images exist
expect(imgCount).toBeGreaterThan(0);
// Verify first visible image loads correctly
for (let i = 0; i < Math.min(imgCount, 3); i++) {
const img = images.nth(i);
const isVisible = await img.isVisible();
if (isVisible) {
// Wait for image to complete loading
await img.evaluate((el: HTMLImageElement) => {
return new Promise((resolve) => {
if (el.complete) {
resolve(true);
} else {
el.onload = () => resolve(true);
el.onerror = () => resolve(false);
}
});
});
break; // Found at least one visible image
}
}
});
});
test.describe('Blog Category Tests', () => {
test('posts show category badges', async ({ page }) => {
await page.goto('/blog');
const categoryBadges = page.locator('[class*="category"], [class*="tag"], [class*="badge"]');
const badgeCount = await categoryBadges.count();
// Categories should be displayed
expect(badgeCount).toBeGreaterThanOrEqual(0);
});
});
test.describe('Blog Responsive Tests', () => {
test('blog listing adapts to mobile', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 667 });
await page.goto('/blog');
// Posts should stack on mobile
const posts = page.locator('article, [class*="post"], [class*="card"]');
await expect(posts.first()).toBeVisible();
// No horizontal scroll
const bodyWidth = await page.evaluate(() => document.body.scrollWidth);
expect(bodyWidth).toBeLessThanOrEqual(395);
});
test('blog post detail is readable on mobile', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 667 });
// Navigate directly to a known blog post
await page.goto('/blog/getting-started-with-astro');
// Content should not overflow (small tolerance for scrollbar)
const bodyWidth = await page.evaluate(() => document.body.scrollWidth);
expect(bodyWidth).toBeLessThanOrEqual(400);
// Text should be readable
const content = page.locator('article, [class*="prose"], [class*="content"]').first();
await expect(content).toBeVisible();
});
});