import { test, expect } from '@playwright/test'; test.describe('Static Assets and Links Verification', () => { test.beforeEach(async ({ page }) => { // Navigate to homepage before each test await page.goto('/'); }); test('should load favicon correctly', async ({ page }) => { const favicon = page.locator('link[rel="icon"]'); await expect(favicon).toHaveAttribute('href', '/favicon.svg'); // Verify favicon actually exists and loads const response = await page.goto('/favicon.svg'); expect(response?.status()).toBe(200); }); test('should reference correct domain in canonical URLs', async ({ page }) => { const canonical = page.locator('link[rel="canonical"]'); const canonicalHref = await canonical.getAttribute('href'); // In production, should use workroot.in; in dev mode, may use localhost if (canonicalHref?.includes('workroot')) { expect(canonicalHref).toContain('workroot.in'); expect(canonicalHref).not.toContain('workroot.com'); } // Should have a canonical URL expect(canonicalHref).toBeTruthy(); }); test('should use correct domain in Open Graph tags', async ({ page }) => { const ogUrl = page.locator('meta[property="og:url"]'); const ogUrlContent = await ogUrl.getAttribute('content'); // In production, should use workroot.in; never use workroot.com if (ogUrlContent?.includes('workroot')) { expect(ogUrlContent).toContain('workroot.in'); expect(ogUrlContent).not.toContain('workroot.com'); } const ogImage = page.locator('meta[property="og:image"]'); const ogImageContent = await ogImage.getAttribute('content'); if (ogImageContent?.includes('workroot')) { expect(ogImageContent).toContain('workroot.in'); expect(ogImageContent).not.toContain('workroot.com'); } }); test('should have all internal navigation links working', async ({ page }) => { // Check main navigation links const navLinks = [ { href: '/', text: 'Home' }, { href: '/about', text: 'About' }, { href: '/services', text: 'Services' }, { href: '/portfolio', text: 'Portfolio' }, { href: '/blog', text: 'Blog' }, { href: '/contact', text: 'Contact' }, ]; for (const link of navLinks) { const element = page.locator(`a[href="${link.href}"]`).first(); await expect(element).toBeVisible(); } }); test('should load external resources from whitelisted domains only', async ({ page }) => { // Wait for page to fully load await page.waitForLoadState('networkidle'); // Check CSP headers allow only whitelisted external domains const response = await page.goto('/'); const cspHeader = response?.headers()['content-security-policy']; expect(cspHeader).toBeDefined(); expect(cspHeader).toContain('https://fonts.googleapis.com'); expect(cspHeader).toContain('https://fonts.gstatic.com'); expect(cspHeader).toContain('https://images.unsplash.com'); }); test('should have working footer links', async ({ page }) => { const footerLinks = [ '/privacy', '/terms', '/cookies', ]; for (const href of footerLinks) { const link = page.locator(`a[href="${href}"]`).first(); await expect(link).toBeVisible(); } }); test('should load blog images correctly', async ({ page }) => { await page.goto('/blog'); // Check if blog post images load const blogImages = page.locator('img[src*="/images/blog/"]'); const count = await blogImages.count(); if (count > 0) { for (let i = 0; i < count; i++) { const img = blogImages.nth(i); await expect(img).toBeVisible(); } } }); test('should not have any broken internal links on homepage', async ({ page }) => { const links = await page.locator('a[href^="/"]').all(); const brokenLinks: string[] = []; const checkedLinks = new Set(); // Known pages that are placeholders (not yet implemented) const knownMissingPages = [ '/cookies', '/services/web-development', '/services/mobile-apps', '/services/cloud-solutions', '/services/it-consulting', '/services/cybersecurity', '/services/devops', ]; for (const link of links) { const href = await link.getAttribute('href'); if (href && !href.includes('#') && !checkedLinks.has(href) && !knownMissingPages.includes(href)) { checkedLinks.add(href); const response = await page.goto(href); const status = response?.status(); // 200 OK or 304 Not Modified are acceptable if (status !== 200 && status !== 304) { brokenLinks.push(`${href} (${status})`); } // Go back to homepage for next iteration await page.goto('/'); } } // Log broken links for debugging if (brokenLinks.length > 0) { console.log('Unexpected broken links found:', brokenLinks); } expect(brokenLinks).toHaveLength(0); }); test('should reference workroot.in in sitemap', async ({ page }) => { const response = await page.goto('/sitemap.xml'); expect(response?.status()).toBe(200); const content = await page.content(); expect(content).toContain('https://workroot.in'); expect(content).not.toContain('https://workroot.com'); }); test('should reference workroot.in in robots.txt', async ({ page }) => { const response = await page.goto('/robots.txt'); expect(response?.status()).toBe(200); const content = await page.content(); expect(content).toContain('workroot.in'); expect(content).not.toContain('workroot.com'); }); test('should have correct schema.org structured data', async ({ page }) => { const jsonLdScripts = page.locator('script[type="application/ld+json"]'); const count = await jsonLdScripts.count(); expect(count).toBeGreaterThan(0); for (let i = 0; i < count; i++) { const scriptContent = await jsonLdScripts.nth(i).textContent(); if (scriptContent) { const data = JSON.parse(scriptContent); // Check for workroot.in references const jsonString = JSON.stringify(data); expect(jsonString).not.toContain('workroot.com'); // If it contains workroot domain, it should be workroot.in if (jsonString.includes('workroot')) { expect(jsonString).toContain('workroot.in'); } } } }); test('should have API health endpoint working', async ({ page }) => { const response = await page.goto('/api/health.json'); expect(response?.status()).toBe(200); const data = await response?.json(); expect(data).toHaveProperty('status', 'ok'); }); test('should preconnect to external domains for performance', async ({ page }) => { const preconnects = [ 'https://fonts.googleapis.com', 'https://fonts.gstatic.com', 'https://images.unsplash.com', ]; for (const href of preconnects) { const link = page.locator(`link[rel="preconnect"][href="${href}"], link[rel="dns-prefetch"][href="${href}"]`); // Should have at least one preconnect or dns-prefetch link await expect(link).toHaveCount(await link.count()); expect(await link.count()).toBeGreaterThanOrEqual(1); } }); test('should load apple-touch-icon correctly', async ({ page }) => { const response = await page.goto('/apple-touch-icon.png'); expect(response?.status()).toBe(200); }); test('should load og-image.jpg correctly', async ({ page }) => { const response = await page.goto('/og-image.jpg'); expect(response?.status()).toBe(200); }); test('should load logo.png correctly', async ({ page }) => { const response = await page.goto('/logo.png'); expect(response?.status()).toBe(200); }); test('should verify blog image assets exist on server', async ({ page }) => { const blogImages = [ '/images/blog/ai-business.jpg', '/images/blog/astro-intro.jpg', '/images/blog/cloud-migration.jpg', ]; for (const imgPath of blogImages) { const response = await page.goto(imgPath); expect(response?.status(), `Blog image should load: ${imgPath}`).toBe(200); } }); test('should have correct domain in twitter:domain meta tag', async ({ page }) => { const twitterDomain = page.locator('meta[name="twitter:domain"]'); const content = await twitterDomain.getAttribute('content'); expect(content).toBe('workroot.in'); }); test('should not have workroot.com referenced anywhere on homepage', async ({ page }) => { const content = await page.content(); expect(content).not.toContain('workroot.com'); }); test('should have correct domain in all pages meta tags', async ({ page }) => { const pagesToCheck = ['/', '/about', '/services', '/portfolio', '/blog', '/contact']; for (const pagePath of pagesToCheck) { await page.goto(pagePath); const content = await page.content(); expect(content, `Page ${pagePath} should not reference workroot.com`).not.toContain('workroot.com'); } }); });