diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-15 02:16:39 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-15 02:21:01 +0200 |
| commit | bdefcd025604f2c3009fe5e0cc01213c2ba62a6a (patch) | |
| tree | eebd34aa234a9148045ca25b00bf7c8039e00ccf /packages/meshbay-hub/tests/test_username_floor.py | |
| parent | 027e7d55f3bb57ba5150fd77e8f0114a0baf8d5c (diff) | |
| download | meshbay-bdefcd025604f2c3009fe5e0cc01213c2ba62a6a.tar.gz | |
feat(hub): usernames are at least 8 characters at registration
Existing shorter accounts keep signing in. Test usernames padded to match.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XuNrwLf5EFWCMHzfoEvnpm
Diffstat (limited to 'packages/meshbay-hub/tests/test_username_floor.py')
| -rw-r--r-- | packages/meshbay-hub/tests/test_username_floor.py | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/packages/meshbay-hub/tests/test_username_floor.py b/packages/meshbay-hub/tests/test_username_floor.py new file mode 100644 index 0000000..607aacc --- /dev/null +++ b/packages/meshbay-hub/tests/test_username_floor.py @@ -0,0 +1,58 @@ +""" +A username is at least 8 characters — at registration, and nowhere else. + +Accounts created under the older 3-character floor must keep signing in, so +the check lives on `RegisterRequest` alone. The client checks the same number +before deriving anything; the two constants are held equal here. +""" + +import re +from pathlib import Path + +import pytest +from meshbay_hub.api import users + +AUTH_PAGE = (Path(__file__).resolve().parents[1] + / "src" / "meshbay_hub" / "static" / "auth-page.js") +AUTH_KEY = "k" * 44 + + +async def _register(client, username): + return await client.post("/v1/users/register", json={ + "username": username, "email": "floor@example.com", "auth_key": AUTH_KEY}) + + +@pytest.mark.asyncio +async def test_seven_characters_is_refused(client): + r = await _register(client, "sevenc7") + assert r.status_code == 422, r.text + + +@pytest.mark.asyncio +async def test_surrounding_spaces_do_not_count(client): + r = await _register(client, " sevenc7 ") + assert r.status_code == 422, r.text + + +@pytest.mark.asyncio +async def test_eight_characters_is_accepted(client): + r = await _register(client, "eightch8") + assert r.status_code == 201, r.text + + +@pytest.mark.asyncio +async def test_an_existing_short_account_still_signs_in(client, monkeypatch): + """An account made under the old floor is not locked out by the new one.""" + monkeypatch.setattr(users, "USERNAME_MIN_LEN", 3) + assert (await _register(client, "bob")).status_code == 201 + monkeypatch.setattr(users, "USERNAME_MIN_LEN", 8) + + r = await client.post("/v1/users/login", json={"username": "bob", "auth_key": AUTH_KEY}) + assert r.status_code == 200, r.text + + +def test_the_client_checks_the_same_floor(): + m = re.search(r"^const USERNAME_MIN_LEN = (\d+);", AUTH_PAGE.read_text(encoding="utf-8"), + re.M) + assert m, "auth-page.js no longer declares USERNAME_MIN_LEN" + assert int(m.group(1)) == users.USERNAME_MIN_LEN |