import at_record_web/model.{ type Entry, Entry, Failure, Grid, LoggedIn, LoggedOut, Model, Notice, Record, Rows, ShelfFailed, ShelfLoaded, ShelfLoading, Warning, blank_form, } import at_record_web/msg.{ ClearNotice, FormTitle, GotBrowseAdd, GotShelf, GotShelfMore, HandleChanged, RetryShelf, SetDisplay, SetView, ShelfData, ShowMoreCrate, } import at_record_web/pages/crate import at_record_web/update.{update} import at_record_web/view import gleam/dict import gleam/http/response.{Response} import gleam/int import gleam/list import gleam/option.{None, Some} import gleam/string import lustre/element import rsvp import support.{ an_entry, base, empty_effect, logged_in, rendered_empty_crate, rendered_loaded_crate, rendered_loading_crate, unauthorized, } pub fn blank_form_defaults_to_owned_test() { assert blank_form().status == "owned" } pub fn handle_changed_updates_login_handle_test() { let #(model, _effect) = update(base(), HandleChanged("alice.test")) assert model.login_handle == "alice.test" } pub fn form_title_updates_form_test() { let #(model, _effect) = update(base(), FormTitle("Spiderland")) assert model.form.title == "Spiderland" } pub fn shelf_401_logs_out_test() { let #(model, _) = update(logged_in(), GotShelf(Error(rsvp.HttpError(Response(401, [], ""))))) assert model.auth == LoggedOut } pub fn shelf_500_keeps_auth_and_marks_failed_test() { let #(model, _) = update(logged_in(), GotShelf(Error(rsvp.HttpError(Response(500, [], ""))))) assert model.auth == LoggedIn("alice.test") assert model.shelf == ShelfFailed assert case model.notice { Some(Notice(Failure, _)) -> True _ -> False } } pub fn shelf_network_error_keeps_auth_and_marks_failed_test() { let #(model, _) = update(logged_in(), GotShelf(Error(rsvp.NetworkError))) assert model.auth == LoggedIn("alice.test") assert model.shelf == ShelfFailed assert case model.notice { Some(Notice(Failure, _)) -> True _ -> False } } pub fn shelf_401_clears_to_empty_loaded_test() { let #(model, _) = update(logged_in(), GotShelf(Error(rsvp.HttpError(Response(401, [], ""))))) assert model.auth == LoggedOut assert model.shelf == ShelfLoaded([]) } pub fn shelf_ok_marks_loaded_test() { let #(model, _) = update( logged_in(), GotShelf(Ok(ShelfData("alice.test", [], dict.new(), None))), ) assert model.shelf == ShelfLoaded([]) assert model.busy == False } pub fn retry_shelf_resets_to_loading_and_reloads_test() { let failed = Model(..logged_in(), shelf: ShelfFailed, busy: False) let #(model, effect) = update(failed, RetryShelf) assert model.shelf == ShelfLoading assert model.busy == True assert model.notice == None // A real load effect is dispatched (not effect.none()). assert effect != empty_effect() } pub fn set_view_resets_to_loading_test() { let seeded = Model(..logged_in(), crate_window: 120) let #(updated, _) = update(seeded, SetView("wanted")) assert updated.shelf == ShelfLoading assert updated.view == "wanted" // Switching filter rewinds the window so the new view starts from the top. assert updated.crate_window == model.crate_window_size } // A cursor is scoped to the view it was minted under, so both reloads drop // it (and any fetch in flight) rather than resume into the wrong pages. pub fn set_view_and_retry_shelf_reset_the_cursor_and_loading_state_test() { let seeded = Model( ..logged_in(), crate_cursor: Some("owned:e1"), shelf_loading_more: True, ) [update(seeded, SetView("wanted")), update(seeded, RetryShelf)] |> list.each(fn(result) { let #(updated, _) = result assert updated.crate_cursor == None assert updated.shelf_loading_more == False }) } pub fn set_display_switches_to_rows_test() { let #(model, _) = update(logged_in(), SetDisplay(Rows)) assert model.display == Rows } pub fn set_display_back_to_grid_persists_without_a_shelf_reload_test() { let rows_view = Model(..logged_in(), display: Rows) let #(model, effect) = update(rows_view, SetDisplay(Grid)) assert model.display == Grid assert effect != empty_effect() } pub fn session_expired_is_a_warning_notice_test() { let #(model, _) = update(logged_in(), GotBrowseAdd("at://x", Error(unauthorized()))) assert case model.notice { Some(Notice(Warning, _)) -> True _ -> False } } pub fn clear_notice_drops_it_test() { let noticed = Model(..logged_in(), notice: Some(Notice(Failure, "boom"))) let #(model, _) = update(noticed, ClearNotice) assert model.notice == None } pub fn empty_owned_view_shows_first_run_panel_with_toolbar_test() { let html = rendered_empty_crate("owned") assert string.contains(html, "NOTHING IN THE CRATE YET") assert string.contains(html, "WANTED") assert string.contains(html, "HISTORY") } pub fn empty_wanted_view_keeps_toolbar_test() { let html = rendered_empty_crate("wanted") assert string.contains(html, "OWNED") assert string.contains(html, "HISTORY") assert string.contains(html, "0 on your wishlist") assert string.contains(html, "Nothing on your wishlist yet") assert !string.contains(html, "NOTHING IN THE CRATE YET") } pub fn empty_history_view_keeps_toolbar_test() { let html = rendered_empty_crate("history") assert string.contains(html, "OWNED") assert string.contains(html, "WANTED") assert string.contains(html, "0 in your history") assert string.contains(html, "No history yet") assert !string.contains(html, "NOTHING IN THE CRATE YET") } pub fn empty_owned_view_omits_the_display_toggle_test() { let html = rendered_empty_crate("owned") assert !string.contains(html, "class=\"display-toggle\"") } pub fn loaded_grid_shows_the_display_toggle_and_cover_cards_test() { let html = rendered_loaded_crate(Grid) assert string.contains(html, "class=\"display-toggle\"") assert string.contains(html, "▦") assert string.contains(html, "☰") assert string.contains(html, "class=\"cover-card\"") assert !string.contains(html, "class=\"row\"") } pub fn display_toggle_buttons_carry_labels_and_pressed_state_test() { let html = rendered_loaded_crate(Grid) assert string.contains(html, "aria-label=\"Grid view\"") assert string.contains(html, "aria-label=\"List view\"") assert string.contains(html, "aria-pressed=\"true\"") assert string.contains(html, "aria-pressed=\"false\"") } pub fn loaded_rows_render_title_and_muted_artist_format_meta_test() { let html = rendered_loaded_crate(Rows) assert string.contains(html, "class=\"row\"") assert string.contains(html, "class=\"row__title\"") assert string.contains(html, "Spiderland") assert string.contains(html, "Slint · LP / 1991") assert !string.contains(html, "class=\"cover-card\"") } pub fn loading_shelf_renders_skeleton_rows_matching_the_chosen_display_test() { let html = rendered_loading_crate(Rows) assert string.contains(html, "skeleton-row") assert !string.contains(html, "skeleton-card") } pub fn loading_shelf_renders_skeleton_cards_matching_the_chosen_display_test() { let html = rendered_loading_crate(Grid) assert string.contains(html, "skeleton-card") assert !string.contains(html, "skeleton-row") } // --- NAV1 chrome: masthead + bottom tab bar (app bar / popout retired) --- pub fn masthead_shows_only_the_wordmark_on_hero_less_routes_test() { let seeded = Model(..logged_in(), route: Record("e1"), shelf: ShelfLoaded([an_entry()])) let html = view.view(seeded) |> element.to_string assert string.contains( html, "