Skip to content

Commit 5602d16

Browse files
authored
[DSM] [Playwright] test for Receive Kit in A-T study (#2161)
* kit received dsm playwright test
1 parent 7b399c6 commit 5602d16

18 files changed

+369
-46
lines changed

playwright-e2e/dsm/component/filters/sections/customize-view.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,18 @@ export class CustomizeView {
1818
}
1919
}
2020

21-
public async selectColumns(columnsGroupName: string, columns: string[]): Promise<void> {
21+
public async selectColumns(columnsGroupName: string, columns: string[], opts: { nth?: number } = {}): Promise<void> {
22+
const { nth } = opts;
2223
this.activeColumnsGroup = columnsGroupName;
23-
await this.openColumnsGroup();
24+
await this.openColumnsGroup({nth});
2425
await this.select(columns);
2526
await this.closeColumnsGroup();
2627
}
2728

28-
public async deselectColumns(columnsGroupName: string, columns: string[]): Promise<void> {
29+
public async deselectColumns(columnsGroupName: string, columns: string[], opts: { nth?: number } = {}): Promise<void> {
30+
const { nth } = opts;
2931
this.activeColumnsGroup = columnsGroupName;
30-
await this.openColumnsGroup();
32+
await this.openColumnsGroup({nth});
3133
await this.select(columns, true);
3234
await this.closeColumnsGroup();
3335
}
@@ -49,13 +51,15 @@ export class CustomizeView {
4951
}
5052
}
5153

52-
private async openColumnsGroup(): Promise<void> {
53-
const columnsGroupButton = this.columnsGroupButton;
54+
private async openColumnsGroup(opts: { nth?: number } = {}): Promise<void> {
55+
const { nth } = opts;
56+
const columnsGroupButton = this.columnsGroupButton({nth});
5457
!(await this.isExpanded(columnsGroupButton)) && (await columnsGroupButton.click());
5558
}
5659

57-
private async closeColumnsGroup(): Promise<void> {
58-
const columnsGroupButton = this.columnsGroupButton;
60+
private async closeColumnsGroup(opts: { nth?: number } = {}): Promise<void> {
61+
const { nth } = opts;
62+
const columnsGroupButton = this.columnsGroupButton({nth});
5963
(await this.isExpanded(columnsGroupButton)) && (await columnsGroupButton.click());
6064
}
6165

@@ -71,8 +75,9 @@ export class CustomizeView {
7175

7276
/* Locators */
7377

74-
private get columnsGroupButton(): Locator {
75-
return this.page.locator(`${this.columnsGroupXPath}/button`);
78+
private columnsGroupButton(opts: { nth?: number } = {}): Locator {
79+
const { nth = 0 } = opts;
80+
return this.page.locator(`${this.columnsGroupXPath}/button`).nth(nth);
7681
}
7782

7883
/* XPaths */

playwright-e2e/dsm/component/filters/sections/search/search.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ export class Search {
1212
constructor(private readonly page: Page) {}
1313

1414
public async open(): Promise<void> {
15-
await this.page.locator(this.openButtonXPath).click();
15+
const open = await this.isOpen();
16+
!open && await this.page.locator(this.openButtonXPath).click();
17+
await expect(async () => expect(await this.isOpen()).toBe(true)).toPass();
1618
}
1719

1820
public async search(): Promise<void> {
@@ -166,6 +168,10 @@ export class Search {
166168
return this.page.locator(`${this.baseTextColumnXPath(columnName)}//mat-form-field//input`);
167169
}
168170

171+
private async isOpen(): Promise<boolean> {
172+
return this.page.locator('#searchTable').isVisible();
173+
}
174+
169175
private additionalFilterCheckboxLocator(columnName: string, checkboxName: AdditionalFilter, isTextField = false): Locator {
170176
return this.page.locator(
171177
`${

playwright-e2e/dsm/component/tables/participant-list-table.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ export class ParticipantListTable extends Table {
4242
return await this.page.locator(this.participantDataByXPath(columnName, columnValue, xColumnName)).innerText();
4343
}
4444

45-
public async getParticipantDataAt(position: number, columnName: string): Promise<string> {
46-
const columnIndex = await this.getHeaderIndex(columnName);
45+
public async getParticipantDataAt(position: number, columnName: string, opts: { exactMatch?: boolean } = {}): Promise<string> {
46+
const columnIndex = await this.getHeaderIndex(columnName, opts);
4747
return this.cell(position, columnIndex).innerText();
4848
}
4949

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export enum TabEnum {
2-
SURVEY_DATA = 'Survey Data',
32
CONTACT_INFORMATION = 'Contact Information',
3+
GENOME_STUDY = 'Genome Study',
4+
INVITAE = 'Invitae',
45
SAMPLE_INFORMATION = 'Sample Information',
5-
INVITAE = 'Invitae'
6+
SURVEY_DATA = 'Survey Data',
67
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Locator, Page } from '@playwright/test';
2+
3+
export default class GenomeStudyTab {
4+
constructor(private readonly page: Page) {
5+
}
6+
7+
async setValue(field: string, value: string): Promise<void> {
8+
await this.getField(field).locator('input').fill(value);
9+
}
10+
11+
async clearSelection(field: string): Promise<void> {
12+
await this.getField(field).locator('button', { hasText: 'Clear Selection' }).click();
13+
}
14+
15+
async clearValue(field: string): Promise<void> {
16+
await this.getField(field).getByRole('textbox').clear();
17+
}
18+
19+
async setNotesAboutPreviousSampleKits(value: string): Promise<void> {
20+
await this.getField('Notes about previous sample kits').locator('textarea').fill(value);
21+
}
22+
23+
getField(field: string): Locator {
24+
return this.page.locator('tab.active[role="tabpanel"]').locator(`xpath=//tr[td[normalize-space()="${field}"]]`);
25+
}
26+
}

playwright-e2e/dsm/component/tabs/tabs.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
1-
import {Locator, Page} from '@playwright/test';
1+
import { expect, Locator, Page } from '@playwright/test';
22
import {TabEnum} from 'dsm/component/tabs/enums/tab-enum';
33
import ContactInformationTab from 'dsm/component/tabs/contactInformationTab';
4+
import GenomeStudyTab from 'dsm/component/tabs/genome-study-tab';
45
import SampleInformationTab from 'dsm/component/tabs/sampleInformationTab';
56

67
export default class Tabs {
78
private readonly tabs = new Map<string, object>([
89
[TabEnum.CONTACT_INFORMATION, new ContactInformationTab(this.page)],
9-
[TabEnum.SAMPLE_INFORMATION, new SampleInformationTab(this.page)]
10+
[TabEnum.SAMPLE_INFORMATION, new SampleInformationTab(this.page)],
11+
[TabEnum.GENOME_STUDY, new GenomeStudyTab(this.page)],
1012
])
1113

1214
constructor(private readonly page: Page) {}
1315

1416
public async clickTab<T extends object>(tabName: TabEnum): Promise<T> {
1517
await this.tabLocator(tabName).click();
18+
await expect(await new Tabs(this.page).isOpen(tabName)).toBe(true);
1619
return (this.tabs as Map<string, object>).get(tabName) as T;
1720
}
1821

@@ -26,6 +29,11 @@ export default class Tabs {
2629
return isTabVisible && contactInformationEntered;
2730
}
2831

32+
private async isOpen(tabName: TabEnum): Promise<boolean> {
33+
const clas = await this.tabLocator(tabName).getAttribute('class');
34+
return clas ? clas.includes('active') : false;
35+
}
36+
2937
private async HasContactInformationTabEnteredData(): Promise<boolean> {
3038
const isNotEnteredVisible = await (this.tabs.get(TabEnum.CONTACT_INFORMATION) as ContactInformationTab)
3139
.isNotEnteredVisible()

playwright-e2e/dsm/pages/participant-list-page.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,30 @@ export default class ParticipantListPage {
151151
await searchPanel.search();
152152
}
153153

154+
public async filterListByShortId(shortId: string, opts: { resultsCount?: number } = {}): Promise<void> {
155+
if (!shortId) {
156+
throw new Error('shortId cannot be null');
157+
}
158+
const { resultsCount = 1 } = opts;
159+
const participantsTable = this.participantListTable;
160+
await this.waitForReady();
161+
162+
const searchPanel = this.filters.searchPanel;
163+
await searchPanel.open();
164+
await searchPanel.text('Short ID', { textValue: shortId });
165+
await searchPanel.search();
166+
167+
await expect(participantsTable.footerLocator().first()).toBeVisible();
168+
await expect(await participantsTable.rowsCount).toBe(resultsCount);
169+
}
170+
154171
public async addColumnsToParticipantList(columnGroup: string, columnOptions: string[]): Promise<void> {
155172
const customizeViewPanel = this.filters.customizeViewPanel;
156173
await customizeViewPanel.open();
157174
await customizeViewPanel.selectColumns(columnGroup, columnOptions);
158175
}
159176

177+
160178
/* Locators */
161179
private get tableRowsLocator(): Locator {
162180
return this.page.locator('[role="row"]:not([mat-header-row]):not(mat-header-row), tbody tr');
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { expect, Page } from '@playwright/test';
2+
import DatePicker from 'dsm/component/date-picker';
3+
import Select from 'dss/component/select';
4+
import Table from 'dss/component/table';
5+
import { waitForNoSpinner } from 'utils/test-utils';
6+
7+
export enum SearchByField {
8+
SHORT_ID = 'Short ID',
9+
TRACKING_NUMBER = 'Tracking Number (Blood kit return)',
10+
MANUFACTURE_BARCODE = 'Manufacturer Barcode'
11+
}
12+
13+
export default class SearchPage {
14+
constructor(private readonly page: Page) {}
15+
16+
async waitForReady(): Promise<void> {
17+
await expect(this.page.locator('h1')).toHaveText('Kit Search');
18+
}
19+
20+
async searchByField(searchField: SearchByField, value: string): Promise<Table> {
21+
const select = new Select(this.page, { label: 'Search by Field', root: 'app-shipping-search' });
22+
await select.selectOption(searchField);
23+
const locator = this.page.locator('//div[button[normalize-space()="Search Kit"]]');
24+
await locator.locator('//input').fill(value);
25+
await locator.locator('//button').click();
26+
await waitForNoSpinner(this.page);
27+
28+
const table = new Table(this.page);
29+
await table.waitForReady();
30+
return table
31+
}
32+
33+
async pickEndDate(opts: { yyyy?: number, month?: number, dayOfMonth?: number } = {}): Promise<string> {
34+
const { yyyy, month, dayOfMonth } = opts;
35+
return new DatePicker(this.page, { nth: 1 }).pickDate({ yyyy, month, dayOfMonth });
36+
}
37+
38+
/**
39+
* Click Reload button
40+
* @returns {Promise<void>}
41+
*/
42+
async reload(): Promise<void> {
43+
await this.page.locator('button', { hasText: 'Reload' }).click();
44+
}
45+
}

playwright-e2e/dss/pages/page-base.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { expect, Locator, Page, Response } from '@playwright/test';
22
import Address from 'dss/component/address';
33
import Institution from 'dss/component/institution';
44
import Question from 'dss/component/Question';
5-
import Checkbox from 'dss/component/checkbox';
65
import Input from 'dss/component/input';
76
import { assertSelectedOption } from 'utils/assertion-helper';
87
import { generateRandomPhoneNum } from 'utils/faker-utils';
@@ -416,9 +415,10 @@ export default abstract class PageBase implements PageInterface {
416415
: new Question(this.page, { prompt: 'Signature' }).toInput();
417416
}
418417

419-
async getDate(): Promise<Date> {
418+
async getDisplayedDate(): Promise<string> {
420419
const locator = this.page.locator('//*[./h3[text()="Date"]]/following-sibling::*/p');
421-
const str = (await locator.innerText()).trim().replace(' ', '');
422-
return new Date(str);
420+
const dateString = await locator.innerText();
421+
const [MM, DD, YYYY] = dateString.split('/');
422+
return `${MM.trim()}/${DD.trim()}/${YYYY.trim()}`;
423423
}
424424
}

playwright-e2e/playwright.config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,12 @@ const testConfig: PlaywrightTestConfig = {
7474
// baseURL: 'http://localhost:3000',
7575

7676
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
77-
trace: process.env.CI ? 'on-first-retry' : 'retain-on-failure',
77+
trace: 'retain-on-failure',
7878
screenshot: {
7979
mode: 'only-on-failure',
8080
fullPage: true
8181
},
82-
video: process.env.video ? 'on' : process.env.CI ? 'on-first-retry' : 'retain-on-failure', // Limit load on CI system because trace and video add load
82+
video: 'retain-on-failure', // Limit load on CI system because trace and video add load
8383

8484
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36',
8585
viewport: { width: 1280, height: 960 },

0 commit comments

Comments
 (0)