Merge pull request #1238 from GSA/e2e-tests-docs

Add E2E documentation and clean E2E tests
This commit is contained in:
Carlo Costino
2024-02-27 10:42:50 -05:00
committed by GitHub
7 changed files with 127 additions and 27 deletions

View File

@@ -106,6 +106,104 @@ All of the E2E tests are found in the `tests/end_to_end` folder and are
written as `pytest` scripts using
[Playwright's Python Framework](https://playwright.dev/python/docs/writing-tests).
Inside the `tests/end_to_end` folder you'll see a `conftest.py` file,
which is similar to the one found in the root `tests` folder but is
specific to the E2E tests.
There a few fixtures defined in here, but the two most important at this
time are these:
- `end_to_end_context`: A Playwright context object needed to interact
with a browser instance.
- `authenticated_page`: A Playwright page object that has gone through
the sign in process the E2E user is authenticated.
In short, if you're starting a test from scratch and testing pages that
do not require authentication, you'll start with the
`end_to_end_context` fixture and work from there.
Any test that requires you to be authenticated, you'll start with the
`authenticated_page` object as that'll have taken care of getting
everything set for you and logged into the site with the E2E test user.
### Creating a new test file
If you want to create a new test file to help organize tests (a great
idea!), it will be handy to import the Playwright `expect` and set the
base URL/URI for yourself, like this:
```python
from playwright.sync_api import expect
E2E_TEST_URI = os.getenv("NOTIFY_E2E_TEST_URI")
```
By importing Playwright's `expect` object for tests and setting
something like `E2E_TEST_URI` for yourself, it will make writing tests
much easier.
### Using the fixtures
To use the `authenticated_page` or `end_to_end_context` fixtures, you
start by defining a test function and then passing in the fixture you
need as a positional argument. This works the same as the other
functions defined to create a test for pytest.
For example, the test for the landing page starts with this:
```python
def test_landing_page(end_to_end_context):
# Open a new page and go to the site.
page = end_to_end_context.browser.new_page()
page.goto(f"{E2E_TEST_URI}/")
# Check to make sure that we've arrived at the next page.
page.wait_for_load_state("domcontentloaded")
...
```
Note the passing in of the `end_to_end_context` fixture - there is no
need to import this or anything, just pass it into the function. pytest
takes care of everything else for you.
The second line that defines a `page` variable is a convenience, since
you'll be referencing the page object a lot. This is recommended to
help keep tests readable while keeping fixture names descriptive.
If you need to test an authenticate page, such as the accounts page,
use the `authenticated_page` fixture instead, like so:
```python
def test_add_new_service_workflow(authenticated_page):
page = authenticated_page
...
```
Again, it's helpful to assign the fixture to a `page` variable for easy
reference throughout the test.
Lastly, if you need want access to the Playwright context object that is
used behind the page fixtures, you can reference it directly as well
using the `end_to_end_context` fixture:
```python
def test_add_new_service_workflow(authenticated_page, end_to_end_context):
page = authenticated_page
# Prepare for adding a new service later in the test.
current_date_time = datetime.datetime.now()
new_service_name = "E2E Federal Test Service {now} - {browser_type}".format(
now=current_date_time.strftime("%m/%d/%Y %H:%M:%S"),
browser_type=end_to_end_context.browser.browser_type.name,
)
...
```
In this example, I've used the context to get to the browser object
itself to get the name of the browser for test data.
## Maintaining E2E Tests with GitHub

View File

@@ -862,9 +862,9 @@ def test_should_show_page_if_prefilled_user_is_already_invited(
mock_get_invites_for_service,
platform_admin_user,
):
active_user_with_permission_to_other_service[
"email_address"
] = "user_1@testnotify.gsa.gov"
active_user_with_permission_to_other_service["email_address"] = (
"user_1@testnotify.gsa.gov"
)
client_request.login(platform_admin_user)
mocker.patch(
"app.models.user.user_api_client.get_user",

View File

@@ -31,9 +31,11 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None):
"name": name,
"id": folder_id or str(uuid.uuid4()),
"parent_id": parent,
"users_with_permission": users_with_permission
if users_with_permission is not None
else [sample_uuid()],
"users_with_permission": (
users_with_permission
if users_with_permission is not None
else [sample_uuid()]
),
}

View File

@@ -904,9 +904,11 @@ def create_service_templates(service_id, number_of_templates=4):
"{}_template_{}".format(template_type, template_number),
template_type,
"{} template {} content".format(template_type, template_number),
subject="{} template {} subject".format(template_type, template_number)
if template_type == "email"
else None,
subject=(
"{} template {} subject".format(template_type, template_number)
if template_type == "email"
else None
),
)
)
@@ -1101,9 +1103,9 @@ def active_user_with_permission_to_other_service(
active_user_with_permission_to_two_services["permissions"].pop(SERVICE_ONE_ID)
active_user_with_permission_to_two_services["services"].pop(0)
active_user_with_permission_to_two_services["name"] = "Service Two User"
active_user_with_permission_to_two_services[
"email_address"
] = "service-two-user@test.gsa.gov"
active_user_with_permission_to_two_services["email_address"] = (
"service-two-user@test.gsa.gov"
)
return active_user_with_permission_to_two_services

View File

@@ -68,12 +68,6 @@ def login_for_end_to_end_testing(browser):
context.storage_state(path=auth_state_path)
@pytest.fixture(scope="session")
def end_to_end_context(browser):
context = browser.new_context()
return context
@pytest.fixture(scope="session")
def end_to_end_authenticated_context(browser):
# Create and load a previously authenticated context for Playwright E2E
@@ -89,17 +83,25 @@ def end_to_end_authenticated_context(browser):
@pytest.fixture(scope="session")
def authenticated_page(end_to_end_context):
# Open a new page and go to the staging site.
page = end_to_end_context.new_page()
def end_to_end_context(browser):
context = browser.new_context()
return context
@pytest.fixture(scope="session")
def authenticated_page(end_to_end_context):
# Open a new page and go to the site.
page = end_to_end_context.new_page()
page.goto(f"{E2E_TEST_URI}/")
sign_in_button = page.get_by_role("link", name="Sign in")
# Wait for the next page to fully load.
page.wait_for_load_state("domcontentloaded")
# Sign in to the site - E2E test accounts are set to flow through.
sign_in_button = page.get_by_role("link", name="Sign in")
sign_in_button.click()
# Wait for the next page to fully load.
page.wait_for_load_state("domcontentloaded")
return page

View File

@@ -9,10 +9,6 @@ E2E_TEST_URI = os.getenv("NOTIFY_E2E_TEST_URI")
def test_add_new_service_workflow(authenticated_page, end_to_end_context):
page = authenticated_page
page.goto(f"{E2E_TEST_URI}/")
# Wait for the next page to fully load.
page.wait_for_load_state("domcontentloaded")
# Prepare for adding a new service later in the test.
current_date_time = datetime.datetime.now()

View File

@@ -7,7 +7,7 @@ E2E_TEST_URI = os.getenv("NOTIFY_E2E_TEST_URI")
def test_landing_page(end_to_end_context):
# Open a new page and go to the staging site.
# Open a new page and go to the site.
page = end_to_end_context.browser.new_page()
page.goto(f"{E2E_TEST_URI}/")