Skip to content

Commit e97ef51

Browse files
darth-cassantegioz
andauthored
Add end to end tests (#306)
Signed-off-by: Daniel Castaño Sánchez <[email protected]> Signed-off-by: Sergio Castaño Arteaga <[email protected]> Co-authored-by: Sergio Castaño Arteaga <[email protected]>
1 parent c44dbbd commit e97ef51

File tree

4 files changed

+144
-0
lines changed

4 files changed

+144
-0
lines changed

.github/workflows/e2e.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: End-to-end tests
2+
on:
3+
pull_request:
4+
branches:
5+
- main
6+
schedule:
7+
- cron: '0 */2 * * *'
8+
workflow_dispatch:
9+
10+
jobs:
11+
e2e-tests:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v5
15+
- uses: actions/setup-node@v4
16+
- name: Install Playwright
17+
run: npm i -D @playwright/test
18+
- name: Install Playwright browsers
19+
run: npx playwright install --with-deps
20+
- name: Run Playwright tests
21+
run: npx playwright test --config tests/e2e/playwright.config.ts

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ Chart.lock
55
chart/charts
66
gitjobs-server/dist
77
gitjobs-server/static/css/styles.css
8+
node_modules
9+
package-lock.json
10+
package.json
11+
test-results

tests/e2e/playwright.config.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { defineConfig, devices } from '@playwright/test';
2+
3+
export default defineConfig({
4+
testDir: '.',
5+
use: {
6+
baseURL: process.env.CI ? 'https://gitjobs.dev' : 'http://localhost:9000',
7+
},
8+
reporter: 'list',
9+
projects: [
10+
{
11+
name: 'chromium',
12+
use: { ...devices['Desktop Chrome'] },
13+
},
14+
{
15+
name: 'firefox',
16+
use: { ...devices['Desktop Firefox'] },
17+
},
18+
{
19+
name: 'webkit',
20+
use: { ...devices['Desktop Safari'] },
21+
},
22+
],
23+
});

tests/e2e/playwright.spec.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import { test, expect } from '@playwright/test';
2+
3+
test.describe('GitJobs', () => {
4+
test.beforeEach(async ({ page }) => {
5+
await page.goto('/');
6+
// Handle cookie consent
7+
try {
8+
await page.getByRole('button', { name: 'Accept all' }).click({ timeout: 5000 });
9+
} catch (error) {
10+
// Ignore if the cookie consent is not visible
11+
}
12+
});
13+
14+
test('should have the correct title and heading', async ({ page }) => {
15+
await expect(page).toHaveTitle(/GitJobs/);
16+
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
17+
});
18+
19+
test('should apply a filter and verify that the results are updated', async ({ page }) => {
20+
await page.locator('div:nth-child(4) > div > .font-semibold').first().click();
21+
await page.locator('label').filter({ hasText: 'Full Time' }).nth(1).click();
22+
23+
const jobCards = await page.getByRole('button', { name: /Job type/ }).all();
24+
for (const jobCard of jobCards) {
25+
await expect(jobCard.locator('.capitalize').first()).toHaveText('full time');
26+
}
27+
});
28+
29+
test('should reset filters', async ({ page }) => {
30+
const initialJobCount = await page.getByRole('button', { name: /Job type/ }).count();
31+
await page.locator('label').filter({ hasText: 'Full Time' }).nth(1).click();
32+
await page.locator('#reset-desktop-filters').click();
33+
const newJobCount = await page.getByRole('button', { name: /Job type/ }).count();
34+
expect(newJobCount).toEqual(initialJobCount);
35+
});
36+
37+
test('should sort jobs', async ({ page }) => {
38+
await page.locator('#sort-desktop').selectOption('open-source');
39+
await expect(page).toHaveURL(/\?sort=open-source/);
40+
});
41+
42+
test('should navigate to the stats page and interact with charts', async ({ page, browserName }) => {
43+
if (browserName === 'firefox') {
44+
// Skip this test on Firefox as it's failing due to a rendering issue with the charts
45+
return;
46+
}
47+
await page.getByRole('link', { name: 'Stats' }).click();
48+
await expect(page).toHaveURL(/\/stats/);
49+
await page.waitForSelector('#line-chart rect', { timeout: 10000 });
50+
await page.locator('#line-chart rect').first().click({ force: true });
51+
await page.waitForSelector('#bar-daily rect', { timeout: 10000 });
52+
await page.locator('#bar-daily rect').first().click({ force: true });
53+
});
54+
55+
test('should navigate to the about page and check for a body', async ({ page }) => {
56+
await page.getByRole('link', { name: 'About' }).click();
57+
await expect(page).toHaveURL(/\/about/);
58+
await expect(page.locator('body')).toBeVisible();
59+
});
60+
61+
test('should navigate to the sign-up page', async ({ page }) => {
62+
await page.locator('#user-dropdown-button').click();
63+
await page.getByRole('link', { name: 'Sign up' }).click();
64+
await expect(page).toHaveURL(/\/sign-up/);
65+
});
66+
67+
test('should allow viewing a job posting', async ({ page }) => {
68+
await page.getByRole('button', { name: /Job type/ }).first().click();
69+
await expect(page).toHaveURL(/\?job_id=/);
70+
await expect(page.locator('#job-view').getByRole('heading')).toBeVisible();
71+
});
72+
73+
test('should display job details correctly', async ({ page }) => {
74+
await page.getByRole('button', { name: /Job type/ }).first().click();
75+
await expect(page.locator('#job-view').getByRole('heading')).toBeVisible();
76+
await expect(page.locator('#preview-content').getByText(/Job description/)).toBeVisible();
77+
await expect(page.getByRole('button', { name: 'Apply' })).toBeEnabled();
78+
await expect(page.locator('#preview-content').getByText(/Published/)).toBeVisible();
79+
await expect(page.locator('#preview-content').getByText(/Job type/)).toBeVisible();
80+
await expect(page.locator('#preview-content').getByText(/Workplace/)).toBeVisible();
81+
await expect(page.locator('#preview-content').getByText(/Seniority level/)).toBeVisible();
82+
await expect(page.getByText('Share this job')).toBeVisible();
83+
});
84+
85+
test('should allow paginating through jobs', async ({ page }) => {
86+
const paginationVisible = await page.locator('[aria-label="pagination"]').isVisible();
87+
if (!paginationVisible) {
88+
console.log('Pagination not visible, skipping test.');
89+
return;
90+
}
91+
const initialPageNumber = await page.locator('[aria-current="page"]').textContent();
92+
await page.getByLabel(/Go to page/).last().click();
93+
const newPageNumber = await page.locator('[aria-current="page"]').textContent();
94+
expect(newPageNumber).not.toBe(initialPageNumber);
95+
});
96+
});

0 commit comments

Comments
 (0)