Skip to content

Commit

Permalink
Merge pull request #46 from fastenhealth/browserstack_tests
Browse files Browse the repository at this point in the history
working tests.
  • Loading branch information
AnalogJ committed Jun 5, 2024
2 parents 108e01a + 8483d49 commit d72e70c
Show file tree
Hide file tree
Showing 25 changed files with 1,102 additions and 5 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,7 @@

js/dist
js/node_modules

js/local.log
js/playwright-report
js/test-results
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,10 @@ ones that Fasten supports
| [clients/internal/source](./clients/internal/source) | Automatically created OAuth clients for accessing production data from various healthcare institutions. Usually inherit from Platform clients |
| [definitions](./definitions/) | Automatically created definition files. These files are generated from files created by `fasten-sources-gen` and are used by Fasten Lighthouse. |



# References

## NPM Library
- https://www.tsmean.com/articles/learn-typescript/typescript-module-compiler-option/
-
52 changes: 52 additions & 0 deletions js/e2e/browserstack.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import * as cp from 'child_process';
const clientPlaywrightVersion = cp
.execSync('npx playwright --version')
.toString()
.trim()
.split(' ')[1];
import * as BrowserStackLocal from'browserstack-local';
import * as util from'util';
import process from 'process';

// BrowserStack Specific Capabilities.
// Set 'browserstack.local:true For Local testing
const caps = {
browser: 'chrome',
os: 'osx',
os_version: 'catalina',
name: 'My first playwright test',
build: 'playwright-build',
'browserstack.username': process.env.BROWSERSTACK_USERNAME || 'USERNAME',
'browserstack.accessKey': process.env.BROWSERSTACK_ACCESS_KEY || 'ACCESSKEY',
'browserstack.local': process.env.BROWSERSTACK_LOCAL || true,
'client.playwrightVersion': clientPlaywrightVersion,
};

export const bsLocal = new BrowserStackLocal.Local();

// replace YOUR_ACCESS_KEY with your key. You can also set an environment variable - "BROWSERSTACK_ACCESS_KEY".
export const BS_LOCAL_ARGS = {
key: process.env.BROWSERSTACK_ACCESS_KEY || 'ACCESSKEY',
};

// Patching the capabilities dynamically according to the project name.
const patchCaps = (name, title) => {
let combination = name.split(/@browserstack/)[0];
let [browerCaps, osCaps] = combination.split(/:/);
let [browser, browser_version] = browerCaps.split(/@/);
let osCapsSplit = osCaps.split(/ /);
let os = osCapsSplit.shift();
let os_version = osCapsSplit.join(' ');
caps.browser = browser ? browser : 'chrome';
caps.os_version = browser_version ? browser_version : 'latest';
caps.os = os ? os : 'osx';
caps.os_version = os_version ? os_version : 'catalina';
caps.name = title;
};

export function getCdpEndpoint(name, title){
patchCaps(name, title)
const cdpUrl = `wss:https://cdp.browserstack.com/playwright?caps=${encodeURIComponent(JSON.stringify(caps))}`
console.log(`--> ${cdpUrl}`)
return cdpUrl;
}
25 changes: 25 additions & 0 deletions js/e2e/global-setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// global-setup.js
import { bsLocal, BS_LOCAL_ARGS } from './browserstack.config';
import { promisify } from 'util';
const sleep = promisify(setTimeout);
const redColour = '\x1b[31m';
const whiteColour = '\x1b[0m';

export default async function setup() {
console.log('Starting BrowserStackLocal ...');
// Starts the Local instance with the required arguments
let localResponseReceived = false;
bsLocal.start(BS_LOCAL_ARGS, (err) => {
if (err) {
console.error(
`${redColour}Error starting BrowserStackLocal${whiteColour}`, err
);
} else {
console.log('BrowserStackLocal Started');
}
localResponseReceived = true;
});
while (!localResponseReceived) {
await sleep(1000);
}
};
18 changes: 18 additions & 0 deletions js/e2e/global-teardown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// global-teardown.js
import { bsLocal } from './browserstack.config';
import { promisify } from'util';
const sleep = promisify(setTimeout);
export default async function teardown(){
// Stop the Local instance after your test run is completed, i.e after driver.quit
let localStopped = false;

if (bsLocal && bsLocal.isRunning()) {
bsLocal.stop(() => {
localStopped = true;
console.log('Stopped BrowserStackLocal');
});
while (!localStopped) {
await sleep(1000);
}
}
}
32 changes: 32 additions & 0 deletions js/e2e/protractor.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// @ts-check
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts

const { SpecReporter } = require('jasmine-spec-reporter');

/**
* @type { import("protractor").Config }
*/
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./src/**/*.e2e-spec.ts'
],
capabilities: {
browserName: 'chrome'
},
directConnect: true,
baseUrl: 'http:https://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.json')
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};
37 changes: 37 additions & 0 deletions js/e2e/src/aetna_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { test, expect } from "@playwright/test";
import {getEndpointDefinition} from '../utils';
import {generateSourceAuthorizeUrl} from '../../src/connect/authorization-url';

test("Aetna Login Flow", async ({page}, testInfo) => {
try {
await page.evaluate(_ => {},`browserstack_executor: ${JSON.stringify({action: "setSessionName", arguments: {name:testInfo.title}})}`);
await page.waitForTimeout(5000);

//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.");

await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'passed',reason: 'Authentication Successful'}})}`);
} catch (e) {
console.log(e);
await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'failed',reason: 'Test failed'}})}`);
}
});
41 changes: 41 additions & 0 deletions js/e2e/src/allscripts_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { test, expect } from "@playwright/test";
import {getEndpointDefinition} from '../utils';
import {generateSourceAuthorizeUrl} from '../../src/connect/authorization-url';

