diff --git a/data/test/plugin/host.lua b/data/test/plugin/host.lua
index de5082923af..a15db738126 100644
--- a/data/test/plugin/host.lua
+++ b/data/test/plugin/host.lua
@@ -9,8 +9,6 @@ local function plugin()
 
   local counter = 0
 
-  local events, context, info
-
   local function idle_text(text)
     counter = counter + 1
     if counter >= 100 then
@@ -21,59 +19,56 @@ local function plugin()
 
   log("hello world")
 
-  repeat
-    events, context, info = coroutine.yield()
-    idle_text("in " .. info.name .. " waiting for titlescreen or lobby")
-  until info.name == "titlescreen" or info.name == "Multiplayer Lobby"
+  local events, context, info = wesnoth.plugin.wait_until_any({"titlescreen", "Multiplayer Lobby"}, function(name)
+    idle_text("in " .. name .. " waiting for titlescreen or lobby")
+  end)
 
   local tries = 0
   while info.name == "titlescreen" and tries < 100 do
-    context.play_multiplayer({})
+    context.play_multiplayer{}
     tries = tries + 1
     log("playing multiplayer...")
-    events, context, info = coroutine.yield()
+    events, context, info = wesnoth.plugin.next_slice()
   end
   if info.name == "titlescreen" then
-    context.exit({code = 1})
-    coroutine.yield()
+    context.exit{code = 1}
+    return
   end
 
-  repeat
-    events, context, info = coroutine.yield()
-    idle_text("in " .. info.name .. " waiting for lobby")
-  until info.name == "Multiplayer Lobby"
+  events, context, info = wesnoth.plugin.wait_until("Multiplayer Lobby", function(name)
+    idle_text("in " .. name .. " waiting for lobby")
+  end)
 
-  context.chat({message = "hosting"})
+  context.chat{message = "hosting"}
   log("creating a game")
-  context.create({})
+  context.create{}
 
-  repeat
-    events, context, info = coroutine.yield()
-    idle_text("in " .. info.name .. " waiting for create")
-  until info.name == "Multiplayer Create"
+  events, context, info = wesnoth.plugin.wait_until("Multiplayer Create", function(name)
+    idle_text("in " .. name .. " waiting for create")
+  end)
 
-  context.select_type({type = "scenario"})
-  local s = info.find_level({id = "test1"})
+  context.select_type{type = "scenario"}
+  local s = info.find_level{id = "test1"}
   if s.index < 0 then
     log(" error: Could not find scenario with id=test1")
   end
-  context.select_level({index = s.index})
+  context.select_level{index = s.index}
 
   log("configuring a game")
-  context.set_name({name = "Test"})
-  context.update_settings({registered_users = false})
+  context.set_name{name = "Test"}
+  context.update_settings{registered_users = false}
 
-  events, context, info = coroutine.yield()
+  events, context, info = wesnoth.plugin.next_slice()
 
-  context.create({})
+  context.create{}
 
   local ready = nil
   repeat
-    events, context, info = coroutine.yield()
+    events, context, info = wesnoth.plugin.next_slice()
     for i,v in ipairs(events) do
-      if v[1] == "chat" then
-        std_print(events[i][2])
-        if v[2].message == "ready" then
+      if v.tag == "chat" then
+        std_print(events[i].contents.message)
+        if v.contents.message == "ready" then
           ready = true
         end
       end
@@ -82,31 +77,28 @@ local function plugin()
   until ready
 
   log("starting game...")
-  context.chat({message = "starting"})
-  context.launch({})
+  context.chat{message = "starting"}
+  context.launch{}
 
-  repeat
-    events, context, info = coroutine.yield()
-    idle_text("in " .. info.name .. " waiting for game")
-  until info.name == "Game"
+  events, context, info = wesnoth.plugin.wait_until("Game", function(name)
+    idle_text("in " .. name .. " waiting for game")
+  end)
 
   log("got to a game context...")
 
-  repeat
-    events, context, info = coroutine.yield()
-    idle_text("in " .. info.name .. " waiting for not game")
-  until info.name ~= "Game"
+  events, context, info = wesnoth.plugin.wait_until_not("Game", function(name)
+    idle_text("in " .. name .. " waiting for not game")
+  end)
 
   log("left a game context...")
 
   repeat
     context.quit({})
     log("quitting a " .. info.name .. " context...")
-    events, context, info = coroutine.yield()
+    events, context, info = wesnoth.plugin.next_slice()
   until info.name == "titlescreen"
 
   context.exit({code = 0})
-  coroutine.yield()
 end
 
 return plugin
diff --git a/data/test/plugin/join.lua b/data/test/plugin/join.lua
index adb48c433ba..53fe8a7a80c 100644
--- a/data/test/plugin/join.lua
+++ b/data/test/plugin/join.lua
@@ -9,8 +9,6 @@ local function plugin()
 
   local counter = 0
 
-  local events, context, info
-
   local function find_test_game(game_info)
     local g = game_info.game_list()
     if g then
@@ -18,8 +16,8 @@ local function plugin()
       if gamelist then
         for i = 1, #gamelist do
           local t = gamelist[i]
-          if t[1] == "game" then
-            local game = t[2]
+          if t.tag == "game" then
+            local game = t.contents
             if game.scenario == "Test" then
               return game.id
             end
