Skip to content

Commit

Permalink
❇️ Add components, tests e2e and articles review
Browse files Browse the repository at this point in the history
  • Loading branch information
kdelfour committed Dec 2, 2024
1 parent 8e75442 commit 26137bf
Show file tree
Hide file tree
Showing 22 changed files with 3,309 additions and 387 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npx playwright test
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,7 @@ pnpm-debug.log*

# jetbrains setting folder
.idea/
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
31 changes: 31 additions & 0 deletions astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,35 @@ export default defineConfig({
base: "",
output: "static",
integrations: [mdx(), sitemap(), tailwind(), icon(), pagefind()],
vite: {
build: {
modulePreload: {
polyfill: true,
resolveDependencies: (filename, deps) => {
console.log(filename, deps);
return deps.filter((dep) => !dep.includes("node_modules"));
},
},
rollupOptions: {
output: {
manualChunks: {
vendor: ["react", "react-dom"],
utils: ["lodash", "date-fns"],
home: ["./src/pages/index.astro"],
articles: ["./src/content/articles/*.astro"],
books: ["./src/content/books/*.astro"],
tags: ["./src/content/tags/*.astro"],
about: ["./src/pages/about.astro"],
},
entryFileNames: "entries/[name]-[hash].js",
chunkFileNames: "chunks/[name]-[hash].js",
assetFileNames: "assets/[name]-[hash][extname]",
},
},
},
optimizeDeps: {
include: ["react", "react-dom"],
exclude: ["@astrojs/image"],
},
},
});
120 changes: 120 additions & 0 deletions e2e/performance.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { test, expect } from '@playwright/test';
import lighthouse from 'lighthouse';
import { launch } from 'chrome-launcher';

test.describe('Tests avancés de performance et qualité web', () => {
test('Vérification des temps de chargement critiques', async ({ page }) => {
await page.goto('/');

const performanceEntries = await page.evaluate(() => {
return performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming;
});

expect(performanceEntries.domContentLoadedEventEnd).toBeLessThan(800);
expect(performanceEntries.loadEventEnd).toBeLessThan(1500);
expect(performanceEntries.domInteractive).toBeLessThan(800);
expect(performanceEntries.responseStart).toBeLessThan(400);
});

test('Analyse Lighthouse des performances et de l’accessibilité', async ({ page }) => {
await page.goto('/');

const chrome = await launch({
chromeFlags: ['--headless', '--disable-gpu', '--no-sandbox']
});

try {
const options = {
logLevel: 'info' as 'info',
output: 'json' as 'json',
port: chrome.port,
};

const runnerResult = await lighthouse(page.url(), options);
if (runnerResult) {
const { lhr } = runnerResult;

expect(lhr.categories.performance.score).toBeGreaterThanOrEqual(0.9);
expect(lhr.categories.accessibility.score).toBeGreaterThanOrEqual(0.9);
expect(lhr.categories['best-practices'].score).toBeGreaterThanOrEqual(0.9);
expect(lhr.categories.seo.score).toBeGreaterThanOrEqual(0.9);

expect(lhr.audits['first-contentful-paint'].numericValue).toBeLessThan(2000);
expect(lhr.audits['largest-contentful-paint'].numericValue).toBeLessThan(2500);
expect(lhr.audits['cumulative-layout-shift'].numericValue).toBeLessThan(0.1);
expect(lhr.audits['total-blocking-time'].numericValue).toBeLessThan(300);
} else {
throw new Error("Lighthouse n'a pas retourné de résultat.");
}
} finally {
chrome.kill();
}
});

test('Métriques Web Vitals et interactions utilisateur', async ({ page }) => {
await page.goto('/');

const webVitals = await page.evaluate(() => {
return new Promise((resolve) => {
let cls = 0;
let lcp = 0;
let fid = 0;

new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (entry.entryType === 'layout-shift') {
cls += (entry as any).value;
}
}
}).observe({ type: 'layout-shift', buffered: true });

new PerformanceObserver((entryList) => {
const entries = entryList.getEntries() as PerformanceEventTiming[];
lcp = entries[entries.length - 1].startTime;
}).observe({ type: 'largest-contentful-paint', buffered: true });

new PerformanceObserver((entryList) => {
const entries = entryList.getEntries() as PerformanceEventTiming[];
fid = entries[entries.length - 1].processingStart - entries[entries.length - 1].startTime;
}).observe({ type: 'first-input', buffered: true });

setTimeout(() => {
resolve({ cls, lcp, fid });
}, 3000);
});
});

expect((webVitals as { cls: number; lcp: number; fid: number }).cls).toBeLessThan(0.1);
expect((webVitals as { cls: number; lcp: number; fid: number }).lcp).toBeLessThan(2500);
expect((webVitals as { cls: number; lcp: number; fid: number }).fid).toBeLessThan(100);
});

test('Taille des ressources et types de fichiers', async ({ page }) => {
await page.goto('/');

const resourceSizes = await page.evaluate(() => {
const resources = performance.getEntriesByType('resource') as PerformanceResourceTiming[];
return resources.reduce((acc: { [key: string]: number }, resource) => {
const type = resource.name.split('.').pop() || 'other';
return {
...acc,
[type]: (acc[type] || 0) + resource.encodedBodySize
};
}, {} as { [key: string]: number });
});

expect(resourceSizes['js'] || 0).toBeLessThan(500 * 1024); // 500KB max pour JS
expect(resourceSizes['css'] || 0).toBeLessThan(100 * 1024); // 100KB max pour CSS
expect(resourceSizes['png'] || 0 + resourceSizes['jpg'] || 0).toBeLessThan(1024 * 1024); // 1MB max pour les images
});

test('Logs du navigateur et erreurs JavaScript', async ({ page }) => {
const consoleMessages: string[] = [];
page.on('console', (msg) => consoleMessages.push(msg.text()));

await page.goto('/');

const errors = consoleMessages.filter((msg) => msg.toLowerCase().includes('error'));
expect(errors.length).toBe(0);
});
});
Loading

0 comments on commit 26137bf

Please sign in to comment.