Files
CompanySite/tests/security-headers.test.ts
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

156 lines
5.1 KiB
TypeScript

/**
* Security Headers Test
* Tests that security headers are properly applied to responses
*/
import { expect, test } from '@playwright/test';
test.describe('Security Headers', () => {
test('should return security headers on homepage', async ({ page }) => {
const response = await page.goto('/');
expect(response).not.toBeNull();
const headers = response!.headers();
// Test CSP header
expect(headers['content-security-policy']).toBeDefined();
expect(headers['content-security-policy']).toContain("default-src 'self'");
expect(headers['content-security-policy']).toContain('frame-ancestors \'none\'');
// Test X-Frame-Options
expect(headers['x-frame-options']).toBe('DENY');
// Test X-Content-Type-Options
expect(headers['x-content-type-options']).toBe('nosniff');
// Test Referrer-Policy
expect(headers['referrer-policy']).toBe('strict-origin-when-cross-origin');
// Test Permissions-Policy
expect(headers['permissions-policy']).toBeDefined();
expect(headers['permissions-policy']).toContain('geolocation=()');
});
test('should return CORS headers on API endpoint', async ({ request }) => {
const response = await request.get('/api/health.json');
expect(response.ok()).toBeTruthy();
const headers = response.headers();
// Test CORS headers
expect(headers['access-control-allow-origin']).toBe('https://workroot.in');
expect(headers['access-control-allow-methods']).toBe('GET');
// Test content type
expect(headers['content-type']).toBe('application/json');
// Test cache control
expect(headers['cache-control']).toBe('no-cache, no-store, must-revalidate');
// Verify response body contains correct domain
const body = await response.json();
expect(body.domain).toBe('workroot.in');
});
test('should apply security headers to all pages', async ({ page }) => {
const pages = ['/', '/about', '/services', '/portfolio', '/contact', '/blog'];
for (const pagePath of pages) {
const response = await page.goto(pagePath);
const headers = response!.headers();
expect(headers['x-frame-options']).toBe('DENY');
expect(headers['x-content-type-options']).toBe('nosniff');
expect(headers['content-security-policy']).toBeDefined();
}
});
});
test.describe('Domain Security', () => {
test('should include workroot.in in structured data', async ({ page }) => {
await page.goto('/');
// Check JSON-LD schema includes correct domain
const schemaScripts = await page.locator('script[type="application/ld+json"]').all();
expect(schemaScripts.length).toBeGreaterThan(0);
for (const script of schemaScripts) {
const content = await script.textContent();
if (content && content.includes('workroot')) {
expect(content).toContain('workroot.in');
expect(content).not.toContain('workroot.com');
}
}
});
test('should have canonical URL with workroot.in', async ({ page }) => {
await page.goto('/');
const canonical = page.locator('link[rel="canonical"]');
const href = await canonical.getAttribute('href');
expect(href).toContain('workroot.in');
expect(href).not.toContain('workroot.com');
});
test('should have correct domain in Open Graph tags', async ({ page }) => {
await page.goto('/');
const ogUrl = page.locator('meta[property="og:url"]');
const content = await ogUrl.getAttribute('content');
expect(content).toContain('workroot.in');
expect(content).not.toContain('workroot.com');
});
});
test.describe('External Resources', () => {
test('should only load resources from whitelisted domains', async ({ page }) => {
// Track all requests
const requests: string[] = [];
page.on('request', (request) => {
requests.push(request.url());
});
await page.goto('/');
await page.waitForLoadState('networkidle');
// Check that external resources are from allowed domains only
const externalRequests = requests.filter(url =>
!url.startsWith('http://localhost') &&
!url.startsWith('http://127.0.0.1') &&
!url.startsWith('http://0.0.0.0')
);
const allowedDomains = [
'workroot.in',
'images.unsplash.com',
'fonts.googleapis.com',
'fonts.gstatic.com',
];
for (const requestUrl of externalRequests) {
const url = new URL(requestUrl);
const isAllowed = allowedDomains.some(domain => url.hostname.includes(domain));
expect(isAllowed).toBeTruthy();
}
});
test('should use crossorigin for external resources', async ({ page }) => {
await page.goto('/');
// Check preconnect links have crossorigin attribute
const preconnects = page.locator('link[rel="preconnect"]');
const count = await preconnects.count();
for (let i = 0; i < count; i++) {
const href = await preconnects.nth(i).getAttribute('href');
if (href && !href.startsWith('/')) {
// External resource should have crossorigin
const crossorigin = await preconnects.nth(i).getAttribute('crossorigin');
expect(crossorigin).toBeDefined();
}
}
});
});