@@ -40,41 +38,39 @@ local function plugin()
 
   log("hello world")
 
-  repeat
-    events, context, info = coroutine.yield()
-    idle_text("in " .. info.name .. " waiting for titlescreen or lobby")
-  until info.name == "titlescreen" or info.name == "Multiplayer Lobby"
+  local events, context, info = wesnoth.plugin.wait_until_any({"titlescreen", "Multiplayer Lobby"}, function(name)
+    idle_text("in " .. name .. " waiting for titlescreen or lobby")
+  end)
 
   local tries = 0
   while info.name == "titlescreen" and tries < 100 do
-    context.play_multiplayer({})
+    context.play_multiplayer{}
     tries = tries + 1
     log("playing multiplayer...")
-    events, context, info = coroutine.yield()
+    events, context, info = wesnoth.plugin.next_slice()
   end
   if info.name == "titlescreen" then
-    context.exit({code = 1})
-    coroutine.yield()
+    context.exit{code = 1}
+    return
   end
 
-  repeat
-    events, context, info = coroutine.yield()
-    idle_text("in " .. info.name .. " waiting for lobby")
-  until info.name == "Multiplayer Lobby"
+  events, context, info = wesnoth.plugin.wait_until("Multiplayer Lobby", function(name)
+    idle_text("in " .. name .. " waiting for lobby")
+  end)
 
-  events, context, info = coroutine.yield()
+  events, context, info = wesnoth.plugin.next_slice()
 
-  context.chat({message = "waiting for test game to join..."})
+  context.chat{message = "waiting for test game to join..."}
 
   local test_game = nil
 
   repeat
-    events, context, info = coroutine.yield()
+    events, context, info = wesnoth.plugin.next_slice()
     idle_text("in " .. info.name .. " waiting for test game")
 
     for i,v in ipairs(events) do
-      if v[1] == "chat" then
-        std_print("chat:", v[2].message)
+      if v.tag == "chat" then
+        std_print("chat:", v.contents.message)
       end
     end
 
@@ -82,76 +78,70 @@ local function plugin()
   until test_game
 
   log("found a test game, joining... id = " .. test_game)
-  context.chat({message = "found test game"})
-  context.select_game({id = test_game})
+  context.chat{message = "found test game"}
+  context.select_game{id = test_game}
 
-  events, context, info = coroutine.yield()
+  events, context, info = wesnoth.plugin.next_slice()
 
-    context.chat({message = "going to join"})
+  context.chat{message = "going to join"}
 
-  context.join({})
+  context.join{}
 
-  events, context, info = coroutine.yield()
+  events, context, info = wesnoth.plugin.next_slice()
 
-  -- Don't know why THIS context has to chat member but it doesn't
+  -- Don't know why THIS context has no chat member but it doesn't
   -- Adding the guard if to bypass a script crash and get mp_tests running.
   -- GAL 28NOV2017
   if context.chat then
-    context.chat({message = "done first join"})
+    context.chat{message = "done first join"}
   end
 
   while not (info.name == "Dialog" or info.name == "Multiplayer Join") do
     if context.join then
-      context.join({})
+      context.join{}
     else
       std_print("did not find join...")
     end
 
-    events, context, info = coroutine.yield()
+    events, context, info = wesnoth.plugin.next_slice()
     idle_text("in " .. info.name .. " waiting for leader select dialog")
   end
 
   if info.name == "Dialog" then
     log("got a leader select dialog...")
-    context.skip_dialog({})
-    events, context, info = coroutine.yield()
-
-    repeat
-      events, context, info = coroutine.yield()
-      idle_text("in " .. info.name .. " waiting for mp join")
-    until info.name == "Multiplayer Join"
+    context.skip_dialog{}
+    events, context, info = wesnoth.plugin.wait_until("Multiplayer Join", function(name)
+      idle_text("in " .. name .. " waiting for mp join")
+    end)
   end
 
   log("got to multiplayer join...")
-  context.chat({message = "ready"})
+  context.chat{message = "ready"}
 
-  repeat
-    events, context, info = coroutine.yield()
-    idle_text("in " .. info.name .. " waiting for game")
-  until info.name == "Game"
+  events, context, info = wesnoth.plugin.wait_until("Game", function(name)
+    idle_text("in " .. name .. " waiting for game")
+  end)
 
   log("got to a game context...")
 
   repeat
-    events, context, info = coroutine.yield()
+    events, context, info = wesnoth.plugin.next_slice()
     idle_text("in " .. info.name .. " waiting for the last scenario")
   until info.scenario_name ~= nil and info.scenario_name().scenario_name == "Multiplayer Unit Test test2"
 
-  repeat
-    events, context, info = coroutine.yield()
-    idle_text("in " .. info.name .. " waiting for not game")
-  until info.name ~= "Game"
+  events, context, info = wesnoth.plugin.wait_until_not("Game", function(name)
+    idle_text("in " .. name .. " waiting for not game")
+  end)
 
   log("left a game context...")
 
   repeat
-    context.quit({})
+    context.quit{}
     log("quitting a " .. info.name .. " context...")
-    events, context, info = coroutine.yield()
+    events, context, info = wesnoth.plugin.next_slice()
   until info.name == "titlescreen"
 
-  context.exit({code = 0})
-  coroutine.yield()
+  context.exit{code = 0}
 end
 
 return plugin