Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add back button to settings/enable-2fa page to allow user to abort #789

Closed
wants to merge 1 commit into from

Conversation

anGie44
Copy link
Contributor

@anGie44 anGie44 commented Dec 1, 2024

Closes #761

What and How 🛠️

This PR introduces a back button in the settings/enable-2fa view. The button is added via the <a> element in the page's template file.

Why 🤷

The new link serves as a an escape hatch, allowing users to return to the authentication settings page.

Testing 🧪

To validate the existence and usage of the <a> element representing the back button, I've leveraged Playwright's browser testing. The test cases live in a ui subdirectory so they can be run independently with a new target, namely make test/ui, or alongside all the the tests via make test.

Locally, you can pull this branch and run make test/ui to validate.

Anything else 💭

I chose Playwright here instead of Selenium because it seems to spin up faster and perhaps less overhead -- did require installing some dependencies (see Dockerfile.dev). Open to discussing this choice more since sets a precedent for e2e browser testing

@anGie44 anGie44 force-pushed the anGie44/hushline-761-back-button-2FA branch 4 times, most recently from 1fb96aa to 537ab3f Compare December 2, 2024 15:24
print(f"Retrying due to error: {retry_state.outcome.exception()}")


@retry(
Copy link
Contributor Author

@anGie44 anGie44 Dec 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Required retrying initial loading of localhost:8080/login because it seems the playwright's browser can spin up before the app (docker compose run) is ready to serve requests.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use pytest fixtures, we can have a liveness check on the app so that it doesn't even return/yield said fixture until it's usable.

Comment on lines +21 to +24
page.goto(f"{BASE_URL}/login", wait_until="domcontentloaded")
page.get_by_label("Username").fill("test")
page.get_by_label("Password").fill(user_password)
page.get_by_role("button", name="Login").click()
Copy link
Contributor Author

@anGie44 anGie44 Dec 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i tried moving this out into a pytest fixture for the test methods to use before testing the actual button-related changes but couldn't get the tests to synchronously wait for a successful login 🤔 so there's duplication here and test below which isn't great. open to any suggestions here :)

@anGie44 anGie44 marked this pull request as ready for review December 2, 2024 15:31
@anGie44 anGie44 force-pushed the anGie44/hushline-761-back-button-2FA branch from 537ab3f to a5d3157 Compare December 4, 2024 00:42
Copy link
Collaborator

@brassy-endomorph brassy-endomorph left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to collaborate on a better UI testing strategy since that itself is no small task. There's also so cleanup in the app code like #663 that would make it much easier to test. I would say that likely using a live app + selenium-eque driver would only be for things like JS-only features due to the complexities around setting up an app like that in a way that preserves fixture isolation.

RUN pip install poetry pytest-playwright

# Playwright dependencies to run browsers
RUN playwright install
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't these go after the poetry install so that we get the versions that are pinned in the poetry.lock file? Is there an equivalent playwritght type lockfile

.PHONY: test
test: ## Run the test suite
docker compose run --rm app \
poetry run pytest --cov hushline --cov-report term --cov-report html -vv $(PYTEST_ADDOPTS) $(TESTS)

.PHONY: test/ui
test/ui: # Only run the ui tests
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we way we'll want to split this is either using some kind of pytest.mark or possibly a wholly separate directory like ui-test since we'd need a separate set of fixtures for a live app, though there might be some clean way to make them overlap.

@@ -29,6 +29,8 @@ stripe = "^10.9.0"
types-requests = "^2.32.0.20240712"
types-setuptools = "^71.1.0.20240813"
python = "^3.11"
pytest-playwright = "^0.6.2"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: alphabetize

from playwright.sync_api import Page, expect
from tenacity import RetryCallState, retry, stop_after_attempt, wait_random_exponential

BASE_URL = "http://127.0.0.1:8080"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This URL (or rather, port) should probably come via a fixture of some sort using a trick like this:

https://github.com/freedomofpress/securedrop/blob/6ad1fa95330c4f36c3144cb871620c64d8bc1f94/securedrop/tests/functional/conftest.py#L43-L48

I'm guessing the UI tests require an already running app that's started in a second terminal or so, yeah?

print(f"Retrying due to error: {retry_state.outcome.exception()}")


@retry(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use pytest fixtures, we can have a liveness check on the app so that it doesn't even return/yield said fixture until it's usable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2FA toggle page should have a "back" button so a user can abort the process
3 participants