test: the lab restores real tabs across real launches, and follows real links

tools/lab/wonderink-workspace-check launches the installed command again
and again against a stand-in for WonderInk's start page whose sign-in is
Basic auth, as WonderInk's is: restored after 5 and 90 minutes; fresh
after two hours and a minute, a day and a week; reopened untouched until
it lapses; a click after a restore counts and the restore does not; a
busy page and an untouched print preview do not; Print does; closed,
reordered, worksheet and missing-worksheet tabs; killed outright; a
restore that crashes twice; corrupt, future-format and half-written
files; the file holding no credential; restored tabs printing. 59 checks.

The print check follows every kind of link on a signed-in page with one
click — new tab in front for links and window.open, nothing for buttons
and anchors, same-tab for no target, Back, closing — and prints a PDF and
a picture reached by a link, and a page after several tabs. 0.2.6.3's
scenarios are unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
ekklesia
2026-09-26 21:12:17 -05:00
co-authored by Claude Opus 5.5
parent b5d9535467
commit 78a844968c
5 changed files with 651 additions and 2 deletions
+101
View File
@@ -177,6 +177,107 @@ if scenario.startswith("bw-"):
QTimer.singleShot(2500, begin)
else:
view.loadFinished.connect(begin)
elif scenario.startswith("links:"):
# links:follow every kind of link on the lab's signed-in links page,
# clicked in turn: what opens where, and what does not
# links:pdf a worksheet reached by a link, printed
# links:image a picture reached by a link, printed as a picture
# links:image-rclick the same picture, right-click Print image
# links:tabs-print several links opened, some closed, then the page printed
from PyQt6.QtCore import QEvent, QPointF, Qt
from PyQt6.QtGui import QMouseEvent
from PyQt6.QtWidgets import QApplication as Application
variant = scenario.split(":", 1)[1]
links_view = window.open_tab(); links_view.load(QUrl(f"{SITE}/login"))
def on_links():
return links_view.url().path() == "/lesson" or links_view.url().path() == "/links"
def click_in(view, selector, then, button=Qt.MouseButton.LeftButton):
js = ("(function(){var e=document.querySelector(%r); if(!e) return null; e.scrollIntoView({block:'center'});"
"var r=e.getBoundingClientRect(); return [r.x+r.width/2, r.y+r.height/2]})()" % selector)
def at(xy):
if not xy:
stamp(f"NO {selector}"); return finish(6)
zoom = view.zoomFactor(); point = QPointF(xy[0] * zoom, xy[1] * zoom)
for kind, buttons in ((QEvent.Type.MouseButtonPress, button), (QEvent.Type.MouseButtonRelease, Qt.MouseButton.NoButton)):
Application.sendEvent(view.focusProxy(), QMouseEvent(kind, point, QPointF(view.mapToGlobal(point)),
button, buttons, Qt.KeyboardModifier.NoModifier))
QTimer.singleShot(1500, then)
view.page().runJavaScript(js, at)
def tabs():
return [window._tabs.widget(i).url().toString().replace(SITE, "") for i in range(window._tabs.count())]
def report(label):
current = window.current()
stamp(f"LINK {label} tabs={len(tabs())} current={current.url().toString().replace(SITE, '')!r} "
f"current_is_new={current is not links_view} worksheet={current in window._pdf_views}")
def back_to_links():
window._tabs.setCurrentWidget(links_view)
def go_links(then):
# From the lesson the site sent us to after signing in, to the links page, in this tab.
links_view.load(QUrl(f"{SITE}/links"))
when(lambda: links_view.url().path() == "/links", lambda: QTimer.singleShot(1200, then), "the links page")
steps = []
if variant == "follow":
order = [("#blank", "text link, target=_blank, to a picture"), ("#external", "another site"),
("#linked-picture", "a linked picture"), ("#pdf", "a worksheet PDF"),
("#popup", "a lesson button that opens a window"), ("#button", "a lesson button"),
("#anchor", "an in-page anchor"), ("#same", "a link with no target")]
def next_link(i=0):
if i == len(order):
# Back, as the right-click menu's Back does, then close every tab the links opened.
links_view.page().triggerAction(links_view.page().WebAction.Back)
def closed_all():
report("after Back")
for view in [window._tabs.widget(j) for j in range(window._tabs.count())]:
if view is not links_view:
window.close_tab(window._tabs.indexOf(view))
QTimer.singleShot(800, lambda: (report("after closing the opened tabs"),
stamp(f"TABS {tabs()}"), finish()))
return QTimer.singleShot(2000, closed_all)
selector, label = order[i]
back_to_links()
click_in(links_view, selector, lambda: (report(f"{selector} ({label})"),
stamp(f"BUTTON {links_view.page().title()!r}") if selector == "#button" else None,
QTimer.singleShot(1500 if selector == "#pdf" else 200, lambda: next_link(i + 1))))
when(on_links, lambda: go_links(lambda: (report("start"), next_link())), "signed in")
elif variant in ("pdf", "image", "image-rclick", "tabs-print"):
target = {"pdf": "#pdf", "image": "#blank", "image-rclick": "#blank", "tabs-print": "#blank"}[variant]
def opened():
report(f"{target} opened")
view = window.current()
if variant == "pdf":
QTimer.singleShot(2500, lambda: (QTimer.singleShot(0, lambda: window.print_view(window.current())),
when(ready, lambda: (keep_preview(), press_print()), "worksheet preview")))
elif variant == "image":
QTimer.singleShot(0, lambda: window.print_view(view))
when(lambda: ready() and preview()._picture is not None, lambda: (
stamp(f"PICTURE picture_box={preview()._picture_box.isVisible()} image={preview()._picture.width()}x{preview()._picture.height()}"),
keep_preview(), press_print()), "picture preview")
elif variant == "image-rclick":
def menu_up(menu):
items = [a.text() for a in menu.actions() if a.text()]
stamp(f"MENU {items}")
action = next(a for a in menu.actions() if a.text() == "Print image…")
menu.close()
when(lambda: ready() and preview()._picture is not None, lambda: (
stamp(f"PICTURE picture_box={preview()._picture_box.isVisible()} image={preview()._picture.width()}x{preview()._picture.height()}"),
keep_preview(), press_print()), "picture preview")
QTimer.singleShot(0, action.trigger)
click_in(view, "img", lambda: when(lambda: Application.activePopupWidget() is not None,
lambda: menu_up(Application.activePopupWidget()), "menu"),
button=Qt.MouseButton.RightButton)
else:
# Three links opened, two of them closed again, then the page they came from printed.
def more():
back_to_links()
click_in(links_view, "#external", lambda: (back_to_links(), click_in(links_view, "#linked-picture", close_two)))
def close_two():
for view in [window._tabs.widget(j) for j in range(window._tabs.count())][-2:]:
window.close_tab(window._tabs.indexOf(view))
back_to_links(); report("before printing")
QTimer.singleShot(0, lambda: window.print_view(links_view))
when(ready, lambda: (keep_preview(), press_print()), "page preview")
more()
when(on_links, lambda: go_links(lambda: (back_to_links(), click_in(links_view, target, lambda: QTimer.singleShot(1500, opened)))), "signed in")
elif scenario.startswith("rclick"):
# A lesson behind a sign-in, with pictures in it; a real right-click.
# rclick-page on the words: the page prints