From 816aacca041c6b8db98edc1e51d9111fd7e944ae Mon Sep 17 00:00:00 2001 From: Angela Tran Date: Mon, 4 Nov 2024 05:02:29 +0000 Subject: [PATCH 01/11] feat: add setup for a separate container to run playwright use a base image that already has playwright and its browsers installed --- compose.yml | 10 ++++++++++ playwright/.gitignore | 3 +++ playwright/Dockerfile | 11 +++++++++++ playwright/requirements.txt | 3 +++ 4 files changed, 27 insertions(+) create mode 100644 playwright/.gitignore create mode 100644 playwright/Dockerfile create mode 100644 playwright/requirements.txt diff --git a/compose.yml b/compose.yml index c1a400b304..71f4f557ba 100644 --- a/compose.yml +++ b/compose.yml @@ -41,3 +41,13 @@ services: - "8000" volumes: - ./.devcontainer:/.devcontainer + + playwright: + build: + context: . + dockerfile: playwright/Dockerfile + image: benefits_client:playwright + volumes: + - ./playwright:/playwright + # https://code.visualstudio.com/docs/remote/create-dev-container#_use-docker-compose + entrypoint: sleep infinity diff --git a/playwright/.gitignore b/playwright/.gitignore new file mode 100644 index 0000000000..1a4b15330a --- /dev/null +++ b/playwright/.gitignore @@ -0,0 +1,3 @@ +__pycache__ +.pytest_cache +test-results diff --git a/playwright/Dockerfile b/playwright/Dockerfile new file mode 100644 index 0000000000..bca9a87dd5 --- /dev/null +++ b/playwright/Dockerfile @@ -0,0 +1,11 @@ +# https://playwright.dev/docs/docker +FROM mcr.microsoft.com/playwright/python:v1.48.0-jammy + +WORKDIR /playwright + +COPY playwright/requirements.txt requirements.txt + +RUN python -m pip install --upgrade pip && \ + pip install -r requirements.txt + +USER pwuser diff --git a/playwright/requirements.txt b/playwright/requirements.txt new file mode 100644 index 0000000000..c197f1ae50 --- /dev/null +++ b/playwright/requirements.txt @@ -0,0 +1,3 @@ +pytest +pytest-playwright +pytest-reporter-html1 From d8bb7cddd935cb56867b4a9a8511cd4d10263bc1 Mon Sep 17 00:00:00 2001 From: Angela Tran Date: Mon, 4 Nov 2024 05:55:51 +0000 Subject: [PATCH 02/11] feat(playwright): add scaffolding for writing and running tests add some test stubs, with one test that is a work-in-progress. the devcontainer will have pytest-playwright installed so that when we're writing tests, we can use auto-complete, reference code definition, etc. use the 'playwright' service container to run the tests. there is a sample .env file and a helper script for running tests. --- compose.yml | 1 + playwright/.env.sample | 2 ++ playwright/run.sh | 7 +++++++ playwright/test_agencycard_flow.py | 0 playwright/test_logingov_flow.py | 13 +++++++++++++ playwright/test_medicaregov_flow.py | 23 +++++++++++++++++++++++ pyproject.toml | 1 + 7 files changed, 47 insertions(+) create mode 100644 playwright/.env.sample create mode 100755 playwright/run.sh create mode 100644 playwright/test_agencycard_flow.py create mode 100644 playwright/test_logingov_flow.py create mode 100644 playwright/test_medicaregov_flow.py diff --git a/compose.yml b/compose.yml index 71f4f557ba..1112150146 100644 --- a/compose.yml +++ b/compose.yml @@ -47,6 +47,7 @@ services: context: . dockerfile: playwright/Dockerfile image: benefits_client:playwright + env_file: playwright/.env volumes: - ./playwright:/playwright # https://code.visualstudio.com/docs/remote/create-dev-container#_use-docker-compose diff --git a/playwright/.env.sample b/playwright/.env.sample new file mode 100644 index 0000000000..7c7dfb8431 --- /dev/null +++ b/playwright/.env.sample @@ -0,0 +1,2 @@ +MEDICARE_FLOW_USERNAME= +MEDICARE_FLOW_PASSWORD= diff --git a/playwright/run.sh b/playwright/run.sh new file mode 100755 index 0000000000..86440ba6b7 --- /dev/null +++ b/playwright/run.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +base_url="https://dev-benefits.calitp.org" + +pytest --base-url $base_url --tracing on -v --template=html1/index.html --report=test-results/report.html --video on diff --git a/playwright/test_agencycard_flow.py b/playwright/test_agencycard_flow.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/playwright/test_logingov_flow.py b/playwright/test_logingov_flow.py new file mode 100644 index 0000000000..3a77646ccf --- /dev/null +++ b/playwright/test_logingov_flow.py @@ -0,0 +1,13 @@ +from playwright.sync_api import Page + + +def test_older_adult_flow(page: Page): + pass + + +def test_veteran_flow(page: Page): + pass + + +def test_calfresh_cardholder_flow(page: Page): + pass diff --git a/playwright/test_medicaregov_flow.py b/playwright/test_medicaregov_flow.py new file mode 100644 index 0000000000..58ea120ca9 --- /dev/null +++ b/playwright/test_medicaregov_flow.py @@ -0,0 +1,23 @@ +import os + +from playwright.sync_api import Page, expect + + +def test_medicare_cardholder_flow(page: Page): + page.goto("/") + page.click("text='Choose your Provider'") + page.get_by_role("link", name="California State Transit (dev)").click() + page.get_by_label("Medicare Cardholder You must").check() + page.get_by_role("button", name="Choose this benefit").click() + page.get_by_role("button", name="Continue to Medicare.gov").click() + page.get_by_label("Username", exact=True).click() + + username = os.environ.get("MEDICARE_FLOW_USERNAME") + page.get_by_label("Username", exact=True).fill(username) + + password = os.environ.get("MEDICARE_FLOW_PASSWORD") + page.get_by_label("Password").fill(password) + + page.get_by_role("button", name="Log in").click() + + expect diff --git a/pyproject.toml b/pyproject.toml index 7e926e7a81..6e1247dbf7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,7 @@ test = [ "pytest", "pytest-django", "pytest-mock", + "pytest-playwright", # only for writing tests. run tests using playwright Docker Compose service "pytest-socket", ] From fed78b6acc2416d2f81f5a7f2f7d8e9c8bfd3f2c Mon Sep 17 00:00:00 2001 From: Angela Tran Date: Mon, 4 Nov 2024 06:06:13 +0000 Subject: [PATCH 03/11] refactor: extract some helper script args out into pytest.ini file this makes it so they are used any time pytest is invoked from this directory --- playwright/pytest.ini | 2 ++ playwright/run.sh | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 playwright/pytest.ini diff --git a/playwright/pytest.ini b/playwright/pytest.ini new file mode 100644 index 0000000000..03d2265ad3 --- /dev/null +++ b/playwright/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +addopts = --tracing on -v --template=html1/index.html --report=test-results/report.html --video on diff --git a/playwright/run.sh b/playwright/run.sh index 86440ba6b7..8ba2ee1e42 100755 --- a/playwright/run.sh +++ b/playwright/run.sh @@ -4,4 +4,5 @@ set -e base_url="https://dev-benefits.calitp.org" -pytest --base-url $base_url --tracing on -v --template=html1/index.html --report=test-results/report.html --video on +# also uses arguments from pytest.ini +pytest --base-url $base_url From 2b109959a6802045fb8a7b0055bdea67b6e3f1a7 Mon Sep 17 00:00:00 2001 From: Angela Tran Date: Mon, 4 Nov 2024 16:43:03 +0000 Subject: [PATCH 04/11] test: add agency card flow test this implements it in a simple way that works. there are probably improvements that can be made, e.g. not waiting 10 seconds for the enrollment to finish. mark medicaregov flow test to be skipped. --- playwright/.env.sample | 8 ++++ playwright/test_agencycard_flow.py | 70 +++++++++++++++++++++++++++++ playwright/test_medicaregov_flow.py | 3 ++ 3 files changed, 81 insertions(+) diff --git a/playwright/.env.sample b/playwright/.env.sample index 7c7dfb8431..10b53253dc 100644 --- a/playwright/.env.sample +++ b/playwright/.env.sample @@ -1,2 +1,10 @@ MEDICARE_FLOW_USERNAME= MEDICARE_FLOW_PASSWORD= + +AGENCY_CARD_SUB= +AGENCY_CARD_NAME= + +TRANSIT_PROCESSOR_CARDHOLDER_NAME= +TRANSIT_PROCESSOR_CARD_NUMBER= +TRANSIT_PROCESSOR_CARD_EXPIRATION= +TRANSIT_PROCESSOR_CARD_SECURITY_CODE= diff --git a/playwright/test_agencycard_flow.py b/playwright/test_agencycard_flow.py index e69de29bb2..f0211c43ff 100644 --- a/playwright/test_agencycard_flow.py +++ b/playwright/test_agencycard_flow.py @@ -0,0 +1,70 @@ +import os + +from playwright.sync_api import Page, expect + + +def test_agency_card_flow(page: Page): + page.goto("https://dev-benefits.calitp.org/") + + # Index - select transit agency + page.get_by_role("link", name="Choose your Provider").click() + page.get_by_role("link", name="California State Transit (dev)").click() + + # Eligibility Index - select enrollment flow + page.get_by_label("Agency Cardholder").check() + page.get_by_role("button", name="Choose this benefit").click() + + # Eligibility Start - continue + page.get_by_role("button", name="Continue").click() + + # Eligibility Confirm - fill out form and submit + page.get_by_placeholder("12345").click() + + sub = os.environ.get("AGENCY_CARD_SUB") + page.get_by_placeholder("12345").fill(sub) + page.keyboard.press("Tab") + + name = os.environ.get("AGENCY_CARD_NAME") + page.get_by_placeholder("Hernandez-Demarcos").fill(name) + + page.get_by_role("button", name="Find my record").click() + + # Enrollment Index - fill out transit processor form in pop-up window + page.mouse.wheel(0, 200) + + with page.expect_popup() as popup_info: + page.get_by_role("button", name="Enroll").click() + + popup = popup_info.value + popup.wait_for_timeout(3000) + + popup.get_by_text("Cardholder name").click() + + cardholder_name = os.environ.get("TRANSIT_PROCESSOR_CARDHOLDER_NAME") + popup.get_by_label("Cardholder name").fill(cardholder_name) + popup.keyboard.press("Tab") + + card_number = os.environ.get("TRANSIT_PROCESSOR_CARD_NUMBER") + popup.get_by_label("Card number").fill(card_number) + popup.keyboard.press("Tab") + + expiration = os.environ.get("TRANSIT_PROCESSOR_CARD_EXPIRATION") + popup.get_by_label("mm/yy").fill(expiration) + popup.keyboard.press("Tab") + + security_code = os.environ.get("TRANSIT_PROCESSOR_CARD_SECURITY_CODE") + popup.get_by_text("Security code", exact=True).click() + popup.get_by_label("Security code").fill(security_code) + + # trigger form validation - not sure why their form behaves this way + popup.keyboard.press("Shift+Tab") + popup.keyboard.press("Shift+Tab") + popup.keyboard.press("Shift+Tab") + popup.keyboard.press("Tab") + + popup.get_by_role("group", name="Enter your card details").get_by_role("button").click() + + page.wait_for_timeout(10000) + + success_message = page.get_by_text("You can now use your contactless card to tap to ride with a reduced fare!") + expect(success_message).to_be_visible() diff --git a/playwright/test_medicaregov_flow.py b/playwright/test_medicaregov_flow.py index 58ea120ca9..52d1dd7fa5 100644 --- a/playwright/test_medicaregov_flow.py +++ b/playwright/test_medicaregov_flow.py @@ -1,8 +1,11 @@ import os +import pytest + from playwright.sync_api import Page, expect +@pytest.mark.skip(reason="WIP - Medicare.gov not allowing test to login") def test_medicare_cardholder_flow(page: Page): page.goto("/") page.click("text='Choose your Provider'") From f5ecfb43173ec43163a829c3667f918befd8fe71 Mon Sep 17 00:00:00 2001 From: Angela Tran Date: Mon, 4 Nov 2024 18:00:30 +0000 Subject: [PATCH 05/11] fix(ci): specify directory to use for running unit tests since the tests-pytest workflow runs from the root level, it was also collecting Playwright tests. --- tests/pytest/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pytest/run.sh b/tests/pytest/run.sh index 8d06749e6a..fe384aaca8 100755 --- a/tests/pytest/run.sh +++ b/tests/pytest/run.sh @@ -2,7 +2,7 @@ set -eu # run normal pytests -coverage run -m pytest +coverage run -m pytest tests/pytest # clean out old coverage results rm -rf benefits/static/coverage From 787e769cf1382fc81b76de316433c5c427a173cf Mon Sep 17 00:00:00 2001 From: Angela Tran Date: Mon, 4 Nov 2024 18:03:14 +0000 Subject: [PATCH 06/11] fix(ci): mark 'playwright' service under a 'testing' profile the tests-cypress workflow was failing because there is no .env file for the playwright service, but we don't even need that service to start. this makes it so it is not started by default. see https://docs.docker.com/compose/how-tos/profiles/ for more. --- compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/compose.yml b/compose.yml index 1112150146..8916cebe3f 100644 --- a/compose.yml +++ b/compose.yml @@ -52,3 +52,4 @@ services: - ./playwright:/playwright # https://code.visualstudio.com/docs/remote/create-dev-container#_use-docker-compose entrypoint: sleep infinity + profiles: ["testing"] From ac111d6302bbf3ea45818be244d2c556fc7d5c87 Mon Sep 17 00:00:00 2001 From: Angela Tran Date: Thu, 21 Nov 2024 18:11:50 +0000 Subject: [PATCH 07/11] refactor: use optional env_file instead of profile-based approach to ensure playwright service doesn't prevent other services from starting if the `playwright/.env` file doesn't exist --- compose.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compose.yml b/compose.yml index 8916cebe3f..42f525c19a 100644 --- a/compose.yml +++ b/compose.yml @@ -47,9 +47,10 @@ services: context: . dockerfile: playwright/Dockerfile image: benefits_client:playwright - env_file: playwright/.env + env_file: + - path: playwright/.env + required: false # avoid throwing an error when running docker compose commands if this .env doesn't exist volumes: - ./playwright:/playwright # https://code.visualstudio.com/docs/remote/create-dev-container#_use-docker-compose entrypoint: sleep infinity - profiles: ["testing"] From 2589eb7ecd39e0d31a6bbb37b2e43fc88dcabfee Mon Sep 17 00:00:00 2001 From: Angela Tran Date: Thu, 21 Nov 2024 18:30:18 +0000 Subject: [PATCH 08/11] refactor(tests): remove usage of .env file entirely for now keep the scope of this PR small. namely, this PR is for setting up the environment in which we run and write tests. figuring out if and how the tests get their values is a separate task outside the scope of this PR. --- compose.yml | 3 --- playwright/.env.sample | 10 ---------- playwright/test_agencycard_flow.py | 14 ++++++-------- 3 files changed, 6 insertions(+), 21 deletions(-) delete mode 100644 playwright/.env.sample diff --git a/compose.yml b/compose.yml index 42f525c19a..71f4f557ba 100644 --- a/compose.yml +++ b/compose.yml @@ -47,9 +47,6 @@ services: context: . dockerfile: playwright/Dockerfile image: benefits_client:playwright - env_file: - - path: playwright/.env - required: false # avoid throwing an error when running docker compose commands if this .env doesn't exist volumes: - ./playwright:/playwright # https://code.visualstudio.com/docs/remote/create-dev-container#_use-docker-compose diff --git a/playwright/.env.sample b/playwright/.env.sample deleted file mode 100644 index 10b53253dc..0000000000 --- a/playwright/.env.sample +++ /dev/null @@ -1,10 +0,0 @@ -MEDICARE_FLOW_USERNAME= -MEDICARE_FLOW_PASSWORD= - -AGENCY_CARD_SUB= -AGENCY_CARD_NAME= - -TRANSIT_PROCESSOR_CARDHOLDER_NAME= -TRANSIT_PROCESSOR_CARD_NUMBER= -TRANSIT_PROCESSOR_CARD_EXPIRATION= -TRANSIT_PROCESSOR_CARD_SECURITY_CODE= diff --git a/playwright/test_agencycard_flow.py b/playwright/test_agencycard_flow.py index f0211c43ff..231c73f6bd 100644 --- a/playwright/test_agencycard_flow.py +++ b/playwright/test_agencycard_flow.py @@ -1,5 +1,3 @@ -import os - from playwright.sync_api import Page, expect @@ -20,11 +18,11 @@ def test_agency_card_flow(page: Page): # Eligibility Confirm - fill out form and submit page.get_by_placeholder("12345").click() - sub = os.environ.get("AGENCY_CARD_SUB") + sub = "71162" page.get_by_placeholder("12345").fill(sub) page.keyboard.press("Tab") - name = os.environ.get("AGENCY_CARD_NAME") + name = "Box" page.get_by_placeholder("Hernandez-Demarcos").fill(name) page.get_by_role("button", name="Find my record").click() @@ -40,19 +38,19 @@ def test_agency_card_flow(page: Page): popup.get_by_text("Cardholder name").click() - cardholder_name = os.environ.get("TRANSIT_PROCESSOR_CARDHOLDER_NAME") + cardholder_name = "Test User" popup.get_by_label("Cardholder name").fill(cardholder_name) popup.keyboard.press("Tab") - card_number = os.environ.get("TRANSIT_PROCESSOR_CARD_NUMBER") + card_number = "4111 1111 1111 1111" popup.get_by_label("Card number").fill(card_number) popup.keyboard.press("Tab") - expiration = os.environ.get("TRANSIT_PROCESSOR_CARD_EXPIRATION") + expiration = "12/34" popup.get_by_label("mm/yy").fill(expiration) popup.keyboard.press("Tab") - security_code = os.environ.get("TRANSIT_PROCESSOR_CARD_SECURITY_CODE") + security_code = "123" popup.get_by_text("Security code", exact=True).click() popup.get_by_label("Security code").fill(security_code) From c980ff0b9b1edbd36c7152ef279f602d14ba4e58 Mon Sep 17 00:00:00 2001 From: Angela Tran Date: Thu, 21 Nov 2024 18:44:18 +0000 Subject: [PATCH 09/11] refactor: move playwright directory under tests directory --- compose.yml | 4 ++-- {playwright => tests/playwright}/.gitignore | 0 {playwright => tests/playwright}/Dockerfile | 2 +- {playwright => tests/playwright}/pytest.ini | 0 {playwright => tests/playwright}/requirements.txt | 0 {playwright => tests/playwright}/run.sh | 0 {playwright => tests/playwright}/test_agencycard_flow.py | 0 {playwright => tests/playwright}/test_logingov_flow.py | 0 {playwright => tests/playwright}/test_medicaregov_flow.py | 0 9 files changed, 3 insertions(+), 3 deletions(-) rename {playwright => tests/playwright}/.gitignore (100%) rename {playwright => tests/playwright}/Dockerfile (78%) rename {playwright => tests/playwright}/pytest.ini (100%) rename {playwright => tests/playwright}/requirements.txt (100%) rename {playwright => tests/playwright}/run.sh (100%) rename {playwright => tests/playwright}/test_agencycard_flow.py (100%) rename {playwright => tests/playwright}/test_logingov_flow.py (100%) rename {playwright => tests/playwright}/test_medicaregov_flow.py (100%) diff --git a/compose.yml b/compose.yml index 71f4f557ba..9bb010f5a5 100644 --- a/compose.yml +++ b/compose.yml @@ -45,9 +45,9 @@ services: playwright: build: context: . - dockerfile: playwright/Dockerfile + dockerfile: tests/playwright/Dockerfile image: benefits_client:playwright volumes: - - ./playwright:/playwright + - ./tests/playwright:/playwright # https://code.visualstudio.com/docs/remote/create-dev-container#_use-docker-compose entrypoint: sleep infinity diff --git a/playwright/.gitignore b/tests/playwright/.gitignore similarity index 100% rename from playwright/.gitignore rename to tests/playwright/.gitignore diff --git a/playwright/Dockerfile b/tests/playwright/Dockerfile similarity index 78% rename from playwright/Dockerfile rename to tests/playwright/Dockerfile index bca9a87dd5..f1cea1d8e1 100644 --- a/playwright/Dockerfile +++ b/tests/playwright/Dockerfile @@ -3,7 +3,7 @@ FROM mcr.microsoft.com/playwright/python:v1.48.0-jammy WORKDIR /playwright -COPY playwright/requirements.txt requirements.txt +COPY tests/playwright/requirements.txt requirements.txt RUN python -m pip install --upgrade pip && \ pip install -r requirements.txt diff --git a/playwright/pytest.ini b/tests/playwright/pytest.ini similarity index 100% rename from playwright/pytest.ini rename to tests/playwright/pytest.ini diff --git a/playwright/requirements.txt b/tests/playwright/requirements.txt similarity index 100% rename from playwright/requirements.txt rename to tests/playwright/requirements.txt diff --git a/playwright/run.sh b/tests/playwright/run.sh similarity index 100% rename from playwright/run.sh rename to tests/playwright/run.sh diff --git a/playwright/test_agencycard_flow.py b/tests/playwright/test_agencycard_flow.py similarity index 100% rename from playwright/test_agencycard_flow.py rename to tests/playwright/test_agencycard_flow.py diff --git a/playwright/test_logingov_flow.py b/tests/playwright/test_logingov_flow.py similarity index 100% rename from playwright/test_logingov_flow.py rename to tests/playwright/test_logingov_flow.py diff --git a/playwright/test_medicaregov_flow.py b/tests/playwright/test_medicaregov_flow.py similarity index 100% rename from playwright/test_medicaregov_flow.py rename to tests/playwright/test_medicaregov_flow.py From bff1ec0819621b479a3c7d4beeaa878ff7ad4156 Mon Sep 17 00:00:00 2001 From: Angela Tran Date: Thu, 21 Nov 2024 18:55:12 +0000 Subject: [PATCH 10/11] refactor: make playwright service's default command be to run the tests --- compose.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compose.yml b/compose.yml index 9bb010f5a5..ae0c06979e 100644 --- a/compose.yml +++ b/compose.yml @@ -49,5 +49,4 @@ services: image: benefits_client:playwright volumes: - ./tests/playwright:/playwright - # https://code.visualstudio.com/docs/remote/create-dev-container#_use-docker-compose - entrypoint: sleep infinity + command: ./run.sh From 694aeae0758a6f43f0fa068990ab9186d2a99381 Mon Sep 17 00:00:00 2001 From: Angela Tran Date: Thu, 21 Nov 2024 19:02:08 +0000 Subject: [PATCH 11/11] refactor: simplify helper script further discussion is needed on how exactly we will pass environment-specific information to the tests. --- tests/playwright/run.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/playwright/run.sh b/tests/playwright/run.sh index 8ba2ee1e42..e10e295723 100755 --- a/tests/playwright/run.sh +++ b/tests/playwright/run.sh @@ -2,7 +2,5 @@ set -e -base_url="https://dev-benefits.calitp.org" - # also uses arguments from pytest.ini -pytest --base-url $base_url +pytest