Skip to content

Commit

Permalink
Tests - Start Page Object Model for Playwright
Browse files Browse the repository at this point in the history
  • Loading branch information
Gustry committed Jan 15, 2025
1 parent 45c62f9 commit c01abd1
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 62 deletions.
23 changes: 12 additions & 11 deletions tests/end2end/playwright/attribute-table.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// @ts-check
import { test, expect } from '@playwright/test';
import { ProjectPage } from './pages/project-page';
import { gotoMap } from './globals';

test.describe('Attribute table', () => {
Expand All @@ -9,18 +10,17 @@ test.describe('Attribute table', () => {
});

test('Thumbnail class generate img with good path', async ({ page }) => {
await page.locator('a#button-attributeLayers').click();
// display form
//await page.locator('#button-edition').click();
await page.locator('#attribute-layer-list-table').locator('button[value=Les_quartiers_a_Montpellier]').click();
await expect(page.locator('#attribute-layer-table-Les_quartiers_a_Montpellier tbody tr')).toHaveCount(7);
const project = new ProjectPage(page, 'attribute_table');
const layerName = 'Les_quartiers_a_Montpellier';

await project.openAttributeTable(layerName);
await expect(project.attributeTableHtml(layerName).locator('tbody tr')).toHaveCount(7);
// mediaFile as stored in data-src attributes
const mediaFile = await page.locator('#attribute-layer-table-Les_quartiers_a_Montpellier img.data-attr-thumbnail').first().getAttribute('data-src');
const mediaFile = await project.attributeTableHtml(layerName).locator('img.data-attr-thumbnail').first().getAttribute('data-src');
// ensure src contain "dynamic" mediaFile
await expect(page.locator('#attribute-layer-table-Les_quartiers_a_Montpellier img.data-attr-thumbnail').first()).toHaveAttribute('src', new RegExp(mediaFile));
await expect(project.attributeTableHtml(layerName).locator('img.data-attr-thumbnail').first()).toHaveAttribute('src', new RegExp(mediaFile));
// ensure src contain getMedia and projet URL
await expect(page.locator('#attribute-layer-table-Les_quartiers_a_Montpellier img.data-attr-thumbnail').first()).toHaveAttribute('src', /getMedia\?repository=testsrepository&project=attribute_table&/);
await expect(project.attributeTableHtml(layerName).locator('img.data-attr-thumbnail').first()).toHaveAttribute('src', /getMedia\?repository=testsrepository&project=attribute_table&/);
});
});

Expand All @@ -37,8 +37,9 @@ test.describe('Attribute table data restricted to map extent', () => {
});

