import at_record_web/model.{type ReleaseInfo, Entry, Model, ReleaseInfo, Source}
import at_record_web/msg.{
ArmRemove, DisarmRemove, EntryAction, GotTimeline, OnRouteChange, TimelineData,
}
import at_record_web/pages/record
import at_record_web/update.{update}
import gleam/dict
import gleam/option.{None, Some}
import gleam/string
import lustre/element
import support.{an_entry, logged_in}
pub fn record_view_shows_the_sleeve_grade_card_when_present_test() {
let html = record.view(logged_in(), an_entry()) |> element.to_string
assert string.contains(html, "SLEEVE")
assert string.contains(html, "VG+")
}
pub fn record_view_omits_the_sleeve_grade_card_when_absent_test() {
let html =
record.view(logged_in(), Entry(..an_entry(), sleeve_grade: None))
|> element.to_string
assert !string.contains(html, "SLEEVE")
}
pub fn record_view_shows_paid_and_from_rows_when_present_test() {
let html = record.view(logged_in(), an_entry()) |> element.to_string
assert string.contains(html, "PAID")
assert string.contains(html, "EUR 40.00")
assert string.contains(html, "FROM")
assert string.contains(html, "Record shop")
}
pub fn record_view_omits_paid_and_from_rows_when_absent_test() {
let html =
record.view(
logged_in(),
Entry(..an_entry(), price: None, counterparty: None),
)
|> element.to_string
assert !string.contains(html, "PAID")
assert !string.contains(html, "FROM")
}
pub fn record_view_shows_the_provenance_line_when_source_is_present_test() {
let source = Source(origin: Some("scan"), provider: Some("discogs"))
let html =
record.view(logged_in(), Entry(..an_entry(), source: Some(source)))
|> element.to_string
assert string.contains(html, "class=\"layer-provenance\"")
assert string.contains(html, "scanned ยท via Discogs")
}
pub fn record_view_shows_added_by_hand_for_manual_source_test() {
let source = Source(origin: Some("manual"), provider: None)
let html =
record.view(logged_in(), Entry(..an_entry(), source: Some(source)))
|> element.to_string
assert string.contains(html, "added by hand")
}
pub fn record_view_omits_the_provenance_line_when_source_is_absent_test() {
let html =
record.view(logged_in(), Entry(..an_entry(), source: None))
|> element.to_string
assert !string.contains(html, "class=\"layer-provenance\"")
}
pub fn arm_remove_then_entry_action_disarms_and_sets_busy_test() {
let #(armed, _) = update(logged_in(), ArmRemove)
assert armed.confirm_remove == True
let #(after, _) = update(armed, EntryAction("e1", "dropped"))
assert after.confirm_remove == False
assert after.busy == True
}
// DisarmRemove is what both the outside-click watcher and the auto-disarm
// timeout dispatch; neither should touch `busy`.
pub fn arm_remove_then_disarm_remove_clears_confirm_without_busy_test() {
let #(armed, _) = update(logged_in(), ArmRemove)
assert armed.confirm_remove == True
let #(after, _) = update(armed, DisarmRemove)
assert after.confirm_remove == False
assert after.busy == False
}
// Re-arming (e.g. a tap on REMOVE while already armed) stays armed and still
// confirms normally on the next EntryAction; the watcher/timer replacement
// that guards against a stale disarm lives in effects.arm_confirm, not here.
pub fn rearming_remove_stays_armed_and_still_confirms_test() {
let #(armed_once, _) = update(logged_in(), ArmRemove)
let #(rearmed, _) = update(armed_once, ArmRemove)
assert rearmed.confirm_remove == True
let #(after, _) = update(rearmed, EntryAction("e1", "dropped"))
assert after.confirm_remove == False
assert after.busy == True
}
fn a_release_info() -> ReleaseInfo {
ReleaseInfo(
artist_display: Some("Slint"),
genres: ["Rock"],
styles: ["Math Rock"],
country: Some("US"),
released: Some("1991"),
)
}
pub fn got_timeline_with_release_stores_release_info_test() {
let #(model, _) =
update(
logged_in(),
GotTimeline(Ok(TimelineData(events: [], release: Some(a_release_info())))),
)
assert model.release_info == Some(a_release_info())
}
pub fn got_timeline_without_release_leaves_release_info_none_test() {
let #(model, _) =
update(
logged_in(),
GotTimeline(Ok(TimelineData(events: [], release: None))),
)
assert model.release_info == None
}
pub fn route_change_clears_release_info_test() {
let seeded = model.Model(..logged_in(), release_info: Some(a_release_info()))
let #(model, _) = update(seeded, OnRouteChange(model.Crate))
assert model.release_info == None
}
pub fn record_view_shows_a_copy_share_link_button_with_the_public_path_test() {
let html = record.view(logged_in(), an_entry()) |> element.to_string
assert string.contains(html, "COPY SHARE LINK")
assert string.contains(html, "/u/alice.test/record/e1")
}
// The fold-out is gone: AMEND/SUGGEST A FIX is now a plain nav link to the
// routed amend screen, not a button dispatching a toggle message.
pub fn record_view_renders_the_amend_action_as_a_link_to_its_own_route_test() {
let html = record.view(logged_in(), an_entry()) |> element.to_string
assert string.contains(
html,
"AMEND",
)
}
pub fn record_view_labels_the_amend_link_as_suggest_a_fix_for_an_adopted_entry_test() {
let via_handles = dict.from_list([#("e1", "bob.test")])
let html =
record.view(Model(..logged_in(), via_handles:), an_entry())
|> element.to_string
assert string.contains(
html,
"SUGGEST A FIX",
)
}