Skip to content

Commit 51b70e1

Browse files
committed
e2e : Add general assertions and snapshot tests
1 parent 063458b commit 51b70e1

34 files changed

Lines changed: 191 additions & 24 deletions

playwright.config.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ export default defineConfig({
7171
],
7272

7373
/* Run your local dev server before starting the tests */
74-
// webServer: {
75-
// command: 'npm run start',
76-
// url: 'http://localhost:3000',
77-
// reuseExistingServer: !process.env.CI,
78-
// },
74+
webServer: {
75+
command: 'npm run dev',
76+
url: 'http://localhost:5173',
77+
reuseExistingServer: !process.env.CI,
78+
},
7979
});

src/components/Plan.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ function updateNodeSize(node: Node, size: [number, number]) {
502502
</li>
503503
</ul>
504504
<div class="ms-auto me-2 small">
505-
<a href="https://github.com/dalibo/pev2" target="_blank">
505+
<a href="https://github.com/dalibo/pev2" target="_blank" data-testid="version">
506506
<LogoImage />
507507
{{ version }}
508508
</a>

tests/e2e/example.spec.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.

tests/e2e/plan.spec.ts

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
import { test, expect } from '@playwright/test';
2+
3+
test.beforeEach(async ({ page }) => {
4+
await page.goto('http://localhost:5173/');
5+
await page.getByRole('button', { name: 'Sample Plans' }).click();
6+
await page.getByRole('link', { name: 'Simple join (JSON format)' }).click();
7+
await page.getByRole('button', { name: 'Submit' }).click();
8+
});
9+
10+
test('verify plan has title', async ({ page }) => {
11+
await expect(page.getByText('Simple join (JSON format)')).toBeVisible();
12+
});
13+
14+
test('redirects to home when clicking on New Plan link', async ({ page }) => {
15+
await page.getByText('New Plan').click();
16+
await expect(page).toHaveURL('http://localhost:5173/');
17+
});
18+
19+
test('redirects to home when clicking pev2 logo', async ({ page }) => {
20+
await page.getByText('New Plan').click();
21+
await expect(page).toHaveURL('http://localhost:5173/');
22+
});
23+
24+
test('switches to dark mode', async ({ page }) => {
25+
await page.getByTitle('Switch to dark mode').click();
26+
await expect(page).toHaveScreenshot('plan_darkMode.png');
27+
});
28+
29+
test('redirects to About page', async ({ page }) => {
30+
await page.getByText('About').click();
31+
await expect(page.getByText('Disclaimer')).toBeVisible();
32+
});
33+
34+
test('opens pev2 GitHub link in a new tab', async ({ page }) => {
35+
const popupPromise = page.waitForEvent('popup');
36+
await page.getByTestId('version').click();
37+
const popup = await popupPromise;
38+
39+
await expect(popup).toHaveURL('https://github.com/dalibo/pev2');
40+
});
41+
42+
test.describe('node', () => {
43+
test('node box toggle shows and hides tabs', async ({ page }) => {
44+
const node = page.locator('.plan-node', { hasText: 'Nested Loop' });
45+
46+
const toggle = node.getByRole('heading', { name: 'Nested Loop' })
47+
const tabs = node.locator('li.nav-item a');
48+
49+
//open
50+
await toggle.click();
51+
await expect(node).toHaveClass(/detailed/);
52+
await expect(tabs).toContainText([
53+
'General',
54+
'IO & Buffers',
55+
'Output',
56+
'Workers',
57+
'Misc',
58+
]);
59+
await expect(node.getByRole('link', { name: 'General' })).toHaveClass(/active/);
60+
await expect(node.getByRole('link', { name: 'IO & Buffers' })).toHaveClass(/disabled/);
61+
62+
//close
63+
await toggle.click();
64+
await expect(node).not.toHaveClass('detailed');
65+
});
66+
});
67+
68+
test.describe('plan style', () => {
69+
let rightPanel;
70+
71+
test.beforeEach(async ({ page }) => {
72+
rightPanel = page.locator('.splitpanes__pane.plan');
73+
});
74+
75+
76+
test('displays plan', async ({ page }) => {
77+
const noneButton = rightPanel.getByRole('button', { name: 'none' });
78+
79+
await expect(noneButton).toHaveClass(/active/)
80+
await expect(page).toHaveScreenshot('plan_none.png');
81+
});
82+
83+
test('displays plan with duration', async ({ page }) => {
84+
const durationButton = rightPanel.getByRole('button', { name: 'duration' });
85+
await durationButton.click()
86+
87+
await expect(durationButton).toHaveClass(/active/)
88+
await expect(page).toHaveScreenshot('plan_duration.png');
89+
});
90+
91+
test('displays plan with rows', async ({ page }) => {
92+
const rowsButton = rightPanel.getByRole('button', { name: 'rows' });
93+
await rowsButton.click()
94+
95+
await expect(rowsButton).toHaveClass(/active/)
96+
await expect(page).toHaveScreenshot('plan_rows.png');
97+
});
98+
99+
test('displays plan with cost', async ({ page }) => {
100+
const costButton = rightPanel.getByRole('button', { name: 'duration' });
101+
await costButton.click()
102+
103+
await expect(costButton).toHaveClass(/active/)
104+
await expect(page).toHaveScreenshot('plan_cost.png');
105+
});
106+
});
107+
108+
test.describe('diagram view', () => {
109+
let leftPanel;
110+
111+
test.beforeEach(async ({ page }) => {
112+
leftPanel = page.locator('.diagram');
113+
});
114+
115+
test('selects node', async ({ page }) => {
116+
const row = leftPanel.getByRole('row', { name: /Nested Loop/ })
117+
const node = page.locator('.plan-node', { hasText: 'Nested Loop' });
118+
await row.click();
119+
120+
await expect(row).toHaveClass(/selected/)
121+
await expect(node).toHaveClass(/detailed/)
122+
await expect(node).toHaveClass(/selected/);
123+
await expect(page).toHaveScreenshot('plan_none.png');
124+
});
125+
126+
test('selects buffers button in diagram option', async ({ page }) => {
127+
const bufferButton = leftPanel.getByRole('button', { name: 'buffers' });
128+
await bufferButton.click();
129+
130+
await expect(bufferButton).toHaveClass(/active/);
131+
await expect(page).toHaveScreenshot('plan_buffers_diagram.png');
132+
});
133+
});
134+
135+
test.describe('plan tabs', () => {
136+
let navPills;
137+
138+
test.beforeEach(async ({ page }) => {
139+
navPills = page.locator('.nav.nav-pills');
140+
});
141+
142+
test('redirects to Plan view', async ({ page }) => {
143+
const planLink = navPills.getByRole('link', { name: 'Plan' });
144+
145+
await planLink.click();
146+
await expect(planLink).toHaveClass(/active/)
147+
await expect(page).toHaveURL(url => url.hash === '#plan')
148+
});
149+
150+
test('redirects to Grid view', async ({ page }) => {
151+
const gridLink = navPills.getByRole('link', { name: 'Grid' });
152+
153+
await gridLink.click();
154+
await expect(gridLink).toHaveClass(/active/)
155+
await expect(page).toHaveURL(url => url.hash === '#grid');
156+
await expect(page).toHaveScreenshot('plan_gridView.png');
157+
});
158+
159+
test('redirects to Raw view', async ({ page }) => {
160+
const rawLink = navPills.getByRole('link', { name: 'Raw' });
161+
162+
await rawLink.click();
163+
await expect(rawLink).toHaveClass(/active/)
164+
await expect(page).toHaveURL(url => url.hash === '#raw')
165+
await expect(page).toHaveScreenshot('plan_rawView.png');
166+
});
167+
168+
test('redirects to Query view', async ({ page }) => {
169+
const queryLink = navPills.getByRole('link', { name: 'Query' });
170+
171+
await queryLink.click();
172+
await expect(queryLink).toHaveClass(/active/)
173+
await expect(page).toHaveURL(url => url.hash === '#query')
174+
await expect(page).toHaveScreenshot('plan_queryView.png');
175+
});
176+
177+
test('redirects to Stats view', async ({ page }) => {
178+
const statsLink = navPills.getByRole('link', { name: 'Stats' });
179+
180+
await statsLink.click();
181+
await expect(statsLink).toHaveClass(/active/)
182+
await expect(page).toHaveURL(url => url.hash === '#stats')
183+
await expect(page).toHaveScreenshot('plan_statsView.png');
184+
});
185+
});
72.2 KB
Loading
85.7 KB
Loading
86.8 KB
Loading
75.9 KB
Loading
92.7 KB
Loading
91.2 KB
Loading

0 commit comments

Comments
 (0)