Skip to content

Commit

Permalink
OZ-711: Modifying the details of a sale order in Odoo should update t…
Browse files Browse the repository at this point in the history
…he respective entry in Superset's sale_order_lines table.
  • Loading branch information
kdaud committed Jan 9, 2025
1 parent 4d423e6 commit c754ef8
Show file tree
Hide file tree
Showing 9 changed files with 185 additions and 19 deletions.
3 changes: 3 additions & 0 deletions e2e/tests/keycloak-odoo-flows.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ test('Coded Odoo groups create corresponding Keycloak roles.', async ({ page })

test('Creating an Odoo group creates the corresponding Keycloak role', async ({ page }) => {
// setup
test.setTimeout(360000);
await page.goto(`${ODOO_URL}`);
await odoo.enterLoginCredentials();
await expect(page.locator('li.o_user_menu a span')).toHaveText(/administrator/i);
Expand All @@ -100,6 +101,7 @@ test('Creating an Odoo group creates the corresponding Keycloak role', async ({

test('Updating a synced Odoo group updates the corresponding Keycloak role.', async ({ page }) => {
// setup
test.setTimeout(720000);
await page.goto(`${ODOO_URL}`);
await odoo.enterLoginCredentials();
await expect(page.locator('li.o_user_menu a span')).toHaveText(/administrator/i);
Expand Down Expand Up @@ -131,6 +133,7 @@ test('Updating a synced Odoo group updates the corresponding Keycloak role.', as

test('Deleting a synced Odoo group deletes the corresponding Keycloak role.', async ({ page }) => {
// setup
test.setTimeout(720000);
await page.goto(`${ODOO_URL}`);
await odoo.enterLoginCredentials();
await expect(page.locator('li.o_user_menu a span')).toHaveText(/administrator/i);
Expand Down
3 changes: 3 additions & 0 deletions e2e/tests/keycloak-openmrs-flows.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ test('Logging out from OpenMRS ends the session in Keycloak and logs out the use

test('Creating an OpenMRS role creates the corresponding Keycloak role.', async ({ page }) => {
// setup
test.setTimeout(240000);
await page.goto(`${O3_URL}/openmrs/admin/users/role.list`);

// replay
Expand All @@ -62,6 +63,7 @@ test('Creating an OpenMRS role creates the corresponding Keycloak role.', async

test('Updating a synced OpenMRS role updates the corresponding Keycloak role.', async ({ page }) => {
// setup
test.setTimeout(420000);
await page.goto(`${O3_URL}/openmrs/admin/users/role.list`);
await openmrs.addRole();
await keycloak.open();
Expand Down Expand Up @@ -98,6 +100,7 @@ test('Updating a synced OpenMRS role updates the corresponding Keycloak role.',

test('Deleting a synced OpenMRS role deletes the corresponding Keycloak role.', async ({ page }) => {
// setup
test.setTimeout(420000);
await page.goto(`${O3_URL}/openmrs/admin/users/role.list`);
await openmrs.addRole();
await keycloak.open();
Expand Down
1 change: 0 additions & 1 deletion e2e/tests/keycloak-senaite-flows.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ test('Logging out from SENAITE ends the session in Keycloak and logs out the use

// replay
await senaite.logout();
await keycloak.confirmLogout();
await expect(page.locator('#username')).toBeVisible();

// verify
Expand Down
128 changes: 126 additions & 2 deletions e2e/tests/odoo-superset-flows.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { test, expect } from '@playwright/test';
import { O3_URL, SUPERSET_URL } from '../utils/configs/globalSetup';
import { O3_URL, ODOO_URL, SUPERSET_URL } from '../utils/configs/globalSetup';
import { Odoo } from '../utils/functions/odoo';
import { Superset } from '../utils/functions/superset';
import { OpenMRS, patientName } from '../utils/functions/openmrs';
import { delay, OpenMRS, patientName } from '../utils/functions/openmrs';

let odoo: Odoo;
let openmrs: OpenMRS;
Expand Down Expand Up @@ -62,6 +62,130 @@ test(`Creating an Odoo sale order line generates an entry in Superset's sale_ord
await expect(unitPrice).toBe(2);
});

test(`Revising an Odoo sale order line modifies the corresponding entry in Superset's sale_order_lines table.`, async ({ page }) => {
// setup
await openmrs.searchPatient(`${patientName.firstName + ' ' + patientName.givenName}`);
await openmrs.navigateToLabOrderForm();
await page.getByRole('searchbox').fill('Complete blood count');
await openmrs.saveLabOrder();

await odoo.open();
await odoo.navigateToSales();
await odoo.createSaleOrderLine();
const salesOrderId = await page.locator('.oe_title h1:nth-child(1) span').textContent();
await expect(page.locator('table tbody td.o_data_cell:nth-child(2) span:nth-child(1) span')).toHaveText('Acétaminophene Co 500mg');

await superset.open();
await superset.selectDBSchema();
await superset.clearSQLEditor();
let saleOrderLinesQuery = `SELECT sale_order_name, customer_name, product_name, quantity, unit_price FROM sale_order_lines WHERE sale_order_name like '${salesOrderId}';`;
await page.getByRole('textbox').first().fill(saleOrderLinesQuery);
await superset.runSQLQuery();
await expect(page.locator('div.virtual-table-cell:nth-child(1)')).toHaveText(`${salesOrderId}`);
await expect(page.locator('div.virtual-table-cell:nth-child(2)')).toHaveText(`${patientName.firstName + ' ' + patientName.givenName}`);
await expect(page.locator('div.virtual-table-cell:nth-child(3)')).toHaveText('Acétaminophene Co 500mg');
await expect(page.locator('div.virtual-table-cell:nth-child(4)')).toHaveText('8');
await expect(page.locator('div.virtual-table-cell:nth-child(5)')).toHaveText('2');

// replay
await page.goto(`${ODOO_URL}`);
await odoo.navigateToSales();
await odoo.searchCustomer();
await page.getByRole('cell', { name: `${patientName.firstName + ' ' + patientName.givenName}` }).nth(0).click();
await odoo.modifySaleOrderLine();

// verify
await page.goto(`${SUPERSET_URL}/sqllab`);
await superset.clearSQLEditor();
await page.getByRole('textbox').first().fill(saleOrderLinesQuery);
await superset.runSQLQuery();
await expect(page.locator('div.virtual-table-cell:nth-child(1)')).toHaveText(`${salesOrderId}`);
await expect(page.locator('div.virtual-table-cell:nth-child(2)')).toHaveText(`${patientName.firstName + ' ' + patientName.givenName}`);
await expect(page.locator('div.virtual-table-cell:nth-child(3)')).toHaveText('Acétaminophene Co 500mg');
await expect(page.locator('div.virtual-table-cell:nth-child(4)')).toHaveText('10');
await expect(page.locator('div.virtual-table-cell:nth-child(5)')).toHaveText('3');
});

test(`Voiding an Odoo sale order line updates the corresponding entry in Superset's sale_order_lines table.`, async ({ page }) => {
// setup
await openmrs.searchPatient(`${patientName.firstName + ' ' + patientName.givenName}`);
await openmrs.navigateToLabOrderForm();
await page.getByRole('searchbox').fill('Complete blood count');
await openmrs.saveLabOrder();
await odoo.open();
await odoo.navigateToSales();
await odoo.createSaleOrderLine();
const salesOrderId = await page.locator('.oe_title h1:nth-child(1) span').textContent();
await expect(page.locator('table tbody td.o_data_cell:nth-child(2) span:nth-child(1) span')).toHaveText('Acétaminophene Co 500mg');
await superset.open();
await superset.selectDBSchema();
await superset.clearSQLEditor();
let saleOrderLinesQuery = `SELECT sale_order_name, customer_name, product_name, quantity, unit_price FROM sale_order_lines WHERE sale_order_name like '${salesOrderId}';`;
await page.getByRole('textbox').first().fill(saleOrderLinesQuery);
await superset.runSQLQuery();
await expect(page.locator('div.virtual-table-cell:nth-child(1)')).toHaveText(`${salesOrderId}`);
await expect(page.locator('div.virtual-table-cell:nth-child(2)')).toHaveText(`${patientName.firstName + ' ' + patientName.givenName}`);
await expect(page.locator('div.virtual-table-cell:nth-child(3)')).toHaveText('Acétaminophene Co 500mg');
await expect(page.locator('div.virtual-table-cell:nth-child(4)')).toHaveText('8');
await expect(page.locator('div.virtual-table-cell:nth-child(5)')).toHaveText('2');

// replay
await page.goto(`${ODOO_URL}`);
await odoo.navigateToSales();
await odoo.searchCustomer();
await page.getByRole('cell', { name: `${patientName.firstName + ' ' + patientName.givenName}` }).nth(0).click();
await odoo.voidSaleOrderLine();

// verify
await page.goto(`${SUPERSET_URL}/sqllab`);
await superset.clearSQLEditor();
await page.getByRole('textbox').first().fill(saleOrderLinesQuery);
await superset.runSQLQuery();
await expect(page.locator('div.virtual-table-cell:nth-child(1)')).toHaveText(`${salesOrderId}`);
await expect(page.locator('div.virtual-table-cell:nth-child(2)')).toHaveText(`${patientName.firstName + ' ' + patientName.givenName}`);
await expect(page.locator('div.virtual-table-cell:nth-child(3)')).toHaveText('Acétaminophene Co 500mg');
await expect(page.locator('div.virtual-table-cell:nth-child(4)')).not.toHaveText('8');
await expect(page.locator('div.virtual-table-cell:nth-child(4)')).toHaveText('0');
});

test(`Deleting an Odoo quotation line removes the corresponding entry in Superset's sale_order_lines table.`, async ({ page }) => {
// setup
await openmrs.searchPatient(`${patientName.firstName + ' ' + patientName.givenName}`);
await openmrs.navigateToLabOrderForm();
await page.getByRole('searchbox').fill('Complete blood count');
await openmrs.saveLabOrder();
await odoo.open();
await odoo.navigateToSales();
await odoo.createQuotationLine();
const salesOrderId = await page.locator('.oe_title h1:nth-child(1) span').textContent();
await expect(page.locator('table tbody td.o_data_cell:nth-child(2) span:nth-child(1) span')).toHaveText(/acyclovir Sirop 200mg/i);
await superset.open();
await superset.selectDBSchema();
await superset.clearSQLEditor();
let saleOrderLinesQuery = `SELECT sale_order_name, customer_name, product_name, quantity, unit_price FROM sale_order_lines WHERE sale_order_name like '${salesOrderId}';`;
await page.getByRole('textbox').first().fill(saleOrderLinesQuery);
await superset.runSQLQuery();
await expect(page.locator('div.virtual-table-cell:nth-child(1)')).toHaveText(`${salesOrderId}`);
await expect(page.locator('div.virtual-table-cell:nth-child(2)')).toHaveText(`${patientName.firstName + ' ' + patientName.givenName}`);
await expect(page.locator('div.virtual-table-cell:nth-child(3)')).toHaveText(/acyclovir Sirop 200mg/i);
await expect(page.locator('div.virtual-table-cell:nth-child(4)')).toHaveText('6');
await expect(page.locator('div.virtual-table-cell:nth-child(5)')).toHaveText('2');

// replay
await page.goto(`${ODOO_URL}`);
await odoo.navigateToSales();
await odoo.searchCustomer();
await page.getByRole('cell', { name: `${patientName.firstName + ' ' + patientName.givenName}` }).nth(0).click();
await odoo.deleteQuotationLine();

// verify
await page.goto(`${SUPERSET_URL}/sqllab`);
await superset.clearSQLEditor();
await page.getByRole('textbox').first().fill(saleOrderLinesQuery);
await superset.runSQLQuery();
await expect(page.locator('div.ant-alert-message')).toHaveText(/the query returned no data/i);
});

test(`A (synced) sale order line in Odoo generates an entry in Superset's sale_order_lines table.`, async ({ page }) => {
// setup
await superset.open();
Expand Down
2 changes: 1 addition & 1 deletion e2e/tests/openmrs-superset-flows.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ test(`Creating an OpenMRS visit creates the visit in Superset's visits table.`,
await expect(page.locator('div.virtual-table-cell:nth-child(3)')).toHaveText('Inpatient Ward');
await expect(page.locator('div.virtual-table-cell:nth-child(6)')).toHaveText('Facility Visit');
await expect(page.locator('div.virtual-table-cell:nth-child(8)')).toHaveText('M');
await expect(page.locator('div.virtual-table-cell:nth-child(10)')).toHaveText('true')
await expect(page.locator('div.virtual-table-cell:nth-child(2)')).toHaveText('false')
await page.getByRole('tab', { name: 'Query history' }).click();
await superset.clearSQLEditor();
await openmrs.voidPatient();
Expand Down
44 changes: 42 additions & 2 deletions e2e/utils/functions/odoo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class Odoo {
}

async createSaleOrderLine() {
await this.page.getByRole('button', { name: 'Create' }).click();
await this.page.getByRole('button', { name: /create/i }).click();
await expect(this.page.locator('li.breadcrumb-item:nth-child(2)')).toHaveText(/new/i);
await this.page.getByLabel('Customer', { exact: true }).type(`${patientName.firstName + ' ' + patientName.givenName}`);
await this.page.getByText(`${patientName.firstName + ' ' + patientName.givenName}`).first().click();
Expand All @@ -52,13 +52,53 @@ export class Odoo {
await this.page.locator('td.o_data_cell:nth-child(7) input').fill('2.00');
await this.page.locator('td.o_data_cell:nth-child(9)').click(), delay(2000);
await expect(this.page.locator('td.o_data_cell:nth-child(9)')).toHaveText('$ 16.00');
await this.page.getByRole('button', { name: 'Confirm' }).click(), delay(3000);
await this.page.getByRole('button', { name: /confirm/i }).click(), delay(3000);
await expect(this.page.locator('td.o_data_cell:nth-child(2) span:nth-child(1) span')).toHaveText('Acétaminophene Co 500mg');
await expect(this.page.locator('td.o_data_cell:nth-child(4)')).toHaveText('8');
await expect(this.page.locator('td.o_data_cell:nth-child(9)')).toHaveText('2.00');
await expect(this.page.locator('td.o_data_cell:nth-child(11)')).toHaveText('$ 16.00');
}

async createQuotationLine() {
await this.page.getByRole('button', { name: /create/i }).click();
await expect(this.page.locator('li.breadcrumb-item:nth-child(2)')).toHaveText(/new/i);
await this.page.getByLabel('Customer', { exact: true }).type(`${patientName.firstName + ' ' + patientName.givenName}`);
await this.page.getByText(`${patientName.firstName + ' ' + patientName.givenName}`).first().click();
await this.page.getByRole('button', { name: 'Add a product' }).click();
await this.page.locator('td.o_data_cell:nth-child(2) div:nth-child(1) input').fill('Acyclovir Sirop 200mg');
await this.page.getByText('Acyclovir Sirop 200mg').first().click();
await this.page.locator('input[name="product_uom_qty"]').fill('6');
await this.page.locator('td.o_data_cell:nth-child(7) input').fill('2.00');
await this.page.locator('td.o_data_cell:nth-child(9)').click(), delay(2000);
await expect(this.page.locator('td.o_data_cell:nth-child(9)')).toHaveText('$ 12.00');
await this.page.getByRole('button', { name: /save/i }).click(), delay(3000);
await expect(this.page.locator('td.o_data_cell:nth-child(2) span:nth-child(1) span')).toHaveText('Acyclovir Sirop 200mg');
}

async modifySaleOrderLine() {
await this.page.getByRole('button', { name: /edit/i }).click();
await this.page.getByText(/acétaminophene co 500mg/i).nth(1).click();
await this.page.locator('input[name="product_uom_qty"]').fill('10');
await this.page.locator('input[name="price_unit"]').fill('3');
await this.page.locator('td.o_field_x2many_list_row_add').click(), delay(2000);
await expect(this.page.locator('td.o_data_cell:nth-child(11)')).toHaveText('$ 30.00');
await this.page.getByRole('button', { name: /save/i }).click(), delay(3000);
}

async voidSaleOrderLine() {
await this.page.getByRole('button', { name: /edit/i }).click();
await this.page.getByText(/acétaminophene co 500mg/i).nth(1).click();
await this.page.locator('input[name="product_uom_qty"]').fill('0');
await this.page.getByRole('button', { name: /save/i }).click(), delay(1000);
await this.page.getByRole('button', { name: 'Ok' }).click(), delay(3000);
}

async deleteQuotationLine() {
await this.page.getByRole('button', { name: /edit/i }).click();
await this.page.getByRole('cell', { name: /delete row/i }).click();
await this.page.getByRole('button', { name: /save/i }).click(), delay(3000);
}

async activateDeveloperMode() {
await this.navigateToSettings();
await expect(this.page.locator('#devel_tool a:nth-child(1)')).toBeVisible();
Expand Down
19 changes: 8 additions & 11 deletions e2e/utils/functions/openmrs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class OpenMRS {
await this.page.locator('#username').fill(`${process.env.OZONE_USERNAME}`);
await this.page.getByRole('button', { name: /continue/i }).click();
await this.page.locator('#password').fill(`${process.env.OZONE_PASSWORD}`);
await this.page.getByRole('button', { name: /sign in/ }).click();
await this.page.getByRole('button', { name: /sign in/i }).click();
}

async createPatient() {
Expand All @@ -68,10 +68,8 @@ export class OpenMRS {
await this.page.locator('div[aria-label="day, "]').fill('16');
await this.page.locator('div[aria-label="month, "]').fill('08');
await this.page.locator('div[aria-label="year, "]').fill('2002');
await this.page.getByRole('button', { name: /register patient/i }).click();
await this.createPatientButton().click();
await expect(this.page.getByText(/new patient created/i)).toBeVisible(), delay(3000);;
await this.page.getByRole('button', { name: 'Close', exact: true }).click();
}

async goToHomePage() {
Expand Down Expand Up @@ -178,7 +176,7 @@ export class OpenMRS {

async addPatientAppointment() {
await this.page.getByRole('link', { name: /appointments/i }).click();
await this.page.getByRole('button', { name: /add/i, exact: true }).click();
await this.page.getByRole('button', { name: 'Add', exact: true }).click();
await this.page.getByLabel(/select a service/i).selectOption('General Medicine service');
await this.page.getByLabel(/select an appointment type/i).selectOption('Scheduled');
await this.page.locator('#duration').fill('40');
Expand All @@ -202,8 +200,8 @@ export class OpenMRS {

async navigateToLabOrderForm() {
await this.page.getByLabel(/order basket/i).click(), delay(2000);
await expect(this.page.getByRole('button', { name: /add/i, exact: true }).nth(1)).toBeVisible();
await this.page.getByRole('button', { name: /add/i, exact: true }).nth(1).click();
await expect(this.page.getByRole('button', { name: 'Add', exact: true }).nth(1)).toBeVisible();
await this.page.getByRole('button', { name: 'Add', exact: true }).nth(1).click();
}

async saveLabOrder() {
Expand All @@ -227,8 +225,7 @@ export class OpenMRS {
await this.page.getByRole('button', { name: /options/i, exact: true }).click();
await this.page.getByRole('menuitem', { name: /delete this encounter/i }).click();
await this.page.getByRole('button', { name: /danger delete/i }).click();
await expect(this.page.getByText(/encounter deleted/i)).toBeVisible();
await expect(this.page.getByText(/encounter successfully deleted/i)).toBeVisible(), delay(5000);
await expect(this.page.getByText(/encounter deleted/i)).toBeVisible(), delay(5000);
}

async cancelLabOrder() {
Expand All @@ -248,8 +245,8 @@ export class OpenMRS {
async navigateToDrugOrderForm() {
await expect(this.page.getByLabel(/order basket/i)).toBeVisible();
await this.page.getByLabel(/order basket/i).click(), delay(2000);
await expect(this.page.getByRole('button', { name: /add/i, exact: true }).nth(0)).toBeVisible();
await this.page.getByRole('button', { name: /add/i, exact: true }).nth(0).click();
await expect(this.page.getByRole('button', { name: 'Add', exact: true }).nth(0)).toBeVisible();
await this.page.getByRole('button', { name: 'Add', exact: true }).nth(0).click();
}

async fillDrugOrderForm() {
Expand Down Expand Up @@ -278,7 +275,7 @@ export class OpenMRS {
async createDrugOrderWithFreeTextDosage() {
await expect(this.page.getByLabel(/order basket/i)).toBeVisible();
await this.page.getByLabel(/order basket/i).click(), delay(2000);
await expect(this.page.getByRole('button', { name: /add/i, exact: true }).nth(0)).toBeVisible();
await expect(this.page.getByRole('button', { name: 'Add', exact: true }).nth(0)).toBeVisible();
await this.page.getByRole('button', { name: 'Add', exact: true }).nth(0).click();
await this.page.getByRole('searchbox').fill('Aspirin 325mg');
await this.page.getByRole('button', { name: 'Order form' }).click();
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"!playwright-report/"
],
"scripts": {
"ozone-pro": "npx playwright test",
"ozone-pro": "npx playwright test odoo-superset",
"ozone-foss": "npx playwright test odoo-openmrs erpnext-openmrs openmrs-senaite",
"openmrs-distro-his": "npx playwright test odoo-openmrs openmrs-senaite"
},
Expand Down
2 changes: 1 addition & 1 deletion playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ dotenv.config();

const config: PlaywrightTestConfig = {
testDir: './e2e/tests',
timeout: 10 * 60 * 1000,
timeout: 3 * 60 * 1000,
expect: {
timeout: 40 * 1000,
},
Expand Down

0 comments on commit c754ef8

Please sign in to comment.