From 807818f14d82462f065b29657cff4f27b88302ec Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sat, 1 Jun 2024 14:59:23 -0700 Subject: [PATCH] working cerner and aetna tests --- js/e2e/src/aetna_test.ts | 28 ++++++++ js/e2e/src/cerner_test.ts | 40 +++++++++++ js/e2e/src/epic_legacy_test.ts | 124 +++++++++++++++++++++++++++++++++ js/e2e/src/local_test.ts | 38 +++++----- js/e2e/src/sample_test.ts | 74 ++++++++++---------- js/e2e/utils.ts | 18 +++++ js/package.json | 4 +- js/playwright.config.ts | 40 +++++------ js/src/utils/uuid.ts | 4 +- js/tsconfig.json | 2 +- 10 files changed, 291 insertions(+), 81 deletions(-) create mode 100644 js/e2e/src/aetna_test.ts create mode 100644 js/e2e/src/cerner_test.ts create mode 100644 js/e2e/src/epic_legacy_test.ts create mode 100644 js/e2e/utils.ts diff --git a/js/e2e/src/aetna_test.ts b/js/e2e/src/aetna_test.ts new file mode 100644 index 000000000..6555be626 --- /dev/null +++ b/js/e2e/src/aetna_test.ts @@ -0,0 +1,28 @@ +import { test, expect } from "@playwright/test"; +import {getEndpointDefinition} from '../utils'; +import {generateSourceAuthorizeUrl} from '../../src/connect/authorization-url'; + +test("Aetna Login Flow", async ({page}) => { + + //get the Cerner Sandbox endpoint definition + let endpointDefinition = await getEndpointDefinition('ac8308d1-90de-4994-bb3d-fe404832714c') + let authorizeData = await generateSourceAuthorizeUrl(endpointDefinition) + + // authorizeData.sourceState + console.log(authorizeData.url.toString()) + + // Start login flow by clicking on button with text "Login to MyChart" + await page.goto(authorizeData.url.toString()); + + // We are on login page + await page.waitForSelector("text=Welcome to Aetna"); + // await expect(page).toHaveTitle("Cerner Health - Sign In"); + await page.click("label[for='username']", { force: true }); + await page.keyboard.type("aetnaTestUser3 "); + await page.click("label[for='password']", { force: true }); + await page.keyboard.type("FHIRdemo2020"); + await page.click("#loginButton"); + + // If successful, Fasten Lighthouse page should now be visible + await page.waitForSelector("text=Your account has been securely connected to FASTEN."); +}); diff --git a/js/e2e/src/cerner_test.ts b/js/e2e/src/cerner_test.ts new file mode 100644 index 000000000..a2b134a06 --- /dev/null +++ b/js/e2e/src/cerner_test.ts @@ -0,0 +1,40 @@ +import { test, expect } from "@playwright/test"; +import {getEndpointDefinition} from '../utils'; +import {generateSourceAuthorizeUrl} from '../../src/connect/authorization-url'; + +test("Cerner Login Flow", async ({page}) => { + test.skip() + //get the Cerner Sandbox endpoint definition + let endpointDefinition = await getEndpointDefinition('3290e5d7-978e-42ad-b661-1cf8a01a989c') + let authorizeData = await generateSourceAuthorizeUrl(endpointDefinition) + + // authorizeData.sourceState + console.log(authorizeData.url.toString()) + + // Start login flow by clicking on button with text "Login to MyChart" + await page.goto(authorizeData.url.toString()); + + // We are on login page + await page.waitForSelector("text=FhirPlay Non-Prod"); + await expect(page).toHaveTitle("Cerner Health - Sign In"); + await page.click("label[for='id_login_username']", { force: true }); + await page.keyboard.type("nancysmart"); + await page.click("label[for='id_login_password']", { force: true }); + await page.keyboard.type("Cerner01"); + await page.click("#signin"); + + // We have logged in + await page.waitForSelector("text=Warning: Unknown app"); + await expect(page).toHaveTitle("Authorization Needed"); + await page.click('#proceedButton'); + + // We are on the Select Patient page. + await page.waitForSelector("text=SMART II, NANCY (Self, 33)"); + await expect(page).toHaveTitle("Authorization Needed"); + await page.click("label[for='12724066']", { force: true, delay: 500 }); + await page.click("#allowButton"); + + + // If successful, Fasten Lighthouse page should now be visible + await page.waitForSelector("text=Your account has been securely connected to FASTEN."); +}); diff --git a/js/e2e/src/epic_legacy_test.ts b/js/e2e/src/epic_legacy_test.ts new file mode 100644 index 000000000..66bea5e0b --- /dev/null +++ b/js/e2e/src/epic_legacy_test.ts @@ -0,0 +1,124 @@ +import { test, expect } from "@playwright/test"; +import {getEndpointDefinition} from '../utils'; +import {generateSourceAuthorizeUrl} from '../../src/connect/authorization-url'; + +test("Epic OAuth2 Legacy Login Flow", async ({page}) => { + test.skip() + + //get the Epic Sandbox endpoint definition + let endpointDefinition = await getEndpointDefinition('fc94bfc7-684d-4e4d-aa6e-ceec01c21c81') + let authorizeData = await generateSourceAuthorizeUrl(endpointDefinition) + + // authorizeData.sourceState + console.log(authorizeData.url.toString()) + + // Start login flow by clicking on button with text "Login to MyChart" + await page.goto(authorizeData.url.toString()); + + // We are on MyChart login page + await page.waitForSelector("text=MyChart Username"); + await expect(page).toHaveTitle("MyChart - Login Page"); + await page.click("label[for='Login']", { force: true }); + await page.keyboard.type("fhirderrick"); + await page.click("label[for='Password']", { force: true }); + await page.keyboard.type("epicepic1"); + await page.click("text=Sign In"); + + // We have logged in to MyChart + await page.waitForSelector("text=Fasten Health has said that it:"); + await page.locator('text=Continue') //wait for continue button + await expect(page).toHaveTitle("MyChart - Are you sure?"); + await page.getByTitle("Continue to next page").click(); + + + // We are on the MyChart authorize page. Authorize our app for 1 hour. + await page.waitForSelector("text=What would you like to share?"); + await expect(page).toHaveTitle("MyChart - Are you sure?"); + // await page.click('text=3 months', { force: true, delay: 1000 }); + await page.click("text=Allow access", { force: true, delay: 500 }); + + // MyChart has granted access, redirecting back to app from MyChart + await page.waitForSelector("text=Epic FHIR Dynamic Registration Redirect"); + + // Should auto redirect if successful, but playwright Chrome seems to have issues so we'll manually click if needed + try { + await page.click("text=Back to main page", { force: true, delay: 5000 }); + } catch (e) {} + + // If successful, Dynamic Client Registration Data should now be visible + await page.waitForSelector("text=Dynamic Client Registration Data"); + + + + // await expect(page).toHaveTitle("MyChart - Are you sure?"); + // await page.getByTitle("Continue to next page").click({ + // force: true, + // delay: 1000, + // }); + // + // // We are on the MyChart authorize page. Authorize our app for 1 hour. + // await page.waitForSelector("text=What would you like to share?"); + // await expect(page).toHaveTitle("MyChart - Are you sure?"); + // // await page.click('text=3 months', { force: true, delay: 1000 }); + // await page.click("text=Allow access", { force: true, delay: 500 }); + // + // // Should auto redirect if successful, but playwright Chrome seems to have issues so we'll manually click if needed + // try { + // await page.click("text=Back to main page", { force: true, delay: 5000 }); + // } catch (e) {} + // + // // MyChart has granted access, redirecting back to app from MyChart + // await page.waitForSelector("text=Your account has been securely connected to FASTEN.") + // await expect((new URL(page.url())).searchParams.get("code")).toBeTruthy() +}); +// +// const expirationOptions = ["1 hour", "1 day", "1 week", "1 month", "3 months"]; +// for (const timeOption of expirationOptions) { +// test(`Epic OAuth2 Login Flow with Dynamic Registration Works with '${timeOption}' Expiration Option Selected`, async ({ +// page, +// }) => { +// await page.goto("http://localhost:5173/"); +// +// // Before we log in, there should be no dynamic client data +// await page.waitForSelector( +// "text=After you log in, your dynamic client data will show here" +// ); +// +// // Start login flow by clicking on button with text "Login to MyChart" +// await page.click("text=Login to MyChart"); +// +// // We are on MyChart login page +// await page.waitForSelector("text=MyChart Username"); +// await expect(page).toHaveTitle("MyChart - Login Page"); +// await page.click("label[for='Login']", { force: true }); +// await page.keyboard.type("fhirderrick"); +// await page.click("label[for='Password']", { force: true }); +// await page.keyboard.type("epicepic1"); +// await page.click("text=Sign In"); +// +// // We have logged in to MyChart +// await page.waitForSelector("text=Not a Company at all has said that it:"); +// await expect(page).toHaveTitle("MyChart - Are you sure?"); +// await page.getByTitle("Continue to next page").click({ +// force: true, +// delay: 1000, +// }); +// +// // We are on the MyChart authorize page. Authorize our app for 1 hour. +// await page.waitForSelector("text=What would you like to share?"); +// await expect(page).toHaveTitle("MyChart - Are you sure?"); +// await page.click(`text=${timeOption}`, { force: true, delay: 1000 }); +// await page.click("text=Allow access", { force: true, delay: 500 }); +// +// // MyChart has granted access, redirecting back to app from MyChart +// await page.waitForSelector("text=Epic FHIR Dynamic Registration Redirect"); +// +// // Should auto redirect if successful, but playwright Chrome seems to have issues so we'll manually click if needed +// try { +// await page.click("text=Back to main page", { force: true, delay: 5000 }); +// } catch (e) {} +// +// // If successful, Dynamic Client Registration Data should now be visible +// await page.waitForSelector("text=Dynamic Client Registration Data"); +// }); +// } diff --git a/js/e2e/src/local_test.ts b/js/e2e/src/local_test.ts index 7d4fe0303..6ddec52d9 100644 --- a/js/e2e/src/local_test.ts +++ b/js/e2e/src/local_test.ts @@ -1,22 +1,22 @@ // @ts-check import { test, expect } from'@playwright/test'; -test('Local Testing', async ({ page },testInfo) => { - - try{ - - await page.evaluate(_ => {},`browserstack_executor: ${JSON.stringify({action: "setSessionName", arguments: {name:testInfo.project.name}})}`); - - await page.waitForTimeout(5000); - - await page.goto('https://www.example.com/'); - - await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'passed',reason: 'Local success'}})}`); - -} catch (e) { - console.log(e); - await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'failed',reason: 'Local fail'}})}`); - -} - -}); +// test('Local Testing', async ({ page },testInfo) => { +// +// try{ +// +// await page.evaluate(_ => {},`browserstack_executor: ${JSON.stringify({action: "setSessionName", arguments: {name:testInfo.project.name}})}`); +// +// await page.waitForTimeout(5000); +// +// await page.goto('https://www.example.com/'); +// +// await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'passed',reason: 'Local success'}})}`); +// +// } catch (e) { +// console.log(e); +// await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'failed',reason: 'Local fail'}})}`); +// +// } +// +// }); diff --git a/js/e2e/src/sample_test.ts b/js/e2e/src/sample_test.ts index 057876519..2bb5b939e 100644 --- a/js/e2e/src/sample_test.ts +++ b/js/e2e/src/sample_test.ts @@ -1,40 +1,40 @@ // @ts-check import { test, expect } from'@playwright/test'; -test('BstackDemo Add to cart', async ({ page },testInfo) => { - -try{ - - await page.evaluate(_ => {},`browserstack_executor: ${JSON.stringify({action: "setSessionName", arguments: {name:testInfo.project.name}})}`); - await page.waitForTimeout(5000); - - await page.goto('https://www.bstackdemo.com/',{ waitUntil: 'networkidle' }); - await page.locator('[id="\\32 "]').getByText('Add to cart').click(); - await page.getByText('Checkout').click(); - await page.locator('#username svg').click(); - await page.locator('#react-select-2-option-0-0').click(); - await page.locator('#password svg').click(); - await page.locator('#react-select-3-option-0-0').click(); - await page.getByRole('button', { name: 'Log In' }).click(); - await page.getByLabel('First Name').click(); - await page.getByLabel('First Name').fill('SampleFirst'); - await page.getByLabel('Last Name').click(); - await page.getByLabel('Last Name').fill('sampleLast'); - await page.getByLabel('Address').click(); - await page.getByLabel('Address').fill('sampleAddress'); - await page.getByLabel('State/Province').click(); - await page.getByLabel('State/Province').fill('SampleState'); - await page.getByLabel('Postal Code').click(); - await page.getByLabel('Postal Code').fill('123456'); - await page.getByRole('button', { name: 'Submit' }).click(); - await page.getByRole('button', { name: 'Continue Shopping »' }).click(); - - await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'passed',reason: 'Product added to cart'}})}`); - -} catch (e) { - console.log(e); - await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'failed',reason: 'Test failed'}})}`); - -} - -}); +// test('BstackDemo Add to cart', async ({ page },testInfo) => { +// +// try{ +// +// await page.evaluate(_ => {},`browserstack_executor: ${JSON.stringify({action: "setSessionName", arguments: {name:testInfo.project.name}})}`); +// await page.waitForTimeout(5000); +// +// await page.goto('https://www.bstackdemo.com/',{ waitUntil: 'networkidle' }); +// await page.locator('[id="\\32 "]').getByText('Add to cart').click(); +// await page.getByText('Checkout').click(); +// await page.locator('#username svg').click(); +// await page.locator('#react-select-2-option-0-0').click(); +// await page.locator('#password svg').click(); +// await page.locator('#react-select-3-option-0-0').click(); +// await page.getByRole('button', { name: 'Log In' }).click(); +// await page.getByLabel('First Name').click(); +// await page.getByLabel('First Name').fill('SampleFirst'); +// await page.getByLabel('Last Name').click(); +// await page.getByLabel('Last Name').fill('sampleLast'); +// await page.getByLabel('Address').click(); +// await page.getByLabel('Address').fill('sampleAddress'); +// await page.getByLabel('State/Province').click(); +// await page.getByLabel('State/Province').fill('SampleState'); +// await page.getByLabel('Postal Code').click(); +// await page.getByLabel('Postal Code').fill('123456'); +// await page.getByRole('button', { name: 'Submit' }).click(); +// await page.getByRole('button', { name: 'Continue Shopping »' }).click(); +// +// await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'passed',reason: 'Product added to cart'}})}`); +// +// } catch (e) { +// console.log(e); +// await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'failed',reason: 'Test failed'}})}`); +// +// } +// +// }); diff --git a/js/e2e/utils.ts b/js/e2e/utils.ts new file mode 100644 index 000000000..ac81ecf9f --- /dev/null +++ b/js/e2e/utils.ts @@ -0,0 +1,18 @@ +import {LighthouseEndpointDefinition} from '../src'; + +export const lighthouseEndpointLookup = { + 'sandbox': 'https://lighthouse.fastenhealth.com/sandbox/', + 'prod': 'https://lighthouse.fastenhealth.com/v1/' +} + +export async function getEndpointDefinition(endpoint_id: string): Promise { + + let lighthouseEndpoint = lighthouseEndpointLookup['sandbox'] + + return await fetch( lighthouseEndpoint + 'connect/' + endpoint_id) + .then(resp => resp.json()) + .then(response => { + console.log(response) + return response.data as LighthouseEndpointDefinition + }) +} diff --git a/js/package.json b/js/package.json index 92adbcd9b..479b1d720 100644 --- a/js/package.json +++ b/js/package.json @@ -6,12 +6,14 @@ "types": "index.d.ts", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "e2e": "npx playwright test" + "e2e": "npx playwright test --headed", + "e2e-debug": "npx playwright test --headed --debug" }, "author": "Jason Kulatunga ", "dependencies": { "@panva/oauth4webapi": "1.2.0" }, + "type": "module", "publishConfig": { "access": "public" }, diff --git a/js/playwright.config.ts b/js/playwright.config.ts index 9c19c1d5d..71856bac3 100644 --- a/js/playwright.config.ts +++ b/js/playwright.config.ts @@ -53,26 +53,26 @@ export default { }, /* Configure projects for major browsers */ - projects: [ - { - name: 'chrome@latest:Windows 11', - use: { - connectOptions: { wsEndpoint: getCdpEndpoint('chrome@latest:Windows 11','test1') }, - }, - } - // { - // name: 'playwright-webkit@latest:OSX Ventura', - // use: { - // connectOptions: { wsEndpoint: getCdpEndpoint('playwright-webkit@latest:OSX Ventura', 'test2') } - // }, - // }, - // { - // name: 'playwright-firefox:Windows 11', - // use: { - // connectOptions: { wsEndpoint: getCdpEndpoint('playwright-firefox:Windows 11', 'test3') } - // }, - // } - ], + // projects: [ + // // { + // // name: 'chrome@latest:Windows 11', + // // use: { + // // connectOptions: { wsEndpoint: getCdpEndpoint('chrome@latest:Windows 11','test1') }, + // // }, + // // } + // // { + // // name: 'playwright-webkit@latest:OSX Ventura', + // // use: { + // // connectOptions: { wsEndpoint: getCdpEndpoint('playwright-webkit@latest:OSX Ventura', 'test2') } + // // }, + // // }, + // { + // name: 'playwright-firefox:Windows 11', + // use: { + // connectOptions: { wsEndpoint: getCdpEndpoint('playwright-firefox:Windows 11', 'test3') } + // }, + // } + // ], /* Folder for test artifacts such as screenshots, videos, traces, etc. */ // outputDir: 'test-results/', diff --git a/js/src/utils/uuid.ts b/js/src/utils/uuid.ts index ff071a20e..ded67df38 100644 --- a/js/src/utils/uuid.ts +++ b/js/src/utils/uuid.ts @@ -1,6 +1,4 @@ - -export function uuidV4(){ - // @ts-ignore +export function uuidV4(): string { return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) ); diff --git a/js/tsconfig.json b/js/tsconfig.json index 0c0c10ec2..5fe5b4470 100644 --- a/js/tsconfig.json +++ b/js/tsconfig.json @@ -8,5 +8,5 @@ }, "include": [ "src/**/*" - ] + ], }