diff --git a/package.json b/package.json index acc7dc1..c065d76 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "type": "module", "scripts": { "lint": "semistandard --fix tests/**/*.js", + "codegen": "npx playwright codegen", "test": "playwright test", "prepare": "npm run lint" }, diff --git a/playwright.config.cjs b/playwright.config.cjs index 83a0cf3..4179d09 100644 --- a/playwright.config.cjs +++ b/playwright.config.cjs @@ -1,7 +1,3 @@ -// import { defineConfig, devices } from '@playwright/test'; -// -// await import('dotenv/config'); - const { defineConfig, devices } = require('@playwright/test'); require('dotenv').config(); diff --git a/tests/dashboards/router.spec.js b/tests/dashboards/router.spec.js index 500c281..4dc458d 100644 --- a/tests/dashboards/router.spec.js +++ b/tests/dashboards/router.spec.js @@ -1,45 +1,47 @@ import { test, expect } from '@playwright/test'; -test.beforeEach(async ({ page }) => { - await page.goto('/', { waitUntil: 'networkidle' }); -}); - -test('Title', async ({ page }) => { - const title = await page.title(); - expect(title).toBe('Difuse - Dashboard - Router'); -}); - -test('Top Cards', async ({ page }) => { - const lanClients = await page.getByRole('heading', { name: 'LAN Clients' }); - const wifiClients = await page.getByRole('heading', { name: 'GHz & 5 GHz Clients' }); - const wgEndpoints = await page.getByRole('heading', { name: 'Peers & Clients' }); - - expect(lanClients && wifiClients && wgEndpoints).toBeTruthy(); -}); - -test('Basic System Information', async ({ page }) => { - const cells = (await page.$$('.tabulator-cell')).filter(async (cell) => { - const field = await cell.getAttribute('tabulator-field'); - return field === 'value'; +test.describe('General - Dashboard - Router', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/', { waitUntil: 'networkidle' }); }); - const currentYear = new Date().getFullYear(); + test('Title', async ({ page }) => { + const title = await page.title(); + expect(title).toBe('Difuse - Dashboard - Router'); + }); - let foundFw = false; - let foundUptime = false; + test('Top Cards', async ({ page }) => { + const lanClients = await page.getByRole('heading', { name: 'LAN Clients' }); + const wifiClients = await page.getByRole('heading', { name: 'GHz & 5 GHz Clients' }); + const wgEndpoints = await page.getByRole('heading', { name: 'Peers & Clients' }); - for (let i = 0; i < cells.length; i++) { - const text = await cells[i].textContent(); - if (text.includes('difos')) { - foundFw = true; - } else if (text.includes(currentYear.toString())) { - foundUptime = true; + expect(lanClients && wifiClients && wgEndpoints).toBeTruthy(); + }); + + test('Basic System Information', async ({ page }) => { + const cells = (await page.$$('.tabulator-cell')).filter(async (cell) => { + const field = await cell.getAttribute('tabulator-field'); + return field === 'value'; + }); + + const currentYear = new Date().getFullYear(); + + let foundFw = false; + let foundUptime = false; + + for (let i = 0; i < cells.length; i++) { + const text = await cells[i].textContent(); + if (text.includes('difos')) { + foundFw = true; + } else if (text.includes(currentYear.toString())) { + foundUptime = true; + } } - } - expect(foundFw && foundUptime).toBe(true); -}); + expect(foundFw && foundUptime).toBe(true); + }); -test('Network Information', async ({ page }) => { - expect(await page.$('th:has-text("Network Information")')).toBeTruthy(); + test('Network Information', async ({ page }) => { + expect(await page.$('th:has-text("Network Information")')).toBeTruthy(); + }); }); diff --git a/tests/dashboards/telephony.spec.js b/tests/dashboards/telephony.spec.js index 826032a..b34b03a 100644 --- a/tests/dashboards/telephony.spec.js +++ b/tests/dashboards/telephony.spec.js @@ -1,37 +1,39 @@ import { test, expect } from '@playwright/test'; -test.beforeEach(async ({ page }) => { - await page.goto('/telephony', { waitUntil: 'networkidle' }); -}); - -test('Title', async ({ page }) => { - const title = await page.title(); - expect(title).toBe('Difuse - Dashboard - Telephony'); -}); - -test('Top Cards', async ({ page }) => { - const sipExtensions = await page.getByRole('heading', { name: 'SIP Extensions' }); - const sipTrunks = await page.getByRole('heading', { name: 'SIP Trunks' }); - const currentChannels = await page.getByRole('heading', { name: 'Current Channels' }); - const completedCalls = await page.getByRole('heading', { name: 'Completed Calls' }); - - expect(sipExtensions && sipTrunks && currentChannels && completedCalls).toBeTruthy(); -}); - -test('Endpoint Table', async ({ page }) => { - expect(await page.getByText('Page Size')).toBeTruthy(); -}); - -test('PBX Information', async ({ page }) => { - const yearRegex = /\b\d{4}\b/; - - const coreReloadText = await page.textContent('td:has-text("Core Last Reload") + td'); - expect(yearRegex.test(coreReloadText)).toBeTruthy(); - - const asteriskVersionText = await page.textContent('td:has-text("Asterisk Version") + td'); - const versionRegex = /^\d+\.\d+\.\d+$/; - expect(versionRegex.test(asteriskVersionText.replaceAll(/\s/g, ''))).toBeTruthy(); - - const coreStartupTimeText = await page.textContent('#core-startup-time'); - expect(yearRegex.test(coreStartupTimeText)).toBeTruthy(); +test.describe('General - Dashboard - Telephony', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/telephony', { waitUntil: 'networkidle' }); + }); + + test('Title', async ({ page }) => { + const title = await page.title(); + expect(title).toBe('Difuse - Dashboard - Telephony'); + }); + + test('Top Cards', async ({ page }) => { + const sipExtensions = await page.getByRole('heading', { name: 'SIP Extensions' }); + const sipTrunks = await page.getByRole('heading', { name: 'SIP Trunks' }); + const currentChannels = await page.getByRole('heading', { name: 'Current Channels' }); + const completedCalls = await page.getByRole('heading', { name: 'Completed Calls' }); + + expect(sipExtensions && sipTrunks && currentChannels && completedCalls).toBeTruthy(); + }); + + test('Endpoint Table', async ({ page }) => { + expect(await page.getByText('Page Size')).toBeTruthy(); + }); + + test('PBX Information', async ({ page }) => { + const yearRegex = /\b\d{4}\b/; + + const coreReloadText = await page.textContent('td:has-text("Core Last Reload") + td'); + expect(yearRegex.test(coreReloadText)).toBeTruthy(); + + const asteriskVersionText = await page.textContent('td:has-text("Asterisk Version") + td'); + const versionRegex = /^\d+\.\d+\.\d+$/; + expect(versionRegex.test(asteriskVersionText.replaceAll(/\s/g, ''))).toBeTruthy(); + + const coreStartupTimeText = await page.textContent('#core-startup-time'); + expect(yearRegex.test(coreStartupTimeText)).toBeTruthy(); + }); }); diff --git a/tests/network/guest-lan.spec.js b/tests/network/guest-lan.spec.js index 0fc9e62..a8c9b1e 100644 --- a/tests/network/guest-lan.spec.js +++ b/tests/network/guest-lan.spec.js @@ -1,47 +1,90 @@ -import { test, expect } from '@playwright/test'; -import { isValidMacAddress, isValidCidr } from '../../utils/utils.js'; +import { expect, test } from '@playwright/test'; +import { isValidCidr, isValidMacAddress, clickSelect2Dropdown, hasToastText, sleep } from '../../utils/utils.js'; -test.beforeEach(async ({ page }) => { - await page.goto('/network/guest-lan', { waitUntil: 'networkidle' }); +test.describe('Network & Services - Network - Guest LAN', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/network/guest-lan', { waitUntil: 'networkidle' }); + await page.waitForFunction(async () => { + await sleep(1000); + const element = document.querySelector('.lan-netmask-select'); + return element && element.classList.contains('select2-hidden-accessible'); + }); + }); + + test('Title', async ({ page }) => { + const title = await page.title(); + expect(title).toBe('Difuse - Network - Guest LAN'); + }); + + test('Info Table', 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(isValidCidr(value)).toBeTruthy(); + } + } + } + }); + + test('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 dhcpCb.check(); + expect(await page.isVisible('label:has-text("DHCP Start1")')).toBeTruthy(); + } + }); + + test.describe('Bad IPv4 Form Submits', () => { + test('Bad IPv4', async ({ page }) => { + const ip = await page.getByPlaceholder('192.168.1.1'); + 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(); + }); + + /* Hayzam - Fix This */ + // test('Bad DHCP Leasetime', async ({ page }) => { + // await page.locator('#leaseTime').fill('55555555555555'); + // await page.click('button.button.green:has-text("Save")'); + // expect(await hasToastText(page, 'Invalid Lease Time')).toBeTruthy(); + // }); + }); }); - -test('Title', async ({ page }) => { - const title = await page.title(); - expect(title).toBe('Difuse - Network - Guest LAN'); -}); - -test('Info Table', async ({ page }) => { - await page.waitForSelector('td:has-text("Static Address")', { timeout: 5000 }); - await page.waitForTimeout(2500); - - 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(isValidCidr(value)).toBeTruthy(); - } - } - } -}); - -test('Bad IPv4 Form Submits', async ({ page }) => { - await page.waitForSelector('#ipAddress', {timeout: 5000}) - await page.fill('#ipAddress', '111.111.111.111.111'); - await page.click('button[type="submit"]'); - const errorPopup = await page.waitForSelector('.swal2-popup', { state: 'visible' }); - const errorText = await errorPopup.textContent(); - expect(errorText).toContain('Invalid IP Address'); -}); \ No newline at end of file diff --git a/utils/utils.js b/utils/utils.js index a46e2ba..54b40f8 100644 --- a/utils/utils.js +++ b/utils/utils.js @@ -43,3 +43,29 @@ export function isValidCidr (cidr, type = 0) { return false; } } + +export async function clickSelect2Dropdown(page, selectSelector) { + const select2ContainerSelector = `${selectSelector} + .select2-container`; + const select2ContainerExists = await page.$(select2ContainerSelector) !== null; + + if (!select2ContainerExists) { + throw new Error('Select2 container not found'); + } + + const select2Selection = `${select2ContainerSelector} .select2-selection`; + await page.click(select2Selection); + await page.waitForSelector('.select2-dropdown .select2-results__option'); +} + +export async function hasToastText(page, text) { + try { + return (await (await page.waitForSelector('.swal2-popup', {state: 'visible'})).textContent()).includes(text); + } catch (error) { + console.log(error); + return false; + } +} + +export async function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} \ No newline at end of file