Something went wrong. Try again.
Paper Mario mod hosting site - AT Protocol appview starhaven.dev
appview
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185import sqlite3import time
import requestsfrom playwright.sync_api import expect
from conftest import Appviewfrom helpers import Actorfrom test_media_gallery import PNG
LISTING_COLLECTION = "dev.starhaven.mod.listing"VERSION_COLLECTION = "dev.starhaven.mod.version"
def offer(sender: Actor, slug: str, recipient: Actor) -> None: """Offers one of the sender's mods to the recipient from its settings.""" page = sender.page page.goto(f"{sender.app_url}/{sender.handle}/{slug}/settings") page.get_by_role("button", name="Transfer", exact=True).click() page.get_by_label("Handle").fill(recipient.handle) page.get_by_role("button", name="Find account").click() page.get_by_role("button", name=f"Transfer to @{recipient.handle}").click() expect(page.get_by_text(f"Waiting for @{recipient.handle} to accept this mod")).to_be_visible()
def banner(actor: Actor): return actor.page.locator(".transfer-offers")
def test_an_offer_shows_only_to_its_recipient_who_can_decline_it(actor: Actor, other_actor: Actor): actor.login() actor.create_mod("test-mod")
# A handle nobody has is refused before anything is offered. actor.page.goto(f"{actor.app_url}/{actor.handle}/test-mod/settings") actor.page.get_by_role("button", name="Transfer", exact=True).click() actor.page.get_by_label("Handle").fill("nobody-has-this.test") actor.page.get_by_role("button", name="Find account").click() expect(actor.page.get_by_text("Handle must belong to an existing account")).to_be_visible()
offer(actor, "test-mod", other_actor) actor.page.goto(f"{actor.app_url}/") expect(banner(actor)).to_have_count(0)
other_actor.login() expect(banner(other_actor)).to_contain_text( f"@{actor.handle} has requested to transfer Test Mod to you" ) other_actor.page.get_by_role("button", name="Decline").click() expect(banner(other_actor)).to_have_count(0)
# The sender can offer it again. actor.page.goto(f"{actor.app_url}/{actor.handle}/test-mod/settings") expect(actor.page.get_by_role("button", name="Transfer", exact=True)).to_be_visible()
def test_the_sender_can_cancel_an_offer(actor: Actor, other_actor: Actor): actor.login() actor.create_mod("test-mod") offer(actor, "test-mod", other_actor) actor.page.get_by_role("button", name="Cancel transfer").click() expect(actor.page.get_by_role("button", name="Transfer", exact=True)).to_be_visible()
other_actor.login() expect(banner(other_actor)).to_have_count(0)
def test_an_offer_expires(appview: Appview, actor: Actor, other_actor: Actor): actor.login() actor.create_mod("test-mod") offer(actor, "test-mod", other_actor)
with sqlite3.connect(appview.database) as db: db.execute("UPDATE mod_transfer SET expires_at = '2000-01-01T00:00:00.000Z'")
other_actor.login() expect(banner(other_actor)).to_have_count(0) actor.page.goto(f"{actor.app_url}/{actor.handle}/test-mod/settings") expect(actor.page.get_by_role("button", name="Transfer", exact=True)).to_be_visible()
def test_only_the_owner_can_offer_a_mod(actor: Actor, other_actor: Actor): actor.login() actor.create_mod("test-mod")
other_actor.login() response = other_actor.page.request.post( f"{actor.app_url}/{actor.handle}/test-mod/transfer", form={"recipient": other_actor.did}, ) assert response.status == 403 expect(banner(other_actor)).to_have_count(0)
def test_accepting_moves_the_mod_its_versions_and_downloads(actor: Actor, other_actor: Actor): actor.login() actor.create_mod("test-mod") actor.page.goto(f"{actor.app_url}/{actor.handle}/test-mod/settings") actor.remove_images() actor.page.locator("media-input input[type=file]").set_input_files( files=[{"name": "one.png", "mimeType": "image/png", "buffer": PNG}] ) expect(actor.page.locator("media-input .item")).to_have_count(1, timeout=15000) actor.page.locator("media-input .alt").first.fill("A screenshot") actor.page.get_by_role("button", name="Save").click() expect(actor.page).to_have_url(f"{actor.app_url}/{actor.handle}/test-mod") actor.publish_version("test-mod", "v1.0", "Added cats", deliverable=b"BPS1 first") actor.publish_version("test-mod", "v2.0", "Added dogs", deliverable=b"BPS1 second") [old_listing] = actor.records(LISTING_COLLECTION) old_downloads = { r["value"]["name"]: r["value"]["deliverable"] for r in actor.records(VERSION_COLLECTION) } offer(actor, "test-mod", other_actor)
other_actor.login() other_actor.page.get_by_role("button", name="Accept").click() expect(other_actor.page).to_have_url(f"{other_actor.app_url}/{other_actor.handle}/test-mod") expect(banner(other_actor)).to_have_count(0)
# The copies are in the recipient's repo, written by them. [listing] = other_actor.records(LISTING_COLLECTION) assert listing["value"]["title"] == "Test Mod" [image] = listing["value"]["media"] assert image["alt"] == "A screenshot" blob = requests.get( f"{other_actor.pds_url}/xrpc/com.atproto.sync.getBlob", params={"did": other_actor.did, "cid": image["file"]["ref"]["$link"]}, timeout=5, ) blob.raise_for_status() assert blob.content == PNG versions = other_actor.records(VERSION_COLLECTION) assert {v["value"]["mod"] for v in versions} == {listing["uri"]}
other_actor.page.get_by_role("link", name="Versions").click() expect(other_actor.page.locator(".version-header h2").first).to_be_visible() assert other_actor.page.locator(".version-header h2").all_text_contents() == [ "v2.0", "v1.0", "1.0", ]
# Each download is the same file, now served from the recipient's mod. for version in versions: url = version["value"]["deliverable"] assert other_actor.did in url response = requests.get(url, timeout=30) response.raise_for_status() expected = {"1.0": b"BPS1 a patch file", "v1.0": b"BPS1 first", "v2.0": b"BPS1 second"} assert response.content == expected[version["value"]["name"]]
# The old addresses lead to the new ones. response = requests.get( f"{actor.app_url}/{actor.handle}/test-mod/versions", allow_redirects=False, timeout=5 ) assert response.status_code == 308 assert response.headers["location"] == f"/{other_actor.handle}/test-mod/versions" response = requests.get(old_downloads["v1.0"], timeout=30) assert response.history[0].status_code == 308 assert response.content == b"BPS1 first"
# The sender's next visit deletes the originals from their repo. actor.page.goto(f"{actor.app_url}/") deadline = time.monotonic() + 10 while actor.records(LISTING_COLLECTION) or actor.records(VERSION_COLLECTION): assert time.monotonic() < deadline, f"{old_listing['uri']} was never deleted" time.sleep(0.2)
# Their downloads still work, from the copies. response = requests.get(versions[0]["value"]["deliverable"], timeout=30) response.raise_for_status()
def test_a_taken_slug_gets_a_number(actor: Actor, other_actor: Actor): actor.login() actor.create_mod("test-mod") offer(actor, "test-mod", other_actor)
other_actor.login() other_actor.create_mod("test-mod") other_actor.page.get_by_role("button", name="Accept").click() expect(other_actor.page.get_by_text("so this one is at")).to_be_visible() other_actor.page.get_by_role("link", name=f"/{other_actor.handle}/test-mod-2").click() expect(other_actor.page.get_by_role("heading", name="Test Mod", exact=True)).to_be_visible()