diff --git a/crates/benilla-app/tests/item_text_frame.rs b/crates/benilla-app/tests/item_text_frame.rs index 6ff6661b..7b7b0e4d 100644 --- a/crates/benilla-app/tests/item_text_frame.rs +++ b/crates/benilla-app/tests/item_text_frame.rs @@ -106,8 +106,11 @@ fn a_letter_reads_with_the_creator_tail() { s.fire_event("ITEM_TEXT_READY", vec![]); assert!(s.eval::("return ItemTextFrame:IsShown()").unwrap()); assert!( - page_blocks(&s).contains(&"\nasd\n\nFrom,\nOne\n\n".to_string()), - "the reference creator tail (ITEM_TEXT_FROM really is comma'd), drawn as one raw block: {:?}", + page_blocks(&s).contains(&"\nasd\n\nFrom,\nOne\n\n\n".to_string()), + "the reference creator tail (ITEM_TEXT_FROM really is comma'd), drawn as one raw block. \ + Three trailing newlines, not two: the realm writes \ + `creator = \"\\n\\n\"..ITEM_TEXT_FROM..\"\\n\"..creator..\"\\n\\n\\n\"` and then \ + `SetText(\"\\n\"..ItemTextGetText()..creator)` (`ItemTextFrame.lua:41-45`): {:?}", page_blocks(&s) ); for hidden in [ @@ -176,8 +179,9 @@ fn a_book_page_shows_the_paging_chrome() { s.fire_event("ITEM_TEXT_BEGIN", vec![]); s.fire_event("ITEM_TEXT_READY", vec![]); assert!( - page_blocks(&s).contains(&"\npage one\n".to_string()), - "the page body drawn: {:?}", + page_blocks(&s).contains(&"\npage one\n\n\n".to_string()), + "the page body drawn, with the authorless arm's own three trailing newlines \ + (`SetText(\"\\n\"..ItemTextGetText()..\"\\n\\n\\n\")`, `ItemTextFrame.lua:46`): {:?}", page_blocks(&s) ); assert_eq!( @@ -381,11 +385,12 @@ fn the_reported_book_crest_draws_at_the_blps_own_size() { } } -/// The reader's `UIPanelWindows` row (`{ area = "left", pushable = 0 }`, `UIParent.lua:20`) makes -/// it and gossip left-slot rivals: showing one replaces the other in both orders, and each -/// displaced window's OnHide ends its own session. +/// The reader's `UIPanelWindows` row is `{ area = "left", pushable = 5 }` (`UIParent.lua:20`) — +/// 1.12's was `pushable = 0`, which made it and gossip left-slot rivals that replaced each other +/// and ended each other's session on the way out. Pushable, they share the screen instead: one +/// takes the left slot and the other slides to centre, in either order, and neither session ends. #[test] -fn a_quest_givers_gossip_displaces_the_open_reader() { +fn a_quest_givers_gossip_seats_beside_the_open_reader() { let _data = benilla_formats::wow_data_or_skip!(); use benilla_ui::script::GossipMenu; @@ -412,35 +417,47 @@ fn a_quest_givers_gossip_displaces_the_open_reader() { })); s.fire_event("GOSSIP_SHOW", vec![]); assert!(s.take_errors().is_empty()); + // The realm made the reader **pushable** (`UIPanelWindows["ItemTextFrame"]` is + // `{ area = "left", pushable = 5 }`, `UIParent.lua:20`), where 1.12's row was `pushable = 0`. + // So gossip does not replace the note: it takes the left slot and the note slides to centre, + // both open, and the read session is not ended. assert!( - !s.eval::("return ItemTextFrame:IsShown()").unwrap(), - "gossip replaced the note — the two-window stack (both drawn at 0,-104) cannot form" + s.eval::("return GetLeftFrame():GetName() == 'GossipFrame'") + .unwrap(), + "gossip takes the left slot" ); - assert!(s - .eval::("return GossipFrame:IsShown() and GetLeftFrame():GetName() == 'GossipFrame'") - .unwrap()); assert!( - s.take_item_text_close(), - "the displaced reader's OnHide ended the read session (CloseItemText)" + s.eval::("return GetCenterFrame():GetName() == 'ItemTextFrame'") + .unwrap(), + "…and pushes the note across rather than over" ); - // The app's close must not disturb the gossip that displaced it. + assert!( + s.eval::("return ItemTextFrame:IsShown() and GossipFrame:IsShown()") + .unwrap(), + "both windows are up: that is what a pushable row buys" + ); + assert!( + !s.take_item_text_close(), + "nothing was displaced, so no `CloseItemText` — the read session stands" + ); + + // The app's own close takes the note and leaves the gossip that pushed it. s.set_item_text(None); s.fire_event("ITEM_TEXT_CLOSED", vec![]); + assert!(!s.eval::("return ItemTextFrame:IsShown()").unwrap()); assert!(s.eval::("return GossipFrame:IsShown()").unwrap()); - // The reverse order: reading the note over an open gossip ends the gossip session. + // The reverse order, with gossip already at the left slot: the note arrives pushable and + // seats beside it, and the gossip session is not ended either. let _ = s.take_gossip_close(); s.set_item_text(Some(letter())); s.fire_event("ITEM_TEXT_BEGIN", vec![]); s.fire_event("ITEM_TEXT_READY", vec![]); assert!(s.take_errors().is_empty()); assert!( - s.eval::("return ItemTextFrame:IsShown() and not GossipFrame:IsShown()") + s.eval::("return ItemTextFrame:IsShown() and GossipFrame:IsShown()") .unwrap(), - "the reader replaces gossip the same way" - ); - assert!( - s.take_gossip_close(), - "the displaced gossip's OnHide ended the gossip session (CloseGossip)" + "the reader seats beside the gossip rather than replacing it" ); + assert!(!s.take_gossip_close(), "…so `CloseGossip` is not queued"); } diff --git a/crates/benilla-app/tests/mail_frame.rs b/crates/benilla-app/tests/mail_frame.rs index 9d8312e0..84bc2ed4 100644 --- a/crates/benilla-app/tests/mail_frame.rs +++ b/crates/benilla-app/tests/mail_frame.rs @@ -252,7 +252,7 @@ fn opening_a_letter_shows_the_open_frame_and_queues_the_body() { /// hides the centre frame (`MailFrame.xml:1903-1907`), and a frame arriving at centre hides the /// letter. A bare stand-in carries the `CharacterFrame` row. #[test] -fn a_letter_and_the_centre_occupant_evict_each_other() { +fn a_letter_covers_the_centre_occupant_and_a_new_arrival_hides_it() { let _data = benilla_formats::wow_data_or_skip!(); let mut s = UiScript::new().unwrap(); load_ui(&s); @@ -283,13 +283,20 @@ fn a_letter_and_the_centre_occupant_evict_each_other() { s.eval::("return OpenMailFrame:IsShown()").unwrap(), "the letter opened" ); + // …and the centre occupant stays. `OpenMailFrame` has no `UIPanelWindows` row, so + // `ShowUIPanel` takes its first branch — `if ( not GetUIPanelWindowInfo(frame, "area") ) then + // frame:Show(); return; end` (`UIParent.lua:920-923`) — a bare Show that claims no slot and + // evicts nothing. The eviction runs the other way only: it is a `UIChildWindows` member, so + // the next panel to seat anywhere hides it (`CloseChildWindows`, `:792-796`), which is the + // second half of this test. assert!( - !s.eval::("return CharacterFrame:IsShown()").unwrap(), - "the centre occupant was evicted, not covered (the reported bug)" + s.eval::("return CharacterFrame:IsShown()").unwrap(), + "the centre occupant is covered, not evicted" ); assert!( - s.eval::("return GetCenterFrame() == nil").unwrap(), - "the eviction is a plain vacate — nothing slides" + s.eval::("return GetCenterFrame():GetName() == 'CharacterFrame'") + .unwrap(), + "and it still holds the centre slot" ); assert!( s.eval::("return MailFrame:IsShown() and GetLeftFrame():GetName() == 'MailFrame'") @@ -297,13 +304,16 @@ fn a_letter_and_the_centre_occupant_evict_each_other() { "the mailbox itself is untouched" ); - // The reverse: re-opening the sheet over the open letter puts the letter away. - s.run("ShowUIPanel(CharacterFrame)").unwrap(); + // The reverse: a sheet **arriving** over the open letter puts the letter away. It has to + // arrive — `ShowUIPanel` returns on its first line for a frame that is already shown + // (`UIParent.lua:916-918`), so asking again while it is up reaches no slot and hides nothing. + s.run("HideUIPanel(CharacterFrame) ShowUIPanel(CharacterFrame)") + .unwrap(); assert!(s.take_errors().is_empty()); assert!( s.eval::("return CharacterFrame:IsShown()").unwrap() && !s.eval::("return OpenMailFrame:IsShown()").unwrap(), - "a frame arriving at centre hides the letter" + "a frame arriving at a slot hides the letter" ); }