Skip to content

Commit c45bd72

Browse files
author
JAMES FUQIAN
committed
more test cases, and use a dedecated docker-compose for selenium tests.
1 parent d541598 commit c45bd72

9 files changed

Lines changed: 120 additions & 76 deletions

File tree

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,14 @@ Configure the remote target BB2 instance where the tested app is registered (as
9292

9393
Go to local repo base directory, from there run:
9494

95-
docker-compose --profile tests up --abort-on-container-exit
95+
docker-compose -f docker-compose.selenium.yml up --abort-on-container-exit
9696

9797
Note: --abort-on-container-exit will abort client and server containers when selenium tests ends
9898

99+
## Visual trouble shoot
100+
101+
Install VNC viewer and point browser to http://localhost:5900 to monitor web UI interactions
102+
99103
## Error Responses and handling:
100104

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

client/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
"web-vitals": "^3.0.3"
2020
},
2121
"scripts": {
22-
"start": "DANGEROUSLY_DISABLE_HOST_CHECK=true REACT_APP_CTX=docker react-scripts start",
23-
"start-native": "NODE_OPTIONS=--openssl-legacy-provider REACT_APP_CTX=native react-scripts start",
22+
"start": "REACT_APP_CTX=docker react-scripts start",
23+
"start-native": "REACT_APP_CTX=native react-scripts start",
2424
"lint": "eslint --ext .ts --ext .js --ext .tsx .",
2525
"build": "react-scripts build",
2626
"test": "react-scripts test",

client/yarn.lock

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1803,10 +1803,10 @@
18031803
"@svgr/plugin-svgo" "^5.5.0"
18041804
loader-utils "^2.0.0"
18051805

1806-
"@testing-library/dom@^8.0.0":
1807-
version "8.18.1"
1808-
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.18.1.tgz#80f91be02bc171fe5a3a7003f88207be31ac2cf3"
1809-
integrity sha512-oEvsm2B/WtcHKE+IcEeeCqNU/ltFGaVyGbpcm4g/2ytuT49jrlH9x5qRKL/H3A6yfM4YAbSbC0ceT5+9CEXnLg==
1806+
"@testing-library/dom@^8.5.0":
1807+
version "8.19.0"
1808+
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.19.0.tgz#bd3f83c217ebac16694329e413d9ad5fdcfd785f"
1809+
integrity sha512-6YWYPPpxG3e/xOo6HIWwB/58HukkwIVTOaZ0VwdMVjhRUX/01E4FtQbck9GazOOj7MXHc5RBzMrU86iBJHbI+A==
18101810
dependencies:
18111811
"@babel/code-frame" "^7.10.4"
18121812
"@babel/runtime" "^7.12.5"
@@ -1817,7 +1817,7 @@
18171817
lz-string "^1.4.4"
18181818
pretty-format "^27.0.2"
18191819

1820-
"@testing-library/jest-dom@^5.16.2":
1820+
"@testing-library/jest-dom@^5.16.5":
18211821
version "5.16.5"
18221822
resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz#3912846af19a29b2dbf32a6ae9c31ef52580074e"
18231823
integrity sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==
@@ -1832,14 +1832,14 @@
18321832
lodash "^4.17.15"
18331833
redent "^3.0.0"
18341834

1835-
"@testing-library/react@^12.1.3":
1836-
version "12.1.5"
1837-
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.5.tgz#bb248f72f02a5ac9d949dea07279095fa577963b"
1838-
integrity sha512-OfTXCJUFgjd/digLUuPxa0+/3ZxsQmE7ub9kcbW/wi96Bh3o/p5vrETcBGfP17NWPGqeYYl5LTRpwyGoMC4ysg==
1835+
"@testing-library/react@^13.4.0":
1836+
version "13.4.0"
1837+
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-13.4.0.tgz#6a31e3bf5951615593ad984e96b9e5e2d9380966"
1838+
integrity sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==
18391839
dependencies:
18401840
"@babel/runtime" "^7.12.5"
1841-
"@testing-library/dom" "^8.0.0"
1842-
"@types/react-dom" "<18.0.0"
1841+
"@testing-library/dom" "^8.5.0"
1842+
"@types/react-dom" "^18.0.0"
18431843

18441844
"@testing-library/user-event@^13.5.0":
18451845
version "13.5.0"
@@ -2019,22 +2019,14 @@
20192019
dependencies:
20202020
"@types/istanbul-lib-report" "*"
20212021

2022-
"@types/jest@*":
2022+
"@types/jest@*", "@types/jest@^29.1.2":
20232023
version "29.1.2"
20242024
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.1.2.tgz#7ad8077043ab5f6c108c8111bcc1d224e5600a87"
20252025
integrity sha512-y+nlX0h87U0R+wsGn6EBuoRWYyv3KFtwRNP3QWp9+k2tJ2/bqcGS3UxD7jgT+tiwJWWq3UsyV4Y+T6rsMT4XMg==
20262026
dependencies:
20272027
expect "^29.0.0"
20282028
pretty-format "^29.0.0"
20292029

2030-
"@types/jest@^27.4.0":
2031-
version "27.5.2"
2032-
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.5.2.tgz#ec49d29d926500ffb9fd22b84262e862049c026c"
2033-
integrity sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==
2034-
dependencies:
2035-
jest-matcher-utils "^27.0.0"
2036-
pretty-format "^27.0.0"
2037-
20382030
"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
20392031
version "7.0.11"
20402032
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
@@ -2100,14 +2092,21 @@
21002092
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
21012093
integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
21022094

2103-
"@types/react-dom@<18.0.0", "@types/react-dom@^17.0.0", "@types/react-dom@^17.0.10":
2095+
"@types/react-dom@^17.0.0", "@types/react-dom@^17.0.10":
21042096
version "17.0.17"
21052097
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.17.tgz#2e3743277a793a96a99f1bf87614598289da68a1"
21062098
integrity sha512-VjnqEmqGnasQKV0CWLevqMTXBYG9GbwuE6x3VetERLh0cq2LTptFE73MrQi2S7GkKXCf2GgwItB/melLnxfnsg==
21072099
dependencies:
21082100
"@types/react" "^17"
21092101

2110-
"@types/react-router-dom@^5.1.7":
2102+
"@types/react-dom@^18.0.0":
2103+
version "18.0.6"
2104+
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.6.tgz#36652900024842b74607a17786b6662dd1e103a1"
2105+
integrity sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==
2106+
dependencies:
2107+
"@types/react" "*"
2108+
2109+
"@types/react-router-dom@^5.3.3":
21112110
version "5.3.3"
21122111
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83"
21132112
integrity sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==
@@ -5935,7 +5934,7 @@ jest-leak-detector@^27.5.1:
59355934
jest-get-type "^27.5.1"
59365935
pretty-format "^27.5.1"
59375936

5938-
jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1:
5937+
jest-matcher-utils@^27.5.1:
59395938
version "27.5.1"
59405939
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab"
59415940
integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==
@@ -7935,7 +7934,7 @@ pretty-error@^4.0.0:
79357934
lodash "^4.17.20"
79367935
renderkid "^3.0.0"
79377936

7938-
pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.5.1:
7937+
pretty-format@^27.0.2, pretty-format@^27.5.1:
79397938
version "27.5.1"
79407939
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e"
79417940
integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==

docker-compose.selenium.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
version: '3'
2+
3+
services:
4+
server:
5+
build:
6+
context: ./server
7+
dockerfile: ./Dockerfile
8+
environment:
9+
- SELENIUM_TESTS=true
10+
- DANGEROUSLY_DISABLE_HOST_CHECK=true
11+
ports:
12+
- "3001:3001"
13+
- "9229:9229"
14+
client:
15+
build:
16+
context: ./client
17+
dockerfile: ./Dockerfile
18+
environment:
19+
- SELENIUM_TESTS=true
20+
- DANGEROUSLY_DISABLE_HOST_CHECK=true
21+
ports:
22+
- "3000:3000"
23+
selenium-tests:
24+
build:
25+
context: ./selenium_tests
26+
dockerfile: ./Dockerfile
27+
command: pytest ./src/test_node_sample.py
28+
depends_on:
29+
- chrome
30+
- server
31+
- client
32+
chrome:
33+
image: selenium/standalone-chrome-debug
34+
hostname: chrome
35+
ports:
36+
- "4444:4444"
37+
- "5900:5900"

docker-compose.yml

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,3 @@ services:
1414
dockerfile: ./Dockerfile
1515
ports:
1616
- "3000:3000"
17-
selenium-tests:
18-
build:
19-
context: ./selenium_tests
20-
dockerfile: ./Dockerfile
21-
command: pytest ./src/test_node_sample.py
22-
depends_on:
23-
- chrome
24-
- server
25-
- client
26-
profiles:
27-
- tests
28-
chrome:
29-
image: selenium/standalone-chrome-debug
30-
hostname: chrome
31-
ports:
32-
- "4444:4444"
33-
- "5900:5900"
Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
# Generated by Selenium IDE
2-
import pytest
32
import time
4-
import json
53
from selenium import webdriver
64
from selenium.webdriver.common.by import By
75
from selenium.webdriver.support import expected_conditions as EC
8-
from selenium.webdriver.common.action_chains import ActionChains
9-
from selenium.webdriver.support import expected_conditions
106
from selenium.webdriver.support.wait import WebDriverWait
11-
from selenium.webdriver.common.keys import Keys
12-
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
137

148

159
class TestNodeSampleApp():
10+
driver_ready = False
11+
1612
def setup_method(self, method):
17-
print("Waiting 20 sec. ======================================>>>>>>>>>")
18-
time.sleep(20)
19-
print("Waited 20 sec. <<<<<<<<<<<<<<<================================")
13+
if not TestNodeSampleApp.driver_ready:
14+
time.sleep(20)
15+
TestNodeSampleApp.driver_ready = True
16+
print("set driver_ready={}".format(TestNodeSampleApp.driver_ready))
17+
else:
18+
print("driver_ready={}".format(TestNodeSampleApp.driver_ready))
2019

2120
opt = webdriver.ChromeOptions()
2221
opt.add_argument("--disable-dev-shm-usage")
@@ -33,7 +32,6 @@ def setup_method(self, method):
3332

3433
# opt.add_argument('--headless')
3534
# self.driver = webdriver.Chrome(options=opt)
36-
print("Register remote debug driver. ***************************")
3735
self.driver = webdriver.Remote(
3836
command_executor='http://chrome:4444/wd/hub', options=opt)
3937

@@ -52,27 +50,46 @@ def _find_and_sendkey(self, timeout_sec, by, by_expr, txt, **kwargs):
5250
elem.send_keys(txt)
5351
return elem
5452

55-
def test_node_sample_app(self):
56-
print("In test_node_sample_app(): about to connect to FE at http://client:3000 ...")
57-
self.driver.get("http://client:3000/")
58-
print("Connected !")
59-
print("Set window size to 1500 X 1800 ++++++++++++++")
60-
self.driver.set_window_size(1500, 1800)
61-
print("Locate button 'Authorize' and click ===================")
62-
# 3 | click | id=auth_btn |
63-
elem = self._find_and_click(30, By.ID, "auth_btn")
64-
# self._find_and_click(30, By.ID, "auth_btn")
65-
print("Wait 10 sec for the bene login page to show up ===================")
66-
time.sleep(10)
67-
print("Locate user name input and type user name ===================")
53+
def _assert_EOB_table_header_present(self):
54+
self._find_and_click(30, By.ID, "column_1")
55+
self._find_and_click(30, By.ID, "column_2")
56+
self._find_and_click(30, By.ID, "column_3")
57+
58+
def _assert_EOB_table_records_present(self):
59+
self._find_and_click(30, By.ID, "column_1")
60+
self._find_and_click(30, By.ID, "column_2")
61+
self._find_and_click(30, By.ID, "column_3")
62+
63+
def _input_user_and_passwd_and_login(self):
6864
self._find_and_sendkey(30, By.ID, "username-textbox", "BBUser10000")
69-
print("Locate password input and type password ===================")
7065
self._find_and_sendkey(30, By.ID, "password-textbox", "PW10000!")
71-
print("Locate login button and click ===================")
7266
self._find_and_click(30, By.ID, "login-button")
73-
print("Wait 10 sec for access grant page to show up ===================")
74-
time.sleep(10)
75-
print("Locate Approve button and click ===================")
67+
68+
def test_node_sample_app_grant_access(self):
69+
self.driver.get("http://client:3000/")
70+
self.driver.set_window_size(1500, 1800)
71+
elem = self._find_and_click(30, By.ID, "auth_btn")
72+
assert elem is not None
73+
self._input_user_and_passwd_and_login()
7674
self._find_and_click(30, By.ID, "approve")
77-
print("Now should be able to see the Claims page ===================")
75+
self._assert_EOB_table_header_present()
7876

77+
def test_node_sample_app_grant_access_no_demographic(self):
78+
self.driver.get("http://client:3000/")
79+
self.driver.set_window_size(1500, 1800)
80+
elem = self._find_and_click(30, By.ID, "auth_btn")
81+
assert elem is not None
82+
self._input_user_and_passwd_and_login()
83+
# select radio button "No Demographic Data"
84+
self._find_and_click(30, By.CSS_SELECTOR, "label:nth-child(5)")
85+
self._find_and_click(30, By.ID, "approve")
86+
self._assert_EOB_table_header_present()
87+
88+
def test_node_sample_app_deny_access(self):
89+
self.driver.get("http://client:3000/")
90+
self.driver.set_window_size(1500, 1800)
91+
elem = self._find_and_click(30, By.ID, "auth_btn")
92+
assert elem is not None
93+
self._input_user_and_passwd_and_login()
94+
self._find_and_click(30, By.ID, "deny")
95+
self._assert_EOB_table_header_present()

server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"build": "./node_modules/.bin/ts-node build.ts",
66
"lint": "eslint --fix --ext .ts --ext .tsx .",
77
"start": "node -r module-alias/register ./dist --env=production",
8-
"start:debug": "DANGEROUSLY_DISABLE_HOST_CHECK=true node --inspect=0.0.0.0:9229 ./node_modules/.bin/ts-node -r tsconfig-paths/register ./src",
8+
"start:debug": "node --inspect=0.0.0.0:9229 ./node_modules/.bin/ts-node -r tsconfig-paths/register ./src",
99
"start:dev": "nodemon",
1010
"test": "jest --coverage"
1111
},

