Skip to content

Commit

Permalink
(refactor) e2e: Centralize types and improve type usage
Browse files Browse the repository at this point in the history
This PR centralizes type annotations used in e2e tests and improves type usage. Key changes include:

- Adding the Playwright ESLint plugin to enforce best practices in e2e tests.
- Moving test-specific types to a dedicated types file and importing them where needed.
- Using consistent type imports in e2e tests.
- Cleaning up eslint overrides for various test file types.

With these changes, e2e tests should be more consistent and easier to maintain.
  • Loading branch information
denniskigen committed Dec 13, 2024
1 parent 0b3e877 commit 4c43f75
Show file tree
Hide file tree
Showing 19 changed files with 278 additions and 174 deletions.
50 changes: 14 additions & 36 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,19 @@
"env": {
"node": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:jest-dom/recommended",
"plugin:testing-library/react"
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:jest-dom/recommended"],
"overrides": [
{
"files": ["**/*.test.tsx"],
"extends": ["plugin:testing-library/react"]
},
{
"files": ["e2e/**/*.spec.ts"],
"extends": ["plugin:playwright/recommended"],
"rules": {
"testing-library/prefer-screen-queries": "off"
}
}
],
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint", "import", "jest-dom", "react-hooks", "testing-library"],
Expand Down Expand Up @@ -71,35 +79,5 @@
"prefer-const": "off",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
},
"overrides": [
{
"files": ["**/e2e/**"],
"rules": {
"testing-library/await-async-events": "off",
"testing-library/await-async-query": "off",
"testing-library/await-async-utils": "off",
"testing-library/no-await-sync-events": "off",
"testing-library/no-await-sync-queries": "off",
"testing-library/no-container": "off",
"testing-library/no-debugging-utils": "off",
"testing-library/no-dom-import": "off",
"testing-library/no-global-regexp-flag-in-query": "off",
"testing-library/no-manual-cleanup": "off",
"testing-library/no-node-access": "off",
"testing-library/no-promise-in-fire-event": "off",
"testing-library/no-render-in-lifecycle": "off",
"testing-library/no-unnecessary-act": "off",
"testing-library/no-wait-for-multiple-assertions": "off",
"testing-library/no-wait-for-side-effects": "off",
"testing-library/no-wait-for-snapshot": "off",
"testing-library/prefer-find-by": "off",
"testing-library/prefer-implicit-assert": "off",
"testing-library/prefer-presence-queries": "off",
"testing-library/prefer-query-by-disappearance": "off",
"testing-library/prefer-screen-queries": "off",
"testing-library/render-result-naming-convention": "off"
}
}
]
}
}
40 changes: 1 addition & 39 deletions e2e/commands/cohort-operations.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,5 @@
import { type APIRequestContext, expect } from '@playwright/test';
import { type Patient } from './patient-operations';

export interface CohortType {
uuid: string;
name: string;
description: string;
display: string;
links: { rel: string; uri: string; resourceAlias: string }[];
resourceVersion: string;
}

export interface Cohort {
uuid: string;
name: string;
description: string;
attributes: any[];
links: any[];
location: any;
groupCohort: boolean | null;
startDate: Date;
endDate: Date;
voidReason: string | null;
voided: boolean;
isStarred?: boolean;
type?: string;
size: number;
cohortType?: CohortType;
resourceVersion: string;
}

export interface CohortMember {
attributes: Array<any>;
description: string;
endDate: string;
startDate: string;
name: string;
uuid: string;
patient: Patient;
}
import { type Cohort, type CohortMember } from '../types';

