import at_record_web/model.{ type EditProposal, EditProposal, InboxCard, InboxFailed, InboxLoaded, InboxLoading, ProposalApplied, ProposalFields, ProposalReviewing, } import at_record_web/pages/edit_proposal import gleam/option.{None, Some} import gleam/string import lustre/element fn an_edit_proposal(uri: String) -> EditProposal { EditProposal( uri:, cid: "cid-1", proposer_did: "did:plc:bob", proposer_handle: Some("bob.test"), target_uri: "at://did:plc:alice/dev.mokkenstorm.crate.catalog.release/r1", release_title: "Spiderland", current: ProposalFields( title: Some("Spiderland"), released: Some("1991"), country: Some("US"), genres: Some(["Rock"]), styles: None, ), fields: ProposalFields( title: Some("Spiderland (Remastered)"), released: None, country: None, genres: None, styles: None, ), created_at: "2026-02-01T00:00:00Z", subject_adoption_count: None, ) } pub fn proposal_route_id_percent_encodes_the_at_uri_test() { let id = model.proposal_route_id("at://did:plc:bob/collection/rkey1") // No literal slashes/colons survive, so the id stays one path segment. assert !string.contains(id, "/") assert !string.contains(id, ":") } pub fn find_proposal_card_matches_by_route_id_test() { let proposal = an_edit_proposal("at://proposer/edit/1") let card = InboxCard(proposal:, status: ProposalReviewing) let id = model.proposal_route_id("at://proposer/edit/1") assert model.find_proposal_card(InboxLoaded([card]), id) == Some(card) } pub fn find_proposal_card_is_none_for_an_unknown_id_test() { let proposal = an_edit_proposal("at://proposer/edit/1") let card = InboxCard(proposal:, status: ProposalReviewing) assert model.find_proposal_card(InboxLoaded([card]), "unknown") == None } pub fn find_proposal_card_is_none_while_loading_or_failed_test() { assert model.find_proposal_card(InboxLoading, "any") == None assert model.find_proposal_card(InboxFailed, "any") == None } fn rendered(proposal: EditProposal) -> String { InboxCard(proposal:, status: ProposalReviewing) |> edit_proposal.view |> element.to_string } pub fn view_renders_the_section_band_with_changed_and_tracked_field_counts_test() { let html = rendered(an_edit_proposal("at://proposer/edit/1")) // Only `title` differs; 5 fields are tracked in total. assert string.contains(html, "PROPOSED CHANGES · 1 OF 5 FIELDS") assert string.contains(html, "4 unchanged fields hidden") } pub fn view_colors_old_values_danger_and_new_values_owned_test() { let html = rendered(an_edit_proposal("at://proposer/edit/1")) assert string.contains(html, "diff-row__old--danger") assert string.contains(html, "diff-row__new--owned") assert string.contains(html, "Spiderland (Remastered)") } pub fn view_shows_an_empty_placeholder_for_a_previously_unset_field_test() { let proposal = EditProposal( ..an_edit_proposal("at://proposer/edit/1"), current: ProposalFields( title: None, released: None, country: None, genres: None, styles: None, ), ) let html = rendered(proposal) assert string.contains(html, "(empty)") assert string.contains(html, "diff-row__old--empty") } pub fn view_links_the_proposer_handle_to_their_public_crate_test() { let html = rendered(an_edit_proposal("at://proposer/edit/1")) assert string.contains(html, "href=\"/u/bob.test\"") assert string.contains(html, "suggests changes to your pressing") } pub fn view_renders_the_version_context_panel_test() { let html = rendered(an_edit_proposal("at://proposer/edit/1")) assert string.contains(html, "class=\"version-context\"") assert string.contains(html, "YOURS") assert string.contains(html, "current version") assert string.contains(html, "THEIRS") assert string.contains(html, "superseding version · minted 2026-02-01") } pub fn yours_caption_shows_the_adoption_count_when_present_test() { let proposal = EditProposal( ..an_edit_proposal("at://proposer/edit/1"), subject_adoption_count: Some(4), ) let html = rendered(proposal) assert string.contains(html, "current version · in 4 crates") } pub fn yours_caption_uses_the_singular_for_one_crate_test() { let proposal = EditProposal( ..an_edit_proposal("at://proposer/edit/1"), subject_adoption_count: Some(1), ) let html = rendered(proposal) assert string.contains(html, "current version · in 1 crate") assert !string.contains(html, "1 crates") } pub fn yours_caption_omits_the_adoption_count_when_absent_test() { let proposal = EditProposal( ..an_edit_proposal("at://proposer/edit/1"), subject_adoption_count: None, ) let html = rendered(proposal) assert string.contains(html, "current version") assert !string.contains(html, "crates") } pub fn view_wires_the_adopt_and_ignore_actions_test() { let html = rendered(an_edit_proposal("at://proposer/edit/1")) assert string.contains(html, "ADOPT THIS VERSION") assert string.contains(html, "IGNORE") } pub fn view_falls_back_to_the_applied_strip_for_an_applied_card_test() { let proposal = an_edit_proposal("at://proposer/edit/1") let html = InboxCard(proposal:, status: ProposalApplied("at://alice/release/rNEW")) |> edit_proposal.view |> element.to_string assert string.contains(html, "class=\"applied-strip\"") assert !string.contains(html, "ADOPT THIS VERSION") }