test('Data restriction, refresh button behaviour and export', async ({ page }) => {
await page.locator('a#button-attributeLayers').click();
await page.locator('#attribute-layer-list-table').locator('button[value=Les_quartiers_a_Montpellier]').click();
const project = new ProjectPage(page, 'attribute_table');
const layerName = 'Les_quartiers_a_Montpellier';
await project.openAttributeTable(layerName);

await expect(page.locator('.btn-refresh-table')).not.toHaveClass(/btn-warning/);

Expand All @@ -53,7 +54,7 @@ test.describe('Attribute table data restricted to map extent', () => {
// Refresh
await page.locator('.btn-refresh-table').click();

await expect(page.locator('#attribute-layer-table-Les_quartiers_a_Montpellier tbody tr')).toHaveCount(5);
await expect(project.attributeTableHtml(layerName).locator('tbody tr')).toHaveCount(5);

const getFeatureRequestPromise = page.waitForRequest(request => request.method() === 'POST' && request.postData() != null && request.postData()?.includes('GetFeature') === true);
// bbox in getFeature request for export
Expand Down
34 changes: 13 additions & 21 deletions tests/end2end/playwright/edition-form.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// @ts-check
import { test, expect } from '@playwright/test';
import { gotoMap } from './globals';
import {ProjectPage} from "./pages/project-page";

test.describe('Edition Form Validation', () => {

Expand All @@ -10,9 +11,8 @@ test.describe('Edition Form Validation', () => {
});

test('Input type number with range and step', async ({ page }) => {
// display form
await page.locator('#button-edition').click();
await page.locator('a#edition-draw').click();
const project = new ProjectPage(page, 'form_edition_all_field_type');
await project.openEditingFormWithLayer('form_edition_all_fields_types');

// ensure input attributes match with field config defined in project
await expect(page.locator('#jforms_view_edition input[name="integer_field"]')).toHaveAttribute('type', 'number')
Expand All @@ -24,22 +24,17 @@ test.describe('Edition Form Validation', () => {
await page.locator('#jforms_view_edition input[name="integer_field"]').fill('50');

// submit form
await page.locator('#jforms_view_edition__submit_submit').click();
// will close & show message
await expect(page.locator('#edition-form-container')).toBeHidden();
await expect(page.locator('#lizmap-edition-message')).toBeVisible();
await project.editingSubmitForm()
})

test('Boolean nullable w/ value map', async ({ page }) => {

let editFeatureRequestPromise = page.waitForResponse(response => response.url().includes('editFeature'));

await page.locator('#button-edition').click();
await page.locator('#edition-layer').selectOption({ label: 'many_bool_formats' });
await page.locator('#edition-draw').click();
await page.locator('#jforms_view_edition_liz_future_action').selectOption('edit');
const project = new ProjectPage(page, 'form_edition_all_field_type');
await project.openEditingFormWithLayer('many_bool_formats');
await page.getByLabel('bool_simple_null_vm').selectOption('t');
await page.locator('#jforms_view_edition__submit_submit').click();
await project.editingSubmitForm('edit');

await editFeatureRequestPromise;

Expand All @@ -49,7 +44,7 @@ test.describe('Edition Form Validation', () => {
await expect(page.getByLabel('bool_simple_null_vm')).toHaveValue('t');

await page.getByLabel('bool_simple_null_vm').selectOption('');
await page.locator('#jforms_view_edition__submit_submit').click();
await project.editingSubmitForm('edit');

await editFeatureRequestPromise;

Expand All @@ -68,8 +63,8 @@ test.describe('Edition Form Validation', () => {
});
});

// display form
await page.locator('#button-edition').click();
const project = new ProjectPage(page, 'form_edition_all_field_type');
await project.buttonEditing.click();
await page.locator('a#edition-draw').click();

// message
Expand Down Expand Up @@ -522,12 +517,9 @@ test.describe('Text widget in a form', () => {

let getFeatureInfoRequestPromise = page.waitForRequest(request => request.method() === 'POST' && request.postData()?.includes('GetFeatureInfo') === true);

await page.locator('#newOlMap').click({
position: {
x: 354,
y: 370
}
});
const project = new ProjectPage(page, 'text_widget');

await project.clickOnMap(354, 370);

await getFeatureInfoRequestPromise;

Expand Down
10 changes: 4 additions & 6 deletions tests/end2end/playwright/media.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// @ts-check
import { test, expect } from '@playwright/test';
import { gotoMap } from './globals';
import {ProjectPage} from "./pages/project-page";

test.describe('Media', () => {
test('Tests media are deleted', async ({ page }) => {
Expand All @@ -17,14 +18,11 @@ test.describe('Media', () => {
await expect(response).toBeOK();

// Open the attribute table
const url = '/index.php/view/map?repository=testsrepository&project=form_edition_all_field_type';
await gotoMap(url, page);

await page.locator('#button-attributeLayers').click();

const project = new ProjectPage(page, 'form_edition_all_field_type');
await project.open();
let getFeatureRequestPromise = page.waitForRequest(request => request.method() === 'POST' && request.postData()?.includes('GetFeature') === true);

await page.locator('#attribute-layer-list button[value="form_edition_upload"]').click();
await project.openAttributeTable('form_edition_upload');
await getFeatureRequestPromise;

await page.getByRole('row', { name: '2 text_file_mandatory' }).getByRole('button').nth(2);
Expand Down
107 changes: 107 additions & 0 deletions tests/end2end/playwright/pages/project-page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import {expect, type Locator, type Page} from '@playwright/test';
import { gotoMap } from '../globals';

export class ProjectPage {
readonly page: Page;
// Metadata
readonly project: string;
readonly repository: string;

// Menu
readonly switcher: Locator;
readonly buttonEditing: Locator;

// Docks
readonly attributeTable: Locator;
readonly dock: Locator;
readonly rightDock: Locator;
readonly bottomDock: Locator;
readonly miniDock: Locator;

readonly search: Locator;

// Messages
readonly warningMessage: Locator;

// Attribute table for the given layer name
readonly attributeTableHtml = (name: string) =>
this.page.locator(`#attribute-layer-table-${name}`);

constructor(page: Page, project: string) {
this.page = page;
this.project = project;
this.repository = 'testsrepository';
this.dock = page.locator('#dock');
this.rightDock = page.locator('#right-dock');
this.bottomDock = page.locator('#bottom-dock');
this.miniDock = page.locator('#mini-dock-content');
this.warningMessage = page.locator('#lizmap-warning-message');
this.search = page.locator('#search-query');
this.switcher = page.locator('#button-switcher');
this.buttonEditing = page.locator('#button-edition');
}

async open(){
await gotoMap(`/index.php/view/map?repository=${this.repository}&project=${this.project}`, this.page);
}

/**
* openAttributeTable function
* Open the attribute table for the given layer
* @param {string} layer Name of the layer
* @param {boolean} maximise If the attribute table must be maximised
*/
async openAttributeTable(layer: string, maximise: boolean = false){
await this.page.locator('a#button-attributeLayers').click();
if (maximise) {
await this.page.getByRole('button', { name: 'Maximize' }).click();
}
await this.page.locator('#attribute-layer-list-table').locator(`button[value=${layer}]`).click();
}

/**
* editingSubmitForm function
* Submit the form
* @param {string} futureAction The action to do after submit : can be close/create/edit.
*/
async editingSubmitForm(futureAction: string = 'close'){
await this.page.locator('#jforms_view_edition_liz_future_action').selectOption(futureAction);
await this.page.locator('#jforms_view_edition__submit_submit').click();
if (futureAction == 'close'){
await expect(this.page.locator('#edition-form-container')).toBeHidden();
} else {
await expect(this.page.locator('#edition-form-container')).toBeVisible();
}
await expect(this.page.locator('#lizmap-edition-message')).toBeVisible();
}

/**
* openEditingFormWithLayer function
* Open the editing panel with the given layer name form
* @param {string} layer Name of the layer
*/
async openEditingFormWithLayer(layer: string){
await this.buttonEditing.click();
await this.page.locator('#edition-layer').selectOption({ label: layer });
await this.page.locator('a#edition-draw').click();
}

async openLayersPanel(){
await this.switcher.click();
}

/**
* clickOnMap function
* Click on the map at the given position
* @param {number} x Position X on the map
* @param {number} y Position Y on the map
*/
async clickOnMap(x: number, y: number){
await this.page.locator('#newOlMap').click({
position: {
x: x,
y: y
}
});
}
}
16 changes: 7 additions & 9 deletions tests/end2end/playwright/project_load_warning.spec.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
// @ts-check
import { test, expect } from '@playwright/test';
import { gotoMap } from './globals';
import { ProjectPage } from './pages/project-page';

test.describe('Project warnings in CFG as admin', () => {
test.use({ storageState: 'playwright/.auth/admin.json' });

test('Visit map with a warning', async ({ page }) => {
const url = '/index.php/view/map?repository=testsrepository&project=project_cfg_warnings';
await gotoMap(url, page)

await expect(page.locator("#lizmap-warning-message")).toBeVisible();
const project = new ProjectPage(page, 'project_cfg_warnings');
await project.open();
await expect(project.warningMessage).toBeVisible();
});

});

test.describe('Project warnings in CFG as anonymous', () => {

test('Visit map without a warning', async ({ page }) => {
const url = '/index.php/view/map?repository=testsrepository&project=project_cfg_warnings';
await gotoMap(url, page)

await expect(page.locator("#lizmap-warning-message")).toHaveCount(0);
const project = new ProjectPage(page, 'project_cfg_warnings');
await project.open();
await expect(project.warningMessage).toHaveCount(0);
});

});
Loading

0 comments on commit c01abd1

Please sign in to comment.