export const generateRandomCohort = async (api: APIRequestContext): Promise<Cohort> => {
const cohortRes = await api.post('cohortm/cohort', {
Expand Down
4 changes: 2 additions & 2 deletions e2e/commands/encounter-operations.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Encounter } from './../../packages/esm-active-visits-app/src/visits-summary/visit.resource';
import { APIRequestContext, expect } from '@playwright/test';
import { type APIRequestContext, expect } from '@playwright/test';
import dayjs from 'dayjs';
import { type Encounter } from '../types';

export const createEncounter = async (
api: APIRequestContext,
Expand Down
47 changes: 1 addition & 46 deletions e2e/commands/patient-operations.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,5 @@
import { type APIRequestContext, expect } from '@playwright/test';

export interface Patient {
uuid: string;
identifiers: Identifier[];
display: string;
person: {
uuid: string;
display: string;
gender: string;
age: number;
birthdate: string;
birthdateEstimated: boolean;
dead: boolean;
deathDate?: any;
causeOfDeath?: any;
preferredAddress: {
address1: string;
cityVillage: string;
country: string;
postalCode: string;
stateProvince: string;
countyDistrict: string;
};
attributes: any[];
voided: boolean;
birthtime?: any;
deathdateEstimated: boolean;
resourceVersion: string;
};
attributes: { value: string; attributeType: { uuid: string; display: string } }[];
voided: boolean;
}

export interface Address {
preferred: boolean;
address1: string;
cityVillage: string;
country: string;
postalCode: string;
stateProvince: string;
}

export interface Identifier {
uuid: string;
display: string;
}
import { type Patient } from '../types';

export const generateRandomPatient = async (api: APIRequestContext): Promise<Patient> => {
const identifierRes = await api.post('idgen/identifiersource/8549f706-7e85-4c1d-9424-217d50a2988b/identifier', {
Expand Down
4 changes: 2 additions & 2 deletions e2e/commands/provider-operations.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Provider } from '../../packages/esm-appointments-app/src/types/index';
import { APIRequestContext, expect } from '@playwright/test';
import { type APIRequestContext, expect } from '@playwright/test';
import { type Provider } from '../types';

export const getProvider = async (api: APIRequestContext): Promise<Provider> => {
const providerRes = await api.get('provider?q=admin', {
Expand Down
4 changes: 2 additions & 2 deletions e2e/commands/visit-operations.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { APIRequestContext, expect } from '@playwright/test';
import { Visit } from '@openmrs/esm-framework';
import { type APIRequestContext, expect } from '@playwright/test';
import dayjs from 'dayjs';
import { type Visit } from '@openmrs/esm-framework';

export const startVisit = async (api: APIRequestContext, patientId: string): Promise<Visit> => {
const visitRes = await api.post('visit', {
Expand Down
2 changes: 1 addition & 1 deletion e2e/pages/home-page.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Page } from '@playwright/test';
import { type Page } from '@playwright/test';

export class HomePage {
constructor(readonly page: Page) {}
Expand Down
2 changes: 1 addition & 1 deletion e2e/pages/patient-lists-page.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Page } from '@playwright/test';
import { type Page } from '@playwright/test';

export class PatientListsPage {
constructor(readonly page: Page) {}
Expand Down
24 changes: 1 addition & 23 deletions e2e/pages/registration-and-edit-page.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,5 @@
import { type Locator, type Page, expect } from '@playwright/test';

export type PatientRegistrationSex = 'male' | 'female' | 'other' | 'unknown';

export interface PatientRegistrationFormValues {
givenName?: string;
middleName?: string;
familyName?: string;
sex?: PatientRegistrationSex;
birthdate?: {
day: string;
month: string;
year: string;
};
postalCode?: string;
address1?: string;
address2?: string;
country?: string;
countyDistrict?: string;
stateProvince?: string;
cityVillage?: string;
phone?: string;
email?: string;
}
import { type PatientRegistrationFormValues, type PatientRegistrationSex } from '../types';

export class RegistrationAndEditPage {
constructor(readonly page: Page) {}
Expand Down
7 changes: 3 additions & 4 deletions e2e/specs/active-visits.spec.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import { expect } from '@playwright/test';
import type { Visit } from '@openmrs/esm-framework';
import { test } from '../core';
import type { Provider } from '../../packages/esm-appointments-app/src/types/index';
import type { Encounter } from '../../packages/esm-active-visits-app/src/visits-summary/visit.resource';

import {
createEncounter,
deleteEncounter,
deletePatient,
endVisit,
generateRandomPatient,
type Patient,
startVisit,
getProvider,
startVisit,
} from '../commands';
import { HomePage } from '../pages';
import { type Encounter, type Patient, type Provider } from '../types';

let patient: Patient;
let visit: Visit;
Expand Down
7 changes: 4 additions & 3 deletions e2e/specs/appointments.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { expect } from '@playwright/test';
import { generateRandomPatient, deletePatient, type Patient, startVisit, endVisit } from '../commands';
import { generateRandomPatient, deletePatient, startVisit, endVisit } from '../commands';
import { type Visit } from '@openmrs/esm-framework';
import { type Patient } from '../types';
import { test } from '../core';
import { AppointmentsPage } from '../pages';
import { type Visit } from '@openmrs/esm-framework';

let patient: Patient;
let visit: Visit;
Expand Down Expand Up @@ -111,7 +112,7 @@ test('Add, edit and cancel an appointment', async ({ page, api }) => {
await page.getByRole('button', { name: 'Options' }).click();
});

await test.step('And I choose the "Cancel" option ', async () => {
await test.step('And I choose the "Cancel" option', async () => {
await page.getByRole('menuitem', { name: 'Cancel' }).click();
});

Expand Down
5 changes: 3 additions & 2 deletions e2e/specs/edit-patient.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import dayjs from 'dayjs';
import { expect } from '@playwright/test';
import { test } from '../core';
import { deletePatient, generateRandomPatient, getPatient, type Patient } from '../commands';
import { type PatientRegistrationFormValues, RegistrationAndEditPage } from '../pages';
import { deletePatient, generateRandomPatient, getPatient } from '../commands';
import { RegistrationAndEditPage } from '../pages';
import { type Patient, type PatientRegistrationFormValues } from '../types';

let patient: Patient;

Expand Down
7 changes: 3 additions & 4 deletions e2e/specs/patient-list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@ import { test } from '../core';
import { PatientListsPage } from '../pages';
import { expect } from '@playwright/test';
import {
type Cohort,
type CohortMember,
type Patient,
addPatientToCohort,
deleteCohort,
deletePatient,
generateRandomCohort,
generateRandomPatient,
removePatientFromCohort,
} from '../commands';
import { type Cohort, type CohortMember, type Patient } from '../types';

let cohortMember: CohortMember;
let cohortUuid: string;
Expand Down Expand Up @@ -46,7 +44,8 @@ test('Create and edit a patient list', async ({ page }) => {

await test.step('Then I should see the information about the list', async () => {
await expect(page).toHaveURL(new RegExp('^[\\w\\d:\\/.-]+\\/patient-lists\\/[\\w\\d-]+$'));
cohortUuid = /patient-lists\/([\w\d-]+)/.exec(page.url())?.[1] ?? null;
const [, extractedUuid] = /patient-lists\/([\w\d-]+)/.exec(page.url());
cohortUuid = extractedUuid;

await expect(patientListPage.patientListHeader()).toHaveText(new RegExp(patientListName));
await expect(patientListPage.patientListHeader()).toHaveText(new RegExp(patientListDescription));
Expand Down
3 changes: 2 additions & 1 deletion e2e/specs/patient-search.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { expect } from '@playwright/test';
import { test } from '../core';
import { HomePage } from '../pages';
import { generateRandomPatient, deletePatient, type Patient } from '../commands';
import { generateRandomPatient, deletePatient } from '../commands';
import { type Patient } from '../types';

let patient: Patient;

Expand Down
7 changes: 4 additions & 3 deletions e2e/specs/register-new-patient.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { expect } from '@playwright/test';
import { test } from '../core';
import { type PatientRegistrationFormValues, RegistrationAndEditPage } from '../pages';
import { RegistrationAndEditPage } from '../pages';
import { type PatientRegistrationFormValues } from '../types';
import { deletePatient } from '../commands';

let patientUuid: string;
Expand Down Expand Up @@ -101,7 +102,7 @@ test('Register an unknown patient', async ({ api, page }) => {
});

await test.step('And then I fill in 25 as the estimated age in years', async () => {
const estimatedAgeField = await page.getByLabel(/estimated age in years/i);
const estimatedAgeField = page.getByLabel(/estimated age in years/i);
await estimatedAgeField.clear();
await estimatedAgeField.fill('25');
});
Expand All @@ -123,7 +124,7 @@ test('Register an unknown patient', async ({ api, page }) => {
await test.step("And I should see the newly registered patient's details displayed in the patient banner", async () => {
const patientBanner = page.locator('header[aria-label="patient banner"]');

expect(patientBanner).toBeVisible();
await expect(patientBanner).toBeVisible();
await expect(patientBanner.getByText('Unknown Unknown')).toBeVisible();
await expect(patientBanner.getByText(/female/i)).toBeVisible();
await expect(patientBanner.getByText(/25 yrs/i)).toBeVisible();
Expand Down
6 changes: 2 additions & 4 deletions e2e/specs/return-to-patient-list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ import { PatientListsPage } from '../pages';
import { expect } from '@playwright/test';
import {
addPatientToCohort,
type Cohort,
type CohortMember,
deleteCohort,
deletePatient,
generateRandomCohort,
generateRandomPatient,
type Patient,
removePatientFromCohort,
} from '../commands';
import { type Cohort, type CohortMember, type Patient } from '../types';

let cohortMembership: CohortMember;
let cohort: Cohort;
Expand Down Expand Up @@ -123,7 +121,7 @@ test('Return to patient list after navigating to visits and refreshing the page'

test('Return to patient list from the patient chart on a new tab', async ({ page, context }) => {
const patientListPage = new PatientListsPage(page);
const locator = await page.locator('table tbody tr td:nth-child(1) a');
const locator = page.locator('table tbody tr td:nth-child(1) a');
const pagePromise = context.waitForEvent('page');

await test.step('When I navigate to the patient list', async () => {
Expand Down
Loading

0 comments on commit 4c43f75

Please sign in to comment.