feat: add full Zonemaster stack with Docker and Spanish UI
- Clone all 5 Zonemaster component repos (LDNS, Engine, CLI, Backend, GUI) - Dockerfile.backend: 8-stage multi-stage build LDNS→Engine→CLI→Backend - Dockerfile.gui: Astro static build served via nginx - docker-compose.yml: backend (internal) + frontend (port 5353) - nginx.conf: root redirects to /es/, /api/ proxied to backend - zonemaster-gui/config.ts: defaultLanguage set to 'es' (Spanish) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
14
zonemaster-gui/e2e/FR01.e2e-spec.ts
Normal file
14
zonemaster-gui/e2e/FR01.e2e-spec.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { test, expect } from './global-setup';
|
||||
|
||||
import { goToHome, setLang } from './utils/app.utils';
|
||||
|
||||
test.describe('Zonemaster test FR01 - [A Home button that sends the user to the default simple view]', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await goToHome(page);
|
||||
await setLang(page, 'en');
|
||||
});
|
||||
|
||||
test('should have a link to go to home page', async ({ page }) => {
|
||||
await expect(page.locator('a.zm-logo')).toHaveAttribute('href', '/en/');
|
||||
});
|
||||
});
|
||||
20
zonemaster-gui/e2e/FR02.e2e-spec.ts
Normal file
20
zonemaster-gui/e2e/FR02.e2e-spec.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { test, expect } from './global-setup';
|
||||
|
||||
import { goToHome, setLang } from './utils/app.utils';
|
||||
|
||||
test.describe('Zonemaster test FR02 - [All menus should be clickable in latest version of different browsers]', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await goToHome(page);
|
||||
await setLang(page, 'en');
|
||||
});
|
||||
|
||||
test('should go to faq page', async ({ page, baseURL }) => {
|
||||
await page.locator('a.zm-menu__item[href="/en/faq/"]').click();
|
||||
await expect(page).toHaveURL(baseURL + '/en/faq/');
|
||||
});
|
||||
|
||||
test('should go to domain page', async ({ page, baseURL }) => {
|
||||
await page.locator('a.zm-menu__item[href="/en/"]').click();
|
||||
await expect(page).toHaveURL(baseURL + '/en/');
|
||||
});
|
||||
});
|
||||
36
zonemaster-gui/e2e/FR03.e2e-spec.ts
Normal file
36
zonemaster-gui/e2e/FR03.e2e-spec.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { test, expect } from './global-setup';
|
||||
|
||||
import { goToHome, setLang, showOptions } from './utils/app.utils';
|
||||
|
||||
test.describe('Zonemaster test FR03 - [All appropriate fields should be writable]', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await goToHome(page);
|
||||
await setLang(page, 'en');
|
||||
await page.waitForLoadState('networkidle');
|
||||
});
|
||||
|
||||
test('should be able to write in the main input', async ({ page }) => {
|
||||
const testString = 'afnic.fr';
|
||||
|
||||
const domainInput = page.locator('#zmDomainTestForm input[name="domain"]').first();
|
||||
|
||||
await domainInput.focus();
|
||||
await page.keyboard.type(testString);
|
||||
await expect(domainInput).toHaveValue(testString);
|
||||
|
||||
await showOptions(page);
|
||||
await page.waitForTimeout(400);
|
||||
|
||||
const nsInput = page.locator('input[name="nameservers[0][ns]"]').first();
|
||||
|
||||
await nsInput.focus();
|
||||
await page.keyboard.type(testString);
|
||||
await expect(nsInput).toHaveValue(testString);
|
||||
|
||||
const keytagInput = page.locator('input[name="ds_info[0][keytag]"]').first();
|
||||
|
||||
await keytagInput.focus();
|
||||
await page.keyboard.type(testString);
|
||||
await expect(keytagInput).toHaveValue(testString);
|
||||
});
|
||||
});
|
||||
14
zonemaster-gui/e2e/FR04.e2e-spec.ts
Normal file
14
zonemaster-gui/e2e/FR04.e2e-spec.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { test, expect } from './global-setup';
|
||||
|
||||
import { goToHome, setLang } from './utils/app.utils';
|
||||
|
||||
test.describe('Zonemaster test FR04 - Valid title for the Web interface', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await goToHome(page);
|
||||
await setLang(page, 'en');
|
||||
});
|
||||
|
||||
test('should have right title - Zonemaster', async ({ page }) => {
|
||||
await expect(page).toHaveTitle('Zonemaster');
|
||||
});
|
||||
});
|
||||
33
zonemaster-gui/e2e/FR05.e2e-spec.ts
Normal file
33
zonemaster-gui/e2e/FR05.e2e-spec.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { test, expect } from './global-setup';
|
||||
|
||||
import { goToHome, setLang } from './utils/app.utils';
|
||||
|
||||
test.describe('Zonemaster test FR05 - [Supports internationalization]', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await goToHome(page);
|
||||
});
|
||||
|
||||
const testSuite = [
|
||||
{ language: 'Danish', code: 'da', expected: 'Domænenavn' },
|
||||
{ language: 'English', code: 'en', expected: 'Domain name' },
|
||||
{ language: 'Spanish', code: 'es', expected: 'Nombre de dominio' },
|
||||
{ language: 'Finnish', code: 'fi', expected: 'Verkkotunnuksen nimi' },
|
||||
{ language: 'French', code: 'fr', expected: 'Nom de domaine' },
|
||||
{ language: 'Norwegian', code: 'nb', expected: 'Domenenavn' },
|
||||
{ language: 'Swedish', code: 'sv', expected: 'Domänamn' },
|
||||
{ language: 'Slovenian', code: 'sl', expected: 'Ime domene' },
|
||||
];
|
||||
|
||||
for (const { language, code, expected } of testSuite) {
|
||||
test(`should have ${language} language option`, async ({ page }) => {
|
||||
const langNavLink = page.locator(`select#languageSwitcher > option[lang="${code}"]`);
|
||||
await expect(langNavLink).toHaveCount(1);
|
||||
await expect(langNavLink).toHaveAttribute('lang', code);
|
||||
})
|
||||
|
||||
test(`should switch to ${language}`, async ({ page }) => {
|
||||
await setLang(page, code);
|
||||
await expect(page.locator('input[name="domain"]')).toHaveAttribute('placeholder', expected);
|
||||
})
|
||||
}
|
||||
});
|
||||
14
zonemaster-gui/e2e/FR08.e2e-spec.ts
Normal file
14
zonemaster-gui/e2e/FR08.e2e-spec.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { test, expect } from './global-setup';
|
||||
|
||||
import { goToHome, clearBrowserCache } from './utils/app.utils';
|
||||
|
||||
test.describe('Zonemaster test FR08 - [Presence of a default fallback language - English]', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await goToHome(page);
|
||||
await clearBrowserCache(page);
|
||||
});
|
||||
|
||||
test('should have a fallback language - English', async ({ page }) => {
|
||||
await expect(page.locator('input[name="domain"]')).toHaveAttribute('placeholder', 'Domain name');
|
||||
});
|
||||
});
|
||||
17
zonemaster-gui/e2e/FR09.e2e-spec.ts
Normal file
17
zonemaster-gui/e2e/FR09.e2e-spec.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import {test, expect} from './global-setup';
|
||||
|
||||
import {goToHome, setLang} from './utils/app.utils';
|
||||
|
||||
test.describe('Zonemaster test FR09 - [Once a language is chosen, all other links should open in that respective language]', () => {
|
||||
test.beforeEach(async ({page}) => {
|
||||
await goToHome(page);
|
||||
await setLang(page, 'fr');
|
||||
});
|
||||
|
||||
test('should keep french when opening faq page', async ({page}) => {
|
||||
await expect(page.locator('input[name="domain"]')).toHaveAttribute('placeholder', 'Nom de domaine');
|
||||
await page.goto('/fr/faq/');
|
||||
await expect(page.locator('main h1')).toHaveText('Questions fréquentes');
|
||||
await expect(page.locator('a.zm-menu__item[href$="/fr/"]')).toHaveText("Démarrer un test");
|
||||
});
|
||||
});
|
||||
24
zonemaster-gui/e2e/FR10.e2e-spec.ts
Normal file
24
zonemaster-gui/e2e/FR10.e2e-spec.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { test, expect } from './global-setup';
|
||||
|
||||
import { goToHome, clearBrowserCache } from './utils/app.utils';
|
||||
|
||||
test.describe('Zonemaster test FR10 - [On launching the URL opens with a default simple view]', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await goToHome(page);
|
||||
await clearBrowserCache(page);
|
||||
});
|
||||
|
||||
test('should have [Run domain test] label visible', async ({ page }) => {
|
||||
await expect(page.locator('h1', { hasText: 'Check how your domain is doing'})).toBeVisible();
|
||||
});
|
||||
|
||||
test('should have [Options] label visible and NOT selected', async ({ page }) => {
|
||||
await expect(page.locator('#advanced-toggle-label', { hasText: 'Show options' })).toBeVisible();
|
||||
await expect(page.locator('#advanced-toggle')).toHaveAttribute('aria-expanded', 'false');
|
||||
});
|
||||
|
||||
|
||||
test('should have options NOT visible', async ({ page }) => {
|
||||
await expect(page.locator('#advanced-options')).toHaveAttribute('hidden');
|
||||
});
|
||||
});
|
||||
22
zonemaster-gui/e2e/FR11.e2e-spec.ts
Normal file
22
zonemaster-gui/e2e/FR11.e2e-spec.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { test, expect } from './global-setup';
|
||||
import { closeOptions, goToHome, setLang, showOptions } from './utils/app.utils';
|
||||
|
||||
test.describe('Zonemaster test FR11 - [The simple view should look the same in latest version of different browsers]', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await goToHome(page);
|
||||
await setLang(page, 'en');
|
||||
await page.waitForLoadState('networkidle');
|
||||
});
|
||||
|
||||
test('should match the domain page', async ({ page }) => {
|
||||
await closeOptions(page);
|
||||
await page.waitForTimeout(400);
|
||||
expect(await page.screenshot()).toMatchSnapshot('domain.png');
|
||||
});
|
||||
|
||||
test('should not match the domain page', async ({ page }) => {
|
||||
await showOptions(page);
|
||||
await page.waitForTimeout(400);
|
||||
expect(await page.screenshot()).toMatchSnapshot('domain-options.png');
|
||||
});
|
||||
});
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 145 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 87 KiB |
BIN
zonemaster-gui/e2e/FR11.e2e-spec.ts-snapshots/domain-options.png
Normal file
BIN
zonemaster-gui/e2e/FR11.e2e-spec.ts-snapshots/domain-options.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 92 KiB |
BIN
zonemaster-gui/e2e/FR11.e2e-spec.ts-snapshots/domain.png
Normal file
BIN
zonemaster-gui/e2e/FR11.e2e-spec.ts-snapshots/domain.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 148 KiB |
22
zonemaster-gui/e2e/FR12.e2e-spec.ts
Normal file
22
zonemaster-gui/e2e/FR12.e2e-spec.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import {test, expect} from './global-setup';
|
||||
|
||||
import {goToHome, setLang, showOptions} from './utils/app.utils';
|
||||
|
||||
test.describe('Zonemaster test FR12 - [The simple view should support an advanced view expanding when the checkbox is enabled]', () => {
|
||||
test.beforeEach(async ({page}) => {
|
||||
await goToHome(page);
|
||||
await setLang(page, 'en');
|
||||
await page.waitForLoadState('networkidle');
|
||||
});
|
||||
|
||||
test('should have [Disable IPv4 checkbox] && [Disable IPv6 checkbox] NOT visible', async ({page}) => {
|
||||
await expect(page.locator('#advanced-options')).toHaveAttribute('hidden');
|
||||
});
|
||||
|
||||
test('should have [IPv4 and IPv6 radio] & [IPv4 only radio] & [IPv6 only radio] visible', async ({page}) => {
|
||||
await showOptions(page);
|
||||
await expect(page.locator('input[name="iptype"][value="both"]')).toBeVisible();
|
||||
await expect(page.locator('input[name="iptype"][value="ipv4"]')).toBeVisible();
|
||||
await expect(page.locator('input[name="iptype"][value="ipv6"]')).toBeVisible();
|
||||
});
|
||||
});
|
||||
36
zonemaster-gui/e2e/FR13.e2e-spec.ts
Normal file
36
zonemaster-gui/e2e/FR13.e2e-spec.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import {test, expect} from './global-setup';
|
||||
|
||||
import {goToHome, setLang, showOptions} from './utils/app.utils';
|
||||
|
||||
test.describe.serial('Zonemaster test FR13 - [The advanced view should support the possibility of enabling or disabling IPv4 or IPv6]', () => {
|
||||
test.beforeEach(async ({page}) => {
|
||||
await goToHome(page);
|
||||
await setLang(page, 'en');
|
||||
await page.waitForLoadState('networkidle');
|
||||
await showOptions(page);
|
||||
await page.waitForTimeout(400);
|
||||
});
|
||||
|
||||
test('should have [IPv4 and IPv6 radio] & [IPv4 only radio] & [IPv6 only radio] visible and disabled', async ({page}) => {
|
||||
await showOptions(page);
|
||||
await page.waitForTimeout(400);
|
||||
await expect(page.locator('input[name="iptype"][value="both"]')).toBeVisible();
|
||||
await expect(page.locator('input[name="iptype"][value="ipv4"]')).not.toBeChecked();
|
||||
await expect(page.locator('input[name="iptype"][value="ipv6"]')).not.toBeChecked();
|
||||
});
|
||||
|
||||
test('should be possible to enable [IPv4 only radio]', async ({page}) => {
|
||||
await page.locator('input[name="iptype"][value="ipv4"]').click();
|
||||
await expect(page.locator('input[name="iptype"][value="ipv4"]')).toBeChecked();
|
||||
});
|
||||
|
||||
test('should have [IPv6 only radio] visible and disabled', async ({ page }) => {
|
||||
await expect(page.locator('input[name="iptype"][value="ipv6"]')).toBeVisible();
|
||||
await expect(page.locator('input[name="iptype"][value="ipv6"]')).not.toBeChecked();
|
||||
});
|
||||
|
||||
test('should be possible to enable [IPv6 only]', async ({ page }) => {
|
||||
await page.locator('input[name="iptype"][value="ipv6"]').click();
|
||||
await expect(page.locator('input[name="iptype"][value="ipv6"]')).toBeChecked();
|
||||
});
|
||||
});
|
||||
38
zonemaster-gui/e2e/FR16.e2e-spec.ts
Normal file
38
zonemaster-gui/e2e/FR16.e2e-spec.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import {test, expect} from './global-setup';
|
||||
|
||||
import {goToHome, mounted, setLang, showOptions} from './utils/app.utils';
|
||||
|
||||
test.describe('Zonemaster test FR16 - [The advanced view should have a text describing what undelegated means]', () => {
|
||||
test.beforeEach(async ({page}) => {
|
||||
await goToHome(page);
|
||||
await setLang(page, 'en');
|
||||
await mounted(page);
|
||||
await showOptions(page);
|
||||
});
|
||||
|
||||
test('should have a link to the proper faq answer', async ({page}) => {
|
||||
await page.waitForTimeout(400);
|
||||
const alert = page.locator('#advanced-options div[role="alert"]');
|
||||
await expect(alert).toBeVisible();
|
||||
await expect(alert.locator('a')).toHaveAttribute('href', '/en/faq/#undelegated');
|
||||
});
|
||||
|
||||
test('should have a description text in multi languages', async ({page}) => {
|
||||
const testSuite = [
|
||||
{lang: 'en', text: 'undelegated'},
|
||||
{lang: 'fr', text: 'non délégué'},
|
||||
{lang: 'sv', text: 'odelegerat'},
|
||||
];
|
||||
|
||||
for (const {lang, text} of testSuite) {
|
||||
await setLang(page, lang);
|
||||
await mounted(page);
|
||||
await showOptions(page);
|
||||
await page.waitForTimeout(400);
|
||||
|
||||
const alert = page.locator('#advanced-options div[role="alert"]');
|
||||
|
||||
await expect(alert.locator('a')).toContainText(text);
|
||||
}
|
||||
});
|
||||
});
|
||||
49
zonemaster-gui/e2e/FR17.e2e-spec.ts
Normal file
49
zonemaster-gui/e2e/FR17.e2e-spec.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import {test, expect} from './global-setup';
|
||||
|
||||
import {goToHome, setLang, showOptions} from './utils/app.utils';
|
||||
|
||||
test.describe.serial('Zonemaster test FR17 - [Able to specify delegation parameters]', () => {
|
||||
test.beforeEach(async ({page}) => {
|
||||
await goToHome(page);
|
||||
await setLang(page, 'en');
|
||||
await page.waitForLoadState('networkidle');
|
||||
await showOptions(page);
|
||||
await page.waitForTimeout(400);
|
||||
});
|
||||
|
||||
test('should have one ns and digest form', async ({ page }) => {
|
||||
await expect(page.locator('fieldset.zm-domain-test__nameservers')).toHaveCount(1);
|
||||
await expect(page.locator('fieldset.zm-domain-test__records')).toHaveCount(1);
|
||||
await expect(page.locator('input[name="nameservers[0][ns]"]')).toHaveCount(1);
|
||||
await expect(page.locator('input[name="ds_info[0][keytag]"]')).toHaveCount(1);
|
||||
});
|
||||
|
||||
test('should be possible to add new ns form', async ({ page }) => {
|
||||
await page.locator('input[name="nameservers[0][ns]"]').first().focus();
|
||||
|
||||
await page.keyboard.type('ns2.nic.fr');
|
||||
|
||||
await expect(page.locator('input[name="nameservers[1][ns]"]')).toHaveCount(1);
|
||||
await expect(page.locator('input[name="ds_info[1][keytag]"]')).toHaveCount(0);
|
||||
});
|
||||
|
||||
test('should be possible to add new digest form', async ({ page }) => {
|
||||
await page.locator('input[name="ds_info[0][keytag]"]').first().focus();
|
||||
|
||||
await page.keyboard.type('12345');
|
||||
|
||||
await expect(page.locator('input[name="nameservers[1][ns]"]')).toHaveCount(0);
|
||||
await expect(page.locator('input[name="ds_info[1][keytag]"]')).toHaveCount(1);
|
||||
});
|
||||
|
||||
test('should be possible to delete ns forms', async ({ page }) => {
|
||||
await page.locator('input[name="nameservers[0][ns]"]').first().focus();
|
||||
|
||||
await page.keyboard.type('ns2.nic.fr');
|
||||
|
||||
await expect(page.locator('input[name="nameservers[1][ns]"]')).toHaveCount(1);
|
||||
|
||||
await page.locator('fieldset.zm-domain-test__nameserver > div > div > button').first().click();
|
||||
await expect(page.locator('input[name="nameservers[1][ns]"]')).toHaveCount(0);
|
||||
});
|
||||
});
|
||||
22
zonemaster-gui/e2e/FR18.e2e-spec.ts
Normal file
22
zonemaster-gui/e2e/FR18.e2e-spec.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import {test, expect} from './global-setup';
|
||||
|
||||
import {goToHome, setLang} from './utils/app.utils';
|
||||
|
||||
test.describe('Zonemaster test FR18 - [The GUI should be able to run tests by just providing the domain name]', () => {
|
||||
test.beforeEach(async ({page}) => {
|
||||
await goToHome(page);
|
||||
await setLang(page, 'en');
|
||||
});
|
||||
|
||||
test('should display progress bar', async ({page}) => {
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
await expect(page.locator('.zm-domain-test__progress-bar')).toHaveCount(0);
|
||||
await page.locator('input[name="domain"]').first().focus();
|
||||
|
||||
await page.keyboard.type('progress.afNiC.Fr');
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
await expect(page.locator('.zm-domain-test__progress-bar')).toHaveCount(1);
|
||||
});
|
||||
});
|
||||
41
zonemaster-gui/e2e/FR19.e2e-spec.ts
Normal file
41
zonemaster-gui/e2e/FR19.e2e-spec.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import {test, expect} from './global-setup';
|
||||
|
||||
import {goToHome, setLang, showOptions} from './utils/app.utils';
|
||||
|
||||
test.describe('Zonemaster test FR19 - [The GUI should be able to run the test with at least one name server as input]', () => {
|
||||
test.beforeEach(async ({page}) => {
|
||||
await goToHome(page);
|
||||
await setLang(page, 'en');
|
||||
await page.waitForLoadState('networkidle');
|
||||
await showOptions(page);
|
||||
});
|
||||
|
||||
test('should NOT display progress bar when we add a NS ip', async ({page}) => {
|
||||
await expect(page.locator('.zm-domain-test__progress-bar')).toHaveCount(0);
|
||||
|
||||
await page.locator('input[name="domain"]').first().focus();
|
||||
await page.keyboard.type('progress.afNiC.Fr');
|
||||
|
||||
await page.locator('input[name="nameservers[0][ip]"]').first().focus();
|
||||
await page.keyboard.type('192.134.4.1');
|
||||
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
await expect(page.locator('input[name="nameservers[0][ns]"]:invalid')).toHaveCount(1);
|
||||
await expect(page.locator('.zm-domain-test__progress-bar')).toHaveCount(0);
|
||||
});
|
||||
|
||||
test('should display progress bar when we add a NS name', async ({page}) => {
|
||||
await expect(page.locator('.zm-domain-test__progress-bar')).toHaveCount(0);
|
||||
|
||||
await page.locator('input[name="domain"]').first().focus();
|
||||
await page.keyboard.type('progress.afNiC.Fr');
|
||||
|
||||
await page.locator('input[name="nameservers[0][ns]"]').first().focus();
|
||||
await page.keyboard.type('ns1.nic.fr');
|
||||
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
await expect(page.locator('.zm-domain-test__progress-bar')).toHaveCount(1);
|
||||
});
|
||||
});
|
||||
32
zonemaster-gui/e2e/FR20.e2e-spec.ts
Normal file
32
zonemaster-gui/e2e/FR20.e2e-spec.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import {test, expect} from './global-setup';
|
||||
|
||||
import {goToHome, setLang, showOptions} from './utils/app.utils';
|
||||
|
||||
test.describe('Zonemaster test FR20 - [The user must be able to submit one or more DS record(s) for use with DNSSEC]', () => {
|
||||
test.beforeEach(async ({page}) => {
|
||||
await goToHome(page);
|
||||
await setLang(page, 'en');
|
||||
await page.waitForLoadState('networkidle');
|
||||
await showOptions(page);
|
||||
});
|
||||
|
||||
test('should display progress bar when we add a DS entry and launch a test', async ({page}) => {
|
||||
await expect(page.locator('.zm-domain-test__progress-bar')).toHaveCount(0);
|
||||
|
||||
await page.locator('input[name="domain"]').first().focus();
|
||||
|
||||
await page.keyboard.type('progress.afNiC.Fr');
|
||||
|
||||
await page.locator('input[name="ds_info[0][keytag]"]').first().focus();
|
||||
await page.keyboard.type('37610');
|
||||
|
||||
await page.locator('input[name="ds_info[0][digest]"]').first().focus();
|
||||
await page.keyboard.type('d2681e301f632bd76544e6d5b6631a12d97b5479ff07cd24efecd19203c77db3');
|
||||
|
||||
await page.locator('select[name="ds_info[0][algorithm]"]').first().selectOption({ label: '8 - RSASHA256' });
|
||||
await page.locator('select[name="ds_info[0][digtype]"]').first().selectOption({ label: '2 - SHA-256' });
|
||||
|
||||
await page.keyboard.press('Enter');
|
||||
await expect(page.locator('.zm-domain-test__progress-bar')).toHaveCount(1);
|
||||
});
|
||||
});
|
||||
55
zonemaster-gui/e2e/FR21.e2e-spec.ts
Normal file
55
zonemaster-gui/e2e/FR21.e2e-spec.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { test, expect } from './global-setup';
|
||||
import { goToHome, setLang, setupApiMocks } from './utils/app.utils';
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
test.describe.serial('Zonemaster test FR21 - [Able to provide a summarized result of the test being run ' +
|
||||
'(possibility in different colours for error, warning, success etc.)]', () => {
|
||||
|
||||
let page: Page;
|
||||
|
||||
// Keep the same page between tests
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
page = await browser.newPage();
|
||||
await setupApiMocks(page);
|
||||
await goToHome(page);
|
||||
await setLang(page, 'en');
|
||||
await page.waitForLoadState('networkidle');
|
||||
});
|
||||
|
||||
test('should display summary', async () => {
|
||||
await expect(page.locator('.zm-domain-test__progress-bar')).toHaveCount(0);
|
||||
await page.locator('input[name="domain"]').first().focus();
|
||||
|
||||
await page.keyboard.type('results.afNiC.Fr');
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
await expect(page.locator('.zm-result')).toBeVisible({ timeout: 10000 });
|
||||
|
||||
const messageCountBadges = page.locator('.zm-filter-toggle');
|
||||
const expectedLabels = ['All', 'Info', 'Notice', 'Warning', 'Error', 'Critical'];
|
||||
|
||||
await expect(messageCountBadges).toHaveCount(expectedLabels.length);
|
||||
|
||||
for (const [idx, label] of expectedLabels.entries()) {
|
||||
await expect(messageCountBadges.nth(idx)).toContainText(label);
|
||||
}
|
||||
});
|
||||
|
||||
test('should display number of each level', async () => {
|
||||
await expect(page.locator('.zm-filter-toggle__badge:not(:empty)')).toHaveCount(6);
|
||||
});
|
||||
|
||||
test('should display summary with good colors', async () => {
|
||||
const filterButtons = page.locator('.zm-filter-toggle input[type="checkbox"]');
|
||||
|
||||
for (const idx of [1, 2, 3, 4, 5]) {
|
||||
await filterButtons.nth(idx).click();
|
||||
}
|
||||
|
||||
// wait for .2 second (color transition)
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
|
||||
expect(await page.screenshot()).toMatchSnapshot('results.png');
|
||||
});
|
||||
});
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 102 KiB |
BIN
zonemaster-gui/e2e/FR21.e2e-spec.ts-snapshots/results.png
Normal file
BIN
zonemaster-gui/e2e/FR21.e2e-spec.ts-snapshots/results.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 107 KiB |
37
zonemaster-gui/e2e/FR22.e2e-spec.ts
Normal file
37
zonemaster-gui/e2e/FR22.e2e-spec.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { test, expect } from './global-setup';
|
||||
|
||||
import { goToHome, setLang } from './utils/app.utils';
|
||||
|
||||
test.describe('Zonemaster test FR22 - [Provide the possibility to see more information about encountered errors ' +
|
||||
'within the simple view]', () => {
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await goToHome(page);
|
||||
await setLang(page, 'en');
|
||||
await page.waitForLoadState('networkidle');
|
||||
});
|
||||
|
||||
test('can toggle modules', async ({ page }) => {
|
||||
await expect(page.locator('.zm-domain-test__progress-bar')).toHaveCount(0);
|
||||
await page.locator('input[name="domain"]').first().focus();
|
||||
|
||||
await page.keyboard.type('results.afNiC.Fr');
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
const basicHeader = page.locator('#zmModule-Basic .zm-result__module__title');
|
||||
const basicHeaderButton = page.locator('#zmModule-Basic .zm-result__module__title button');
|
||||
const basicContent = page.locator('#zmModule-Basic-content');
|
||||
|
||||
await expect(basicHeader).toBeVisible({ timeout: 10000 });
|
||||
await expect(basicHeader).toHaveText(/Basic/i);
|
||||
await expect(basicContent).toHaveCount(0);
|
||||
|
||||
await basicHeaderButton.click();
|
||||
|
||||
await expect(basicContent).toHaveCount(1);
|
||||
|
||||
await basicHeaderButton.click();
|
||||
|
||||
await expect(basicContent).toHaveCount(0);
|
||||
});
|
||||
});
|
||||
29
zonemaster-gui/e2e/FR23.e2e-spec.ts
Normal file
29
zonemaster-gui/e2e/FR23.e2e-spec.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { test, expect } from './global-setup';
|
||||
|
||||
import { setLang } from './utils/app.utils';
|
||||
|
||||
|
||||
test.describe('Zonemaster test FR23 - [Provide a list of previous runs for the domain and should be paginated]', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await setLang(page, 'en');
|
||||
await page.waitForLoadState('networkidle');
|
||||
});
|
||||
|
||||
test('should display previous tests', async ({ page }) => {
|
||||
await page.locator('input[name="domain"]').first().focus();
|
||||
|
||||
await page.keyboard.type('results.afNiC.Fr');
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
const historyButton = page.locator('#zmHistoryButton');
|
||||
|
||||
await expect(historyButton).toBeVisible({ timeout: 10000 });
|
||||
await expect(historyButton).toHaveText('History');
|
||||
await historyButton.click();
|
||||
await expect(page.locator('#historyDialog')).toBeVisible({ timeout: 10000 });
|
||||
|
||||
await expect(page.locator('#historyDialog li:first-child')).toHaveCount(1);
|
||||
await expect(page.locator('#historyDialog footer')).toHaveCount(1);
|
||||
});
|
||||
});
|
||||
32
zonemaster-gui/e2e/FR25.e2e-spec.ts
Normal file
32
zonemaster-gui/e2e/FR25.e2e-spec.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { test, expect } from './global-setup';
|
||||
|
||||
import { setLang } from './utils/app.utils';
|
||||
|
||||
test.describe('Zonemaster test FR25 - [Should be able to export the result in multiple formats (HTML, CSV, JSON, TEXT)]', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await setLang(page, 'en');
|
||||
await page.waitForLoadState('networkidle');
|
||||
});
|
||||
|
||||
test('should have an export button', async ({ page }) => {
|
||||
await page.locator('input[name="domain"]').first().focus();
|
||||
|
||||
await page.keyboard.type('results.afNiC.Fr');
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
const exportButton = page.locator('#zmExportButton');
|
||||
const exportContent = page.locator('#zmExportDialog');
|
||||
|
||||
await expect(exportButton).toBeVisible({ timeout: 10000 });
|
||||
await expect(exportButton).toHaveText('Export');
|
||||
await expect(exportContent).toBeHidden();
|
||||
await exportButton.click();
|
||||
await expect(exportContent).toBeVisible({ timeout: 1000 });
|
||||
|
||||
await expect(page.locator('#zmExportDialog button:nth-child(1)')).toHaveText('JSON');
|
||||
await expect(page.locator('#zmExportDialog button:nth-child(2)')).toHaveText('HTML');
|
||||
await expect(page.locator('#zmExportDialog button:nth-child(3)')).toHaveText('CSV');
|
||||
await expect(page.locator('#zmExportDialog button:nth-child(4)')).toHaveText('Text');
|
||||
});
|
||||
});
|
||||
18
zonemaster-gui/e2e/example.spec.ts
Normal file
18
zonemaster-gui/e2e/example.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test('has title', async ({ page }) => {
|
||||
await page.goto('https://playwright.dev/');
|
||||
|
||||
// Expect a title "to contain" a substring.
|
||||
await expect(page).toHaveTitle(/Playwright/);
|
||||
});
|
||||
|
||||
test('get started link', async ({ page }) => {
|
||||
await page.goto('https://playwright.dev/');
|
||||
|
||||
// Click the get started link.
|
||||
await page.getByRole('link', { name: 'Get started' }).click();
|
||||
|
||||
// Expects page to have a heading with the name of Installation.
|
||||
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
|
||||
});
|
||||
19
zonemaster-gui/e2e/global-setup.ts
Normal file
19
zonemaster-gui/e2e/global-setup.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { test as base } from '@playwright/test';
|
||||
import { setupApiMocks } from './utils/app.utils';
|
||||
|
||||
/**
|
||||
* Global test setup that runs before each test
|
||||
* - Sets up API mocking to avoid needing a real backend
|
||||
* - Waits for network to be idle before proceeding
|
||||
*/
|
||||
export const test = base.extend({
|
||||
page: async ({ page }, use) => {
|
||||
// Setup API mocks for all tests
|
||||
await setupApiMocks(page);
|
||||
|
||||
// Use the page in the test
|
||||
await use(page);
|
||||
},
|
||||
});
|
||||
|
||||
export { expect } from '@playwright/test';
|
||||
959
zonemaster-gui/e2e/interceptors/mock.interceptor.ts
Normal file
959
zonemaster-gui/e2e/interceptors/mock.interceptor.ts
Normal file
@@ -0,0 +1,959 @@
|
||||
/**
|
||||
* Mock API interceptor for Playwright E2E tests
|
||||
*
|
||||
* This module provides mock responses for API calls to avoid needing a real backend during tests.
|
||||
* Migrated from Angular HttpInterceptor to work with Playwright's route interception.
|
||||
*
|
||||
* Usage in tests:
|
||||
* ```typescript
|
||||
* import { setupApiMocks } from './utils/app.utils';
|
||||
*
|
||||
* test.beforeEach(async ({ page }) => {
|
||||
* await setupApiMocks(page);
|
||||
* await page.goto('/');
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
|
||||
export interface MockEndpoint {
|
||||
url: string;
|
||||
body: any;
|
||||
method: string;
|
||||
json: any;
|
||||
}
|
||||
|
||||
const urls: MockEndpoint[] = [
|
||||
// Version info
|
||||
{
|
||||
url: 'http://localhost:4321/api',
|
||||
body: {jsonrpc: '2.0', id: 1643203570632, method:'version_info', params: {}},
|
||||
method: 'POST',
|
||||
json: {jsonrpc: '2.0', id: 1643203570632, result: {zonemaster_engine: 'e2e-test', zonemaster_backend: 'e2e-test', zonemaster_ldns: 'e2e-test'}}
|
||||
},
|
||||
|
||||
// Profile list in option
|
||||
{
|
||||
url: 'http://localhost:4321/api',
|
||||
body: {jsonrpc: '2.0', id:1643203351479, method: 'profile_names', params: {}},
|
||||
method: 'POST',
|
||||
json: {jsonrpc: '2.0', id: 1643203351479, result: ["default", "test_profile"]}
|
||||
},
|
||||
|
||||
// FR18 - Should display progress bar
|
||||
// FR26 - Should display progress bar
|
||||
{
|
||||
url: 'http://localhost:4321/api',
|
||||
body: {'jsonrpc': '2.0', 'id': 1572254767685, 'method': 'start_domain_test', 'params':
|
||||
{
|
||||
'language':'en', 'domain': 'progress.afNiC.Fr', 'profile': 'default',
|
||||
'nameservers': [], 'ds_info': []
|
||||
}
|
||||
},
|
||||
method: 'POST',
|
||||
json: {'jsonrpc': '2.0', 'id': 1572254767685, 'result': '2005cf23e9fb24b6'}
|
||||
},
|
||||
|
||||
// FR19 - Should display progress bar when we add a NS name
|
||||
{
|
||||
url: 'http://localhost:4321/api',
|
||||
body: {'jsonrpc': '2.0', 'id': 1572254767685, 'method': 'start_domain_test', 'params':
|
||||
{
|
||||
'language':'en', 'domain': 'progress.afNiC.Fr', 'profile': 'default',
|
||||
'nameservers': [{"ns": "ns1.nic.fr"}], 'ds_info': []
|
||||
}
|
||||
},
|
||||
method: 'POST',
|
||||
json: {'jsonrpc': '2.0', 'id': 1572254767685, 'result': '2005cf23e9fb24b6'}
|
||||
},
|
||||
|
||||
// FR19 - should NOT display progress bar when we add a NS ip
|
||||
{
|
||||
url: 'http://localhost:4321/api',
|
||||
body: {'jsonrpc': '2.0', 'id': 1572254767685, 'method': 'start_domain_test', 'params':
|
||||
{
|
||||
'language':'en', 'domain': 'progress.afNiC.Fr', 'profile': 'default',
|
||||
'nameservers': [{"ns":"", "ip": "192.134.4.1"}], 'ds_info': []
|
||||
}
|
||||
},
|
||||
method: 'POST',
|
||||
json: {
|
||||
"jsonrpc": "2.0",
|
||||
"error": {
|
||||
"message": "Invalid method parameter(s).",
|
||||
"code": "-32602",
|
||||
"data": [
|
||||
{
|
||||
"path": "/nameservers/0/ns",
|
||||
"message": "The domain name character(s) are not supported"
|
||||
}
|
||||
]
|
||||
},
|
||||
"id": 1572254767685
|
||||
}
|
||||
},
|
||||
|
||||
// FR20 - should display progress bar when we add a DS entry and launch a test
|
||||
{
|
||||
url: 'http://localhost:4321/api',
|
||||
body:{'jsonrpc': '2.0', 'id': 1572277567967, 'method': 'start_domain_test', 'params':
|
||||
{
|
||||
'language':'en', 'domain': 'progress.afNiC.Fr', 'profile': 'default',
|
||||
'nameservers': [], 'ds_info': [{
|
||||
"keytag": 37610,
|
||||
"algorithm":8,
|
||||
"digtype":2,
|
||||
"digest":"d2681e301f632bd76544e6d5b6631a12d97b5479ff07cd24efecd19203c77db3"
|
||||
}]
|
||||
}
|
||||
},
|
||||
method: 'POST',
|
||||
json: {'jsonrpc': '2.0', 'id': 1572277567967, 'result': '2005cf23e9fb24b6'}
|
||||
},
|
||||
|
||||
// FR18 - Should display progress bar
|
||||
// FR19 - Should display progress bar when we add a NS name
|
||||
// FR20 - should display progress bar when we add a DS entry and launch a test
|
||||
// FR26 - Should display progress bar
|
||||
{
|
||||
url: 'http://localhost:4321/api',
|
||||
body: {'jsonrpc': '2.0', 'id': 1572254972236, 'method': 'test_progress', 'params': {'test_id': '2005cf23e9fb24b6'}},
|
||||
method: 'POST',
|
||||
json: {'jsonrpc': '2.0', 'id': 1572254972236, 'result': 50}
|
||||
},
|
||||
|
||||
|
||||
// FR21 - Should display summary
|
||||
// FR22 - Should display full messages
|
||||
{
|
||||
url: 'http://localhost:4321/api',
|
||||
body: {'jsonrpc': '2.0', 'id': 1572254767685, 'method': 'start_domain_test', 'params':
|
||||
{
|
||||
'language':'en', 'domain': 'results.afNiC.Fr', 'profile': 'default',
|
||||
'nameservers': [], 'ds_info': []
|
||||
}
|
||||
},
|
||||
method: 'POST',
|
||||
json: {'jsonrpc': '2.0', 'id': 1572254767685, 'result': '226f6d4f44ae3f80'}
|
||||
},
|
||||
|
||||
{
|
||||
url: 'http://localhost:4321/api',
|
||||
body: {'jsonrpc': '2.0', 'id': 1572254767685, 'method': 'start_domain_test', 'params':
|
||||
{
|
||||
'language':'en', 'domain': 'empty-results.afNiC.Fr', 'profile': 'default',
|
||||
'nameservers': [], 'ds_info': []
|
||||
}
|
||||
},
|
||||
method: 'POST',
|
||||
json: {'jsonrpc': '2.0', 'id': 1572254767685, 'result': 'a0fbcbf6c5ff5842'}
|
||||
},
|
||||
|
||||
// FR21 - Should display summary
|
||||
// FR22 - Should display full messages
|
||||
{
|
||||
url: 'http://localhost:4321/api',
|
||||
body: {'jsonrpc': '2.0', 'id': 1572254972236, 'method': 'test_progress', 'params': {'test_id': '226f6d4f44ae3f80'}},
|
||||
method: 'POST',
|
||||
json: {'jsonrpc': '2.0', 'id': 1572254972236, 'result': 100}
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
url: 'http://localhost:4321/api',
|
||||
body: {'jsonrpc': '2.0', 'id': 1572254972236, 'method': 'test_progress', 'params': {'test_id': 'a0fbcbf6c5ff5842'}},
|
||||
method: 'POST',
|
||||
json: {'jsonrpc': '2.0', 'id': 1572254972236, 'result': 100}
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
url: 'http://localhost:4321/api',
|
||||
body: {'jsonrpc': '2.0', 'id': 1572254972327, 'method': 'get_test_results', 'params': {'id': 'a0fbcbf6c5ff5842', 'language': 'en'}},
|
||||
method: 'POST',
|
||||
json: {'jsonrpc': '2.0', 'id': 1572254972327, 'result': {
|
||||
'params': {'profile' : 'default', 'priority': 10, 'ipv6': true, 'ipv4': true, 'client_id': 'Zonemaster GUI',
|
||||
'nameservers': [], 'ds_info': [], 'domain': 'empty-results.afNiC.Fr', 'queue': 0, 'client_version': '3.1.0'
|
||||
}, 'hash_id': 'a0fbcbf6c5ff5842', 'created_at': '2019-10-28T09:29:26Z', 'creation_time': '2019-10-28 09:29:26.288692', 'id': 49640, 'results':[]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// FR21 - Should display summary
|
||||
// FR22 - Should display full messages
|
||||
|
||||
// FR23 - Should display previous tests
|
||||
// FR24 - Should display previous run link
|
||||
// FR25 - Should have an export button
|
||||
// FR25 - Should open a modal that contains four export possibilities
|
||||
{
|
||||
url: 'http://localhost:4321/api',
|
||||
body: {'jsonrpc': '2.0', 'id': 1572254972327, 'method': 'get_test_results', 'params': {'id': '226f6d4f44ae3f80', 'language': 'en'}},
|
||||
method: 'POST',
|
||||
json: {'jsonrpc': '2.0', 'id': 1572254972327, 'result': {
|
||||
'params': {
|
||||
'profile' : 'default',
|
||||
'priority': 10,
|
||||
'ipv6': true,
|
||||
'ipv4': true,
|
||||
'client_id': 'Zonemaster GUI',
|
||||
'nameservers': [],
|
||||
'ds_info': [],
|
||||
'domain': 'results.afNiC.Fr',
|
||||
'queue': 0,
|
||||
'client_version': '3.6.1'
|
||||
},
|
||||
'hash_id': 'efd1dedc98d456bf',
|
||||
'created_at': '2022-11-23T16:38:17Z',
|
||||
'creation_time': '2022-11-23 16:38:17',
|
||||
'id': 49640,
|
||||
"testcase_descriptions": {
|
||||
"CONSISTENCY04": "Name server NS consistency",
|
||||
"ZONE08": "MX is not an alias",
|
||||
"DNSSEC10": "Zone contains NSEC or NSEC3 records",
|
||||
"NAMESERVER07": "To check whether authoritative name servers return an upward referral",
|
||||
"UNSPECIFIED": "UNSPECIFIED",
|
||||
"CONSISTENCY06": "SOA MNAME consistency",
|
||||
"NAMESERVER04": "Same source address",
|
||||
"ZONE10": "No multiple SOA records",
|
||||
"SYNTAX08": "MX name must have a valid hostname",
|
||||
"SYNTAX05": "Misuse of '@' character in the SOA RNAME field",
|
||||
"ZONE05": "SOA 'expire' minimum value",
|
||||
"NAMESERVER08": "Testing QNAME case insensitivity",
|
||||
"CONNECTIVITY03": "AS Diversity",
|
||||
"NAMESERVER02": "Test of EDNS0 support",
|
||||
"NAMESERVER05": "Behaviour against AAAA query",
|
||||
"BASIC01": "The domain must have a parent domain",
|
||||
"SYNTAX01": "No illegal characters in the domain name",
|
||||
"CONSISTENCY01": "SOA serial number consistency",
|
||||
"DELEGATION06": "Existence of SOA",
|
||||
"SYNTAX02": "No hyphen ('-') at the start or end of the domain name",
|
||||
"SYNTAX04": "The NS name must have a valid domain/hostname",
|
||||
"DELEGATION01": "Minimum number of name servers",
|
||||
"ZONE04": "SOA 'retry' at least 1 hour",
|
||||
"CONSISTENCY02": "SOA RNAME consistency",
|
||||
"NAMESERVER03": "Test availability of zone transfer (AXFR)",
|
||||
"ADDRESS01": "Name server address must be globally routable",
|
||||
"CONSISTENCY03": "SOA timers consistency",
|
||||
"DNSSEC15": "Existence of CDS and CDNSKEY",
|
||||
"ADDRESS03": "Reverse DNS entry matches name server name",
|
||||
"NAMESERVER09": "Testing QNAME case sensitivity",
|
||||
"DNSSEC04": "Check for too short or too long RRSIG lifetimes",
|
||||
"DELEGATION02": "Name servers must have distinct IP addresses",
|
||||
"ADDRESS02": "Reverse DNS entry exists for name server IP address",
|
||||
"DELEGATION05": "Name server must not point at CNAME alias",
|
||||
"CONSISTENCY05": "Consistency between glue and authoritative data",
|
||||
"SYNTAX03": "There must be no double hyphen ('--') in position 3 and 4 of the domain name",
|
||||
"ZONE01": "Fully qualified master nameserver in SOA",
|
||||
"ZONE03": "SOA 'retry' lower than 'refresh'",
|
||||
"ZONE09": "MX record present",
|
||||
"ZONE07": "SOA master is not an alias",
|
||||
"DELEGATION07": "Parent glue name records present in child",
|
||||
"SYNTAX07": "No illegal characters in the SOA MNAME field",
|
||||
"DELEGATION04": "Name server is authoritative",
|
||||
"SYNTAX06": "No illegal characters in the SOA RNAME field",
|
||||
"NAMESERVER01": "A name server should not be a recursor",
|
||||
"DELEGATION03": "No truncation of referrals",
|
||||
"DNSSEC05": "Check for invalid DNSKEY algorithms",
|
||||
"ZONE06": "SOA 'minimum' maximum value",
|
||||
"ZONE02": "SOA 'refresh' minimum value",
|
||||
"BASIC02": "The domain must have at least one working name server",
|
||||
"NAMESERVER06": "NS can be resolved"
|
||||
},
|
||||
'results': [
|
||||
{
|
||||
"message": "Using version v4.5.1 of the Zonemaster engine.\n",
|
||||
"module": "SYSTEM",
|
||||
"testcase": "UNSPECIFIED",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"testcase": "BASIC01",
|
||||
"level": "INFO",
|
||||
"module": "Basic",
|
||||
"message": "Parent domain 'fr' was found for the tested domain.\n"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "BASIC02",
|
||||
"message": "Nameserver ns1.nic.fr/192.134.4.1 listed these servers as glue: ns1.nic.fr., ns2.nic.fr., ns3.nic.fr..\n",
|
||||
"module": "BASIC"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "BASIC02",
|
||||
"module": "Basic",
|
||||
"message": "Nameserver ns1.nic.fr/2001:67c:2218:2::4:1 listed these servers as glue: ns1.nic.fr., ns2.nic.fr., ns3.nic.fr..\n"
|
||||
},
|
||||
{
|
||||
"module": "Basic",
|
||||
"message": "Nameserver ns2.nic.fr/192.93.0.4 listed these servers as glue: ns1.nic.fr., ns2.nic.fr., ns3.nic.fr..\n",
|
||||
"testcase": "BASIC02",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "BASIC02",
|
||||
"message": "Nameserver ns2.nic.fr/2001:660:3005:1::1:2 listed these servers as glue: ns1.nic.fr., ns2.nic.fr., ns3.nic.fr..\n",
|
||||
"module": "BASIC"
|
||||
},
|
||||
{
|
||||
"message": "Nameserver ns3.nic.fr/192.134.0.49 listed these servers as glue: ns1.nic.fr., ns2.nic.fr., ns3.nic.fr..\n",
|
||||
"module": "Basic",
|
||||
"testcase": "BASIC02",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"module": "Basic",
|
||||
"message": "Nameserver ns3.nic.fr/2001:660:3006:1::1:1 listed these servers as glue: ns1.nic.fr., ns2.nic.fr., ns3.nic.fr..\n",
|
||||
"level": "INFO",
|
||||
"testcase": "BASIC02"
|
||||
},
|
||||
{
|
||||
"module": "Basic",
|
||||
"message": "Functional nameserver found. \"A\" query for www.afnic.fr test skipped.\n",
|
||||
"testcase": "UNSPECIFIED",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"module": "ADDRESS",
|
||||
"message": "All Nameserver addresses are in the routable public addressing space.\n",
|
||||
"level": "INFO",
|
||||
"testcase": "ADDRESS01"
|
||||
},
|
||||
{
|
||||
"module": "ADDRESS",
|
||||
"message": "Reverse DNS entry exists for each Nameserver IP address.\n",
|
||||
"testcase": "ADDRESS02",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"message": "Every reverse DNS entry matches name server name.\n",
|
||||
"module": "ADDRESS",
|
||||
"testcase": "ADDRESS03",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"module": "CONNECTIVITY",
|
||||
"message": "At least two IPv4 addresses of the authoritative nameservers are announce by different AS sets. A merged list of all AS: (\"2485, \"2486).\n",
|
||||
"testcase": "CONNECTIVITY03",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"module": "CONNECTIVITY",
|
||||
"message": "At least two IPv6 addresses of the authoritative nameservers are announce by different AS sets. A merged list of all AS: (\"2486, \"2485).\n",
|
||||
"level": "INFO",
|
||||
"testcase": "CONNECTIVITY03"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "CONSISTENCY01",
|
||||
"module": "CONSISTENCY",
|
||||
"message": "Saw SOA serial number 2022112200 on following nameserver set : ns1.nic.fr/192.134.4.1; ns1.nic.fr/2001:67c:2218:2::4:1; ns2.nic.fr/192.93.0.4; ns2.nic.fr/2001:660:3005:1::1:2; ns3.nic.fr/192.134.0.49; ns3.nic.fr/2001:660:3006:1::1:1.\n"
|
||||
},
|
||||
{
|
||||
"message": "A single SOA serial number was found (2022112200).\n",
|
||||
"module": "CONSISTENCY",
|
||||
"testcase": "CONSISTENCY01",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"testcase": "CONSISTENCY02",
|
||||
"level": "INFO",
|
||||
"message": "A single SOA rname value was found (hostmaster.nic.fr.).\n",
|
||||
"module": "CONSISTENCY"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "CONSISTENCY03",
|
||||
"module": "CONSISTENCY",
|
||||
"message": "A single SOA time parameter set was seen (REFRESH=7200, RETRY=1800, EXPIRE=2419200, MINIMUM=5400).\n"
|
||||
},
|
||||
{
|
||||
"testcase": "CONSISTENCY04",
|
||||
"level": "INFO",
|
||||
"message": "A single NS set was found (ns1.nic.fr.; ns2.nic.fr.; ns3.nic.fr.).\n",
|
||||
"module": "CONSISTENCY"
|
||||
},
|
||||
{
|
||||
"message": "Glue records are consistent between glue and authoritative data.\n",
|
||||
"module": "CONSISTENCY",
|
||||
"level": "INFO",
|
||||
"testcase": "CONSISTENCY05"
|
||||
},
|
||||
{
|
||||
"message": "A single SOA mname value was seen (dnsmaster.nic.fr.).\n",
|
||||
"module": "CONSISTENCY",
|
||||
"level": "INFO",
|
||||
"testcase": "CONSISTENCY06"
|
||||
},
|
||||
{
|
||||
"module": "DELEGATION",
|
||||
"message": "Parent lists enough (3) nameservers (ns1.nic.fr; ns2.nic.fr; ns3.nic.fr). Lower limit set to 2.\n",
|
||||
"level": "INFO",
|
||||
"testcase": "DELEGATION01"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "DELEGATION01",
|
||||
"message": "Child lists enough (3) nameservers (ns1.nic.fr; ns2.nic.fr; ns3.nic.fr). Lower limit set to 2.\n",
|
||||
"module": "DELEGATION"
|
||||
},
|
||||
{
|
||||
"module": "DELEGATION",
|
||||
"message": "Child lists enough (3) nameservers (ns1.nic.fr; ns2.nic.fr; ns3.nic.fr) that resolve to IPv4 addresses (192.134.0.49; 192.134.4.1; 192.93.0.4). Lower limit set to 2.\n",
|
||||
"testcase": "DELEGATION01",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "DELEGATION01",
|
||||
"module": "DELEGATION",
|
||||
"message": "Child lists enough (3) nameservers (ns1.nic.fr; ns2.nic.fr; ns3.nic.fr) that resolve to IPv6 addresses (2001:660:3005:1::1:2; 2001:660:3006:1::1:1; 2001:67c:2218:2::4:1). Lower limit set to 2.\n"
|
||||
},
|
||||
{
|
||||
"testcase": "DELEGATION01",
|
||||
"level": "INFO",
|
||||
"message": "Delegation lists enough (3) nameservers (ns1.nic.fr; ns2.nic.fr; ns3.nic.fr) that resolve to IPv4 addresses (192.134.0.49; 192.134.4.1; 192.93.0.4). Lower limit set to 2.\n",
|
||||
"module": "DELEGATION"
|
||||
},
|
||||
{
|
||||
"message": "Delegation lists enough (3) nameservers (ns1.nic.fr; ns2.nic.fr; ns3.nic.fr) that resolve to IPv6 addresses (2001:660:3005:1::1:2; 2001:660:3006:1::1:1; 2001:67c:2218:2::4:1). Lower limit set to 2.\n",
|
||||
"module": "DELEGATION",
|
||||
"level": "INFO",
|
||||
"testcase": "DELEGATION01"
|
||||
},
|
||||
{
|
||||
"message": "All the IP addresses used by the nameservers in parent are unique.\n",
|
||||
"module": "DELEGATION",
|
||||
"level": "INFO",
|
||||
"testcase": "DELEGATION02"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "DELEGATION02",
|
||||
"message": "All the IP addresses used by the nameservers in child are unique.\n",
|
||||
"module": "DELEGATION"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "DELEGATION02",
|
||||
"module": "DELEGATION",
|
||||
"message": "All the IP addresses used by the nameservers are unique.\n"
|
||||
},
|
||||
{
|
||||
"testcase": "DELEGATION03",
|
||||
"level": "INFO",
|
||||
"module": "DELEGATION",
|
||||
"message": "The smallest possible legal referral packet is smaller than 513 octets (it is 373).\n"
|
||||
},
|
||||
{
|
||||
"module": "DELEGATION",
|
||||
"message": "All these nameservers are confirmed to be authoritative : ns1.nic.fr; ns2.nic.fr; ns3.nic.fr.\n",
|
||||
"testcase": "DELEGATION04",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"testcase": "DELEGATION05",
|
||||
"level": "INFO",
|
||||
"module": "DELEGATION",
|
||||
"message": "No nameserver points to CNAME alias.\n"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "DELEGATION06",
|
||||
"message": "All the nameservers have SOA record.\n",
|
||||
"module": "DELEGATION"
|
||||
},
|
||||
{
|
||||
"module": "DELEGATION",
|
||||
"message": "All of the nameserver names are listed both at parent and child.\n",
|
||||
"testcase": "DELEGATION07",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"message": "RRSIG with keytag 53080 and covering type(s) DNSKEY expires at : Wed Dec 21 20:36:15 2022.\n",
|
||||
"module": "DNSSEC",
|
||||
"level": "INFO",
|
||||
"testcase": "DNSSEC04"
|
||||
},
|
||||
{
|
||||
"message": "RRSIG with keytag 15756 and covering type(s) SOA expires at : Wed Dec 21 12:48:04 2022.\n",
|
||||
"module": "DNSSEC",
|
||||
"testcase": "DNSSEC04",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"module": "DNSSEC",
|
||||
"message": "The DNSKEY with tag 53080 uses algorithm number 13 (ECDSA Curve P-256 with SHA-256), which is OK.\n",
|
||||
"testcase": "DNSSEC05",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"testcase": "DNSSEC05",
|
||||
"level": "INFO",
|
||||
"module": "DNSSEC",
|
||||
"message": "The DNSKEY with tag 15756 uses algorithm number 13 (ECDSA Curve P-256 with SHA-256), which is OK.\n"
|
||||
},
|
||||
{
|
||||
"testcase": "DNSSEC05",
|
||||
"level": "INFO",
|
||||
"module": "DNSSEC",
|
||||
"message": "The DNSKEY with tag 53080 uses algorithm number 13 (ECDSA Curve P-256 with SHA-256), which is OK.\n"
|
||||
},
|
||||
{
|
||||
"message": "The DNSKEY with tag 15756 uses algorithm number 13 (ECDSA Curve P-256 with SHA-256), which is OK.\n",
|
||||
"module": "DNSSEC",
|
||||
"testcase": "DNSSEC05",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"message": "The DNSKEY with tag 53080 uses algorithm number 13 (ECDSA Curve P-256 with SHA-256), which is OK.\n",
|
||||
"module": "DNSSEC",
|
||||
"level": "INFO",
|
||||
"testcase": "DNSSEC05"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "DNSSEC05",
|
||||
"module": "DNSSEC",
|
||||
"message": "The DNSKEY with tag 15756 uses algorithm number 13 (ECDSA Curve P-256 with SHA-256), which is OK.\n"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "DNSSEC05",
|
||||
"module": "DNSSEC",
|
||||
"message": "The DNSKEY with tag 15756 uses algorithm number 13 (ECDSA Curve P-256 with SHA-256), which is OK.\n"
|
||||
},
|
||||
{
|
||||
"testcase": "DNSSEC05",
|
||||
"level": "INFO",
|
||||
"message": "The DNSKEY with tag 53080 uses algorithm number 13 (ECDSA Curve P-256 with SHA-256), which is OK.\n",
|
||||
"module": "DNSSEC"
|
||||
},
|
||||
{
|
||||
"module": "DNSSEC",
|
||||
"message": "The DNSKEY with tag 53080 uses algorithm number 13 (ECDSA Curve P-256 with SHA-256), which is OK.\n",
|
||||
"testcase": "DNSSEC05",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"testcase": "DNSSEC05",
|
||||
"level": "INFO",
|
||||
"message": "The DNSKEY with tag 15756 uses algorithm number 13 (ECDSA Curve P-256 with SHA-256), which is OK.\n",
|
||||
"module": "DNSSEC"
|
||||
},
|
||||
{
|
||||
"module": "DNSSEC",
|
||||
"message": "The DNSKEY with tag 53080 uses algorithm number 13 (ECDSA Curve P-256 with SHA-256), which is OK.\n",
|
||||
"level": "INFO",
|
||||
"testcase": "DNSSEC05"
|
||||
},
|
||||
{
|
||||
"module": "DNSSEC",
|
||||
"message": "The DNSKEY with tag 15756 uses algorithm number 13 (ECDSA Curve P-256 with SHA-256), which is OK.\n",
|
||||
"level": "INFO",
|
||||
"testcase": "DNSSEC05"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "DNSSEC10",
|
||||
"message": "The zone has NSEC3 records. Fetched from the nameservers with IP addresses \"192.134.0.49; 192.134.4.1; 192.93.0.4; 2001:660:3005:1::1:2; 2001:660:3006:1::1:1; 2001:67c:2218:2::4:1\".\n",
|
||||
"module": "DNSSEC"
|
||||
},
|
||||
{
|
||||
"module": "DNSSEC",
|
||||
"message": "No CDS or CDNSKEY RRsets are found on any name server.\n",
|
||||
"testcase": "DNSSEC15",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"message": "Nameserver ns1.nic.fr/192.134.4.1 is not a recursor.\n",
|
||||
"module": "NAMESERVER",
|
||||
"ns": "ns1.nic.fr/192.134.4.1",
|
||||
"testcase": "NAMESERVER01",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"testcase": "NAMESERVER01",
|
||||
"level": "INFO",
|
||||
"ns": "ns1.nic.fr/2001:67c:2218:2::4:1",
|
||||
"module": "NAMESERVER",
|
||||
"message": "Nameserver ns1.nic.fr/2001:67c:2218:2::4:1 is not a recursor.\n"
|
||||
},
|
||||
{
|
||||
"message": "Nameserver ns2.nic.fr/192.93.0.4 is not a recursor.\n",
|
||||
"module": "NAMESERVER",
|
||||
"testcase": "NAMESERVER01",
|
||||
"ns": "ns2.nic.fr/192.93.0.4",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"ns": "ns2.nic.fr/2001:660:3005:1::1:2",
|
||||
"testcase": "NAMESERVER01",
|
||||
"level": "INFO",
|
||||
"module": "NAMESERVER",
|
||||
"message": "Nameserver ns2.nic.fr/2001:660:3005:1::1:2 is not a recursor.\n"
|
||||
},
|
||||
{
|
||||
"module": "NAMESERVER",
|
||||
"message": "Nameserver ns3.nic.fr/192.134.0.49 is not a recursor.\n",
|
||||
"testcase": "NAMESERVER01",
|
||||
"level": "INFO",
|
||||
"ns": "ns3.nic.fr/192.134.0.49"
|
||||
},
|
||||
{
|
||||
"message": "Nameserver ns3.nic.fr/2001:660:3006:1::1:1 is not a recursor.\n",
|
||||
"module": "NAMESERVER",
|
||||
"testcase": "NAMESERVER01",
|
||||
"level": "INFO",
|
||||
"ns": "ns3.nic.fr/2001:660:3006:1::1:1"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "NAMESERVER02",
|
||||
"ns": "All",
|
||||
"message": "The following nameservers support EDNS0 : ns1.nic.fr/2001:67c:2218:2::4:1; ns3.nic.fr/192.134.0.49; ns1.nic.fr/192.134.4.1; ns3.nic.fr/2001:660:3006:1::1:1; ns2.nic.fr/192.93.0.4; ns2.nic.fr/2001:660:3005:1::1:2.\n",
|
||||
"module": "NAMESERVER"
|
||||
},
|
||||
{
|
||||
"module": "NAMESERVER",
|
||||
"message": "AXFR not available on nameserver ns1.nic.fr/192.134.4.1.\n",
|
||||
"testcase": "NAMESERVER03",
|
||||
"level": "INFO",
|
||||
"ns": "ns1.nic.fr/192.134.4.1"
|
||||
},
|
||||
{
|
||||
"ns": "ns1.nic.fr/2001:67c:2218:2::4:1",
|
||||
"testcase": "NAMESERVER03",
|
||||
"level": "INFO",
|
||||
"module": "NAMESERVER",
|
||||
"message": "AXFR not available on nameserver ns1.nic.fr/2001:67c:2218:2::4:1.\n"
|
||||
},
|
||||
{
|
||||
"message": "AXFR not available on nameserver ns2.nic.fr/192.93.0.4.\n",
|
||||
"module": "NAMESERVER",
|
||||
"level": "INFO",
|
||||
"testcase": "NAMESERVER03",
|
||||
"ns": "ns2.nic.fr/192.93.0.4"
|
||||
},
|
||||
{
|
||||
"testcase": "NAMESERVER03",
|
||||
"ns": "ns2.nic.fr/2001:660:3005:1::1:2",
|
||||
"level": "INFO",
|
||||
"message": "AXFR not available on nameserver ns2.nic.fr/2001:660:3005:1::1:2.\n",
|
||||
"module": "NAMESERVER"
|
||||
},
|
||||
{
|
||||
"testcase": "NAMESERVER03",
|
||||
"ns": "ns3.nic.fr/192.134.0.49",
|
||||
"level": "INFO",
|
||||
"module": "NAMESERVER",
|
||||
"message": "AXFR not available on nameserver ns3.nic.fr/192.134.0.49.\n"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "NAMESERVER03",
|
||||
"ns": "ns3.nic.fr/2001:660:3006:1::1:1",
|
||||
"message": "AXFR not available on nameserver ns3.nic.fr/2001:660:3006:1::1:1.\n",
|
||||
"module": "NAMESERVER"
|
||||
},
|
||||
{
|
||||
"testcase": "NAMESERVER04",
|
||||
"ns": "All",
|
||||
"level": "INFO",
|
||||
"message": "All nameservers reply with same IP used to query them.\n",
|
||||
"module": "NAMESERVER"
|
||||
},
|
||||
{
|
||||
"message": "The following nameservers answer AAAA queries without problems : ns3.nic.fr/2001:660:3006:1::1:1; ns1.nic.fr/192.134.4.1; ns3.nic.fr/192.134.0.49; ns1.nic.fr/2001:67c:2218:2::4:1; ns2.nic.fr/192.93.0.4; ns2.nic.fr/2001:660:3005:1::1:2.\n",
|
||||
"module": "NAMESERVER",
|
||||
"level": "INFO",
|
||||
"testcase": "NAMESERVER05",
|
||||
"ns": "All"
|
||||
},
|
||||
{
|
||||
"ns": "All",
|
||||
"testcase": "NAMESERVER06",
|
||||
"level": "INFO",
|
||||
"message": "All nameservers succeeded to resolve to an IP address.\n",
|
||||
"module": "NAMESERVER"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "NAMESERVER07",
|
||||
"ns": "All",
|
||||
"module": "NAMESERVER",
|
||||
"message": "None of the following nameservers returns an upward referral : ns1.nic.fr; ns2.nic.fr; ns3.nic.fr.\n"
|
||||
},
|
||||
{
|
||||
"testcase": "NAMESERVER08",
|
||||
"level": "INFO",
|
||||
"ns": "ns1.nic.fr/192.134.4.1",
|
||||
"message": "Nameserver ns1.nic.fr/192.134.4.1 preserves original case of queried names (WwW.afNiC.fr).\n",
|
||||
"module": "NAMESERVER"
|
||||
},
|
||||
{
|
||||
"testcase": "NAMESERVER08",
|
||||
"ns": "ns1.nic.fr/2001:67c:2218:2::4:1",
|
||||
"level": "INFO",
|
||||
"message": "Nameserver ns1.nic.fr/2001:67c:2218:2::4:1 preserves original case of queried names (WwW.afNiC.fr).\n",
|
||||
"module": "NAMESERVER"
|
||||
},
|
||||
{
|
||||
"module": "NAMESERVER",
|
||||
"message": "Nameserver ns2.nic.fr/192.93.0.4 preserves original case of queried names (WwW.afNiC.fr).\n",
|
||||
"level": "INFO",
|
||||
"testcase": "NAMESERVER08",
|
||||
"ns": "ns2.nic.fr/192.93.0.4"
|
||||
},
|
||||
{
|
||||
"message": "Nameserver ns2.nic.fr/2001:660:3005:1::1:2 preserves original case of queried names (WwW.afNiC.fr).\n",
|
||||
"module": "NAMESERVER",
|
||||
"level": "INFO",
|
||||
"testcase": "NAMESERVER08",
|
||||
"ns": "ns2.nic.fr/2001:660:3005:1::1:2"
|
||||
},
|
||||
{
|
||||
"testcase": "NAMESERVER08",
|
||||
"ns": "ns3.nic.fr/192.134.0.49",
|
||||
"level": "INFO",
|
||||
"module": "NAMESERVER",
|
||||
"message": "Nameserver ns3.nic.fr/192.134.0.49 preserves original case of queried names (WwW.afNiC.fr).\n"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "NAMESERVER08",
|
||||
"ns": "ns3.nic.fr/2001:660:3006:1::1:1",
|
||||
"message": "Nameserver ns3.nic.fr/2001:660:3006:1::1:1 preserves original case of queried names (WwW.afNiC.fr).\n",
|
||||
"module": "NAMESERVER"
|
||||
},
|
||||
{
|
||||
"ns": "All",
|
||||
"testcase": "NAMESERVER09",
|
||||
"level": "INFO",
|
||||
"message": "When asked for SOA records on \"www.afnic.fr\" with different cases, all servers reply consistently.\n",
|
||||
"module": "NAMESERVER"
|
||||
},
|
||||
{
|
||||
"module": "SYNTAX",
|
||||
"message": "No illegal characters in the domain name (afnic.fr).\n",
|
||||
"level": "INFO",
|
||||
"testcase": "SYNTAX01"
|
||||
},
|
||||
{
|
||||
"message": "Neither end of any label in the domain name (afnic.fr) has a hyphen.\n",
|
||||
"module": "SYNTAX",
|
||||
"level": "INFO",
|
||||
"testcase": "SYNTAX02"
|
||||
},
|
||||
{
|
||||
"message": "Domain name (afnic.fr) has no label with a double hyphen ('--') in position 3 and 4 (with a prefix which is not 'xn--').\n",
|
||||
"module": "SYNTAX",
|
||||
"testcase": "SYNTAX03",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"testcase": "SYNTAX04",
|
||||
"level": "INFO",
|
||||
"module": "SYNTAX",
|
||||
"message": "Nameserver (ns1.nic.fr) syntax is valid.\n"
|
||||
},
|
||||
{
|
||||
"testcase": "SYNTAX04",
|
||||
"level": "INFO",
|
||||
"message": "Nameserver (ns2.nic.fr) syntax is valid.\n",
|
||||
"module": "SYNTAX"
|
||||
},
|
||||
{
|
||||
"module": "SYNTAX",
|
||||
"message": "Nameserver (ns3.nic.fr) syntax is valid.\n",
|
||||
"testcase": "SYNTAX04",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"module": "SYNTAX",
|
||||
"message": "There is no misused '@' character in the SOA RNAME field (hostmaster.nic.fr.).\n",
|
||||
"level": "INFO",
|
||||
"testcase": "SYNTAX05"
|
||||
},
|
||||
{
|
||||
"message": "The SOA RNAME field (hostmaster@nic.fr) is compliant with RFC2822.\n",
|
||||
"module": "SYNTAX",
|
||||
"level": "INFO",
|
||||
"testcase": "SYNTAX06"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "SYNTAX07",
|
||||
"message": "SOA MNAME (dnsmaster.nic.fr) syntax is valid.\n",
|
||||
"module": "SYNTAX"
|
||||
},
|
||||
{
|
||||
"testcase": "SYNTAX08",
|
||||
"level": "INFO",
|
||||
"module": "SYNTAX",
|
||||
"message": "Domain name MX (mx4.nic.fr) syntax is valid.\n"
|
||||
},
|
||||
{
|
||||
"testcase": "SYNTAX08",
|
||||
"level": "INFO",
|
||||
"message": "Domain name MX (mx5.nic.fr) syntax is valid.\n",
|
||||
"module": "SYNTAX"
|
||||
},
|
||||
{
|
||||
"message": "SOA 'mname' nameserver dnsmaster.nic.fr/192.134.4.2 does not respond.\n",
|
||||
"module": "ZONE",
|
||||
"level": "NOTICE",
|
||||
"testcase": "ZONE01"
|
||||
},
|
||||
{
|
||||
"testcase": "ZONE01",
|
||||
"level": "NOTICE",
|
||||
"message": "SOA 'mname' nameserver (dnsmaster.nic.fr) is not listed in \"parent\" NS records for tested zone (ns1.nic.fr; ns2.nic.fr; ns3.nic.fr).\n",
|
||||
"module": "ZONE"
|
||||
},
|
||||
{
|
||||
"module": "ZONE",
|
||||
"message": "SOA 'refresh' value (7200) is less than the recommended one (14400).\n",
|
||||
"level": "NOTICE",
|
||||
"testcase": "ZONE02"
|
||||
},
|
||||
{
|
||||
"testcase": "ZONE03",
|
||||
"level": "INFO",
|
||||
"message": "SOA 'refresh' value (7200) is higher than the SOA 'retry' value (1800).\n",
|
||||
"module": "ZONE"
|
||||
},
|
||||
{
|
||||
"testcase": "ZONE04",
|
||||
"level": "NOTICE",
|
||||
"module": "ZONE",
|
||||
"message": "SOA 'retry' value (1800) is less than the recommended one (3600).\n"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "ZONE05",
|
||||
"message": "SOA 'expire' value (2419200) is higher than the minimum recommended value (604800) and not lower than the 'refresh' value (7200).\n",
|
||||
"module": "ZONE"
|
||||
},
|
||||
{
|
||||
"module": "ZONE",
|
||||
"message": "SOA 'minimum' value (5400) is between the recommended ones (300/86400).\n",
|
||||
"testcase": "ZONE06",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"testcase": "ZONE07",
|
||||
"level": "INFO",
|
||||
"module": "ZONE",
|
||||
"message": "SOA 'mname' value (dnsmaster.nic.fr) refers to a NS which is not an alias (CNAME).\n"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "ZONE07",
|
||||
"module": "ZONE",
|
||||
"message": "SOA 'mname' value (dnsmaster.nic.fr) refers to a NS which is not an alias (CNAME).\n"
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"testcase": "ZONE08",
|
||||
"module": "ZONE",
|
||||
"message": "MX record for the domain is not pointing to a CNAME.\n"
|
||||
},
|
||||
{
|
||||
"testcase": "ZONE08",
|
||||
"level": "INFO",
|
||||
"message": "MX record for the domain is not pointing to a CNAME.\n",
|
||||
"module": "ZONE"
|
||||
},
|
||||
{
|
||||
"module": "ZONE",
|
||||
"message": "Mail targets in the MX RRset \"mx5.nic.fr.; mx4.nic.fr.\" returned from name servers \"2001:660:3006:1::1:1; 2001:67c:2218:2::4:1; 192.134.4.1; 2001:660:3005:1::1:2; 192.93.0.4; 192.134.0.49\".\n",
|
||||
"testcase": "ZONE09",
|
||||
"level": "INFO"
|
||||
},
|
||||
{
|
||||
"module": "ZONE",
|
||||
"message": "A unique SOA record is returned by all nameservers of the zone.\n",
|
||||
"level": "INFO",
|
||||
"testcase": "ZONE10"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// FR23 - Should display previous tests
|
||||
// FR24 - Should display previous run link
|
||||
// FR25 - Should have an export button
|
||||
// FR25 - Should open a modal that contains four export possibilities
|
||||
{
|
||||
url: 'http://localhost:4321/api',
|
||||
body: {'jsonrpc': '2.0', 'id': 1572271917712, 'method': 'get_test_history', 'params': {'offset': 0, 'limit': 100, 'filter': 'all', 'frontend_params': {'domain': 'results.afNiC.Fr'}}},
|
||||
method: 'POST',
|
||||
json: {'jsonrpc': '2.0', 'id': 1572271917712, 'result': [
|
||||
{'overall_result': 'error', 'created_at': '2019-10-28T09:24:57Z', 'creation_time': '2019-10-28 09:42:42.432378', 'id': '293f626579274f18'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-28T09:24:57Z', 'creation_time': '2019-10-28 09:24:57.395431', 'id': '84bfac6ae74d0e62'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-24T07:49:48Z', 'creation_time': '2019-10-24 07:49:48.079617', 'id': 'efe0931716b0068c'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-24T07:49:16Z', 'creation_time': '2019-10-24 07:49:16.271481', 'id': '46acbdcbc456db1d'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-24T07:35:52Z', 'creation_time': '2019-10-24 07:35:52.819536', 'id': 'fd5b10ae1a46ce5e'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-24T07:35:21Z', 'creation_time': '2019-10-24 07:35:21.309154', 'id': '1b29b0582a99d7ab'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-24T06:51:22Z', 'creation_time': '2019-10-24 06:51:22.373411', 'id': '8c4829b7f60edc25'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-24T06:50:50Z', 'creation_time': '2019-10-24 06:50:50.801272', 'id': '9b89a0988dbccfdb'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-24T06:39:37Z', 'creation_time': '2019-10-24 06:39:37.48699', 'id': '89c662ddd43a8b03'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-24T06:39:05Z', 'creation_time': '2019-10-24 06:39:05.851497', 'id': '2add42a68594b37a'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-23T20:59:41Z', 'creation_time': '2019-10-23 20:59:41.594768', 'id': 'c334d7eb96af1d19'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-23T20:55:13Z', 'creation_time': '2019-10-23 20:55:13.205118', 'id': 'b4146c79de8b3638'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-23T20:46:06Z', 'creation_time': '2019-10-23 20:46:06.989113', 'id': '226f6d4f44ae3f80'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-23T20:40:46Z', 'creation_time': '2019-10-23 20:40:46.272244', 'id': 'a509e33a41f28322'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-23T20:34:21Z', 'creation_time': '2019-10-23 20:34:21.681947', 'id': '5d41c57fa24c76f5'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-23T20:28:25Z', 'creation_time': '2019-10-23 20:28:25.518303', 'id': '298b4c53d5024f44'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-23T20:16:39Z', 'creation_time': '2019-10-23 20:16:39.466781', 'id': 'f9c587426b885036'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-23T19:41:31Z', 'creation_time': '2019-10-23 19:41:31.048622', 'id': 'bb2109eb54d9ef58'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-23T16:20:56Z', 'creation_time': '2019-10-23 16:20:56.180064', 'id': '3ff7e65752a431e8'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-23T15:37:05Z', 'creation_time': '2019-10-23 15:37:05.935049', 'id': 'e8a3507cce49392d'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-23T15:25:35Z', 'creation_time': '2019-10-23 15:25:35.162808', 'id': '19f7773777cdad1a'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-23T15:09:54Z', 'creation_time': '2019-10-23 15:09:54.801371', 'id': '61907eb87c8bb1d9'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-23T14:52:56Z', 'creation_time': '2019-10-23 14:52:56.823486', 'id': '497ce5549e80d6d1'},
|
||||
{'overall_result': 'ok', 'created_at': '2019-10-23T14:39:25Z', 'creation_time': '2019-10-23 14:39:25.259204', 'id': '470e62da84dcbd16'},
|
||||
{'overall_result': 'error', 'created_at': '2019-10-23T14:26:35Z', 'creation_time': '2019-10-23 14:26:35.853106', 'id': '9b8e25c35dc365ac'}
|
||||
]}
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* Find a matching mock response for the given request
|
||||
*/
|
||||
export function findMockResponse(url: string, method: string, body: any): any | null {
|
||||
for (const element of urls) {
|
||||
// Don't compare client info
|
||||
const requestParams = { ...body?.params };
|
||||
delete requestParams['client_version'];
|
||||
delete requestParams['client_id'];
|
||||
|
||||
// Match URL by checking if both end with /api (ignore hostname and port differences)
|
||||
const urlMatch = url.endsWith('/api') && element.url.endsWith('/api');
|
||||
const methodMatch = method === element.method;
|
||||
const bodyMethodMatch = body?.method === element.body.method;
|
||||
|
||||
// For params matching, check if request params contain all mock params' required fields
|
||||
let paramsMatch = false;
|
||||
if (bodyMethodMatch && element.body.params) {
|
||||
// Check if key fields match (domain, language, etc.)
|
||||
// For start_domain_test, we primarily care about domain matching
|
||||
if (element.body.method === 'start_domain_test') {
|
||||
paramsMatch = requestParams.domain === element.body.params.domain &&
|
||||
requestParams.language === element.body.params.language;
|
||||
} else {
|
||||
// For other methods, do exact match
|
||||
paramsMatch = JSON.stringify(requestParams) === JSON.stringify(element.body.params);
|
||||
}
|
||||
}
|
||||
|
||||
if (urlMatch && methodMatch && bodyMethodMatch && paramsMatch) {
|
||||
return element.json;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
92
zonemaster-gui/e2e/utils/app.utils.ts
Normal file
92
zonemaster-gui/e2e/utils/app.utils.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { expect, type Page } from "@playwright/test";
|
||||
import { findMockResponse } from "../interceptors/mock.interceptor";
|
||||
|
||||
export function goToHome(page: Page) {
|
||||
return page.goto('/');
|
||||
}
|
||||
|
||||
export async function mounted(page: Page) {
|
||||
await expect(page.locator('body')).toHaveAttribute('data-domain-test-hydrated', 'true');
|
||||
}
|
||||
|
||||
export async function setupApiMocks(page: Page) {
|
||||
// Match any URL ending with /api
|
||||
await page.route(/\/api$/, async (route) => {
|
||||
const request = route.request();
|
||||
const method = request.method();
|
||||
const url = request.url();
|
||||
|
||||
let body;
|
||||
try {
|
||||
body = request.postDataJSON();
|
||||
} catch (e) {
|
||||
body = null;
|
||||
}
|
||||
|
||||
const mockResponse = findMockResponse(url, method, body);
|
||||
|
||||
if (mockResponse) {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(mockResponse),
|
||||
});
|
||||
} else {
|
||||
console.log('⚠️ No mock found for request:', { method: body?.method, params: body?.params });
|
||||
// If no mock is found, continue with the actual request
|
||||
await route.continue();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function setLang(page: Page, lang: string) {
|
||||
return Promise.all([
|
||||
page.waitForSelector('select#languageSwitcher'),
|
||||
page.locator('select#languageSwitcher').selectOption(lang),
|
||||
]);
|
||||
}
|
||||
|
||||
export async function closeOptions(page: Page) {
|
||||
const toggle = page.locator('#advanced-toggle');
|
||||
const panel = page.locator('#advanced-options');
|
||||
|
||||
// Ensure the toggle is visible/ready
|
||||
await expect(toggle).toBeVisible();
|
||||
|
||||
// If it's currently open, close it
|
||||
if (await toggle.getAttribute('aria-expanded') === 'true') {
|
||||
await toggle.click();
|
||||
}
|
||||
|
||||
// Confirm it's actually closed
|
||||
await expect(toggle).toHaveAttribute('aria-expanded', 'false');
|
||||
|
||||
// Wait for the panel to be hidden / detached
|
||||
await panel.waitFor({ state: 'hidden' });
|
||||
}
|
||||
|
||||
export async function showOptions(page: Page) {
|
||||
const toggle = page.locator('#advanced-toggle');
|
||||
|
||||
// Wait for toggle to be ready
|
||||
await expect(toggle).toBeVisible();
|
||||
|
||||
// Click if not already open
|
||||
if (await toggle.getAttribute('aria-expanded') !== 'true') {
|
||||
await toggle.click();
|
||||
}
|
||||
|
||||
// Ensure it's REALLY open
|
||||
await expect(toggle).toHaveAttribute('aria-expanded', 'true');
|
||||
|
||||
// Wait for the content you're about to use
|
||||
await page.locator('#advanced-options').waitFor({ state: 'visible' });
|
||||
}
|
||||
|
||||
export function clearBrowserCache(page: Page) {
|
||||
return Promise.all([
|
||||
page.evaluate(() => window.localStorage.clear()),
|
||||
page.evaluate(() => window.sessionStorage.clear()),
|
||||
page.context().clearCookies(),
|
||||
])
|
||||
}
|
||||
Reference in New Issue
Block a user