Pull request #2367: ADG-9679 add playwright test from python
Merge in DNS/adguard-home from ADG-9679 to master Squashed commit of the following: commit d2a759b4636b7ec931bfba625827c8b91c60c7e7 Merge: a5e7eea169726171f0Author: Igor Lobanov <bniwredyc@gmail.com> Date: Mon Apr 14 16:05:01 2025 +0200 Merge remote-tracking branch 'origin/master' into ADG-9679 commit a5e7eea16e6c29d25290ee79b1918df8af59bb51 Author: Igor Lobanov <bniwredyc@gmail.com> Date: Mon Apr 14 13:56:26 2025 +0200 vitest version bump commit 26620d1923d92b3a6eb9b80a364748f2f6f66030 Author: Igor Lobanov <bniwredyc@gmail.com> Date: Thu Apr 10 15:39:11 2025 +0200 formatting commit dbab03d1316241eaff0fc9c99d58a1933e415d2b Author: Igor Lobanov <bniwredyc@gmail.com> Date: Thu Apr 10 15:37:55 2025 +0200 rollback experiments commit 4427d984177786f7d905915cf8080166b45d7b46 Author: Igor Lobanov <bniwredyc@gmail.com> Date: Thu Apr 10 15:33:28 2025 +0200 checking dir structure commit 2cf7eed247d2869ed285dbee0bf32cf1d8df7e86 Author: Igor Lobanov <bniwredyc@gmail.com> Date: Thu Apr 10 15:21:11 2025 +0200 fixed docker image builder commit 8bd06f412fad9dd09df0e076879bd2cbd2f30d1a Author: Igor Lobanov <bniwredyc@gmail.com> Date: Thu Apr 10 15:18:33 2025 +0200 home-js-builder version bump commit 2a83bfeb322a20ec4278e359b18d0466966ec043 Author: Igor Lobanov <bniwredyc@gmail.com> Date: Thu Apr 10 15:17:38 2025 +0200 try to remove installation dependencies for e2e test (build is already available) commit 163e4581e83152f99058b798484468009e8e88b0 Author: Igor Lobanov <bniwredyc@gmail.com> Date: Thu Apr 10 13:52:27 2025 +0200 Revert "changed nslookup to dig in e2e tests" This reverts commit ecb68200ea28e295f504338cc59c711b5540022b. commit 15f7c5e2c77e230da77a0f9de0bd9cce8451da95 Author: Igor Lobanov <bniwredyc@gmail.com> Date: Thu Apr 10 13:45:40 2025 +0200 js-home-builder version bump commit ecb68200ea28e295f504338cc59c711b5540022b Author: Igor Lobanov <bniwredyc@gmail.com> Date: Wed Apr 9 15:07:39 2025 +0200 changed nslookup to dig in e2e tests commit 77c94a60be8839f3e0ad9d02e7dbb2ebd802d3d6 Author: Eugene Miroshkin <e.miroshkin@adguard.com> Date: Wed Apr 9 11:09:15 2025 +0300 revert timeouts commit 9dfebc8bcaf2cd3258b39fcbd0f67ab51c2eb46d Merge: 912f4cb7b1cc6c00e4Author: Eugene Miroshkin <e.miroshkin@adguard.com> Date: Wed Apr 9 11:02:19 2025 +0300 merge master commit 912f4cb7b71f02866244fe447ca0e7fbd2a015bb Author: Eugene Miroshkin <e.miroshkin@adguard.com> Date: Wed Apr 9 10:48:59 2025 +0300 cleanup code commit 9da200ebca5b001f4952f33d819d90c1938920ee Author: Eugene Miroshkin <e.miroshkin@adguard.com> Date: Thu Apr 3 17:39:20 2025 +0300 update tests commit 794e0bd0a92a41c4d3827b716eeab584a25bd3ed Author: Eugene Miroshkin <e.miroshkin@adguard.com> Date: Thu Mar 13 18:15:58 2025 +0300 cleanup commit 9a523b4e255dd24c0f640bc279924ed2c13509a9 Author: Eugene Miroshkin <e.miroshkin@adguard.com> Date: Thu Mar 13 18:04:34 2025 +0300 ADG-9679 add playwright test from python
This commit is contained in:
committed by
Igor 🐧 Lobanov
parent
9726171f0f
commit
4d258972d1
40
client/tests/e2e/control-panel.spec.ts
Normal file
40
client/tests/e2e/control-panel.spec.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { ADMIN_USERNAME, ADMIN_PASSWORD } from '../constants';
|
||||
|
||||
test.describe('Control Panel', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/login.html');
|
||||
await page.getByTestId('username').click();
|
||||
await page.getByTestId('username').fill(ADMIN_USERNAME);
|
||||
await page.getByTestId('password').click();
|
||||
await page.getByTestId('password').fill(ADMIN_PASSWORD);
|
||||
await page.keyboard.press('Tab');
|
||||
await page.getByTestId('sign_in').click();
|
||||
await page.waitForURL((url) => !url.href.endsWith('/login.html'));
|
||||
});
|
||||
|
||||
test('should sign out successfully', async ({ page }) => {
|
||||
|
||||
await page.getByTestId('sign_out').click();
|
||||
|
||||
|
||||
await page.waitForURL((url) => url.href.endsWith('/login.html'));
|
||||
|
||||
|
||||
await expect(page.getByTestId('sign_in')).toBeVisible();
|
||||
});
|
||||
|
||||
test('should change theme to dark and then light', async ({ page }) => {
|
||||
|
||||
await page.getByTestId('theme_dark').click();
|
||||
|
||||
|
||||
await expect(page.locator('body[data-theme="dark"]')).toBeVisible();
|
||||
|
||||
|
||||
await page.getByTestId('theme_light').click();
|
||||
|
||||
|
||||
await expect(page.locator('body:not([data-theme="dark"])')).toBeVisible();
|
||||
});
|
||||
});
|
||||
52
client/tests/e2e/dns-settings.spec.ts
Normal file
52
client/tests/e2e/dns-settings.spec.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { test, expect, type Page } from '@playwright/test';
|
||||
import { ADMIN_USERNAME, ADMIN_PASSWORD } from '../constants';
|
||||
|
||||
test.describe('DNS Settings', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Login before each test
|
||||
await page.goto('/login.html');
|
||||
await page.getByTestId('username').click();
|
||||
await page.getByTestId('username').fill(ADMIN_USERNAME);
|
||||
await page.getByTestId('password').click();
|
||||
await page.getByTestId('password').fill(ADMIN_PASSWORD);
|
||||
await page.keyboard.press('Tab');
|
||||
await page.getByTestId('sign_in').click();
|
||||
await page.waitForURL((url) => !url.href.endsWith('/login.html'));
|
||||
});
|
||||
|
||||
const runDNSSettingsTest = async (page: Page, address: string) => {
|
||||
await page.goto('/#dns');
|
||||
|
||||
const currentDns = await page.getByTestId('upstream_dns').inputValue();
|
||||
|
||||
await page.getByTestId('upstream_dns').fill(address);
|
||||
await page.getByTestId('dns_upstream_test').click();
|
||||
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await expect(page.getByTestId('upstream_dns')).toHaveValue(address);
|
||||
|
||||
await page.getByTestId('upstream_dns').fill(currentDns);
|
||||
await page.getByTestId('dns_upstream_save').click({ force: true });
|
||||
};
|
||||
|
||||
test('test for Default DNS', async ({ page }) => {
|
||||
await runDNSSettingsTest(page, 'https://dns10.quad9.net/dns-query');
|
||||
});
|
||||
|
||||
test('test for Plain DNS', async ({ page }) => {
|
||||
await runDNSSettingsTest(page, '94.140.14.140');
|
||||
});
|
||||
|
||||
test('test for DNS-over-HTTPS', async ({ page }) => {
|
||||
await runDNSSettingsTest(page, 'https://unfiltered.adguard-dns.com/dns-query');
|
||||
});
|
||||
|
||||
test('test for DNS-over-TLS', async ({ page }) => {
|
||||
await runDNSSettingsTest(page, 'tls://unfiltered.adguard-dns.com');
|
||||
});
|
||||
|
||||
test('test for DNS-over-QUIC', async ({ page }) => {
|
||||
await runDNSSettingsTest(page, 'quic://unfiltered.adguard-dns.com');
|
||||
});
|
||||
});
|
||||
73
client/tests/e2e/filtering.spec.ts
Normal file
73
client/tests/e2e/filtering.spec.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { test, expect, type Page } from '@playwright/test';
|
||||
import { execSync } from 'child_process';
|
||||
import { ADMIN_USERNAME, ADMIN_PASSWORD } from '../constants';
|
||||
|
||||
test.describe('Filtering', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Login before each test
|
||||
await page.goto('/login.html');
|
||||
await page.getByTestId('username').click();
|
||||
await page.getByTestId('username').fill(ADMIN_USERNAME);
|
||||
await page.getByTestId('password').click();
|
||||
await page.getByTestId('password').fill(ADMIN_PASSWORD);
|
||||
await page.keyboard.press('Tab');
|
||||
await page.getByTestId('sign_in').click();
|
||||
await page.waitForURL((url) => !url.href.endsWith('/login.html'));
|
||||
});
|
||||
|
||||
const runTerminalCommand = (command: string) => {
|
||||
try {
|
||||
console.info(`Executing command: ${command}`);
|
||||
|
||||
const output = execSync(command, { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
||||
|
||||
console.info('Command executed successfully.');
|
||||
console.debug(`Command output:\n${output}`);
|
||||
|
||||
return output;
|
||||
} catch (error: any) {
|
||||
console.error(`Command execution failed with error:\n${error.message}`);
|
||||
throw new Error(`Failed to execute command: ${command}\nError: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const runCustomRuleTest = async (page: Page, domain_to_block: string) => {
|
||||
await page.goto('/#custom_rules');
|
||||
|
||||
await page.getByTestId('custom_rule_textarea').fill(domain_to_block);
|
||||
await page.getByTestId('apply_custom_rule').click();
|
||||
|
||||
const nslookupBlockedResult = await runTerminalCommand(`nslookup ${domain_to_block} 127.0.0.1`).toString();
|
||||
|
||||
console.info(`nslookup blocked CNAME result: '${nslookupBlockedResult}'`);
|
||||
|
||||
const currentRules = await page.getByTestId('custom_rule_textarea').inputValue();
|
||||
console.debug(`Current rules before removal:\n${currentRules}`);
|
||||
|
||||
if (currentRules.includes(domain_to_block)) {
|
||||
const updatedRules = currentRules
|
||||
.split('\n')
|
||||
.filter((line) => line.trim() !== domain_to_block.trim())
|
||||
.join('\n');
|
||||
|
||||
await page.getByTestId('custom_rule_textarea').fill(updatedRules);
|
||||
console.info(`Rule '${domain_to_block}' removed successfully.`);
|
||||
|
||||
console.info('Applying the updated filtering rules after removal.');
|
||||
await page.getByTestId('apply_custom_rule').click();
|
||||
|
||||
await page.waitForLoadState('domcontentloaded');
|
||||
|
||||
console.info(`Filtering rules successfully updated after removing '${domain_to_block}'.`);
|
||||
} else {
|
||||
console.warn(`Rule '${domain_to_block}' not found. No changes were made.`);
|
||||
}
|
||||
|
||||
const nslookupUnblockedResult = await runTerminalCommand(`nslookup ${domain_to_block} 127.0.0.1`).toString();
|
||||
console.info(`nslookup unblocked CNAME result: '${nslookupUnblockedResult}'`);
|
||||
};
|
||||
|
||||
test('Test blocking rule for apple.com', async ({ page }) => {
|
||||
await runCustomRuleTest(page, 'apple.com');
|
||||
});
|
||||
});
|
||||
89
client/tests/e2e/general-settings.spec.ts
Normal file
89
client/tests/e2e/general-settings.spec.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { execSync } from 'child_process';
|
||||
import { ADMIN_USERNAME, ADMIN_PASSWORD } from '../constants';
|
||||
|
||||
test.describe('General Settings', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/login.html');
|
||||
await page.getByTestId('username').click();
|
||||
await page.getByTestId('username').fill(ADMIN_USERNAME);
|
||||
await page.getByTestId('password').click();
|
||||
await page.getByTestId('password').fill(ADMIN_PASSWORD);
|
||||
await page.keyboard.press('Tab');
|
||||
await page.getByTestId('sign_in').click();
|
||||
await page.waitForURL((url) => !url.href.endsWith('/login.html'));
|
||||
});
|
||||
|
||||
test('should toggle browsing security feature and verify DNS changes', async ({ page }) => {
|
||||
await page.goto('/#settings');
|
||||
|
||||
const browsingSecurity = await page.getByTestId('safebrowsing');
|
||||
const browsingSecurityLabel = await browsingSecurity.locator('xpath=following-sibling::*[1]');
|
||||
|
||||
const initialState = await browsingSecurity.isChecked();
|
||||
|
||||
if (!initialState) {
|
||||
await browsingSecurityLabel.click();
|
||||
await expect(browsingSecurity).toBeChecked();
|
||||
}
|
||||
|
||||
const resultEnabled = execSync('nslookup totalvirus.com 127.0.0.1').toString();
|
||||
|
||||
await browsingSecurityLabel.click();
|
||||
await expect(browsingSecurity).not.toBeChecked();
|
||||
|
||||
const resultDisabled = execSync('nslookup totalvirus.com 127.0.0.1').toString();
|
||||
|
||||
expect(resultEnabled).not.toEqual(resultDisabled);
|
||||
|
||||
if (initialState) {
|
||||
await browsingSecurityLabel.click();
|
||||
await expect(browsingSecurity).toBeChecked();
|
||||
}
|
||||
});
|
||||
|
||||
test('should toggle parental control feature and verify DNS changes', async ({ page }) => {
|
||||
await page.goto('/#settings');
|
||||
|
||||
const parentalControl = page.getByTestId('parental');
|
||||
const parentalControlLabel = await parentalControl.locator('xpath=following-sibling::*[1]');
|
||||
|
||||
const initialState = await parentalControl.isChecked();
|
||||
|
||||
if (!initialState) {
|
||||
await parentalControlLabel.click();
|
||||
await expect(parentalControl).toBeChecked();
|
||||
}
|
||||
|
||||
const resultEnabled = execSync('nslookup pornhub.com 127.0.0.1').toString();
|
||||
|
||||
await parentalControlLabel.click();
|
||||
await expect(parentalControl).not.toBeChecked();
|
||||
|
||||
const resultDisabled = execSync('nslookup pornhub.com 127.0.0.1').toString();
|
||||
|
||||
expect(resultEnabled).not.toEqual(resultDisabled);
|
||||
|
||||
if (initialState) {
|
||||
await parentalControlLabel.click();
|
||||
await expect(parentalControl).toBeChecked();
|
||||
}
|
||||
});
|
||||
|
||||
test('should toggle safe search feature', async ({ page }) => {
|
||||
await page.goto('/#settings');
|
||||
|
||||
const safeSearch = page.getByTestId('safesearch');
|
||||
const safeSearchLabel = await safeSearch.locator('xpath=following-sibling::*[1]');
|
||||
|
||||
const initialState = await safeSearch.isChecked();
|
||||
|
||||
await safeSearchLabel.click();
|
||||
|
||||
await expect(safeSearch).not.toBeChecked({ checked: initialState });
|
||||
|
||||
await safeSearchLabel.click();
|
||||
|
||||
await expect(safeSearch).toBeChecked({ checked: initialState });
|
||||
});
|
||||
});
|
||||
124
client/tests/e2e/querylog.spec.ts
Normal file
124
client/tests/e2e/querylog.spec.ts
Normal file
@@ -0,0 +1,124 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { ADMIN_USERNAME, ADMIN_PASSWORD } from '../constants';
|
||||
|
||||
test.describe('QueryLog', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/login.html');
|
||||
await page.getByTestId('username').click();
|
||||
await page.getByTestId('username').fill(ADMIN_USERNAME);
|
||||
await page.getByTestId('password').click();
|
||||
await page.getByTestId('password').fill(ADMIN_PASSWORD);
|
||||
await page.keyboard.press('Tab');
|
||||
await page.getByTestId('sign_in').click();
|
||||
await page.waitForURL((url) => !url.href.endsWith('/login.html'));
|
||||
});
|
||||
|
||||
test('Search of queryLog should work correctly', async ({ page }) => {
|
||||
await page.route('/control/querylog', async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"answer": [
|
||||
{
|
||||
"type": "A",
|
||||
"value": "77.88.44.242",
|
||||
"ttl": 294
|
||||
},
|
||||
{
|
||||
"type": "A",
|
||||
"value": "5.255.255.242",
|
||||
"ttl": 294
|
||||
},
|
||||
{
|
||||
"type": "A",
|
||||
"value": "77.88.55.242",
|
||||
"ttl": 294
|
||||
}
|
||||
],
|
||||
"answer_dnssec": false,
|
||||
"cached": false,
|
||||
"client": "127.0.0.1",
|
||||
"client_info": {
|
||||
"whois": {},
|
||||
"name": "localhost",
|
||||
"disallowed_rule": "127.0.0.1",
|
||||
"disallowed": false
|
||||
},
|
||||
"client_proto": "",
|
||||
"elapsedMs": "78.163167",
|
||||
"question": {
|
||||
"class": "IN",
|
||||
"name": "ya.ru",
|
||||
"type": "A"
|
||||
},
|
||||
"reason": "NotFilteredNotFound",
|
||||
"rules": [],
|
||||
"status": "NOERROR",
|
||||
"time": "2024-07-17T16:02:37.500662+02:00",
|
||||
"upstream": "https://dns10.quad9.net:443/dns-query"
|
||||
},
|
||||
{
|
||||
"answer": [
|
||||
{
|
||||
"type": "A",
|
||||
"value": "77.88.55.242",
|
||||
"ttl": 351
|
||||
},
|
||||
{
|
||||
"type": "A",
|
||||
"value": "77.88.44.242",
|
||||
"ttl": 351
|
||||
},
|
||||
{
|
||||
"type": "A",
|
||||
"value": "5.255.255.242",
|
||||
"ttl": 351
|
||||
}
|
||||
],
|
||||
"answer_dnssec": false,
|
||||
"cached": false,
|
||||
"client": "127.0.0.1",
|
||||
"client_info": {
|
||||
"whois": {},
|
||||
"name": "localhost",
|
||||
"disallowed_rule": "127.0.0.1",
|
||||
"disallowed": false
|
||||
},
|
||||
"client_proto": "",
|
||||
"elapsedMs": "5051.070708",
|
||||
"question": {
|
||||
"class": "IN",
|
||||
"name": "ya.ru",
|
||||
"type": "A"
|
||||
},
|
||||
"reason": "NotFilteredNotFound",
|
||||
"rules": [],
|
||||
"status": "NOERROR",
|
||||
"time": "2024-07-17T16:02:37.4983+02:00",
|
||||
"upstream": "https://dns10.quad9.net:443/dns-query"
|
||||
}
|
||||
],
|
||||
"oldest": "2024-07-17T16:02:37.4983+02:00"
|
||||
}
|
||||
),
|
||||
});
|
||||
});
|
||||
|
||||
await page.goto('/#logs');
|
||||
|
||||
await page.getByTestId('querylog_search').fill('127.0.0.1');
|
||||
|
||||
const [request] = await Promise.all([
|
||||
page.waitForRequest((req) => req.url().includes('/control/querylog')),
|
||||
]);
|
||||
|
||||
if (request) {
|
||||
expect(request.url()).toContain('search=127.0.0.1');
|
||||
expect(await page.getByTestId('querylog_cell').first().isVisible()).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user