Skip to content

Docs for 1.0 #498

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

Merged
merged 17 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/python-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,17 @@ jobs:
- name: selfie-lib - ruff
run: uv run ruff format --check && uv run ruff check
working-directory: python/selfie-lib
- name: pytest-selfie - pytest
run: uv run pytest -vv
working-directory: python/pytest-selfie
- name: pytest-selfie - pyright
run: uv run pyright
working-directory: python/pytest-selfie
- name: pytest-selfie - ruff
run: uv run ruff format --check && uv run ruff check
working-directory: python/pytest-selfie
- run: uv run pytest -vv
- name: example-pytest-selfie - pytest
run: uv run pytest -vv
working-directory: python/example-pytest-selfie
- name: example-pytest-selfie - pyright
run: uv run pyright
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ python/html/
python/latex/
python/selfie-lib/selfie_lib.egg-info/
python/pytest-selfie/pytest_selfie.egg-info/
node_modules/
node_modules/
.pytest_cache/
3 changes: 2 additions & 1 deletion python/example-pytest-selfie/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from flask import (
Flask,
abort,
jsonify,
make_response,
redirect,
Expand Down Expand Up @@ -86,7 +87,7 @@ def auth_user():
return None
email, signature = login_cookie.split("|")
if signature != sign_email(email):
return None
return abort(401)
return {"email": email}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,18 @@ def client():
yield client


def test_homepage(client):
def test_homepage_v1(client):
expect_selfie(client.get("/").data.decode()).to_be("""
<html><body>
<h1>Please login</h1>
<form action="/login" method="post">
<input type="text" name="email" placeholder="email">
<input type="submit" value="login">
</form>
</body></html>""")


def test_homepage_v2(client):
web_selfie(client.get("/")).to_be("""<html>
<body>
<h1>
Expand All @@ -32,25 +43,16 @@ def test_homepage(client):
200 OK""")


def test_T01_not_logged_in(client):
response = client.get("/")
expect_selfie(response.data.decode()).to_be("""
<html><body>
<h1>Please login</h1>
<form action="/login" method="post">
<input type="text" name="email" placeholder="email">
<input type="submit" value="login">
</form>
</body></html>""")
def test_login_flow(client):
web_selfie(client.get("/")).to_match_disk("1. not logged in").facet("md").to_be(
"Please login"
)

web_selfie(client.post("/login", data={"email": "[email protected]"})).to_match_disk(
"2. post login form"
).facet("md").to_be("""Email sent!

def test_T02_login(client):
response = client.post("/login", data={"email": "[email protected]"})
expect_selfie(response.data.decode()).to_be("""
<html><body>
<h1>Email sent!</h1>
<p>Check your email for your login link.</p>
</body></html>""")
Check your email for your login link.""")

email = wait_for_incoming_email()
expect_selfie(email).to_be(
Expand All @@ -61,19 +63,21 @@ def test_T02_login(client):
}
)

web_selfie(client.get("/login-confirm/2Yw4aCQ")).to_be("""REDIRECT 302 Found to /
╔═ [cookies] ═╗
[email protected]|29Xwa32OsHUoHm4TRitwQMWpuynz3r1aw3BcB5pPGdY=; Path=/""")

def test_T03_login_confirm(client):
response = client.get("/login-confirm/erjchFY=", follow_redirects=False)
expect_selfie(headers_to_string(response)).to_be("""200 OK
Content-Type=text/html; charset=utf-8""")


def headers_to_string(response):
headers = [f"{response.status}"]
for name, value in response.headers.items():
if name.lower() not in ["server", "date", "content-length"]:
headers.append(f"{name}={value}")
return "\n".join(headers)
client.set_cookie(
"login", "[email protected]|29Xwa32OsHUoHm4TRitwQMWpuynz3r1aw3BcB5pPGdY="
)
web_selfie(client.get("/")).to_match_disk("3. log in works with cookies").facet(
"md"
).to_be("Welcome back [email protected]")

client.set_cookie("login", "[email protected]|ABCDEF")
web_selfie(client.get("/")).to_match_disk(
"4. log in fails with fake cookies"
).facet("status").to_be("401 UNAUTHORIZED")


if __name__ == "__main__":
Expand Down
71 changes: 71 additions & 0 deletions python/example-pytest-selfie/tests/facets_test.ss
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
╔═ test_login_flow/1. not logged in ═╗
<html>
<body>
<h1>
Please login
</h1>
<form action="/login" method="post">
<input name="email" placeholder="email" type="text"/>
<input type="submit" value="login"/>
</form>
</body>
</html>

╔═ test_login_flow/1. not logged in[md] ═╗
Please login
╔═ test_login_flow/1. not logged in[status] ═╗
200 OK
╔═ test_login_flow/2. post login form ═╗
<html>
<body>
<h1>
Email sent!
</h1>
<p>
Check your email for your login link.
</p>
</body>
</html>

╔═ test_login_flow/2. post login form[md] ═╗
Email sent!

Check your email for your login link.
╔═ test_login_flow/2. post login form[status] ═╗
200 OK
╔═ test_login_flow/3. log in works with cookies ═╗
<html>
<body>
<h1>
Welcome back [email protected]
</h1>
</body>
</html>

╔═ test_login_flow/3. log in works with cookies[md] ═╗
Welcome back [email protected]
╔═ test_login_flow/3. log in works with cookies[status] ═╗
200 OK
╔═ test_login_flow/4. log in fails with fake cookies ═╗
<!DOCTYPE html>
<html lang="en">
<title>
401 Unauthorized
</title>
<h1>
Unauthorized
</h1>
<p>
The server could not verify that you are authorized to access the URL requested. You either supplied the wrong credentials (e.g. a bad password), or your browser doesn't understand how to supply the credentials required.
</p>
</html>

╔═ test_login_flow/4. log in fails with fake cookies[md] ═╗
401 Unauthorized

Unauthorized

The server could not verify that you are authorized to access the URL requested. You either supplied the wrong credentials (e.g. a bad password), or your browser doesn't understand how to supply the credentials required.
╔═ test_login_flow/4. log in fails with fake cookies[status] ═╗
401 UNAUTHORIZED
╔═ [end of file] ═╗
12 changes: 10 additions & 2 deletions python/example-pytest-selfie/tests/selfie_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,20 @@
def _web_camera(response: TestResponse) -> Snapshot:
redirect_reason = REDIRECTS.get(response.status_code)
if redirect_reason is not None:
return Snapshot.of(
snapshot = Snapshot.of(
f"REDIRECT {response.status_code} {redirect_reason} to "
+ response.headers.get("Location", "<unknown>")
)
else:
return Snapshot.of(response.data.decode()).plus_facet("status", response.status)
snapshot = Snapshot.of(response.data.decode()).plus_facet(
"status", response.status
)

if response.headers.get("Set-Cookie"):
snapshot = snapshot.plus_facet(
"cookies", response.headers.get("Set-Cookie", "")
)
return snapshot


def _pretty_print_html(html: str):
Expand Down
Loading
Loading