Skip to content

Commit 25617bb

Browse files
author
JAMES FUQIAN
committed
fix selenium tests
1 parent f4013b6 commit 25617bb

3 files changed

Lines changed: 69 additions & 70 deletions

File tree

README.md

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ Once you have Docker and Node installed and setup then do the following:
2626

2727
cp server/sample-bluebutton-config.json -> server/.bluebutton-config.json
2828

29+
or (if running a docker compose selenium tests)
30+
31+
cp server/sample-bluebutton-selenium-config.json -> server/.bluebutton-config.json
32+
2933
Make sure to replace the clientId and clientSecret variables within the config file with
3034
the ones you were provided, for your application, when you created your Blue Button Sandbox account.
3135

@@ -75,20 +79,6 @@ Both ways of starting the sample are running the sample in foreground, logging a
7579

7680
For client and server started separately in their command window, type Ctrl C respectively
7781

78-
## Run selenium tests in docker
79-
80-
Configure the remote target BB2 instance where the tested app is registered (as described above "Running the Back-end & Front-end")
81-
82-
Go to local repo base directory, from there run:
83-
84-
docker-compose -f docker-compose.selenium.yml up --abort-on-container-exit
85-
86-
Note: --abort-on-container-exit will abort client and server containers when selenium tests ends
87-
88-
## Visual trouble shoot
89-
90-
Install VNC viewer and point browser to http://localhost:5900 to monitor web UI interactions
91-
9282
## Error Responses and handling:
9383

9484
[See ErrorResponses.md](./ErrorResponses.md)

selenium_tests/src/test_node_sample.py

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
# Generated by Selenium IDE
21
import time
32
from selenium import webdriver
43
from selenium.webdriver.common.by import By
54
from selenium.webdriver.support import expected_conditions as EC
65
from selenium.webdriver.support.wait import WebDriverWait
76

7+
CSS_SEL_FE_ERR_MSG_CONTENT = "tbody .ds-c-table__cell--align-left:nth-child(2)"
8+
89

910
class TestNodeSampleApp():
1011
driver_ready = False
@@ -73,6 +74,13 @@ def _assert_EOB_table_records_present(self, cnt):
7374
elements = self._find_elem_xpath(xpath)
7475
assert len(elements) == cnt
7576

77+
def _assert_EOB_table_error_present(self):
78+
element = self._find_and_return(30,
79+
By.CSS_SELECTOR,
80+
CSS_SEL_FE_ERR_MSG_CONTENT)
81+
assert element is not None
82+
print(element.text)
83+
7684
def _input_user_and_passwd_and_login(self):
7785
self._find_and_sendkey(30, By.ID, "username-textbox", "BBUser10000")
7886
self._find_and_sendkey(30, By.ID, "password-textbox", "PW10000!")
@@ -85,6 +93,7 @@ def test_node_sample_app_grant_access(self):
8593
assert elem is not None
8694
self._input_user_and_passwd_and_login()
8795
self._find_and_click(30, By.ID, "approve")
96+
time.sleep(5)
8897
self._assert_EOB_table_header_present()
8998
self._assert_EOB_table_records_present(10)
9099

@@ -97,6 +106,7 @@ def test_node_sample_app_grant_access_no_demographic(self):
97106
# select radio button "No Demographic Data"
98107
self._find_and_click(30, By.CSS_SELECTOR, "label:nth-child(5)")
99108
self._find_and_click(30, By.ID, "approve")
109+
time.sleep(5)
100110
self._assert_EOB_table_header_present()
101111
self._assert_EOB_table_records_present(10)
102112

@@ -107,5 +117,27 @@ def test_node_sample_app_deny_access(self):
107117
assert elem is not None
108118
self._input_user_and_passwd_and_login()
109119
self._find_and_click(30, By.ID, "deny")
110-
self._assert_EOB_table_header_present()
111-
self._assert_EOB_table_records_present(0)
120+
time.sleep(5)
121+
self._assert_EOB_table_error_present()
122+
123+
def test_node_sample_app_grant_followed_by_deny_access(self):
124+
'''
125+
this is to verify that the cached result from previous
126+
authorized eob query is clean up (should not see cached claims)
127+
'''
128+
self.driver.get("http://client:3000/")
129+
self.driver.set_window_size(1500, 1800)
130+
elem = self._find_and_click(30, By.ID, "auth_btn")
131+
assert elem is not None
132+
self._input_user_and_passwd_and_login()
133+
self._find_and_click(30, By.ID, "approve")
134+
time.sleep(5)
135+
self._assert_EOB_table_records_present(10)
136+
# go again
137+
elem = self._find_and_click(30, By.ID, "auth_btn")
138+
assert elem is not None
139+
self._input_user_and_passwd_and_login()
140+
self._find_and_click(30, By.ID, "deny")
141+
time.sleep(5)
142+
# should see error message
143+
self._assert_EOB_table_error_present()

server/index.ts

Lines changed: 30 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ interface User {
77
errors?: string[]
88
}
99

