Something went wrong. Try again.
Paper Mario atproto mod hosting site starhaven.dev
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148import pytestimport requestsfrom playwright.sync_api import expect
from helpers import Actor
COLLECTION = "dev.starhaven.mod.version"LISTING_COLLECTION = "dev.starhaven.mod.listing"
def test_publish_version_writes_to_pds_and_serves_the_file(actor: Actor): actor.login() actor.create_mod("test-mod") actor.publish_version("test-mod", "v1.0", "Added cats", deliverable=b"patch bytes")
[record] = actor.records(COLLECTION) assert record["value"]["$type"] == COLLECTION assert record["value"]["name"] == "v1.0" assert record["value"]["description"] == "Added cats"
# The version points at the listing it is a version of. [listing] = actor.records(LISTING_COLLECTION) assert record["value"]["mod"] == listing["uri"]
# The deliverable is readable by anyone, with no signature. response = requests.get(record["value"]["deliverable"], timeout=30) response.raise_for_status() assert response.content == b"patch bytes"
def test_the_card_offers_the_newest_version_and_the_tab_lists_them_all(actor: Actor): actor.login() actor.create_mod("test-mod") expect(actor.page.get_by_text("This mod has no downloads yet.")).to_be_visible()
actor.publish_version("test-mod", "v1.0", "Added cats") actor.publish_version("test-mod", "v2.0", "Added dogs")
actor.page.goto(f"{actor.app_url}/{actor.handle}/test-mod") expect(actor.page.get_by_role("link", name="Download v2.0")).to_be_visible()
actor.page.get_by_role("link", name="Versions").click() expect(actor.page.locator(".version-header h2").first).to_be_visible() names = actor.page.locator(".version-header h2").all_text_contents() assert names == ["v2.0", "v1.0"]
def test_the_version_form_still_works_after_an_htmx_tab_swap(actor: Actor): """The dialog and its upload script arrive in the fragment, not the document.""" actor.login() actor.create_mod("test-mod") actor.page.goto(f"{actor.app_url}/{actor.handle}/test-mod")
# Survives the swap only if the document was never reloaded. actor.page.evaluate("window.__notReloaded = true") actor.page.get_by_role("link", name="Versions").click() expect(actor.page).to_have_url(f"{actor.app_url}/{actor.handle}/test-mod/versions") assert actor.page.evaluate("window.__notReloaded") is True
# The form is folded away until asked for, then publishes for real. version = actor.page.get_by_label("Version", exact=True) expect(version).to_be_hidden() actor.publish_version("test-mod", "v1.0", "Added cats", goto=False)
[record] = actor.records(COLLECTION) assert record["value"]["name"] == "v1.0"
def test_the_form_marks_no_field_until_one_is_actually_wrong(actor: Actor): actor.login() actor.create_mod("test-mod") actor.page.goto(f"{actor.app_url}/{actor.handle}/test-mod/versions") actor.page.get_by_role("button", name="Upload a new version").click()
# An empty error slot must not make its field look rejected. marked = ".form-item:has(.error:not([hidden]))" assert actor.page.locator(marked).count() == 0
actor.page.get_by_role("button", name="Publish version").click()
# Every empty field is reported at once, not one per attempt, and each # message appears against its own field as well as in the summary. summary = actor.page.locator("#version-dialog-summary") expect(summary).to_be_visible() assert summary.locator("li").all_text_contents() == [ "Enter a version", "Enter what changed", "Select a file", ] for field in ["version-name", "version-description", "version-file"]: expect(actor.page.locator(f"#{field}-error")).to_be_visible()
# Filling one in takes its error away and leaves the others. actor.page.get_by_label("Version", exact=True).fill("v1.0") actor.page.get_by_role("button", name="Publish version").click() assert summary.locator("li").all_text_contents() == [ "Enter what changed", "Select a file", ] expect(actor.page.locator("#version-name-error")).to_be_hidden()
def test_a_stranger_can_neither_publish_nor_be_offered_the_form(actor: Actor): actor.login() actor.create_mod("test-mod") actor.page.context.clear_cookies()
actor.page.goto(f"{actor.app_url}/{actor.handle}/test-mod/versions") expect(actor.page.get_by_role("button", name="Upload a new version")).to_have_count(0)
# The UI hiding it is not the check that matters. response = requests.post( f"{actor.app_url}/{actor.handle}/test-mod/versions/presign", json={"filename": "mod.bps", "size": 1024}, timeout=10, ) assert response.status_code == 403
def test_deleting_a_mod_takes_its_versions_off_the_site(actor: Actor): actor.login() actor.create_mod("test-mod") actor.publish_version("test-mod", "v1.0", "Added cats") actor.delete_mod("test-mod")
actor.page.goto(f"{actor.app_url}/{actor.handle}/test-mod/versions") expect(actor.page.get_by_role("heading", name="v1.0")).to_have_count(0)
# 12KB of room, so two 8KB uploads fit individually but not together.@pytest.mark.parametrize( "server_args", [["--s3-user-quota-bytes", "12288"]], indirect=True)def test_the_quota_counts_every_mod_the_user_has(actor: Actor): actor.login() actor.create_mod("first-mod", title="First Mod") actor.create_mod("second-mod", title="Second Mod")
# Fits on its own, and uses most of the quota. actor.publish_version("first-mod", "v1.0", "Added cats", deliverable=b"x" * 8000)
# Would fit on its own too, but not on top of the first - and it is a # version of a different mod, so this is the per-user total being counted. actor.submit_version("second-mod", "v1.0", "Added dogs", deliverable=b"x" * 8000)
assert "you have left" in actor.version_error() assert len(actor.records(COLLECTION)) == 1