mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2025-12-21 17:34:53 +08:00
Pull request #2367: ADG-9679 add playwright test from python
Some checks failed
build / test (macOS-latest) (push) Has been cancelled
build / test (ubuntu-latest) (push) Has been cancelled
build / test (windows-latest) (push) Has been cancelled
build / build-release (push) Has been cancelled
build / notify (push) Has been cancelled
lint / go-lint (push) Has been cancelled
lint / eslint (push) Has been cancelled
lint / notify (push) Has been cancelled
Some checks failed
build / test (macOS-latest) (push) Has been cancelled
build / test (ubuntu-latest) (push) Has been cancelled
build / test (windows-latest) (push) Has been cancelled
build / build-release (push) Has been cancelled
build / notify (push) Has been cancelled
lint / go-lint (push) Has been cancelled
lint / eslint (push) Has been cancelled
lint / notify (push) Has been cancelled
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
@@ -7,7 +7,7 @@
|
|||||||
# Make sure to sync any changes with the branch overrides below.
|
# Make sure to sync any changes with the branch overrides below.
|
||||||
'variables':
|
'variables':
|
||||||
'channel': 'edge'
|
'channel': 'edge'
|
||||||
'dockerFrontend': 'adguard/home-js-builder:3.0'
|
'dockerFrontend': 'adguard/home-js-builder:3.1'
|
||||||
'dockerGo': 'adguard/go-builder:1.24.2--1'
|
'dockerGo': 'adguard/go-builder:1.24.2--1'
|
||||||
|
|
||||||
'stages':
|
'stages':
|
||||||
@@ -278,7 +278,7 @@
|
|||||||
# need to build a few of these.
|
# need to build a few of these.
|
||||||
'variables':
|
'variables':
|
||||||
'channel': 'beta'
|
'channel': 'beta'
|
||||||
'dockerFrontend': 'adguard/home-js-builder:3.0'
|
'dockerFrontend': 'adguard/home-js-builder:3.1'
|
||||||
'dockerGo': 'adguard/go-builder:1.24.2--1'
|
'dockerGo': 'adguard/go-builder:1.24.2--1'
|
||||||
# release-vX.Y.Z branches are the branches from which the actual final
|
# release-vX.Y.Z branches are the branches from which the actual final
|
||||||
# release is built.
|
# release is built.
|
||||||
@@ -294,5 +294,5 @@
|
|||||||
# are the ones that actually get released.
|
# are the ones that actually get released.
|
||||||
'variables':
|
'variables':
|
||||||
'channel': 'release'
|
'channel': 'release'
|
||||||
'dockerFrontend': 'adguard/home-js-builder:3.0'
|
'dockerFrontend': 'adguard/home-js-builder:3.1'
|
||||||
'dockerGo': 'adguard/go-builder:1.24.2--1'
|
'dockerGo': 'adguard/go-builder:1.24.2--1'
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
'key': 'AHBRTSPECS'
|
'key': 'AHBRTSPECS'
|
||||||
'name': 'AdGuard Home - Build and run tests'
|
'name': 'AdGuard Home - Build and run tests'
|
||||||
'variables':
|
'variables':
|
||||||
'dockerFrontend': 'adguard/home-js-builder:3.0'
|
'dockerFrontend': 'adguard/home-js-builder:3.1'
|
||||||
'dockerGo': 'adguard/go-builder:1.24.2--1'
|
'dockerGo': 'adguard/go-builder:1.24.2--1'
|
||||||
'channel': 'development'
|
'channel': 'development'
|
||||||
|
|
||||||
@@ -233,6 +233,6 @@
|
|||||||
# Set the default release channel on the release branch to beta, as we
|
# Set the default release channel on the release branch to beta, as we
|
||||||
# may need to build a few of these.
|
# may need to build a few of these.
|
||||||
'variables':
|
'variables':
|
||||||
'dockerFrontend': 'adguard/home-js-builder:3.0'
|
'dockerFrontend': 'adguard/home-js-builder:3.1'
|
||||||
'dockerGo': 'adguard/go-builder:1.24.2--1'
|
'dockerGo': 'adguard/go-builder:1.24.2--1'
|
||||||
'channel': 'candidate'
|
'channel': 'candidate'
|
||||||
|
|||||||
1207
client/package-lock.json
generated
vendored
1207
client/package-lock.json
generated
vendored
File diff suppressed because it is too large
Load Diff
4
client/package.json
vendored
4
client/package.json
vendored
@@ -66,7 +66,7 @@
|
|||||||
"@babel/preset-react": "^7.24.1",
|
"@babel/preset-react": "^7.24.1",
|
||||||
"@playwright/test": "1.50.1",
|
"@playwright/test": "1.50.1",
|
||||||
"@types/lodash": "^4.17.4",
|
"@types/lodash": "^4.17.4",
|
||||||
"@types/node": "^22.10.2",
|
"@types/node": "^22.13.10",
|
||||||
"@types/react": "^17.0.80",
|
"@types/react": "^17.0.80",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@types/react-redux": "^7.1.33",
|
"@types/react-redux": "^7.1.33",
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
"stylelint": "^16.5.0",
|
"stylelint": "^16.5.0",
|
||||||
"ts-loader": "^9.5.1",
|
"ts-loader": "^9.5.1",
|
||||||
"url-loader": "^4.1.1",
|
"url-loader": "^4.1.1",
|
||||||
"vitest": "^3.0.4",
|
"vitest": "^3.1.1",
|
||||||
"webpack": "^5.91.0",
|
"webpack": "^5.91.0",
|
||||||
"webpack-cli": "^5.1.4",
|
"webpack-cli": "^5.1.4",
|
||||||
"webpack-dev-server": "^5.0.4",
|
"webpack-dev-server": "^5.0.4",
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ class CustomRules extends Component<CustomRulesProps> {
|
|||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
<div className="text-edit-container mb-4">
|
<div className="text-edit-container mb-4">
|
||||||
<textarea
|
<textarea
|
||||||
|
data-testid="custom_rule_textarea"
|
||||||
className="form-control font-monospace text-input"
|
className="form-control font-monospace text-input"
|
||||||
value={userRules}
|
value={userRules}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
@@ -91,6 +92,7 @@ class CustomRules extends Component<CustomRulesProps> {
|
|||||||
|
|
||||||
<div className="card-actions">
|
<div className="card-actions">
|
||||||
<button
|
<button
|
||||||
|
data-testid="apply_custom_rule"
|
||||||
className="btn btn-success btn-standard btn-large"
|
className="btn btn-success btn-standard btn-large"
|
||||||
type="submit"
|
type="submit"
|
||||||
onClick={this.handleSubmit}>
|
onClick={this.handleSubmit}>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ const Header = () => {
|
|||||||
<div className="header__column">
|
<div className="header__column">
|
||||||
<div className="header__right">
|
<div className="header__right">
|
||||||
{!processingProfile && name && (
|
{!processingProfile && name && (
|
||||||
<a href="control/logout" className="btn btn-sm btn-outline-secondary">
|
<a href="control/logout" className="btn btn-sm btn-outline-secondary" data-testid="sign_out">
|
||||||
{t('sign_out')}
|
{t('sign_out')}
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ const Row = memo(
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={style} className={className} onClick={onClick} role="row">
|
<div style={style} className={className} onClick={onClick} role="row" data-testid="querylog_cell">
|
||||||
<DateCell {...rowProps} />
|
<DateCell {...rowProps} />
|
||||||
|
|
||||||
<DomainCell {...rowProps} />
|
<DomainCell {...rowProps} />
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ export const Form = ({ className, setIsLoading }: Props) => {
|
|||||||
}}>
|
}}>
|
||||||
<div className="field__search">
|
<div className="field__search">
|
||||||
<SearchField
|
<SearchField
|
||||||
|
data-testid="querylog_search"
|
||||||
value={searchValue}
|
value={searchValue}
|
||||||
handleChange={(val) => setValue('search', val)}
|
handleChange={(val) => setValue('search', val)}
|
||||||
onKeyDown={onEnterPress}
|
onKeyDown={onEnterPress}
|
||||||
|
|||||||
@@ -27,12 +27,14 @@ const SETTINGS = {
|
|||||||
enabled: false,
|
enabled: false,
|
||||||
title: i18next.t('use_adguard_browsing_sec'),
|
title: i18next.t('use_adguard_browsing_sec'),
|
||||||
subtitle: i18next.t('use_adguard_browsing_sec_hint'),
|
subtitle: i18next.t('use_adguard_browsing_sec_hint'),
|
||||||
|
testId: 'safebrowsing',
|
||||||
[ORDER_KEY]: 0,
|
[ORDER_KEY]: 0,
|
||||||
},
|
},
|
||||||
parental: {
|
parental: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
title: i18next.t('use_adguard_parental'),
|
title: i18next.t('use_adguard_parental'),
|
||||||
subtitle: i18next.t('use_adguard_parental_hint'),
|
subtitle: i18next.t('use_adguard_parental_hint'),
|
||||||
|
testId: 'parental',
|
||||||
[ORDER_KEY]: 1,
|
[ORDER_KEY]: 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -90,11 +92,12 @@ class Settings extends Component<SettingsProps> {
|
|||||||
renderSettings = (settings: any) =>
|
renderSettings = (settings: any) =>
|
||||||
getObjectKeysSorted(SETTINGS, ORDER_KEY).map((key: any) => {
|
getObjectKeysSorted(SETTINGS, ORDER_KEY).map((key: any) => {
|
||||||
const setting = settings[key];
|
const setting = settings[key];
|
||||||
const { enabled, title, subtitle } = setting;
|
const { enabled, title, subtitle, testId } = setting;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={key} className="form__group form__group--checkbox">
|
<div key={key} className="form__group form__group--checkbox">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
|
data-testid={testId}
|
||||||
value={enabled}
|
value={enabled}
|
||||||
title={title}
|
title={title}
|
||||||
subtitle={subtitle}
|
subtitle={subtitle}
|
||||||
@@ -118,6 +121,7 @@ class Settings extends Component<SettingsProps> {
|
|||||||
<>
|
<>
|
||||||
<div className="form__group form__group--checkbox">
|
<div className="form__group form__group--checkbox">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
|
data-testid="safesearch"
|
||||||
value={enabled}
|
value={enabled}
|
||||||
title={i18next.t('enforce_safe_search')}
|
title={i18next.t('enforce_safe_search')}
|
||||||
subtitle={i18next.t('enforce_save_search_hint')}
|
subtitle={i18next.t('enforce_save_search_hint')}
|
||||||
|
|||||||
@@ -94,14 +94,17 @@ const Footer = () => {
|
|||||||
auto: {
|
auto: {
|
||||||
desc: t('theme_auto_desc'),
|
desc: t('theme_auto_desc'),
|
||||||
icon: '#auto',
|
icon: '#auto',
|
||||||
|
testId: 'theme_auto',
|
||||||
},
|
},
|
||||||
dark: {
|
dark: {
|
||||||
desc: t('theme_dark_desc'),
|
desc: t('theme_dark_desc'),
|
||||||
icon: '#dark',
|
icon: '#dark',
|
||||||
|
testId: 'theme_dark',
|
||||||
},
|
},
|
||||||
light: {
|
light: {
|
||||||
desc: t('theme_light_desc'),
|
desc: t('theme_light_desc'),
|
||||||
icon: '#light',
|
icon: '#light',
|
||||||
|
testId: 'theme_light',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -113,7 +116,9 @@ const Footer = () => {
|
|||||||
type="button"
|
type="button"
|
||||||
className="btn btn-sm btn-secondary footer__theme-button"
|
className="btn btn-sm btn-secondary footer__theme-button"
|
||||||
onClick={() => onThemeChange(theme)}
|
onClick={() => onThemeChange(theme)}
|
||||||
title={content[theme].desc}>
|
title={content[theme].desc}
|
||||||
|
data-testid={content[theme].testId}
|
||||||
|
>
|
||||||
<svg className={cn('footer__theme-icon', { 'footer__theme-icon--active': currentValue === theme })}>
|
<svg className={cn('footer__theme-icon', { 'footer__theme-icon--active': currentValue === theme })}>
|
||||||
<use xlinkHref={content[theme].icon} />
|
<use xlinkHref={content[theme].icon} />
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
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