From feddcaaff7792710b52d4a5d9d26adf1a2bf560d Mon Sep 17 00:00:00 2001 From: Etienne Trimaille Date: Mon, 20 Jan 2025 11:48:59 +0100 Subject: [PATCH] Tests - Move HTTP requests metadata from Cypress to Playwright --- .../integration/requests-metadata-ghaction.js | 222 ----------------- tests/end2end/playwright/auth.setup.ts | 41 ++- .../playwright/requests-metadata.spec.js | 233 ++++++++++++++++++ 3 files changed, 253 insertions(+), 243 deletions(-) delete mode 100644 tests/end2end/cypress/integration/requests-metadata-ghaction.js create mode 100644 tests/end2end/playwright/requests-metadata.spec.js diff --git a/tests/end2end/cypress/integration/requests-metadata-ghaction.js b/tests/end2end/cypress/integration/requests-metadata-ghaction.js deleted file mode 100644 index b6f2b46532..0000000000 --- a/tests/end2end/cypress/integration/requests-metadata-ghaction.js +++ /dev/null @@ -1,222 +0,0 @@ -describe('Request JSON metadata', function () { - it('As anonymous', function () { - cy.logout(); - - const metadata = cy.request({ - url: 'index.php/view/app/metadata', - failOnStatusCode: false, - }).then((response) => { - expect(response.status).to.eq(200); - expect(response.headers['content-type']).to.eq('application/json'); - expect(response.body.qgis_server_info.error).to.eq("NO_ACCESS") - }); - }) - - it('As admin using basic auth', function () { - cy.logout() - - const request = cy.request({ - url: 'index.php/view/app/metadata', - headers: { - authorization: 'Basic YWRtaW46YWRtaW4=', - }, - failOnStatusCode: false, - }).then((response) => { - expect(response.status).to.eq(200); - expect(response.headers['content-type']).to.eq('application/json'); - - // LWC Metadata - expect(response.body.info.version).to.exist; - expect(response.body.info.date).to.exist; - expect(response.body.info.commit).to.exist; - - // QGIS Server info - expect(response.body.qgis_server_info.py_qgis_server.found).to.eq(true) - expect(response.body.qgis_server_info.py_qgis_server.version).to.match(/\.|n\/a/i) - expect(response.body.qgis_server_info.metadata.version).to.contain('3.') - expect(response.body.qgis_server_info.plugins.lizmap_server.version).to.match(/(\d+\.\d+|master|dev)/i) - - // Modules - expect(response.body.modules.lizmapdemo.version).to.match(/\d+\.\d+/i) - - // Desktop plugin - expect(response.body.lizmap_desktop_plugin_version).to.match(/(\d{5,6})/i) - - // check the repositories - expect(response.body.repositories.testsrepository.label).to.eq("Tests repository"); - expect(response.body.repositories.testsrepository.path).to.eq("tests/"); - expect(response.body.repositories.testsrepository.authorized_groups.sort()).to.deep.eq( - [ - "__anonymous", - "admins", - "group_a", - "group_b", - "publishers" - ].sort() - ); - expect(response.body.repositories.testsrepository.authorized_groups.sort()).to.deep.eq( - [ - "__anonymous", - "admins", - "group_a", - "group_b", - "publishers" - ].sort() - ); - expect(response.body.repositories.montpellier.projects).to.deep.eq( - { - "events": { - "title": "Touristic events around Montpellier, France" - }, - "montpellier": { - "title": "Montpellier - Transports" - } - } - ); - - // check the groups of users - expect(response.body.acl.groups).to.deep.eq( - { - "admins": { - "label": "admins" - }, - "group_a": { - "label": "group_a" - }, - "group_b": { - "label": "group_b" - }, - "intranet": { - "label": "Intranet demos group" - }, - "lizadmins": { - "label": "lizadmins" - }, - "publishers": { - "label": "Publishers" - }, - "users": { - "label": "users" - } - } - ) - - }); - }) - - it('As admin after login using the UI', function () { - cy.loginAsAdmin() - - const request = cy.request({ - url: 'index.php/view/app/metadata', - failOnStatusCode: false, - }).then((response) => { - expect(response.status).to.eq(200); - expect(response.headers['content-type']).to.eq('application/json'); - - expect(response.body.qgis_server_info.py_qgis_server.found).to.eq(true) - expect(response.body.qgis_server_info.py_qgis_server.version).to.match(/\.|n\/a/i) - expect(response.body.qgis_server_info.metadata.version).to.contain('3.') - expect(response.body.qgis_server_info.plugins.lizmap_server.version).to.match(/(\d+\.\d+|master|dev)/i) - }); - }) - - it('As normal user using UI', function () { - cy.loginAsUserA() - - const request = cy.request({ - url: 'index.php/view/app/metadata', - failOnStatusCode: false, - }).then((response) => { - expect(response.status).to.eq(200); - expect(response.headers['content-type']).to.eq('application/json'); - expect(response.body.qgis_server_info.error).to.eq("NO_ACCESS") - - }); - }) - - - - it('As publisher user using UI', function () { - cy.loginAsPublisher() - - const request = cy.request({ - url: 'index.php/view/app/metadata', - failOnStatusCode: false, - }).then((response) => { - expect(response.status).to.eq(200); - expect(response.headers['content-type']).to.eq('application/json'); - expect(response.body.qgis_server_info.py_qgis_server.found).to.eq(true) - - // Desktop plugin - expect(response.body.lizmap_desktop_plugin_version).to.match(/(\d{5,6})/i) - - // check the repositories - expect(response.body.repositories.testsrepository.label).to.eq("Tests repository"); - expect(response.body.repositories.testsrepository.path).to.eq("tests/"); - expect(response.body.repositories.testsrepository.authorized_groups.sort()).to.deep.eq( - [ - "__anonymous", - "admins", - "group_a", - "group_b", - "publishers" - ].sort() - ); - expect(response.body.repositories.testsrepository.authorized_groups.sort()).to.deep.eq( - [ - "__anonymous", - "admins", - "group_a", - "group_b", - "publishers" - ].sort() - ); - expect(response.body.repositories.testsrepository.projects.events.title).to.eq('Touristic events around Montpellier, France'); - - // check the groups of users - expect(response.body.acl.groups).to.deep.eq( - { - "admins": { - "label": "admins" - }, - "group_a": { - "label": "group_a" - }, - "group_b": { - "label": "group_b" - }, - "intranet": { - "label": "Intranet demos group" - }, - "lizadmins": { - "label": "lizadmins" - }, - "publishers": { - "label": "Publishers" - }, - "users": { - "label": "users" - } - } - ) - }); - - }) - - it('As publisher using BASIC Auth with wrong credentials', function () { - const request = cy.request({ - url: 'index.php/view/app/metadata', - headers: { - authorization: 'Basic dXNlcl9pbl9ncm91cF9hOm1hdXZhaXM=', - }, - failOnStatusCode: false, - }).then((response) => { - expect(response.headers['content-type']).to.eq('application/json'); - expect(response.body.qgis_server_info.error).to.eq("WRONG_CREDENTIALS") - expect(response.body.api.dataviz.version).to.eq("1.0.0") - }); - }) - - -}) diff --git a/tests/end2end/playwright/auth.setup.ts b/tests/end2end/playwright/auth.setup.ts index 43caac4b72..39434ea762 100644 --- a/tests/end2end/playwright/auth.setup.ts +++ b/tests/end2end/playwright/auth.setup.ts @@ -1,40 +1,39 @@ import { test as setup } from '@playwright/test'; +// @ts-ignore import path from 'path'; +import { Page } from '@playwright/test'; -const user_in_group_aFile = path.join(__dirname, './.auth/user_in_group_a.json'); -setup('authenticate as user_in_group_a', async ({ page }) => { +/** + * Performs the authentication steps + * @param {Page} page The page object + * @param {string} login The login + * @param {string} password The password + * @param {string} user_file The path to the file where the cookies will be stored + */ +export async function auth_using_login(page: Page, login: string, password: string, user_file: string) { // Perform authentication steps. Replace these actions with your own. await page.goto('admin.php/auth/login?auth_url_return=%2Findex.php'); - await page.locator('#jforms_jcommunity_login_auth_login').fill('user_in_group_a'); - await page.locator('#jforms_jcommunity_login_auth_password').fill('admin'); + await page.locator('#jforms_jcommunity_login_auth_login').fill(login); + await page.locator('#jforms_jcommunity_login_auth_password').fill(password); await page.getByRole('button', { name: 'Sign in' }).click(); // Wait until the page receives the cookies. - // // Sometimes login flow sets cookies in the process of several redirects. // Wait for the final URL to ensure that the cookies are actually set. await page.waitForURL('index.php'); // End of authentication steps. + await page.context().storageState({ path: user_file }); +} - await page.context().storageState({ path: user_in_group_aFile }); +setup('authenticate as user_in_group_a', async ({ page }) => { + await auth_using_login(page, 'user_in_group_a', 'admin', path.join(__dirname, './.auth/user_in_group_a.json')); }); -const adminFile = path.join(__dirname, './.auth/admin.json'); - setup('authenticate as admin', async ({ page }) => { - // Perform authentication steps. Replace these actions with your own. - await page.goto('admin.php/auth/login?auth_url_return=%2Findex.php'); - await page.locator('#jforms_jcommunity_login_auth_login').fill('admin'); - await page.locator('#jforms_jcommunity_login_auth_password').fill('admin'); - await page.getByRole('button', { name: 'Sign in' }).click(); - // Wait until the page receives the cookies. - // - // Sometimes login flow sets cookies in the process of several redirects. - // Wait for the final URL to ensure that the cookies are actually set. - await page.waitForURL('index.php'); - - // End of authentication steps. + await auth_using_login(page, 'admin', 'admin', path.join(__dirname, './.auth/admin.json')); +}); - await page.context().storageState({ path: adminFile }); +setup('authenticate as publisher', async ({ page }) => { + await auth_using_login(page, 'publisher', 'admin', path.join(__dirname, './.auth/publisher.json')); }); diff --git a/tests/end2end/playwright/requests-metadata.spec.js b/tests/end2end/playwright/requests-metadata.spec.js new file mode 100644 index 0000000000..ffa8fb6a23 --- /dev/null +++ b/tests/end2end/playwright/requests-metadata.spec.js @@ -0,0 +1,233 @@ +// @ts-check +import { test, expect } from '@playwright/test'; + +const url = 'index.php/view/app/metadata'; + +/** + * Check for a JSON response about the metadata + * @param {Response} response The response object + * + * @return {JSON} The JSON response + */ +export async function checkJson(response) { + expect(response.ok()).toBeTruthy(); + expect(response.status()).toBe(200); + expect(response.headers()['content-type']).toBe('application/json'); + const json = await response.json(); + + // LWC metadata are always accessible... + expect(json.info.version).toBeDefined(); + expect(json.info.date).toBeDefined(); + expect(json.info.commit).toBeDefined(); + return json; +} + +test.describe('Not connected from context, so testing basic auth', + { + tag: ['@requests', '@readonly'], + }, () => { + + test('As anonymous', async ({request}) => { + const response = await request.get(url, {}); + const json = await checkJson(response); + // Only testing the access to qgis_server_info + expect(json.qgis_server_info.error).toBe("NO_ACCESS") + }); + + test('Wrong credentials', async ({request}) => { + const response = await request.get( + url, + { + headers: { + authorization: 'Basic dXNlcl9pbl9ncm91cF9hOm1hdXZhaXM' + } + }); + const json = await checkJson(response); + // Only testing the access to qgis_server_info + expect(json.qgis_server_info.error).toBe("WRONG_CREDENTIALS") + }); + + test('As admin', async ({request}) => { + const response = await request.get( + url, + { + headers: { + authorization: 'Basic YWRtaW46YWRtaW4=', + } + }); + const json = await checkJson(response); + // Only testing the access to qgis_server_info + expect(json.qgis_server_info.metadata.name).toBeDefined(); + }); +}); + +test.describe('Connected from context, as a normal user', + { + tag: ['@requests', '@readonly'], + }, + () => { + + test.use({ storageState: 'playwright/.auth/user_in_group_a.json' }); + + test('Request metadata', async ({ request }) => { + const response = await request.get(url, {}); + const json = await checkJson(response); + // Only testing the access to qgis_server_info + expect(json.qgis_server_info.error).toBe("NO_ACCESS"); + }); +}); + +test.describe('Connected from context, as a publisher', + { + tag: ['@requests', '@readonly'], + }, + () => { + + test.use({ storageState: 'playwright/.auth/publisher.json' }); + + test('Checking JSON metadata content as a publisher', async ({ request }) => { + const response = await request.get(url, {}); + const json = await checkJson(response); + // More checks are done on admin tests below + expect(json.qgis_server_info.metadata.name).toBeDefined(); + + // Desktop plugin + expect(json.lizmap_desktop_plugin_version).toBeGreaterThan(10000); + + // Repositories + expect(json.repositories.testsrepository.label).toBe("Tests repository"); + expect(json.repositories.testsrepository.path).toBe("tests/"); + expect(json.repositories.testsrepository.authorized_groups.sort()).toStrictEqual( + [ + "__anonymous", + "admins", + "group_a", + "group_b", + "publishers" + ].sort() + ); + expect(json.repositories.testsrepository.authorized_groups.sort()).toStrictEqual( + [ + "__anonymous", + "admins", + "group_a", + "group_b", + "publishers" + ].sort() + ); + expect(json.repositories.testsrepository.projects.events.title).toBe('Touristic events around Montpellier, France'); + + // Check the groups of users + expect(json.acl.groups).toStrictEqual( + { + "admins": { + "label": "admins" + }, + "group_a": { + "label": "group_a" + }, + "group_b": { + "label": "group_b" + }, + "intranet": { + "label": "Intranet demos group" + }, + "lizadmins": { + "label": "lizadmins" + }, + "publishers": { + "label": "Publishers" + }, + "users": { + "label": "users" + } + } + ) + }); +}); + +test.describe('Request JSON metadata as admin, connected from context', + { + tag: ['@requests', '@readonly'], + }, + () => { + + test.use({ storageState: 'playwright/.auth/admin.json' }); + + test('Checking JSON metadata content as admin', async ({ request }) => { + const response = await request.get(url, {}); + const json = await checkJson(response); + + // QGIS Server info + expect(json.qgis_server_info.py_qgis_server.found).toBe(true); + expect(json.qgis_server_info.py_qgis_server.version).toMatch(/\.|n\/a/i); + expect(json.qgis_server_info.metadata.version).toContain('3.'); + expect(json.qgis_server_info.plugins.lizmap_server.version).toMatch(/(\d+\.\d+|master|dev)/i); + + // Modules + expect(json.modules.lizmapdemo.version).toMatch(/\d+\.\d+/i) + + // Desktop plugin + expect(json.lizmap_desktop_plugin_version).toBeGreaterThan(10000); + + // Repositories + expect(json.repositories.testsrepository.label).toBe("Tests repository"); + expect(json.repositories.testsrepository.path).toBe("tests/"); + expect(json.repositories.testsrepository.authorized_groups.sort()).toStrictEqual( + [ + "__anonymous", + "admins", + "group_a", + "group_b", + "publishers" + ].sort() + ); + expect(json.repositories.testsrepository.authorized_groups.sort()).toStrictEqual( + [ + "__anonymous", + "admins", + "group_a", + "group_b", + "publishers" + ].sort() + ); + expect(json.repositories.montpellier.projects).toStrictEqual( + { + "events": { + "title": "Touristic events around Montpellier, France" + }, + "montpellier": { + "title": "Montpellier - Transports" + } + } + ); + + // Check the groups of users + expect(json.acl.groups).toStrictEqual( + { + "admins": { + "label": "admins" + }, + "group_a": { + "label": "group_a" + }, + "group_b": { + "label": "group_b" + }, + "intranet": { + "label": "Intranet demos group" + }, + "lizadmins": { + "label": "lizadmins" + }, + "publishers": { + "label": "Publishers" + }, + "users": { + "label": "users" + } + } + ) + + }); +});