fix: normalize unicode escape sequences and reformat multi-line expressions across codebase

This commit is contained in:
2026-06-09 16:48:08 +00:00
parent 66dfda88bc
commit c4f2937415
175 changed files with 12660 additions and 4175 deletions
+297 -212
View File
@@ -31,7 +31,7 @@ TOPICS = ["devlog", "showcase", "question", "rant", "fun", "random"]
PROJECT_TYPES = ["game", "game_asset", "software", "mobile_app", "website"]
GIST_LANGUAGES = ["python", "javascript", "go", "rust", "bash", "sql", "json"]
UPLOAD_FILE = ("load_test.txt", b"locust upload payload", "text/plain")
UUID_RE = r'[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}'
UUID_RE = r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"
PASSWORD = "testpass123"
@@ -40,10 +40,17 @@ def random_username():
def do_signup(client, username, email):
with client.post("/auth/signup", data={
"username": username, "email": email,
"password": PASSWORD, "confirm_password": PASSWORD,
}, catch_response=True, name="signup") as resp:
with client.post(
"/auth/signup",
data={
"username": username,
"email": email,
"password": PASSWORD,
"confirm_password": PASSWORD,
},
catch_response=True,
name="signup",
) as resp:
if resp.status_code == 200 and resp.history:
resp.success()
return True
@@ -52,9 +59,15 @@ def do_signup(client, username, email):
def do_login(client, email):
with client.post("/auth/login", data={
"email": email, "password": PASSWORD,
}, catch_response=True, name="login") as resp:
with client.post(
"/auth/login",
data={
"email": email,
"password": PASSWORD,
},
catch_response=True,
name="login",
) as resp:
if resp.status_code == 200 and resp.history:
resp.success()
return True
@@ -78,10 +91,14 @@ def seed_data(environment, **kwargs):
attempts += 1
username = random_username()
email = f"{username}@locust.devplace"
body = urllib.parse.urlencode({
"username": username, "email": email,
"password": PASSWORD, "confirm_password": PASSWORD,
}).encode()
body = urllib.parse.urlencode(
{
"username": username,
"email": email,
"password": PASSWORD,
"confirm_password": PASSWORD,
}
).encode()
req = urllib.request.Request(f"{host}/auth/signup", data=body)
try:
urllib.request.urlopen(req, timeout=10)
@@ -102,23 +119,21 @@ def seed_data(environment, **kwargs):
def logged_in_opener(email):
jar = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(
urllib.request.HTTPCookieProcessor(jar)
)
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
body = urllib.parse.urlencode({"email": email, "password": PASSWORD}).encode()
opener.open(
urllib.request.Request(f"{host}/auth/login", data=body), timeout=10
)
opener.open(urllib.request.Request(f"{host}/auth/login", data=body), timeout=10)
return opener
for seed in SEED_USERS[:3]:
try:
opener = logged_in_opener(seed["email"])
body = urllib.parse.urlencode({
"content": "x " * 100,
"title": f"Seed post {uuid.uuid4().hex[:6]}",
"topic": random.choice(TOPICS),
}).encode()
body = urllib.parse.urlencode(
{
"content": "x " * 100,
"title": f"Seed post {uuid.uuid4().hex[:6]}",
"topic": random.choice(TOPICS),
}
).encode()
resp = opener.open(
urllib.request.Request(f"{host}/posts/create", data=body),
timeout=10,
@@ -127,7 +142,7 @@ def seed_data(environment, **kwargs):
if m and m.group(1) not in POST_SLUGS:
POST_SLUGS.append(m.group(1))
html = resp.read().decode("utf-8", errors="replace")
m2 = re.search(rf'/votes/post/({UUID_RE})', html)
m2 = re.search(rf"/votes/post/({UUID_RE})", html)
if m2 and m2.group(1) not in POST_UIDS:
POST_UIDS.append(m2.group(1))
except Exception as e:
@@ -139,10 +154,12 @@ def seed_data(environment, **kwargs):
for seed in SEED_USERS[:2]:
try:
opener = logged_in_opener(seed["email"])
body = urllib.parse.urlencode({
"content": f"Seed comment by {seed['username']}",
"post_uid": post_uid,
}).encode()
body = urllib.parse.urlencode(
{
"content": f"Seed comment by {seed['username']}",
"post_uid": post_uid,
}
).encode()
opener.open(
urllib.request.Request(f"{host}/comments/create", data=body),
timeout=10,
@@ -153,11 +170,13 @@ def seed_data(environment, **kwargs):
for seed in SEED_USERS[:2]:
try:
opener = logged_in_opener(seed["email"])
body = urllib.parse.urlencode({
"title": f"Project {uuid.uuid4().hex[:6]}",
"description": "z " * 50,
"project_type": random.choice(PROJECT_TYPES),
}).encode()
body = urllib.parse.urlencode(
{
"title": f"Project {uuid.uuid4().hex[:6]}",
"description": "z " * 50,
"project_type": random.choice(PROJECT_TYPES),
}
).encode()
opener.open(
urllib.request.Request(f"{host}/projects/create", data=body),
timeout=10,
@@ -168,12 +187,14 @@ def seed_data(environment, **kwargs):
for seed in SEED_USERS[:2]:
try:
opener = logged_in_opener(seed["email"])
body = urllib.parse.urlencode({
"title": f"Gist {uuid.uuid4().hex[:6]}",
"description": "Seed gist for load testing.",
"source_code": "print('hello')\n" * 5,
"language": random.choice(GIST_LANGUAGES),
}).encode()
body = urllib.parse.urlencode(
{
"title": f"Gist {uuid.uuid4().hex[:6]}",
"description": "Seed gist for load testing.",
"source_code": "print('hello')\n" * 5,
"language": random.choice(GIST_LANGUAGES),
}
).encode()
resp = opener.open(
urllib.request.Request(f"{host}/gists/create", data=body),
timeout=10,
@@ -182,7 +203,7 @@ def seed_data(environment, **kwargs):
if m and m.group(1) not in GIST_SLUGS:
GIST_SLUGS.append(m.group(1))
html = resp.read().decode("utf-8", errors="replace")
m2 = re.search(rf'/votes/gist/({UUID_RE})', html)
m2 = re.search(rf"/votes/gist/({UUID_RE})", html)
if m2 and m2.group(1) not in GIST_UIDS:
GIST_UIDS.append(m2.group(1))
except Exception as e:
@@ -193,10 +214,12 @@ def seed_data(environment, **kwargs):
for seed in SEED_USERS[:2]:
try:
opener = logged_in_opener(seed["email"])
body = urllib.parse.urlencode({
"title": f"Bug {uuid.uuid4().hex[:6]}",
"description": "Seed bug report for load testing.",
}).encode()
body = urllib.parse.urlencode(
{
"title": f"Bug {uuid.uuid4().hex[:6]}",
"description": "Seed bug report for load testing.",
}
).encode()
opener.open(
urllib.request.Request(f"{host}/bugs/create", data=body),
timeout=10,
@@ -208,33 +231,46 @@ def seed_data(environment, **kwargs):
try:
from devplacepy.database import get_table, init_db
from devplacepy.utils import make_combined_slug
init_db()
news_table = get_table("news")
for i in range(3):
title = f"Locust news article {i} {uuid.uuid4().hex[:4]}"
article_uid = str(uuid.uuid4())
slug = make_combined_slug(title, article_uid)
news_table.insert({
"uid": article_uid, "slug": slug, "title": title,
"external_id": f"locust_seed_{i}", "grade": 8,
"status": "published", "show_on_landing": 1,
"source_name": "Locust", "synced_at": "2026-01-01T00:00:00",
"description": "Locust seed article for load testing.",
})
news_table.insert(
{
"uid": article_uid,
"slug": slug,
"title": title,
"external_id": f"locust_seed_{i}",
"grade": 8,
"status": "published",
"show_on_landing": 1,
"source_name": "Locust",
"synced_at": "2026-01-01T00:00:00",
"description": "Locust seed article for load testing.",
}
)
NEWS_UIDS.append(article_uid)
NEWS_SLUGS.append(slug)
admin_news_uid = str(uuid.uuid4())
admin_news_title = f"Admin target news {uuid.uuid4().hex[:4]}"
news_table.insert({
"uid": admin_news_uid,
"slug": make_combined_slug(admin_news_title, admin_news_uid),
"title": admin_news_title,
"external_id": f"locust_admin_target_{uuid.uuid4().hex[:6]}",
"grade": 5, "status": "published", "show_on_landing": 0,
"source_name": "Locust", "synced_at": "2026-01-01T00:00:00",
"description": "Dedicated target for admin news mutations.",
})
news_table.insert(
{
"uid": admin_news_uid,
"slug": make_combined_slug(admin_news_title, admin_news_uid),
"title": admin_news_title,
"external_id": f"locust_admin_target_{uuid.uuid4().hex[:6]}",
"grade": 5,
"status": "published",
"show_on_landing": 0,
"source_name": "Locust",
"synced_at": "2026-01-01T00:00:00",
"description": "Dedicated target for admin news mutations.",
}
)
ADMIN_TARGETS["news_uid"] = admin_news_uid
except Exception as e:
logger.warning(f"Seed news articles failed: {e}")
@@ -244,35 +280,52 @@ def seed_data(environment, **kwargs):
from datetime import datetime, timezone
from devplacepy.database import get_table, init_db
from devplacepy.utils import hash_password, generate_uid
init_db()
username = f"lu_admin_{uuid.uuid4().hex[:6]}"
email = f"{username}@locust.devplace"
get_table("users").insert({
"uid": generate_uid(),
"username": username,
"email": email,
"password_hash": hash_password(PASSWORD),
"bio": "", "location": "", "git_link": "", "website": "",
"role": "Admin", "is_active": True,
"level": 1, "xp": 0, "stars": 0,
"created_at": datetime.now(timezone.utc).isoformat(),
})
get_table("users").insert(
{
"uid": generate_uid(),
"username": username,
"email": email,
"password_hash": hash_password(PASSWORD),
"bio": "",
"location": "",
"git_link": "",
"website": "",
"role": "Admin",
"is_active": True,
"level": 1,
"xp": 0,
"stars": 0,
"created_at": datetime.now(timezone.utc).isoformat(),
}
)
ADMIN_USER["username"] = username
ADMIN_USER["email"] = email
ALL_USERNAMES.append(username)
disposable_uid = generate_uid()
disposable_name = f"lu_target_{uuid.uuid4().hex[:6]}"
get_table("users").insert({
"uid": disposable_uid,
"username": disposable_name,
"email": f"{disposable_name}@locust.devplace",
"password_hash": hash_password(PASSWORD),
"bio": "", "location": "", "git_link": "", "website": "",
"role": "Member", "is_active": True,
"level": 1, "xp": 0, "stars": 0,
"created_at": datetime.now(timezone.utc).isoformat(),
})
get_table("users").insert(
{
"uid": disposable_uid,
"username": disposable_name,
"email": f"{disposable_name}@locust.devplace",
"password_hash": hash_password(PASSWORD),
"bio": "",
"location": "",
"git_link": "",
"website": "",
"role": "Member",
"is_active": True,
"level": 1,
"xp": 0,
"stars": 0,
"created_at": datetime.now(timezone.utc).isoformat(),
}
)
ADMIN_TARGETS["disposable_uid"] = disposable_uid
logger.info(f"Created admin user {username} and disposable target")
except Exception as e:
@@ -283,25 +336,22 @@ def seed_data(environment, **kwargs):
# project cards: /votes/project/{uuid}
# comment deletion: /comments/delete/{uuid}
uuid_pat = rf'({UUID_RE})'
uuid_pat = rf"({UUID_RE})"
for seed in SEED_USERS:
try:
opener = logged_in_opener(seed["email"])
resp = opener.open(
urllib.request.Request(f"{host}/projects"), timeout=10
)
resp = opener.open(urllib.request.Request(f"{host}/projects"), timeout=10)
html = resp.read().decode("utf-8", errors="replace")
m = re.search(rf'/projects\?user_uid={uuid_pat}', html)
m = re.search(rf"/projects\?user_uid={uuid_pat}", html)
if m and m.group(1) not in USER_UIDS:
USER_UIDS.append(m.group(1))
proj_matches = re.findall(rf'/votes/project/{uuid_pat}', html)
PROJECT_UIDS.extend(
p for p in proj_matches if p not in PROJECT_UIDS
)
proj_matches = re.findall(rf"/votes/project/{uuid_pat}", html)
PROJECT_UIDS.extend(p for p in proj_matches if p not in PROJECT_UIDS)
slug_matches = re.findall(r'href="/projects/([^"/?#]+)"', html)
PROJECT_SLUGS.extend(
s for s in slug_matches
s
for s in slug_matches
if s not in PROJECT_SLUGS and s not in ("create",)
)
except Exception as e:
@@ -315,7 +365,7 @@ def seed_data(environment, **kwargs):
timeout=10,
)
html = resp.read().decode("utf-8", errors="replace")
matches = re.findall(rf'/comments/delete/{uuid_pat}', html)
matches = re.findall(rf"/comments/delete/{uuid_pat}", html)
COMMENT_UIDS.extend(m for m in matches if m not in COMMENT_UIDS)
except Exception as e:
logger.warning(f"Harvest comment UIDs failed: {e}")
@@ -324,7 +374,7 @@ def seed_data(environment, **kwargs):
opener = logged_in_opener(SEED_USERS[0]["email"])
resp = opener.open(urllib.request.Request(f"{host}/bugs"), timeout=10)
html = resp.read().decode("utf-8", errors="replace")
bug_matches = re.findall(rf'/votes/bug/{uuid_pat}', html)
bug_matches = re.findall(rf"/votes/bug/{uuid_pat}", html)
BUG_UIDS.extend(b for b in bug_matches if b not in BUG_UIDS)
except Exception as e:
logger.warning(f"Harvest bug UIDs failed: {e}")
@@ -376,9 +426,7 @@ class DevPlaceUser(HttpUser):
slugs = POST_SLUGS if POST_SLUGS else POST_UIDS
if not slugs:
return
self.client.get(
f"/posts/{random.choice(slugs)}", name="posts/[uid]"
)
self.client.get(f"/posts/{random.choice(slugs)}", name="posts/[uid]")
@task(3)
def view_profile(self):
@@ -418,9 +466,7 @@ class DevPlaceUser(HttpUser):
slugs = NEWS_SLUGS if NEWS_SLUGS else NEWS_UIDS
if not slugs:
return
self.client.get(
f"/news/{random.choice(slugs)}", name="news/[slug]"
)
self.client.get(f"/news/{random.choice(slugs)}", name="news/[slug]")
@task(1)
def view_bugs(self):
@@ -458,29 +504,21 @@ class DevPlaceUser(HttpUser):
def view_gist_detail(self):
if not GIST_SLUGS:
return
self.client.get(
f"/gists/{random.choice(GIST_SLUGS)}", name="gists/[slug]"
)
self.client.get(f"/gists/{random.choice(GIST_SLUGS)}", name="gists/[slug]")
@task(1)
def search_profiles(self):
term = random.choice(ALL_USERNAMES)[:5] if ALL_USERNAMES else "lu"
self.client.get(
"/profile/search", params={"q": term}, name="profile/search"
)
self.client.get("/profile/search", params={"q": term}, name="profile/search")
@task(1)
def search_messages(self):
term = random.choice(ALL_USERNAMES)[:5] if ALL_USERNAMES else "lu"
self.client.get(
"/messages/search", params={"q": term}, name="messages/search"
)
self.client.get("/messages/search", params={"q": term}, name="messages/search")
@task(1)
def view_seo(self):
self.client.get(
random.choice(["/robots.txt", "/sitemap.xml"]), name="seo"
)
self.client.get(random.choice(["/robots.txt", "/sitemap.xml"]), name="seo")
@task(1)
def view_static(self):
@@ -507,18 +545,19 @@ class DevPlaceUser(HttpUser):
@task(1)
def request_password_reset(self):
email = random.choice(SEED_USERS)["email"] if SEED_USERS else "x@locust.devplace"
email = (
random.choice(SEED_USERS)["email"] if SEED_USERS else "x@locust.devplace"
)
self.client.post(
"/auth/forgot-password", data={"email": email},
"/auth/forgot-password",
data={"email": email},
name="auth/forgot-password/post",
)
@task(1)
def reset_password_flow(self):
token = uuid.uuid4().hex + uuid.uuid4().hex
self.client.get(
f"/auth/reset-password/{token}", name="auth/reset-password"
)
self.client.get(f"/auth/reset-password/{token}", name="auth/reset-password")
self.client.post(
f"/auth/reset-password/{token}",
data={"password": PASSWORD, "confirm_password": PASSWORD},
@@ -534,9 +573,9 @@ class DevPlaceUser(HttpUser):
"title": f"Load test {uuid.uuid4().hex[:6]}",
"topic": random.choice(TOPICS),
}
with self.client.post("/posts/create", data=data,
catch_response=True,
name="posts/create") as resp:
with self.client.post(
"/posts/create", data=data, catch_response=True, name="posts/create"
) as resp:
if resp.status_code == 200 and resp.history:
m = re.search(r"/posts/(\S+)", resp.url)
if m:
@@ -544,7 +583,7 @@ class DevPlaceUser(HttpUser):
if slug not in POST_SLUGS:
POST_SLUGS.append(slug)
self.own_post_slugs.append(slug)
m2 = re.search(rf'/votes/post/({UUID_RE})', resp.text)
m2 = re.search(rf"/votes/post/({UUID_RE})", resp.text)
if m2 and m2.group(1) not in POST_UIDS:
POST_UIDS.append(m2.group(1))
resp.success()
@@ -555,18 +594,27 @@ class DevPlaceUser(HttpUser):
def comment_on_post(self):
if not POST_UIDS:
return
self.client.post("/comments/create", data={
"content": f"Comment {uuid.uuid4().hex[:6]} " * 3,
"post_uid": random.choice(POST_UIDS),
}, name="comments/create")
self.client.post(
"/comments/create",
data={
"content": f"Comment {uuid.uuid4().hex[:6]} " * 3,
"post_uid": random.choice(POST_UIDS),
},
name="comments/create",
)
@task(1)
def create_project(self):
with self.client.post("/projects/create", data={
"title": f"Project {uuid.uuid4().hex[:6]}",
"description": "y " * 50,
"project_type": random.choice(PROJECT_TYPES),
}, catch_response=True, name="projects/create") as resp:
with self.client.post(
"/projects/create",
data={
"title": f"Project {uuid.uuid4().hex[:6]}",
"description": "y " * 50,
"project_type": random.choice(PROJECT_TYPES),
},
catch_response=True,
name="projects/create",
) as resp:
m = re.search(r"/projects/(\S+)", resp.url)
if resp.status_code == 200 and m:
slug = m.group(1)
@@ -579,19 +627,24 @@ class DevPlaceUser(HttpUser):
@task(1)
def create_gist(self):
with self.client.post("/gists/create", data={
"title": f"Gist {uuid.uuid4().hex[:6]}",
"description": "Load test gist.",
"source_code": "x = 1\n" * 20,
"language": random.choice(GIST_LANGUAGES),
}, catch_response=True, name="gists/create") as resp:
with self.client.post(
"/gists/create",
data={
"title": f"Gist {uuid.uuid4().hex[:6]}",
"description": "Load test gist.",
"source_code": "x = 1\n" * 20,
"language": random.choice(GIST_LANGUAGES),
},
catch_response=True,
name="gists/create",
) as resp:
m = re.search(r"/gists/(\S+)", resp.url)
if resp.status_code == 200 and m:
slug = m.group(1)
if slug not in GIST_SLUGS:
GIST_SLUGS.append(slug)
self.own_gist_slugs.append(slug)
m2 = re.search(rf'/votes/gist/({UUID_RE})', resp.text)
m2 = re.search(rf"/votes/gist/({UUID_RE})", resp.text)
if m2 and m2.group(1) not in GIST_UIDS:
GIST_UIDS.append(m2.group(1))
resp.success()
@@ -600,10 +653,14 @@ class DevPlaceUser(HttpUser):
@task(1)
def create_bug(self):
self.client.post("/bugs/create", data={
"title": f"Bug {uuid.uuid4().hex[:6]}",
"description": "Load test bug report description.",
}, name="bugs/create")
self.client.post(
"/bugs/create",
data={
"title": f"Bug {uuid.uuid4().hex[:6]}",
"description": "Load test bug report description.",
},
name="bugs/create",
)
# ── social interaction ──────────────────────────────────────
@@ -611,14 +668,14 @@ class DevPlaceUser(HttpUser):
data = {"value": random.choice([1, -1])}
name = f"votes/{target_type}"
if random.random() < 0.5:
self.client.post(
f"/votes/{target_type}/{uid}", data=data, name=name
)
self.client.post(f"/votes/{target_type}/{uid}", data=data, name=name)
return
with self.client.post(
f"/votes/{target_type}/{uid}", data=data,
f"/votes/{target_type}/{uid}",
data=data,
headers={"x-requested-with": "fetch"},
catch_response=True, name=f"{name}/ajax",
catch_response=True,
name=f"{name}/ajax",
) as resp:
try:
payload = resp.json()
@@ -665,9 +722,7 @@ class DevPlaceUser(HttpUser):
targets = [u for u in ALL_USERNAMES if u != self.username]
if not targets:
return
self.client.post(
f"/follow/{random.choice(targets)}", name="follow/[username]"
)
self.client.post(f"/follow/{random.choice(targets)}", name="follow/[username]")
@task(1)
def unfollow_user(self):
@@ -683,19 +738,27 @@ class DevPlaceUser(HttpUser):
if not USER_UIDS or not SEED_USERS:
return
target_uid = random.choice(USER_UIDS)
self.client.post("/messages/send", data={
"content": f"Msg from {self.username}",
"receiver_uid": target_uid,
}, name="messages/send")
self.client.post(
"/messages/send",
data={
"content": f"Msg from {self.username}",
"receiver_uid": target_uid,
},
name="messages/send",
)
# ── user self-management ────────────────────────────────────
@task(1)
def update_profile(self):
self.client.post("/profile/update", data={
"bio": f"Updated at {uuid.uuid4().hex[:6]}",
"location": random.choice(["NL", "US", "DE", "UK", " "]),
}, name="profile/update")
self.client.post(
"/profile/update",
data={
"bio": f"Updated at {uuid.uuid4().hex[:6]}",
"location": random.choice(["NL", "US", "DE", "UK", " "]),
},
name="profile/update",
)
@task(1)
def view_messages(self):
@@ -706,21 +769,21 @@ class DevPlaceUser(HttpUser):
if not USER_UIDS:
return
self.client.get(
"/messages", params={"with_uid": random.choice(USER_UIDS)},
"/messages",
params={"with_uid": random.choice(USER_UIDS)},
name="messages?with_uid",
)
@task(1)
def view_notifications(self):
resp = self.client.get("/notifications", name="notifications")
matches = re.findall(rf'/notifications/mark-read/({UUID_RE})', resp.text)
NOTIFICATION_UIDS.extend(
m for m in matches if m not in NOTIFICATION_UIDS
)
matches = re.findall(rf"/notifications/mark-read/({UUID_RE})", resp.text)
NOTIFICATION_UIDS.extend(m for m in matches if m not in NOTIFICATION_UIDS)
cursor = re.search(r'/notifications\?before=([^"]+)', resp.text)
if cursor:
self.client.get(
"/notifications", params={"before": cursor.group(1)},
"/notifications",
params={"before": cursor.group(1)},
name="notifications?before",
)
@@ -735,7 +798,9 @@ class DevPlaceUser(HttpUser):
@task(1)
def mark_all_notifications_read(self):
self.client.post("/notifications/mark-all-read", name="notifications/mark-all-read")
self.client.post(
"/notifications/mark-all-read", name="notifications/mark-all-read"
)
@task(1)
def mark_one_notification_read(self):
@@ -819,7 +884,8 @@ class DevPlaceUser(HttpUser):
with self.client.post(
"/uploads/upload",
files={"file": (name, content, mime)},
catch_response=True, name="uploads/upload",
catch_response=True,
name="uploads/upload",
) as resp:
if resp.status_code == 201:
resp.success()
@@ -828,9 +894,7 @@ class DevPlaceUser(HttpUser):
except ValueError:
uid = None
if uid:
self.client.delete(
f"/uploads/delete/{uid}", name="uploads/delete"
)
self.client.delete(f"/uploads/delete/{uid}", name="uploads/delete")
else:
resp.failure(f"upload failed: status={resp.status_code}")
@@ -845,8 +909,10 @@ class DevPlaceUser(HttpUser):
},
}
with self.client.post(
"/push.json", json=body,
catch_response=True, name="push.json/register",
"/push.json",
json=body,
catch_response=True,
name="push.json/register",
) as resp:
if resp.status_code in (200, 400):
resp.success()
@@ -867,7 +933,8 @@ class DevPlaceUser(HttpUser):
with self.client.get(
f"/avatar/multiavatar/{seed}?size=32",
headers={"If-None-Match": etag},
catch_response=True, name="avatar/multiavatar/304",
catch_response=True,
name="avatar/multiavatar/304",
) as cached:
if cached.status_code == 304:
cached.success()
@@ -878,11 +945,15 @@ class DevPlaceUser(HttpUser):
def comment_on_news(self):
if not NEWS_UIDS:
return
self.client.post("/comments/create", data={
"content": f"News comment {uuid.uuid4().hex[:6]} " * 2,
"target_uid": random.choice(NEWS_UIDS),
"target_type": "news",
}, name="comments/news")
self.client.post(
"/comments/create",
data={
"content": f"News comment {uuid.uuid4().hex[:6]} " * 2,
"target_uid": random.choice(NEWS_UIDS),
"target_type": "news",
},
name="comments/news",
)
@task(1)
def comment_on_target(self):
@@ -896,34 +967,40 @@ class DevPlaceUser(HttpUser):
if not pools:
return
target_type, uids = random.choice(pools)
self.client.post("/comments/create", data={
"content": f"{target_type} comment {uuid.uuid4().hex[:6]} " * 2,
"target_uid": random.choice(uids),
"target_type": target_type,
}, name=f"comments/{target_type}")
self.client.post(
"/comments/create",
data={
"content": f"{target_type} comment {uuid.uuid4().hex[:6]} " * 2,
"target_uid": random.choice(uids),
"target_type": target_type,
},
name=f"comments/{target_type}",
)
@task(1)
def reply_to_comment(self):
if not POST_UIDS or not COMMENT_UIDS:
return
self.client.post("/comments/create", data={
"content": f"Reply {uuid.uuid4().hex[:6]} " * 2,
"post_uid": random.choice(POST_UIDS),
"parent_uid": random.choice(COMMENT_UIDS),
}, name="comments/reply")
self.client.post(
"/comments/create",
data={
"content": f"Reply {uuid.uuid4().hex[:6]} " * 2,
"post_uid": random.choice(POST_UIDS),
"parent_uid": random.choice(COMMENT_UIDS),
},
name="comments/reply",
)
@task(2)
def browse_and_engage(self):
slugs = POST_SLUGS if POST_SLUGS else POST_UIDS
if not slugs:
return
resp = self.client.get(
f"/posts/{random.choice(slugs)}", name="posts/[uid]"
)
vote_uid = re.search(rf'/votes/post/({UUID_RE})', resp.text)
resp = self.client.get(f"/posts/{random.choice(slugs)}", name="posts/[uid]")
vote_uid = re.search(rf"/votes/post/({UUID_RE})", resp.text)
if vote_uid:
self._vote("post", vote_uid.group(1))
comment_uid = re.search(rf'/comments/delete/({UUID_RE})', resp.text)
comment_uid = re.search(rf"/comments/delete/({UUID_RE})", resp.text)
if comment_uid and comment_uid.group(1) not in COMMENT_UIDS:
COMMENT_UIDS.append(comment_uid.group(1))
@@ -962,9 +1039,13 @@ class AdminUser(HttpUser):
@task(1)
def save_settings(self):
self.client.post("/admin/settings", data={
"max_upload_size_mb": "10",
}, name="admin/settings/save")
self.client.post(
"/admin/settings",
data={
"max_upload_size_mb": "10",
},
name="admin/settings/save",
)
@task(1)
def news_toggle(self):
@@ -1000,7 +1081,8 @@ class AdminUser(HttpUser):
if not uid:
return
self.client.post(
f"/admin/users/{uid}/role", data={"role": "Member"},
f"/admin/users/{uid}/role",
data={"role": "Member"},
name="admin/users/role",
)
@@ -1010,7 +1092,8 @@ class AdminUser(HttpUser):
if not uid:
return
self.client.post(
f"/admin/users/{uid}/password", data={"password": PASSWORD},
f"/admin/users/{uid}/password",
data={"password": PASSWORD},
name="admin/users/password",
)
@@ -1019,9 +1102,7 @@ class AdminUser(HttpUser):
uid = ADMIN_TARGETS.get("disposable_uid")
if not uid:
return
self.client.post(
f"/admin/users/{uid}/toggle", name="admin/users/toggle"
)
self.client.post(f"/admin/users/{uid}/toggle", name="admin/users/toggle")
class AnonymousUser(HttpUser):
@@ -1035,27 +1116,27 @@ class AnonymousUser(HttpUser):
@task(3)
def browse_post(self):
if POST_SLUGS:
self.client.get(
f"/posts/{random.choice(POST_SLUGS)}", name="posts/[uid]"
)
self.client.get(f"/posts/{random.choice(POST_SLUGS)}", name="posts/[uid]")
@task(2)
def browse_public(self):
path = random.choice([
"/", "/news", "/gists", "/projects", "/leaderboard",
])
path = random.choice(
[
"/",
"/news",
"/gists",
"/projects",
"/leaderboard",
]
)
self.client.get(path, name="public/[page]")
@task(2)
def browse_detail(self):
if NEWS_SLUGS:
self.client.get(
f"/news/{random.choice(NEWS_SLUGS)}", name="news/[slug]"
)
self.client.get(f"/news/{random.choice(NEWS_SLUGS)}", name="news/[slug]")
if GIST_SLUGS:
self.client.get(
f"/gists/{random.choice(GIST_SLUGS)}", name="gists/[slug]"
)
self.client.get(f"/gists/{random.choice(GIST_SLUGS)}", name="gists/[slug]")
if PROJECT_SLUGS:
self.client.get(
f"/projects/{random.choice(PROJECT_SLUGS)}", name="projects/[slug]"
@@ -1067,9 +1148,11 @@ class AnonymousUser(HttpUser):
return
uid = random.choice(POST_UIDS)
with self.client.post(
f"/votes/post/{uid}", data={"value": 1},
f"/votes/post/{uid}",
data={"value": 1},
headers={"x-requested-with": "fetch"},
catch_response=True, name="votes/post/guest-redirect",
catch_response=True,
name="votes/post/guest-redirect",
) as resp:
if "/auth/login" in resp.url:
resp.success()
@@ -1079,7 +1162,9 @@ class AnonymousUser(HttpUser):
@task(1)
def guest_guarded_get_redirects_to_login(self):
with self.client.get(
"/messages", catch_response=True, name="guarded/guest-redirect",
"/messages",
catch_response=True,
name="guarded/guest-redirect",
) as resp:
if "/auth/login" in resp.url:
resp.success()