from bindery.store import Store def test_chapters_revisions_and_rules(tmp_path): store = Store(tmp_path / "db.sqlite") sid = store.create_story("https://example/s/1", "example", "T", "A", ["title"]) c1 = store.add_chapter(sid, "u1", "One", "

1

", "h1", "new", 0) c2 = store.add_chapter(sid, "u2", "Two", "

2

", "h2", "new", 1) 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, "

1b

", "h1b", "recheck") == 2 newest = store.list_revisions(c1)[-1] assert (newest["rev"], newest["text_hash"], newest["source"]) == (2, "h1b", "recheck") assert store.get_chapter(c1)["current_rev"] == 2 store.replace_revision(c1, 2, "

1c

", "h1c") assert store.list_revisions(c1)[-1]["text_hash"] == "h1c" assert store.revision_html(c1, 1) == "

1

" store.update_chapter(c1, current_rev=1, included=0) assert [c["url"] for c in store.chapters_for_build(sid)] == ["u2"] store.set_rules(None, [{"pattern": "g"}]) store.set_rules(sid, [{"pattern": "s", "flags": "i"}]) assert [r["pattern"] for r in store.rules(None)] == ["g"] assert store.rules(sid)[0]["flags"] == "i" story = store.get_story(sid) assert story["locked_fields"] == ["title"] and story["pinned"] == {} store.update_story(sid, pinned={"title": "Kept"}) assert store.get_story_by_url("https://example/s/1")["pinned"] == {"title": "Kept"} store.delete_story(sid) assert store.get_chapter(c1) is None assert store.rules(sid) == [] assert store.rules(None) != [] def test_list_stories_counts_offsite_and_revised_chapters(tmp_path): store = Store(tmp_path / "db.sqlite") sid = store.create_story("https://example/s/1", "example", "T", "A", []) c1 = store.add_chapter(sid, "u1", "One", "

1

", "h1", "new", 0) c2 = store.add_chapter(sid, "u2", "Two", "

2

", "h2", "new", 1) store.add_chapter(sid, "u3", "Three", "

3

", "h3", "new", 2) store.update_chapter(c1, on_site=0) store.add_revision(c2, "

2b

", "h2b", "recheck") story = store.list_stories()[0] assert story["offsite_count"] == 1 assert story["revised_count"] == 1 def test_list_stories_sorts_titles_without_leading_articles(tmp_path): store = Store(tmp_path / "db.sqlite") for n, title in enumerate(["The Zebra", "an Owl", "Anthem", "A Bee", "Theory", "Cat"]): store.create_story(f"https://example/s/{n}", "example", title, "A", []) titles = [s["title"] for s in store.list_stories()] assert titles == ["Anthem", "A Bee", "Cat", "an Owl", "Theory", "The Zebra"] # The web interface sorts by the same key. assert [s["sort_title"] for s in store.list_stories()] == ["anthem", "bee", "cat", "owl", "theory", "zebra"] def test_cover_replaces_previous_cover(tmp_path): store = Store(tmp_path / "db.sqlite") sid = store.create_story("u", "s", "T", "A", []) store.put_image(sid, "c1", "jpg", "image/jpeg", b"1", is_cover=True) store.put_image(sid, "c2", "jpg", "image/jpeg", b"2", is_cover=True) store.put_image(sid, "i1", "png", "image/png", b"3") assert store.cover(sid)["url"] == "c2" assert [i["url"] for i in store.images(sid)] == ["i1"] def test_add_chapters_places_them_in_one_step(tmp_path): store = Store(tmp_path / "db.sqlite") sid = store.create_story("u", "s", "T", "A", []) store.add_chapter(sid, "u1", "One", "

1

", "h1", "new", 0) store.add_chapter(sid, "u3", "Three", "

3

", "h3", "new", 1) store.add_chapter(sid, "u9", "Nine", "

9

", "h9", "new", 2) new = [{"url": u, "title": u, "html": "

", "text_hash": "h"} for u in ("u2", "u4")] ids = store.add_chapters(sid, new, "import", ["u1", "u2", "u3", "u4"]) chapters = store.list_chapters(sid) assert [c["url"] for c in chapters] == ["u1", "u2", "u3", "u4", "u9"] assert [c["position"] for c in chapters] == [0, 1, 2, 3, 4] assert [c["id"] for c in chapters if c["url"] in ("u2", "u4")] == ids def test_settings(tmp_path): store = Store(tmp_path / "db.sqlite") sid = store.create_story("u", "s", "T", "A", []) assert store.get_setting(None, "paragraphs") is None store.set_setting(None, "paragraphs", True) store.set_setting(sid, "paragraphs", False) assert (store.get_setting(None, "paragraphs"), store.get_setting(sid, "paragraphs")) == (True, False) store.set_setting(sid, "paragraphs", None) assert store.get_setting(sid, "paragraphs") is None store.set_setting(sid, "paragraphs", True) store.delete_story(sid) assert store.get_setting(sid, "paragraphs") is None