Skip to content

Commit 8d2b57c

Browse files
authored
Merge pull request #2020 from roland-ruedenauer/add-more-frontend-tests
Add two more test cases to moin.apps.frontend ...
2 parents 293b9f5 + 8d151da commit 8d2b57c

File tree

7 files changed

+157
-68
lines changed

7 files changed

+157
-68
lines changed

src/moin/_tests/wikiconfig.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
1818

1919

2020
class Config(DefaultConfig):
21-
"""Default configuration for unit tests."""
22-
23-
_here = abspath(dirname(__file__))
24-
_root = abspath(join(_here, "..", ".."))
25-
data_dir = join(_here, "wiki", "data") # needed for plugins package TODO
26-
index_storage = "FileStorage", (join(_here, "wiki", "index"),), {}
21+
"""
22+
Default configuration for unit tests.
23+
"""
24+
25+
wikiconfig_dir = abspath(dirname(__file__))
26+
instance_dir = join(wikiconfig_dir, "wiki")
27+
data_dir = join(instance_dir, "data")
28+
index_storage = "FileStorage", (join(instance_dir, "index"),), {}
2729
default_acl = None
2830
default_root = "FrontPage"
2931
interwikiname = "MoinTest"

src/moin/apps/admin/_tests/test_admin.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
),
2626
)
2727
def test_admin(app, url_for_args, status, data):
28-
with app.test_client() as c:
29-
rv = c.get(url_for(**url_for_args))
28+
with app.test_client() as client:
29+
rv = client.get(url_for(**url_for_args))
3030
assert rv.status == status
3131
assert rv.headers["Content-Type"] == "text/html; charset=utf-8"
3232
for item in data:

src/moin/apps/feed/_tests/test_feed.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

1414
class TestFeeds:
1515
def test_global_atom(self, app):
16-
with app.test_client() as c:
17-
rv = c.get(url_for("feed.atom"))
16+
with app.test_client() as client:
17+
rv = client.get(url_for("feed.atom"))
1818
assert rv.status == "200 OK"
1919
assert rv.headers["Content-Type"] == "application/atom+xml"
2020
assert rv.data.startswith(b"<?xml")
@@ -24,17 +24,17 @@ def test_global_atom(self, app):
2424
def test_global_atom_with_an_item(self, app):
2525
basename = "Foo"
2626
update_item(basename, {COMMENT: "foo data for feed item"}, "")
27-
with app.test_client() as c:
28-
rv = c.get(url_for("feed.atom"))
27+
with app.test_client() as client:
28+
rv = client.get(url_for("feed.atom"))
2929
assert rv.status == "200 OK"
3030
assert rv.headers["Content-Type"] == "application/atom+xml"
3131
assert rv.data.startswith(b"<?xml")
3232
assert b"foo data for feed item" in rv.data
3333

3434
# Test cache invalidation
3535
update_item(basename, {COMMENT: "checking if the cache invalidation works"}, "")
36-
with app.test_client() as c:
37-
rv = c.get(url_for("feed.atom"))
36+
with app.test_client() as client:
37+
rv = client.get(url_for("feed.atom"))
3838
assert rv.status == "200 OK"
3939
assert rv.headers["Content-Type"] == "application/atom+xml"
4040
assert rv.data.startswith(b"<?xml")

src/moin/apps/frontend/_tests/test_frontend.py

