import { test, expect } from '@playwright/test'; import { clickSelect2Dropdown, getDefaultNetmask, hasToastText, isValidCidr, isValidMacAddress, isValidPrivateIPV4, isValidateDhcpInput, splitIPv6 } from '../../utils/utils.js'; test.describe('Network & Services - Network - LAN', () => { test.beforeEach(async ({ page }) => { await page.goto('/network/lan', { waitUntil: 'networkidle' }); }); test('Title', async ({ page }) => { expect(await page.title()).toBe('Difuse - Network - LAN'); }); test('Card Header Title', async ({ page }) => { const title = await page.locator('.card-header-title'); expect(await title).toBeTruthy(); }); test('Tabs', async ({ page }) => { const ipv4Tab = await page.$('a[role="tab"][id="4-tab"]'); const ipv4visible = await ipv4Tab.isVisible(); expect(ipv4visible).toBeTruthy(); await page.click('a[role="tab"][id="4-tab"]'); await page.waitForSelector('#content-4'); const ipv4Content = await page.locator('#content-4'); const ipv4ContentVisible = await ipv4Content.isVisible(); expect(ipv4ContentVisible).toBeTruthy(); const ipv6Tab = await page.$('a[role="tab"][id="6-tab"]'); const ipv6visible = await ipv6Tab.isVisible(); expect(ipv6visible).toBeTruthy(); await page.click('a[role="tab"][id="6-tab"]'); await page.waitForSelector('#content-6'); const ipv6Content = await page.locator('#content-6'); const ipv6ContentVisible = await ipv6Content.isVisible(); expect(ipv6ContentVisible).toBeTruthy(); const bridgeSlaves = await page.$('a[role="tab"][id="bs-tab"]'); const bridgeSlavesVisible = await bridgeSlaves.isVisible(); expect(bridgeSlavesVisible).toBeTruthy(); await page.click('a[role="tab"][id="bs-tab"]'); await page.waitForSelector('#content-bs'); const bsContent = await page.locator('#content-bs'); const bsContentVisible = await bsContent.isVisible(); expect(bsContentVisible).toBeTruthy(); }); test('Info Tables', async ({ page }) => { const rows = await page.$$('table > tbody > tr'); for (const row of rows) { const cells = await row.$$('td'); if (cells.length === 2) { const label = await cells[0].textContent(); const value = await cells[1].textContent(); if (label === 'Protocol') { expect(value).toBe('Static Address'); } else if (label === 'Uptime') { expect(typeof parseInt(value)).toBe('number'); } else if (label === 'MAC') { expect(isValidMacAddress(value)).toBeTruthy(); } else if (label === 'RX' || label === 'TX') { expect(typeof parseInt(value)).toBe('number'); } else if (label === 'IPv4') { expect(isValidPrivateIPV4(value)).toBe(true); } else if (label === 'IPv6 (Prefixes)') { const splittedValue = splitIPv6(value); if (!splittedValue) { expect(value).toBe(false); } else if (splittedValue.length === 1) { const isValid = isValidCidr(splittedValue[0]); expect(isValid).toBe(true); } else if (splittedValue.length === 2) { const ipv6One = splittedValue[0]; const isValidIPv6One = isValidCidr(ipv6One); const ipv6Two = splittedValue[1]; const isValidIPv6Two = isValidCidr(ipv6Two); expect(await isValidIPv6One && isValidIPv6Two).toBe(true); } } } } }); test('Validate Ip Address', async ({ page }) => { await page.waitForSelector('#ipAddress'); const ipAddress = await page.locator('#ipAddress'); const ipValue = await ipAddress.inputValue(); const validateIP = await isValidPrivateIPV4(ipValue); expect(validateIP).toBe(true); }); test('Validate Network Mask Address', async ({ page }) => { await page.waitForSelector('#ipAddress'); const ipAddress = await page.locator('#ipAddress'); const ipValue = await ipAddress.inputValue(); const networkMask = await page.locator('.lan-netmask-select'); const networkValue = await networkMask.inputValue(); const defaultValue = getDefaultNetmask(ipValue); expect(defaultValue).toBe(networkValue); }); test('Enable DHCP Toggle', async ({ page }) => { const dhcpCb = await page.$('.dhcp-cb'); const isChecked = await dhcpCb.isChecked(); if (isChecked) { expect(await page.isVisible('label:has-text("DHCP Start")')).toBeTruthy(); } else { await page.evaluate((checkbox) => checkbox.click(), dhcpCb); expect(await page.isVisible('label:has-text("DHCP Start")')).toBeTruthy(); } }); test('Disable DHCP Toggle', async ({ page }) => { const dhcpCb = await page.$('.dhcp-cb'); const isChecked = await dhcpCb.isChecked(); if (isChecked) { await page.evaluate((checkbox) => checkbox.click(), dhcpCb); expect(await page.isVisible('label:has-text("DHCP Start")')).toBe(false); } else { expect(await page.isVisible('label:has-text("DHCP Start")')).toBe(false); } }); test('DHCP validation', async ({ page }) => { await page.waitForSelector('#ipAddress'); const ipAddress = await page.locator('#ipAddress'); const ipValue = await ipAddress.inputValue().toString(); const networkMask = await page.locator('.lan-netmask-select'); const networkValue = await networkMask.inputValue().toString(); const dhcpStart = await page.locator('#dhcpStart'); const dhcpStartValue = await dhcpStart.inputValue(); const dhcpMax = await page.locator('#dhcpMax'); const dhcpMaxValue = await dhcpMax.inputValue(); const isValid = isValidateDhcpInput(ipValue, networkValue, dhcpStartValue, dhcpMaxValue); if (isValid) { expect(isValid).toBe(true); } else { expect(isValid).toBe(false); } }); test.describe('Bad IPv4 Form Submits', () => { test('Bad IPv4', async ({ page }) => { const ip = await page.locator('#ipAddress'); await ip.fill('1.1.1.1.1.1.1.1.1.1.1'); await page.click('button.button.green:has-text("Save")'); expect(await hasToastText(page, 'Invalid IP Address')).toBeTruthy(); }); test('Bad Netmask', async ({ page }) => { await clickSelect2Dropdown(page, '.lan-netmask-select'); await page.getByRole('searchbox', { name: 'Search' }).fill('15151515515151515'); await page.keyboard.press('Enter'); await page.click('button.button.green:has-text("Save")'); expect(await hasToastText(page, 'Invalid Netmask')).toBeTruthy(); }); test('Bad DHCP Start', async ({ page }) => { await page.locator('#dhcpStart').fill('55555555555555'); await page.click('button.button.green:has-text("Save")'); expect(await hasToastText(page, 'Invalid DHCP Range')).toBeTruthy(); }); test('Bad DHCP Max Leases', async ({ page }) => { await page.locator('#dhcpMax').fill('55555555555555'); await page.click('button.button.green:has-text("Save")'); expect(await hasToastText(page, 'Invalid DHCP Range')).toBeTruthy(); }); }); test('Lease Time', async ({ page }) => { await page.waitForTimeout(2000); const leaseTimeInput = await page.$('#leaseTime'); const value = await leaseTimeInput.inputValue(); const leaseTimeValue = Number(value); expect(leaseTimeValue).toBeGreaterThanOrEqual(1); expect(leaseTimeValue).toBeLessThanOrEqual(12); }); test.describe('IPV6 Tab', () => { test.beforeEach(async ({ page }) => { await page.goto('/network/lan', { waitUntil: 'networkidle' }); const ipv6Tab = await page.$("a:has-text('IPv6')"); await ipv6Tab.click(); }); test('ULA Prefix Validation', async ({ page }) => { await page.waitForSelector('#ulaPrefix'); const ulaPrefix = await page.locator('#ulaPrefix'); const value = await ulaPrefix.inputValue(); if (value) { const isValidIPv6 = isValidCidr(value); expect(isValidIPv6).toBe(true); } }); test('Bad ULA Prefix Validation', async ({ page }) => { await page.waitForSelector('#ulaPrefix'); const ulaPrefix = await page.locator('#ulaPrefix'); await ulaPrefix.fill('1.1.1.1.1.1.1.1.1.1.1'); const saveButton = await page.getByRole('button', { name: 'Save' }); await saveButton.click(); expect(await hasToastText(page, 'Invalid ULA Prefix')).toBeTruthy(); }); test('RA & DHCPv6', async ({ page }) => { const selectElement = await page.locator('label:has-text("RA & DHCPv6") + .field-body select.rad-select'); const optionDatas = await selectElement.evaluate(select => { const options = Array.from(select.querySelectorAll('option')); return options.map(option => { return { label: option.textContent.trim(), value: option.value.trim() }; }); }); for (const optionData of optionDatas) { if (optionData.label === 'SLAAC') { expect(optionData.value).toBe('slaac'); } else if (optionData.label === 'SLAAC & DHCPv6') { expect(optionData.value).toBe('slaac-dhcp'); } else if (optionData.label === 'IPv6 Relay') { expect(optionData.value).toBe('relay'); } else if (optionData.label === 'IPv6 Hybrid') { expect(optionData.value).toBe('hybrid'); } else if (optionData.label === 'Automatic') { expect(optionData.value).toBe('default'); } } }); test('RA Default', async ({ page }) => { const selectElement = await page.locator('label:has-text("RA Default") + .control.icons-left select.raDefaultSelect'); const optionDatas = await selectElement.evaluate(select => { const options = Array.from(select.querySelectorAll('option')); return options.map(option => { return { label: option.textContent.trim(), value: option.value.trim() }; }); }); for (const optionData of optionDatas) { if (optionData.label === 'Automatic') { expect(optionData.value).toBe('0'); } else if (optionData.label === 'On Available Prefix') { expect(optionData.value).toBe('1'); } else if (optionData.label === 'Forced') { expect(optionData.value).toBe('2'); } } }); }); test.describe('Bridge Slaves Tab', () => { test.beforeEach(async ({ page }) => { await page.goto('/network/lan', { waitUntil: 'networkidle' }); const bridgeSlaveTab = await page.$("a:has-text('Bridge Slaves')"); await bridgeSlaveTab.click(); }); test('SFP 2', async ({ page }) => { const sfp = page.locator('.mdi-ethernet-cable'); expect(await sfp.isVisible()).toBeTruthy(); }); }); });