srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/web/tests/helpers.py
blob: 285b769b4ffb9625c68751a2409f510dd9f48314 (plain) (blame)
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
"""Shared helpers for the Playwright test suite. See README.md for how to
run these tests and what needs to already be running.
"""
import os
import random
import string
import subprocess

FRONTEND_URL = "http://localhost:4173"

# Buying is a real payment now, so a test cannot get an item by clicking Buy.
# Ownership is granted straight in the database instead, which is what a paid
# webhook would have done.
DATABASE_URL = os.environ.get(
    "TYPERPUNK_TEST_DATABASE_URL",
    "postgresql://typerpunk:typerpunk@localhost/typerpunk",
)


def grant_cosmetics(username, cosmetic_ids):
    """Gives an account the named cosmetics without going through checkout."""
    ids = ", ".join(f"'{cid}'" for cid in cosmetic_ids)
    sql = (
        "INSERT INTO user_cosmetics (user_id, cosmetic_id, acquired_at) "
        "SELECT u.id, c.id, '2026-01-01T00:00:00Z' "
        "FROM users u CROSS JOIN cosmetics c "
        f"WHERE u.username = '{username}' AND c.id IN ({ids}) "
        "ON CONFLICT (user_id, cosmetic_id) DO NOTHING"
    )
    subprocess.run(
        ["psql", DATABASE_URL, "-v", "ON_ERROR_STOP=1", "-c", sql],
        check=True, capture_output=True,
    )


def random_username(prefix="test"):
    suffix = "".join(random.choices(string.ascii_lowercase + string.digits, k=8))
    return f"{prefix}_{suffix}"


def random_password():
    """A fresh password per run. These accounts are throwaway, so nothing is
    gained by a fixed literal - and a hardcoded one in a checked-in file has
    the shape of a real credential, which trips secret scanners."""
    return "Tp" + "".join(random.choices(string.ascii_letters + string.digits, k=16))


def register_and_login(page, username, password=None):
    """Registers a fresh account through the real Account screen and leaves
    the app on the main menu, signed in."""
    password = password or random_password()
    page.goto(FRONTEND_URL, timeout=40000)
    # The account entry point is the top-right identity control: "Sign In"
    # when signed out, your username once signed in. It used to be an icon in
    # the main menu's bottom-left cluster.
    page.click('.auth-control button')
    page.wait_for_timeout(300)
    page.click('[data-action="tab-register"]')
    page.fill('input[name="username"]', username)
    page.fill('input[name="password"]', password)
    page.click('.account-form button[type="submit"]')
    page.wait_for_selector('.account-signed-in', timeout=10000)
    page.click('[data-action="menu"]')
    page.wait_for_timeout(300)