1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
from __future__ import annotations
from pygitweb.static_tests.js_runtime import JsPage
_NAV = (
'<div id="navbar-user">'
'<a id="navbar-user-link" href="/login"></a>'
'<span id="navbar-user-avatar" class="bg-secondary"></span>'
'<div class="navbar-user-name"></div>'
'<div class="navbar-user-meta"></div>'
"</div>"
)
def test_missing_navbar_returns_immediately(js: JsPage) -> None:
js.set_html("<div></div>")
js.load("navbar-auth.js")
assert js.count("#navbar-user") == 0
def test_missing_child_nodes_return_immediately(js: JsPage) -> None:
js.set_html('<div id="navbar-user"></div>')
js.load("navbar-auth.js")
assert js.count(".navbar-user-name") == 0
def test_disabled_auth_renders_a_guest_who_cannot_sign_in(js: JsPage) -> None:
js.route("/auth/status", body={"auth_enabled": False})
js.set_html(_NAV)
js.load("navbar-auth.js")
assert js.text(".navbar-user-name") == "Guest"
assert js.text(".navbar-user-meta") == "Sign-in not used"
assert js.attr("#navbar-user-link", "href") is None
assert js.attr("#navbar-user-link", "aria-disabled") == "true"
assert "pe-none" in js.classes("#navbar-user-link")
def test_admin_without_gravatar_uses_the_admin_avatar(js: JsPage) -> None:
js.route("/auth/status", body={"auth_enabled": True, "username": "Admin"})
js.set_html(_NAV)
js.load("navbar-auth.js")
assert js.attr("#navbar-user", "data-logged-in") == "true"
assert js.prop("#navbar-user-link", "href").endswith("/user")
assert js.text(".navbar-user-name") == "Admin"
assert js.text(".navbar-user-meta") == "Signed in"
assert "bg-primary" in js.classes("#navbar-user-avatar")
assert "svg" in js.prop("#navbar-user-avatar", "innerHTML")
def test_user_gravatar_falls_back_when_the_image_errors(js: JsPage) -> None:
js.route(
"/auth/status",
body={"auth_enabled": True, "username": "ada", "gravatar_url": "http://img/a"},
)
js.set_html(_NAV)
js.load("navbar-auth.js")
assert js.prop("#navbar-user-avatar img", "src") == "http://img/a"
js.run("document.querySelector('#navbar-user-avatar img').onerror()")
assert js.count("#navbar-user-avatar img") == 0
assert "bg-teal" in js.classes("#navbar-user-avatar")
assert "bg-primary" not in js.classes("#navbar-user-avatar")
def test_signed_out_visitor_links_to_login(js: JsPage) -> None:
js.route("/auth/status", body={"auth_enabled": True, "username": ""})
js.set_html(_NAV)
js.load("navbar-auth.js")
assert js.attr("#navbar-user", "data-logged-in") == "false"
assert js.prop("#navbar-user-link", "href").endswith("/login")
assert js.text(".navbar-user-meta") == "Not signed in"
assert "bg-secondary" in js.classes("#navbar-user-avatar")
def test_signed_in_user_gets_profile_and_sign_out(js: JsPage) -> None:
js.route("/auth/status", body={"auth_enabled": True, "username": "ada"})
js.set_html(
'<div id="navbar-user">'
'<a id="navbar-user-link" href="/login"></a>'
'<span id="navbar-user-avatar" class="bg-secondary"></span>'
'<div class="navbar-user-name"></div>'
'<div class="navbar-user-meta"></div>'
'<div id="navbar-user-menu" class="d-none">'
'<a id="navbar-user-profile" href="/user"></a>'
'<a id="navbar-user-logout" href="/logout"></a>'
"</div></div>"
)
js.load("navbar-auth.js")
assert "dropdown" in js.classes("#navbar-user")
assert "dropup" in js.classes("#navbar-user")
assert js.attr("#navbar-user-link", "data-bs-toggle") == "dropdown"
assert js.prop("#navbar-user-profile", "href").endswith("/user")
assert "next=/" in js.prop("#navbar-user-logout", "href")
assert "d-none" not in js.classes("#navbar-user-menu")
def test_top_navbar_menu_opens_downward(js: JsPage) -> None:
js.route("/auth/status", body={"auth_enabled": True, "username": "ada"})
js.set_html(
'<div id="navbar-user" data-dropdown="down" data-login-href="/login?next=/project/demo/blog/">'
'<a id="navbar-user-link" href="/login?next=/project/demo/blog/"></a>'
'<span id="navbar-user-avatar" class="bg-secondary"></span>'
'<div class="navbar-user-name"></div>'
'<div class="navbar-user-meta"></div>'
'<div id="navbar-user-menu" class="d-none"></div>'
"</div>"
)
js.load("navbar-auth.js")
assert "dropdown" in js.classes("#navbar-user")
assert "dropup" not in js.classes("#navbar-user")
def test_signed_out_keeps_a_login_return_path(js: JsPage) -> None:
js.route("/auth/status", body={"auth_enabled": True, "username": ""})
js.set_html(
'<div id="navbar-user" data-login-href="/login?next=/project/demo/blog/">'
'<a id="navbar-user-link" href="/login"></a>'
'<span id="navbar-user-avatar" class="bg-secondary"></span>'
'<div class="navbar-user-name"></div>'
'<div class="navbar-user-meta"></div>'
"</div>"
)
js.load("navbar-auth.js")
assert js.prop("#navbar-user-link", "href").endswith("/login?next=/project/demo/blog/")
def test_status_fetch_failure_sends_the_link_to_login(js: JsPage) -> None:
js.route("/auth/status", error="offline")
js.set_html(_NAV)
js.load("navbar-auth.js")
assert js.prop("#navbar-user-link", "href").endswith("/login")
assert "bg-secondary" in js.classes("#navbar-user-avatar")