Keep a move or a delete of chapters that the user makes during a job

A job placed each new chapter with the chapter order from its start, so
a move by hand during the job went back. The store now places a new
chapter against the order that the story has at that moment, in one
transaction. A recheck of a chapter that the user deleted no longer
stops the job.
This commit is contained in:
tim
2026-10-02 23:37:33 +02:00
parent 81efc03b75
commit ff2fa0bf90
4 changed files with 144 additions and 22 deletions
+92
View File
@@ -0,0 +1,92 @@
"""Changes that the user makes to the chapters of a story while a job runs for it."""
import pytest
from test_deliver import CHAPTER, linked_story, site, titles, update
from test_deliver import fake as fake
from test_deliver import jobs as jobs
from test_deliver import story_epub as story_epub
from bindery import fff, orchestrator
from bindery.jobs import DownloadMode
from bindery.store import Store
THREE = [(1, "One", "a"), (2, "Two", "b"), (3, "Three", "c")]
def during_download(monkeypatch, number, action):
"""Run `action` when the job downloads the chapter with this number."""
fetch = fff.fetch_chapter
def fetch_and_act(adapter, url, index):
if url == CHAPTER.format(number):
action()
return fetch(adapter, url, index)
monkeypatch.setattr(fff, "fetch_chapter", fetch_and_act)
def chapter_id(story_id, title):
return next(c["id"] for c in orchestrator.store.list_chapters(story_id) if c["title"] == title)
def test_a_move_during_a_download_stays(fake, jobs, monkeypatch):
story_id = linked_story(THREE)
site(monkeypatch, [*THREE, (4, "Four", "d"), (5, "Five", "e")])
during_download(monkeypatch, 4, lambda: orchestrator.move_chapters(story_id, [chapter_id(story_id, "Three")], None))
assert "2 new chapters" in update(story_id)
assert titles(story_id) == ["Three", "One", "Two", "Four", "Five"]
def test_a_new_chapter_in_the_middle_goes_after_its_moved_predecessor(fake, jobs, monkeypatch):
story_id = linked_story(THREE)
site(monkeypatch, [(1, "One", "a"), (9, "Nine", "x"), (2, "Two", "b"), (3, "Three", "c")])
during_download(
monkeypatch,
9,
lambda: orchestrator.move_chapters(story_id, [chapter_id(story_id, "One")], chapter_id(story_id, "Three")),
)
update(story_id)
assert titles(story_id) == ["Two", "Three", "One", "Nine"]
def test_a_delete_during_a_download_stays(fake, jobs, monkeypatch):
story_id = linked_story(THREE)
site(monkeypatch, [*THREE, (4, "Four", "d")])
during_download(monkeypatch, 4, lambda: orchestrator.delete_chapters(story_id, [chapter_id(story_id, "Two")]))
assert "1 new chapter" in update(story_id)
assert titles(story_id) == ["One", "Three", "Four"]
def test_a_delete_during_a_recheck_does_not_stop_the_job(fake, jobs, monkeypatch):
story_id = linked_story(THREE)
site(monkeypatch, [(1, "One", "a2"), (2, "Two", "b2"), (3, "Three", "c2")])
during_download(monkeypatch, 2, lambda: orchestrator.delete_chapters(story_id, [chapter_id(story_id, "Two")]))
assert "2 of 3 rechecked chapters changed" in update(story_id, DownloadMode.RECHECK_ALL)
assert titles(story_id) == ["One", "Three"]
def test_the_order_function_of_add_chapters_sees_the_stored_order(tmp_path):
store = Store(tmp_path / "db.sqlite")
sid = store.create_story("u", "s", "T", "A", [])
for n, url in enumerate(["u2", "u1"]):
store.add_chapter(sid, url, url, "<p/>", "h", "new", n)
new = [{"url": "u3", "title": "u3", "html": "<p/>", "text_hash": "h"}]
seen = []
store.add_chapters(sid, new, "new", lambda stored: seen.append(stored) or [*stored, "u3"])
assert seen == [["u2", "u1"]]
assert [c["url"] for c in store.list_chapters(sid)] == ["u2", "u1", "u3"]
def test_a_refused_reorder_changes_nothing(tmp_path):
store = Store(tmp_path / "db.sqlite")
sid = store.create_story("u", "s", "T", "A", [])
ids = [store.add_chapter(sid, f"u{n}", str(n), "<p/>", "h", "new", n) for n in range(3)]
def refuse(order):
raise ValueError("no")
with pytest.raises(ValueError, match="no"):
store.reorder_chapters(sid, refuse)
assert [c["id"] for c in store.list_chapters(sid)] == ids
store.reorder_chapters(sid, lambda order: order[::-1])
assert [c["id"] for c in store.list_chapters(sid)] == ids[::-1]
+1 -1
View File
@@ -6,7 +6,7 @@ def test_chapters_revisions_and_rules(tmp_path):
sid = store.create_story("https://example/s/1", "example", "T", "A", ["title"])
c1 = store.add_chapter(sid, "u1", "One", "<p>1</p>", "h1", "new", 0)
c2 = store.add_chapter(sid, "u2", "Two", "<p>2</p>", "h2", "new", 1)
store.set_positions(sid, [c2, c1])
store.reorder_chapters(sid, lambda order: [c2, c1])
assert [c["url"] for c in store.chapters_for_build(sid)] == ["u2", "u1"]
assert store.add_revision(c1, "<p>1b</p>", "h1b", "recheck") == 2