Skip to content

Commit 3027324

Browse files
authored
Facet docs for 1.0 (#498)
2 parents b6bdd16 + 79055bc commit 3027324

File tree

19 files changed

+989
-323
lines changed

19 files changed

+989
-323
lines changed

.github/workflows/python-ci.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,17 @@ jobs:
3232
- name: selfie-lib - ruff
3333
run: uv run ruff format --check && uv run ruff check
3434
working-directory: python/selfie-lib
35+
- name: pytest-selfie - pytest
36+
run: uv run pytest -vv
37+
working-directory: python/pytest-selfie
3538
- name: pytest-selfie - pyright
3639
run: uv run pyright
3740
working-directory: python/pytest-selfie
3841
- name: pytest-selfie - ruff
3942
run: uv run ruff format --check && uv run ruff check
4043
working-directory: python/pytest-selfie
41-
- run: uv run pytest -vv
44+
- name: example-pytest-selfie - pytest
45+
run: uv run pytest -vv
4246
working-directory: python/example-pytest-selfie
4347
- name: example-pytest-selfie - pyright
4448
run: uv run pyright

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ python/html/
1010
python/latex/
1111
python/selfie-lib/selfie_lib.egg-info/
1212
python/pytest-selfie/pytest_selfie.egg-info/
13-
node_modules/
13+
node_modules/
14+
.pytest_cache/

python/example-pytest-selfie/app.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from flask import (
1111
Flask,
12+
abort,
1213
jsonify,
1314
make_response,
1415
redirect,
@@ -86,7 +87,7 @@ def auth_user():
8687
return None
8788
email, signature = login_cookie.split("|")
8889
if signature != sign_email(email):
89-
return None
90+
return abort(401)
9091
return {"email": email}
9192

9293

python/example-pytest-selfie/tests/app_account_test.py python/example-pytest-selfie/tests/facets_test.py

+34-30
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,18 @@ def client():
1313
yield client
1414

1515

16-
def test_homepage(client):
16+
def test_homepage_v1(client):
17+
expect_selfie(client.get("/").data.decode()).to_be("""
18+
<html><body>
19+
<h1>Please login</h1>
20+
<form action="/login" method="post">
21+
<input type="text" name="email" placeholder="email">
22+
<input type="submit" value="login">
23+
</form>
24+
</body></html>""")
25+
26+
27+
def test_homepage_v2(client):
1728
web_selfie(client.get("/")).to_be("""<html>
1829
<body>
1930
<h1>
@@ -32,25 +43,16 @@ def test_homepage(client):
3243
200 OK""")
3344

3445

35-
def test_T01_not_logged_in(client):
36-
response = client.get("/")
37-
expect_selfie(response.data.decode()).to_be("""
38-
<html><body>
39-
<h1>Please login</h1>
40-
<form action="/login" method="post">
41-
<input type="text" name="email" placeholder="email">
42-
<input type="submit" value="login">
43-
</form>
44-
</body></html>""")
46+
def test_login_flow(client):
47+
web_selfie(client.get("/")).to_match_disk("1. not logged in").facet("md").to_be(
48+
"Please login"
49+
)
4550

51+
web_selfie(client.post("/login", data={"email": "[email protected]"})).to_match_disk(
52+
"2. post login form"
53+
).facet("md").to_be("""Email sent!
4654
47-
def test_T02_login(client):
48-
response = client.post("/login", data={"email": "[email protected]"})
49-
expect_selfie(response.data.decode()).to_be("""
50-
<html><body>
51-
<h1>Email sent!</h1>
52-
<p>Check your email for your login link.</p>
53-
</body></html>""")
55+
Check your email for your login link.""")
5456

5557
email = wait_for_incoming_email()
5658
expect_selfie(email).to_be(
@@ -61,19 +63,21 @@ def test_T02_login(client):
6163
}
6264
)
6365

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

65-
def test_T03_login_confirm(client):
66-
response = client.get("/login-confirm/erjchFY=", follow_redirects=False)
67-
expect_selfie(headers_to_string(response)).to_be("""200 OK
68-
Content-Type=text/html; charset=utf-8""")
69-
70-
71-
def headers_to_string(response):
72-
headers = [f"{response.status}"]
73-
for name, value in response.headers.items():
74-
if name.lower() not in ["server", "date", "content-length"]:
75-
headers.append(f"{name}={value}")
76-
return "\n".join(headers)
70+
client.set_cookie(
71+
"login", "[email protected]|29Xwa32OsHUoHm4TRitwQMWpuynz3r1aw3BcB5pPGdY="
72+
)
73+
web_selfie(client.get("/")).to_match_disk("3. log in works with cookies").facet(
74+
"md"
75+
).to_be("Welcome back [email protected]")
76+
77+
client.set_cookie("login", "[email protected]|ABCDEF")
78+
web_selfie(client.get("/")).to_match_disk(
79+
"4. log in fails with fake cookies"
80+
).facet("status").to_be("401 UNAUTHORIZED")
7781

7882

7983
if __name__ == "__main__":
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
╔═ test_login_flow/1. not logged in ═╗
2+
<html>
3+
<body>
4+
<h1>
5+
Please login
6+
</h1>
7+
<form action="/login" method="post">
8+
<input name="email" placeholder="email" type="text"/>
9+
<input type="submit" value="login"/>
10+
</form>
11+
</body>
12+
</html>
13+
14+
╔═ test_login_flow/1. not logged in[md] ═╗
15+
Please login
16+
╔═ test_login_flow/1. not logged in[status] ═╗
17+
200 OK
18+
╔═ test_login_flow/2. post login form ═╗
19+
<html>
20+
<body>
21+
<h1>
22+
Email sent!
23+
</h1>
24+
<p>
25+
Check your email for your login link.
26+
</p>
27+
</body>
28+
</html>
29+
30+
╔═ test_login_flow/2. post login form[md] ═╗
31+
Email sent!
32+
33+
Check your email for your login link.
34+
╔═ test_login_flow/2. post login form[status] ═╗
35+
200 OK
36+
╔═ test_login_flow/3. log in works with cookies ═╗
37+
<html>
38+
<body>
39+
<h1>
40+
Welcome back [email protected]
41+
</h1>
42+
</body>
43+
</html>
44+
45+
╔═ test_login_flow/3. log in works with cookies[md] ═╗
46+
Welcome back [email protected]
47+
╔═ test_login_flow/3. log in works with cookies[status] ═╗
48+
200 OK
49+
╔═ test_login_flow/4. log in fails with fake cookies ═╗
50+
<!DOCTYPE html>
51+
<html lang="en">
52+
<title>
53+
401 Unauthorized
54+
</title>
55+
<h1>
56+
Unauthorized
57+
</h1>
58+
<p>
59+
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.
60+
</p>
61+
</html>
62+
63+
╔═ test_login_flow/4. log in fails with fake cookies[md] ═╗
64+
401 Unauthorized
65+
66+
Unauthorized
67+
68+
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.
69+
╔═ test_login_flow/4. log in fails with fake cookies[status] ═╗
70+
401 UNAUTHORIZED
71+
╔═ [end of file] ═╗

python/example-pytest-selfie/tests/selfie_settings.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,20 @@
1616
def _web_camera(response: TestResponse) -> Snapshot:
1717
redirect_reason = REDIRECTS.get(response.status_code)
1818
if redirect_reason is not None:
19-
return Snapshot.of(
19+
snapshot = Snapshot.of(
2020
f"REDIRECT {response.status_code} {redirect_reason} to "
2121
+ response.headers.get("Location", "<unknown>")
2222
)
2323
else:
24-
return Snapshot.of(response.data.decode()).plus_facet("status", response.status)
24+
snapshot = Snapshot.of(response.data.decode()).plus_facet(
25+
"status", response.status
26+
)
27+
28+
if response.headers.get("Set-Cookie"):
29+
snapshot = snapshot.plus_facet(
30+
"cookies", response.headers.get("Set-Cookie", "")
31+
)
32+
return snapshot
2533

2634

2735
def _pretty_print_html(html: str):

0 commit comments

Comments
 (0)