test("Allscripts Login Flow", async ({page}, testInfo) => {
try{
await page.evaluate(_ => {},`browserstack_executor: ${JSON.stringify({action: "setSessionName", arguments: {name:testInfo.title}})}`);
await page.waitForTimeout(5000);

//get the Allscripts - Veradigm Sandbox endpoint definition
let endpointDefinition = await getEndpointDefinition('7682675b-8247-4fda-b2cd-048bfeafc8af')
let authorizeData = await generateSourceAuthorizeUrl(endpointDefinition)

// authorizeData.sourceState
console.log(authorizeData.url.toString())

await page.goto(authorizeData.url.toString());

// We are on login page
await page.waitForSelector("text=Allscripts Health Connect Core");
await expect(page).toHaveTitle("Allscripts FHIR Authorization - ");
await page.focus("#username");
await page.keyboard.type("[email protected]");
await page.focus("#passwordEntered");
await page.keyboard.type("Allscripts#1");
await page.click("#local-login");

// We have logged in
await page.waitForSelector("text=Uncheck the permissions you do not wish to grant.");
await expect(page).toHaveTitle("Allscripts FHIR Authorization - ");
await page.click('button[value="yes"]');

// If successful, Fasten Lighthouse page should now be visible
await page.waitForSelector("text=Your account has been securely connected to FASTEN.");

await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'passed',reason: 'Authentication Successful'}})}`);
} catch (e) {
console.log(e);
await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'failed',reason: 'Test failed'}})}`);
}
});
41 changes: 41 additions & 0 deletions js/e2e/src/athena_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { test, expect } from "@playwright/test";
import {getEndpointDefinition} from '../utils';
import {generateSourceAuthorizeUrl} from '../../src/connect/authorization-url';

test("Athena Login Flow", async ({page}, testInfo) => {
try {
await page.evaluate(_ => {},`browserstack_executor: ${JSON.stringify({action: "setSessionName", arguments: {name:testInfo.title}})}`);
await page.waitForTimeout(5000);
//get the Cerner Sandbox endpoint definition
let endpointDefinition = await getEndpointDefinition('950e9092-8ce7-4926-ad87-64616f00cb4c')
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=Fasten Health - preview");
await expect(page).toHaveTitle("Login");
await page.click("label[for='okta-signin-username']", { force: true });
await page.keyboard.type("[email protected]");
await page.click("label[for='okta-signin-password']", { force: true });
await page.keyboard.type("Password1");
await page.click("#okta-signin-submit");

// We have logged in
await page.waitForSelector("text=Select a health record");
await expect(page).toHaveTitle("Login");
await page.locator("text=Jake Medlock (you)").click();

// If successful, Fasten Lighthouse page should now be visible
await page.waitForSelector("text=Your account has been securely connected to FASTEN.");

await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'passed',reason: 'Authentication Successful'}})}`);
} catch (e) {
console.log(e);
await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'failed',reason: 'Test failed'}})}`);
}
});
41 changes: 41 additions & 0 deletions js/e2e/src/careevolution_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { test, expect } from "@playwright/test";
import {getEndpointDefinition} from '../utils';
import {generateSourceAuthorizeUrl} from '../../src/connect/authorization-url';

test("CareEvolution Login Flow", async ({page}, testInfo) => {
try {
await page.evaluate(_ => {},`browserstack_executor: ${JSON.stringify({action: "setSessionName", arguments: {name:testInfo.title}})}`);
await page.waitForTimeout(5000);

//get the CareEvolution Sandbox endpoint definition
let endpointDefinition = await getEndpointDefinition('8b47cf7b-330e-4ede-9967-4caa7be623aa')
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("#login-button");
await page.focus("#Username");
await page.keyboard.type("CEPatient");
await page.focus("#Password");
await page.keyboard.type("CEPatient2018");
await page.click("#login-button");

// We have logged in
await page.waitForSelector("text=Whose record do you want to allow access to?");
// await expect(page).toHaveText("Authorization Request");
await page.locator("text=Fran Demoski (28)").click();
await page.click('input[value="Agree"]');

// If successful, Fasten Lighthouse page should now be visible
await page.waitForSelector("text=Your account has been securely connected to FASTEN.");
await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'passed',reason: 'Authentication Successful'}})}`);
} catch (e) {
console.log(e);
await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'failed',reason: 'Test failed'}})}`);
}
});
49 changes: 49 additions & 0 deletions js/e2e/src/cerner_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { test, expect } from "@playwright/test";
import {getEndpointDefinition} from '../utils';
import {generateSourceAuthorizeUrl} from '../../src/connect/authorization-url';

test("Cerner Login Flow", async ({page}, testInfo) => {
try {
await page.evaluate(_ => {},`browserstack_executor: ${JSON.stringify({action: "setSessionName", arguments: {name:testInfo.title}})}`);
await page.waitForTimeout(5000);

//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.");

await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'passed',reason: 'Authentication Successful'}})}`);
} catch (e) {
console.log(e);
await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'failed',reason: 'Test failed'}})}`);
}
});
Loading

0 comments on commit d72e70c

Please sign in to comment.