From 0096de9682181dede086a49eb77a961872191dbb Mon Sep 17 00:00:00 2001 From: kdaud Date: Mon, 4 Nov 2024 13:06:55 +0300 Subject: [PATCH] OZ-707: E2E tests verifying Odoo groups are synced to Keycloak. --- e2e/tests/keycloak-odoo-flows.spec.ts | 126 +++++++++++++++++++++++++- e2e/utils/functions/keycloak.ts | 7 ++ e2e/utils/functions/odoo.ts | 76 +++++++++++++++- package.json | 2 +- playwright.config.ts | 6 +- 5 files changed, 208 insertions(+), 9 deletions(-) diff --git a/e2e/tests/keycloak-odoo-flows.spec.ts b/e2e/tests/keycloak-odoo-flows.spec.ts index 9cec60a..fdd26ce 100644 --- a/e2e/tests/keycloak-odoo-flows.spec.ts +++ b/e2e/tests/keycloak-odoo-flows.spec.ts @@ -1,8 +1,9 @@ import { test, expect } from '@playwright/test'; -import { KEYCLOAK_URL, ODOO_URL } from '../utils/configs/globalSetup'; -import { Odoo } from '../utils/functions/odoo'; +import { Odoo, randomOdooGroupName } from '../utils/functions/odoo'; import { OpenMRS } from '../utils/functions/openmrs'; import { Keycloak } from '../utils/functions/keycloak'; +import { KEYCLOAK_URL, ODOO_URL } from '../utils/configs/globalSetup'; +import { randomSupersetRoleName } from '../utils/functions/superset'; let odoo: Odoo; let openmrs: OpenMRS; @@ -42,6 +43,127 @@ test('Logging out from Odoo logs out the user from Keycloak.', async ({ page }) await expect(page).toHaveURL(/.*login/); }); +test('Existing Odoo groups are synced as roles in Keycloak.', async ({ page }) => { + // setup + await page.goto(`${ODOO_URL}`); + await odoo.enterLoginCredentials(); + await expect(page.locator('li.o_user_menu a span')).toHaveText(/administrator/i); + await odoo.activateDeveloperMode(); + + // replay + await odoo.navigateToGroups(); + await expect(page.getByText('Administration / Settings')).toBeVisible(); + await expect(page.getByText('Extra Rights / Technical Features')).toBeVisible(); + await expect(page.getByText('Invoicing / Billing Administrator')).toBeVisible(); + await expect(page.getByText('Technical / Discount on lines')).toBeVisible(); + await expect(page.getByText('User types / Portal')).toBeVisible(); + + // verify + await keycloak.open(); + await keycloak.navigateToClients(); + await keycloak.selectOdooId(); + await keycloak.selectRoles(); + await page.getByPlaceholder('Search role by name').fill('Administration / Settings'); + await page.getByRole('button', { name: 'Search' }).press('Enter'); + await expect(page.getByText('Administration / Settings')).toBeVisible(); + await page.getByPlaceholder('Search role by name').fill('Extra Rights / Technical Features'); + await page.getByRole('button', { name: 'Search' }).press('Enter'); + await expect(page.getByText('Extra Rights / Technical Features')).toBeVisible(); + await page.getByPlaceholder('Search role by name').fill('Invoicing / Billing Administrator'); + await page.getByRole('button', { name: 'Search' }).press('Enter'); + await expect(page.getByText('Invoicing / Billing Administrator')).toBeVisible(); + await page.getByPlaceholder('Search role by name').fill('Technical / Discount on lines'); + await page.getByRole('button', { name: 'Search' }).press('Enter'); + await expect(page.getByText('Technical / Discount on lines')).toBeVisible(); + await page.getByPlaceholder('Search role by name').fill('User types / Portal'); + await page.getByRole('button', { name: 'Search' }).press('Enter'); + await expect(page.getByText('User types / Portal')).toBeVisible(); +}); + +test('Creating an Odoo group creates the corresponding Keycloak role', async ({ page }) => { + // setup + await page.goto(`${ODOO_URL}`); + await odoo.enterLoginCredentials(); + await expect(page.locator('li.o_user_menu a span')).toHaveText(/administrator/i); + await odoo.activateDeveloperMode(); + + // replay + await odoo.navigateToGroups(); + await odoo.createGroup(); + + // verify + await keycloak.open(); + await keycloak.navigateToClients(); + await keycloak.selectOdooId(); + await keycloak.selectRoles(); + await keycloak.searchOdooRole(); + await expect(page.locator('tbody:nth-child(2) td:nth-child(1) a')).toHaveText(`${randomOdooGroupName.groupName}`); +}); +/* +test('Updating a synced Odoo group updates the corresponding Keycloak role.', async ({ page }) => { + // setup + await page.goto(`${ODOO_URL}`); + await odoo.enterLoginCredentials(); + await expect(page.locator('li.o_user_menu a span')).toHaveText(/administrator/i); + await odoo.activateDeveloperMode(); + await odoo.navigateToGroups(); + await odoo.createGroup(); + await keycloak.open(); + await keycloak.navigateToClients(); + await keycloak.selectOdooId(); + await keycloak.selectRoles(); + await keycloak.searchOdooRole(); + await expect(page.locator('tbody:nth-child(2) td:nth-child(1) a')).toHaveText(`${randomOdooGroupName.groupName}`); + + // replay + await page.goto(`${ODOO_URL}`); + await odoo.navigateToSettings(); + await odoo.navigateToGroups(); + await odoo.searchGroup(); + await odoo.updateGroup(); + + // verify + await page.goto(`${KEYCLOAK_URL}/admin/master/console`); + await keycloak.navigateToClients(); + await keycloak.selectOdooId(); + await keycloak.selectRoles(); + await keycloak.searchOdooRole(); + await expect(page.getByText(`${randomSupersetRoleName.roleName}`)).not.toBeVisible(); + await expect(page.getByText(`${randomSupersetRoleName.updatedRoleName}`)).toBeVisible(); +}); + +test('Deleting a synced Odoo group deletes the corresponding Keycloak role.', async ({ page }) => { + // setup + await page.goto(`${ODOO_URL}`); + await odoo.enterLoginCredentials(); + await expect(page.locator('li.o_user_menu a span')).toHaveText(/administrator/i); + await odoo.activateDeveloperMode(); + await odoo.navigateToGroups(); + await odoo.createGroup(); + await keycloak.open(); + await keycloak.navigateToClients(); + await keycloak.selectOdooId(); + await keycloak.selectRoles(); + await keycloak.searchOdooRole(); + await expect(page.locator('tbody:nth-child(2) td:nth-child(1) a')).toHaveText(`${randomOdooGroupName.groupName}`); + + // replay + await page.goto(`${ODOO_URL}`); + await odoo.navigateToSettings(); + await odoo.navigateToGroups(); + await odoo.searchGroup(); + await odoo.deleteGroup(); + + // verify + await page.goto(`${KEYCLOAK_URL}/admin/master/console`); + await keycloak.navigateToClients(); + await keycloak.selectOdooId(); + await keycloak.selectRoles(); + await keycloak.searchOdooRole(); + await expect(page.getByText(`${randomSupersetRoleName.roleName}`)).not.toBeVisible(); +}); + +*/ test.afterEach(async ({ page }) => { await page.close(); }); diff --git a/e2e/utils/functions/keycloak.ts b/e2e/utils/functions/keycloak.ts index 25e712c..9fe78e8 100644 --- a/e2e/utils/functions/keycloak.ts +++ b/e2e/utils/functions/keycloak.ts @@ -2,6 +2,7 @@ import { Page, expect } from '@playwright/test'; import { KEYCLOAK_URL } from '../configs/globalSetup'; import { randomSupersetRoleName } from './superset'; import { delay, randomOpenMRSRoleName } from './openmrs'; +import { randomOdooGroupName } from './odoo'; export var randomKeycloakRoleName = { roleName : `${(Math.random() + 1).toString(36).substring(2)}` @@ -82,6 +83,12 @@ export class Keycloak { await this.page.getByRole('button', { name: 'Search' }).press('Enter'); } + async searchOdooRole() { + await expect(this.page.getByPlaceholder('Search role by name')).toBeVisible(); + await this.page.getByPlaceholder('Search role by name').fill(`${randomOdooGroupName.groupName}`); + await this.page.getByRole('button', { name: 'Search' }).press('Enter'); + } + async navigateToClientAttributes() { await this.page.getByRole('link', { name: `${randomOpenMRSRoleName.roleName}` }).click(); await this.page.getByTestId('attributesTab').click(); diff --git a/e2e/utils/functions/odoo.ts b/e2e/utils/functions/odoo.ts index 01f0bf8..49e7b5e 100644 --- a/e2e/utils/functions/odoo.ts +++ b/e2e/utils/functions/odoo.ts @@ -3,21 +3,30 @@ import { ODOO_URL } from '../configs/globalSetup'; import { Keycloak } from './keycloak'; import { delay, patientName } from './openmrs'; +export var randomOdooGroupName = { + groupName : `${Array.from({ length: 8 }, () => String.fromCharCode(Math.floor(Math.random() * 26) + 97)).join('')}`, + updatedGroupName : `${Array.from({ length: 8 }, () => String.fromCharCode(Math.floor(Math.random() * 26) + 97)).join('')}` +} + export class Odoo { constructor(readonly page: Page) {} async open() { await this.page.goto(`${ODOO_URL}`); if (`${process.env.TEST_PRO}` == 'true') { - await this.page.locator('div.o_login_auth div a').click(); + await this.page.getByRole('link', { name: 'Login with Single Sign-On' }).click(); } else { - await this.page.locator('#login').fill(`${process.env.ODOO_USERNAME_ON_FOSS}`); - await this.page.locator('#password').fill(`${process.env.ODOO_PASSWORD_ON_FOSS}`); - await this.page.locator('button[type="submit"]').click(); + await this.enterLoginCredentials(); } await expect(this.page).toHaveURL(/.*web/); } + async enterLoginCredentials() { + await this.page.locator('#login').fill(`${process.env.ODOO_USERNAME_ON_FOSS}`); + await this.page.locator('#password').fill(`${process.env.ODOO_PASSWORD_ON_FOSS}`); + await this.page.locator('button[type="submit"]').click(); + } + async searchCustomer() { await expect(this.page.locator('.o_searchview_input')).toBeVisible(); await this.page.locator('.o_searchview_input').fill(`${patientName.firstName + ' ' + patientName.givenName}`); @@ -55,6 +64,65 @@ export class Odoo { await expect(this.page.locator('td.o_data_cell:nth-child(11)')).toHaveText('$ 16.00'); } + async activateDeveloperMode() { + await this.navigateToSettings(); + await expect(this.page.locator('#devel_tool a:nth-child(1)')).toBeVisible(); + await this.page.locator('#devel_tool a:nth-child(1)').click(); + } + + async navigateToGroups() { + await this.navigateToSettings(); + await expect(this.page.locator('ul.o_menu_sections>:nth-child(2)>a')).toBeVisible(); + await this.page.locator('ul.o_menu_sections>:nth-child(2)>a').click(); + await expect(this.page.getByRole('menuitem', { name: /groups/i })).toBeVisible(); + await this.page.getByRole('menuitem', { name: /groups/i }).click(); + } + + async navigateToSettings() { + await this.page.locator("//a[contains(@class, 'full')]").click(); + await expect(this.page.getByRole('menuitem', { name: /settings/i })).toBeVisible(); + await this.page.getByRole('menuitem', { name: /settings/i }).click(); + } + + async createGroup() { + await this.page.getByRole('button', { name: /create/i }).click(); + await this.page.getByLabel(/application/i).click(); + await expect(this.page.getByText(/accounting/i)).toBeVisible(); + await this.page.getByText(/accounting/i).click(); + await this.page.getByLabel(/name/i).fill(`${randomOdooGroupName.groupName}`); + await this.page.getByRole('button', { name: /save/i }).click(); + await delay(240000); + } + + async searchGroup() { + await this.page.getByLabel(/remove/i).click(); + await expect(this.page.locator('div>div>input')).toBeVisible(); + await this.page.locator('div>div>input').type(`${randomOdooGroupName.groupName}`); + await this.page.locator('div>div>input').press('Enter'); + await this.page.getByRole('cell', { name: `${randomOdooGroupName.groupName}` }).click(); + } + + async updateGroup() { + await expect(this.page.getByRole('button', { name: /edit/i })).toBeVisible(); + await this.page.getByRole('button', { name: /edit/i }).click(); + await this.page.getByLabel(/name/i).clear(); + await this.page.getByLabel(/name/i).fill(`${randomOdooGroupName.updatedGroupName}`); + await this.page.getByRole('button', { name: /save/i }).click(); + await delay(150000); + } + + async deleteGroup() { + await expect(this.page.getByRole('button', { name: /action/i })).toBeVisible(); + await this.page.getByRole('button', { name: /action/i }).click(); + await expect(this.page.getByRole('menuitemcheckbox', { name: /delete/i })).toBeVisible(); + await this.page.getByRole('menuitemcheckbox', { name: /delete/i }).click(); + await expect(this.page.getByRole('button', { name: /ok/i })).toBeVisible(); + await this.page.getByRole('button', { name: /ok/i }).click(); + await delay(2000); + await expect(this.page.getByText(`${randomOdooGroupName.groupName}` )).not.toBeVisible(); + await delay(150000); + } + async logout() { await this.page.goto(`${ODOO_URL}`); await expect(this.page.locator('.o_user_menu>a')).toBeVisible(); diff --git a/package.json b/package.json index 7c98608..e356f7c 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "!playwright-report/" ], "scripts": { - "ozone-pro": "npx playwright test", + "ozone-pro": "npx playwright test keycloak-odoo", "ozone-foss": "npx playwright test odoo-openmrs erpnext-openmrs openmrs-senaite", "openmrs-distro-his": "npx playwright test odoo-openmrs openmrs-senaite" }, diff --git a/playwright.config.ts b/playwright.config.ts index d4222e6..cbe7561 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -5,7 +5,7 @@ dotenv.config(); const config: PlaywrightTestConfig = { testDir: './e2e/tests', - timeout: 3 * 60 * 1000, + timeout: 4 * 60 * 1000, expect: { timeout: 40 * 1000, }, @@ -24,7 +24,9 @@ const config: PlaywrightTestConfig = { name: 'chromium', use: { ...devices['Desktop Chromium'], - viewport: { width: 1920, height: 1080 } + viewport: { width: 1920, height: 1080 }, + video: 'retain-on-failure', + screenshot: 'only-on-failure' }, },