import at_record/gen/defs.{CatalogRef, ExternalId} import at_record/gen/shelf/entry.{type ShelfEntry, ShelfEntry} import at_record/storage.{type StoredItem, StoredItem} import at_record_server/browse.{NetworkMatch} import at_record_server/catalog/row.{type BrowseRow, BrowseRow} import at_record_server/catalog/strategy.{MostAdopted, MostRecent} import at_record_server/known_users.{KnownUser} import atproto/xrpc import gleam/bit_array import gleam/http/response import gleam/list import gleam/option.{type Option, None, Some} import support fn row( uri uri: String, discogs_id discogs_id: Option(String), created_at created_at: String, ) -> BrowseRow { variant_row(uri:, discogs_id:, created_at:, supersedes: None, based_on: None) } fn variant_row( uri uri: String, discogs_id discogs_id: Option(String), created_at created_at: String, supersedes supersedes: Option(String), based_on based_on: Option(String), ) -> BrowseRow { BrowseRow( uri:, cid: "bafyrow", title: "Title", artist_display: None, genres: [], styles: [], released: None, country: None, cover: None, thumb_url: None, discogs_id:, created_at:, publisher_did: "did:plc:pub", publisher_handle: "pub.test", publisher_pds: "https://pds.test", supersedes:, based_on:, ) } fn genesis( rkey rkey: String, action action: String, release_uri release_uri: Option(String), discogs_ids discogs_ids: List(String), ) -> StoredItem(ShelfEntry) { let external_ids = case discogs_ids { [] -> None ids -> Some( list.map(ids, fn(id) { ExternalId(id:, provider: "discogs", url: None) }), ) } StoredItem( uri: "at://did:plc:me/dev.mokkenstorm.crate.shelf.entry/" <> rkey, cid: "bafy" <> rkey, rkey:, value: ShelfEntry( ..support.blank_shelf_entry(), action:, external_ids:, release: release_uri |> option.map(fn(u) { CatalogRef(uri: u, cid: "bafyrel", external_ids: None) }), ), ) } pub fn resolve_variants_groups_by_natural_key_or_leaves_singletons_test() { let cases = [ #( [ #("at://a/1", Some("42")), #("at://b/2", Some("42")), #("at://c/3", Some("99")), ], 2, ), #([#("at://a/1", None), #("at://b/2", None)], 2), ] cases |> list.each(fn(c) { let #(specs, expected_groups) = c let rows = specs |> list.map(fn(s) { let #(uri, discogs_id) = s row(uri:, discogs_id:, created_at: "z") }) let resolved = browse.resolve_variants(rows, fn(_uri) { 0 }, MostAdopted) assert list.length(resolved) == expected_groups }) } pub fn resolve_variants_switches_winner_by_strategy_test() { let old = row(uri: "at://old/1", discogs_id: Some("42"), created_at: "2020-01-01") let new = row(uri: "at://new/1", discogs_id: Some("42"), created_at: "2024-01-01") let cases = [ #( MostAdopted, fn(uri) { case uri { "at://old/1" -> 5 _ -> 1 } }, "at://old/1", ), #(MostRecent, fn(_uri) { 0 }, "at://new/1"), ] cases |> list.each(fn(c) { let #(chosen, adoption_count, expected_winner) = c let assert [resolved] = browse.resolve_variants([old, new], adoption_count, chosen) assert resolved.row.uri == expected_winner }) } pub fn resolve_variants_groups_a_basedon_fork_without_a_shared_discogs_id_test() { let original = row(uri: "at://a/1", discogs_id: Some("42"), created_at: "2020-01-01") let fork = variant_row( uri: "at://b/1", discogs_id: Some("99"), created_at: "2024-01-01", supersedes: None, based_on: Some("at://a/1"), ) let resolved = browse.resolve_variants([original, fork], fn(_uri) { 0 }, MostRecent) let assert [winner] = resolved assert winner.variant_count == 2 assert winner.row.uri == "at://b/1" } pub fn year_from_released_parses_or_rejects_test() { assert browse.year_from_released(Some("1991-03-27")) == Some(1991) assert browse.year_from_released(Some("1991")) == Some(1991) assert browse.year_from_released(None) == None assert browse.year_from_released(Some("")) == None assert browse.year_from_released(Some("abcd")) == None assert browse.year_from_released(Some("197")) == None assert browse.year_from_released(Some("91")) == None } pub fn ownership_matches_by_release_uri_test() { let stored = [ genesis( rkey: "3owned", action: "acquired", release_uri: Some("at://did:plc:pub/rel/1"), discogs_ids: [], ), ] let own = browse.ownership(stored) let hit = row(uri: "at://did:plc:pub/rel/1", discogs_id: None, created_at: "z") let miss = row(uri: "at://did:plc:pub/rel/2", discogs_id: None, created_at: "z") assert browse.flags(own, hit.uri, hit.discogs_id) == #(True, False) assert browse.flags(own, miss.uri, miss.discogs_id) == #(False, False) } pub fn ownership_matches_by_discogs_id_across_status_test() { let stored = [ genesis(rkey: "3owned", action: "acquired", release_uri: None, discogs_ids: [ "42", ]), genesis(rkey: "3wanted", action: "wanted", release_uri: None, discogs_ids: [ "99", ]), ] let own = browse.ownership(stored) let owned_row = row(uri: "at://other/x", discogs_id: Some("42"), created_at: "z") let wanted_row = row(uri: "at://other/y", discogs_id: Some("99"), created_at: "z") let unknown_row = row(uri: "at://other/z", discogs_id: Some("7"), created_at: "z") assert browse.flags(own, owned_row.uri, owned_row.discogs_id) == #(True, False) assert browse.flags(own, wanted_row.uri, wanted_row.discogs_id) == #(False, True) assert browse.flags(own, unknown_row.uri, unknown_row.discogs_id) == #(False, False) } fn a_known_user(handle: String, pds: String) -> known_users.KnownUser { KnownUser(did: "did:plc:" <> handle, handle:, pds:) } fn list_records_body( uri: String, cid: String, identifiers_json: String, ) -> String { "{\"records\":[{\"uri\":\"" <> uri <> "\",\"cid\":\"" <> cid <> "\",\"value\":{\"title\":\"Spiderland\",\"artistDisplay\":\"Slint\",\"createdAt\":\"2026-01-01T00:00:00Z\",\"identifiers\":" <> identifiers_json <> "}}]}" } fn empty_records_body() -> String { "{\"records\":[]}" } fn client_with_body(body: String) -> xrpc.Client { xrpc.Client(send: fn(_req) { Ok(response.Response(200, [], bit_array.from_string(body))) }) } pub fn find_by_barcode_matches_despaced_identifiers_on_both_sides_test() { let body = list_records_body( "at://did:plc:pub/dev.mokkenstorm.crate.catalog.release/r1", "bafyrel", "[{\"type\":\"Barcode\",\"value\":\"01234567 89011\"}]", ) let user = a_known_user("pub.test", "https://pds.test") let found = browse.find_by_barcode(client_with_body(body), [user], "0123456789011") assert found == Some(NetworkMatch( uri: "at://did:plc:pub/dev.mokkenstorm.crate.catalog.release/r1", cid: "bafyrel", title: "Spiderland", artist_display: Some("Slint"), thumb_url: None, publisher_handle: "pub.test", )) } pub fn find_by_barcode_ignores_non_barcode_identifiers_test() { let body = list_records_body( "at://did:plc:pub/dev.mokkenstorm.crate.catalog.release/r1", "bafyrel", "[{\"type\":\"CatalogNumber\",\"value\":\"0123456789011\"}]", ) let user = a_known_user("pub.test", "https://pds.test") let found = browse.find_by_barcode(client_with_body(body), [user], "0123456789011") assert found == None } pub fn find_by_barcode_misses_across_every_known_user_test() { let user_a = a_known_user("a.test", "https://a.test") let user_b = a_known_user("b.test", "https://b.test") let found = browse.find_by_barcode( client_with_body(empty_records_body()), [user_a, user_b], "0123456789011", ) assert found == None } pub fn find_by_barcode_stops_at_the_first_hit_test() { let hit_body = list_records_body( "at://did:plc:first/dev.mokkenstorm.crate.catalog.release/r1", "bafyrel", "[{\"type\":\"Barcode\",\"value\":\"0123456789011\"}]", ) let first = a_known_user("first.test", "https://first.test") // Panics if queried: proves the fan-out short-circuits on the first hit. let unreachable = KnownUser( did: "did:plc:second", handle: "second.test", pds: "https://second.test", ) let client = xrpc.Client(send: fn(req) { case req.host { "first.test" -> Ok(response.Response(200, [], bit_array.from_string(hit_body))) _ -> panic as "the fan-out should have stopped after the first hit" } }) let found = browse.find_by_barcode(client, [first, unreachable], "0123456789011") assert found == Some(NetworkMatch( uri: "at://did:plc:first/dev.mokkenstorm.crate.catalog.release/r1", cid: "bafyrel", title: "Spiderland", artist_display: Some("Slint"), thumb_url: None, publisher_handle: "first.test", )) }