diff --git a/monarch/monarch.lua b/monarch/monarch.lua index 4641443..ebf2b40 100644 --- a/monarch/monarch.lua +++ b/monarch/monarch.lua @@ -33,6 +33,8 @@ M.SCREEN_TRANSITION_OUT_STARTED = hash("monarch_screen_transition_out_started") M.SCREEN_TRANSITION_OUT_FINISHED = hash("monarch_screen_transition_out_finished") M.SCREEN_TRANSITION_FAILED = hash("monarch_screen_transition_failed") +local WAIT_FOR_TRANSITION = true +local DO_NOT_WAIT_FOR_TRANSITION = false -- all registered screens local screens = {} @@ -47,8 +49,7 @@ local transition_listeners = {} -- monarch is considered busy while there are active transitions local active_transition_count = 0 - -local function log(...) end +local function log(...) end function M.debug() log = print @@ -93,8 +94,8 @@ end local queue = {} local function queue_error(message) - print(message) log("queue() error - clearing queue") + print(message) while next(queue) do table.remove(queue) end @@ -337,7 +338,7 @@ end local function change_context(screen) log("change_context()", screen.id) screen.wait_for = CONTEXT - msg.post(screen.script, CONTEXT) + msg.post(screen.script, CONTEXT, { id = screen.id }) coroutine.yield() screen.wait_for = nil end @@ -451,12 +452,14 @@ local function load(screen) return true end -local function transition(screen, message_id, message) +local function transition(screen, message_id, message, wait) log("transition()", screen.id) if screen.transition_url then screen.wait_for = M.TRANSITION.DONE msg.post(screen.transition_url, message_id, message) - coroutine.yield() + if wait then + coroutine.yield() + end screen.wait_for = nil else log("transition() no transition url - ignoring") @@ -481,6 +484,7 @@ local function focus_lost(screen, next_screen) -- the focus_url -- we add a delay to ensure the message queue has time to be processed cowait(0) + cowait(0) else log("focus_lost() no focus url - ignoring") end @@ -538,8 +542,21 @@ local function enable(screen, previous_screen) end) end -local function show_out(screen, next_screen, cb) +local function show_out(screen, next_screen, wait_for_transition, cb) log("show_out()", screen.id) + assert(wait_for_transition ~= nil) + -- make sure the screen is loaded. scenario: + -- show A - stack [A] + -- - show_in for A + -- show B with no_stack = true - stack [A] + -- - show_in for B and show_out for A + -- show C + -- - show_in for C and show_out for A again! + if not screen.loaded then + log("show_out() screen was not loaded") + cb() + return + end run_coroutine(screen, cb, function() active_transition_count = active_transition_count + 1 notify_transition_listeners(M.SCREEN_TRANSITION_OUT_STARTED, { screen = screen.id, next_screen = next_screen.id }) @@ -552,7 +569,7 @@ local function show_out(screen, next_screen, cb) local next_is_popup = next_screen and next_screen.popup local current_is_popup = screen.popup if (not next_is_popup and not current_is_popup) or (current_is_popup) then - transition(screen, M.TRANSITION.SHOW_OUT, { next_screen = next_screen.id }) + transition(screen, M.TRANSITION.SHOW_OUT, { next_screen = next_screen.id }, wait_for_transition) unload(screen) elseif next_is_popup then change_timestep(screen) @@ -562,8 +579,9 @@ local function show_out(screen, next_screen, cb) end) end -local function show_in(screen, previous_screen, reload, add_to_stack, cb) - log("show_in()", screen.id) +local function show_in(screen, previous_screen, reload, add_to_stack, wait_for_transition, cb) + log("show_in()", screen.id, wait_for_transition) + assert(wait_for_transition ~= nil) run_coroutine(screen, cb, function() active_transition_count = active_transition_count + 1 notify_transition_listeners(M.SCREEN_TRANSITION_IN_STARTED, { screen = screen.id, previous_screen = previous_screen and previous_screen.id }) @@ -579,11 +597,14 @@ local function show_in(screen, previous_screen, reload, add_to_stack, cb) notify_transition_listeners(M.SCREEN_TRANSITION_FAILED, { screen = screen.id }) return end + -- wait until screen has had a chance to render + cowait(0) + cowait(0) if add_to_stack then stack[#stack + 1] = screen end reset_timestep(screen) - transition(screen, M.TRANSITION.SHOW_IN, { previous_screen = previous_screen and previous_screen.id }) + transition(screen, M.TRANSITION.SHOW_IN, { previous_screen = previous_screen and previous_screen.id }, wait_for_transition) acquire_input(screen) focus_gained(screen, previous_screen) active_transition_count = active_transition_count - 1 @@ -591,8 +612,9 @@ local function show_in(screen, previous_screen, reload, add_to_stack, cb) end) end -local function back_in(screen, previous_screen, cb) +local function back_in(screen, previous_screen, wait_for_transition, cb) log("back_in()", screen.id) + assert(wait_for_transition ~= nil) run_coroutine(screen, cb, function() active_transition_count = active_transition_count + 1 notify_transition_listeners(M.SCREEN_TRANSITION_IN_STARTED, { screen = screen.id, previous_screen = previous_screen and previous_screen.id }) @@ -604,9 +626,12 @@ local function back_in(screen, previous_screen, cb) notify_transition_listeners(M.SCREEN_TRANSITION_FAILED, { screen = screen.id }) return end + -- wait until screen has had a chance to render + cowait(0) + cowait(0) reset_timestep(screen) if previous_screen and not previous_screen.popup then - transition(screen, M.TRANSITION.BACK_IN, { previous_screen = previous_screen.id }) + transition(screen, M.TRANSITION.BACK_IN, { previous_screen = previous_screen.id }, wait_for_transition) end acquire_input(screen) focus_gained(screen, previous_screen) @@ -615,8 +640,9 @@ local function back_in(screen, previous_screen, cb) end) end -local function back_out(screen, next_screen, cb) +local function back_out(screen, next_screen, wait_for_transition, cb) log("back_out()", screen.id) + assert(wait_for_transition ~= nil) run_coroutine(screen, cb, function() notify_transition_listeners(M.SCREEN_TRANSITION_OUT_STARTED, { screen = screen.id, next_screen = next_screen and next_screen.id }) active_transition_count = active_transition_count + 1 @@ -626,7 +652,7 @@ local function back_out(screen, next_screen, cb) if next_screen and screen.popup then reset_timestep(next_screen) end - transition(screen, M.TRANSITION.BACK_OUT, { next_screen = next_screen and next_screen.id }) + transition(screen, M.TRANSITION.BACK_OUT, { next_screen = next_screen and next_screen.id }, wait_for_transition) unload(screen) active_transition_count = active_transition_count - 1 notify_transition_listeners(M.SCREEN_TRANSITION_OUT_FINISHED, { screen = screen.id, next_screen = next_screen and next_screen.id }) @@ -679,9 +705,7 @@ function M.show(id, options, data, cb) id = tohash(id) assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id))) - log("show() queuing action", id) queue_action(function(action_done, action_error) - log("show()", id) local screen = screens[id] if not screen then action_error(("show() there is no longer a screen with id %s"):format(tostring(id))) @@ -719,21 +743,11 @@ function M.show(id, options, data, cb) pop = pop - 1 end stack[#stack] = nil - show_out(top, screen, callbacks.track()) + show_out(top, screen, WAIT_FOR_TRANSITION, callbacks.track()) callbacks.yield_until_done() top = stack[#stack] end - -- unload the previous screen and transition out from top - -- wait until we are done if showing the same screen as is already visible - if top and not top.popup then - local same_screen = top and top.id == screen.id - show_out(top, screen, callbacks.track()) - if same_screen or (options and options.sequential) then - callbacks.yield_until_done() - end - end - -- if the screen we want to show is in the stack -- already and the clear flag is set then we need -- to remove every screen on the stack up until and @@ -755,8 +769,8 @@ function M.show(id, options, data, cb) end end - -- show screen, wait until preloaded if it is already preloading - -- this can typpically happen if you do a show() on app start for a + -- wait until preloaded if it is already preloading + -- this can typically happen if you do a show() on app start for a -- screen that has Preload set to true if M.is_preloading(id) then M.when_preloaded(id, function() @@ -764,7 +778,25 @@ function M.show(id, options, data, cb) end) coroutine.yield() end - show_in(screen, top, options and options.reload, add_to_stack, callbacks.track()) + + -- showing and hiding the same screen? + local same_screen = top and top.id == screen.id + if same_screen or (options and options.sequential) then + if top then + show_out(top, screen, WAIT_FOR_TRANSITION, callbacks.track()) + callbacks.yield_until_done() + end + show_in(screen, top, options and options.reload, add_to_stack, WAIT_FOR_TRANSITION, callbacks.track()) + else + -- show screen + local cb = callbacks.track() + show_in(screen, top, options and options.reload, add_to_stack, DO_NOT_WAIT_FOR_TRANSITION, function() + if top and not top.popup then + show_out(top, screen, WAIT_FOR_TRANSITION, callbacks.track()) + end + cb() + end) + end callbacks.when_done(function() pcallfn(cb) @@ -818,7 +850,7 @@ function M.hide(id, cb) action_error(("hide() there is no longer a screen with id %s"):format(tostring(id))) return end - back_out(screen, nil, callbacks.track()) + back_out(screen, nil, WAIT_FOR_TRANSITION, callbacks.track()) end callbacks.when_done(function() pcallfn(cb) @@ -845,19 +877,22 @@ function M.back(data, cb) -- if we go back to the same screen we need to first hide it -- and wait until it is hidden before we show it again if top and screen.id == top.id then - back_out(screen, top, function() + back_out(screen, top, WAIT_FOR_TRANSITION, function() if data then top.data = data end - back_in(top, screen, callbacks.track()) + back_in(top, screen, WAIT_FOR_TRANSITION, callbacks.track()) end) else - back_out(screen, top, callbacks.track()) if top then if data then top.data = data end - back_in(top, screen, callbacks.track()) + back_in(top, screen, DO_NOT_WAIT_FOR_TRANSITION, function() + back_out(screen, top, WAIT_FOR_TRANSITION, callbacks.track()) + end) + else + back_out(screen, top, WAIT_FOR_TRANSITION, callbacks.track()) end end end @@ -1021,13 +1056,9 @@ function M.post(id, message_id, message) return false, "Unable to post message since screen has no receiver url specified" end else - run_coroutine(screen, nil, function() - change_context(screen) - log("post() sending message to", screen.receiver_url) - for id,instance in pairs(screen.factory_ids) do - msg.post(instance, message_id, message) - end - end) + for id,instance in pairs(screen.factory_ids) do + msg.post(instance, message_id, message) + end end return true end @@ -1120,4 +1151,9 @@ function M.dump_stack() return s end +function M.queue_size() + return #queue +end + + return M diff --git a/test/cowait.lua b/test/cowait.lua index 656b0bd..07a8a9d 100644 --- a/test/cowait.lua +++ b/test/cowait.lua @@ -4,7 +4,10 @@ function M.seconds(amount) local co = coroutine.running() assert(co, "You must run this from within a coroutine") timer.delay(amount, false, function() - coroutine.resume(co) + local ok, err = coroutine.resume(co) + if not ok then + print(err) + end end) coroutine.yield() end @@ -13,10 +16,13 @@ function M.eval(fn, timeout) local co = coroutine.running() assert(co, "You must run this from within a coroutine") local start = socket.gettime() - timer.delay(0.01, true, function(self, handle, time_elapsed) + timer.delay(0.02, true, function(self, handle, time_elapsed) if fn() or (timeout and socket.gettime() > (start + timeout)) then timer.cancel(handle) - coroutine.resume(co) + local ok, err = coroutine.resume(co) + if not ok then + print(err) + end end end) coroutine.yield() diff --git a/test/data/screen_preload.gui_script b/test/data/screen_preload.gui_script index 267ea9d..ae2e41c 100644 --- a/test/data/screen_preload.gui_script +++ b/test/data/screen_preload.gui_script @@ -1,5 +1,5 @@ function init(self) local monarch = require "monarch.monarch" local data = monarch.data(hash("screen_preload")) - data.count = data.count + 1 + if data then data.count = data.count + 1 end end diff --git a/test/test_monarch.lua b/test/test_monarch.lua index ec0bdb5..94518dd 100644 --- a/test/test_monarch.lua +++ b/test/test_monarch.lua @@ -77,6 +77,9 @@ return function() local function wait_until_not_busy() return wait_timeout(function() return not monarch.is_busy() end) end + local function wait_until_stack(expected_screens) + return wait_timeout(function() return check_stack(expected_screens) end) + end local function wait_until_loaded(screen_id) wait_until_done(function(done) monarch.when_preloaded(screen_id, done) @@ -115,57 +118,42 @@ return function() it("should be able to show screens and go back to previous screens", function() monarch.show(SCREEN1_STR) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 })) monarch.show(SCREEN2) - assert(wait_until_hidden(SCREEN1), "Screen1 was never hidden") - assert(wait_until_shown(SCREEN2), "Screen2 was never shown") - assert_stack({ SCREEN1, SCREEN2 }) + assert(wait_until_stack({ SCREEN1, SCREEN2 })) monarch.back() - assert(wait_until_hidden(SCREEN2), "Screen2 was never hidden") - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 })) monarch.back() - assert(wait_until_hidden(SCREEN1), "Screen1 was never hidden") - assert_stack({ }) + assert(wait_until_stack({ })) end) it("should be able to replace screens at the top of the stack", function() monarch.show(SCREEN1_STR) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 }), "Screen1 was never shown") monarch.show(SCREEN2) - assert(wait_until_hidden(SCREEN1), "Screen1 was never hidden") - assert(wait_until_shown(SCREEN2), "Screen2 was never shown") - assert_stack({ SCREEN1, SCREEN2 }) + assert(wait_until_stack({ SCREEN1, SCREEN2 })) monarch.replace(SCREEN1) - assert(wait_until_hidden(SCREEN2), "Screen2 was never hidden") - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1, SCREEN1 }) + assert(wait_until_stack({ SCREEN1, SCREEN1 })) end) it("should be able to tell if a screen is visible or not", function() assert(not monarch.is_visible(SCREEN1)) monarch.show(SCREEN1) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 })) assert(monarch.is_visible(SCREEN1)) monarch.show(SCREEN2) - assert(wait_until_hidden(SCREEN1), "Screen1 was never hidden") - assert(wait_until_shown(SCREEN2), "Screen2 was never shown") - assert_stack({ SCREEN1, SCREEN2 }) + assert(wait_until_stack({ SCREEN1, SCREEN2 })) assert(not monarch.is_visible(SCREEN1)) assert(monarch.is_visible(SCREEN2)) monarch.show(POPUP1) - assert(wait_until_shown(POPUP1), "Popup1 was never shown") - assert_stack({ SCREEN1, SCREEN2, POPUP1 }) + assert(wait_until_stack({ SCREEN1, SCREEN2, POPUP1 })) assert(not monarch.is_visible(SCREEN1)) assert(monarch.is_visible(SCREEN2)) assert(monarch.is_visible(POPUP1)) @@ -174,13 +162,32 @@ return function() it("should be able to show a screen without adding it to the stack", function() monarch.show(BACKGROUND, { no_stack = true }) assert(wait_until_shown(BACKGROUND), "Background was never shown") - assert_stack({ }) + assert(wait_until_stack({ })) monarch.show(SCREEN1) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 })) end) + it("should be able to show a screen without adding it to the stack at any time", function() + monarch.show(SCREEN1) + assert(wait_until_not_busy()) + assert(wait_until_stack({ SCREEN1 })) + + monarch.show(BACKGROUND, { no_stack = true }) + assert(wait_until_not_busy()) + assert(wait_until_shown(BACKGROUND)) + assert(wait_until_stack({ SCREEN1 })) + + monarch.show(SCREEN2) + assert(wait_until_not_busy()) + assert(wait_until_stack({ SCREEN1, SCREEN2 })) + + monarch.back() + assert(wait_until_not_busy()) + assert(wait_until_shown(SCREEN1)) + assert(wait_until_stack({ SCREEN1 })) + end) + it("should be able to hide a screen not added to the stack", function() monarch.show(BACKGROUND, { no_stack = true }) assert(wait_until_shown(BACKGROUND), "Background was never shown") @@ -190,22 +197,17 @@ return function() assert(wait_until_hidden(BACKGROUND), "Background was never hidden") assert_stack({ }) end) - + it("should be able to hide the top screen", function() monarch.show(SCREEN1) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 })) monarch.show(SCREEN2) - assert(wait_until_hidden(SCREEN1), "Screen1 was never hidden") - assert(wait_until_shown(SCREEN2), "Screen2 was never shown") - assert_stack({ SCREEN1, SCREEN2 }) + assert(wait_until_stack({ SCREEN1, SCREEN2 })) assert(monarch.hide(SCREEN1) == false) assert(monarch.hide(SCREEN2) == true) - assert(wait_until_hidden(SCREEN2), "Screen2 was never hidden") - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 })) end) it("should be able to pass data to a screen when showing it or going back to it", function() @@ -230,51 +232,40 @@ return function() it("should be able to show the same screen twice", function() monarch.show(SCREEN1) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 })) monarch.show(SCREEN1) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1, SCREEN1 }) + assert(wait_until_stack({ SCREEN1, SCREEN1 })) end) it("should be able to clear the stack if trying to show the same screen twice", function() monarch.show(SCREEN1) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 })) monarch.show(SCREEN2) - assert(wait_until_shown(SCREEN2), "Screen2 was never shown") - assert_stack({ SCREEN1, SCREEN2 }) + assert(wait_until_stack({ SCREEN1, SCREEN2 })) monarch.show(SCREEN1, { clear = true }) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 })) end) it("should be able to show one popup on top of another if the Popup On Popup flag is set", function() monarch.show(SCREEN1) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 })) monarch.show(POPUP1) - assert(wait_until_shown(POPUP1), "Popup1 was never shown") - assert_stack({ SCREEN1, POPUP1 }) + assert(wait_until_stack({ SCREEN1, POPUP1 })) monarch.show(POPUP2) - assert(wait_until_shown(POPUP2), "Popup2 was never shown") - assert_stack({ SCREEN1, POPUP1, POPUP2 }) + assert(wait_until_stack({ SCREEN1, POPUP1, POPUP2 })) end) - it("should prevent further operations while hiding/showing a screen", function() + it("should be able to queue multiple display commands", function() monarch.show(SCREEN1) monarch.show(SCREEN2) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert(wait_until_shown(SCREEN2), "Screen2 was never shown") - assert_stack({ SCREEN1, SCREEN2 }) + assert(wait_until_stack({ SCREEN1, SCREEN2 })) assert(monarch.back()) assert(monarch.back()) - assert(wait_until_hidden(SCREEN1), "Screen1 was never hidden") - assert(wait_until_hidden(SCREEN2), "Screen2 was never hidden") + assert(wait_until_stack({}), "Stack never became empty") end) @@ -292,84 +283,63 @@ return function() it("should close any open popups when showing a popup without the Popup On Popup flag", function() monarch.show(SCREEN1) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 })) monarch.show(POPUP2) - assert(wait_until_shown(POPUP2), "Popup2 was never shown") - assert_stack({ SCREEN1, POPUP2 }) + assert(wait_until_stack({ SCREEN1, POPUP2 })) monarch.show(POPUP1) - assert(wait_until_shown(POPUP1), "Popup1 was never shown") - assert_stack({ SCREEN1, POPUP1 }) + assert(wait_until_stack({ SCREEN1, POPUP1 })) end) it("should close any open popups when showing a non-popup", function() monarch.show(SCREEN1) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 })) monarch.show(POPUP1) - assert(wait_until_shown(POPUP1), "Popup1 was never shown") - assert_stack({ SCREEN1, POPUP1 }) + assert(wait_until_stack({ SCREEN1, POPUP1 })) monarch.show(POPUP2) - assert(wait_until_shown(POPUP2), "Popup2 was never shown") - assert_stack({ SCREEN1, POPUP1, POPUP2 }) + assert(wait_until_stack({ SCREEN1, POPUP1, POPUP2 })) monarch.show(SCREEN2) - assert(wait_until_shown(SCREEN2), "Popup2 was never shown") - assert_stack({ SCREEN1, SCREEN2 }) + assert(wait_until_stack({ SCREEN1, SCREEN2 })) end) it("should close any open popups when replacing a non-popup", function() monarch.show(SCREEN1) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 })) monarch.show(POPUP1) - assert(wait_until_shown(POPUP1), "Popup1 was never shown") - assert_stack({ SCREEN1, POPUP1 }) + assert(wait_until_stack({ SCREEN1, POPUP1 })) monarch.show(POPUP2) - assert(wait_until_shown(POPUP2), "Popup2 was never shown") - assert_stack({ SCREEN1, POPUP1, POPUP2 }) + assert(wait_until_stack({ SCREEN1, POPUP1, POPUP2 })) monarch.replace(SCREEN2) - assert(wait_until_shown(SCREEN2), "Screen2 was never shown") - assert_stack({ SCREEN2 }) + assert(wait_until_stack({ SCREEN2 })) end) it("should replace a popup", function() monarch.show(SCREEN1) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 })) monarch.show(POPUP1) - assert(wait_until_shown(POPUP1), "Popup1 was never shown") - assert_stack({ SCREEN1, POPUP1 }) + assert(wait_until_stack({ SCREEN1, POPUP1 })) monarch.replace(POPUP2) - assert(wait_until_shown(POPUP2), "Popup2 was never shown") - assert_stack({ SCREEN1, POPUP2 }) + assert(wait_until_stack({ SCREEN1, POPUP2 })) end) it("should replace a pop-up two levels down", function() monarch.show(SCREEN1) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 })) monarch.show(POPUP1) - assert(wait_until_shown(POPUP1), "Popup1 was never shown") - assert_stack({ SCREEN1, POPUP1 }) + assert(wait_until_stack({ SCREEN1, POPUP1 })) monarch.show(POPUP2) - assert(wait_until_shown(POPUP2), "Popup2 was never shown") - assert_stack({ SCREEN1, POPUP1, POPUP2 }) + assert(wait_until_stack({ SCREEN1, POPUP1, POPUP2 })) monarch.show(POPUP2, { pop = 2 }) - assert(wait_until_shown(POPUP2), "Popup2 was never shown") - assert_stack({ SCREEN1, POPUP2 }) + assert(wait_until_stack({ SCREEN1, POPUP2 })) end) it("shouldn't over-pop popups", function() monarch.show(SCREEN1) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert_stack({ SCREEN1 }) + assert(wait_until_stack({ SCREEN1 })) monarch.show(POPUP1) - assert(wait_until_shown(POPUP1), "Popup1 was never shown") - assert_stack({ SCREEN1, POPUP1 }) + assert(wait_until_stack({ SCREEN1, POPUP1 })) monarch.show(POPUP2, { pop = 10 }) - assert(wait_until_shown(POPUP2), "Popup2 was never shown") - assert_stack({ SCREEN1, POPUP2 }) + assert(wait_until_stack({ SCREEN1, POPUP2 })) end) it("should be able to get the id of the screen at the top and bottom of the stack", function() @@ -379,7 +349,7 @@ return function() assert(monarch.bottom(-1) == nil) monarch.show(SCREEN1) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") + assert(wait_until_stack({ SCREEN1 })) assert(monarch.top() == SCREEN1) assert(monarch.top(0) == SCREEN1) assert(monarch.top(1) == nil) @@ -388,9 +358,7 @@ return function() assert(monarch.bottom(-1) == nil) monarch.show(SCREEN2) - assert(wait_until_hidden(SCREEN1), "Screen1 was never hidden") - assert(wait_until_shown(SCREEN2), "Screen2 was never shown") - assert_stack({ SCREEN1, SCREEN2 }) + assert(wait_until_stack({ SCREEN1, SCREEN2 })) assert(monarch.top(0) == SCREEN2) assert(monarch.top(-1) == SCREEN1) assert(monarch.bottom(0) == SCREEN1) @@ -399,8 +367,8 @@ return function() it("should be busy while transition is running", function() monarch.show(TRANSITION1) - assert(wait_until_shown(TRANSITION1), "Transition1 was never shown") assert(monarch.is_busy()) + assert(wait_until_shown(TRANSITION1), "Transition1 was never shown") assert(wait_until_not_busy()) end) @@ -428,11 +396,11 @@ return function() monarch.add_listener(URL2) monarch.show(SCREEN1) + assert(wait_until_not_busy()) assert(mock_msg.messages(URL1)[1].message_id == monarch.SCREEN_TRANSITION_IN_STARTED) assert(mock_msg.messages(URL1)[1].message.screen == SCREEN1) assert(mock_msg.messages(URL2)[1].message_id == monarch.SCREEN_TRANSITION_IN_STARTED) assert(mock_msg.messages(URL2)[1].message.screen == SCREEN1) - assert(wait_until_not_busy()) assert(mock_msg.messages(URL1)[2].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED) assert(mock_msg.messages(URL1)[2].message.screen == SCREEN1) assert(mock_msg.messages(URL2)[2].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED) @@ -444,30 +412,30 @@ return function() assert(#mock_msg.messages(URL1) == 6) assert(#mock_msg.messages(URL2) == 2) - assert(mock_msg.messages(URL1)[3].message_id == monarch.SCREEN_TRANSITION_OUT_STARTED) - assert(mock_msg.messages(URL1)[3].message.screen == SCREEN1) - assert(mock_msg.messages(URL1)[4].message_id == monarch.SCREEN_TRANSITION_IN_STARTED) + assert(mock_msg.messages(URL1)[3].message_id == monarch.SCREEN_TRANSITION_IN_STARTED) + assert(mock_msg.messages(URL1)[3].message.screen == SCREEN2) + assert(mock_msg.messages(URL1)[4].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED) assert(mock_msg.messages(URL1)[4].message.screen == SCREEN2) - assert(mock_msg.messages(URL1)[5].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED) - assert(mock_msg.messages(URL1)[5].message.screen == SCREEN2) + assert(mock_msg.messages(URL1)[5].message_id == monarch.SCREEN_TRANSITION_OUT_STARTED) + assert(mock_msg.messages(URL1)[5].message.screen == SCREEN1) assert(mock_msg.messages(URL1)[6].message_id == monarch.SCREEN_TRANSITION_OUT_FINISHED) assert(mock_msg.messages(URL1)[6].message.screen == SCREEN1) - + monarch.back() assert(wait_until_not_busy()) - + assert(#mock_msg.messages(URL1) == 10) assert(#mock_msg.messages(URL2) == 2) - assert(mock_msg.messages(URL1)[7].message_id == monarch.SCREEN_TRANSITION_OUT_STARTED) - assert(mock_msg.messages(URL1)[7].message.screen == SCREEN2) - assert(mock_msg.messages(URL1)[8].message_id == monarch.SCREEN_TRANSITION_IN_STARTED) + assert(mock_msg.messages(URL1)[7].message_id == monarch.SCREEN_TRANSITION_IN_STARTED) + assert(mock_msg.messages(URL1)[7].message.screen == SCREEN1) + assert(mock_msg.messages(URL1)[8].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED) assert(mock_msg.messages(URL1)[8].message.screen == SCREEN1) - assert(mock_msg.messages(URL1)[9].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED) - assert(mock_msg.messages(URL1)[9].message.screen == SCREEN1) + assert(mock_msg.messages(URL1)[9].message_id == monarch.SCREEN_TRANSITION_OUT_STARTED) + assert(mock_msg.messages(URL1)[9].message.screen == SCREEN2) assert(mock_msg.messages(URL1)[10].message_id == monarch.SCREEN_TRANSITION_OUT_FINISHED) assert(mock_msg.messages(URL1)[10].message.screen == SCREEN2) end) - + it("should be able to show a screen even while it is preloading", function() monarch.show(SCREEN_PRELOAD, nil, { count = 1 }) assert(wait_until_shown(SCREEN_PRELOAD), "Screen_preload was never shown") @@ -499,13 +467,12 @@ return function() _G.focus1_lost = nil monarch.show(SCREEN1) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") + assert(wait_until_stack({ SCREEN1 })) monarch.show(FOCUS1) - assert(wait_until_shown(FOCUS1), "Screen1 was never shown") + assert(wait_until_stack({ SCREEN1, FOCUS1 })) assert(_G.focus1_gained) monarch.show(SCREEN1) - assert(wait_until_shown(SCREEN1), "Screen1 was never shown") - assert(wait_until_hidden(FOCUS1), "Focus1 was never hidden") + assert(wait_until_stack({ SCREEN1, FOCUS1, SCREEN1 })) assert(_G.focus1_lost) end) @@ -556,9 +523,8 @@ return function() _G.screen1_foobar = nil monarch.show(SCREEN1) - wait_until_shown(SCREEN1) monarch.show(SCREEN2) - wait_until_shown(SCREEN2) + assert(wait_until_stack({ SCREEN1, SCREEN2 })) local ok, err = monarch.post(SCREEN1, "foobar") assert(not ok and err, "Expected monarch.post() to return false plus an error message") cowait(0.1)