diff --git a/e2e/specs/clinical-forms.spec.ts b/e2e/specs/clinical-forms.spec.ts index ae4e673d8e..71348d6f1f 100644 --- a/e2e/specs/clinical-forms.spec.ts +++ b/e2e/specs/clinical-forms.spec.ts @@ -26,52 +26,53 @@ test('Fill a clinical form', async ({ page }) => { }); await test.step('And I click the `Clinical forms` button on the siderail', async () => { - await chartPage.page.getByLabel(/clinical forms/i, { exact: true }).click(); + await page.getByLabel(/clinical forms/i, { exact: true }).click(); }); await test.step('Then I should see the clinical forms workspace', async () => { const headerRow = chartPage.formsTable().locator('thead > tr'); - await expect(chartPage.page.getByPlaceholder(/search this list/i)).toBeVisible(); + await expect(page.getByPlaceholder(/search this list/i)).toBeVisible(); await expect(headerRow).toContainText(/form name \(a-z\)/i); await expect(headerRow).toContainText(/last completed/i); - await expect(chartPage.page.getByRole('cell', { name: /covid 19/i })).toBeVisible(); - await expect(chartPage.page.getByRole('cell', { name: /laboratory test results/i })).toBeVisible(); - await expect(chartPage.page.getByRole('cell', { name: /soap note template/i })).toBeVisible(); - await expect(chartPage.page.getByRole('cell', { name: /surgical operation/i })).toBeVisible(); + await expect(page.getByRole('cell', { name: 'Covid 19', exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: /laboratory test results/i, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: /soap note template/i, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: /surgical operation/i, exact: true })).toBeVisible(); }); await test.step('When I click the `Soap note template` link to launch the form', async () => { - await chartPage.page.getByText(/soap note template/i).click(); + await page.getByText(/soap note template/i).click(); }); await test.step('Then I should see the `Soap note template` form launch in the workspace', async () => { - await expect(chartPage.page.getByText(/soap note template/i)).toBeVisible(); + await expect(page.getByText(/soap note template/i)).toBeVisible(); }); await test.step('When I fill the `Subjective findings` question', async () => { - await chartPage.page.locator('#SOAPSubjectiveFindingsid').fill(subjectiveFindings); + await page.getByLabel(/subjective Findings/i).fill(subjectiveFindings); }); await test.step('And I fill the `Objective findings` question', async () => { - await chartPage.page.locator('#SOAPObjectiveFindingsid').fill(objectiveFindings); + await page.getByLabel(/objective findings/i).fill(objectiveFindings); }); await test.step('And I fill the `Assessment` question', async () => { - await chartPage.page.locator('#SOAPAssessmentid').fill(assessment); + await page.getByLabel(/assessment/i).fill(assessment); }); await test.step('And I fill the `Plan` question', async () => { - await chartPage.page.locator('#SOAPPlanid').fill(plan); + await page.getByLabel(/plan/i).fill(plan); }); await test.step('And I click on the `Save and close` button', async () => { - await chartPage.page.getByRole('button', { name: /save and close/i }).click(); + await page.getByRole('button', { name: /save/i }).click(); }); await test.step('Then I should see a success notification', async () => { - await expect(chartPage.page.getByText(/the form has been submitted successfully/i)).toBeVisible(); + await expect(page.getByText(/record created/i, { exact: true })).toBeVisible(); + await expect(page.getByText(/a new encounter was created/i, { exact: true })).toBeVisible(); }); await test.step('And if I navigate to the visits dashboard', async () => { @@ -79,23 +80,23 @@ test('Fill a clinical form', async ({ page }) => { }); await test.step('Then I should see the newly filled form in the encounters table', async () => { - await expect(visitsPage.page.getByRole('tab', { name: /visit summaries/i })).toBeVisible(); - await expect(visitsPage.page.getByRole('tab', { name: /all encounters/i })).toBeVisible(); + await expect(page.getByRole('tab', { name: /visit summaries/i })).toBeVisible(); + await expect(page.getByRole('tab', { name: /all encounters/i })).toBeVisible(); - await visitsPage.page.getByRole('tab', { name: /^encounters$/i }).click(); + await page.getByRole('tab', { name: /^encounters$/i }).click(); - const headerRow = visitsPage.page.getByRole('table').locator('thead > tr'); + const headerRow = page.getByRole('table').locator('thead > tr'); await expect(headerRow).toContainText(/date & time/i); await expect(headerRow).toContainText(/encounter type/i); await expect(headerRow).toContainText(/provider/i); - await visitsPage.page.getByRole('table').locator('th#expand').click(); + await page.getByRole('table').locator('th#expand').click(); - await expect(visitsPage.page.getByText(subjectiveFindings)).toBeVisible(); - await expect(visitsPage.page.getByText(objectiveFindings)).toBeVisible(); - await expect(visitsPage.page.getByText(assessment)).toBeVisible(); - await expect(visitsPage.page.getByText(plan)).toBeVisible(); + await expect(page.getByText(subjectiveFindings)).toBeVisible(); + await expect(page.getByText(objectiveFindings)).toBeVisible(); + await expect(page.getByText(assessment)).toBeVisible(); + await expect(page.getByText(plan)).toBeVisible(); }); }); diff --git a/e2e/specs/results-viewer.spec.ts b/e2e/specs/results-viewer.spec.ts index 15efdcf58c..dfe7d0b03e 100644 --- a/e2e/specs/results-viewer.spec.ts +++ b/e2e/specs/results-viewer.spec.ts @@ -15,6 +15,201 @@ test.beforeEach(async ({ api }) => { test('Record and edit test results', async ({ page }) => { const resultsViewerPage = new ResultsViewerPage(page); const visitsPage = new VisitsPage(page); + const form = page.locator('[data-extension-slot-name="form-widget-slot"]'); + + const completeBloodCountData = [ + { + label: 'White Blood Cells (WBC) (10^3/uL)', + resultsPageReference: 'White Blood Cells', + value: '12.5', + updatedValue: '12.7', + }, + { + label: 'Red Blood Cells (RBC) (10^6/uL)', + resultsPageReference: 'Red Blood Cells', + value: '5.2', + updatedValue: '5.3', + }, + { + label: 'Platelets (10^3/mL)', + resultsPageReference: 'Platelets', + value: '150', + updatedValue: '155', + }, + // TODO: Uncomment the rest once https://openmrs.atlassian.net/browse/O3-3478 is fixed + // { + // label: 'Neutrophils (%)', + // resultsPageReference: 'Neutrophils', + // value: '60', + // updatedValue: '62' + // }, + // { + // label: 'MCV (fL) - Mean Corpuscular Volume', + // resultsPageReference: 'MCV', + // value: '90', + // updatedValue: '92' + // }, + // { + // label: 'MCH (pg) - Mean Corpuscular Hemoglobin', + // resultsPageReference: 'MCH', + // value: '30', + // updatedValue: '31' + // }, + // { + // label: 'MCHC (g/dL) - Mean Cell Hemoglobin Concentration', + // resultsPageReference: 'MCHC', + // value: '33', + // updatedValue: '34' + // }, + // { + // label: 'Lymphocytes (%) - microscopic exam', + // resultsPageReference: 'Lymphocytes', + // value: '30', + // updatedValue: '32' + // }, + // { + // label: 'Hematocrit (%)', + // resultsPageReference: 'Hematocrit', + // value: '45', + // updatedValue: '47' + // }, + // { + // label: 'Haemoglobin (g/dL)', + // resultsPageReference: 'Haemoglobin', + // value: '15', + // updatedValue: '16' + // }, + // { + // label: 'Combined % of monocytes, eosinophils and basophils (%)', + // resultsPageReference: 'Combined % of monocytes, eosinophils and basophils', + // value: '5', + // updatedValue: '6' + // } + ]; + + const chemistryResultsData = [ + { + label: 'Alkaline Phosphatase (U/L)', + resultsPageReference: 'Alkaline Phosphatase', + value: '70', + updatedValue: '72', + }, + { + label: 'Amylase (IU/L)', + resultsPageReference: 'Amylase', + value: '120', + updatedValue: '122', + }, + { + label: 'BUN (mmol/L) - Blood Urea Nitrogen', + resultsPageReference: 'Blood Urea Nitrogen', + value: '5.5', + updatedValue: '5.7', + }, + // TODO: Uncomment the rest once https://openmrs.atlassian.net/browse/O3-3478 is fixed + // { + // label: 'Fasting Blood Glucose (mg/dL)', + // resultsPageReference: 'Fasting Blood Glucose', + // value: '90', + // updatedValue: '92' + // }, + // { + // label: 'Post-Prandial Blood Glucose (mg/dL)', + // resultsPageReference: 'Post-Prandial Blood Glucose', + // value: '140', + // updatedValue: '142' + // }, + // { + // label: 'Serum Albumin (g/dL)', + // resultsPageReference: 'Serum Albumin', + // value: '4.0', + // updatedValue: '4.2' + // }, + // { + // label: 'Serum Calcium (mg/dL)', + // resultsPageReference: 'Serum Calcium', + // value: '9.0', + // updatedValue: '9.2' + // }, + // { + // label: 'Serum Potassium (mmol/L)', + // resultsPageReference: 'Serum Potassium', + // value: '4.2', + // updatedValue: '4.4' + // }, + // { + // label: 'Serum Sodium (mmol/L)', + // resultsPageReference: 'Serum Sodium', + // value: '140', + // updatedValue: '142' + // }, + // { + // label: 'Serum Creatinine (umol/L)', + // resultsPageReference: 'Serum Creatinine', + // value: '70', + // updatedValue: '72' + // }, + // { + // label: 'Total Protein (g/dL)', + // resultsPageReference: 'Total Protein', + // value: '7.0', + // updatedValue: '7.2' + // }, + // { + // label: 'Serum Glucose (mg/dl)', + // resultsPageReference: 'Serum Glucose', + // value: '90', + // updatedValue: '92' + // }, + // { + // label: 'Serum Glucose (mmol)', + // resultsPageReference: 'Serum Glucose', + // value: '5.0', + // updatedValue: '5.2' + // }, + // { + // label: 'Total Bilirubin (umol/L)', + // resultsPageReference: 'Total Bilirubin', + // value: '10', + // updatedValue: '12' + // }, + // { + // label: 'Serum Glutamic-Oxaloacetic Transaminase (IU/L) aka SGPT, AST', + // resultsPageReference: 'Serum Glutamic-Oxaloacetic Transaminase', + // value: '30', + // updatedValue: '32' + // }, + // { + // label: 'Alkaline Phosphatase, ALP (U/L)', + // resultsPageReference: 'Alkaline Phosphatase, ALP', + // value: '70', + // updatedValue: '72' + // }, + // { + // label: 'Serum Uric Acid (mg/dL)', + // resultsPageReference: 'Serum Uric Acid', + // value: '4.5', + // updatedValue: '4.7' + // }, + // { + // label: 'Total Cholesterol (mmol/L)', + // resultsPageReference: 'Total Cholesterol', + // value: '5.0', + // updatedValue: '5.2' + // }, + // { + // label: 'Triglycerides (mmol/L)', + // resultsPageReference: 'Triglycerides', + // value: '1.5', + // updatedValue: '1.7' + // }, + // { + // label: 'Serum Carbon Dioxide CO2 (mmol/L)', + // resultsPageReference: 'Serum Carbon Dioxide CO2', + // value: '25', + // updatedValue: '27' + // } + ]; await test.step('When I visit the results viewer page', async () => { await resultsViewerPage.goTo(patient.uuid); @@ -37,66 +232,33 @@ test('Record and edit test results', async ({ page }) => { await page.getByText(/laboratory test results/i).click(); }); - await test.step('Then it should launch in the workspace', async () => { - await expect(page.getByRole('button', { name: /hematology/i, exact: true })).toBeVisible(); - await expect(page.getByRole('button', { name: 'Chemistry', exact: true })).toBeVisible(); - await expect(page.getByRole('button', { name: /other/i, exact: true })).toBeVisible(); - }); - - await test.step('When I click the `Hematology` tab', async () => { - await page.getByRole('button', { name: 'Hematology', exact: true }).click(); - }); - await test.step('And I fill the "Complete Blood Count" section', async () => { - await page.locator('#ManualInputWhiteBloodCellsid').fill('12'); - await page.locator('#ManualEntryRedBloodCellsid').fill('15'); - await page.locator('#ManualEntryPlateletsid').fill('10'); - await page.locator('#ManualEntryNeutrophilsMicroscopicid').fill('10'); - await page.locator('#ManualEntryMCVid').fill('10'); - await page.locator('#ManualEntryMCHid').fill('10'); - }); - - await test.step('When I click the `Chemistry` tab', async () => { - await page.getByRole('button', { name: 'Chemistry', exact: true }).click(); + for (const { label, value } of completeBloodCountData) { + await test.step(label, async () => { + await form.getByLabel(label, { exact: true }).fill(value); + }); + } }); await test.step('And I fill the "Chemistry Results" section', async () => { - await page.locator('#ManualEntryAlkalinePhosphataseid').fill('10'); - await page.locator('#ManualEntryAmylaseid').fill('10'); - await page.locator('#ManualEntryBUNid').fill('10'); - await page.locator('#manualEntryFastingBloodGlucosemgdlid').fill('10'); - await page.locator('#manualEntryPostPrandialBloodGlucosemgdlid').fill('10'); - await page.locator('#manualEntrySerumAlbuminid').fill('10'); - }); - - await test.step('When I click the `Other` tab', async () => { - await page.getByRole('button', { name: 'Other', exact: true }).click(); + for (const { label, value } of chemistryResultsData) { + await test.step(label, async () => { + await form.getByLabel(label, { exact: true }).fill(value); + }); + } }); - await test.step('And I fill the "Urine" and "Stool" sections', async () => { - await page.locator('#manualEntryCultureandSensitivityUrineid').fill('83%'); - await page.locator('#manualEntryUrinePregnancyTestid_1').check(); - await page.locator('#manualEntryUrineProteinDipStickid_0').check(); - await page.locator('#manualEntryUrineBacteriuriaTestid_1').check(); - await page.locator('#manualEntryErythrocytesPresenceInUrineSedimentByLightMicroscopyTestid_1').check(); - await page.locator('#manualEntryLeukocytesPresenceInUrineSedimentByLightMicroscopyid_2').check(); - await page.locator('#manualEntryEpithelialCastsPresenceInUrineSedimentByLightMicroscopyTestid_2').check(); - await page.locator('#manualEntryYeastPresenceInUrineSedimentByLightMicroscopyid_1').check(); - await page.locator('#manualEntrySporePresenceInUrineTestid_3').check(); - await page.locator('#manualEntryTrichomonasVaginalisPresenceInUrineSedimentByLightMicroscopyid_0').check(); - await page.locator('#manualEntryCrystalsTypeInUrineSedimentByLightMicroscopyTestid_3').check(); - await page.locator('#manualEntryStoolExamid').selectOption('Cestode Infection'); - await page.locator('#manualEntryStoolFatTestSemiQuantitativeid_3').check(); - await page.locator('#manualEntryStoolTestforReducingSubstanceid_0').check(); - await page.locator('#manualEntryFecalOccultBloodTestid_2').check(); + await test.step('(SKIPPED) And I fill the "Urine" and "Stool" sections', async () => { + // TODO: https://openmrs.atlassian.net/browse/O3-3487 }); - await test.step('And I click on the `Save and close` button', async () => { - await page.getByRole('button', { name: /save and close/i }).click(); + await test.step('And I click on the `Save` button', async () => { + await page.getByRole('button', { name: /save/i, exact: true }).click(); }); await test.step('Then I should see a success notification', async () => { - await expect(page.getByText('The form has been submitted successfully.')).toBeVisible(); + await expect(page.getByText(/record created/i, { exact: true })).toBeVisible(); + await expect(page.getByText(/a new encounter was created/i, { exact: true })).toBeVisible(); }); await test.step('When I go to the results viewer page', async () => { @@ -108,10 +270,18 @@ test('Record and edit test results', async ({ page }) => { }); await test.step('Then I should see the newly entered test results reflect in the results viewer', async () => { - const whiteBloodCellRow = page.locator('tr:has-text("white blood cells")'); - const redBloodCellRow = page.locator('tr:has-text("red blood cells")'); - await expect(whiteBloodCellRow).toContainText(/12/i); - await expect(redBloodCellRow).toContainText(/15/i); + for (const { resultsPageReference, value } of completeBloodCountData) { + await test.step(resultsPageReference, async () => { + const row = page.locator(`tr:has-text("${resultsPageReference}")`); + await expect(row).toContainText(value); + }); + } + for (const { resultsPageReference, value } of chemistryResultsData) { + await test.step(resultsPageReference, async () => { + const row = page.locator(`tr:has-text("${resultsPageReference}")`); + await expect(row).toContainText(value); + }); + } }); await test.step('When I navigate to the `Visits` page', async () => { @@ -139,19 +309,29 @@ test('Record and edit test results', async ({ page }) => { await page.getByRole('menuitem', { name: /edit this encounter/i }).click(); }); - await test.step('And I amend the values for "White blood cells" and "Red blood cells"', async () => { - await page.locator('#ManualInputWhiteBloodCellsid').clear(); - await page.locator('#ManualInputWhiteBloodCellsid').fill('13'); - await page.locator('#ManualEntryRedBloodCellsid').clear(); - await page.locator('#ManualEntryRedBloodCellsid').fill('16'); + await test.step('And I edit values in the Complete Blood Count Section', async () => { + for (const { label, updatedValue } of completeBloodCountData) { + await test.step(label, async () => { + await form.getByLabel(label, { exact: true }).fill(updatedValue); + }); + } + }); + + await test.step('And I edit values in the Chemistry Results Data Section', async () => { + for (const { label, updatedValue } of chemistryResultsData) { + await test.step(label, async () => { + await form.getByLabel(label, { exact: true }).fill(updatedValue); + }); + } }); await test.step('And I save the form', async () => { - await page.getByRole('button', { name: /save and close/i }).click(); + await page.getByRole('button', { name: /save/i }).click(); }); await test.step('Then I should see a success notification', async () => { - await expect(page.getByText('The form has been submitted successfully.')).toBeVisible(); + await expect(page.getByText(/record updated/i, { exact: true })).toBeVisible(); + await expect(page.getByText(/the patient encounter was updated/i, { exact: true })).toBeVisible(); }); await test.step('When I revisit the `Results Viewer` page', async () => { @@ -163,10 +343,18 @@ test('Record and edit test results', async ({ page }) => { }); await test.step('Then I should see the updated results reflect in the results viewer', async () => { - const whiteBloodCellRow = page.locator('tr:has-text("white blood cells")'); - const redBloodCellRow = page.locator('tr:has-text("red blood cells")'); - await expect(whiteBloodCellRow).toContainText(/13/i); - await expect(redBloodCellRow).toContainText(/16/i); + for (const { resultsPageReference, updatedValue } of completeBloodCountData) { + await test.step(resultsPageReference, async () => { + const row = page.locator(`tr:has-text("${resultsPageReference}")`); + await expect(row).toContainText(updatedValue); + }); + } + for (const { resultsPageReference, updatedValue } of chemistryResultsData) { + await test.step(resultsPageReference, async () => { + const row = page.locator(`tr:has-text("${resultsPageReference}")`); + await expect(row).toContainText(updatedValue); + }); + } }); }); diff --git a/e2e/support/github/run-e2e-docker-env.sh b/e2e/support/github/run-e2e-docker-env.sh index 8ea68c5c6b..32fa8a91fc 100644 --- a/e2e/support/github/run-e2e-docker-env.sh +++ b/e2e/support/github/run-e2e-docker-env.sh @@ -5,7 +5,7 @@ script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) # create a temporary working directory working_dir=$(mktemp -d "${TMPDIR:-/tmp/}openmrs-e2e-frontends.XXXXXXXXXX") # get a list of all the apps in this workspace -apps=$(yarn workspaces list --json | jq -r 'if ((.location == ".") or (.location | test("form-engine-app")) or (.location | test("-app") | not)) then halt else .name end') +apps=$(yarn workspaces list --json | jq -r 'select((.location != ".") and (.location | test("form-entry-app") | not) and (.location | test("-app"))) | .name') # this array will hold all of the packed app names app_names=() diff --git a/playwright.config.ts b/playwright.config.ts index c00224ad9e..746bacaade 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -19,7 +19,7 @@ const config: PlaywrightTestConfig = { use: { baseURL: `${process.env.E2E_BASE_URL}/spa/`, storageState: 'e2e/storageState.json', - video: 'retain-on-failure', + video: 'on', trace: 'retain-on-failure', }, projects: [