From 65cca794ddbcf1100652d8def99b6d1e2c24377b Mon Sep 17 00:00:00 2001 From: Etienne Trimaille Date: Wed, 15 Jan 2025 15:23:19 +0100 Subject: [PATCH 1/2] Tests - Start Page Object Model for Playwright --- .../playwright/attribute-table.spec.js | 23 ++-- tests/end2end/playwright/edition-form.spec.js | 34 +++--- tests/end2end/playwright/media.spec.js | 10 +- tests/end2end/playwright/pages/project.ts | 107 ++++++++++++++++++ .../playwright/project_load_warning.spec.js | 16 ++- tests/end2end/playwright/snap.spec.js | 31 ++--- 6 files changed, 159 insertions(+), 62 deletions(-) create mode 100644 tests/end2end/playwright/pages/project.ts diff --git a/tests/end2end/playwright/attribute-table.spec.js b/tests/end2end/playwright/attribute-table.spec.js index f7b2111a59..404de3b33c 100644 --- a/tests/end2end/playwright/attribute-table.spec.js +++ b/tests/end2end/playwright/attribute-table.spec.js @@ -1,5 +1,6 @@ // @ts-check import { test, expect } from '@playwright/test'; +import { ProjectPage } from './pages/project'; import { gotoMap } from './globals'; test.describe('Attribute table', () => { @@ -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&/); }); }); @@ -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/); @@ -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 diff --git a/tests/end2end/playwright/edition-form.spec.js b/tests/end2end/playwright/edition-form.spec.js index c3cb3f19ec..c5eed37281 100644 --- a/tests/end2end/playwright/edition-form.spec.js +++ b/tests/end2end/playwright/edition-form.spec.js @@ -1,6 +1,7 @@ // @ts-check import { test, expect } from '@playwright/test'; import { gotoMap } from './globals'; +import {ProjectPage} from "./pages/project"; test.describe('Edition Form Validation', () => { @@ -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') @@ -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; @@ -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; @@ -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 @@ -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; diff --git a/tests/end2end/playwright/media.spec.js b/tests/end2end/playwright/media.spec.js index 7b10f64c81..cf59e1f9f2 100644 --- a/tests/end2end/playwright/media.spec.js +++ b/tests/end2end/playwright/media.spec.js @@ -1,6 +1,7 @@ // @ts-check import { test, expect } from '@playwright/test'; import { gotoMap } from './globals'; +import {ProjectPage} from "./pages/project"; test.describe('Media', () => { test('Tests media are deleted', async ({ page }) => { @@ -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); diff --git a/tests/end2end/playwright/pages/project.ts b/tests/end2end/playwright/pages/project.ts new file mode 100644 index 0000000000..93fa446775 --- /dev/null +++ b/tests/end2end/playwright/pages/project.ts @@ -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'); + } + + /** + * open function + * Open the project + */ + 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(); + } + + /** + * 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 + } + }); + } +} diff --git a/tests/end2end/playwright/project_load_warning.spec.js b/tests/end2end/playwright/project_load_warning.spec.js index bfc00fe84c..5446dfca8a 100644 --- a/tests/end2end/playwright/project_load_warning.spec.js +++ b/tests/end2end/playwright/project_load_warning.spec.js @@ -1,15 +1,14 @@ // @ts-check import { test, expect } from '@playwright/test'; -import { gotoMap } from './globals'; +import { ProjectPage } from './pages/project'; 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(); }); }); @@ -17,10 +16,9 @@ test.describe('Project warnings in CFG as admin', () => { 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); }); }); diff --git a/tests/end2end/playwright/snap.spec.js b/tests/end2end/playwright/snap.spec.js index 26d869e9cd..c4e7fad84a 100644 --- a/tests/end2end/playwright/snap.spec.js +++ b/tests/end2end/playwright/snap.spec.js @@ -1,6 +1,7 @@ // @ts-check import { test, expect } from '@playwright/test'; import { gotoMap } from './globals'; +import {ProjectPage} from "./pages/project"; test.describe('Snap on edition', () => { test.beforeEach(async ({ page }) => { @@ -12,29 +13,29 @@ test.describe('Snap on edition', () => { let editFeatureRequestPromise = page.waitForResponse(response => response.url().includes('editFeature')); - await page.locator('#button-edition').click(); - await page.locator('a#edition-draw').click(); + const project = new ProjectPage(page, 'form_edition_multilayer_snap'); + await project.openEditingFormWithLayer('form_edition_snap_control'); await editFeatureRequestPromise; await page.waitForTimeout(300); - // brefly check the form + // briefly check the form await expect(page.getByRole('heading', { name: 'form_edition_snap_control' })).toHaveText("form_edition_snap_control") await expect(page.getByLabel('id')).toBeVisible() // move to digitization panel await page.getByRole('tab', { name: 'Digitization' }).click() - let getSnappingPointFeatureRquestPromise = page.waitForRequest(request => request.method() === 'POST' && request.postData() != null && request.postData()?.includes('GetFeature') === true && request.postData()?.includes('form_edition_snap_point') === true); - let getSnappingPointDescribeFeatureRquestPromise = page.waitForRequest(request => request.method() === 'POST' && request.postData() != null && request.postData()?.includes('DescribeFeatureType') === true && request.postData()?.includes('form_edition_snap_point') === true); + let getSnappingPointFeatureRequestPromise = page.waitForRequest(request => request.method() === 'POST' && request.postData() != null && request.postData()?.includes('GetFeature') === true && request.postData()?.includes('form_edition_snap_point') === true); + let getSnappingPointDescribeFeatureRequestPromise = page.waitForRequest(request => request.method() === 'POST' && request.postData() != null && request.postData()?.includes('DescribeFeatureType') === true && request.postData()?.includes('form_edition_snap_point') === true); // activate snapping await page.getByRole('button', { name: 'Start' }).click(); - const allSnapPointResponses = await Promise.all([getSnappingPointFeatureRquestPromise, getSnappingPointDescribeFeatureRquestPromise]) + const allSnapPointResponses = await Promise.all([getSnappingPointFeatureRequestPromise, getSnappingPointDescribeFeatureRequestPromise]) - // check snap paneland controls + // check snap panel and controls await expect(page.locator("#edition-point-coord-form-group").getByRole("button").nth(2)).toBeDisabled(); //check layer list in the panel @@ -93,12 +94,12 @@ test.describe('Snap on edition', () => { // activate snap on line and refresh snap await page.locator("#edition-point-coord-form-group .snap-layers-list .snap-layer").nth(0).locator("input").check() - let getSnappingLineFeatureRquestPromise = page.waitForRequest(request => request.method() === 'POST' && request.postData() != null && request.postData()?.includes('GetFeature') === true && request.postData()?.includes('form_edition_snap_line') === true); - let getSnappingLineDescribeFeatureRquestPromise = page.waitForRequest(request => request.method() === 'POST' && request.postData() != null && request.postData()?.includes('DescribeFeatureType') === true && request.postData()?.includes('form_edition_snap_line') === true); + let getSnappingLineFeatureRequestPromise = page.waitForRequest(request => request.method() === 'POST' && request.postData() != null && request.postData()?.includes('GetFeature') === true && request.postData()?.includes('form_edition_snap_line') === true); + let getSnappingLineDescribeFeatureRequestPromise = page.waitForRequest(request => request.method() === 'POST' && request.postData() != null && request.postData()?.includes('DescribeFeatureType') === true && request.postData()?.includes('form_edition_snap_line') === true); await page.locator("#edition-point-coord-form-group").getByRole("button").nth(2).click() - const allSnapLineResponses = await Promise.all([getSnappingLineFeatureRquestPromise, getSnappingLineDescribeFeatureRquestPromise]) + const allSnapLineResponses = await Promise.all([getSnappingLineFeatureRequestPromise, getSnappingLineDescribeFeatureRequestPromise]) await page.waitForTimeout(300); @@ -142,19 +143,19 @@ test.describe('Snap on edition', () => { // activate snap on polygon and refresh snap await page.locator("#edition-point-coord-form-group .snap-layers-list .snap-layer").nth(2).locator("input").check() - let getSnappingPolygonFeatureRquestPromise = page.waitForRequest(request => request.method() === 'POST' && request.postData() != null && request.postData()?.includes('GetFeature') === true && request.postData()?.includes('form_edition_snap_polygon') === true); - let getSnappingPolygonDescribeFeatureRquestPromise = page.waitForRequest(request => request.method() === 'POST' && request.postData() != null && request.postData()?.includes('DescribeFeatureType') === true && request.postData()?.includes('form_edition_snap_polygon') === true); + let getSnappingPolygonFeatureRequestPromise = page.waitForRequest(request => request.method() === 'POST' && request.postData() != null && request.postData()?.includes('GetFeature') === true && request.postData()?.includes('form_edition_snap_polygon') === true); + let getSnappingPolygonDescribeFeatureRequestPromise = page.waitForRequest(request => request.method() === 'POST' && request.postData() != null && request.postData()?.includes('DescribeFeatureType') === true && request.postData()?.includes('form_edition_snap_polygon') === true); await page.locator("#edition-point-coord-form-group").getByRole("button").nth(2).click() - const allSnapPolygonResponses = await Promise.all([getSnappingPolygonFeatureRquestPromise, getSnappingPolygonDescribeFeatureRquestPromise]) + const allSnapPolygonResponses = await Promise.all([getSnappingPolygonFeatureRequestPromise, getSnappingPolygonDescribeFeatureRequestPromise]) await page.waitForTimeout(300); await expect(page.locator("#edition-point-coord-form-group").getByRole("button").nth(2)).toBeDisabled(); // disable all layer - await page.locator('#button-switcher').click(); + await project.switcher.click(); await page.getByTestId('form_edition_snap_point').getByLabel('Point snap').click(); await page.getByTestId('form_edition_snap_line').getByLabel('Line snap').click(); await page.getByTestId('form_edition_snap_polygon').getByLabel('Polygon snap').click(); @@ -188,7 +189,7 @@ test.describe('Snap on edition', () => { // back to layers tree, enable line layer and polygon layer to reorder the snap layer list - await page.locator('#button-switcher').click(); + await project.switcher.click(); await page.getByTestId('form_edition_snap_line').getByLabel('Line snap').click(); await page.getByTestId('form_edition_snap_polygon').getByLabel('Polygon snap').click(); From e92bf171cfc7be9af0bb7aa07750c15c903c1613 Mon Sep 17 00:00:00 2001 From: Etienne Trimaille Date: Thu, 16 Jan 2025 09:06:15 +0100 Subject: [PATCH 2/2] Tests - POM, switch from ts to spec.js file --- .../pages/{project.ts => project.js} | 104 ++++++++++++++---- 1 file changed, 80 insertions(+), 24 deletions(-) rename tests/end2end/playwright/pages/{project.ts => project.js} (61%) diff --git a/tests/end2end/playwright/pages/project.ts b/tests/end2end/playwright/pages/project.js similarity index 61% rename from tests/end2end/playwright/pages/project.ts rename to tests/end2end/playwright/pages/project.js index 93fa446775..027cfc9e77 100644 --- a/tests/end2end/playwright/pages/project.ts +++ b/tests/end2end/playwright/pages/project.js @@ -1,36 +1,92 @@ -import {expect, type Locator, type Page} from '@playwright/test'; +// @ts-check +import {expect, Locator, Page} from '@playwright/test'; import { gotoMap } from '../globals'; export class ProjectPage { - readonly page: Page; + /** @type {Page} */ + page; + // Metadata - readonly project: string; - readonly repository: string; + /** + * Project name metadata + * @type {string} + */ + project; + /** + * Repository name metadata + * @type {string} + */ + repository; // Menu - readonly switcher: Locator; - readonly buttonEditing: Locator; + /** + * Layer switcher menu + * @type {Locator} + */ + switcher; + /** + * Editing menu + * @type {Locator} + */ + buttonEditing; // Docks - readonly attributeTable: Locator; - readonly dock: Locator; - readonly rightDock: Locator; - readonly bottomDock: Locator; - readonly miniDock: Locator; - - readonly search: Locator; + /** + * Attribute table dock + * @type {Locator} + */ + attributeTable; + /** + * Main left dock + * @type {Locator} + */ + dock; + /** + * Right dock + * @type {Locator} + */ + rightDock; + /** + * Bottom dock + * @type {Locator} + */ + bottomDock; + /** + * Mini dock + * @type {Locator} + */ + miniDock; + /** + * Top search bar + * @type {Locator} + */ + search; // Messages - readonly warningMessage: Locator; + /** + * Foreground message bar + * @type {Locator} + */ + warningMessage; - // Attribute table for the given layer name - readonly attributeTableHtml = (name: string) => + /** + * Attribute table for the given layer name + * @param {string} name Name of the layer + * @returns {Locator} + */ + attributeTableHtml = (name) => this.page.locator(`#attribute-layer-table-${name}`); - constructor(page: Page, project: string) { + /** + * Constructor + * @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; this.project = project; - this.repository = 'testsrepository'; + this.repository = repository; this.dock = page.locator('#dock'); this.rightDock = page.locator('#right-dock'); this.bottomDock = page.locator('#bottom-dock'); @@ -43,7 +99,7 @@ export class ProjectPage { /** * open function - * Open the project + * Open the URL for the given project and repository */ async open(){ await gotoMap(`/index.php/view/map?repository=${this.repository}&project=${this.project}`, this.page); @@ -55,7 +111,7 @@ export class ProjectPage { * @param {string} layer Name of the layer * @param {boolean} maximise If the attribute table must be maximised */ - async openAttributeTable(layer: string, maximise: boolean = false){ + async openAttributeTable(layer, maximise = false){ await this.page.locator('a#button-attributeLayers').click(); if (maximise) { await this.page.getByRole('button', { name: 'Maximize' }).click(); @@ -68,10 +124,10 @@ export class ProjectPage { * Submit the form * @param {string} futureAction The action to do after submit : can be close/create/edit. */ - async editingSubmitForm(futureAction: string = 'close'){ + async editingSubmitForm(futureAction = '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'){ + if (futureAction === 'close'){ await expect(this.page.locator('#edition-form-container')).toBeHidden(); } else { await expect(this.page.locator('#edition-form-container')).toBeVisible(); @@ -84,7 +140,7 @@ export class ProjectPage { * Open the editing panel with the given layer name form * @param {string} layer Name of the layer */ - async openEditingFormWithLayer(layer: string){ + async openEditingFormWithLayer(layer){ await this.buttonEditing.click(); await this.page.locator('#edition-layer').selectOption({ label: layer }); await this.page.locator('a#edition-draw').click(); @@ -96,7 +152,7 @@ export class ProjectPage { * @param {number} x Position X on the map * @param {number} y Position Y on the map */ - async clickOnMap(x: number, y: number){ + async clickOnMap(x, y){ await this.page.locator('#newOlMap').click({ position: { x: x,