Skip to content

Commit da13f46

Browse files
committed
Merge branch 'main' of https://github.com/NHSDigital/eps-prescription-tracker-ui into AEA-4655-user-has-no-access-to-cpts
2 parents bef5a15 + 359d74e commit da13f46

File tree

11 files changed

+3157
-276
lines changed

11 files changed

+3157
-276
lines changed

Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ install-python:
2424
install-hooks: install-python
2525
poetry run pre-commit install --install-hooks --overwrite
2626

27+
install-playwright:
28+
playwright install
29+
playwright install-deps
30+
playwright install --force chrome
31+
2732
install-node:
2833
npm ci
2934

@@ -40,7 +45,7 @@ lint: lint-black lint-pyright lint-flake8
4045

4146
run-tests: guard-product guard-env
4247
echo "Running Regression Tests"
43-
poetry run python ./runner.py --product=$(product) --env=$(env) --tags=${tags}
48+
poetry run python ./runner.py --product=$(product) --env=$(env) --tags=$(tags)
4449

4550
check-licenses:
4651
scripts/check_python_licenses.sh

README.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@ These tests will automate End-to-End regression testing for:
55
* [Electronic Prescription Service (EPS-FHIR)](https://digital.nhs.uk/developer/api-catalogue/electronic-prescription-service-fhir)
66
* [Prescriptions for Patients (PfP)](https://digital.nhs.uk/developer/api-catalogue/prescriptions-for-patients)
77
* [Prescription Status Update (PSU)](https://digital.nhs.uk/developer/api-catalogue/prescription-status-update-fhir/)
8-
*
8+
* [Clinical Prescription Tracker UI (CPT-UI)](https://github.com/NHSDigital/eps-prescription-tracker-ui)
99

1010
## General usage
1111
These tests are run automatically during deployment and shouldn't need to be touched unless performing debugging or
1212
adding/removing/changing test cases <br />
1313
If there are any test failures, this will report a failed build
14+
15+
When developing new features that need to be regression tested, you'll need to create a new PR for them on this repository. When you are happy with the tests and the feature, merge the regression tests first. This will create a new tagged release, which you should then reference in the counterpart feature pull request before merging the code.
16+
1417
## Setup
1518

1619
### Environment Variables
@@ -65,8 +68,14 @@ If your IDE supports it, you can directly run the .feature files within `/featur
6568
Make sure that your behave run configuration includes the `--product=` & `--env=` <B>These are mandatory</B>
6669

6770
### Method 3:
68-
Run the tests by calling the Make command `make run-tests`. This requires the parameters `product=` and `env=` to be passed in
69-
* This will run the tests without tags so will run everything
71+
Run the tests by calling the Make command `make run-tests`. This requires the parameters `product=` and `env=` to be passed in.
72+
Optionally, you can pass in tags to be run, for example `tags=cpt-ui` will run all CPT-UI-tagged tests.
73+
Further, if you want to actually see the tests being executed, you can pass a `HEADLESS=true` to the makefile.
74+
75+
For example:
76+
```
77+
product=cpts-ui env=internal-dev PULL_REQUEST_ID=pr-300 tags=cpt-ui HEADLESS=true make run-tests
78+
```
7079

7180
### Method 4 (Not Recommended):
7281
Run the tests by running `behave` in a command prompt or terminal window.

features/cpts_ui/logout.feature

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
@cpts_ui @logout @regression @blocker @smoke @ui
2+
@allure.tms:https://nhsd-jira.digital.nhs.uk/browse/AEA-4809
3+
Feature: The user is able to logout of the application
4+
5+
Background:
6+
Given I am logged in
7+
And I am on the select your role page
8+
9+
############################################################################
10+
# Logging out
11+
############################################################################
12+
Scenario: Display logout modal when user clicks logout
13+
When I click the logout button
14+
Then I see the logout confirmation modal
15+
16+
Scenario: User confirms logout
17+
Given the logout confirmation modal is displayed
18+
When I confirm the logout
19+
Then I see the logout successful page
20+
21+
Scenario: User can log back in from the logout successful page
22+
Given I am on the logout successful page
23+
When I click the "log back in" button
24+
Then I am on the login page
25+
26+
############################################################################
27+
# Closing the logout modal
28+
############################################################################
29+
Scenario: Close the modal with the cross icon
30+
Given the logout confirmation modal is displayed
31+
When I close the modal with the cross
32+
Then the logout confirmation modal is not displayed
33+
34+
Scenario: Close the modal with the cancel button
35+
Given the logout confirmation modal is displayed
36+
When I close the modal with the cancel button
37+
Then the logout confirmation modal is not displayed
38+
39+
Scenario: Close the modal by clicking outside the modal
40+
Given the logout confirmation modal is displayed
41+
When I close the modal by clicking outside the modal
42+
Then the logout confirmation modal is not displayed
43+
44+
Scenario: Close the modal by pressing the escape key
45+
Given the logout confirmation modal is displayed
46+
When I close the modal by hitting escape
47+
Then the logout confirmation modal is not displayed

features/environment.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
PULL_REQUEST_ID = os.getenv("PULL_REQUEST_ID")
7373
JWT_PRIVATE_KEY = os.getenv("JWT_PRIVATE_KEY")
7474
JWT_KID = os.getenv("JWT_KID")
75+
HEADLESS = os.getenv("HEADLESS", "True").lower() in ("true", "1", "yes")
7576

7677
CPTS_UI_PREFIX = "cpt-ui"
7778
EPS_FHIR_SUFFIX = "electronic-prescriptions"
@@ -132,7 +133,9 @@ def before_all(context):
132133
if product == "CPTS-UI":
133134
global _page
134135
playwright = sync_playwright().start()
135-
context.browser = playwright.chromium.launch(headless=True, channel="chrome")
136+
context.browser = playwright.chromium.launch(
137+
headless=HEADLESS, channel="chrome"
138+
)
136139

137140
eps_api_methods.calculate_eps_fhir_base_url(context)
138141
print("CPTS-UI: ", context.cpts_ui_base_url)

features/steps/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from cpts_ui.common_steps import * # noqa: F403,F401
12
from cpts_ui.search_for_a_prescription_steps import * # noqa: F403,F401
23
from cpts_ui.home_steps import * # noqa: F403,F401
34
from cpts_ui.select_your_role_steps import * # noqa: F403,F401
5+
from cpts_ui.logout_steps import * # noqa: F403,F401
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# pylint: disable=no-name-in-module
2+
from behave import given, then # pyright: ignore [reportAttributeAccessIssue]
3+
4+
from features.environment import MOCK_CIS2_LOGIN_ID_MULTIPLE_ACCESS_ROLES
5+
6+
7+
@then("I am logged out")
8+
def i_am_logged_out(context):
9+
# No cookies with names starting with "CognitoIdentityServiceProvider" should be present
10+
cookies = context.page.context.cookies()
11+
cognito_cookies = [
12+
cookie
13+
for cookie in cookies
14+
if cookie["name"].startswith("CognitoIdentityServiceProvider")
15+
]
16+
assert len(cognito_cookies) == 0
17+
18+
19+
@given("I am logged in")
20+
def login(context):
21+
# TODO: This /site/ is not generic. Also, the .html will need to be removed when the SPA is fixed
22+
context.page.goto(context.cpts_ui_base_url + "site/login.html")
23+
context.page.get_by_role("button", name="Log in with mock CIS2").click()
24+
context.page.get_by_label("Username").fill(MOCK_CIS2_LOGIN_ID_MULTIPLE_ACCESS_ROLES)
25+
context.page.get_by_role("button", name="Sign In").click()
26+
context.page.wait_for_url("**/selectyourrole.html")
27+
28+
# There should be cookies with names starting with "CognitoIdentityServiceProvider"
29+
cookies = context.page.context.cookies()
30+
cognito_cookies = [
31+
cookie
32+
for cookie in cookies
33+
if cookie["name"].startswith("CognitoIdentityServiceProvider")
34+
]
35+
assert len(cognito_cookies) > 0
36+
37+
38+
@then("I am on the login page")
39+
def i_am_on_login_page(context):
40+
# TODO: This needs to cover the .html for the broken SPA. Will need to be removed.
41+
assert context.page.url == context.cpts_ui_base_url + "site/login"
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# pylint: disable=no-name-in-module
2+
from behave import given, when, then # pyright: ignore [reportAttributeAccessIssue]
3+
from playwright.sync_api import expect
4+
5+
from pages.logout import Logout
6+
7+
8+
###############################################################################
9+
# GIVEN
10+
###############################################################################
11+
12+
13+
@given("the logout confirmation modal is displayed")
14+
def given_logout_modal_is_displayed(context):
15+
logout_page = Logout(context.page)
16+
logout_page.logout_modal_header_link.click()
17+
expect(logout_page.logout_modal_content).to_be_visible()
18+
19+
20+
@given("I am on the logout successful page")
21+
def given_on_logout_successful_page(context):
22+
context.execute_steps("Given the logout confirmation modal is displayed")
23+
context.execute_steps("When I confirm the logout")
24+
25+
logout_page = Logout(context.page)
26+
27+
expect(logout_page.logout_page_heading).to_be_visible()
28+
expect(logout_page.logout_page_content).to_be_visible()
29+
expect(logout_page.logout_page_login_link).to_be_visible()
30+
31+
32+
###############################################################################
33+
# WHEN
34+
###############################################################################
35+
36+
37+
@when("I click the logout button")
38+
def when_i_click_logout_button(context):
39+
logout_page = Logout(context.page)
40+
logout_page.logout_modal_header_link.click()
41+
42+
43+
@when("I confirm the logout")
44+
def when_i_confirm_the_logout(context):
45+
logout_page = Logout(context.page)
46+
logout_page.logout_modal_logout_button.click()
47+
48+
49+
@when('I click the "log back in" button')
50+
def when_i_click_log_back_in_button(context):
51+
logout_page = Logout(context.page)
52+
logout_page.logout_page_login_link.click()
53+
54+
55+
@when("I close the modal with the cross")
56+
def when_i_close_modal_with_cross(context):
57+
logout_page = Logout(context.page)
58+
logout_page.logout_modal_close_button.click()
59+
60+
61+
@when("I close the modal with the cancel button")
62+
def when_i_close_modal_with_cancel_button(context):
63+
logout_page = Logout(context.page)
64+
logout_page.logout_modal_cancel_button.click()
65+
66+
67+
@when("I close the modal by clicking outside the modal")
68+
def when_i_close_modal_with_overlay(context):
69+
logout_page = Logout(context.page)
70+
logout_page.logout_modal_overlay.click(force=True, position={"x": 0, "y": 0})
71+
72+
73+
@when("I close the modal by hitting escape")
74+
def when_i_close_modal_by_hitting_escape(context):
75+
logout_page = Logout(context.page)
76+
logout_page.page.keyboard.press("Escape")
77+
78+
79+
###############################################################################
80+
# THEN STEPS
81+
###############################################################################
82+
83+
84+
@then("I see the logout confirmation modal")
85+
def then_i_see_logout_confirmation_modal(context):
86+
logout_page = Logout(context.page)
87+
expect(logout_page.logout_modal_content.get_by_role("heading")).to_contain_text(
88+
"Are you sure you want to log out?"
89+
)
90+
expect(logout_page.logout_modal_content.get_by_role("paragraph")).to_contain_text(
91+
"Logging out will end your session."
92+
)
93+
94+
95+
@then("the logout confirmation modal is not displayed")
96+
def then_logout_confirmation_modal_not_displayed(context):
97+
logout_page = Logout(context.page)
98+
expect(logout_page.logout_modal_content).not_to_be_visible()
99+
100+
101+
@then("I see the logout successful page")
102+
def then_i_see_logout_successful_page(context):
103+
logout_page = Logout(context.page)
104+
expect(logout_page.logout_page_heading).to_be_visible()
105+
expect(logout_page.logout_page_content).to_be_visible()

features/steps/cpts_ui/select_your_role_steps.py

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@
33
from playwright.sync_api import expect
44

55
from pages.select_your_role import SelectYourRole
6-
from features.environment import (
7-
MOCK_CIS2_LOGIN_ID_MULTIPLE_ACCESS_ROLES,
8-
MOCK_CIS2_LOGIN_ID_NO_ACCESS_ROLE,
9-
)
6+
from features.environment import MOCK_CIS2_LOGIN_ID_NO_ACCESS_ROLE
107

118

129
@when("I go to the select your role page")
1310
def i_go_to_the_select_your_role_page(context):
11+
# TODO: This site/*.html is not generic. Also, the .html will need to be removed when the SPA is fixed
1412
context.page.goto(context.cpts_ui_base_url + "site/selectyourrole.html")
1513

1614

@@ -21,21 +19,6 @@ def i_am_on_select_your_role_page(context):
2119
expect(select_your_role_page.summary).to_be_visible()
2220

2321

24-
@then("I am on the select your role page")
25-
def verify_on_select_your_role_page(context):
26-
select_your_role_page = SelectYourRole(context.page)
27-
expect(select_your_role_page.summary).to_be_visible()
28-
29-
30-
@given("I am logged in")
31-
def login(context):
32-
context.page.goto(context.cpts_ui_base_url + "site/auth_demo.html")
33-
context.page.get_by_role("button", name="Log in with mock CIS2").click()
34-
context.page.get_by_label("Username").fill(MOCK_CIS2_LOGIN_ID_MULTIPLE_ACCESS_ROLES)
35-
context.page.get_by_role("button", name="Sign In").click()
36-
context.page.wait_for_url("**/selectyourrole.html")
37-
38-
3922
@given("I am logged in without access")
4023
def login_without_access(context):
4124
context.page.goto(context.cpts_ui_base_url + "site/auth_demo.html")
@@ -45,6 +28,12 @@ def login_without_access(context):
4528
context.page.wait_for_url("**/selectyourrole.html")
4629

4730

31+
@then("I am on the select your role page")
32+
def verify_on_select_your_role_page(context):
33+
select_your_role_page = SelectYourRole(context.page)
34+
expect(select_your_role_page.summary).to_be_visible()
35+
36+
4837
@then("I can see the summary container")
4938
def i_can_see_the_summary_container(context):
5039
select_your_role_page = SelectYourRole(context.page)

0 commit comments

Comments
 (0)