forked from retoor/devplacepy
chore: reorganize test files into domain-specific subdirectories under tests/
Split the monolithic test directory into three tiers (unit, api, e2e) with a path-mirroring directory structure. Added corresponding Makefile targets (test-unit, test-api, test-e2e) and updated all documentation references (CLAUDE.md, README.md, testing-cicd.html, testing-framework.html, testing-make.html) to reflect the new layout and naming conventions.
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
import html
|
||||
import json
|
||||
import re
|
||||
import requests
|
||||
from tests.conftest import BASE_URL
|
||||
from devplacepy.database import get_table
|
||||
from devplacepy.docs_api import API_GROUPS
|
||||
from devplacepy.utils import clear_user_cache
|
||||
def _configs_by_id(text):
|
||||
configs = re.findall(r"data-config='(.*?)'", text, re.S)
|
||||
return {
|
||||
json.loads(html.unescape(cfg))["id"]: json.loads(html.unescape(cfg))
|
||||
for cfg in configs
|
||||
}
|
||||
def _key_role_visibility(username):
|
||||
return get_table("users").find_one(username=username)["api_key"]
|
||||
_author_key = []
|
||||
def _author():
|
||||
# A dedicated Member author so seeding posts never pollutes alice/bob state
|
||||
# (notifications, post counts, XP) that other test files assert on.
|
||||
if _author_key:
|
||||
return _author_key[0]
|
||||
name = "rolevis_author"
|
||||
requests.post(
|
||||
f"{BASE_URL}/auth/signup",
|
||||
data={
|
||||
"username": name,
|
||||
"email": f"{name}@t.dev",
|
||||
"password": "secret123",
|
||||
"confirm_password": "secret123",
|
||||
},
|
||||
allow_redirects=True,
|
||||
)
|
||||
row = get_table("users").find_one(username=name)
|
||||
get_table("users").update({"uid": row["uid"], "role": "Member"}, ["uid"])
|
||||
_author_key.append(row["api_key"])
|
||||
return _author_key[0]
|
||||
def _seed_post_role_visibility():
|
||||
requests.post(
|
||||
f"{BASE_URL}/posts/create",
|
||||
headers={"X-API-KEY": _author()},
|
||||
data={
|
||||
"content": "role visibility seed post body text",
|
||||
"title": "RoleVis",
|
||||
"topic": "random",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def test_docs_layout_has_sidebar(page, app_server):
|
||||
page.goto(f"{BASE_URL}/docs/index.html", wait_until="domcontentloaded")
|
||||
assert (
|
||||
page.locator(
|
||||
".sidebar-card a.sidebar-link[href='/docs/authentication.html']"
|
||||
).count()
|
||||
== 1
|
||||
)
|
||||
|
||||
|
||||
def test_docs_auth_examples_use_logged_in_user(alice):
|
||||
page, user = alice
|
||||
page.goto(f"{BASE_URL}/docs/authentication.html", wait_until="domcontentloaded")
|
||||
content = page.content()
|
||||
key = get_table("users").find_one(username=user["username"])["api_key"]
|
||||
assert key in content
|
||||
assert user["username"] in content
|
||||
|
||||
|
||||
def test_docs_widget_code_has_highlight_linenumbers_copy(page, app_server):
|
||||
page.goto(f"{BASE_URL}/docs/social-actions.html", wait_until="domcontentloaded")
|
||||
panel = page.locator(".code-block pre.code-panel").first
|
||||
panel.wait_for(state="visible")
|
||||
panel.locator(".code-gutter").first.wait_for(state="attached")
|
||||
assert panel.locator(".code-gutter").count() >= 1
|
||||
assert panel.locator(".code-copy-btn").count() >= 1
|
||||
assert panel.locator("code.hljs").count() >= 1
|
||||
# switching language tab re-highlights (not left as plain text)
|
||||
page.locator(".code-block .code-tab:has-text('Python')").first.click()
|
||||
panel.locator("code.hljs").first.wait_for(state="attached")
|
||||
assert panel.locator("code.hljs").count() >= 1
|
||||
|
||||
|
||||
def test_docs_prose_code_has_linenumbers_copy(page, app_server):
|
||||
page.goto(f"{BASE_URL}/docs/authentication.html", wait_until="domcontentloaded")
|
||||
pre = page.locator(".docs-content pre.code-pre").first
|
||||
pre.wait_for(state="visible")
|
||||
assert pre.locator(".code-gutter").count() >= 1
|
||||
assert pre.locator(".code-copy-btn").count() >= 1
|
||||
assert pre.locator("code.hljs").count() >= 1
|
||||
|
||||
|
||||
def test_docs_panel_format_picker_defaults_json(page, app_server):
|
||||
page.goto(f"{BASE_URL}/docs/content.html", wait_until="domcontentloaded")
|
||||
panel = page.locator(".api-tester").first
|
||||
panel.wait_for(state="visible")
|
||||
active = panel.locator(".format-option.active").first
|
||||
active.wait_for(state="visible")
|
||||
assert active.inner_text().strip() == "JSON"
|
||||
assert panel.locator(".response-tabs .code-tab:has-text('Expected')").count() == 1
|
||||
assert (
|
||||
panel.locator(".response-tabs .code-tab:has-text('Live response')").count() == 1
|
||||
)
|
||||
expected = panel.locator(".response-pane.active").first
|
||||
expected.wait_for(state="visible")
|
||||
assert expected.locator("pre.response-body code").count() >= 1
|
||||
|
||||
|
||||
def test_docs_panel_html_format_updates_snippet(page, app_server):
|
||||
page.goto(f"{BASE_URL}/docs/content.html", wait_until="domcontentloaded")
|
||||
panel = page.locator(".api-tester").first
|
||||
panel.wait_for(state="visible")
|
||||
code = panel.locator("pre.code-panel code").first
|
||||
code.wait_for(state="attached")
|
||||
assert "application/json" in code.inner_text()
|
||||
panel.locator(".format-option:has-text('HTML')").first.click()
|
||||
panel.locator("pre.code-panel code").filter(has_text="text/html").first.wait_for(
|
||||
timeout=5000
|
||||
)
|
||||
|
||||
|
||||
def test_docs_panel_live_send_returns_json(page, app_server):
|
||||
page.goto(f"{BASE_URL}/docs/bugs.html", wait_until="domcontentloaded")
|
||||
panel = page.locator(".api-tester").first
|
||||
panel.wait_for(state="visible")
|
||||
send = panel.locator(".try-send").first
|
||||
send.wait_for(state="visible")
|
||||
send.click()
|
||||
status = panel.locator(".response-pane.active .response-status").first
|
||||
status.wait_for(state="visible", timeout=10000)
|
||||
assert status.inner_text().strip().startswith("2")
|
||||
|
||||
|
||||
def test_guest_docs_hide_admin(page, app_server):
|
||||
page.goto(f"{BASE_URL}/docs/index.html", wait_until="domcontentloaded")
|
||||
assert page.locator("a[href='/docs/admin.html']").count() == 0
|
||||
assert page.locator("a[href='/docs/services.html']").count() == 0
|
||||
assert requests.get(f"{BASE_URL}/docs/admin.html").status_code == 404
|
||||
assert requests.get(f"{BASE_URL}/docs/services.html").status_code == 404
|
||||
|
||||
|
||||
def test_member_docs_hide_admin(bob):
|
||||
page, _ = bob
|
||||
assert (
|
||||
requests.get(
|
||||
f"{BASE_URL}/docs/admin.html", headers={"X-API-KEY": _key_role_visibility("bob_test")}
|
||||
).status_code
|
||||
== 404
|
||||
)
|
||||
page.goto(f"{BASE_URL}/docs/index.html", wait_until="domcontentloaded")
|
||||
assert page.locator("a[href='/docs/admin.html']").count() == 0
|
||||
|
||||
|
||||
def test_admin_docs_access(alice):
|
||||
page, _ = alice
|
||||
assert (
|
||||
requests.get(
|
||||
f"{BASE_URL}/docs/admin.html", headers={"X-API-KEY": _key_role_visibility("alice_test")}
|
||||
).status_code
|
||||
== 200
|
||||
)
|
||||
page.goto(f"{BASE_URL}/docs/index.html", wait_until="domcontentloaded")
|
||||
assert page.locator("a[href='/docs/admin.html']").count() >= 1
|
||||
Reference in New Issue
Block a user