Lines changed: 131 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,51 @@
55
MoinMoin - Tests for frontend
66
"""
77

8+
from __future__ import annotations
9+
10+
from typing import Any, TYPE_CHECKING, Iterable
811
from io import BytesIO
912

13+
import pytest
14+
1015
from flask import url_for
1116
from flask import g as flaskg
1217
from werkzeug.datastructures import FileStorage
1318

14-
from moin.apps.frontend import views
1519
from moin import user
20+
from moin.apps.frontend import views
21+
from moin.constants.keys import ITEMID
22+
23+
if TYPE_CHECKING:
24+
from flask.testing import FlaskClient
25+
from werkzeug.test import TestResponse
26+
27+
28+
def create_user(name: str, password: str, pwencoded: bool = False, email: str | None = None) -> None:
29+
"""helper to create test user"""
30+
if email is None:
31+
32+
user.create_user(name, password, email, is_encrypted=pwencoded)
1633

17-
import pytest
34+
35+
def set_user_in_client_session(client: FlaskClient, user: user.User) -> None:
36+
# the test configuration has MoinAuth enabled
37+
with client.session_transaction() as session:
38+
session["user.itemid"] = user.profile[ITEMID]
39+
session["user.trusted"] = False
40+
session["user.auth_method"] = "moin"
41+
session["user.auth_attribs"] = tuple()
42+
session["user.session_token"] = user.get_session_token()
43+
44+
45+
def client_request(
46+
client: FlaskClient, method: str, url: str, *, user: user.User | None = None, **kwargs: Any
47+
) -> TestResponse:
48+
if user is not None:
49+
set_user_in_client_session(client, user)
50+
print(f"client request: {method} {url}")
51+
response = client.open(url, method=method, **kwargs)
52+
return response
1853

1954

2055
class TestFrontend:
@@ -26,51 +61,68 @@ def custom_setup(self, app):
2661
def _test_view(
2762
self,
2863
viewname,
29-
status="200 OK",
30-
data=("<html>", "</html>"),
31-
content_types=("text/html; charset=utf-8",),
32-
viewopts=None,
33-
params=None,
34-
):
64+
*,
65+
status: str = "200 OK",
66+
data: Iterable[str] = ("<html>", "</html>"),
67+
content_types: Iterable[str] = ("text/html; charset=utf-8",),
68+
viewopts: dict[str, Any] | None = None,
69+
params: dict[str, Any] | None = None,
70+
user: user.User | None = None,
71+
) -> TestResponse:
72+
3573
if viewopts is None:
3674
viewopts = {}
3775
if params is None:
3876
params = {}
3977

40-
with self.app.test_client() as c:
41-
for method in ["HEAD", "GET"]:
42-
print("%s %s" % (method, url_for(viewname, **viewopts)))
43-
rv = c.open(url_for(viewname, **viewopts), method=method, data=params)
44-
rv_data = rv.data.decode()
45-
assert rv.status == status
46-
assert rv.headers["Content-Type"] in content_types
47-
if method == "GET":
48-
for item in data:
49-
assert item in rv_data
50-
return rv
78+
with self.app.test_client() as client:
79+
80+
request_url = url_for(viewname, **viewopts)
81+
82+
response = client_request(client, "HEAD", request_url, user=user, data=params)
83+
assert response.status == status
84+
assert response.headers["Content-Type"] in content_types
85+
86+
response = client_request(client, "GET", request_url, user=user, data=params)
87+
assert response.status == status
88+
assert response.headers["Content-Type"] in content_types
89+
rv_data = response.data.decode()
90+
for item in data:
91+
assert item in rv_data
92+
93+
return response
5194

5295
def _test_view_post(
5396
self,
54-
viewname,
55-
status="302 FOUND",
56-
content_types=("text/html; charset=utf-8",),
57-
data=("<html>", "</html>"),
58-
form=None,
59-
viewopts=None,
60-
):
97+
viewname: str,
98+
*,
99+
status: str = "302 FOUND",
100+
content_types: Iterable[str] = ("text/html; charset=utf-8",),
101+
data: Iterable[str] = ("<html>", "</html>"),
102+
form: dict[str, Any] | None = None,
103+
viewopts: dict[str, Any] | None = None,
104+
params: dict[str, Any] | None = None,
105+
user: user.User | None = None,
106+
) -> TestResponse:
107+
108+
if params is None:
109+
params = {}
61110
if viewopts is None:
62111
viewopts = {}
63112
if form is None:
64113
form = {}
65-
print("POST %s" % url_for(viewname, **viewopts))
66-
with self.app.test_client() as c:
67-
rv = c.post(url_for(viewname, **viewopts), data=form)
68-
rv_data = rv.data.decode()
69-
assert rv.status == status
70-
assert rv.headers["Content-Type"] in content_types
114+
115+
request_url = url_for(viewname, **viewopts)
116+
print("POST %s" % request_url)
117+
118+
with self.app.test_client() as client:
119+
response = client_request(client, "POST", request_url, user=user, query_string=params, data=form)
120+
assert response.status == status
121+
assert response.headers["Content-Type"] in content_types
122+
rv_data = response.get_data(as_text=True)
71123
for item in data:
72124
assert item in rv_data
73-
return rv
125+
return response
74126

75127
def test_ajaxdelete_item_name_route(self):
76128
self._test_view_post(
@@ -170,6 +222,31 @@ def test_convert_item(self):
170222
def test_modify_item(self):
171223
self._test_view("frontend.modify_item", status="200 OK", viewopts=dict(item_name="DoesntExist"))
172224

225+
def test_modify_item_show_preview(self):
226+
227+
create_user("björn", "Xiwejr622")
228+
test_user = flaskg.user = user.User(name="björn", password="Xiwejr622")
229+
230+
content = "New item content."
231+
232+
self._test_view_post(
233+
"frontend.modify_item",
234+
status="200 OK",
235+
viewopts=dict(item_name="quokka"),
236+
params={"itemtype": "default", "contenttype": "text/x.moin.wiki;charset=utf-8", "template": ""},
237+
form={
238+
"comment": "",
239+
"content_form_data_text": content,
240+
"content_form_data_file": content.encode(encoding="utf-8"),
241+
"preview": "Preview",
242+
"meta_form_acl": "None",
243+
"meta_form_name": "quokka",
244+
"meta_form_summary": "",
245+
"meta_form_tags": "",
246+
},
247+
user=test_user,
248+
)
249+
173250
def test_rename_item(self):
174251
self._test_view("frontend.rename_item", status="404 NOT FOUND", viewopts=dict(item_name="DoesntExist"))
175252

@@ -253,6 +330,22 @@ def test_recoverpass(self):
253330
def test_login(self):
254331
self._test_view("frontend.login")
255332

333+
def test_login_post(self):
334+
username = "moin"
335+
password = "Xiwejr622"
336+
create_user(username, password)
337+
response = self._test_view_post(
338+
"frontend.login",
339+
form={
340+
"login_username": username,
341+
"login_password": password,
342+
"login_nexturl": "http://localhost/Home",
343+
"login_submit": "1",
344+
},
345+
data=("Redirecting...",),
346+
)
347+
assert response.location == "http://localhost/Home"
348+
256349
def test_logout(self):
257350
self._test_view("frontend.logout", status="302 FOUND", data=["<!doctype html"])
258351

@@ -284,7 +377,7 @@ def custom_setup(self, app):
284377
flaskg.user = saved_user
285378

286379
def test_user_password_change(self):
287-
self.createUser("moin", "Xiwejr622")
380+
create_user("moin", "Xiwejr622")
288381
flaskg.user = user.User(name="moin", password="Xiwejr622")
289382
form = self.fillPasswordChangeForm("Xiwejr622", "Woodoo645", "Woodoo645")
290383
valid = form.validate()
@@ -294,7 +387,7 @@ def test_user_unicode_password_change(self):
294387
name = "moin"
295388
password = "__שם משתמש לא קיים__" # Hebrew
296389

297-
self.createUser(name, password)
390+
create_user(name, password)
298391
flaskg.user = user.User(name=name, password=password)
299392
form = self.fillPasswordChangeForm(password, "Woodoo645", "Woodoo645")
300393
valid = form.validate()
@@ -305,22 +398,22 @@ def test_user_password_change_to_unicode_pw(self):
305398
password = "Xiwejr622"
306399
new_password = "__שם משתמש לא קיים__" # Hebrew
307400

308-
self.createUser(name, password)
401+
create_user(name, password)
309402
flaskg.user = user.User(name=name, password=password)
310403
form = self.fillPasswordChangeForm(password, new_password, new_password)
311404
valid = form.validate()
312405
assert valid # form data is valid
313406

314407
def test_fail_user_password_change_pw_mismatch(self):
315-
self.createUser("moin", "Xiwejr622")
408+
create_user("moin", "Xiwejr622")
316409
flaskg.user = user.User(name="moin", password="Xiwejr622")
317410
form = self.fillPasswordChangeForm("Xiwejr622", "Piped33", "Woodoo645")
318411
valid = form.validate()
319412
# form data is invalid because password1 != password2
320413
assert not valid
321414

322415
def test_fail_password_change(self):
323-
self.createUser("moin", "Xiwejr622")
416+
create_user("moin", "Xiwejr622")
324417
flaskg.user = user.User(name="moin", password="Xiwejr622")
325418
form = self.fillPasswordChangeForm("Xinetd33", "Woodoo645", "Woodoo645")
326419
valid = form.validate()
@@ -340,9 +433,3 @@ def fillPasswordChangeForm(self, current_password, password1, password2):
340433
)
341434
form = FormClass.from_flat(request_form)
342435
return form
343-
344-
def createUser(self, name, password, pwencoded=False, email=None):
345-
"""helper to create test user"""
346-
if email is None:
347-
348-
user.create_user(name, password, email, is_encrypted=pwencoded)

src/moin/apps/misc/_tests/test_misc.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@
1010

1111
class TestMisc:
1212
def test_global_sitemap(self, app):
13-
with app.test_client() as c:
14-
rv = c.get(url_for("misc.sitemap"))
13+
with app.test_client() as client:
14+
rv = client.get(url_for("misc.sitemap"))
1515
assert rv.status == "200 OK"
1616
assert rv.headers["Content-Type"] == "text/xml; charset=utf-8"
1717
assert rv.data.startswith(b"<?xml")
1818
assert b'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' in rv.data
1919
assert b"</urlset>" in rv.data
2020

2121
def test_urls_names(self, app):
22-
with app.test_client() as c:
23-
rv = c.get(url_for("misc.urls_names"))
22+
with app.test_client() as client:
23+
rv = client.get(url_for("misc.urls_names"))
2424
assert rv.status == "200 OK"
2525
assert rv.headers["Content-Type"] == "text/plain; charset=utf-8"

src/moin/apps/serve/_tests/test_serve.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010

1111
class TestServe:
1212
def test_index(self, app):
13-
with app.test_client() as c:
14-
rv = c.get(url_for("serve.index"))
13+
with app.test_client() as client:
14+
rv = client.get(url_for("serve.index"))
1515
assert rv.status == "200 OK"
1616
assert rv.headers["Content-Type"] == "text/plain"
1717

1818
def test_files(self, app):
19-
with app.test_client() as c:
20-
rv = c.get(url_for("serve.files", name="DoesntExist"))
19+
with app.test_client() as client:
20+
rv = client.get(url_for("serve.files", name="DoesntExist"))
2121
assert rv.status == "404 NOT FOUND"
2222
assert rv.headers["Content-Type"] == "text/html; charset=utf-8"
2323
assert rv.text.startswith("<!doctype html")

src/moin/items/_tests/test_Blog.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ def set_self_app(self, app):
2727
self.app = app
2828

2929
def _test_view(self, item_name, req_args={}, data_tokens=[], exclude_data_tokens=[], regex=None):
30-
with self.app.test_client() as c:
31-
rv = c.get(url_for("frontend.show_item", item_name=item_name, **req_args))
30+
with self.app.test_client() as client:
31+
rv = client.get(url_for("frontend.show_item", item_name=item_name, **req_args))
3232
rv_data = rv.data.decode()
3333
for data in data_tokens:
3434
assert data in rv_data

0 commit comments

Comments
 (0)