diff --git a/playwright-e2e/dsm/component/kitType/enums/kitType-enum.ts b/playwright-e2e/dsm/component/kitType/enums/kitType-enum.ts index ba380f579b..c130e9da9e 100644 --- a/playwright-e2e/dsm/component/kitType/enums/kitType-enum.ts +++ b/playwright-e2e/dsm/component/kitType/enums/kitType-enum.ts @@ -1,5 +1,6 @@ export enum KitTypeEnum { SALIVA = 'SALIVA', BLOOD = 'BLOOD', - STOOL = 'STOOL' + STOOL = 'STOOL', + BLOOD_AND_RNA = 'BLOOD & RNA' } diff --git a/playwright-e2e/dsm/component/navigation/navigation.ts b/playwright-e2e/dsm/component/navigation/navigation.ts index 7ac26d7478..b69a716fa5 100644 --- a/playwright-e2e/dsm/component/navigation/navigation.ts +++ b/playwright-e2e/dsm/component/navigation/navigation.ts @@ -15,6 +15,7 @@ import {MiscellaneousEnum} from 'dsm/component/navigation/enums/miscellaneousNav import KitsSentPage from 'dsm/pages/kitsInfo-pages/kitsSentPage'; import KitsReceivedPage from 'dsm/pages/kitsInfo-pages/kitsReceived-page/kitsReceivedPage'; import TrackingScanPage from 'dsm/pages/scanner-pages/trackingScan-page'; +import RgpFinalScanPage from 'dsm/pages/scanner-pages/rgpFinalScan-page'; type Selection = StudyNavEnum | StudyEnum | SamplesNavEnum | MiscellaneousEnum; @@ -27,6 +28,7 @@ export class Navigation { [SamplesNavEnum.INITIAL_SCAN, new InitialScanPage(this.page)], [SamplesNavEnum.TRACKING_SCAN, new TrackingScanPage(this.page)], [SamplesNavEnum.FINAL_SCAN, new FinalScanPage(this.page)], + [SamplesNavEnum.RGP_FINAL_SCAN, new RgpFinalScanPage(this.page)], [SamplesNavEnum.KIT_UPLOAD, new KitUploadPage(this.page)], [SamplesNavEnum.SENT, new KitsSentPage(this.page)], [SamplesNavEnum.RECEIVED, new KitsReceivedPage(this.page, this.request)], diff --git a/playwright-e2e/dsm/pages/scanner-pages/rgpFinalScan-page.ts b/playwright-e2e/dsm/pages/scanner-pages/rgpFinalScan-page.ts new file mode 100644 index 0000000000..6fd9436bdd --- /dev/null +++ b/playwright-e2e/dsm/pages/scanner-pages/rgpFinalScan-page.ts @@ -0,0 +1,52 @@ +import {expect, Page, Locator} from '@playwright/test'; + +type inputField = 'Kit Label' | 'RNA' | 'DSM Label'; + +export default class RgpFinalScanPage { + private readonly PAGE_TITLE = 'RGP Final Scan'; + + constructor(private readonly page: Page) {} + + public async fillScanTrio(kitLabel: string, rna:string, dsmLabel: string, rowNumber: number): Promise { + //First check if the number row is valid + const totalAmountOfRows = await this.getNumberOfScannableRows(); + expect(rowNumber, 'RGP Final Scan Page: More scannable rows displayed than expected').toBeLessThanOrEqual(totalAmountOfRows); + + //Setup which row will be filled with info + const kitLabelLocator = this.page.locator(`(//mat-form-field//input[contains(@data-placeholder, 'Kit Label')])[${rowNumber}]`); + const rnaLocator = this.page.locator(`(//mat-form-field//input[contains(@data-placeholder, 'RNA')])[${rowNumber}]`); + const dsmLabelLocator = this.page.locator(`(//mat-form-field//input[contains(@data-placeholder, 'DSM Label')])[${rowNumber}]`); + + //Input info + await kitLabelLocator.fill(kitLabel); + await kitLabelLocator.blur(); + + await rnaLocator.fill(rna); + await rnaLocator.blur(); + + await dsmLabelLocator.fill(dsmLabel); + await dsmLabelLocator.blur(); + } + + public async getNumberOfScannableRows(): Promise { + const numberOfRows = this.page.locator('//form/div').count(); + return numberOfRows; + } + + private getSaveScanPairsButton(): Locator { + const scanPairButton = this.page.getByRole('button', { name: 'Save Scan Pairs' }); + return scanPairButton; + } + + public async save(): Promise { + const scanPairButton = this.getSaveScanPairsButton(); + await expect(scanPairButton, 'RGP Final Scan page - Save Scan Pairs button is not enabled like expected').toBeEnabled(); + await scanPairButton.focus(); + await scanPairButton.click(); + } + + public async assertPageTitle(): Promise { + const heading = this.page.locator(`//h1[contains(., '${this.PAGE_TITLE}')]`); + await expect(heading, 'RGP Final Scan page header is not visible').toBeVisible(); + } +} diff --git a/playwright-e2e/tests/dsm/kitUploadFlow/blood-and-rna-kit-upload-flow.spec.ts b/playwright-e2e/tests/dsm/kitUploadFlow/blood-and-rna-kit-upload-flow.spec.ts new file mode 100644 index 0000000000..af33d10a41 --- /dev/null +++ b/playwright-e2e/tests/dsm/kitUploadFlow/blood-and-rna-kit-upload-flow.spec.ts @@ -0,0 +1,160 @@ +import { expect } from '@playwright/test'; +import { test } from 'fixtures/dsm-fixture'; +import { Navigation } from 'dsm/component/navigation/navigation'; +import Select from 'dss/component/select'; +import { KitUploadInfo } from 'dsm/pages/kitUpload-page/models/kitUpload-model'; +import {StudyEnum} from 'dsm/component/navigation/enums/selectStudyNav-enum'; +import { KitTypeEnum } from 'dsm/component/kitType/enums/kitType-enum'; +import ParticipantListPage from 'dsm/pages/participant-list-page'; +import {StudyNavEnum} from 'dsm/component/navigation/enums/studyNav-enum'; +import * as user from 'data/fake-user.json'; +import crypto from 'crypto'; +import KitUploadPage from 'dsm/pages/kitUpload-page/kitUpload-page'; +import {SamplesNavEnum} from 'dsm/component/navigation/enums/samplesNav-enum'; +import FamilyMemberTab from 'dsm/pages/participant-page/rgp/family-member-tab'; +import { FamilyMember } from 'dsm/component/tabs/enums/familyMember-enum'; +import KitsWithoutLabelPage from 'dsm/pages/kitsInfo-pages/kitsWithoutLabel-page'; +import {KitsColumnsEnum} from 'dsm/pages/kitsInfo-pages/enums/kitsColumns-enum'; +import KitsSentPage from 'dsm/pages/kitsInfo-pages/kitsSentPage'; +import KitsReceivedPage from 'dsm/pages/kitsInfo-pages/kitsReceived-page/kitsReceivedPage'; +import TrackingScanPage from 'dsm/pages/scanner-pages/trackingScan-page'; +import RgpFinalScanPage from 'dsm/pages/scanner-pages/rgpFinalScan-page' +import { simplifyShortID } from 'utils/faker-utils'; +import { saveParticipantGuid } from 'utils/faker-utils'; +import { ParticipantListTable } from 'dsm/component/tables/participant-list-table'; + +test.describe('Blood & RNA Kit Upload', () => { +test.skip('Verify that a blood & rna kit can be uploaded @rgp @functional @upload', async ({ page, request}, testInfo) => { + const testResultDirectory = testInfo.outputDir; + + const study = StudyEnum.RGP; + const kitType = KitTypeEnum.BLOOD_AND_RNA; + const expectedKitTypes = [KitTypeEnum.BLOOD, KitTypeEnum.BLOOD_AND_RNA]; //Later will be just Blood & RNA kit type for RGP + + //Go into DSM + const navigation = new Navigation(page, request); + + //select RGP study + await new Select(page, { label: 'Select study' }).selectOption('RGP'); + + //Go to recently created playwright test participant to get their short id + const participantListPage = await navigation.selectFromStudy(StudyNavEnum.PARTICIPANT_LIST); + await participantListPage.assertPageTitle(); + await participantListPage.waitForReady(); + + const participantListTable = new ParticipantListTable(page); + const participantGuid = await participantListTable.getGuidOfMostRecentAutomatedParticipant(user.patient.firstName, true); + saveParticipantGuid(participantGuid); + + await participantListPage.filterListByParticipantGUID(user.patient.participantGuid); + await participantListTable.openParticipantPageAt(0); + + //For RGP, the short id needed for the kit upload is the family member's subject id + const proband = new FamilyMemberTab(page, FamilyMember.PROBAND); + proband.relationshipID = user.patient.relationshipID; + + const probandTab = proband.getFamilyMemberTab(); + await expect(probandTab).toBeVisible(); + await probandTab.click(); + await expect(probandTab).toHaveClass('nav-link active');//Make sure the tab is in view and selected + + const participantInfoSection = proband.getParticipantInfoSection(); + await participantInfoSection.click(); + + const probandSubjectID = proband.getSubjectID(); + await expect(probandSubjectID).not.toBeEmpty(); + const shortID = await probandSubjectID.inputValue(); + const simpleShortId = simplifyShortID(shortID, 'RGP'); + + //Deactivate existing kits for participant + //Note: no blood kits are automatically created for RGP - preliminary deactivation of existing kits is done in case of prior test run + const kitsWithoutLabelPage = await navigation.selectFromSamples(SamplesNavEnum.KITS_WITHOUT_LABELS); + await kitsWithoutLabelPage.waitForLoad(); + await kitsWithoutLabelPage.assertPageTitle(); + await kitsWithoutLabelPage.selectKitType(kitType); + await kitsWithoutLabelPage.assertCreateLabelsBtn(); + await kitsWithoutLabelPage.assertReloadKitListBtn(); + await kitsWithoutLabelPage.assertTableHeader(); + await kitsWithoutLabelPage.deactivateAllKitsFor(simpleShortId); + + //The rest of the kit upload information - RGP kits are by family member instead of by account - using the proband's info to make a kit + const kitUploadInfo = new KitUploadInfo(shortID, user.patient.firstName, user.patient.lastName); + kitUploadInfo.street1 = user.patient.streetAddress; + kitUploadInfo.city = user.patient.city; + kitUploadInfo.postalCode = user.patient.zip; + kitUploadInfo.state = user.patient.state.abbreviation; + kitUploadInfo.country = user.patient.country.abbreviation; + + //Upload a Blood & RNA kit + const kitUploadPage = await navigation.selectFromSamples(SamplesNavEnum.KIT_UPLOAD); + await kitUploadPage.waitForLoad(); + await kitUploadPage.assertPageTitle(); + await kitUploadPage.assertDisplayedKitTypes(expectedKitTypes); + await kitUploadPage.selectKitType(kitType); + await kitUploadPage.assertBrowseBtn(); + await kitUploadPage.assertUploadKitsBtn(); + await kitUploadPage.assertInstructionSnapshot(); + await kitUploadPage.uploadFile(kitType, [kitUploadInfo], study, testResultDirectory); + + //Go to Kits w/o Label to extract a shipping ID + await navigation.selectFromSamples(SamplesNavEnum.KITS_WITHOUT_LABELS); + await kitsWithoutLabelPage.waitForLoad(); + await kitsWithoutLabelPage.selectKitType(kitType); + await kitsWithoutLabelPage.assertCreateLabelsBtn(); + await kitsWithoutLabelPage.assertReloadKitListBtn(); + await kitsWithoutLabelPage.assertTableHeader(); + await kitsWithoutLabelPage.assertPageTitle(); + + await kitsWithoutLabelPage.search(KitsColumnsEnum.SHORT_ID, simpleShortId); + const shippingID = (await kitsWithoutLabelPage.getData(KitsColumnsEnum.SHIPPING_ID)).trim(); + + //Tracking scan + const labelNumber = crypto.randomUUID().toString().substring(0, 10); + const kitLabel = `RGP_${labelNumber}`; + const trackingScanPage = await navigation.selectFromSamples(SamplesNavEnum.TRACKING_SCAN); + await trackingScanPage.assertPageTitle(); + const trackingLabel = `tracking-${crypto.randomUUID().toString().substring(0, 10)}`; + await trackingScanPage.fillScanPairs([trackingLabel, kitLabel]); + await trackingScanPage.save(); + + //RGP final scan page - RNA labels must have the prefix 'RNA' (all caps) + const finalScanPage = await navigation.selectFromSamples(SamplesNavEnum.RGP_FINAL_SCAN); + const rnaNumber = crypto.randomUUID().toString().substring(0, 10); + const rnaLabel = `RNA${rnaNumber}`; + await finalScanPage.assertPageTitle(); + await finalScanPage.fillScanTrio(kitLabel, rnaLabel, shippingID, 1); + await finalScanPage.save(); + + //Kits Sent Page + const kitsSentPage = await navigation.selectFromSamples(SamplesNavEnum.SENT); + await kitsSentPage.waitForLoad(); + await kitsSentPage.assertPageTitle(); + await kitsSentPage.assertDisplayedKitTypes(expectedKitTypes); + await kitsSentPage.selectKitType(kitType); + + //Check for the sent blood kit + await kitsSentPage.search(KitsColumnsEnum.MF_CODE, kitLabel); + await kitsSentPage.assertDisplayedRowsCount(1); + + //Check for the sent RNA kit + await kitsSentPage.search(KitsColumnsEnum.MF_CODE, rnaLabel); + await kitsSentPage.assertDisplayedRowsCount(1); + + //Kits Received Page + const kitsReceivedPage = await navigation.selectFromSamples(SamplesNavEnum.RECEIVED); + await kitsReceivedPage.waitForLoad(); + await kitsReceivedPage.assertPageTitle(); + await kitsReceivedPage.kitReceivedRequest(kitLabel); //Mark the blood kit as received + await kitsReceivedPage.kitReceivedRequest(rnaLabel); //Mark the RNA kit as received + await kitsReceivedPage.assertDisplayedKitTypes(expectedKitTypes); + await kitsReceivedPage.selectKitType(kitType); + + //Check for the received blood kit + await kitsReceivedPage.search(KitsColumnsEnum.MF_CODE, kitLabel); + await kitsReceivedPage.assertDisplayedRowsCount(1); + + //Check for the received RNA kit + await kitsReceivedPage.search(KitsColumnsEnum.MF_CODE, rnaLabel); + await kitsReceivedPage.assertDisplayedRowsCount(1); + }); +}); diff --git a/playwright-e2e/tests/dsm/kitUploadFlow/blood-and-rna-kit-upload-flow.spec.ts-snapshots/upload-instructions-chromium-darwin.png b/playwright-e2e/tests/dsm/kitUploadFlow/blood-and-rna-kit-upload-flow.spec.ts-snapshots/upload-instructions-chromium-darwin.png new file mode 100644 index 0000000000..98b3f44eb9 Binary files /dev/null and b/playwright-e2e/tests/dsm/kitUploadFlow/blood-and-rna-kit-upload-flow.spec.ts-snapshots/upload-instructions-chromium-darwin.png differ diff --git a/playwright-e2e/utils/faker-utils.ts b/playwright-e2e/utils/faker-utils.ts index 99ceb81ca3..2274818550 100644 --- a/playwright-e2e/utils/faker-utils.ts +++ b/playwright-e2e/utils/faker-utils.ts @@ -46,3 +46,17 @@ export const saveParticipantGuid = (guid: string) => { user.patient.participantGuid = guid; }; +/** + * Takes a short id that is presumed to have the study in it e.g. RGP_1234_56 and + * returns the short id without the study name prefix e.g. 1234_56 + * @param shortId the short id + * @param studyName the study name/alias used in the short id e.g. RGP + * @returns simplified short id + */ +export const simplifyShortID = (shortId: string, studyName: string): string => { + const shortIdParts = shortId.split(`${studyName}_`); // Use 'RGP_' to determine where to split + const rgpPrefix = shortIdParts[0]; //RGP_ prefix + const subjectID = shortIdParts[1]; //The subject id to be used as short id + const simplifiedShortID = subjectID; + return simplifiedShortID; +}