mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
feat(koreader): rebuild the plugin interface and fix four-way annotation sync
Squash of feat/koreader-widget-board. KOReader plugin 2.0.0 gets the widget-board dashboard, redesigned book details, menus, lists and dialogs, Decor page and reading companions. Highlights, notes and bookmarks now stay in step across web, Kobo, KOReader and the phones (defects D-00 to D-20, migration 0121), and reading progress and narration hand off cleanly between devices.
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
-- Proves KOReader's side of BookOrbit: a trimmed Tools entry, the menu bar
|
||||
-- tab that acts as a button (and its opt-out), the icon path the tab bar can
|
||||
-- resolve, and where each of the menu sheet's actions goes.
|
||||
|
||||
package.loaded["gettext"] = function(text)
|
||||
return text
|
||||
end
|
||||
@@ -11,20 +15,23 @@ package.loaded["ffi/util"] = {
|
||||
end,
|
||||
}
|
||||
|
||||
local ticks = {}
|
||||
package.loaded["device"] = { model = "test-device" }
|
||||
package.loaded["ui/widget/infomessage"] = { new = function(_, opts) return opts end }
|
||||
package.loaded["ui/widget/inputdialog"] = {}
|
||||
package.loaded["ui/widget/multiinputdialog"] = {}
|
||||
package.loaded["ui/network/manager"] = {}
|
||||
package.loaded["ui/widget/notification"] = {}
|
||||
package.loaded["ui/uimanager"] = {}
|
||||
package.loaded["ffi/sha2"] = { md5 = function(value) return value end }
|
||||
package.loaded["util"] = {
|
||||
trim = function(value)
|
||||
return tostring(value or ""):match("^%s*(.-)%s*$")
|
||||
end,
|
||||
package.loaded["ui/network/manager"] = {
|
||||
runWhenConnected = function(_, callback) callback() end,
|
||||
}
|
||||
package.loaded["ui/widget/notification"] = {}
|
||||
package.loaded["ui/uimanager"] = {
|
||||
nextTick = function(_, callback) table.insert(ticks, callback) end,
|
||||
tickAfterNext = function(_, callback) table.insert(ticks, callback) end,
|
||||
show = function() end,
|
||||
}
|
||||
package.loaded["ffi/sha2"] = { md5 = function(value) return value end }
|
||||
package.loaded["libs/libkoreader-lfs"] = { currentdir = function() return "/opt/koreader" end }
|
||||
package.loaded["bookorbit_api"] = {}
|
||||
package.loaded["bookorbit_highlight_diagnostics"] = {}
|
||||
package.loaded["bookorbit_sweep"] = {
|
||||
syncStatus = function()
|
||||
return { lastSweepAt = 0, matched = 0, unmatched = 0 }
|
||||
@@ -46,194 +53,151 @@ local function itemText(item)
|
||||
if item.text_func then return item:text_func() end
|
||||
end
|
||||
|
||||
local function findItem(items, text)
|
||||
for _, item in ipairs(items) do
|
||||
if itemText(item) == text then return item end
|
||||
local function texts(items)
|
||||
local out = {}
|
||||
for _, item in ipairs(items) do table.insert(out, itemText(item)) end
|
||||
return table.concat(out, "|")
|
||||
end
|
||||
|
||||
local function newPlugin(opts)
|
||||
opts = opts or {}
|
||||
local calls = {}
|
||||
local plugin = {
|
||||
settings = { menu_bar_icon = opts.menu_bar_icon },
|
||||
path = opts.path or "plugins/bookorbit.koplugin",
|
||||
ui = opts.reader and { document = { file = "/books/Book.epub" }, menu = {} } or { menu = {} },
|
||||
isLoggedIn = function() return opts.logged_out ~= true end,
|
||||
calls = calls,
|
||||
}
|
||||
MainMenu.install(plugin)
|
||||
for _, name in ipairs({ "browseCatalog", "openSignIn", "openBookSheet", "openSettings", "openSyncStatus", "startSweep", "applyUpdate", "customizeHome" }) do
|
||||
plugin[name] = function(_, ...) table.insert(calls, { name, ... }) end
|
||||
end
|
||||
end
|
||||
|
||||
local function hasItem(items, text)
|
||||
return findItem(items, text) ~= nil
|
||||
end
|
||||
|
||||
local function assertItemText(items, index, text, label)
|
||||
assertEqual(itemText(items[index]), text, label)
|
||||
end
|
||||
|
||||
local function assertSeparator(items, index, expected, label)
|
||||
assertEqual(items[index].separator == true, expected, label)
|
||||
return plugin, calls
|
||||
end
|
||||
|
||||
local function menuItems(plugin)
|
||||
local menu_items = {}
|
||||
plugin:addToMainMenu(menu_items)
|
||||
return menu_items.bookorbit.sub_item_table
|
||||
return menu_items
|
||||
end
|
||||
|
||||
local function newPlugin(logged_in)
|
||||
local plugin = {
|
||||
SYNC_STRATEGY = { PROMPT = 1, SILENT = 2, DISABLE = 3 },
|
||||
settings = {
|
||||
auto_sync = true,
|
||||
annotation_sync = true,
|
||||
skip_sync_when_offline = false,
|
||||
sync_forward = 1,
|
||||
sync_backward = 1,
|
||||
},
|
||||
isLoggedIn = function()
|
||||
return logged_in
|
||||
end,
|
||||
updateCheckMenuText = function()
|
||||
return "Installed plugin: current"
|
||||
end,
|
||||
getSyncPeriod = function()
|
||||
return 10
|
||||
end,
|
||||
}
|
||||
MainMenu.install(plugin)
|
||||
return plugin
|
||||
local function runTicks()
|
||||
while #ticks > 0 do table.remove(ticks, 1)() end
|
||||
end
|
||||
|
||||
local plugin = newPlugin(false)
|
||||
-- The file browser's Tools entry: open BookOrbit, or its settings.
|
||||
local plugin, calls = newPlugin()
|
||||
local items = menuItems(plugin)
|
||||
assertEqual(#items, 1, "logged-out menu only has setup group")
|
||||
assertEqual(hasItem(items, "Account & setup"), true, "logged-out menu keeps account setup")
|
||||
assertEqual(hasItem(items, "Open dashboard"), false, "logged-out menu hides dashboard")
|
||||
assertEqual(hasItem(items, "Current book"), false, "logged-out menu hides current book")
|
||||
assertEqual(hasItem(items, "Sync current book now"), false, "logged-out menu hides current book sync")
|
||||
assertEqual(hasItem(items, "Sync all books now"), false, "logged-out menu hides sync all")
|
||||
assertEqual(hasItem(items, "Sync settings"), false, "logged-out menu hides sync settings")
|
||||
assertEqual(hasItem(items, "Settings"), false, "logged-out menu hides settings")
|
||||
assertEqual(texts(items.bookorbit.sub_item_table), "Open BookOrbit|Settings", "the Tools entry is two rows in the file browser")
|
||||
assertEqual(items.bookorbit.sorting_hint, "tools", "the entry still falls back to the Tools menu")
|
||||
|
||||
local account = findItem(items, "Account & setup")
|
||||
assertEqual(hasItem(account.sub_item_table, "Login"), true, "logged-out setup has login")
|
||||
local dashboard_items = plugin:dashboardMenuItems()
|
||||
assertEqual(hasItem(dashboard_items, "Account & setup"), true, "dashboard setup menu keeps account setup when logged out")
|
||||
-- In a book it adds This book.
|
||||
local reader = newPlugin({ reader = true })
|
||||
assertEqual(texts(menuItems(reader).bookorbit.sub_item_table), "Open BookOrbit|This book|Settings", "a book adds This book")
|
||||
|
||||
plugin = newPlugin(true)
|
||||
items = menuItems(plugin)
|
||||
assertEqual(#items, 4, "file manager menu has dashboard, global sync, settings and setup rows")
|
||||
assertItemText(items, 1, "Open dashboard", "file manager order starts with dashboard")
|
||||
assertItemText(items, 2, "Sync all books now", "file manager order keeps global sync second")
|
||||
assertItemText(items, 3, "Settings", "file manager order keeps settings third")
|
||||
assertItemText(items, 4, "Account & setup", "file manager order ends with setup")
|
||||
assertSeparator(items, 1, true, "file manager dashboard ends dashboard group")
|
||||
assertSeparator(items, 2, true, "file manager sync all ends global sync group")
|
||||
assertSeparator(items, 3, true, "file manager settings ends settings group")
|
||||
assertSeparator(items, 4, false, "file manager setup has no trailing separator")
|
||||
assertEqual(hasItem(items, "Open dashboard"), true, "logged-in menu shows dashboard")
|
||||
assertEqual(hasItem(items, "Open dashboard on startup (Off)"), false, "logged-in top level hides dashboard startup")
|
||||
assertEqual(hasItem(items, "Installed plugin: current"), false, "logged-in top level hides update row")
|
||||
assertEqual(hasItem(items, "Current book"), false, "file manager menu hides current book")
|
||||
assertEqual(hasItem(items, "Sync current book now"), false, "file manager menu hides current book sync")
|
||||
assertEqual(hasItem(items, "Auto sync current book"), false, "file manager menu hides current book auto sync")
|
||||
assertEqual(hasItem(items, "Sync all books now"), true, "logged-in menu shows sync all")
|
||||
assertEqual(hasItem(items, "Two-way highlights & bookmarks"), false, "logged-in top level hides the two-way toggle")
|
||||
assertEqual(hasItem(items, "Skip auto-sync when offline"), false, "logged-in top level hides offline skip toggle")
|
||||
assertEqual(hasItem(items, "Sync settings"), false, "logged-in menu replaces sync settings with settings")
|
||||
assertEqual(hasItem(items, "Settings"), true, "logged-in menu shows settings")
|
||||
assertEqual(hasItem(items, "Account & setup"), true, "logged-in menu keeps account setup")
|
||||
local file_manager_settings = findItem(items, "Settings")
|
||||
assertEqual(hasItem(file_manager_settings.sub_item_table, "Dashboard"), true, "file manager settings has dashboard group")
|
||||
assertEqual(hasItem(file_manager_settings.sub_item_table, "Sync"), true, "file manager settings has sync group")
|
||||
assertEqual(hasItem(file_manager_settings.sub_item_table, "Plugin"), true, "file manager settings has plugin group")
|
||||
local file_manager_dashboard_settings = findItem(file_manager_settings.sub_item_table, "Dashboard")
|
||||
assertEqual(hasItem(file_manager_dashboard_settings.sub_item_table, "Open dashboard on startup (Off)"), true, "file manager dashboard settings has startup option")
|
||||
assertEqual(hasItem(file_manager_dashboard_settings.sub_item_table, "Section 1 (Stats)"), true, "file manager dashboard settings has slot 1")
|
||||
assertEqual(hasItem(file_manager_dashboard_settings.sub_item_table, "Section 2 (Continue reading)"), true, "file manager dashboard settings has slot 2")
|
||||
assertEqual(hasItem(file_manager_dashboard_settings.sub_item_table, "Section 3 (Discover)"), true, "file manager dashboard settings has slot 3")
|
||||
assertEqual(hasItem(file_manager_dashboard_settings.sub_item_table, "Section 4 (Browse)"), true, "file manager dashboard settings has slot 4")
|
||||
assertEqual(hasItem(file_manager_dashboard_settings.sub_item_table, "Reset to Default"), true, "dashboard settings can restore the four defaults")
|
||||
local file_manager_sync_settings = findItem(file_manager_settings.sub_item_table, "Sync")
|
||||
assertEqual(hasItem(file_manager_sync_settings.sub_item_table, "Auto sync current book"), false, "file manager sync settings hides reader auto sync")
|
||||
assertEqual(hasItem(file_manager_sync_settings.sub_item_table, "Two-way highlights & bookmarks"), true, "file manager sync settings has the two-way toggle")
|
||||
assertEqual(hasItem(file_manager_sync_settings.sub_item_table, "Skip auto-sync when offline"), true, "file manager sync settings has offline skip toggle")
|
||||
assertEqual(hasItem(file_manager_sync_settings.sub_item_table, "Open dashboard on startup (Off)"), false, "file manager sync settings excludes dashboard startup")
|
||||
local file_manager_plugin_settings = findItem(file_manager_settings.sub_item_table, "Plugin")
|
||||
assertEqual(hasItem(file_manager_plugin_settings.sub_item_table, "Installed plugin: current"), true, "file manager plugin settings has update row")
|
||||
-- The menu bar tab is a button: never remembered, never a list.
|
||||
local tab = items.bookorbit_tab
|
||||
assertEqual(tab ~= nil, true, "the menu bar tab is offered by default")
|
||||
assertEqual(tab.remember, false, "the tab is never remembered, so opening the menu never fires it")
|
||||
assertEqual(#tab, 0, "the tab holds no rows")
|
||||
assertEqual(type(tab.callback), "function", "the tab acts on a tap")
|
||||
|
||||
dashboard_items = plugin:dashboardMenuItems()
|
||||
assertEqual(hasItem(dashboard_items, "Open dashboard"), false, "dashboard mirror skips open dashboard")
|
||||
assertItemText(dashboard_items, 1, "Installed plugin: current", "dashboard mirror promotes update row first")
|
||||
assertItemText(dashboard_items, 2, "Sync all books now", "dashboard mirror keeps sync all second")
|
||||
assertItemText(dashboard_items, 3, "Settings", "dashboard mirror keeps settings third")
|
||||
assertItemText(dashboard_items, 4, "Account & setup", "dashboard mirror keeps setup fourth")
|
||||
assertSeparator(dashboard_items, 1, true, "dashboard mirror update row ends update group")
|
||||
assertSeparator(dashboard_items, 2, true, "dashboard mirror sync all ends global sync group")
|
||||
assertSeparator(dashboard_items, 3, true, "dashboard mirror settings ends settings group")
|
||||
assertSeparator(dashboard_items, 4, false, "dashboard mirror setup has no trailing separator")
|
||||
assertEqual(hasItem(dashboard_items, "Sync all books now"), true, "dashboard mirror keeps sync all")
|
||||
assertEqual(hasItem(dashboard_items, "Installed plugin: current"), true, "dashboard mirror top level shows update row")
|
||||
assertEqual(hasItem(dashboard_items, "Account & setup"), true, "dashboard mirror keeps account setup")
|
||||
local dashboard_settings = findItem(dashboard_items, "Settings")
|
||||
local dashboard_dashboard_settings = findItem(dashboard_settings.sub_item_table, "Dashboard")
|
||||
assertEqual(hasItem(dashboard_dashboard_settings.sub_item_table, "Open dashboard on startup (Off)"), true, "dashboard settings has startup option")
|
||||
assertEqual(hasItem(dashboard_dashboard_settings.sub_item_table, "Section 1 (Stats)"), true, "dashboard settings has slot 1")
|
||||
assertEqual(hasItem(dashboard_dashboard_settings.sub_item_table, "Section 2 (Continue reading)"), true, "dashboard settings has slot 2")
|
||||
assertEqual(hasItem(dashboard_dashboard_settings.sub_item_table, "Section 3 (Discover)"), true, "dashboard settings has slot 3")
|
||||
assertEqual(hasItem(dashboard_dashboard_settings.sub_item_table, "Section 4 (Browse)"), true, "dashboard settings has slot 4")
|
||||
assertEqual(hasItem(dashboard_items, "Section 1 (Stats)"), false, "slot pickers are not promoted to the dashboard menu top level")
|
||||
local dashboard_sync_settings = findItem(dashboard_settings.sub_item_table, "Sync")
|
||||
assertEqual(hasItem(dashboard_sync_settings.sub_item_table, "Two-way highlights & bookmarks"), true, "dashboard sync settings has the two-way toggle")
|
||||
assertEqual(hasItem(dashboard_sync_settings.sub_item_table, "Skip auto-sync when offline"), true, "dashboard sync settings has offline skip toggle")
|
||||
assertEqual(hasItem(dashboard_sync_settings.sub_item_table, "Open dashboard on startup (Off)"), false, "dashboard sync settings excludes dashboard startup")
|
||||
assertEqual(hasItem(dashboard_settings.sub_item_table, "Plugin"), false, "dashboard settings omits duplicate plugin group")
|
||||
-- Its icon is the shipped SVG, reached from KOReader's icon folders by a
|
||||
-- climb to the root, with the extension the tab bar adds stripped.
|
||||
assertEqual(tab.icon:sub(1, 9), "../../../", "the icon name climbs out of the icon folders")
|
||||
assertEqual(tab.icon:find("opt/koreader/plugins/bookorbit.koplugin/assets/bookorbit.tab", 1, true) ~= nil, true, "a relative plugin path is made absolute")
|
||||
assertEqual(tab.icon:sub(-4) ~= ".svg", true, "the extension is left to the tab bar")
|
||||
local user_plugin = newPlugin({ path = "/mnt/onboard/.adds/koreader/plugins/bookorbit.koplugin" })
|
||||
assertEqual(user_plugin:menuBarIconName():find("../mnt/onboard/.adds/koreader/plugins/bookorbit.koplugin/assets/bookorbit.tab", 1, true) ~= nil, true,
|
||||
"an absolute plugin path is used as it is")
|
||||
|
||||
plugin.ui = { document = {} }
|
||||
items = menuItems(plugin)
|
||||
assertEqual(#items, 6, "reader menu has dashboard, current-book, auto-sync, global sync, settings and setup rows")
|
||||
assertItemText(items, 1, "Open dashboard", "reader order starts with dashboard")
|
||||
assertItemText(items, 2, "Sync current book now", "reader order keeps current book sync second")
|
||||
assertItemText(items, 3, "Auto sync current book", "reader order keeps auto sync third")
|
||||
assertItemText(items, 4, "Sync all books now", "reader order keeps sync all fourth")
|
||||
assertItemText(items, 5, "Settings", "reader order keeps settings fifth")
|
||||
assertItemText(items, 6, "Account & setup", "reader order ends with setup")
|
||||
assertSeparator(items, 1, true, "reader dashboard ends dashboard group")
|
||||
assertSeparator(items, 2, false, "reader current book sync stays in sync action group")
|
||||
assertSeparator(items, 3, true, "reader auto sync ends current-book group")
|
||||
assertSeparator(items, 4, true, "reader sync all ends sync action group")
|
||||
assertSeparator(items, 5, true, "reader settings ends settings group")
|
||||
assertSeparator(items, 6, false, "reader setup has no trailing separator")
|
||||
assertEqual(hasItem(items, "Current book"), false, "reader menu flattens current book actions")
|
||||
assertEqual(hasItem(items, "Sync current book now"), true, "reader menu has manual book sync")
|
||||
assertEqual(hasItem(items, "Auto sync current book"), true, "reader top level has auto sync")
|
||||
assertEqual(hasItem(items, "Push progress"), false, "reader menu hides progress-only push")
|
||||
assertEqual(hasItem(items, "Pull progress"), false, "reader menu hides progress-only pull")
|
||||
assertEqual(hasItem(items, "Retry highlight sync"), false, "reader menu hides highlight retry")
|
||||
assertEqual(hasItem(items, "Retry open-book match"), false, "reader menu hides match retry")
|
||||
-- Turned off, the tab is not registered at all (an unordered item would show
|
||||
-- up as a NEW: row in the first menu).
|
||||
local hidden = newPlugin({ menu_bar_icon = false })
|
||||
assertEqual(menuItems(hidden).bookorbit_tab, nil, "no tab when the icon is turned off")
|
||||
|
||||
local settings = findItem(items, "Settings")
|
||||
assertEqual(hasItem(settings.sub_item_table, "Dashboard"), true, "reader settings has dashboard group")
|
||||
assertEqual(hasItem(settings.sub_item_table, "Sync"), true, "reader settings has sync group")
|
||||
assertEqual(hasItem(settings.sub_item_table, "Plugin"), true, "reader settings has plugin group")
|
||||
local reader_dashboard_settings = findItem(settings.sub_item_table, "Dashboard")
|
||||
assertEqual(hasItem(reader_dashboard_settings.sub_item_table, "Open dashboard on startup (Off)"), true, "reader dashboard settings has startup option")
|
||||
local sync_settings = findItem(settings.sub_item_table, "Sync")
|
||||
assertEqual(hasItem(sync_settings.sub_item_table, "Auto sync current book"), false, "reader sync settings excludes top-level auto sync")
|
||||
assertEqual(hasItem(sync_settings.sub_item_table, "Two-way highlights & bookmarks"), true, "sync settings has the two-way toggle")
|
||||
assertEqual(hasItem(sync_settings.sub_item_table, "Skip auto-sync when offline"), true, "sync settings has offline toggle")
|
||||
assertEqual(hasItem(sync_settings.sub_item_table, "Open dashboard on startup (Off)"), false, "sync settings excludes dashboard startup")
|
||||
assertEqual(hasItem(items, "Two-way highlights & bookmarks"), false, "top level hides the two-way toggle")
|
||||
assertEqual(hasItem(items, "Skip auto-sync when offline"), false, "top level hides offline toggle")
|
||||
assertEqual(findItem(sync_settings.sub_item_table, "Skip auto-sync when offline").enabled_func(), true, "offline toggle is enabled when auto sync is on")
|
||||
local reader_plugin_settings = findItem(settings.sub_item_table, "Plugin")
|
||||
assertEqual(hasItem(reader_plugin_settings.sub_item_table, "Installed plugin: current"), true, "reader plugin settings has update row")
|
||||
-- Tapping the tab: BookOrbit in the file browser, This book in a book, and
|
||||
-- sign-in when signed out, each after the menu's own close.
|
||||
plugin.ui.menu.onCloseFileManagerMenu = function() table.insert(calls, { "close_fm_menu" }) end
|
||||
tab.callback()
|
||||
assertEqual(calls[1][1], "close_fm_menu", "the KOReader menu closes first")
|
||||
assertEqual(#calls, 1, "nothing opens before the close has painted")
|
||||
runTicks()
|
||||
assertEqual(calls[2][1], "browseCatalog", "the file browser's tab opens BookOrbit")
|
||||
|
||||
local reader_dashboard_items = plugin:dashboardMenuItems()
|
||||
assertEqual(hasItem(reader_dashboard_items, "Sync current book now"), false, "dashboard mirror hides current book sync while reader is open")
|
||||
assertEqual(hasItem(reader_dashboard_items, "Auto sync current book"), false, "dashboard mirror hides auto sync while reader is open")
|
||||
assertItemText(reader_dashboard_items, 1, "Installed plugin: current", "reader dashboard mirror promotes update row first")
|
||||
assertItemText(reader_dashboard_items, 2, "Sync all books now", "reader dashboard mirror keeps sync all second")
|
||||
assertItemText(reader_dashboard_items, 3, "Settings", "reader dashboard mirror keeps settings third")
|
||||
assertItemText(reader_dashboard_items, 4, "Account & setup", "reader dashboard mirror keeps setup fourth")
|
||||
local book, book_calls = newPlugin({ reader = true })
|
||||
book.ui.menu.onCloseReaderMenu = function() table.insert(book_calls, { "close_reader_menu" }) end
|
||||
menuItems(book).bookorbit_tab.callback()
|
||||
runTicks()
|
||||
assertEqual(book_calls[1][1], "close_reader_menu", "the reader menu closes first")
|
||||
assertEqual(book_calls[2][1], "openBookSheet", "in a book the tab opens This book")
|
||||
|
||||
plugin.settings.annotation_sync = false
|
||||
plugin.settings.auto_sync = false
|
||||
items = menuItems(plugin)
|
||||
settings = findItem(items, "Settings")
|
||||
sync_settings = findItem(settings.sub_item_table, "Sync")
|
||||
assertEqual(findItem(sync_settings.sub_item_table, "Skip auto-sync when offline").enabled_func(), false, "offline toggle is disabled when auto sync is off")
|
||||
assertEqual(hasItem(items, "Retry highlight sync"), false, "two-way-off reader menu hides highlight retry")
|
||||
assertEqual(hasItem(items, "Retry open-book match"), false, "two-way-off reader menu hides match retry")
|
||||
local out, out_calls = newPlugin({ logged_out = true })
|
||||
menuItems(out).bookorbit_tab.callback()
|
||||
runTicks()
|
||||
assertEqual(out_calls[1][1], "openSignIn", "signed out, the tab opens sign-in")
|
||||
|
||||
-- Open BookOrbit from Tools signs in first when needed.
|
||||
out_calls[1] = nil
|
||||
out:openBookOrbit()
|
||||
assertEqual(out_calls[#out_calls][1], "openSignIn", "Open BookOrbit asks for a sign-in when signed out")
|
||||
|
||||
-- The sheet's actions close it, then act.
|
||||
local sheet_plugin, sheet_calls = newPlugin()
|
||||
local events = {}
|
||||
local catalog = {
|
||||
goDashboard = function() table.insert(events, "home") end,
|
||||
onCloseAllMenus = function() table.insert(events, "exit") end,
|
||||
onSearchButtonTap = function() table.insert(events, "search") end,
|
||||
boardOpenLink = function(_, link) table.insert(events, "link:" .. link) end,
|
||||
showBookActions = function() table.insert(events, "list-options") end,
|
||||
}
|
||||
local closes, refreshes = 0, 0
|
||||
local page = {
|
||||
close = function() closes = closes + 1 end,
|
||||
refresh = function() refreshes = refreshes + 1 end,
|
||||
sheet_data = {},
|
||||
}
|
||||
package.loaded["bookorbit_menu_sheet"] = { data = function() return { reloaded = true } end }
|
||||
local function run(action)
|
||||
sheet_plugin:onMenuSheetAction(page, catalog, action)
|
||||
runTicks()
|
||||
end
|
||||
run({ kind = "home" })
|
||||
run({ kind = "exit" })
|
||||
run({ kind = "search" })
|
||||
run({ kind = "link", link = "authors" })
|
||||
run({ kind = "list-options" })
|
||||
assertEqual(table.concat(events, ","), "home,exit,search,link:authors,list-options", "catalog actions reach the catalog")
|
||||
assertEqual(closes, 5, "every action closes the sheet first")
|
||||
|
||||
-- Sync now keeps the sheet open: its tile shows the run, then the outcome.
|
||||
run({ kind = "sync" })
|
||||
assertEqual(closes, 5, "Sync now leaves the sheet open")
|
||||
assertEqual(sheet_calls[1][1], "startSweep", "Sync now starts a library sync")
|
||||
local sweep = sheet_calls[1][2]
|
||||
assertEqual(sweep.quiet, true, "the sync reports to the sheet, not a dialog")
|
||||
assertEqual(page.sheet_data.sync.running, true, "the tile says the sync is running")
|
||||
sweep.on_progress("Matching books")
|
||||
assertEqual(page.sheet_data.sync.text, "Matching books", "the short progress line is shown")
|
||||
sweep.on_done(nil)
|
||||
assertEqual(page.sheet_data.reloaded, true, "the sheet's numbers are reloaded when the sync ends")
|
||||
assertEqual(page.sheet_data.sync.done, true, "the tile says the sync finished")
|
||||
assertEqual(refreshes, 3, "the sheet redraws at start, on progress and at the end")
|
||||
plugin.errorLabel = function() return "fallback" end
|
||||
sheet_plugin.errorLabel = plugin.errorLabel
|
||||
sweep.on_done("not_started")
|
||||
assertEqual(page.sheet_data.sync.err, "Another sync is running", "a sync that did not start says why")
|
||||
|
||||
table.remove(sheet_calls, 1)
|
||||
run({ kind = "settings" })
|
||||
run({ kind = "status" })
|
||||
run({ kind = "about" })
|
||||
run({ kind = "customize" })
|
||||
local names = {}
|
||||
for _, call in ipairs(sheet_calls) do table.insert(names, call[1]) end
|
||||
assertEqual(table.concat(names, ","), "openSettings,openSyncStatus,openSettings,customizeHome", "plugin actions reach the plugin")
|
||||
assertEqual(sheet_calls[3][3], "about", "Help & about opens settings on About")
|
||||
|
||||
print("bookorbit_menu_context_test.lua: ok")
|
||||
|
||||
Reference in New Issue
Block a user