diff --git a/tests/end2end/playwright/bad-repository.spec.js b/tests/end2end/playwright/bad-repository.spec.js index 4c76a2d62..5563077e4 100644 --- a/tests/end2end/playwright/bad-repository.spec.js +++ b/tests/end2end/playwright/bad-repository.spec.js @@ -1,5 +1,6 @@ // @ts-check import { test, expect } from '@playwright/test'; +import {AdminPage} from "./pages/admin"; test.describe('Bad repository in conf', () => { @@ -8,6 +9,8 @@ test.describe('Bad repository in conf', () => { test.beforeEach(async ({ page }) => { // Go to repos page await page.goto('/admin.php/admin/maps', { waitUntil: 'networkidle' }); + const adminPage = new AdminPage(page); + await adminPage.checkPage('Maps management'); }); test('Badge displayed for bad repository', async ({ page }) => { diff --git a/tests/end2end/playwright/landing_page_config.spec.js b/tests/end2end/playwright/landing_page_config.spec.js index 394ef8e12..e1b0c42be 100644 --- a/tests/end2end/playwright/landing_page_config.spec.js +++ b/tests/end2end/playwright/landing_page_config.spec.js @@ -1,5 +1,7 @@ // @ts-check import { test, expect } from '@playwright/test'; +import {HomePage} from "./pages/homepage"; +import {AdminPage} from "./pages/admin"; test.describe('Landing page content', () => { @@ -7,13 +9,16 @@ test.describe('Landing page content', () => { const adminContext = await browser.newContext({ storageState: 'playwright/.auth/admin.json' }); const page = await adminContext.newPage(); + const adminPage = new AdminPage(page); // unanthenticated context const userContext = await browser.newContext(); const userPage = await userContext.newPage(); + const homeUserPage = new HomePage(userPage); + const homeAdminPage = new HomePage(page); // Go to Landing Page admin await page.goto('admin.php'); - await page.getByRole('link', { name: 'Landing page content' }).click(); + await adminPage.openPage('Landing page content'); // set top content // NOTE : use .ck-content to get the CKEditor await page.getByRole('group', { name: 'Top of the landing page' }).locator('.ck-content').first().fill('Top for unauth 2nd'); @@ -27,23 +32,23 @@ test.describe('Landing page content', () => { // save form and ensure, it's ok await page.getByRole('button', { name: 'Save' }).click(); - await expect(page.locator('#admin-message div p')).toHaveText('Content of the landing page has been saved'); + await adminPage.checkAlert('alert-success', 'Content of the landing page has been saved'); // Go to Landing page await page.goto('index.php'); // check text order - await expect(page.locator('#landingPageContent')).toHaveText('Top for auth 1st Top for unauth 2nd'); - await expect(page.locator('#landingPageContentBottom')).toHaveText('Bottom for unauth 1st Bottom for auth 2nd'); + await expect(homeAdminPage.topContent).toHaveText('Top for auth 1st Top for unauth 2nd'); + await expect(homeAdminPage.bottomContent).toHaveText('Bottom for unauth 1st Bottom for auth 2nd'); // check unauthenticated await userPage.goto('index.php'); - await expect(userPage.locator('#landingPageContent')).toHaveText('Top for unauth 2nd'); - await expect(userPage.locator('#landingPageContentBottom')).toHaveText('Bottom for unauth 1st'); + await expect(homeUserPage.topContent).toHaveText('Top for unauth 2nd'); + await expect(homeUserPage.bottomContent).toHaveText('Bottom for unauth 1st'); // now, we'll disable content for unauthenticated in authed context await page.goto('admin.php'); - await page.getByRole('link', { name: 'Landing page content' }).click(); + await adminPage.openPage('Landing page content'); await page.getByRole('group', { name: 'Top of the landing page' }).locator('.ck-content').last().fill('Top only'); await page.getByRole('group', { name: 'Bottom of the landing page' }).locator('.ck-content').last().fill('Bottom only'); await page.getByRole('group', { name: 'Top of the landing page' }).locator('.ck-content').first().fill('Top unauth only'); @@ -52,17 +57,17 @@ test.describe('Landing page content', () => { await page.getByRole('group', { name: 'Top of the landing page' }).getByLabel('No').check(); await page.getByRole('group', { name: 'Bottom of the landing page' }).getByLabel('No').check(); await page.getByRole('button', { name: 'Save' }).click(); - await expect(page.locator('#admin-message div p')).toHaveText('Content of the landing page has been saved'); + await adminPage.checkAlert('alert-success', 'Content of the landing page has been saved'); // go to landing page ... await page.goto('index.php'); - await expect(page.locator('#landingPageContent')).toHaveText('Top only'); - await expect(page.locator('#landingPageContentBottom')).toHaveText('Bottom only'); + await expect(homeAdminPage.topContent).toHaveText('Top only'); + await expect(homeAdminPage.bottomContent).toHaveText('Bottom only'); // check unauthed - await userPage.goto('index.php'); - await expect(userPage.locator('#landingPageContent')).toHaveText('Top unauth only'); - await expect(userPage.locator('#landingPageContentBottom')).toHaveText('Bottom unauth only'); + await userPage.reload(); + await expect(homeUserPage.topContent).toHaveText('Top unauth only'); + await expect(homeUserPage.bottomContent).toHaveText('Bottom unauth only'); }); }); diff --git a/tests/end2end/playwright/maps-management.spec.js b/tests/end2end/playwright/maps-management.spec.js index be62f9630..fb852f7ba 100644 --- a/tests/end2end/playwright/maps-management.spec.js +++ b/tests/end2end/playwright/maps-management.spec.js @@ -1,5 +1,6 @@ // @ts-check import { test, expect } from '@playwright/test'; +import {AdminPage} from "./pages/admin"; test.describe('Maps management', () => { @@ -12,9 +13,8 @@ test.describe('Maps management', () => { test('Create and remove a repository', async ({ page }) => { // Go to Maps management - await page.getByRole('link', { name: 'Maps management' }).click(); - // Check selected admin menu item - await expect(page.locator('#menu li.active')).toHaveText('Maps management'); + const adminPage = new AdminPage(page); + await adminPage.openPage('Maps management'); // Contains 2 buttons Create a repository await expect(page.locator('div').filter({ hasText: 'Create a repository' }).getByRole('link', { name: 'Create a repository' })).toHaveCount(2); @@ -24,7 +24,7 @@ test.describe('Maps management', () => { // Check URL await expect(page).toHaveURL(/.*admin.php\/admin\/maps\/editSection/); // Check selected admin menu item - await expect(page.locator('#menu li.active')).toHaveText('Maps management'); + await adminPage.checkPage('Maps management'); // Check form await expect(page.locator('[id=jforms_admin_config_section_path]')).toHaveValue(''); @@ -96,11 +96,10 @@ test.describe('Maps management', () => { // Check URL await expect(page).toHaveURL(/.*admin.php\/admin\/maps/); // Check message - await expect(page.locator('div.alert.alert-block')).toHaveClass(/alert-info/); - await expect(page.locator('div.alert.alert-block.alert-info')).toContainText('The repository data has been saved.'); + await adminPage.checkAlert('alert-info', 'The repository data has been saved.'); // Check selected admin menu item - await expect(page.locator('#menu li.active')).toHaveText('Maps management'); + await adminPage.checkPage('Maps management'); // Remove created repository page.once('dialog', dialog => { @@ -109,20 +108,18 @@ test.describe('Maps management', () => { }); await page.locator('[href="/admin.php/admin/maps/removeSection?repository=projets1982"]').click(); // Check message - await expect(page.locator('div.alert.alert-block')).toHaveClass(/alert-info/); - await expect(page.locator('div.alert.alert-block.alert-info')).toContainText('The repository has been removed (8 group(s) concerned)'); + await adminPage.checkAlert('alert-info', 'The repository has been removed (8 group(s) concerned)'); // Check URL await expect(page).toHaveURL(/.*admin.php\/admin\/maps/); // Check selected admin menu item - await expect(page.locator('#menu li.active')).toHaveText('Maps management'); + await adminPage.checkPage('Maps management'); }); test('Update a repository', async ({ page }) => { // Go to Maps management - await page.getByRole('link', { name: 'Maps management' }).click(); - // Check selected admin menu item - await expect(page.locator('#menu li.active')).toHaveText('Maps management'); + const adminPage = new AdminPage(page); + await adminPage.openPage('Maps management'); // Go to modify repository await page.locator('a[href="/admin.php/admin/maps/modifySection?repository=testsrepository"]').click() @@ -130,7 +127,7 @@ test.describe('Maps management', () => { // Check URL await expect(page).toHaveURL(/.*admin.php\/admin\/maps\/editSection\?repository=testsrepository/); // Check selected admin menu item - await expect(page.locator('#menu li.active')).toHaveText('Maps management'); + await adminPage.checkPage('Maps management'); // Check form await expect(page.locator('[id=jforms_admin_config_section_path]')).toHaveValue('/srv/lzm/tests/qgis-projects/tests/'); @@ -196,7 +193,7 @@ test.describe('Maps management', () => { await expect(page).toHaveURL(/.*admin.php\/admin\/maps/); // Check selected admin menu item - await expect(page.locator('#menu li.active')).toHaveText('Maps management'); + await adminPage.checkPage('Maps management'); }); }); diff --git a/tests/end2end/playwright/pages/admin.js b/tests/end2end/playwright/pages/admin.js new file mode 100644 index 000000000..ee66f25e4 --- /dev/null +++ b/tests/end2end/playwright/pages/admin.js @@ -0,0 +1,45 @@ +// @ts-check + +import {expect, Locator, Page} from '@playwright/test'; +import { BasePage } from './base'; + +export class AdminPage extends BasePage { + /** + * Main administrator menu + * @type {Locator} + */ + menu; + + /** + * Main administrator message bar + * @type {Locator} + */ + warningMessage; + + /** + * Constructor for an administrator page + * @param {Page} page The playwright page + */ + constructor(page) { + super(page); + this.menu = page.locator('#menu'); + this.warningMessage = page.locator('.alert'); + } + + /** + * Navigate in the administrator menu by clicking in the menu + * @param {string} expected Name of the page + */ + async openPage(expected){ + await this.page.getByRole('link', { name: expected }).click(); + await this.checkPage(expected); + } + + /** + * Check that the menu is OK + * @param {string} expected Name of the page + */ + async checkPage(expected){ + await expect(this.menu.locator('li.active')).toHaveText(expected); + } +} diff --git a/tests/end2end/playwright/pages/base.js b/tests/end2end/playwright/pages/base.js new file mode 100644 index 000000000..1ecdf7dbb --- /dev/null +++ b/tests/end2end/playwright/pages/base.js @@ -0,0 +1,42 @@ +// @ts-check + +import {expect, Locator, Page} from '@playwright/test'; + +export class BasePage { + /** @type {Page} */ + page; + + /** + * Header menu + * @type {Locator} + */ + headerMenu; + + /** + * Top message bar + * @type {Locator} + */ + alert; + + /** + * Constructor for a base page + * @param {Page} page The playwright page + */ + constructor(page) { + this.page = page; + this.headerMenu = page.locator('#headermenu'); + this.alert = page.locator('.alert'); + } + + /** + * Check main alert message : level and content if necessary + * @param {string} level Name of the CSS class for the level + * @param {string} message Content of the message, if necessary + */ + async checkAlert(level, message) { + await expect(this.alert).toHaveClass(new RegExp(level, "g")); + if (message) { + await expect(this.alert).toHaveText(message); + } + } +} diff --git a/tests/end2end/playwright/pages/homepage.js b/tests/end2end/playwright/pages/homepage.js new file mode 100644 index 000000000..673932505 --- /dev/null +++ b/tests/end2end/playwright/pages/homepage.js @@ -0,0 +1,35 @@ +// @ts-check + +import {Locator, Page} from '@playwright/test'; +import { BasePage } from './base'; + +export class HomePage extends BasePage { + /** + * Search project locator + * @type {Locator} + */ + search; + + /** + * Top text locator + * @type {Locator} + */ + topContent; + + /** + * Bottom text locator + * @type {Locator} + */ + bottomContent; + + /** + * Constructor for main landing page of Lizmap + * @param {Page} page The playwright page + */ + constructor(page) { + super(page); + this.topContent = page.locator('#landingPageContent'); + this.bottomContent = page.locator('#landingPageContentBottom'); + this.search = page.locator('#search'); + } +} diff --git a/tests/end2end/playwright/pages/project.js b/tests/end2end/playwright/pages/project.js index 027cfc9e7..df01871ce 100644 --- a/tests/end2end/playwright/pages/project.js +++ b/tests/end2end/playwright/pages/project.js @@ -1,11 +1,9 @@ // @ts-check import {expect, Locator, Page} from '@playwright/test'; import { gotoMap } from '../globals'; +import { BasePage } from './base'; -export class ProjectPage { - /** @type {Page} */ - page; - +export class ProjectPage extends BasePage { // Metadata /** * Project name metadata @@ -78,13 +76,13 @@ export class ProjectPage { this.page.locator(`#attribute-layer-table-${name}`); /** - * Constructor + * Constructor for a QGIS project page * @param {Page} page The playwright page * @param {string} project The project name * @param {string} repository The repository name, default to testsrepository */ constructor(page, project, repository = 'testsrepository') { - this.page = page; + super(page); this.project = project; this.repository = repository; this.dock = page.locator('#dock'); diff --git a/tests/end2end/playwright/server-information.spec.js b/tests/end2end/playwright/server-information.spec.js index 4652d9322..8a0f47b0d 100644 --- a/tests/end2end/playwright/server-information.spec.js +++ b/tests/end2end/playwright/server-information.spec.js @@ -1,5 +1,6 @@ // @ts-check import { test, expect } from '@playwright/test'; +import {AdminPage} from "./pages/admin"; test.describe('Server information', () => { @@ -11,10 +12,11 @@ test.describe('Server information', () => { }); test('Check page', async ({ page }) => { + const adminPage = new AdminPage(page); + // Go to server information - await page.getByRole('link', { name: 'Server information' }).click(); - // Check selected admin menu item - await expect(page.locator('#menu li.active')).toHaveText('Server information'); + await adminPage.openPage('Server information'); + // Check that Lizmap Web Client table contains 3 lines const lwcRows = page.locator('#lizmap_server_information table.table-lizmap-web-client tr') await expect(lwcRows).toHaveCount(3);