From 66c1857e8c2ae0a92c22e57e60be6334f748c146 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Tue, 27 Aug 2024 12:47:46 -0400 Subject: [PATCH 01/26] WIP --- .../place-clinical-order-in-mercury.spec.ts | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts new file mode 100644 index 0000000000..0e61e8eba0 --- /dev/null +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -0,0 +1,68 @@ +import { expect } from '@playwright/test'; +import { CustomizeView, DataFilter, Label } from 'dsm/enums'; +import { Navigation, Study, StudyName } from 'dsm/navigation'; +import ParticipantListPage from 'dsm/pages/participant-list-page'; +import Select from 'dss/component/select'; +import { test } from 'fixtures/dsm-fixture'; + +const pecgsStudies = [StudyName.OSTEO2]; //Checking OS2 first +test.describe.serial('Verify that clinical orders can be placed in mercury @dsm @functional', () => { + let navigation; + let customizeViewPanel; + let searchPanel; + let shortID; + let participantPage; + + for (const study of pecgsStudies) { + test(`${study}: Verify a clinical order can be placed for a participant with Enrolled status`, async ({ page, request }) => { + navigation = new Navigation(page, request); + await new Select(page, { label: 'Select study' }).selectOption(study); + + const participantListPage = await navigation.selectFromStudy(Study.PARTICIPANT_LIST); + await participantListPage.waitForReady(); + + const participantListTable = participantListPage.participantListTable; + + await test.step(`Put Clinical Order ID and Clinical Order Date columns onto the Participant List`, async () => { + customizeViewPanel = participantListPage.filters.customizeViewPanel; + await customizeViewPanel.open(); + await customizeViewPanel.selectColumns(CustomizeView.CLINICAL_ORDERS, [Label.CLINICAL_ORDER_DATE, Label.CLINICAL_ORDER_ID]); + await customizeViewPanel.close(); + }) + + await test.step(`Look for a participant that is enrolled that already has had an order placed at some point`, async () => { + searchPanel = participantListPage.filters.searchPanel; + await searchPanel.open(); + await searchPanel.checkboxes(Label.STATUS, { checkboxValues: [DataFilter.ENROLLED] }); + await searchPanel.dates(Label.CLINICAL_ORDER_DATE, { additionalFilters: [DataFilter.NOT_EMPTY] }); + await searchPanel.text(Label.CLINICAL_ORDER_ID, { additionalFilters: [DataFilter.NOT_EMPTY] }); + await searchPanel.search({ uri: 'filterList' }); + + const numberOfReturnedParticipants = await participantListTable.getRowsCount(); + expect(numberOfReturnedParticipants).toBeGreaterThanOrEqual(1); + + shortID = await participantListTable.getCellDataForColumn(Label.SHORT_ID, 1); + console.log(`shortID: ${shortID}`); + expect(shortID).toBeTruthy(); + + await participantListPage.filterListByShortId(shortID); + participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); + await participantPage.waitForReady(); + }) + + await test.step(`Place the order in mercury via Participant Page -> Sequencing Order tab`, async () => { + //Stuff here + }) + }) + + test(`${study}: Verify a clinical order can be placed for a participant with Lost-to-FollowUp status`, async ({ page, request }) => { + navigation = new Navigation(page, request); + await new Select(page, { label: 'Select study' }).selectOption(study); + + const participantListPage = await navigation.selectFromStudy(Study.PARTICIPANT_LIST); + await participantListPage.waitForReady(); + + const participantListTable = participantListPage.participantListTable; + }) + } +}) From 36ba812dd0346ffc079dbd02f88734e8249f4abd Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Fri, 30 Aug 2024 13:38:31 -0400 Subject: [PATCH 02/26] putting in method to get relevant ptps --- playwright-e2e/dsm/enums.ts | 13 ++++--- .../dsm/pages/tablist/sequencing-order-tab.ts | 11 ++++++ .../place-clinical-order-in-mercury.spec.ts | 37 +++++++++++++++++++ 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/playwright-e2e/dsm/enums.ts b/playwright-e2e/dsm/enums.ts index 690ab1265e..cf4991a043 100644 --- a/playwright-e2e/dsm/enums.ts +++ b/playwright-e2e/dsm/enums.ts @@ -11,16 +11,17 @@ export enum KitSampleType { } export enum DataFilter { - NOT_EMPTY = 'Not Empty', - EXACT_MATCH = 'Exact Match', - RANGE = 'Range', EMPTY = 'Empty', ENROLLED = 'Enrolled', - REQUEST = 'Request', - RECEIVED = 'Received', + EXACT_MATCH = 'Exact Match', + LOST_TO_FOLLOWUP = 'Lost to Followup', NO = 'No', - YES = 'Yes', + NOT_EMPTY = 'Not Empty', + RANGE = 'Range', + RECEIVED = 'Received', REGISTERED = 'Registered', + REQUEST = 'Request', + YES = 'Yes', } export enum FieldSettingInputType { diff --git a/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts b/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts index 97f7e16d22..55df1b0479 100644 --- a/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts +++ b/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts @@ -7,6 +7,17 @@ export default class SequeuncingOrderTab extends TabBase { private readonly SAMPLE_ROW_XPATH = '//app-sequencing-order//tr'; private readonly DATE_FIELD_XPATH = `//input[@data-placeholder='mm/dd/yyyy']`; private readonly NOT_ELIGIBLE_DUE_TO_RESIDENCE = `Error: Participant lives in New York or Canada and is not eligible for clinical sequencing`; + private readonly SEQUENCING_ORDER_COLUMNS = [ + 'Select', + 'Sample Type', + 'Sample', + 'Sample Status', + 'Collection Date', + 'Latest Sequencing Order Date', + 'Latest Order Status', + 'Latest Order Number', + 'Latest PDO Number' + ]; constructor(page: Page) { super(page, Tab.SEQUENCING_ORDER); diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index 0e61e8eba0..e168622f97 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -1,4 +1,5 @@ import { expect } from '@playwright/test'; +import { ParticipantListTable } from 'dsm/component/tables/participant-list-table'; import { CustomizeView, DataFilter, Label } from 'dsm/enums'; import { Navigation, Study, StudyName } from 'dsm/navigation'; import ParticipantListPage from 'dsm/pages/participant-list-page'; @@ -12,6 +13,7 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm let searchPanel; let shortID; let participantPage; + let sequencingOrderID; for (const study of pecgsStudies) { test(`${study}: Verify a clinical order can be placed for a participant with Enrolled status`, async ({ page, request }) => { @@ -66,3 +68,38 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm }) } }) + +async function findParticipantForGermlineSequencing(opts: { + enrollmentStatus: DataFilter.ENROLLED | DataFilter.LOST_TO_FOLLOWUP, + participantListPage: ParticipantListPage, + participantListTable: ParticipantListTable + residenceInUSTerritory?: boolean +}): Promise { + const { enrollmentStatus, participantListPage, participantListTable, residenceInUSTerritory = false } = opts; + + const customizeViewPanel = participantListPage.filters.customizeViewPanel; + await customizeViewPanel.open(); + await customizeViewPanel.selectColumns(CustomizeView.CONTACT_INFORMATION, [Label.CITY, Label.COUNTRY]); + await customizeViewPanel.close(); + + const searchPanel = participantListPage.filters.searchPanel; + await searchPanel.open(); + await searchPanel.checkboxes(Label.STATUS, { checkboxValues: [enrollmentStatus] }); + await searchPanel.dates(Label.CLINICAL_ORDER_DATE, { additionalFilters: [DataFilter.NOT_EMPTY] }); + await searchPanel.text(Label.CLINICAL_ORDER_ID, { additionalFilters: [DataFilter.NOT_EMPTY] }); + + if (residenceInUSTerritory) { + //Location used: Yigo, Guam + await searchPanel.text(Label.CITY, { textValue: 'YIGO' }); + await searchPanel.text(Label.COUNTRY, { textValue: 'GU' }); + } else { + await searchPanel.text(Label.CITY, { textValue: 'CAMBRIDGE' }); + await searchPanel.text(Label.COUNTRY, { textValue: 'US' }); + } + + await searchPanel.search({ uri: 'filterList' }); + + const numberOfReturnedParticipants = await participantListTable.getRowsCount(); + expect(numberOfReturnedParticipants).toBeGreaterThanOrEqual(1); +} + From c9eb0d1827cf10e3c7644319ae21cc9e7ff66b19 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Wed, 4 Sep 2024 12:23:47 -0400 Subject: [PATCH 03/26] in sequencing order tab --- .../dsm/pages/tablist/sequencing-order-tab.ts | 41 +++++-- .../place-clinical-order-in-mercury.spec.ts | 112 ++++++++++++------ 2 files changed, 104 insertions(+), 49 deletions(-) diff --git a/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts b/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts index 55df1b0479..839d815d4a 100644 --- a/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts +++ b/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts @@ -7,17 +7,7 @@ export default class SequeuncingOrderTab extends TabBase { private readonly SAMPLE_ROW_XPATH = '//app-sequencing-order//tr'; private readonly DATE_FIELD_XPATH = `//input[@data-placeholder='mm/dd/yyyy']`; private readonly NOT_ELIGIBLE_DUE_TO_RESIDENCE = `Error: Participant lives in New York or Canada and is not eligible for clinical sequencing`; - private readonly SEQUENCING_ORDER_COLUMNS = [ - 'Select', - 'Sample Type', - 'Sample', - 'Sample Status', - 'Collection Date', - 'Latest Sequencing Order Date', - 'Latest Order Status', - 'Latest Order Number', - 'Latest PDO Number' - ]; + private readonly PLACE_ORDER_MODAL_TEXT = `Are you sure you want to place a clinical sequencing order for the following samples:`; constructor(page: Page) { super(page, Tab.SEQUENCING_ORDER); @@ -49,11 +39,35 @@ export default class SequeuncingOrderTab extends TabBase { await expect(placeOrderButton).not.toBeVisible(); } + public async assertPlaceOrderButtonDisplayed(): Promise { + const placeOrderButton = this.getPlaceOrderButton(); + await placeOrderButton.scrollIntoViewIfNeeded(); + await expect(placeOrderButton, 'The Place Order button is not visible to the current DSM user').toBeVisible(); + } + public async assertParticipantNotEligibleForClinicalSequencing(): Promise { const validationMessage = this.page.getByText(this.NOT_ELIGIBLE_DUE_TO_RESIDENCE); await expect(validationMessage).toBeVisible(); } + public async assertClinicalOrderModalDisplayed(): Promise { + const placeOrderModal = this.page.locator(`//div[contains(text(), '${this.PLACE_ORDER_MODAL_TEXT}')]`); + await placeOrderModal.scrollIntoViewIfNeeded(); + await expect(placeOrderModal, 'Place Order modal is not visible - clinical order cannot be placed').toBeVisible(); + } + + public async closeClinicalOrderModal(): Promise { + const button = this.page.locator(`//div[@class='modal-content']/div[@class='modal-footer']//button[normalize-space(text())='Close']`); + await expect(button, 'Clinical Order modal -> [Close] button is not visible').toBeVisible(); + await button.click(); + } + + public async submitClinicalOrder(): Promise { + const button = this.page.locator(`//div[@class='modal-content']/div[@class='modal-footer']//button[normalize-space(text())='Submit']`); + await expect(button, 'Clinical Order modal -> [Submit] button is not visible').toBeVisible(); + await button.click(); + } + public async fillAvailableCollectionDateFields(opts: {canPlaceClinicalOrder?: boolean}): Promise { const { canPlaceClinicalOrder = true } = opts; const collectionDateIndex = canPlaceClinicalOrder ? 5 : 4; //Index depending on whether test user has permission to place clinical order @@ -106,6 +120,11 @@ export default class SequeuncingOrderTab extends TabBase { return this.toLocator.getByRole('button', { name: 'Place order' }); } + public async selectSampleCheckbox(sample: Locator): Promise { + const checkbox = sample.locator('//mat-checkbox'); + await checkbox.click(); + } + private getCheckboxOfSample(sample: Locator): Locator { return sample.locator('//mat-checkbox'); } diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index e168622f97..4ad3bc5bdc 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -1,19 +1,23 @@ -import { expect } from '@playwright/test'; +import { expect, Locator } from '@playwright/test'; import { ParticipantListTable } from 'dsm/component/tables/participant-list-table'; -import { CustomizeView, DataFilter, Label } from 'dsm/enums'; +import { CustomizeView, DataFilter, Label, Tab } from 'dsm/enums'; import { Navigation, Study, StudyName } from 'dsm/navigation'; import ParticipantListPage from 'dsm/pages/participant-list-page'; +import ParticipantPage from 'dsm/pages/participant-page'; +import SequeuncingOrderTab from 'dsm/pages/tablist/sequencing-order-tab'; import Select from 'dss/component/select'; import { test } from 'fixtures/dsm-fixture'; +import { studyShortName } from 'utils/test-utils'; const pecgsStudies = [StudyName.OSTEO2]; //Checking OS2 first test.describe.serial('Verify that clinical orders can be placed in mercury @dsm @functional', () => { let navigation; - let customizeViewPanel; - let searchPanel; let shortID; - let participantPage; - let sequencingOrderID; + let participantPage: ParticipantPage; + let sequencingOrderTab: SequeuncingOrderTab; + let normalSample: Locator; + let tumorSample: Locator; + let previousLatestOrderNumber: string; for (const study of pecgsStudies) { test(`${study}: Verify a clinical order can be placed for a participant with Enrolled status`, async ({ page, request }) => { @@ -22,39 +26,45 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm const participantListPage = await navigation.selectFromStudy(Study.PARTICIPANT_LIST); await participantListPage.waitForReady(); - const participantListTable = participantListPage.participantListTable; - await test.step(`Put Clinical Order ID and Clinical Order Date columns onto the Participant List`, async () => { - customizeViewPanel = participantListPage.filters.customizeViewPanel; - await customizeViewPanel.open(); - await customizeViewPanel.selectColumns(CustomizeView.CLINICAL_ORDERS, [Label.CLINICAL_ORDER_DATE, Label.CLINICAL_ORDER_ID]); - await customizeViewPanel.close(); - }) - - await test.step(`Look for a participant that is enrolled that already has had an order placed at some point`, async () => { - searchPanel = participantListPage.filters.searchPanel; - await searchPanel.open(); - await searchPanel.checkboxes(Label.STATUS, { checkboxValues: [DataFilter.ENROLLED] }); - await searchPanel.dates(Label.CLINICAL_ORDER_DATE, { additionalFilters: [DataFilter.NOT_EMPTY] }); - await searchPanel.text(Label.CLINICAL_ORDER_ID, { additionalFilters: [DataFilter.NOT_EMPTY] }); - await searchPanel.search({ uri: 'filterList' }); - - const numberOfReturnedParticipants = await participantListTable.getRowsCount(); - expect(numberOfReturnedParticipants).toBeGreaterThanOrEqual(1); - - shortID = await participantListTable.getCellDataForColumn(Label.SHORT_ID, 1); - console.log(`shortID: ${shortID}`); - expect(shortID).toBeTruthy(); + await test.step('Chose an enrolled participant that will get a clinical order placed', async () => { + shortID = await findParticipantForGermlineSequencing({ + enrollmentStatus: DataFilter.ENROLLED, + participantList: participantListPage, + participantTable: participantListTable, + studyName: study + }); await participantListPage.filterListByShortId(shortID); participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); await participantPage.waitForReady(); - }) + }); + + await test.step('Make sure that the Sequencing Order tab is visible', async () => { + await participantPage.tablist(Tab.SEQUENCING_ORDER).isVisible(); + sequencingOrderTab = await participantPage.tablist(Tab.SEQUENCING_ORDER).click(); + await sequencingOrderTab.waitForReady(); + }); + + await test.step('Place a clinical order using the Sequencing Order tab', async () => { + normalSample = await sequencingOrderTab.getFirstAvailableNormalSample(); + await sequencingOrderTab.selectSampleCheckbox(normalSample); + + tumorSample = await sequencingOrderTab.getFirstAvailableTumorSample(); + await sequencingOrderTab.selectSampleCheckbox(tumorSample); - await test.step(`Place the order in mercury via Participant Page -> Sequencing Order tab`, async () => { - //Stuff here - }) + await sequencingOrderTab.assertPlaceOrderButtonDisplayed(); + await sequencingOrderTab.placeOrder(); + + await sequencingOrderTab.assertClinicalOrderModalDisplayed(); + await sequencingOrderTab.submitClinicalOrder(); + }); + + /* NOTE: Need to go from Participant Page -> Participant List -> (refresh) -> Participant Page in order to see the new info */ + await test.step('Use the new Latest Order Number to place the order in mercury', async () => { + //Verify that Latest Sequencing Order Date is the current date and Latest Order Number has received new input + }); }) test(`${study}: Verify a clinical order can be placed for a participant with Lost-to-FollowUp status`, async ({ page, request }) => { @@ -71,19 +81,36 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm async function findParticipantForGermlineSequencing(opts: { enrollmentStatus: DataFilter.ENROLLED | DataFilter.LOST_TO_FOLLOWUP, - participantListPage: ParticipantListPage, - participantListTable: ParticipantListTable + participantList: ParticipantListPage, + participantTable: ParticipantListTable, + studyName: StudyName, + usePediatricParticipant?: boolean, residenceInUSTerritory?: boolean }): Promise { - const { enrollmentStatus, participantListPage, participantListTable, residenceInUSTerritory = false } = opts; + const { enrollmentStatus, participantList, participantTable, studyName, usePediatricParticipant = false, residenceInUSTerritory = false } = opts; + + const studyInformation = studyShortName(studyName); + let participantPrefix = studyInformation.playwrightPrefixAdult; + if (usePediatricParticipant) { + participantPrefix = studyInformation.playwrightPrefixChild; + } + console.log(`prefix: ${participantPrefix}`); - const customizeViewPanel = participantListPage.filters.customizeViewPanel; + const customizeViewPanel = participantList.filters.customizeViewPanel; await customizeViewPanel.open(); + await customizeViewPanel.selectColumns(CustomizeView.CLINICAL_ORDERS, [ + Label.CLINICAL_ORDER_DATE, + Label.CLINICAL_ORDER_ID, + Label.CLINICAL_ORDER_PDO_NUMBER, + Label.CLINICAL_ORDER_STATUS, + Label.CLINICAL_ORDER_STATUS_DATE + ]); await customizeViewPanel.selectColumns(CustomizeView.CONTACT_INFORMATION, [Label.CITY, Label.COUNTRY]); await customizeViewPanel.close(); - const searchPanel = participantListPage.filters.searchPanel; + const searchPanel = participantList.filters.searchPanel; await searchPanel.open(); + await searchPanel.text(Label.FIRST_NAME, { textValue: participantPrefix, additionalFilters: [DataFilter.EXACT_MATCH], exactMatch: false }); await searchPanel.checkboxes(Label.STATUS, { checkboxValues: [enrollmentStatus] }); await searchPanel.dates(Label.CLINICAL_ORDER_DATE, { additionalFilters: [DataFilter.NOT_EMPTY] }); await searchPanel.text(Label.CLINICAL_ORDER_ID, { additionalFilters: [DataFilter.NOT_EMPTY] }); @@ -99,7 +126,16 @@ async function findParticipantForGermlineSequencing(opts: { await searchPanel.search({ uri: 'filterList' }); - const numberOfReturnedParticipants = await participantListTable.getRowsCount(); + const numberOfReturnedParticipants = await participantTable.getRowsCount(); expect(numberOfReturnedParticipants).toBeGreaterThanOrEqual(1); + + //Randomly chose a participant to get a clinical order who had previously had an order placed + const randomizedParticipantRows = await participantTable.randomizeRows(); + const rowNumber = randomizedParticipantRows[0]; + + const shortID = await participantTable.getParticipantDataAt(rowNumber, Label.SHORT_ID); + console.log(`Participant chosen for clinical order: ${shortID}`); + + return shortID; } From fb683a5d6b10c547560054ebb12f145de4ef2fd7 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Fri, 6 Sep 2024 17:03:25 -0400 Subject: [PATCH 04/26] continuing with placing a clinical order --- playwright-e2e/dsm/enums.ts | 11 ++++++ .../dsm/pages/tablist/sequencing-order-tab.ts | 37 +++++++++++++++++-- .../place-clinical-order-in-mercury.spec.ts | 36 ++++++++++++++++-- 3 files changed, 77 insertions(+), 7 deletions(-) diff --git a/playwright-e2e/dsm/enums.ts b/playwright-e2e/dsm/enums.ts index cf4991a043..73e2a7fa75 100644 --- a/playwright-e2e/dsm/enums.ts +++ b/playwright-e2e/dsm/enums.ts @@ -784,3 +784,14 @@ export enum ParticipantListPageOptions { SAVE_CURRENT_VIEW = 'Save Current View', SAVED_FILTERS = 'Saved Filters', } + +export enum SequencingOrderColumn { + SAMPLE_TYPE = 'Sample Type', + SAMPLE = 'Sample', + SAMPLE_STATUS = 'Sample Status', + COLLECTION_DATE = 'Collection Date', + LATEST_SEQUENCING_ORDER_DATE = 'Latest Seqeuncing Order Date', + LATEST_ORDER_STATUS = 'Latetst Order Status', + LATEST_ORDER_NUMBER = 'Latest Order Number', + LATEST_PDO_NUMBER = 'Latest PDO Number', +} diff --git a/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts b/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts index 839d815d4a..f0368f1d22 100644 --- a/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts +++ b/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts @@ -1,13 +1,13 @@ import { Locator, Page, expect } from '@playwright/test'; -import { getDate } from 'utils/date-utils'; +import { getDate, getDateinISOFormat, getToday } from 'utils/date-utils'; import TabBase from './tab-base'; -import { Tab } from 'dsm/enums'; +import { SequencingOrderColumn, Tab } from 'dsm/enums'; export default class SequeuncingOrderTab extends TabBase { private readonly SAMPLE_ROW_XPATH = '//app-sequencing-order//tr'; private readonly DATE_FIELD_XPATH = `//input[@data-placeholder='mm/dd/yyyy']`; private readonly NOT_ELIGIBLE_DUE_TO_RESIDENCE = `Error: Participant lives in New York or Canada and is not eligible for clinical sequencing`; - private readonly PLACE_ORDER_MODAL_TEXT = `Are you sure you want to place a clinical sequencing order for the following samples:`; + private readonly PLACE_CLINICAL_ORDER_MODAL_TEXT = `Are you sure you want to place a clinical sequencing order for the following samples:`; constructor(page: Page) { super(page, Tab.SEQUENCING_ORDER); @@ -51,7 +51,7 @@ export default class SequeuncingOrderTab extends TabBase { } public async assertClinicalOrderModalDisplayed(): Promise { - const placeOrderModal = this.page.locator(`//div[contains(text(), '${this.PLACE_ORDER_MODAL_TEXT}')]`); + const placeOrderModal = this.page.locator(`//div[contains(text(), '${this.PLACE_CLINICAL_ORDER_MODAL_TEXT}')]`); await placeOrderModal.scrollIntoViewIfNeeded(); await expect(placeOrderModal, 'Place Order modal is not visible - clinical order cannot be placed').toBeVisible(); } @@ -125,6 +125,28 @@ export default class SequeuncingOrderTab extends TabBase { await checkbox.click(); } + public async getColumnDataForSample(sample: Locator, columnName: SequencingOrderColumn): Promise { + const columnIndex = await this.getColumnHeaderIndex(columnName); + const cellContent = await sample.locator(`//td[${columnIndex}]`).textContent() as string; + console.log(`Sequencing order tab - sample data under ${columnName} column: ${cellContent}`); + return cellContent; + } + + public async fillCollectionDateIfNeeded(normalSample: Locator): Promise { + const collectionDateColumnIndex = await this.getColumnHeaderIndex(SequencingOrderColumn.COLLECTION_DATE); + const unfilledCollectionDateColumn = normalSample.locator(`//td[${collectionDateColumnIndex}]/app-field-datepicker//input`); + if (unfilledCollectionDateColumn) { + await normalSample.locator(`//td[${collectionDateColumnIndex}]//button[normalize-space(text())='Today']`).click(); + + //Assert that the correct date was inputted + const today = getToday(); + const collectionDateInISOFormat = getDateinISOFormat(today); + const collectionDateColumn = normalSample.locator(`//td[${collectionDateColumnIndex}]`); + const collectionDate = await collectionDateColumn.innerText(); + expect(collectionDate).toBe(collectionDateInISOFormat); + } + } + private getCheckboxOfSample(sample: Locator): Locator { return sample.locator('//mat-checkbox'); } @@ -144,4 +166,11 @@ export default class SequeuncingOrderTab extends TabBase { expect(amountOfSamples, 'No tumor samples were available in the Sequencing tab').toBeGreaterThanOrEqual(1); return samples; } + + private async getColumnHeaderIndex(columnName: SequencingOrderColumn): Promise { + const precedingColumns = this.page.locator(`//th[normalize-space(text())='${columnName}']/preceding-sibling::th`); + const columnIndex = await precedingColumns.count() + 1; + console.log(`${columnName} is the ${columnIndex}th column`); + return columnIndex; + } } diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index 4ad3bc5bdc..4fccf8a876 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -1,23 +1,25 @@ import { expect, Locator } from '@playwright/test'; import { ParticipantListTable } from 'dsm/component/tables/participant-list-table'; -import { CustomizeView, DataFilter, Label, Tab } from 'dsm/enums'; +import { CustomizeView, DataFilter, Label, SequencingOrderColumn, Tab } from 'dsm/enums'; import { Navigation, Study, StudyName } from 'dsm/navigation'; import ParticipantListPage from 'dsm/pages/participant-list-page'; import ParticipantPage from 'dsm/pages/participant-page'; import SequeuncingOrderTab from 'dsm/pages/tablist/sequencing-order-tab'; import Select from 'dss/component/select'; import { test } from 'fixtures/dsm-fixture'; +import { getToday } from 'utils/date-utils'; import { studyShortName } from 'utils/test-utils'; const pecgsStudies = [StudyName.OSTEO2]; //Checking OS2 first test.describe.serial('Verify that clinical orders can be placed in mercury @dsm @functional', () => { let navigation; - let shortID; + let shortID: string; let participantPage: ParticipantPage; let sequencingOrderTab: SequeuncingOrderTab; let normalSample: Locator; let tumorSample: Locator; - let previousLatestOrderNumber: string; + let previousLatestOrderNumberTumor: string; + let previousLatestOrderNumberNormal: string; for (const study of pecgsStudies) { test(`${study}: Verify a clinical order can be placed for a participant with Enrolled status`, async ({ page, request }) => { @@ -50,9 +52,16 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm await test.step('Place a clinical order using the Sequencing Order tab', async () => { normalSample = await sequencingOrderTab.getFirstAvailableNormalSample(); await sequencingOrderTab.selectSampleCheckbox(normalSample); + //console.log(`normal xpath: ${normalSample}`); + await sequencingOrderTab.fillCollectionDateIfNeeded(normalSample); + previousLatestOrderNumberNormal = await sequencingOrderTab.getColumnDataForSample(normalSample, SequencingOrderColumn.LATEST_ORDER_NUMBER); + console.log(`previous Latest Order Number for normal sample: ${previousLatestOrderNumberNormal}`); tumorSample = await sequencingOrderTab.getFirstAvailableTumorSample(); await sequencingOrderTab.selectSampleCheckbox(tumorSample); + //console.log(`tumor xpath: ${tumorSample}`); + previousLatestOrderNumberTumor = await sequencingOrderTab.getColumnDataForSample(tumorSample, SequencingOrderColumn.LATEST_ORDER_NUMBER); + console.log(`previous Latest Order Number for tumor sample: ${previousLatestOrderNumberTumor}`); await sequencingOrderTab.assertPlaceOrderButtonDisplayed(); await sequencingOrderTab.placeOrder(); @@ -63,7 +72,28 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm /* NOTE: Need to go from Participant Page -> Participant List -> (refresh) -> Participant Page in order to see the new info */ await test.step('Use the new Latest Order Number to place the order in mercury', async () => { + await participantPage.backToList(); + await participantListPage.filterListByShortId(shortID); + await participantListTable.openParticipantPageAt({ position: 0 }); + + await participantPage.waitForReady(); + sequencingOrderTab = await participantPage.tablist(Tab.SEQUENCING_ORDER).click(); + await sequencingOrderTab.waitForReady(); + //Verify that Latest Sequencing Order Date is the current date and Latest Order Number has received new input + const today = getToday(); + + const orderDateNormal = await sequencingOrderTab.getColumnDataForSample(normalSample, SequencingOrderColumn.LATEST_SEQUENCING_ORDER_DATE); + expect(orderDateNormal).toBe(today); + + const orderDateTumor = await sequencingOrderTab.getColumnDataForSample(tumorSample, SequencingOrderColumn.LATEST_SEQUENCING_ORDER_DATE); + expect(orderDateTumor).toBe(today); + + const newLatestOrderNumberNormal = await sequencingOrderTab.getColumnDataForSample(normalSample, SequencingOrderColumn.LATEST_ORDER_NUMBER); + expect(newLatestOrderNumberNormal).not.toBe(previousLatestOrderNumberNormal); + + const newLatestOrderNumberTumor = await sequencingOrderTab.getColumnDataForSample(tumorSample, SequencingOrderColumn.LATEST_ORDER_NUMBER); + expect(newLatestOrderNumberTumor).not.toBe(previousLatestOrderNumberTumor); }); }) From 5571344e9f8f482560a396b29be423b062b73d41 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Mon, 9 Sep 2024 09:56:35 -0400 Subject: [PATCH 05/26] beginnings of placing a mercury order also installed gcp pubsub library --- playwright-e2e/dsm/enums.ts | 4 +- .../dsm/pages/tablist/sequencing-order-tab.ts | 5 +- playwright-e2e/package-lock.json | 793 +++++++++++++++++- playwright-e2e/package.json | 1 + .../place-clinical-order-in-mercury.spec.ts | 46 +- 5 files changed, 825 insertions(+), 24 deletions(-) diff --git a/playwright-e2e/dsm/enums.ts b/playwright-e2e/dsm/enums.ts index 73e2a7fa75..d5ce1727a9 100644 --- a/playwright-e2e/dsm/enums.ts +++ b/playwright-e2e/dsm/enums.ts @@ -790,8 +790,8 @@ export enum SequencingOrderColumn { SAMPLE = 'Sample', SAMPLE_STATUS = 'Sample Status', COLLECTION_DATE = 'Collection Date', - LATEST_SEQUENCING_ORDER_DATE = 'Latest Seqeuncing Order Date', - LATEST_ORDER_STATUS = 'Latetst Order Status', + LATEST_SEQUENCING_ORDER_DATE = 'Latest Sequencing Order Date', + LATEST_ORDER_STATUS = 'Latest Order Status', LATEST_ORDER_NUMBER = 'Latest Order Number', LATEST_PDO_NUMBER = 'Latest PDO Number', } diff --git a/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts b/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts index f0368f1d22..5d6b611d19 100644 --- a/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts +++ b/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts @@ -135,15 +135,14 @@ export default class SequeuncingOrderTab extends TabBase { public async fillCollectionDateIfNeeded(normalSample: Locator): Promise { const collectionDateColumnIndex = await this.getColumnHeaderIndex(SequencingOrderColumn.COLLECTION_DATE); const unfilledCollectionDateColumn = normalSample.locator(`//td[${collectionDateColumnIndex}]/app-field-datepicker//input`); - if (unfilledCollectionDateColumn) { + if (await unfilledCollectionDateColumn.isVisible()) { await normalSample.locator(`//td[${collectionDateColumnIndex}]//button[normalize-space(text())='Today']`).click(); //Assert that the correct date was inputted const today = getToday(); const collectionDateInISOFormat = getDateinISOFormat(today); const collectionDateColumn = normalSample.locator(`//td[${collectionDateColumnIndex}]`); - const collectionDate = await collectionDateColumn.innerText(); - expect(collectionDate).toBe(collectionDateInISOFormat); + await expect(collectionDateColumn).toHaveText(collectionDateInISOFormat); } } diff --git a/playwright-e2e/package-lock.json b/playwright-e2e/package-lock.json index 54fe27bd61..0bb9767858 100644 --- a/playwright-e2e/package-lock.json +++ b/playwright-e2e/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "dependencies": { "@google-cloud/local-auth": "^2.1.1", + "@google-cloud/pubsub": "^4.7.1", "@googleapis/gmail": "^1.1.1", "@types/lodash": "^4.14.191", "@types/node": "^20.11.5", @@ -136,6 +137,155 @@ "node": ">=12.0.0" } }, + "node_modules/@google-cloud/paginator": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.2.tgz", + "integrity": "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==", + "license": "Apache-2.0", + "dependencies": { + "arrify": "^2.0.0", + "extend": "^3.0.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/precise-date": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/precise-date/-/precise-date-4.0.0.tgz", + "integrity": "sha512-1TUx3KdaU3cN7nfCdNf+UVqA/PSX29Cjcox3fZZBtINlRrXVTmUkQnCKv2MbBUbCopbK4olAT1IHl76uZyCiVA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/projectify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz", + "integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/promisify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz", + "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/pubsub": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/@google-cloud/pubsub/-/pubsub-4.7.1.tgz", + "integrity": "sha512-g6RN//1WjEg5pUqAT1xJZDFmhC5nitFVHYyS52THSl7VKubWv+T9cHkeHp/+cc1HDUbkMRjs5hwVSoa0bRR+8Q==", + "license": "Apache-2.0", + "dependencies": { + "@google-cloud/paginator": "^5.0.0", + "@google-cloud/precise-date": "^4.0.0", + "@google-cloud/projectify": "^4.0.0", + "@google-cloud/promisify": "^4.0.0", + "@opentelemetry/api": "~1.9.0", + "@opentelemetry/semantic-conventions": "~1.26.0", + "arrify": "^2.0.0", + "extend": "^3.0.2", + "google-auth-library": "^9.3.0", + "google-gax": "^4.3.3", + "heap-js": "^2.2.0", + "is-stream-ended": "^0.1.4", + "lodash.snakecase": "^4.1.1", + "p-defer": "^3.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/pubsub/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@google-cloud/pubsub/node_modules/gaxios": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", + "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/pubsub/node_modules/gcp-metadata": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", + "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^6.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/pubsub/node_modules/google-auth-library": { + "version": "9.14.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.14.1.tgz", + "integrity": "sha512-Rj+PMjoNFGFTmtItH7gHfbHpGVSb3vmnGK3nwNBqxQF9NoBpttSZI/rc0WiM63ma2uGDQtYEkMHkK9U6937NiA==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^6.1.1", + "gcp-metadata": "^6.1.0", + "gtoken": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/pubsub/node_modules/gtoken": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", + "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", + "license": "MIT", + "dependencies": { + "gaxios": "^6.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/pubsub/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/@googleapis/gmail": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@googleapis/gmail/-/gmail-1.2.0.tgz", @@ -147,6 +297,37 @@ "node": ">=12.0.0" } }, + "node_modules/@grpc/grpc-js": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.11.2.tgz", + "integrity": "sha512-DWp92gDD7/Qkj7r8kus6/HCINeo3yPZWZ3paKgDgsbKbSpoxKg1yvN8xe2Q8uE3zOsPe3bX8FQX2+XValq2yTw==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "license": "Apache-2.0", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.11", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", @@ -180,6 +361,16 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -215,6 +406,24 @@ "node": ">= 8" } }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.26.0.tgz", + "integrity": "sha512-U9PJlOswJPSgQVPI+XEuNLElyFWkb0hAiMg+DExD9V0St03X2lPHGMdxMY/LrVmoukuIpXJ12oyrOtEZ4uXFkw==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, "node_modules/@playwright/test": { "version": "1.41.0", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.0.tgz", @@ -230,6 +439,70 @@ "node": ">=16" } }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, "node_modules/@selderee/plugin-htmlparser2": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", @@ -242,6 +515,15 @@ "url": "https://ko-fi.com/killymxi" } }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, "node_modules/@types/adm-zip": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.5.tgz", @@ -251,6 +533,12 @@ "@types/node": "*" } }, + "node_modules/@types/caseless": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", + "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==", + "license": "MIT" + }, "node_modules/@types/file-saver": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.5.tgz", @@ -274,6 +562,12 @@ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.199.tgz", "integrity": "sha512-Vrjz5N5Ia4SEzWWgIVwnHNEnb1UE1XMkvY5DGXrAeOGE9imk0hgTHh5GyDjLDJi9OTCn9oo9dXH1uToK1VRfrg==" }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", + "license": "MIT" + }, "node_modules/@types/mailparser": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@types/mailparser/-/mailparser-3.4.1.tgz", @@ -292,12 +586,44 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/request": { + "version": "2.48.12", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz", + "integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==", + "license": "MIT", + "dependencies": { + "@types/caseless": "*", + "@types/node": "*", + "@types/tough-cookie": "*", + "form-data": "^2.5.0" + } + }, + "node_modules/@types/request/node_modules/form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, "node_modules/@types/semver": { "version": "7.5.3", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==", "dev": true }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "license": "MIT" + }, "node_modules/@types/uuid": { "version": "9.0.7", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", @@ -492,6 +818,18 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -551,7 +889,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -560,7 +897,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -869,11 +1205,24 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -884,8 +1233,7 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/combined-stream": { "version": "1.0.8", @@ -1121,6 +1469,18 @@ "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, + "node_modules/duplexify": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", + "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.2" + } + }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -1138,6 +1498,12 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, "node_modules/encoding-japanese": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.0.0.tgz", @@ -1146,6 +1512,15 @@ "node": ">=8.10.0" } }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -1250,6 +1625,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -1550,6 +1934,15 @@ "node": ">=0.10.0" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -1810,6 +2203,15 @@ "node": ">=12" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", @@ -1949,6 +2351,113 @@ "node": ">=12" } }, + "node_modules/google-gax": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.4.1.tgz", + "integrity": "sha512-Phyp9fMfA00J3sZbJxbbB4jC55b7DBjE3F6poyL3wKMEBVKA79q6BGuHcTiM28yOzVql0NDbRL8MLLh8Iwk9Dg==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.10.9", + "@grpc/proto-loader": "^0.7.13", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "google-auth-library": "^9.3.0", + "node-fetch": "^2.7.0", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^2.0.2", + "protobufjs": "^7.3.2", + "retry-request": "^7.0.0", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/google-gax/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/google-gax/node_modules/gaxios": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", + "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/google-gax/node_modules/gcp-metadata": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", + "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^6.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/google-gax/node_modules/google-auth-library": { + "version": "9.14.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.14.1.tgz", + "integrity": "sha512-Rj+PMjoNFGFTmtItH7gHfbHpGVSb3vmnGK3nwNBqxQF9NoBpttSZI/rc0WiM63ma2uGDQtYEkMHkK9U6937NiA==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^6.1.1", + "gcp-metadata": "^6.1.0", + "gtoken": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/google-gax/node_modules/gtoken": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", + "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", + "license": "MIT", + "dependencies": { + "gaxios": "^6.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/google-gax/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/google-p12-pem": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-4.0.1.tgz", @@ -2126,6 +2635,15 @@ "he": "bin/he" } }, + "node_modules/heap-js": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/heap-js/-/heap-js-2.5.0.tgz", + "integrity": "sha512-kUGoI3p7u6B41z/dp33G6OaL7J4DRqRYwVmeIlwLClx7yaaAy7hoDExnuejTKtuDwfcatGmddHDEOjf6EyIxtQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/html-to-text": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz", @@ -2159,6 +2677,20 @@ "entities": "^4.4.0" } }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -2243,8 +2775,7 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/internal-slot": { "version": "1.0.5", @@ -2364,6 +2895,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -2460,6 +3000,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-stream-ended": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", + "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==", + "license": "MIT" + }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -2725,12 +3271,30 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", + "license": "MIT" + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "license": "Apache-2.0" + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -2937,6 +3501,15 @@ "node": "*" } }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.12.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", @@ -3022,7 +3595,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "dependencies": { "wrappy": "1" } @@ -3059,6 +3631,15 @@ "node": ">= 0.8.0" } }, + "node_modules/p-defer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-3.0.0.tgz", + "integrity": "sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -3218,6 +3799,42 @@ "node": ">= 0.8.0" } }, + "node_modules/proto3-json-serializer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-2.0.2.tgz", + "integrity": "sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ==", + "license": "Apache-2.0", + "dependencies": { + "protobufjs": "^7.2.5" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/protobufjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -3268,6 +3885,20 @@ } ] }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", @@ -3377,6 +4008,15 @@ "uuid": "bin/uuid" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.6", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", @@ -3403,6 +4043,20 @@ "node": ">=4" } }, + "node_modules/retry-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz", + "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", + "license": "MIT", + "dependencies": { + "@types/request": "^2.48.8", + "extend": "^3.0.2", + "teeny-request": "^9.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -3625,6 +4279,44 @@ "node": ">=0.10.0" } }, + "node_modules/stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "license": "MIT", + "dependencies": { + "stubs": "^3.0.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "license": "MIT" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.trim": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", @@ -3674,7 +4366,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3703,6 +4394,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", + "license": "MIT" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3727,6 +4424,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/teeny-request": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", + "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", + "license": "Apache-2.0", + "dependencies": { + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.9", + "stream-events": "^1.0.5", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -3974,6 +4687,12 @@ "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==" }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", @@ -4062,11 +4781,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/xlsx": { "version": "0.20.1", @@ -4081,11 +4816,47 @@ "node": ">=0.8" } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/playwright-e2e/package.json b/playwright-e2e/package.json index 2c2b3499dc..626515c2d0 100644 --- a/playwright-e2e/package.json +++ b/playwright-e2e/package.json @@ -32,6 +32,7 @@ }, "dependencies": { "@google-cloud/local-auth": "^2.1.1", + "@google-cloud/pubsub": "^4.7.1", "@googleapis/gmail": "^1.1.1", "@types/lodash": "^4.14.191", "@types/node": "^20.11.5", diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index 4fccf8a876..b1e2df5e6c 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -7,10 +7,12 @@ import ParticipantPage from 'dsm/pages/participant-page'; import SequeuncingOrderTab from 'dsm/pages/tablist/sequencing-order-tab'; import Select from 'dss/component/select'; import { test } from 'fixtures/dsm-fixture'; -import { getToday } from 'utils/date-utils'; +import { getDateMonthAbbreviated, getToday } from 'utils/date-utils'; import { studyShortName } from 'utils/test-utils'; const pecgsStudies = [StudyName.OSTEO2]; //Checking OS2 first +const { MERCURY_PUBSUB_TOPIC_NAME } = process.env; + test.describe.serial('Verify that clinical orders can be placed in mercury @dsm @functional', () => { let navigation; let shortID: string; @@ -19,7 +21,9 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm let normalSample: Locator; let tumorSample: Locator; let previousLatestOrderNumberTumor: string; + let newLatestOrderNumberTumor: string; let previousLatestOrderNumberNormal: string; + let newLatestOrderNumberNormal: string; for (const study of pecgsStudies) { test(`${study}: Verify a clinical order can be placed for a participant with Enrolled status`, async ({ page, request }) => { @@ -31,12 +35,13 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm const participantListTable = participantListPage.participantListTable; await test.step('Chose an enrolled participant that will get a clinical order placed', async () => { - shortID = await findParticipantForGermlineSequencing({ + /*shortID = await findParticipantForGermlineSequencing({ enrollmentStatus: DataFilter.ENROLLED, participantList: participantListPage, participantTable: participantListTable, studyName: study - }); + });*/ + shortID = 'P47H2G'; await participantListPage.filterListByShortId(shortID); participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); @@ -71,7 +76,7 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm }); /* NOTE: Need to go from Participant Page -> Participant List -> (refresh) -> Participant Page in order to see the new info */ - await test.step('Use the new Latest Order Number to place the order in mercury', async () => { + await test.step('Verify that the Latest Sequencing Order Date and Latest Order Number have been updated', async () => { await participantPage.backToList(); await participantListPage.filterListByShortId(shortID); await participantListTable.openParticipantPageAt({ position: 0 }); @@ -84,17 +89,21 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm const today = getToday(); const orderDateNormal = await sequencingOrderTab.getColumnDataForSample(normalSample, SequencingOrderColumn.LATEST_SEQUENCING_ORDER_DATE); - expect(orderDateNormal).toBe(today); + expect(orderDateNormal.trim()).toBe(today); const orderDateTumor = await sequencingOrderTab.getColumnDataForSample(tumorSample, SequencingOrderColumn.LATEST_SEQUENCING_ORDER_DATE); - expect(orderDateTumor).toBe(today); + expect(orderDateTumor.trim()).toBe(today); - const newLatestOrderNumberNormal = await sequencingOrderTab.getColumnDataForSample(normalSample, SequencingOrderColumn.LATEST_ORDER_NUMBER); + newLatestOrderNumberNormal = await sequencingOrderTab.getColumnDataForSample(normalSample, SequencingOrderColumn.LATEST_ORDER_NUMBER); expect(newLatestOrderNumberNormal).not.toBe(previousLatestOrderNumberNormal); - const newLatestOrderNumberTumor = await sequencingOrderTab.getColumnDataForSample(tumorSample, SequencingOrderColumn.LATEST_ORDER_NUMBER); + newLatestOrderNumberTumor = await sequencingOrderTab.getColumnDataForSample(tumorSample, SequencingOrderColumn.LATEST_ORDER_NUMBER); expect(newLatestOrderNumberTumor).not.toBe(previousLatestOrderNumberTumor); }); + + await test.step('Place an order in mercury', () => { + const result = createMercuryOrderMessage({ latestOrderNumber: newLatestOrderNumberTumor }); + }); }) test(`${study}: Verify a clinical order can be placed for a participant with Lost-to-FollowUp status`, async ({ page, request }) => { @@ -169,3 +178,24 @@ async function findParticipantForGermlineSequencing(opts: { return shortID; } +function createMercuryOrderMessage(opts: { latestOrderNumber: string, orderStatus?: string }): string { + const { latestOrderNumber, orderStatus = 'Approved' } = opts; + const today = getToday(); + const readableDate = getDateMonthAbbreviated(today); + + const message = ` + { + "status": { + "orderID":"${latestOrderNumber}", + "orderStatus": "${orderStatus}", + "details": "Successfully created order", + "pdoKey": "Made by Playwright on ${readableDate}", + "json": "PDO-123" + } + }`; + + const messageObject = JSON.parse(message); + console.log(`Resulting mercury order message object: ${JSON.stringify(messageObject)}`); + + return 'blank'; +} From 0bbe6cb8afa5224a92d77ed1aeb978c92950965e Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Mon, 9 Sep 2024 10:01:07 -0400 Subject: [PATCH 06/26] ran npm audit fix to fix some vulnerabilities --- playwright-e2e/package-lock.json | 143 +++++++++++++++++++++---------- 1 file changed, 98 insertions(+), 45 deletions(-) diff --git a/playwright-e2e/package-lock.json b/playwright-e2e/package-lock.json index 0bb9767858..2f89888a6f 100644 --- a/playwright-e2e/package-lock.json +++ b/playwright-e2e/package-lock.json @@ -1085,12 +1085,13 @@ "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" }, "node_modules/axios": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", - "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "dev": true, + "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -1147,12 +1148,13 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -2027,10 +2029,11 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2075,9 +2078,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "dev": true, "funding": [ { @@ -2085,6 +2088,7 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -2933,6 +2937,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -3228,27 +3233,50 @@ "integrity": "sha512-l+nePcPbIG1fNlqMzrh68MLkX/gTxk/+vdvAb388Ssi7UuUN31MI44w4Yf33mM3Cm4xDfw48mdf3rkdHszLNew==" }, "node_modules/libmime": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/libmime/-/libmime-5.2.1.tgz", - "integrity": "sha512-A0z9O4+5q+ZTj7QwNe/Juy1KARNb4WaviO4mYeFC4b8dBT2EEqK2pkM+GC8MVnkOjqhl5nYQxRgnPYRRTNmuSQ==", + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-5.3.5.tgz", + "integrity": "sha512-nSlR1yRZ43L3cZCiWEw7ali3jY29Hz9CQQ96Oy+sSspYnIP5N54ucOPHqooBsXzwrX1pwn13VUE05q4WmzfaLg==", + "license": "MIT", "dependencies": { - "encoding-japanese": "2.0.0", + "encoding-japanese": "2.1.0", "iconv-lite": "0.6.3", - "libbase64": "1.2.1", - "libqp": "2.0.1" + "libbase64": "1.3.0", + "libqp": "2.1.0" } }, + "node_modules/libmime/node_modules/encoding-japanese": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.1.0.tgz", + "integrity": "sha512-58XySVxUgVlBikBTbQ8WdDxBDHIdXucB16LO5PBHR8t75D54wQrNo4cg+58+R1CtJfKnsVsvt9XlteRaR8xw1w==", + "license": "MIT", + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/libmime/node_modules/libbase64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.3.0.tgz", + "integrity": "sha512-GgOXd0Eo6phYgh0DJtjQ2tO8dc0IVINtZJeARPeiIJqge+HdsWSuaDTe8ztQ7j/cONByDZ3zeB325AHiv5O0dg==", + "license": "MIT" + }, + "node_modules/libmime/node_modules/libqp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-2.1.0.tgz", + "integrity": "sha512-O6O6/fsG5jiUVbvdgT7YX3xY3uIadR6wEZ7+vy9u7PKHAlSEB6blvC1o5pHBjgsi95Uo0aiBBdkyFecj6jtb7A==", + "license": "MIT" + }, "node_modules/libqp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/libqp/-/libqp-2.0.1.tgz", "integrity": "sha512-Ka0eC5LkF3IPNQHJmYBWljJsw0UvM6j+QdKRbWyCdTmYwvIDE6a7bCm0UkTAL/K+3KXK5qXT/ClcInU01OpdLg==" }, "node_modules/linkify-it": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", - "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "license": "MIT", "dependencies": { - "uc.micro": "^1.0.1" + "uc.micro": "^2.0.0" } }, "node_modules/locate-path": { @@ -3307,19 +3335,30 @@ } }, "node_modules/mailparser": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/mailparser/-/mailparser-3.6.5.tgz", - "integrity": "sha512-nteTpF0Khm5JLOnt4sigmzNdUH/6mO7PZ4KEnvxf4mckyXYFFhrtAWZzbq/V5aQMH+049gA7ZjfLdh+QiX2Uqg==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/mailparser/-/mailparser-3.7.1.tgz", + "integrity": "sha512-RCnBhy5q8XtB3mXzxcAfT1huNqN93HTYYyL6XawlIKycfxM/rXPg9tXoZ7D46+SgCS1zxKzw+BayDQSvncSTTw==", + "license": "MIT", "dependencies": { - "encoding-japanese": "2.0.0", + "encoding-japanese": "2.1.0", "he": "1.2.0", "html-to-text": "9.0.5", "iconv-lite": "0.6.3", - "libmime": "5.2.1", - "linkify-it": "4.0.1", + "libmime": "5.3.5", + "linkify-it": "5.0.0", "mailsplit": "5.4.0", - "nodemailer": "6.9.3", - "tlds": "1.240.0" + "nodemailer": "6.9.13", + "punycode.js": "2.3.1", + "tlds": "1.252.0" + } + }, + "node_modules/mailparser/node_modules/encoding-japanese": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.1.0.tgz", + "integrity": "sha512-58XySVxUgVlBikBTbQ8WdDxBDHIdXucB16LO5PBHR8t75D54wQrNo4cg+58+R1CtJfKnsVsvt9XlteRaR8xw1w==", + "license": "MIT", + "engines": { + "node": ">=8.10.0" } }, "node_modules/mailsplit": { @@ -3353,12 +3392,13 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -3486,9 +3526,10 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/nodemailer": { - "version": "6.9.3", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.3.tgz", - "integrity": "sha512-fy9v3NgTzBngrMFkDsKEj0r02U7jm6XfC3b52eoNV+GCrGj+s8pt5OqhiJdWKuw51zCTdiNR/IUD1z33LIIGpg==", + "version": "6.9.13", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.13.tgz", + "integrity": "sha512-7o38Yogx6krdoBf3jCAqnIN4oSQFx+fMa0I7dK1D+me9kBxx12D+/33wSb+fhOCtIxvYJ+4x4IMEhmhCKfAiOA==", + "license": "MIT-0", "engines": { "node": ">=6.0.0" } @@ -3851,6 +3892,15 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.11.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", @@ -4447,9 +4497,10 @@ "dev": true }, "node_modules/tlds": { - "version": "1.240.0", - "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.240.0.tgz", - "integrity": "sha512-1OYJQenswGZSOdRw7Bql5Qu7uf75b+F3HFBXbqnG/ifHa0fev1XcG+3pJf3pA/KC6RtHQzfKgIf1vkMlMG7mtQ==", + "version": "1.252.0", + "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.252.0.tgz", + "integrity": "sha512-GA16+8HXvqtfEnw/DTcwB0UU354QE1n3+wh08oFjr6Znl7ZLAeUgYzCcK+/CCrOyE0vnHR8/pu3XXG3vDijXpQ==", + "license": "MIT", "bin": { "tlds": "bin.js" } @@ -4459,6 +4510,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -4642,9 +4694,10 @@ } }, "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" }, "node_modules/unbox-primitive": { "version": "1.0.2", From a106f63d3b56f5fd419bcd93c9c87c013acb0faa Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Tue, 10 Sep 2024 15:56:32 -0400 Subject: [PATCH 07/26] placed mercury order and checking for the resulting order in Clinical Order page --- playwright-e2e/config/.env.dev | 2 + playwright-e2e/config/.env.test | 2 + playwright-e2e/dsm/enums.ts | 10 + .../dsm/pages/clinical-orders-page.ts | 14 ++ .../dsm/pages/tablist/sequencing-order-tab.ts | 17 +- .../place-clinical-order-in-mercury.spec.ts | 182 ++++++++++++++---- playwright-e2e/utils/date-utils.ts | 4 + playwright-e2e/utils/test-utils.ts | 14 ++ 8 files changed, 193 insertions(+), 52 deletions(-) diff --git a/playwright-e2e/config/.env.dev b/playwright-e2e/config/.env.dev index 680b13f9aa..8012bdeea5 100644 --- a/playwright-e2e/config/.env.dev +++ b/playwright-e2e/config/.env.dev @@ -4,6 +4,8 @@ SITE_PASSWORD= # PEPPER API_BASE_URL=https://pepper-dev.datadonationplatform.org +MERCURY_PUBSUB_TOPIC_NAME = +MERCURY_PUBSUB_PROJECT_ID = # ATCP ATCP_BASE_URL=https://atcp.dev.datadonationplatform.org diff --git a/playwright-e2e/config/.env.test b/playwright-e2e/config/.env.test index 0406341ab7..e507f3e5a8 100644 --- a/playwright-e2e/config/.env.test +++ b/playwright-e2e/config/.env.test @@ -4,6 +4,8 @@ SITE_PASSWORD= # PEPPER API_BASE_URL=https://pepper-test.datadonationplatform.org +MERCURY_PUBSUB_TOPIC_NAME = +MERCURY_PUBSUB_PROJECT_ID = # ATCP ATCP_BASE_URL=https://atcp.test.datadonationplatform.org diff --git a/playwright-e2e/dsm/enums.ts b/playwright-e2e/dsm/enums.ts index d5ce1727a9..4abe2b6ab8 100644 --- a/playwright-e2e/dsm/enums.ts +++ b/playwright-e2e/dsm/enums.ts @@ -795,3 +795,13 @@ export enum SequencingOrderColumn { LATEST_ORDER_NUMBER = 'Latest Order Number', LATEST_PDO_NUMBER = 'Latest PDO Number', } + +export enum ClinicalOrdersColumn { + SHORT_ID = 'Short ID', + SAMPLE_TYPE = 'Sample Type', + SAMPLE = 'Sample', + ORDER_NUMBER = 'Order Number', + ORDER_DATE = 'Order Date', + STATUS = 'Status', + STATUS_DETAIL = 'Status Detail' +} diff --git a/playwright-e2e/dsm/pages/clinical-orders-page.ts b/playwright-e2e/dsm/pages/clinical-orders-page.ts index d28eddeb31..5ee6749d5a 100644 --- a/playwright-e2e/dsm/pages/clinical-orders-page.ts +++ b/playwright-e2e/dsm/pages/clinical-orders-page.ts @@ -2,20 +2,30 @@ import { expect, Locator, Page } from '@playwright/test'; export default class ClinicalOrdersPage { protected PAGE_TITLE = 'Clinical Orders'; + private readonly DOWNLOAD_INFO = 'Download list includes additional fields "Order Message & Status Message"'; constructor(private readonly page: Page) {} public async waitForReady(): Promise { const downloadListButton = this.getDownloadListButton(); const reloadListButton = this.getReloadListButton(); + const downloadHelpText = this.getDownloadHelpText(); const clinicalOrdersTable = await this.getClinicalOrdersTable(); const amountOfClinicalOrders = clinicalOrdersTable.length; await expect(downloadListButton, 'Clinical Orders Page -> Download List button is not visible').toBeVisible(); await expect(reloadListButton, 'Clinical Orders Page -> Reload List button is not visible').toBeVisible(); + await expect(downloadHelpText, `Clinical Orders Page -> help text: "${this.DOWNLOAD_INFO}" is not visible`).toBeVisible(); expect.soft(amountOfClinicalOrders).toBeGreaterThanOrEqual(1); //Just in case there's times where there aren't clinical orders } + public getClinicalOrderRow(opts: { sampleType: 'Normal' | 'Tumor', orderNumber: string }): Locator { + const { sampleType, orderNumber } = opts; + return this.page.locator( + `//app-clinical-page//td[contains(text(), '${orderNumber}')]/preceding-sibling::td[contains(text(), '${sampleType}')]/parent::tr` + ); + } + /* Locators */ private getDownloadListButton(): Locator { return this.page.getByRole('button', { name: 'Download list' }); @@ -28,4 +38,8 @@ export default class ClinicalOrdersPage { private async getClinicalOrdersTable(): Promise { return this.page.locator('//table//tbody//tr').all(); } + + private getDownloadHelpText(): Locator { + return this.page.getByText(this.DOWNLOAD_INFO); + } } diff --git a/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts b/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts index 5d6b611d19..6444b6084b 100644 --- a/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts +++ b/playwright-e2e/dsm/pages/tablist/sequencing-order-tab.ts @@ -2,6 +2,7 @@ import { Locator, Page, expect } from '@playwright/test'; import { getDate, getDateinISOFormat, getToday } from 'utils/date-utils'; import TabBase from './tab-base'; import { SequencingOrderColumn, Tab } from 'dsm/enums'; +import { getColumnHeaderIndex } from 'utils/test-utils'; export default class SequeuncingOrderTab extends TabBase { private readonly SAMPLE_ROW_XPATH = '//app-sequencing-order//tr'; @@ -125,15 +126,8 @@ export default class SequeuncingOrderTab extends TabBase { await checkbox.click(); } - public async getColumnDataForSample(sample: Locator, columnName: SequencingOrderColumn): Promise { - const columnIndex = await this.getColumnHeaderIndex(columnName); - const cellContent = await sample.locator(`//td[${columnIndex}]`).textContent() as string; - console.log(`Sequencing order tab - sample data under ${columnName} column: ${cellContent}`); - return cellContent; - } - public async fillCollectionDateIfNeeded(normalSample: Locator): Promise { - const collectionDateColumnIndex = await this.getColumnHeaderIndex(SequencingOrderColumn.COLLECTION_DATE); + const collectionDateColumnIndex = await getColumnHeaderIndex(SequencingOrderColumn.COLLECTION_DATE, this.page); const unfilledCollectionDateColumn = normalSample.locator(`//td[${collectionDateColumnIndex}]/app-field-datepicker//input`); if (await unfilledCollectionDateColumn.isVisible()) { await normalSample.locator(`//td[${collectionDateColumnIndex}]//button[normalize-space(text())='Today']`).click(); @@ -165,11 +159,4 @@ export default class SequeuncingOrderTab extends TabBase { expect(amountOfSamples, 'No tumor samples were available in the Sequencing tab').toBeGreaterThanOrEqual(1); return samples; } - - private async getColumnHeaderIndex(columnName: SequencingOrderColumn): Promise { - const precedingColumns = this.page.locator(`//th[normalize-space(text())='${columnName}']/preceding-sibling::th`); - const columnIndex = await precedingColumns.count() + 1; - console.log(`${columnName} is the ${columnIndex}th column`); - return columnIndex; - } } diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index b1e2df5e6c..294f8ac5f1 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -1,29 +1,38 @@ import { expect, Locator } from '@playwright/test'; import { ParticipantListTable } from 'dsm/component/tables/participant-list-table'; -import { CustomizeView, DataFilter, Label, SequencingOrderColumn, Tab } from 'dsm/enums'; -import { Navigation, Study, StudyName } from 'dsm/navigation'; +import { ClinicalOrdersColumn, CustomizeView, DataFilter, Label, SequencingOrderColumn, Tab } from 'dsm/enums'; +import { Navigation, Samples, Study, StudyName } from 'dsm/navigation'; import ParticipantListPage from 'dsm/pages/participant-list-page'; import ParticipantPage from 'dsm/pages/participant-page'; import SequeuncingOrderTab from 'dsm/pages/tablist/sequencing-order-tab'; import Select from 'dss/component/select'; import { test } from 'fixtures/dsm-fixture'; -import { getDateMonthAbbreviated, getToday } from 'utils/date-utils'; -import { studyShortName } from 'utils/test-utils'; +import { getDateEasternTimeZone, getDateMonthAbbreviated, getToday, getTodayInEastCoastDateTimeFormat, toLocalTime } from 'utils/date-utils'; +import { getColumnDataForRow, studyShortName } from 'utils/test-utils'; +import { PubSub } from '@google-cloud/pubsub'; +import ClinicalOrdersPage from 'dsm/pages/clinical-orders-page'; const pecgsStudies = [StudyName.OSTEO2]; //Checking OS2 first -const { MERCURY_PUBSUB_TOPIC_NAME } = process.env; +const MERCURY_PUBSUB_TOPIC_NAME = process.env.MERCURY_PUBSUB_TOPIC_NAME as string; +const MERCURY_PUBSUB_PROJECT_ID = process.env.MERCURY_PUBSUB_PROJECT_ID as string; test.describe.serial('Verify that clinical orders can be placed in mercury @dsm @functional', () => { - let navigation; + const approvedOrderStatus = 'Approved'; + const orderStatusDetail = 'Successfully created order via Playwright'; + let navigation: Navigation; let shortID: string; let participantPage: ParticipantPage; let sequencingOrderTab: SequeuncingOrderTab; let normalSample: Locator; let tumorSample: Locator; + let sampleNameNormal: string; + let sampleNameTumor: string; let previousLatestOrderNumberTumor: string; - let newLatestOrderNumberTumor: string; + let latestOrderNumberTumor: string; let previousLatestOrderNumberNormal: string; - let newLatestOrderNumberNormal: string; + let latestOrderNumberNormal: string; + let orderDateNormal: string; + let orderDateTumor: string; for (const study of pecgsStudies) { test(`${study}: Verify a clinical order can be placed for a participant with Enrolled status`, async ({ page, request }) => { @@ -35,13 +44,12 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm const participantListTable = participantListPage.participantListTable; await test.step('Chose an enrolled participant that will get a clinical order placed', async () => { - /*shortID = await findParticipantForGermlineSequencing({ + shortID = await findParticipantForGermlineSequencing({ enrollmentStatus: DataFilter.ENROLLED, participantList: participantListPage, participantTable: participantListTable, studyName: study - });*/ - shortID = 'P47H2G'; + }); await participantListPage.filterListByShortId(shortID); participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); @@ -57,15 +65,15 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm await test.step('Place a clinical order using the Sequencing Order tab', async () => { normalSample = await sequencingOrderTab.getFirstAvailableNormalSample(); await sequencingOrderTab.selectSampleCheckbox(normalSample); - //console.log(`normal xpath: ${normalSample}`); + sampleNameNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.SAMPLE, page); await sequencingOrderTab.fillCollectionDateIfNeeded(normalSample); - previousLatestOrderNumberNormal = await sequencingOrderTab.getColumnDataForSample(normalSample, SequencingOrderColumn.LATEST_ORDER_NUMBER); + previousLatestOrderNumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); console.log(`previous Latest Order Number for normal sample: ${previousLatestOrderNumberNormal}`); tumorSample = await sequencingOrderTab.getFirstAvailableTumorSample(); await sequencingOrderTab.selectSampleCheckbox(tumorSample); - //console.log(`tumor xpath: ${tumorSample}`); - previousLatestOrderNumberTumor = await sequencingOrderTab.getColumnDataForSample(tumorSample, SequencingOrderColumn.LATEST_ORDER_NUMBER); + sampleNameTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.SAMPLE, page); + previousLatestOrderNumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); console.log(`previous Latest Order Number for tumor sample: ${previousLatestOrderNumberTumor}`); await sequencingOrderTab.assertPlaceOrderButtonDisplayed(); @@ -88,32 +96,113 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm //Verify that Latest Sequencing Order Date is the current date and Latest Order Number has received new input const today = getToday(); - const orderDateNormal = await sequencingOrderTab.getColumnDataForSample(normalSample, SequencingOrderColumn.LATEST_SEQUENCING_ORDER_DATE); + orderDateNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_SEQUENCING_ORDER_DATE, page); expect(orderDateNormal.trim()).toBe(today); - const orderDateTumor = await sequencingOrderTab.getColumnDataForSample(tumorSample, SequencingOrderColumn.LATEST_SEQUENCING_ORDER_DATE); + orderDateTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_SEQUENCING_ORDER_DATE, page); expect(orderDateTumor.trim()).toBe(today); - newLatestOrderNumberNormal = await sequencingOrderTab.getColumnDataForSample(normalSample, SequencingOrderColumn.LATEST_ORDER_NUMBER); - expect(newLatestOrderNumberNormal).not.toBe(previousLatestOrderNumberNormal); + latestOrderNumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); + expect(latestOrderNumberNormal).not.toBe(previousLatestOrderNumberNormal); - newLatestOrderNumberTumor = await sequencingOrderTab.getColumnDataForSample(tumorSample, SequencingOrderColumn.LATEST_ORDER_NUMBER); - expect(newLatestOrderNumberTumor).not.toBe(previousLatestOrderNumberTumor); + latestOrderNumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); + expect(latestOrderNumberTumor).not.toBe(previousLatestOrderNumberTumor); }); - await test.step('Place an order in mercury', () => { - const result = createMercuryOrderMessage({ latestOrderNumber: newLatestOrderNumberTumor }); + await test.step('Place an order in mercury', async () => { + const message = createMercuryOrderMessage({ + latestOrderNumber: latestOrderNumberTumor, + orderStatus: approvedOrderStatus, + orderDetails: orderStatusDetail + }); + await placeMercuryOrder(MERCURY_PUBSUB_TOPIC_NAME, message); + }); + + await test.step('Verify that the mercury order was successfully placed', async () => { + //Check that Latest Order Status, Latest PDO Number are not empty for both Normal and Tumor samples - tab needs info refreshed in order to see changes + await participantPage.backToList(); + await participantListPage.filterListByShortId(shortID); + participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); + await participantPage.waitForReady(); + + await participantPage.tablist(Tab.SEQUENCING_ORDER).isVisible(); + await participantPage.tablist(Tab.SEQUENCING_ORDER).click(); + await sequencingOrderTab.waitForReady(); + + /* Checking the Normal sample's info */ + const latestOrderStatusNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); + expect(latestOrderStatusNormal).toBe(approvedOrderStatus); + const latestPDONumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); + expect(latestPDONumberNormal).toContain(`Made-by-Playwright-on`); + + /* Checking the Tumor sample's info */ + const latestOrderStatusTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); + expect(latestOrderStatusTumor).toBe(approvedOrderStatus); + const latestPDONumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); + expect(latestPDONumberTumor).toContain(`Made-by-Playwright-on`); + }); + + await test.step('Verify that the mercury order can be seen in Samples -> Clinical Orders', async () => { + //Check that info of the newest clinical order can be seen in Clinical Orders page + const clinicalOrderPage = await navigation.selectFromSamples(Samples.CLINICAL_ORDERS); + await clinicalOrderPage.waitForReady(); + + const clinicalOrderNormal = clinicalOrderPage.getClinicalOrderRow({ sampleType: 'Normal', orderNumber: latestOrderNumberNormal }); + const clinicalOrderTumor = clinicalOrderPage.getClinicalOrderRow({ sampleType: 'Tumor', orderNumber: latestOrderNumberTumor }); + + // Check that each sample's info is present: Short ID, Sample Type, Sample, Order Number, Order Date, Status, Status Detail + /* Normal Sample */ + const normalShortID = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.SHORT_ID, page); + expect(normalShortID).toBe(shortID); + + const normalSampleType = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.SAMPLE_TYPE, page); + expect(normalSampleType).toBe('Normal'); + + const normalSampleName = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.SAMPLE, page); + expect(normalSampleName).toBe(sampleNameNormal); + + const normalOrderNumber = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.ORDER_NUMBER, page); + expect(normalOrderNumber).toBe(latestOrderNumberNormal); + + const normalOrderDate = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.ORDER_DATE, page); + expect(normalOrderDate).toBe(orderDateNormal); + + const normalOrderStatus = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.STATUS, page); + expect(normalOrderStatus).toBe(approvedOrderStatus); + + const normalStatusDetail = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.STATUS_DETAIL, page); + expect(normalStatusDetail).toBe(orderStatusDetail); + + /* Tumor Sample */ + const tumorShortID = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.SHORT_ID, page); + expect(tumorShortID).toBe(shortID); + + const tumorSampleType = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.SAMPLE_TYPE, page); + expect(tumorSampleType).toBe('Tumor'); + + const tumorSampleName = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.SAMPLE, page); + expect(tumorSampleName).toBe(sampleNameNormal); + + const tumorOrderNumber = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.ORDER_NUMBER, page); + expect(tumorOrderNumber).toBe(latestOrderNumberNormal); + + const tumorOrderDate = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.ORDER_DATE, page); + expect(tumorOrderDate).toBe(orderDateNormal); + + const tumorOrderStatus = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.STATUS, page); + expect(tumorOrderStatus).toBe(approvedOrderStatus); + + const tumorStatusDetail = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.STATUS_DETAIL, page); + expect(tumorStatusDetail).toBe(orderStatusDetail); }); }) test(`${study}: Verify a clinical order can be placed for a participant with Lost-to-FollowUp status`, async ({ page, request }) => { - navigation = new Navigation(page, request); - await new Select(page, { label: 'Select study' }).selectOption(study); - - const participantListPage = await navigation.selectFromStudy(Study.PARTICIPANT_LIST); - await participantListPage.waitForReady(); + //stuff here + }) - const participantListTable = participantListPage.participantListTable; + test(`${study}: Verify a clinical order can be placed for a participant located in U.S. territory`, async ({ page, request }) => { + //stuff here }) } }) @@ -178,24 +267,43 @@ async function findParticipantForGermlineSequencing(opts: { return shortID; } -function createMercuryOrderMessage(opts: { latestOrderNumber: string, orderStatus?: string }): string { - const { latestOrderNumber, orderStatus = 'Approved' } = opts; - const today = getToday(); - const readableDate = getDateMonthAbbreviated(today); +function createMercuryOrderMessage(opts: { + latestOrderNumber: string, + orderStatus?: string, + orderDetails?: string +}): string { + const { latestOrderNumber, orderStatus = 'Approved', orderDetails = 'Successfully created order' } = opts; + const readableDate = getTodayInEastCoastDateTimeFormat(); const message = ` { "status": { "orderID":"${latestOrderNumber}", "orderStatus": "${orderStatus}", - "details": "Successfully created order", - "pdoKey": "Made by Playwright on ${readableDate}", + "details": "${orderDetails}", + "pdoKey": "Made-by-Playwright-on ${readableDate}", "json": "PDO-123" } }`; const messageObject = JSON.parse(message); - console.log(`Resulting mercury order message object: ${JSON.stringify(messageObject)}`); + console.log(`Resulting pubsub message is:\n ${JSON.stringify(messageObject)}`); + return JSON.stringify(messageObject); +} - return 'blank'; +async function placeMercuryOrder(topicNameOrID: string, messsage: string): Promise { + const pubsubClient = new PubSub({projectId: MERCURY_PUBSUB_PROJECT_ID}); + pubsubClient.getTopics + const dataBuffer = Buffer.from(messsage); + console.log(`Topic name or id: ${topicNameOrID}`); + + try { + const messageID = await pubsubClient + .topic(topicNameOrID) + .publishMessage({ data: dataBuffer }); + console.log(`Message ${messageID} was published`); + } catch (error) { + console.log(`Received error while publishing: ${(error as Error).message}`); + process.exitCode = 1; + } } diff --git a/playwright-e2e/utils/date-utils.ts b/playwright-e2e/utils/date-utils.ts index 412c15a614..28827d8881 100644 --- a/playwright-e2e/utils/date-utils.ts +++ b/playwright-e2e/utils/date-utils.ts @@ -149,3 +149,7 @@ export const calculateAge = (month: string, day: string, year: string): number = return resultAge; }; + +export const getTodayInEastCoastDateTimeFormat = (): string => { + return new Date().toLocaleString('en-US', { timeZone: 'America/New_York' }); +} diff --git a/playwright-e2e/utils/test-utils.ts b/playwright-e2e/utils/test-utils.ts index 89ba0c1b21..66121ffef1 100644 --- a/playwright-e2e/utils/test-utils.ts +++ b/playwright-e2e/utils/test-utils.ts @@ -367,3 +367,17 @@ export function totalNumberOfOccurences(opts: { arrayToSearch: string[], wordToS } return numberOfOccurrences; } + +export async function getColumnHeaderIndex(columnName: string, page: Page): Promise { + const precedingColumns = page.locator(`//th[normalize-space(text())='${columnName}']/preceding-sibling::th`); + const columnIndex = await precedingColumns.count() + 1; + console.log(`${columnName} is the ${columnIndex}th column`); + return columnIndex; +} + +export async function getColumnDataForRow(row: Locator, columnName: string, page: Page): Promise { + const columnIndex = await getColumnHeaderIndex(columnName, page); + const cellContent = await row.locator(`//td[${columnIndex}]`).textContent() as string; + console.log(`Data under ${columnName} column: ${cellContent}`); + return cellContent; +} From e03e40f80884584d410c6b6ab9e789c4f8e5a257 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Tue, 10 Sep 2024 16:07:30 -0400 Subject: [PATCH 08/26] small fixes --- .../clinical-orders/place-clinical-order-in-mercury.spec.ts | 6 +++--- playwright-e2e/utils/test-utils.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index 294f8ac5f1..0c932be6a7 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -181,13 +181,13 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm expect(tumorSampleType).toBe('Tumor'); const tumorSampleName = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.SAMPLE, page); - expect(tumorSampleName).toBe(sampleNameNormal); + expect(tumorSampleName).toBe(sampleNameTumor); const tumorOrderNumber = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.ORDER_NUMBER, page); - expect(tumorOrderNumber).toBe(latestOrderNumberNormal); + expect(tumorOrderNumber).toBe(latestOrderNumberTumor); const tumorOrderDate = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.ORDER_DATE, page); - expect(tumorOrderDate).toBe(orderDateNormal); + expect(tumorOrderDate).toBe(orderDateTumor); const tumorOrderStatus = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.STATUS, page); expect(tumorOrderStatus).toBe(approvedOrderStatus); diff --git a/playwright-e2e/utils/test-utils.ts b/playwright-e2e/utils/test-utils.ts index 66121ffef1..60363d1b42 100644 --- a/playwright-e2e/utils/test-utils.ts +++ b/playwright-e2e/utils/test-utils.ts @@ -379,5 +379,5 @@ export async function getColumnDataForRow(row: Locator, columnName: string, page const columnIndex = await getColumnHeaderIndex(columnName, page); const cellContent = await row.locator(`//td[${columnIndex}]`).textContent() as string; console.log(`Data under ${columnName} column: ${cellContent}`); - return cellContent; + return cellContent.trim(); } From b8c5a2cd0b4092fe33834f0339c98691eec3bf59 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Tue, 10 Sep 2024 16:10:42 -0400 Subject: [PATCH 09/26] took out topic line --- .../dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index 0c932be6a7..fbb645249e 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -293,7 +293,6 @@ function createMercuryOrderMessage(opts: { async function placeMercuryOrder(topicNameOrID: string, messsage: string): Promise { const pubsubClient = new PubSub({projectId: MERCURY_PUBSUB_PROJECT_ID}); - pubsubClient.getTopics const dataBuffer = Buffer.from(messsage); console.log(`Topic name or id: ${topicNameOrID}`); From 36b7572f7f4f5b286b26a35728eecdef3aea64f0 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Tue, 10 Sep 2024 16:51:55 -0400 Subject: [PATCH 10/26] test for putting in mercury order for lost to followup pediatric ptp done --- .../place-clinical-order-in-mercury.spec.ts | 161 +++++++++++++++++- 1 file changed, 160 insertions(+), 1 deletion(-) diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index fbb645249e..3feeff4963 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -198,7 +198,166 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm }) test(`${study}: Verify a clinical order can be placed for a participant with Lost-to-FollowUp status`, async ({ page, request }) => { - //stuff here + navigation = new Navigation(page, request); + await new Select(page, { label: 'Select study' }).selectOption(study); + + const participantListPage = await navigation.selectFromStudy(Study.PARTICIPANT_LIST); + await participantListPage.waitForReady(); + const participantListTable = participantListPage.participantListTable; + + await test.step('Chose an enrolled participant that will get a clinical order placed', async () => { + shortID = await findParticipantForGermlineSequencing({ + enrollmentStatus: DataFilter.LOST_TO_FOLLOWUP, + participantList: participantListPage, + participantTable: participantListTable, + studyName: study, + usePediatricParticipant: true + }); + + await participantListPage.filterListByShortId(shortID); + participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); + await participantPage.waitForReady(); + }); + + await test.step('Make sure that the Sequencing Order tab is visible', async () => { + await participantPage.tablist(Tab.SEQUENCING_ORDER).isVisible(); + sequencingOrderTab = await participantPage.tablist(Tab.SEQUENCING_ORDER).click(); + await sequencingOrderTab.waitForReady(); + }); + + await test.step('Place a clinical order using the Sequencing Order tab', async () => { + normalSample = await sequencingOrderTab.getFirstAvailableNormalSample(); + await sequencingOrderTab.selectSampleCheckbox(normalSample); + sampleNameNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.SAMPLE, page); + await sequencingOrderTab.fillCollectionDateIfNeeded(normalSample); + previousLatestOrderNumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); + console.log(`previous Latest Order Number for normal sample: ${previousLatestOrderNumberNormal}`); + + tumorSample = await sequencingOrderTab.getFirstAvailableTumorSample(); + await sequencingOrderTab.selectSampleCheckbox(tumorSample); + sampleNameTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.SAMPLE, page); + previousLatestOrderNumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); + console.log(`previous Latest Order Number for tumor sample: ${previousLatestOrderNumberTumor}`); + + await sequencingOrderTab.assertPlaceOrderButtonDisplayed(); + await sequencingOrderTab.placeOrder(); + + await sequencingOrderTab.assertClinicalOrderModalDisplayed(); + await sequencingOrderTab.submitClinicalOrder(); + }); + + /* NOTE: Need to go from Participant Page -> Participant List -> (refresh) -> Participant Page in order to see the new info */ + await test.step('Verify that the Latest Sequencing Order Date and Latest Order Number have been updated', async () => { + await participantPage.backToList(); + await participantListPage.filterListByShortId(shortID); + await participantListTable.openParticipantPageAt({ position: 0 }); + + await participantPage.waitForReady(); + sequencingOrderTab = await participantPage.tablist(Tab.SEQUENCING_ORDER).click(); + await sequencingOrderTab.waitForReady(); + + //Verify that Latest Sequencing Order Date is the current date and Latest Order Number has received new input + const today = getToday(); + + orderDateNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_SEQUENCING_ORDER_DATE, page); + expect(orderDateNormal.trim()).toBe(today); + + orderDateTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_SEQUENCING_ORDER_DATE, page); + expect(orderDateTumor.trim()).toBe(today); + + latestOrderNumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); + expect(latestOrderNumberNormal).not.toBe(previousLatestOrderNumberNormal); + + latestOrderNumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); + expect(latestOrderNumberTumor).not.toBe(previousLatestOrderNumberTumor); + }); + + await test.step('Place an order in mercury', async () => { + const message = createMercuryOrderMessage({ + latestOrderNumber: latestOrderNumberTumor, + orderStatus: approvedOrderStatus, + orderDetails: orderStatusDetail + }); + await placeMercuryOrder(MERCURY_PUBSUB_TOPIC_NAME, message); + }); + + await test.step('Verify that the mercury order was successfully placed', async () => { + //Check that Latest Order Status, Latest PDO Number are not empty for both Normal and Tumor samples - tab needs info refreshed in order to see changes + await participantPage.backToList(); + await participantListPage.filterListByShortId(shortID); + participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); + await participantPage.waitForReady(); + + await participantPage.tablist(Tab.SEQUENCING_ORDER).isVisible(); + await participantPage.tablist(Tab.SEQUENCING_ORDER).click(); + await sequencingOrderTab.waitForReady(); + + /* Checking the Normal sample's info */ + const latestOrderStatusNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); + expect(latestOrderStatusNormal).toBe(approvedOrderStatus); + const latestPDONumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); + expect(latestPDONumberNormal).toContain(`Made-by-Playwright-on`); + + /* Checking the Tumor sample's info */ + const latestOrderStatusTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); + expect(latestOrderStatusTumor).toBe(approvedOrderStatus); + const latestPDONumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); + expect(latestPDONumberTumor).toContain(`Made-by-Playwright-on`); + }); + + await test.step('Verify that the mercury order can be seen in Samples -> Clinical Orders', async () => { + //Check that info of the newest clinical order can be seen in Clinical Orders page + const clinicalOrderPage = await navigation.selectFromSamples(Samples.CLINICAL_ORDERS); + await clinicalOrderPage.waitForReady(); + + const clinicalOrderNormal = clinicalOrderPage.getClinicalOrderRow({ sampleType: 'Normal', orderNumber: latestOrderNumberNormal }); + const clinicalOrderTumor = clinicalOrderPage.getClinicalOrderRow({ sampleType: 'Tumor', orderNumber: latestOrderNumberTumor }); + + // Check that each sample's info is present: Short ID, Sample Type, Sample, Order Number, Order Date, Status, Status Detail + /* Normal Sample */ + const normalShortID = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.SHORT_ID, page); + expect(normalShortID).toBe(shortID); + + const normalSampleType = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.SAMPLE_TYPE, page); + expect(normalSampleType).toBe('Normal'); + + const normalSampleName = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.SAMPLE, page); + expect(normalSampleName).toBe(sampleNameNormal); + + const normalOrderNumber = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.ORDER_NUMBER, page); + expect(normalOrderNumber).toBe(latestOrderNumberNormal); + + const normalOrderDate = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.ORDER_DATE, page); + expect(normalOrderDate).toBe(orderDateNormal); + + const normalOrderStatus = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.STATUS, page); + expect(normalOrderStatus).toBe(approvedOrderStatus); + + const normalStatusDetail = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.STATUS_DETAIL, page); + expect(normalStatusDetail).toBe(orderStatusDetail); + + /* Tumor Sample */ + const tumorShortID = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.SHORT_ID, page); + expect(tumorShortID).toBe(shortID); + + const tumorSampleType = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.SAMPLE_TYPE, page); + expect(tumorSampleType).toBe('Tumor'); + + const tumorSampleName = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.SAMPLE, page); + expect(tumorSampleName).toBe(sampleNameTumor); + + const tumorOrderNumber = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.ORDER_NUMBER, page); + expect(tumorOrderNumber).toBe(latestOrderNumberTumor); + + const tumorOrderDate = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.ORDER_DATE, page); + expect(tumorOrderDate).toBe(orderDateTumor); + + const tumorOrderStatus = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.STATUS, page); + expect(tumorOrderStatus).toBe(approvedOrderStatus); + + const tumorStatusDetail = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.STATUS_DETAIL, page); + expect(tumorStatusDetail).toBe(orderStatusDetail); + }); }) test(`${study}: Verify a clinical order can be placed for a participant located in U.S. territory`, async ({ page, request }) => { From 103ac2385a410372482e888cffa7c0b6ccf6cec7 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Tue, 10 Sep 2024 16:58:37 -0400 Subject: [PATCH 11/26] inputting test case for a lost to followup ptp whose residence is in US territory --- .../place-clinical-order-in-mercury.spec.ts | 164 +++++++++++++++++- 1 file changed, 162 insertions(+), 2 deletions(-) diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index 3feeff4963..ed49fde875 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -360,8 +360,168 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm }); }) - test(`${study}: Verify a clinical order can be placed for a participant located in U.S. territory`, async ({ page, request }) => { - //stuff here + test(`${study}: Verify a clinical order can be placed for a lost to follwup participant located in U.S. territory`, async ({ page, request }) => { + navigation = new Navigation(page, request); + await new Select(page, { label: 'Select study' }).selectOption(study); + + const participantListPage = await navigation.selectFromStudy(Study.PARTICIPANT_LIST); + await participantListPage.waitForReady(); + const participantListTable = participantListPage.participantListTable; + + await test.step('Chose an enrolled participant that will get a clinical order placed', async () => { + shortID = await findParticipantForGermlineSequencing({ + enrollmentStatus: DataFilter.LOST_TO_FOLLOWUP, + participantList: participantListPage, + participantTable: participantListTable, + studyName: study, + usePediatricParticipant: true, + residenceInUSTerritory: true + }); + + await participantListPage.filterListByShortId(shortID); + participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); + await participantPage.waitForReady(); + }); + + await test.step('Make sure that the Sequencing Order tab is visible', async () => { + await participantPage.tablist(Tab.SEQUENCING_ORDER).isVisible(); + sequencingOrderTab = await participantPage.tablist(Tab.SEQUENCING_ORDER).click(); + await sequencingOrderTab.waitForReady(); + }); + + await test.step('Place a clinical order using the Sequencing Order tab', async () => { + normalSample = await sequencingOrderTab.getFirstAvailableNormalSample(); + await sequencingOrderTab.selectSampleCheckbox(normalSample); + sampleNameNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.SAMPLE, page); + await sequencingOrderTab.fillCollectionDateIfNeeded(normalSample); + previousLatestOrderNumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); + console.log(`previous Latest Order Number for normal sample: ${previousLatestOrderNumberNormal}`); + + tumorSample = await sequencingOrderTab.getFirstAvailableTumorSample(); + await sequencingOrderTab.selectSampleCheckbox(tumorSample); + sampleNameTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.SAMPLE, page); + previousLatestOrderNumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); + console.log(`previous Latest Order Number for tumor sample: ${previousLatestOrderNumberTumor}`); + + await sequencingOrderTab.assertPlaceOrderButtonDisplayed(); + await sequencingOrderTab.placeOrder(); + + await sequencingOrderTab.assertClinicalOrderModalDisplayed(); + await sequencingOrderTab.submitClinicalOrder(); + }); + + /* NOTE: Need to go from Participant Page -> Participant List -> (refresh) -> Participant Page in order to see the new info */ + await test.step('Verify that the Latest Sequencing Order Date and Latest Order Number have been updated', async () => { + await participantPage.backToList(); + await participantListPage.filterListByShortId(shortID); + await participantListTable.openParticipantPageAt({ position: 0 }); + + await participantPage.waitForReady(); + sequencingOrderTab = await participantPage.tablist(Tab.SEQUENCING_ORDER).click(); + await sequencingOrderTab.waitForReady(); + + //Verify that Latest Sequencing Order Date is the current date and Latest Order Number has received new input + const today = getToday(); + + orderDateNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_SEQUENCING_ORDER_DATE, page); + expect(orderDateNormal.trim()).toBe(today); + + orderDateTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_SEQUENCING_ORDER_DATE, page); + expect(orderDateTumor.trim()).toBe(today); + + latestOrderNumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); + expect(latestOrderNumberNormal).not.toBe(previousLatestOrderNumberNormal); + + latestOrderNumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); + expect(latestOrderNumberTumor).not.toBe(previousLatestOrderNumberTumor); + }); + + await test.step('Place an order in mercury', async () => { + const message = createMercuryOrderMessage({ + latestOrderNumber: latestOrderNumberTumor, + orderStatus: approvedOrderStatus, + orderDetails: orderStatusDetail + }); + await placeMercuryOrder(MERCURY_PUBSUB_TOPIC_NAME, message); + }); + + await test.step('Verify that the mercury order was successfully placed', async () => { + //Check that Latest Order Status, Latest PDO Number are not empty for both Normal and Tumor samples - tab needs info refreshed in order to see changes + await participantPage.backToList(); + await participantListPage.filterListByShortId(shortID); + participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); + await participantPage.waitForReady(); + + await participantPage.tablist(Tab.SEQUENCING_ORDER).isVisible(); + await participantPage.tablist(Tab.SEQUENCING_ORDER).click(); + await sequencingOrderTab.waitForReady(); + + /* Checking the Normal sample's info */ + const latestOrderStatusNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); + expect(latestOrderStatusNormal).toBe(approvedOrderStatus); + const latestPDONumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); + expect(latestPDONumberNormal).toContain(`Made-by-Playwright-on`); + + /* Checking the Tumor sample's info */ + const latestOrderStatusTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); + expect(latestOrderStatusTumor).toBe(approvedOrderStatus); + const latestPDONumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); + expect(latestPDONumberTumor).toContain(`Made-by-Playwright-on`); + }); + + await test.step('Verify that the mercury order can be seen in Samples -> Clinical Orders', async () => { + //Check that info of the newest clinical order can be seen in Clinical Orders page + const clinicalOrderPage = await navigation.selectFromSamples(Samples.CLINICAL_ORDERS); + await clinicalOrderPage.waitForReady(); + + const clinicalOrderNormal = clinicalOrderPage.getClinicalOrderRow({ sampleType: 'Normal', orderNumber: latestOrderNumberNormal }); + const clinicalOrderTumor = clinicalOrderPage.getClinicalOrderRow({ sampleType: 'Tumor', orderNumber: latestOrderNumberTumor }); + + // Check that each sample's info is present: Short ID, Sample Type, Sample, Order Number, Order Date, Status, Status Detail + /* Normal Sample */ + const normalShortID = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.SHORT_ID, page); + expect(normalShortID).toBe(shortID); + + const normalSampleType = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.SAMPLE_TYPE, page); + expect(normalSampleType).toBe('Normal'); + + const normalSampleName = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.SAMPLE, page); + expect(normalSampleName).toBe(sampleNameNormal); + + const normalOrderNumber = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.ORDER_NUMBER, page); + expect(normalOrderNumber).toBe(latestOrderNumberNormal); + + const normalOrderDate = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.ORDER_DATE, page); + expect(normalOrderDate).toBe(orderDateNormal); + + const normalOrderStatus = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.STATUS, page); + expect(normalOrderStatus).toBe(approvedOrderStatus); + + const normalStatusDetail = await getColumnDataForRow(clinicalOrderNormal, ClinicalOrdersColumn.STATUS_DETAIL, page); + expect(normalStatusDetail).toBe(orderStatusDetail); + + /* Tumor Sample */ + const tumorShortID = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.SHORT_ID, page); + expect(tumorShortID).toBe(shortID); + + const tumorSampleType = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.SAMPLE_TYPE, page); + expect(tumorSampleType).toBe('Tumor'); + + const tumorSampleName = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.SAMPLE, page); + expect(tumorSampleName).toBe(sampleNameTumor); + + const tumorOrderNumber = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.ORDER_NUMBER, page); + expect(tumorOrderNumber).toBe(latestOrderNumberTumor); + + const tumorOrderDate = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.ORDER_DATE, page); + expect(tumorOrderDate).toBe(orderDateTumor); + + const tumorOrderStatus = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.STATUS, page); + expect(tumorOrderStatus).toBe(approvedOrderStatus); + + const tumorStatusDetail = await getColumnDataForRow(clinicalOrderTumor, ClinicalOrdersColumn.STATUS_DETAIL, page); + expect(tumorStatusDetail).toBe(orderStatusDetail); + }); }) } }) From 667f73c9fa916933ab1bf9dbdf04f002f5c589d5 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Fri, 13 Sep 2024 09:41:39 -0400 Subject: [PATCH 12/26] adding LMS to test --- playwright-e2e/.env.sample | 2 ++ playwright-e2e/config/.env.dev | 4 ++-- playwright-e2e/config/.env.test | 4 ++-- .../dsm/component/tables/participant-list-table.ts | 4 ++++ .../place-clinical-order-in-mercury.spec.ts | 8 +++++--- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/playwright-e2e/.env.sample b/playwright-e2e/.env.sample index d609e69d6c..0f57283a9f 100644 --- a/playwright-e2e/.env.sample +++ b/playwright-e2e/.env.sample @@ -4,6 +4,8 @@ SITE_PASSWORD= # PEPPER API_BASE_URL=https://pepper-dev.datadonationplatform.org +MERCURY_PUBSUB_TOPIC_NAME = +MERCURY_PUBSUB_PROJECT_ID = # ATCP ATCP_BASE_URL=https://atcp.dev.datadonationplatform.org diff --git a/playwright-e2e/config/.env.dev b/playwright-e2e/config/.env.dev index 8012bdeea5..73128e8e61 100644 --- a/playwright-e2e/config/.env.dev +++ b/playwright-e2e/config/.env.dev @@ -4,8 +4,8 @@ SITE_PASSWORD= # PEPPER API_BASE_URL=https://pepper-dev.datadonationplatform.org -MERCURY_PUBSUB_TOPIC_NAME = -MERCURY_PUBSUB_PROJECT_ID = +MERCURY_PUBSUB_TOPIC_NAME = +MERCURY_PUBSUB_PROJECT_ID = # ATCP ATCP_BASE_URL=https://atcp.dev.datadonationplatform.org diff --git a/playwright-e2e/config/.env.test b/playwright-e2e/config/.env.test index e507f3e5a8..112d3ce8f7 100644 --- a/playwright-e2e/config/.env.test +++ b/playwright-e2e/config/.env.test @@ -4,8 +4,8 @@ SITE_PASSWORD= # PEPPER API_BASE_URL=https://pepper-test.datadonationplatform.org -MERCURY_PUBSUB_TOPIC_NAME = -MERCURY_PUBSUB_PROJECT_ID = +MERCURY_PUBSUB_TOPIC_NAME = +MERCURY_PUBSUB_PROJECT_ID = # ATCP ATCP_BASE_URL=https://atcp.test.datadonationplatform.org diff --git a/playwright-e2e/dsm/component/tables/participant-list-table.ts b/playwright-e2e/dsm/component/tables/participant-list-table.ts index 51fc1e2554..b31755e1f5 100644 --- a/playwright-e2e/dsm/component/tables/participant-list-table.ts +++ b/playwright-e2e/dsm/component/tables/participant-list-table.ts @@ -58,6 +58,10 @@ export class ParticipantListTable extends Table { return this.cell(position, columnIndex).innerText(); } + public getParticipantColumnDataViaShortID(shortID: string, columnToCheck: string): string { + + } + public async selectCheckboxForParticipantAt(position: number): Promise { await this.getParticipantAt(position).nth(0).locator('mat-checkbox').click(); } diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index ed49fde875..fed0043fb7 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -12,7 +12,7 @@ import { getColumnDataForRow, studyShortName } from 'utils/test-utils'; import { PubSub } from '@google-cloud/pubsub'; import ClinicalOrdersPage from 'dsm/pages/clinical-orders-page'; -const pecgsStudies = [StudyName.OSTEO2]; //Checking OS2 first +const pecgsStudies = [StudyName.OSTEO2, StudyName.LMS]; //Checking OS2 first const MERCURY_PUBSUB_TOPIC_NAME = process.env.MERCURY_PUBSUB_TOPIC_NAME as string; const MERCURY_PUBSUB_PROJECT_ID = process.env.MERCURY_PUBSUB_PROJECT_ID as string; @@ -44,12 +44,13 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm const participantListTable = participantListPage.participantListTable; await test.step('Chose an enrolled participant that will get a clinical order placed', async () => { - shortID = await findParticipantForGermlineSequencing({ + /*shortID = await findParticipantForGermlineSequencing({ enrollmentStatus: DataFilter.ENROLLED, participantList: participantListPage, participantTable: participantListTable, studyName: study - }); + });*/ + shortID = 'PTPGLV';//checking LMS ptp await participantListPage.filterListByShortId(shortID); participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); @@ -545,6 +546,7 @@ async function findParticipantForGermlineSequencing(opts: { const customizeViewPanel = participantList.filters.customizeViewPanel; await customizeViewPanel.open(); + await customizeViewPanel.selectColumns(CustomizeView.SAMPLE, [Label.STATUS]); await customizeViewPanel.selectColumns(CustomizeView.CLINICAL_ORDERS, [ Label.CLINICAL_ORDER_DATE, Label.CLINICAL_ORDER_ID, From 6a6d495ee76aee26086f42487af6339af58edae5 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Thu, 19 Sep 2024 10:13:37 -0400 Subject: [PATCH 13/26] making changes to allow LMS to be used --- .../dsm/pages/participant-list-page.ts | 10 ++ .../place-clinical-order-in-mercury.spec.ts | 96 ++++++++++++------- 2 files changed, 71 insertions(+), 35 deletions(-) diff --git a/playwright-e2e/dsm/pages/participant-list-page.ts b/playwright-e2e/dsm/pages/participant-list-page.ts index c5c037cd6b..f3755e0ad3 100644 --- a/playwright-e2e/dsm/pages/participant-list-page.ts +++ b/playwright-e2e/dsm/pages/participant-list-page.ts @@ -730,4 +730,14 @@ export default class ParticipantListPage extends DsmPageBase { const { optionName } = opts; return this.page.locator(`//text()[normalize-space()='${optionName}']/preceding-sibling::button`); } + + public async refreshParticipantListUsingShortID(opts: { ID: string }): Promise { + const { ID } = opts; + const searchPanel = this.filters.searchPanel; + await searchPanel.open(); + const shortIDField = this.page.locator(`//app-filter-column//input[contains(@data-placeholder, 'Short ID')]`); + await expect(shortIDField, 'Search Panel -> Short ID column is not visible, it may need to be added to the Participant List').toBeVisible(); + await searchPanel.text(Label.SHORT_ID, { textValue: ID }); + await searchPanel.search(); + } } diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index fed0043fb7..e483e6a897 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -44,15 +44,15 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm const participantListTable = participantListPage.participantListTable; await test.step('Chose an enrolled participant that will get a clinical order placed', async () => { - /*shortID = await findParticipantForGermlineSequencing({ + shortID = await findParticipantForGermlineSequencing({ enrollmentStatus: DataFilter.ENROLLED, participantList: participantListPage, participantTable: participantListTable, studyName: study - });*/ - shortID = 'PTPGLV';//checking LMS ptp + }); + //shortID = 'PTPGLV';//checking LMS ptp - await participantListPage.filterListByShortId(shortID); + await participantListPage.refreshParticipantListUsingShortID({ ID: shortID }); participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); await participantPage.waitForReady(); }); @@ -87,7 +87,7 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm /* NOTE: Need to go from Participant Page -> Participant List -> (refresh) -> Participant Page in order to see the new info */ await test.step('Verify that the Latest Sequencing Order Date and Latest Order Number have been updated', async () => { await participantPage.backToList(); - await participantListPage.filterListByShortId(shortID); + await participantListPage.refreshParticipantListUsingShortID({ ID: shortID }); await participantListTable.openParticipantPageAt({ position: 0 }); await participantPage.waitForReady(); @@ -121,26 +121,32 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm await test.step('Verify that the mercury order was successfully placed', async () => { //Check that Latest Order Status, Latest PDO Number are not empty for both Normal and Tumor samples - tab needs info refreshed in order to see changes - await participantPage.backToList(); - await participantListPage.filterListByShortId(shortID); - participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); - await participantPage.waitForReady(); - - await participantPage.tablist(Tab.SEQUENCING_ORDER).isVisible(); - await participantPage.tablist(Tab.SEQUENCING_ORDER).click(); - await sequencingOrderTab.waitForReady(); - - /* Checking the Normal sample's info */ - const latestOrderStatusNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); - expect(latestOrderStatusNormal).toBe(approvedOrderStatus); - const latestPDONumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); - expect(latestPDONumberNormal).toContain(`Made-by-Playwright-on`); - - /* Checking the Tumor sample's info */ - const latestOrderStatusTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); - expect(latestOrderStatusTumor).toBe(approvedOrderStatus); - const latestPDONumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); - expect(latestPDONumberTumor).toContain(`Made-by-Playwright-on`); + await expect(async () => { + //Occasionally, a couple of seconds are needed before the info shows up in DSM UI + await participantPage.backToList(); + await participantListPage.refreshParticipantListUsingShortID({ ID: shortID }); + participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); + await participantPage.waitForReady(); + + await participantPage.tablist(Tab.SEQUENCING_ORDER).isVisible(); + await participantPage.tablist(Tab.SEQUENCING_ORDER).click(); + await sequencingOrderTab.waitForReady(); + + /* Checking the Normal sample's info */ + const latestOrderStatusNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); + expect(latestOrderStatusNormal).toBe(approvedOrderStatus); + const latestPDONumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); + expect(latestPDONumberNormal).toContain(`Made-by-Playwright-on`); + + /* Checking the Tumor sample's info */ + const latestOrderStatusTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); + expect(latestOrderStatusTumor).toBe(approvedOrderStatus); + const latestPDONumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); + expect(latestPDONumberTumor).toContain(`Made-by-Playwright-on`); + }).toPass({ + intervals: [10_000], + timeout: 60_000 + }); }); await test.step('Verify that the mercury order can be seen in Samples -> Clinical Orders', async () => { @@ -215,7 +221,7 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm usePediatricParticipant: true }); - await participantListPage.filterListByShortId(shortID); + await participantListPage.refreshParticipantListUsingShortID({ ID: shortID }); participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); await participantPage.waitForReady(); }); @@ -250,7 +256,7 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm /* NOTE: Need to go from Participant Page -> Participant List -> (refresh) -> Participant Page in order to see the new info */ await test.step('Verify that the Latest Sequencing Order Date and Latest Order Number have been updated', async () => { await participantPage.backToList(); - await participantListPage.filterListByShortId(shortID); + await participantListPage.refreshParticipantListUsingShortID({ ID: shortID }); await participantListTable.openParticipantPageAt({ position: 0 }); await participantPage.waitForReady(); @@ -285,7 +291,7 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm await test.step('Verify that the mercury order was successfully placed', async () => { //Check that Latest Order Status, Latest PDO Number are not empty for both Normal and Tumor samples - tab needs info refreshed in order to see changes await participantPage.backToList(); - await participantListPage.filterListByShortId(shortID); + await participantListPage.refreshParticipantListUsingShortID({ ID: shortID }); participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); await participantPage.waitForReady(); @@ -379,7 +385,7 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm residenceInUSTerritory: true }); - await participantListPage.filterListByShortId(shortID); + await participantListPage.refreshParticipantListUsingShortID({ ID: shortID }); participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); await participantPage.waitForReady(); }); @@ -414,7 +420,7 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm /* NOTE: Need to go from Participant Page -> Participant List -> (refresh) -> Participant Page in order to see the new info */ await test.step('Verify that the Latest Sequencing Order Date and Latest Order Number have been updated', async () => { await participantPage.backToList(); - await participantListPage.filterListByShortId(shortID); + await participantListPage.refreshParticipantListUsingShortID({ ID: shortID }); await participantListTable.openParticipantPageAt({ position: 0 }); await participantPage.waitForReady(); @@ -449,7 +455,7 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm await test.step('Verify that the mercury order was successfully placed', async () => { //Check that Latest Order Status, Latest PDO Number are not empty for both Normal and Tumor samples - tab needs info refreshed in order to see changes await participantPage.backToList(); - await participantListPage.filterListByShortId(shortID); + await participantListPage.refreshParticipantListUsingShortID({ ID: shortID }); participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); await participantPage.waitForReady(); @@ -578,11 +584,31 @@ async function findParticipantForGermlineSequencing(opts: { const numberOfReturnedParticipants = await participantTable.getRowsCount(); expect(numberOfReturnedParticipants).toBeGreaterThanOrEqual(1); - //Randomly chose a participant to get a clinical order who had previously had an order placed - const randomizedParticipantRows = await participantTable.randomizeRows(); - const rowNumber = randomizedParticipantRows[0]; + //Enrollment Status and Kit Status have the same name in the Participant List Table, so take out Enrollment Status + await customizeViewPanel.open(); + await customizeViewPanel.deselectColumns(CustomizeView.PARTICIPANT, [Label.STATUS]); + await customizeViewPanel.close(); + + //Randomly chose a participant to get a clinical order who had previously had an order placed - and does not have deactivated kits (due to the bug: PEPPER-1511) + /*const randomizedParticipantRows = await participantTable.randomizeRows(); + const rowNumber = randomizedParticipantRows[0];*/ + let participantChosen = false; + let rowNumber = 0; + let shortID = ''; + while (!participantChosen) { + const randomizedParticipantRows = await participantTable.randomizeRows(); + rowNumber = randomizedParticipantRows[0]; + const kitStatus = (await participantTable.getParticipantDataAt(rowNumber, Label.STATUS)).trim(); + console.log(`Kit Status: ${kitStatus}`); + if (!kitStatus.includes(`Deactivated`) || studyName === StudyName.OSTEO2) { + participantChosen = true; + shortID = await participantTable.getParticipantDataAt(rowNumber, Label.SHORT_ID); + console.log(`short id without a deactivated kit: ${shortID}`); + } + } - const shortID = await participantTable.getParticipantDataAt(rowNumber, Label.SHORT_ID); + //const shortID = await participantTable.getParticipantDataAt(rowNumber, Label.SHORT_ID); + //shortID = 'PTPGLV'; console.log(`Participant chosen for clinical order: ${shortID}`); return shortID; From 89143dacc696fd14ec61e6e659a49c7eda5c862f Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Mon, 30 Sep 2024 10:48:32 -0400 Subject: [PATCH 14/26] slight changes --- .../place-clinical-order-in-mercury.spec.ts | 22 +++++++++++++------ playwright-e2e/utils/test-utils.ts | 1 - 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index e483e6a897..0e4144719e 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -21,6 +21,7 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm const orderStatusDetail = 'Successfully created order via Playwright'; let navigation: Navigation; let shortID: string; + let participantEnrollmentStatus: DataFilter; let participantPage: ParticipantPage; let sequencingOrderTab: SequeuncingOrderTab; let normalSample: Locator; @@ -44,8 +45,9 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm const participantListTable = participantListPage.participantListTable; await test.step('Chose an enrolled participant that will get a clinical order placed', async () => { + participantEnrollmentStatus = DataFilter.ENROLLED; shortID = await findParticipantForGermlineSequencing({ - enrollmentStatus: DataFilter.ENROLLED, + enrollmentStatus: participantEnrollmentStatus, participantList: participantListPage, participantTable: participantListTable, studyName: study @@ -213,8 +215,9 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm const participantListTable = participantListPage.participantListTable; await test.step('Chose an enrolled participant that will get a clinical order placed', async () => { + participantEnrollmentStatus = DataFilter.LOST_TO_FOLLOWUP; shortID = await findParticipantForGermlineSequencing({ - enrollmentStatus: DataFilter.LOST_TO_FOLLOWUP, + enrollmentStatus: participantEnrollmentStatus, participantList: participantListPage, participantTable: participantListTable, studyName: study, @@ -300,10 +303,13 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm await sequencingOrderTab.waitForReady(); /* Checking the Normal sample's info */ - const latestOrderStatusNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); - expect(latestOrderStatusNormal).toBe(approvedOrderStatus); - const latestPDONumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); - expect(latestPDONumberNormal).toContain(`Made-by-Playwright-on`); + if ((study === StudyName.OSTEO2) && (participantEnrollmentStatus === DataFilter.LOST_TO_FOLLOWUP)) { + //LMS Lost-to-Followup participants do not have all info displayed in SequencingOrder tab (tracked by PEPPER-1511) + const latestOrderStatusNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); + expect(latestOrderStatusNormal).toBe(approvedOrderStatus); + const latestPDONumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); + expect(latestPDONumberNormal).toContain(`Made-by-Playwright-on`); + } /* Checking the Tumor sample's info */ const latestOrderStatusTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); @@ -376,8 +382,9 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm const participantListTable = participantListPage.participantListTable; await test.step('Chose an enrolled participant that will get a clinical order placed', async () => { + participantEnrollmentStatus = DataFilter.LOST_TO_FOLLOWUP; shortID = await findParticipantForGermlineSequencing({ - enrollmentStatus: DataFilter.LOST_TO_FOLLOWUP, + enrollmentStatus: participantEnrollmentStatus, participantList: participantListPage, participantTable: participantListTable, studyName: study, @@ -579,6 +586,7 @@ async function findParticipantForGermlineSequencing(opts: { await searchPanel.text(Label.COUNTRY, { textValue: 'US' }); } + await searchPanel.search({ uri: 'filterList' }); await searchPanel.search({ uri: 'filterList' }); const numberOfReturnedParticipants = await participantTable.getRowsCount(); diff --git a/playwright-e2e/utils/test-utils.ts b/playwright-e2e/utils/test-utils.ts index 60363d1b42..74a9232197 100644 --- a/playwright-e2e/utils/test-utils.ts +++ b/playwright-e2e/utils/test-utils.ts @@ -371,7 +371,6 @@ export function totalNumberOfOccurences(opts: { arrayToSearch: string[], wordToS export async function getColumnHeaderIndex(columnName: string, page: Page): Promise { const precedingColumns = page.locator(`//th[normalize-space(text())='${columnName}']/preceding-sibling::th`); const columnIndex = await precedingColumns.count() + 1; - console.log(`${columnName} is the ${columnIndex}th column`); return columnIndex; } From 81adeef7f2486e9f87397cf4e92965a7b47b66a1 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Mon, 30 Sep 2024 15:53:18 -0400 Subject: [PATCH 15/26] get rid of empty method --- playwright-e2e/dsm/component/tables/participant-list-table.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/playwright-e2e/dsm/component/tables/participant-list-table.ts b/playwright-e2e/dsm/component/tables/participant-list-table.ts index b31755e1f5..51fc1e2554 100644 --- a/playwright-e2e/dsm/component/tables/participant-list-table.ts +++ b/playwright-e2e/dsm/component/tables/participant-list-table.ts @@ -58,10 +58,6 @@ export class ParticipantListTable extends Table { return this.cell(position, columnIndex).innerText(); } - public getParticipantColumnDataViaShortID(shortID: string, columnToCheck: string): string { - - } - public async selectCheckboxForParticipantAt(position: number): Promise { await this.getParticipantAt(position).nth(0).locator('mat-checkbox').click(); } From acce2554548326b1403ed1a341092e5ea32bfc8e Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Fri, 11 Oct 2024 11:22:13 -0400 Subject: [PATCH 16/26] cleanup --- .../place-clinical-order-in-mercury.spec.ts | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index 0e4144719e..50adc19f2d 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -12,7 +12,7 @@ import { getColumnDataForRow, studyShortName } from 'utils/test-utils'; import { PubSub } from '@google-cloud/pubsub'; import ClinicalOrdersPage from 'dsm/pages/clinical-orders-page'; -const pecgsStudies = [StudyName.OSTEO2, StudyName.LMS]; //Checking OS2 first +const pecgsStudies = [StudyName.OSTEO2]; //Checking OS2 first - LMS runs into PEPPER-1511 more; TODO: Add LMS once PEPPER-1511 is fixed const MERCURY_PUBSUB_TOPIC_NAME = process.env.MERCURY_PUBSUB_TOPIC_NAME as string; const MERCURY_PUBSUB_PROJECT_ID = process.env.MERCURY_PUBSUB_PROJECT_ID as string; @@ -461,26 +461,32 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm await test.step('Verify that the mercury order was successfully placed', async () => { //Check that Latest Order Status, Latest PDO Number are not empty for both Normal and Tumor samples - tab needs info refreshed in order to see changes - await participantPage.backToList(); - await participantListPage.refreshParticipantListUsingShortID({ ID: shortID }); - participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); - await participantPage.waitForReady(); + //NOTE: occasionally needs a couple more seconds before the expected statuses are displayed + await expect(async () => { + await participantPage.backToList(); + await participantListPage.refreshParticipantListUsingShortID({ ID: shortID }); + participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); + await participantPage.waitForReady(); - await participantPage.tablist(Tab.SEQUENCING_ORDER).isVisible(); - await participantPage.tablist(Tab.SEQUENCING_ORDER).click(); - await sequencingOrderTab.waitForReady(); + await participantPage.tablist(Tab.SEQUENCING_ORDER).isVisible(); + await participantPage.tablist(Tab.SEQUENCING_ORDER).click(); + await sequencingOrderTab.waitForReady(); - /* Checking the Normal sample's info */ - const latestOrderStatusNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); - expect(latestOrderStatusNormal).toBe(approvedOrderStatus); - const latestPDONumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); - expect(latestPDONumberNormal).toContain(`Made-by-Playwright-on`); + /* Checking the Normal sample's info */ + const latestOrderStatusNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); + expect(latestOrderStatusNormal).toBe(approvedOrderStatus); + const latestPDONumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); + expect(latestPDONumberNormal).toContain(`Made-by-Playwright-on`); - /* Checking the Tumor sample's info */ - const latestOrderStatusTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); - expect(latestOrderStatusTumor).toBe(approvedOrderStatus); - const latestPDONumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); - expect(latestPDONumberTumor).toContain(`Made-by-Playwright-on`); + /* Checking the Tumor sample's info */ + const latestOrderStatusTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); + expect(latestOrderStatusTumor).toBe(approvedOrderStatus); + const latestPDONumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); + expect(latestPDONumberTumor).toContain(`Made-by-Playwright-on`); + }).toPass({ + intervals: [10_000], + timeout: 60_000 + }); }); await test.step('Verify that the mercury order can be seen in Samples -> Clinical Orders', async () => { From 88f4a47a7a8cc648451bbe924d9a50ed8603c7eb Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Fri, 11 Oct 2024 14:33:41 -0400 Subject: [PATCH 17/26] got rid of space --- playwright-e2e/config/.env.dev | 4 ++-- playwright-e2e/config/.env.test | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/playwright-e2e/config/.env.dev b/playwright-e2e/config/.env.dev index 73128e8e61..8133de8e94 100644 --- a/playwright-e2e/config/.env.dev +++ b/playwright-e2e/config/.env.dev @@ -4,8 +4,8 @@ SITE_PASSWORD= # PEPPER API_BASE_URL=https://pepper-dev.datadonationplatform.org -MERCURY_PUBSUB_TOPIC_NAME = -MERCURY_PUBSUB_PROJECT_ID = +MERCURY_PUBSUB_TOPIC_NAME= +MERCURY_PUBSUB_PROJECT_ID= # ATCP ATCP_BASE_URL=https://atcp.dev.datadonationplatform.org diff --git a/playwright-e2e/config/.env.test b/playwright-e2e/config/.env.test index 112d3ce8f7..805aa1ff34 100644 --- a/playwright-e2e/config/.env.test +++ b/playwright-e2e/config/.env.test @@ -4,8 +4,8 @@ SITE_PASSWORD= # PEPPER API_BASE_URL=https://pepper-test.datadonationplatform.org -MERCURY_PUBSUB_TOPIC_NAME = -MERCURY_PUBSUB_PROJECT_ID = +MERCURY_PUBSUB_TOPIC_NAME= +MERCURY_PUBSUB_PROJECT_ID= # ATCP ATCP_BASE_URL=https://atcp.test.datadonationplatform.org From 31085ef231a56094940e404df1b1a1b4a51b34d6 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Fri, 11 Oct 2024 14:35:01 -0400 Subject: [PATCH 18/26] more cleanup --- playwright-e2e/.env.sample | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/playwright-e2e/.env.sample b/playwright-e2e/.env.sample index 0f57283a9f..4b33a5c3fe 100644 --- a/playwright-e2e/.env.sample +++ b/playwright-e2e/.env.sample @@ -4,8 +4,8 @@ SITE_PASSWORD= # PEPPER API_BASE_URL=https://pepper-dev.datadonationplatform.org -MERCURY_PUBSUB_TOPIC_NAME = -MERCURY_PUBSUB_PROJECT_ID = +MERCURY_PUBSUB_TOPIC_NAME= +MERCURY_PUBSUB_PROJECT_ID= # ATCP ATCP_BASE_URL=https://atcp.dev.datadonationplatform.org From 560f169102ca49a09fa3f0e20e29c3499d7f9185 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Fri, 11 Oct 2024 16:19:33 -0400 Subject: [PATCH 19/26] connecting to mercury info in vault --- .circleci/export-playwright-env.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.circleci/export-playwright-env.sh b/.circleci/export-playwright-env.sh index 8104eeb34b..6a1f8c6b93 100755 --- a/.circleci/export-playwright-env.sh +++ b/.circleci/export-playwright-env.sh @@ -9,6 +9,12 @@ echo "export SITE_PASSWORD=$sitePwd" >> playwright-env/envvars export bspToken=$(vault read --format=json secret/pepper/test/v1/e2e | jq -r ".data.bsp | .[] | select(.env==\"$ENV\") | .token") echo "export BSP_TOKEN=$bspToken" >> playwright-env/envvars +export pubsubTopicName=$(vault read --format=json secret/pepper/test/v1/e2e | jq -r ".data.mercury | .[] | select(.env==\"$ENV\") | .pubsubTopicName") +echo "export MERCURY_PUBSUB_TOPIC_NAME=$pubsubTopicName" >> playwright-env/envvars + +export pubsubProjectId=$(vault read --format=json secret/pepper/test/v1/e2e | jq -r ".data.mercury | .[] | select(.env==\"$ENV\") | .pubsubProjectId") +echo "export MERCURY_PUBSUB_PROJECT_ID=$pubsubProjectId" >> playwright-env/envvars + export dsmUser1=$(vault read --format=json secret/pepper/test/v1/e2e | jq -r ".data.users | .[] | select(.app==\"dsm\") | .users[0] | .userName") export dsmUser1Password=$(vault read --format=json secret/pepper/test/v1/e2e | jq -r ".data.users | .[] | select(.app==\"dsm\") | .users[0] | .password") echo "export DSM_USER1_EMAIL=$dsmUser1" >> playwright-env/envvars From e2b5faf3f8767c4ab5fe24808d9d88176f983bf3 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Tue, 15 Oct 2024 05:57:27 -0400 Subject: [PATCH 20/26] implement feedback --- .../clinical-orders/place-clinical-order-in-mercury.spec.ts | 4 ++-- playwright-e2e/utils/date-utils.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index 50adc19f2d..fb846a7c93 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -7,7 +7,7 @@ import ParticipantPage from 'dsm/pages/participant-page'; import SequeuncingOrderTab from 'dsm/pages/tablist/sequencing-order-tab'; import Select from 'dss/component/select'; import { test } from 'fixtures/dsm-fixture'; -import { getDateEasternTimeZone, getDateMonthAbbreviated, getToday, getTodayInEastCoastDateTimeFormat, toLocalTime } from 'utils/date-utils'; +import { getDateEasternTimeZone, getDateMonthAbbreviated, getToday, getTodayInEastCoastDateTimeZone, toLocalTime } from 'utils/date-utils'; import { getColumnDataForRow, studyShortName } from 'utils/test-utils'; import { PubSub } from '@google-cloud/pubsub'; import ClinicalOrdersPage from 'dsm/pages/clinical-orders-page'; @@ -634,7 +634,7 @@ function createMercuryOrderMessage(opts: { orderDetails?: string }): string { const { latestOrderNumber, orderStatus = 'Approved', orderDetails = 'Successfully created order' } = opts; - const readableDate = getTodayInEastCoastDateTimeFormat(); + const readableDate = getTodayInEastCoastDateTimeZone(); const message = ` { diff --git a/playwright-e2e/utils/date-utils.ts b/playwright-e2e/utils/date-utils.ts index 7bd5c03dff..2449277975 100644 --- a/playwright-e2e/utils/date-utils.ts +++ b/playwright-e2e/utils/date-utils.ts @@ -150,6 +150,6 @@ export const calculateAge = (month: string, day: string, year: string): number = return resultAge; }; -export const getTodayInEastCoastDateTimeFormat = (): string => { +export const getTodayInEastCoastDateTimeZone = (): string => { return new Date().toLocaleString('en-US', { timeZone: 'America/New_York' }); } From bc42eec11fb289802e5f3fd88de49f6b4693baa4 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Tue, 15 Oct 2024 06:08:44 -0400 Subject: [PATCH 21/26] decreasing intervals for waiting for expectToPass --- .../dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index fb846a7c93..19ba600bd5 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -484,7 +484,7 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm const latestPDONumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); expect(latestPDONumberTumor).toContain(`Made-by-Playwright-on`); }).toPass({ - intervals: [10_000], + intervals: [5_000], timeout: 60_000 }); }); From 20890c84c831272b067f5edb556c87ea666e3655 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Tue, 15 Oct 2024 10:41:05 -0400 Subject: [PATCH 22/26] adding expectToPass since it seems it might need it on a circleci run --- .../place-clinical-order-in-mercury.spec.ts | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index 19ba600bd5..23afb9483c 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -293,29 +293,32 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm await test.step('Verify that the mercury order was successfully placed', async () => { //Check that Latest Order Status, Latest PDO Number are not empty for both Normal and Tumor samples - tab needs info refreshed in order to see changes - await participantPage.backToList(); - await participantListPage.refreshParticipantListUsingShortID({ ID: shortID }); - participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); - await participantPage.waitForReady(); + await expect(async () => { + //Occasionally, a couple of seconds are needed before the info shows up in DSM UI + await participantPage.backToList(); + await participantListPage.refreshParticipantListUsingShortID({ ID: shortID }); + participantPage = await participantListTable.openParticipantPageAt({ position: 0 }); + await participantPage.waitForReady(); - await participantPage.tablist(Tab.SEQUENCING_ORDER).isVisible(); - await participantPage.tablist(Tab.SEQUENCING_ORDER).click(); - await sequencingOrderTab.waitForReady(); + await participantPage.tablist(Tab.SEQUENCING_ORDER).isVisible(); + await participantPage.tablist(Tab.SEQUENCING_ORDER).click(); + await sequencingOrderTab.waitForReady(); - /* Checking the Normal sample's info */ - if ((study === StudyName.OSTEO2) && (participantEnrollmentStatus === DataFilter.LOST_TO_FOLLOWUP)) { - //LMS Lost-to-Followup participants do not have all info displayed in SequencingOrder tab (tracked by PEPPER-1511) + /* Checking the Normal sample's info */ const latestOrderStatusNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); expect(latestOrderStatusNormal).toBe(approvedOrderStatus); const latestPDONumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); expect(latestPDONumberNormal).toContain(`Made-by-Playwright-on`); - } - /* Checking the Tumor sample's info */ - const latestOrderStatusTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); - expect(latestOrderStatusTumor).toBe(approvedOrderStatus); - const latestPDONumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); - expect(latestPDONumberTumor).toContain(`Made-by-Playwright-on`); + /* Checking the Tumor sample's info */ + const latestOrderStatusTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_STATUS, page); + expect(latestOrderStatusTumor).toBe(approvedOrderStatus); + const latestPDONumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); + expect(latestPDONumberTumor).toContain(`Made-by-Playwright-on`); + }).toPass({ + intervals: [10_000], + timeout: 60_000 + }); }); await test.step('Verify that the mercury order can be seen in Samples -> Clinical Orders', async () => { @@ -484,7 +487,7 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm const latestPDONumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); expect(latestPDONumberTumor).toContain(`Made-by-Playwright-on`); }).toPass({ - intervals: [5_000], + intervals: [10_000], timeout: 60_000 }); }); From d7af04340e046b5915c43b4a8032bc781ddaf738 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Tue, 15 Oct 2024 14:13:12 -0400 Subject: [PATCH 23/26] checking if timing works better for circleci since it passes locally --- .../clinical-orders/place-clinical-order-in-mercury.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index 23afb9483c..fd861ba80f 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -146,7 +146,7 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm const latestPDONumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); expect(latestPDONumberTumor).toContain(`Made-by-Playwright-on`); }).toPass({ - intervals: [10_000], + intervals: [20_000], timeout: 60_000 }); }); @@ -316,7 +316,7 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm const latestPDONumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); expect(latestPDONumberTumor).toContain(`Made-by-Playwright-on`); }).toPass({ - intervals: [10_000], + intervals: [20_000], timeout: 60_000 }); }); @@ -487,7 +487,7 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm const latestPDONumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_PDO_NUMBER, page); expect(latestPDONumberTumor).toContain(`Made-by-Playwright-on`); }).toPass({ - intervals: [10_000], + intervals: [20_000], timeout: 60_000 }); }); From 52b642922c9a06f0604c610d7a33cec101c7d78d Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Tue, 15 Oct 2024 14:37:53 -0400 Subject: [PATCH 24/26] adding more logging to try to find where test is failing in circleci --- .../place-clinical-order-in-mercury.spec.ts | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index fd861ba80f..7b2b516686 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -11,6 +11,7 @@ import { getDateEasternTimeZone, getDateMonthAbbreviated, getToday, getTodayInEa import { getColumnDataForRow, studyShortName } from 'utils/test-utils'; import { PubSub } from '@google-cloud/pubsub'; import ClinicalOrdersPage from 'dsm/pages/clinical-orders-page'; +import { logInfo } from 'utils/log-utils'; const pecgsStudies = [StudyName.OSTEO2]; //Checking OS2 first - LMS runs into PEPPER-1511 more; TODO: Add LMS once PEPPER-1511 is fixed const MERCURY_PUBSUB_TOPIC_NAME = process.env.MERCURY_PUBSUB_TOPIC_NAME as string; @@ -71,13 +72,13 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm sampleNameNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.SAMPLE, page); await sequencingOrderTab.fillCollectionDateIfNeeded(normalSample); previousLatestOrderNumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); - console.log(`previous Latest Order Number for normal sample: ${previousLatestOrderNumberNormal}`); + logInfo(`previous Latest Order Number for normal sample: ${previousLatestOrderNumberNormal}`); tumorSample = await sequencingOrderTab.getFirstAvailableTumorSample(); await sequencingOrderTab.selectSampleCheckbox(tumorSample); sampleNameTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.SAMPLE, page); previousLatestOrderNumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); - console.log(`previous Latest Order Number for tumor sample: ${previousLatestOrderNumberTumor}`); + logInfo(`previous Latest Order Number for tumor sample: ${previousLatestOrderNumberTumor}`); await sequencingOrderTab.assertPlaceOrderButtonDisplayed(); await sequencingOrderTab.placeOrder(); @@ -241,13 +242,13 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm sampleNameNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.SAMPLE, page); await sequencingOrderTab.fillCollectionDateIfNeeded(normalSample); previousLatestOrderNumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); - console.log(`previous Latest Order Number for normal sample: ${previousLatestOrderNumberNormal}`); + logInfo(`previous Latest Order Number for normal sample: ${previousLatestOrderNumberNormal}`); tumorSample = await sequencingOrderTab.getFirstAvailableTumorSample(); await sequencingOrderTab.selectSampleCheckbox(tumorSample); sampleNameTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.SAMPLE, page); previousLatestOrderNumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); - console.log(`previous Latest Order Number for tumor sample: ${previousLatestOrderNumberTumor}`); + logInfo(`previous Latest Order Number for tumor sample: ${previousLatestOrderNumberTumor}`); await sequencingOrderTab.assertPlaceOrderButtonDisplayed(); await sequencingOrderTab.placeOrder(); @@ -412,13 +413,13 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm sampleNameNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.SAMPLE, page); await sequencingOrderTab.fillCollectionDateIfNeeded(normalSample); previousLatestOrderNumberNormal = await getColumnDataForRow(normalSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); - console.log(`previous Latest Order Number for normal sample: ${previousLatestOrderNumberNormal}`); + logInfo(`previous Latest Order Number for normal sample: ${previousLatestOrderNumberNormal}`); tumorSample = await sequencingOrderTab.getFirstAvailableTumorSample(); await sequencingOrderTab.selectSampleCheckbox(tumorSample); sampleNameTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.SAMPLE, page); previousLatestOrderNumberTumor = await getColumnDataForRow(tumorSample, SequencingOrderColumn.LATEST_ORDER_NUMBER, page); - console.log(`previous Latest Order Number for tumor sample: ${previousLatestOrderNumberTumor}`); + logInfo(`previous Latest Order Number for tumor sample: ${previousLatestOrderNumberTumor}`); await sequencingOrderTab.assertPlaceOrderButtonDisplayed(); await sequencingOrderTab.placeOrder(); @@ -564,7 +565,6 @@ async function findParticipantForGermlineSequencing(opts: { if (usePediatricParticipant) { participantPrefix = studyInformation.playwrightPrefixChild; } - console.log(`prefix: ${participantPrefix}`); const customizeViewPanel = participantList.filters.customizeViewPanel; await customizeViewPanel.open(); @@ -616,17 +616,17 @@ async function findParticipantForGermlineSequencing(opts: { const randomizedParticipantRows = await participantTable.randomizeRows(); rowNumber = randomizedParticipantRows[0]; const kitStatus = (await participantTable.getParticipantDataAt(rowNumber, Label.STATUS)).trim(); - console.log(`Kit Status: ${kitStatus}`); + logInfo(`Kit Status: ${kitStatus}`); if (!kitStatus.includes(`Deactivated`) || studyName === StudyName.OSTEO2) { participantChosen = true; shortID = await participantTable.getParticipantDataAt(rowNumber, Label.SHORT_ID); - console.log(`short id without a deactivated kit: ${shortID}`); + logInfo(`short id without a deactivated kit: ${shortID}`); } } //const shortID = await participantTable.getParticipantDataAt(rowNumber, Label.SHORT_ID); //shortID = 'PTPGLV'; - console.log(`Participant chosen for clinical order: ${shortID}`); + logInfo(`Participant chosen for clinical order: ${shortID}`); return shortID; } @@ -651,22 +651,23 @@ function createMercuryOrderMessage(opts: { }`; const messageObject = JSON.parse(message); - console.log(`Resulting pubsub message is:\n ${JSON.stringify(messageObject)}`); + logInfo(`Resulting pubsub message is:\n ${JSON.stringify(messageObject)}`); return JSON.stringify(messageObject); } async function placeMercuryOrder(topicNameOrID: string, messsage: string): Promise { const pubsubClient = new PubSub({projectId: MERCURY_PUBSUB_PROJECT_ID}); const dataBuffer = Buffer.from(messsage); - console.log(`Topic name or id: ${topicNameOrID}`); + logInfo(`Topic name or id: ${topicNameOrID}`); + logInfo(`Project ID: ${MERCURY_PUBSUB_PROJECT_ID}`); try { const messageID = await pubsubClient .topic(topicNameOrID) .publishMessage({ data: dataBuffer }); - console.log(`Message ${messageID} was published`); + logInfo(`Message ${messageID} was published`); } catch (error) { - console.log(`Received error while publishing: ${(error as Error).message}`); + logInfo(`Received error while publishing: ${(error as Error).message}`); process.exitCode = 1; } } From 0d305820c3025264c4457c6a7323ec44ba46532a Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Thu, 17 Oct 2024 13:30:07 -0400 Subject: [PATCH 25/26] description change --- .../dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts index 7b2b516686..2d862133cd 100644 --- a/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts +++ b/playwright-e2e/tests/dsm/clinical-orders/place-clinical-order-in-mercury.spec.ts @@ -385,7 +385,7 @@ test.describe.serial('Verify that clinical orders can be placed in mercury @dsm await participantListPage.waitForReady(); const participantListTable = participantListPage.participantListTable; - await test.step('Chose an enrolled participant that will get a clinical order placed', async () => { + await test.step('Chose a lost-to-followup participant that will get a clinical order placed', async () => { participantEnrollmentStatus = DataFilter.LOST_TO_FOLLOWUP; shortID = await findParticipantForGermlineSequencing({ enrollmentStatus: participantEnrollmentStatus, From cf0b52bfa3de38b79ec340fe02fa924b4cb612d7 Mon Sep 17 00:00:00 2001 From: Kiara Westbrooks Date: Fri, 22 Nov 2024 11:28:08 -0500 Subject: [PATCH 26/26] attempting to fix one pixel difference error --- playwright-e2e/playwright.config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/playwright-e2e/playwright.config.ts b/playwright-e2e/playwright.config.ts index 10b48f4149..9c0b5a69e2 100644 --- a/playwright-e2e/playwright.config.ts +++ b/playwright-e2e/playwright.config.ts @@ -36,7 +36,8 @@ const testConfig: PlaywrightTestConfig = { scale: 'css', // Account for minor difference in text rendering and resolution between headless and headed mode threshold: 1, - maxDiffPixelRatio: 0.5 + maxDiffPixels: 1 + //maxDiffPixelRatio: 0.5 } }, /* Run tests in files in parallel */