10+
const BENE_DENIED_ACCESS = "access_denied"
11+
const FE_MSG_ACCESS_DENIED = "Beneficiary denied app access to their data"
12+
const ERR_QUERY_EOB = "Error when querying the patient's EOB!"
13+
const ERR_MISSING_AUTH_CODE = "Response was missing access code!"
14+
const ERR_MISSING_STATE = "State is required when using PKCE"
15+
1016
const app = express();
1117

1218
const bb = new BlueButton();
@@ -20,6 +26,12 @@ const authData = bb.generateAuthData();
2026
const loggedInUser: User = {
2127
};
2228

29+
// helper to clean up cached eob data
30+
function clearBB2Data() {
31+
loggedInUser.authToken = undefined;
32+
loggedInUser.eobData = {};
33+
}
34+
2335
// AuthorizationToken holds access grant info:
2436
// access token, expire in, expire at, token type, scope, refreh token, etc.
2537
// it is associated with current logged in user in real app,
@@ -35,13 +47,20 @@ app.get("/api/authorize/authurl", (req: Request, res: Response) => {
3547
// auth flow: oauth2 call back
3648
app.get("/api/bluebutton/callback", async (req: Request, res: Response) => {
3749
if (typeof req.query.error === "string") {
38-
res.json({ message: req.query.error });
50+
// clear all cached claims eob data since the bene has denied access
51+
// for the application
52+
clearBB2Data();
53+
let errMsg = req.query.error;
54+
if (req.query.error === BENE_DENIED_ACCESS) {
55+
errMsg = FE_MSG_ACCESS_DENIED;
56+
}
57+
loggedInUser.eobData = {"message": errMsg};
58+
process.stdout.write(errMsg + '\n');
3959
} else {
4060
if (
4161
typeof req.query.code === "string" &&
4262
typeof req.query.state === "string"
4363
) {
44-
// let results;
4564
try {
4665
authToken = await bb.getAuthorizationToken(
4766
authData,
@@ -54,64 +73,22 @@ app.get("/api/bluebutton/callback", async (req: Request, res: Response) => {
5473
// access token can expire, SDK automatically refresh access token when that happens.
5574
const eobResults = await bb.getExplanationOfBenefitData(authToken);
5675
authToken = eobResults.token; // in case authToken got refreshed during fhir call
57-
// const patientResults = await bb.getPatientData(authToken);
58-
// authToken = patientResults.token;
59-
// const coverageResults = await bb.getCoverageData(authToken);
60-
// authToken = coverageResults.token;
61-
// const profileResults = await bb.getProfileData(authToken);
62-
// authToken = profileResults.token;
63-
64-
// nav pages if needed for eob, patient, coverage
65-
// client code can preemptively refresh tokens by calling refreshAuthToken(authToken)
66-
// console.log(
67-
// "============= preemptively do oauth token refresh before fetch EOB ================="
68-
// );
69-
70-
// console.log("============= authToken =================");
71-
72-
// authToken = await bb.refreshAuthToken(authToken);
73-
74-
// console.log(authToken);
7576

7677
loggedInUser.authToken = authToken;
77-
// console.log("============= EOB PAGES =================");
7878

7979
loggedInUser.eobData = eobResults.response?.data;
80-
// const eobs = await bb.getPages(eobbundle, authToken);
81-
// for (let i = 0; i < eobs.pages.length; i++) {
82-
// fs.writeFileSync(`eob_p${i}.json`, JSON.stringify(eobs.pages[i]));
83-
// }
84-
85-
// authToken = eobs.token;
86-
87-
// console.log("=============PATIENT=================");
88-
// const ptbundle = patientResults.response?.data;
89-
// const pts = await bb.getPages(ptbundle, authToken);
90-
// authToken = pts.token;
91-
92-
// console.log("=============COVERAGE=================");
93-
// const coveragebundle = coverageResults.response?.data;
94-
// const coverages = await bb.getPages(coveragebundle, authToken);
95-
// authToken = coverages.token;
96-
97-
// console.log("=============PROFILE=================");
98-
// const pfbundle = profileResults.response?.data;
99-
// const pfs = await bb.getPages(pfbundle, authToken);
100-
// authToken = pfs.token;
101-
102-
// results = {
103-
// eob: eobs.pages,
104-
// patient: pts.pages,
105-
// coverage: coverages.pages,
106-
// profile: pfs.pages,
107-
// };
10880
} catch (e) {
109-
console.log(e);
81+
loggedInUser.eobData = {};
82+
process.stdout.write(ERR_QUERY_EOB + '\n');
83+
process.stdout.write("Exception: " + e + '\n');
11084
}
111-
// res.json(results);
11285
} else {
113-
//res.json({ message: "Missing AC in callback." });
114-
console.log("Missing AC in callback.");
86+
clearBB2Data();
87+
process.stdout.write(ERR_MISSING_AUTH_CODE + '\n');
88+
process.stdout.write("OR" + '\n');
89+
process.stdout.write(ERR_MISSING_STATE + '\n');
90+
process.stdout.write("AUTH CODE: " + req.query.code + '\n');
91+
process.stdout.write("STATE: " + req.query.state + '\n');
11592
}
11693
}
11794
const fe_redirect_url =

0 commit comments

Comments
 (0)