A host from the web site; the same page kept once; deleting from the Notebooks chooser
From the development repository at 299f73d, 2026-10-11: hosting from the site documented; a page loaded from a notebook and left unchanged is not kept again; notebooks and pages are deleted from the chooser, to the system's Trash (--trash); the Notebooks button. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
4e3a281d65
commit
0d01e23d7c
15 files changed
+711
-63
No files matched your search
@@ -521,6 +521,8 @@ class EndToEndTest(unittest.TestCase):
|
||||
cls.processes = []
|
||||
cls.directory = tempfile.TemporaryDirectory()
|
||||
cls.notebooks = pathlib.Path(cls.directory.name) / "notebooks"
|
||||
# Deleted notebooks and pages go here, not to the real Trash.
|
||||
cls.trash = pathlib.Path(cls.directory.name) / "trash"
|
||||
relay_port, driver_port = free_port(), free_port()
|
||||
cls.start([sys.executable, str(PROJECT / "relay" / "kokkoja_relay.py"),
|
||||
"--port", str(relay_port)])
|
||||
@@ -552,7 +554,8 @@ class EndToEndTest(unittest.TestCase):
|
||||
site_option = ["--site", cls.site] if name == "Host" else []
|
||||
cls.start([sys.executable, str(PROJECT / "kokkoja.py"), "--no-browser",
|
||||
"--port", str(port), "--relay", f"ws://127.0.0.1:{relay_port}",
|
||||
"--notebooks", str(cls.notebooks), "--config", str(config), *site_option])
|
||||
"--notebooks", str(cls.notebooks), "--config", str(config),
|
||||
"--trash", str(cls.trash), *site_option])
|
||||
cls.programs[name] = (f"http://{host}:{port}/", config)
|
||||
cls.start(["geckodriver", "--port", str(driver_port)])
|
||||
try:
|
||||
@@ -824,6 +827,21 @@ class EndToEndTest(unittest.TestCase):
|
||||
lambda v: v.startswith("Already kept"), "the second keep to be reported")
|
||||
time.sleep(1)
|
||||
self.assertEqual(sorted(p.name for p in self.downloads.iterdir()), [f"{today}_01.svg"])
|
||||
# The browser has no trash: a deleted page is gone, and the
|
||||
# notebook with it when it is deleted whole.
|
||||
self.assertEqual(firefox.run_until_done("""
|
||||
const [name, done] = arguments;
|
||||
(async () => {
|
||||
const m = window.kokkoja.notebook;
|
||||
const listed = await m.listNotebooks();
|
||||
await m.discardPage('Guest notebook', name);
|
||||
const after = await m.listKeptPages('Guest notebook');
|
||||
await m.discardNotebook('Guest notebook');
|
||||
done({trash: listed.trash, after,
|
||||
notebooks: (await m.listNotebooks()).notebooks,
|
||||
current: await m.readCurrentPage('Guest notebook')});
|
||||
})().catch((e) => done({error: String(e)}));
|
||||
""", f"{today}_01.svg"), {"trash": False, "after": [], "notebooks": [], "current": None})
|
||||
|
||||
# Exporting downloads a picture.
|
||||
firefox.run("document.getElementById('export_page').click();")
|
||||
@@ -2072,11 +2090,11 @@ class EndToEndTest(unittest.TestCase):
|
||||
# is the student's again.
|
||||
firefox.run("document.getElementById('load_notebook_page').click();")
|
||||
notebooks = self.wait_until_true(lambda: firefox.run("""
|
||||
return [...document.querySelectorAll('#chooser_notebooks button')].map((b) => b.textContent);
|
||||
return [...document.querySelectorAll('#chooser_notebooks button.notebook_pick')].map((b) => b.textContent);
|
||||
"""), lambda names: "Teacher notebook" in names, "the chooser to list the notebooks")
|
||||
self.assertEqual(notebooks, sorted(notebooks))
|
||||
firefox.run("""
|
||||
[...document.querySelectorAll('#chooser_notebooks button')]
|
||||
[...document.querySelectorAll('#chooser_notebooks button.notebook_pick')]
|
||||
.find((b) => b.textContent === 'Teacher notebook').click();
|
||||
""")
|
||||
cards = self.wait_until_true(lambda: firefox.run("""
|
||||
@@ -2140,6 +2158,80 @@ class EndToEndTest(unittest.TestCase):
|
||||
"""), lambda n: n >= count, "the chooser to list the kept pages again")
|
||||
self.assertEqual(loaded["images"], stacked["images"])
|
||||
self.assertEqual(loaded["page"]["height"], 3608)
|
||||
# Each page loaded on the way was left unchanged, so none was kept
|
||||
# again (the file names a page anew at every load; the contents
|
||||
# are compared without the names).
|
||||
self.wait_until_true(
|
||||
lambda: (self.notebooks / "Teacher notebook" / "Current.svg").read_text(),
|
||||
lambda text: f'data-number="{loaded["page"]["number"]}"' in text, "the loaded page to be written")
|
||||
self.assertEqual(len(self.kept_pages("Teacher notebook")), count)
|
||||
|
||||
# Deleting from the chooser: a mark on each page and notebook, one
|
||||
# Delete button that asks for a second press, the entries moved
|
||||
# to the Trash. The notebook being written in cannot be
|
||||
# marked; another notebook goes with everything in it.
|
||||
firefox.run("document.getElementById('load_notebook_page').click();")
|
||||
self.wait_until_true(lambda: firefox.run("""
|
||||
return document.querySelectorAll('#chooser_pages .page_slot button.mark').length;
|
||||
"""), lambda n: n == count, "the chooser to list the kept pages with marks")
|
||||
self.assertTrue(firefox.run("return document.getElementById('chooser_delete').hidden;"))
|
||||
before = self.kept_pages("Teacher notebook")
|
||||
firefox.run("""
|
||||
const marks = document.querySelectorAll('#chooser_pages .page_slot button.mark');
|
||||
marks[0].click(); marks[1].click(); marks[2].click(); marks[2].click();
|
||||
""")
|
||||
delete = lambda: firefox.run("""
|
||||
const b = document.getElementById('chooser_delete');
|
||||
return b.hidden ? null : b.textContent;
|
||||
""")
|
||||
self.assertEqual(delete(), "Delete 2 pages?")
|
||||
self.assertEqual(firefox.run("""
|
||||
return [...document.querySelectorAll('#chooser_pages .page_slot')].map((s) => s.classList.contains('marked'));
|
||||
""")[:3], [True, True, False])
|
||||
firefox.run("document.getElementById('chooser_delete').click();")
|
||||
self.assertEqual(delete(), "Press again to move 2 pages to the Trash")
|
||||
# Marking something else takes the first press back.
|
||||
firefox.run("document.querySelectorAll('#chooser_pages .page_slot button.mark')[2].click();")
|
||||
self.assertEqual(delete(), "Delete 3 pages?")
|
||||
firefox.run("document.getElementById('chooser_delete').click();")
|
||||
firefox.run("document.getElementById('chooser_delete').click();")
|
||||
self.wait_until_true(lambda: firefox.run("return document.getElementById('chooser_message').textContent;"),
|
||||
lambda text: text == "3 pages moved to the Trash.", "the deletion to be reported")
|
||||
self.assertEqual(self.kept_pages("Teacher notebook"), before[3:])
|
||||
self.assertEqual(sorted(p.name for p in self.trash.iterdir()), before[:3])
|
||||
self.assertEqual(firefox.run("return document.querySelectorAll('#chooser_pages .page_slot').length;"),
|
||||
count - 3)
|
||||
self.assertIsNone(delete())
|
||||
# The notebook being written in: its mark explains instead.
|
||||
firefox.run("""
|
||||
[...document.querySelectorAll('#chooser_notebooks .notebook_row')]
|
||||
.find((r) => r.querySelector('.notebook_pick').textContent === 'Teacher notebook')
|
||||
.querySelector('button.mark').click();
|
||||
""")
|
||||
self.assertIn("writing in this notebook", firefox.run("return document.getElementById('chooser_message').textContent;"))
|
||||
self.assertIsNone(delete())
|
||||
# Another notebook, with its pages, goes as one; the toolbar's list loses it.
|
||||
self.assertTrue((self.notebooks / "Other notebook" / "Current.svg").exists())
|
||||
firefox.run("""
|
||||
[...document.querySelectorAll('#chooser_notebooks .notebook_row')]
|
||||
.find((r) => r.querySelector('.notebook_pick').textContent === 'Other notebook')
|
||||
.querySelector('button.mark').click();
|
||||
""")
|
||||
self.assertEqual(delete(), "Delete 1 notebook?")
|
||||
firefox.run("document.getElementById('chooser_delete').click();")
|
||||
self.assertEqual(delete(), "Press again to move 1 notebook to the Trash")
|
||||
firefox.run("document.getElementById('chooser_delete').click();")
|
||||
self.wait_until_true(lambda: firefox.run("return document.getElementById('chooser_message').textContent;"),
|
||||
lambda text: text == "1 notebook moved to the Trash.", "the notebook's deletion to be reported")
|
||||
self.assertFalse((self.notebooks / "Other notebook").exists())
|
||||
self.assertTrue((self.trash / "Other notebook" / "Current.svg").exists())
|
||||
self.assertNotIn("Other notebook", firefox.run("""
|
||||
return [...document.querySelectorAll('#chooser_notebooks button.notebook_pick')].map((b) => b.textContent);
|
||||
"""))
|
||||
self.wait_until_true(lambda: firefox.run("""
|
||||
return [...document.getElementById('session_notebook').options].map((o) => o.textContent);
|
||||
"""), lambda names: "Other notebook" not in names, "the toolbar's list to lose the notebook")
|
||||
firefox.run("document.getElementById('chooser_close').click();")
|
||||
# A page that its images have made longer than a sheet is first
|
||||
# shown at the scale at which one sheet fits the window.
|
||||
self.assertEqual(firefox.run(VIEW), long_view)
|
||||
|
||||
Reference in new issue
Block a user