import at_record/gen/catalog/edit as catalog_edit import at_record/gen/catalog/list_edit_proposals.{ProposalRow} import at_record/gen/catalog/release as catalog_release import at_record/gen/defs.{CatalogRef} import at_record_server/catalog_deps.{type Deps, Deps} import at_record_server/edit_inbox.{type OwnRelease, OwnRelease} import at_record_server/oauth/sessions.{type OauthSession} import atproto/constellation.{type Backlink, Backlink, BacklinksPage} import atproto/uri import atproto/xrpc import gleam/int import gleam/list import gleam/option.{None, Some} import support const own_did = "did:plc:me" const other_did = "did:plc:someone" fn session() -> OauthSession { support.stub_session() } /// A client whose every request fails, so `handle_resolver.resolve_handle` /// degrades to `None` without needing a live PLC directory. fn no_network_client() -> xrpc.Client { xrpc.Client(send: fn(_req) { Error("offline") }) } /// [1, 2, .., count] fn range(count: Int) -> List(Int) { list.repeat(Nil, count) |> list.index_map(fn(_, i) { i + 1 }) } fn release( title: String, created_at: String, ) -> catalog_release.CatalogRelease { catalog_release.CatalogRelease( ..support.blank_catalog_release(), title:, created_at:, released: Some("1991"), country: Some("US"), genres: Some(["Rock"]), ) } fn own_release( n: Int, supersedes: option.Option(defs.CatalogRef), ) -> OwnRelease { let uri = "at://" <> own_did <> "/dev.mokkenstorm.crate.catalog.release/r" <> int.to_string(n) OwnRelease( ref: CatalogRef( uri:, cid: "bafyrel" <> int.to_string(n), external_ids: None, ), value: catalog_release.CatalogRelease( ..release( "Spiderland " <> int.to_string(n), "2026-01-0" <> int.to_string(n % 9 + 1) <> "T00:00:00Z", ), supersedes:, ), ) } fn release_fields(title: String) -> catalog_edit.ReleaseFields { catalog_edit.ReleaseFields( title: Some(title), released: None, country: None, genres: None, styles: None, thumb_url: None, cover: None, ) } fn edit_record( entity: String, target_uri: String, fields: option.Option(catalog_edit.ReleaseFields), ) -> catalog_edit.CatalogEdit { catalog_edit.CatalogEdit( created_at: "2026-02-01T00:00:00Z", entity:, fields: option.map(fields, catalog_edit.CatalogEditFieldsReleaseFields), op: "update", rationale: None, source: None, subject: Some(CatalogRef( uri: target_uri, cid: "bafyold", external_ids: None, )), ) } fn backlink(did: String, n: Int) -> Backlink { Backlink( did:, collection: "dev.mokkenstorm.crate.catalog.edit", rkey: "e" <> int.to_string(n), ) } /// Deps whose `backlinks` returns one backlink per own release (via `n`) and /// whose `fetch_edit` looks the matching edit record up from `edits`. fn deps_with( backlinks_by_release: fn(String) -> List(Backlink), edits: fn(String) -> option.Option(#(String, catalog_edit.CatalogEdit)), ) -> Deps { Deps( backlinks: fn(subject, _source) { Ok(BacklinksPage( total: 0, records: backlinks_by_release(subject), cursor: None, )) }, fetch_release: fn(_) { panic as "fetch_release must not be called" }, fetch_edit: edits, release_mbid: fn(_, _) { panic as "release_mbid must not be called" }, ) } pub fn current_only_drops_a_release_another_own_release_supersedes_test() { let old = own_release(1, None) let new = own_release(2, Some(old.ref)) let rows = edit_inbox.current_only([old, new]) assert list.map(rows, fn(r) { r.ref.uri }) == [new.ref.uri] } pub fn current_only_keeps_independent_releases_test() { let a = own_release(1, None) let b = own_release(2, None) let rows = edit_inbox.current_only([a, b]) assert list.length(rows) == 2 } pub fn own_authored_proposal_is_excluded_test() { let owned = own_release(1, None) let deps = deps_with(fn(_subject) { [backlink(own_did, 1)] }, fn(_uri) { Some(#( "bafyedit1", edit_record( "release", owned.ref.uri, Some(release_fields("Better Title")), ), )) }) let rows = edit_inbox.list_proposals(deps, no_network_client(), session(), [owned]) assert rows == [] } pub fn foreign_release_entity_proposal_is_included_test() { let owned = own_release(1, None) let deps = deps_with(fn(_subject) { [backlink(other_did, 1)] }, fn(_uri) { Some(#( "bafyedit1", edit_record( "release", owned.ref.uri, Some(release_fields("Better Title")), ), )) }) let rows = edit_inbox.list_proposals(deps, no_network_client(), session(), [owned]) let assert [ ProposalRow( proposer_did:, target_uri:, release_title:, fields:, current:, .., ), ] = rows assert proposer_did == other_did assert target_uri == owned.ref.uri assert release_title == owned.value.title assert fields == Some(release_fields("Better Title")) assert current == Some(catalog_edit.ReleaseFields( title: Some(owned.value.title), released: owned.value.released, country: owned.value.country, genres: owned.value.genres, styles: owned.value.styles, thumb_url: None, cover: None, )) } pub fn proposer_handle_resolution_failure_degrades_silently_test() { let owned = own_release(1, None) let deps = deps_with(fn(_subject) { [backlink(other_did, 1)] }, fn(_uri) { Some(#( "bafyedit1", edit_record( "release", owned.ref.uri, Some(release_fields("Better Title")), ), )) }) let rows = edit_inbox.list_proposals(deps, no_network_client(), session(), [owned]) let assert [ProposalRow(proposer_handle:, ..)] = rows assert proposer_handle == None } pub fn non_release_entity_proposal_is_dropped_test() { let owned = own_release(1, None) let deps = deps_with(fn(_subject) { [backlink(other_did, 1)] }, fn(_uri) { Some(#( "bafyedit1", edit_record("artist", owned.ref.uri, Some(release_fields("x"))), )) }) let rows = edit_inbox.list_proposals(deps, no_network_client(), session(), [owned]) assert rows == [] } pub fn proposal_targeting_a_different_release_is_dropped_test() { let owned = own_release(1, None) let deps = deps_with(fn(_subject) { [backlink(other_did, 1)] }, fn(_uri) { Some(#( "bafyedit1", edit_record( "release", "at://someone/else/rkey", Some(release_fields("x")), ), )) }) let rows = edit_inbox.list_proposals(deps, no_network_client(), session(), [owned]) assert rows == [] } pub fn a_failed_backlinks_lookup_skips_that_release_rather_than_failing_test() { let owned = own_release(1, None) let deps = Deps( backlinks: fn(_subject, _source) { Error(xrpc.RequestFailed("down")) }, fetch_release: fn(_) { panic as "fetch_release must not be called" }, fetch_edit: fn(_) { panic as "fetch_edit must not be called" }, release_mbid: fn(_, _) { panic as "release_mbid must not be called" }, ) let rows = edit_inbox.list_proposals(deps, no_network_client(), session(), [owned]) assert rows == [] } pub fn release_fanout_is_capped_newest_first_test() { let count = edit_inbox.release_fanout_cap + 5 let owns = range(count) |> list.map(fn(n) { own_release(n, None) }) // Each release's backlink rkey carries the release's own rkey, so // `fetch_edit` (keyed only on the resulting edit uri) can rebuild a // proposal targeting exactly the release that was queried. let deps = deps_with( fn(subject) { [ Backlink( did: other_did, collection: catalog_edit.collection, rkey: uri.rkey(subject), ), ] }, fn(edit_uri) { let target_uri = "at://" <> own_did <> "/" <> catalog_release.collection <> "/" <> uri.rkey(edit_uri) Some(#( "bafyedit", edit_record("release", target_uri, Some(release_fields("x"))), )) }, ) let rows = edit_inbox.list_proposals(deps, no_network_client(), session(), owns) assert list.length(rows) == edit_inbox.release_fanout_cap } pub fn merged_proposal_cap_applies_across_a_single_release_test() { let owned = own_release(1, None) let count = edit_inbox.proposal_cap + 5 let backlinks = range(count) |> list.map(fn(n) { backlink(other_did, n) }) let deps = deps_with(fn(_subject) { backlinks }, fn(_uri) { Some(#( "bafyedit", edit_record("release", owned.ref.uri, Some(release_fields("x"))), )) }) let rows = edit_inbox.list_proposals(deps, no_network_client(), session(), [owned]) assert list.length(rows) == edit_inbox.proposal_cap }