diff --git a/.github/workflows/regression_tests.yml b/.github/workflows/regression_tests.yml index 8556d1bb..a3c294bf 100644 --- a/.github/workflows/regression_tests.yml +++ b/.github/workflows/regression_tests.yml @@ -16,6 +16,7 @@ on: description: 'The product we are testing' type: choice options: + - CPTS-UI - EPS-FHIR - EPS-FHIR-PRESCRIBING - EPS-FHIR-DISPENSING diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 603bdf8f..82770fc2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -60,4 +60,4 @@ repos: language: system fail_fast: false -default_stages: [pre-commit, commit] +default_stages: [pre-commit, pre-commit] diff --git a/README.md b/README.md index 62315857..7bb2a52d 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ Change the `env` variable accordingly to either `INT` or `INTERNAL-DEV`. If you wish to test a different product i.e. `PFP-APIGEE` then you must change `product=` and `--tags` respectively. ### Method 5: -Run the tests by pushing changes to github in a pull request and running the regression tests job. +Run the tests by pushing changes to github in a pull request and running the regression tests job. You can do this by the browser or by running this ``` BRANCH=fix_tests_take_2 @@ -114,12 +114,20 @@ This process will stop after the first program detects an error or if Black modi You may need to run this multiple times to ensure everything is ok before committing. -### Generating the allure report from a github test run -To generate and view the results of a github test run, first authenticate to github by running this and following instructions +### Generating the allure report from a GitHub test run +To generate and view the results of a GitHub test run, first authenticate to GitHub by running this and following instructions ``` gh auth login ``` -Then download the alluere results by noting the github run id in a browser and running this +Then download the allure results by noting the GitHub run ID in a browser and running this ``` -GITHUB_RUN_ID=11523235428 make download-allure-report +GITHUB_RUN_ID=11523235428 make download-allure-report ``` + +# UI testing +This pack has recently been updated to include UI-based testing using Playwright for CPTS-UI. It will run headless using the Chrome browser + +## Recording new tests: +Playwright contains a handy (but not perfect) feature which will record actions you make and give you the code for them +to begin, run the command:
+`playwright codegen` diff --git a/features/cpts_ui/home_page.feature b/features/cpts_ui/home_page.feature new file mode 100644 index 00000000..73a09c1c --- /dev/null +++ b/features/cpts_ui/home_page.feature @@ -0,0 +1,6 @@ +@cpts_ui @home @regression @blocker @smoke @ui +@allure.tms:https://nhsd-jira.digital.nhs.uk/browse/AEA-4460 +Feature: I can visit the Clinical Prescription Tracker Service Website + Scenario: user can navigate to the Clinical Prescription Tracker Service Website homepage + When I go to the homepage + Then I am on the homepage diff --git a/features/environment.py b/features/environment.py index 320e83bd..a5fb8419 100644 --- a/features/environment.py +++ b/features/environment.py @@ -5,11 +5,11 @@ from behave.model import Scenario from dotenv import load_dotenv - +from playwright.sync_api import sync_playwright from methods.api import eps_api_methods load_dotenv(override=True) - +global _page INTERNAL_QA_BASE_URL = "https://internal-qa.api.service.nhs.uk/" INTERNAL_DEV_BASE_URL = "https://internal-dev.api.service.nhs.uk/" INT_BASE_URL = "https://int.api.service.nhs.uk/" @@ -17,13 +17,17 @@ SANDBOX_INT_BASE_URL = "https://sandbox.api.service.nhs.uk/" REF_BASE_URL = "https://ref.api.service.nhs.uk/" +AWS_BASE_URL = ".eps.national.nhs.uk/" PFP_AWS_PR_URL = "https://pfp-{{aws_pull_request_id}}.dev.eps.national.nhs.uk/" PFP_AWS_SANDBOX_PR_URL = ( "https://pfp-{{aws_pull_request_id}}-sandbox.dev.eps.national.nhs.uk/" ) +CPTS_UI_PR_URL = "https://cpt-ui-{{aws_pull_request_id}}.dev.eps.national.nhs.uk/" +CPTS_UI_SANDBOX_PR_URL = ( + "https://cpt-ui-{{aws_pull_request_id}}sandbox.dev.eps.national.nhs.uk/" +) - -ENVS = { +APIGEE_ENVS = { "INTERNAL-DEV": INTERNAL_DEV_BASE_URL, "INTERNAL-QA": INTERNAL_QA_BASE_URL, "INT": INT_BASE_URL, @@ -32,6 +36,15 @@ "SANDBOX": SANDBOX_INT_BASE_URL, } +AWS_ENVS = { + "INTERNAL-DEV": f".dev{AWS_BASE_URL}", + "INTERNAL-QA": f".qa{AWS_BASE_URL}", + "INT": f".int{AWS_BASE_URL}", + "REF": f".ref{AWS_BASE_URL}", + "INTERNAL-DEV-SANDBOX": f".sandbox{AWS_BASE_URL}", + "SANDBOX": f".sandbox.dev{AWS_BASE_URL}", +} + CIS2_USERS = { "prescriber": {"user_id": "656005750107", "role_id": "555254242105"}, "dispenser": {"user_id": "555260695103", "role_id": "555265434108"}, @@ -39,8 +52,10 @@ LOGIN_USERS = {"user_id": "9449304130"} REPOS = { + "CPTS-UI": "https://github.com/NHSDigital/eps-prescription-tracker-ui", "EPS-FHIR": "https://github.com/NHSDigital/electronic-prescription-service-api", - # TODO Add EPS Dispensing and Prescribing repo URLs + "EPS-FHIR-PRESCRIBING": "https://github.com/NHSDigital/electronic-prescription-service-api", + "EPS-FHIR-DISPENSING": "https://github.com/NHSDigital/electronic-prescription-service-api", "PFP-APIGEE": "https://github.com/NHSDigital/prescriptions-for-patients", "PFP-AWS": "https://github.com/NHSDigital/prescriptionsforpatients", "PSU": "https://github.com/NHSDigital/eps-prescription-status-update-api", @@ -54,6 +69,7 @@ JWT_PRIVATE_KEY = os.getenv("JWT_PRIVATE_KEY") JWT_KID = os.getenv("JWT_KID") +CPTS_UI_PREFIX = "cpt-ui" EPS_FHIR_SUFFIX = "electronic-prescriptions" EPS_FHIR_PRESCRIBING_SUFFIX = "fhir-prescribing" EPS_FHIR_DISPENSING_SUFFIX = "fhir-dispensing" @@ -76,25 +92,41 @@ def count_of_scenarios_to_run(context): def before_all(context): + product = context.config.userdata["product"].upper() if count_of_scenarios_to_run(context) != 0: env = context.config.userdata["env"].upper() - product = context.config.userdata["product"].upper() - context.eps_fhir_base_url = os.path.join(select_base_url(env), EPS_FHIR_SUFFIX) + context.cpts_ui_base_url = f"https://{CPTS_UI_PREFIX}" + select_aws_base_url( + env + ) + context.eps_fhir_base_url = os.path.join( + select_apigee_base_url(env), EPS_FHIR_SUFFIX + ) context.eps_fhir_prescribing_base_url = os.path.join( - select_base_url(env), EPS_FHIR_PRESCRIBING_SUFFIX + select_apigee_base_url(env), EPS_FHIR_PRESCRIBING_SUFFIX ) context.eps_fhir_dispensing_base_url = os.path.join( - select_base_url(env), EPS_FHIR_DISPENSING_SUFFIX + select_apigee_base_url(env), EPS_FHIR_DISPENSING_SUFFIX ) - context.pfp_base_url = os.path.join(select_base_url(env), PFP_SUFFIX) - context.psu_base_url = os.path.join(select_base_url(env), PSU_SUFFIX) + context.pfp_base_url = os.path.join(select_apigee_base_url(env), PFP_SUFFIX) + context.psu_base_url = os.path.join(select_apigee_base_url(env), PSU_SUFFIX) if PULL_REQUEST_ID: pull_request_id = PULL_REQUEST_ID.lower() if "pr-" in pull_request_id: get_url_with_pr(context, env, product) else: raise RuntimeError("no tests to run. Check your tags and try again") + if product == "CPTS-UI": + global _page + playwright = sync_playwright().start() + browser = playwright.chromium.launch( + headless=True, slow_mo=1000, channel="chrome" + ) + context.page = browser.new_page() + _page = context.page + set_page(context, _page) + eps_api_methods.calculate_eps_fhir_base_url(context) + print("CPTS-UI: ", context.cpts_ui_base_url) print("EPS: ", context.eps_fhir_base_url) print("EPS-PRESCRIBING: ", context.eps_fhir_prescribing_base_url) print("EPS-DISPENSING: ", context.eps_fhir_dispensing_base_url) @@ -120,23 +152,44 @@ def get_url_with_pr(context, env, product): context.pfp_base_url = os.path.join( INTERNAL_DEV_BASE_URL, f"{PFP_SUFFIX}-{PULL_REQUEST_ID}" ) - if product == "PFP-AWS": - context.pfp_base_url = os.path.join( - INTERNAL_DEV_BASE_URL, f"{PFP_SUFFIX}-{PULL_REQUEST_ID}" - ) - if env == "INTERNAL-DEV": - context.pfp_base_url = PFP_AWS_PR_URL.replace( - "{{aws_pull_request_id}}", PULL_REQUEST_ID - ) - if env == "INTERNAL-DEV-SANDBOX": - context.pfp_base_url = PFP_AWS_SANDBOX_PR_URL.replace( - "{{aws_pull_request_id}}", PULL_REQUEST_ID - ) - if product == "PSU": context.psu_base_url = os.path.join( INTERNAL_DEV_BASE_URL, f"{PSU_SUFFIX}-{PULL_REQUEST_ID}" ) + if product == "PFP-AWS": + handle_pfp_aws_pr_url(context, env) + if product == "CPTS-UI": + handle_cpt_ui_pr_url(context, env) + + +def handle_cpt_ui_pr_url(context, env): + assert PULL_REQUEST_ID is not None + context.cpts_ui_base_url = ( + f"https://{CPTS_UI_PREFIX}-{PULL_REQUEST_ID}{select_apigee_base_url(env)}" + ) + if env == "INTERNAL-DEV": + context.cpts_ui_base_url = CPTS_UI_PR_URL.replace( + "{{aws_pull_request_id}}", PULL_REQUEST_ID + ) + if env == "INTERNAL-DEV-SANDBOX": + context.cpts_ui_base_url = CPTS_UI_SANDBOX_PR_URL.replace( + "{{aws_pull_request_id}}", PULL_REQUEST_ID + ) + + +def handle_pfp_aws_pr_url(context, env): + assert PULL_REQUEST_ID is not None + context.pfp_base_url = os.path.join( + INTERNAL_DEV_BASE_URL, f"{PFP_SUFFIX}-{PULL_REQUEST_ID}" + ) + if env == "INTERNAL-DEV": + context.pfp_base_url = PFP_AWS_PR_URL.replace( + "{{aws_pull_request_id}}", PULL_REQUEST_ID + ) + if env == "INTERNAL-DEV-SANDBOX": + context.pfp_base_url = PFP_AWS_SANDBOX_PR_URL.replace( + "{{aws_pull_request_id}}", PULL_REQUEST_ID + ) def after_all(context): @@ -167,6 +220,8 @@ def after_all(context): if os.path.exists(directory_path) and os.path.isdir(directory_path): print(f"Directory '{directory_path}' exists. Deleting...") shutil.rmtree(directory_path) + if _page: + _page.close() def setup_logging(level: int = logging.INFO): @@ -179,9 +234,16 @@ def setup_logging(level: int = logging.INFO): ) -def select_base_url(env): - if env in ENVS: - return ENVS[env] +def select_apigee_base_url(env): + if env in APIGEE_ENVS: + return APIGEE_ENVS[env] + else: + raise ValueError(f"Unknown environment or missing base URL for: {env} .") + + +def select_aws_base_url(env): + if env in AWS_ENVS: + return AWS_ENVS[env] else: raise ValueError(f"Unknown environment or missing base URL for: {env} .") @@ -199,3 +261,11 @@ def write_properties_file(file_path, properties_dict): with open(file_path, "w") as file: for key, value in properties_dict.items(): file.write(f"{key}={value}\n") + + +def get_page(self): + return self._page + + +def set_page(self, _page): + self._page = _page diff --git a/features/steps/home_page_steps.py b/features/steps/home_page_steps.py new file mode 100644 index 00000000..2714db00 --- /dev/null +++ b/features/steps/home_page_steps.py @@ -0,0 +1,14 @@ +# pylint: disable=no-name-in-module +from behave import when, then # pyright: ignore [reportAttributeAccessIssue] +from pages.home_page import HomePage + + +@when("I go to the homepage") +def goto_page(context): + context.page.goto(context.cpts_ui_base_url + "site/") + + +@then("I am on the homepage") +def verify_on_page(context): + home_page = HomePage(context.page) + home_page.verify_header_link() diff --git a/pages/home_page.py b/pages/home_page.py new file mode 100644 index 00000000..e676fde7 --- /dev/null +++ b/pages/home_page.py @@ -0,0 +1,12 @@ +from playwright.sync_api import Page, expect + + +class HomePage: + + def __init__(self, page: Page): + self.page = page + + def verify_header_link(self): + expect( + self.page.get_by_role("link", name="Clinical prescription") + ).to_be_visible() diff --git a/pyproject.toml b/pyproject.toml index 6439a7c6..f52ee09d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,6 +29,7 @@ pytest-nhsd-apim = "^3.3.15" requests-oauthlib = "^2.0.0" nhs-number-generator = {git = "https://github.com/Iain-S/nhs_number_generator.git"} pyright = "^1.1.377" +playwright = "^1.48.0" [tool.poetry.group.dev.dependencies]