server/src/configs/sample.config.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
* Replace your client/secret/callback url for each environment below with your specific app details
55
* (Note: local is mainly for BB2 internal developers)
66
*/
7+
8+
const SELENIUM_TESTS = process.env.SELENIUM_TESTS;
9+
710
export type ConfigType = {
811
[env: string]: {
912
bb2BaseUrl: string,
@@ -24,7 +27,7 @@ const config: ConfigType = {
2427
bb2BaseUrl: 'https://sandbox.bluebutton.cms.gov',
2528
bb2ClientId: '<client-id>',
2629
bb2ClientSecret: '<client-secret>',
27-
bb2CallbackUrl: 'http://localhost:3001/api/bluebutton/callback/',
30+
bb2CallbackUrl: SELENIUM_TESTS ? 'http://server:3001/api/bluebutton/callback/' : 'http://localhost:3001/api/bluebutton/callback/',
2831
},
2932
local: {
3033
bb2BaseUrl: 'https://sandbox.bluebutton.cms.gov',

server/src/routes/Authorize.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ export async function authorizationCallback(req: Request, res: Response) {
7676
* This is a hardcoded redirect, but this should be used from settings stored in a conf file
7777
* or other mechanism
7878
*/
79-
res.redirect('http://localhost:3000');
79+
const fe_redirect_url = process.env.SELENIUM_TESTS ? 'http://client:3000' : 'http://localhost:3000';
80+
res.redirect(fe_redirect_url);
8081
}
8182

8283
export function getAuthUrl(req: Request, res: Response) {

0 commit comments

Comments
 (0)