The two books that failed are in Open Library after all
The user supplied the failing ISBNs: 9781883937386 (The Hittite Warrior) and 9781883937676 (Shadow Hawk), both Bethlehem Books. Both resolve against the source the app already queries — title, author, publisher, page count, cover art — and both real responses parse correctly through the app's own OpenLibraryClient. Captured as fixtures with a regression test, because these are the specific books that motivated the research. That kills the coverage hypothesis for these two and demotes Harvard, which holds neither: its 93% in the sample table is inflated by construction (the sample was drawn from Harvard) and misleading in exactly the direction that matters — it is a research library and does not carry small-press children's historical fiction. The failure is upstream of the metadata sources. Documented the three candidates; the leading one is that the barcode never decoded into a valid ISBN-13, which ScanCodeFilter drops silently with no UI feedback whatsoever. Revised the recommendation accordingly: make the app say what happened before adding any source. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CDcPottghJXEvfYKqFM7zf
This commit is contained in:
@@ -61,6 +61,38 @@ class OpenLibraryClientTest {
|
||||
assertEquals("https://covers.openlibrary.org/b/id/675832-M.jpg", result.coverUrl)
|
||||
}
|
||||
|
||||
/**
|
||||
* Two real books off the user's shelf that the app failed to identify on its
|
||||
* first on-device run, captured verbatim from the live API on 2026-09-09. Both
|
||||
* are small-press (Bethlehem Books) children's historical fiction — the exact
|
||||
* profile we assumed Open Library would be thin on. It isn't: both carry title,
|
||||
* author, publisher and cover art, and neither exposes an `isbn_13` identifier,
|
||||
* which is why the lookup ISBN has to survive as the fallback. Whatever went
|
||||
* wrong on the phone, it was NOT this parser and NOT Open Library's coverage.
|
||||
*/
|
||||
@Test
|
||||
fun `parses the real responses for the two books the app failed to identify`() {
|
||||
val hittite = checkNotNull(
|
||||
client.parseResponse(fixture("openlibrary_hittite_warrior.json"), "9781883937386"),
|
||||
)
|
||||
assertEquals("Hittite warrior", hittite.title)
|
||||
assertEquals(listOf("Joanne S. Williamson"), hittite.authors)
|
||||
assertEquals("Bethlehem Books", hittite.publisher)
|
||||
assertEquals(237, hittite.pageCount)
|
||||
assertEquals("1883937388", hittite.isbn10)
|
||||
// No isbn_13 in the record — the ISBN we looked up has to carry through.
|
||||
assertEquals("9781883937386", hittite.isbn13)
|
||||
assertEquals("https://covers.openlibrary.org/b/id/930599-L.jpg", hittite.coverUrl)
|
||||
|
||||
val shadowHawk = checkNotNull(
|
||||
client.parseResponse(fixture("openlibrary_shadow_hawk.json"), "9781883937676"),
|
||||
)
|
||||
assertEquals("Shadow hawk", shadowHawk.title)
|
||||
assertEquals(listOf("Andre Norton"), shadowHawk.authors)
|
||||
assertEquals("9781883937676", shadowHawk.isbn13)
|
||||
checkNotNull(shadowHawk.coverUrl)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns null when the isbn key is absent from the response`() {
|
||||
val body = fixture("openlibrary_not_found.json")
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"ISBN:9781883937386": {"url": "http://openlibrary.org/books/OL395004M/Hittite_warrior", "key": "/books/OL395004M", "title": "Hittite warrior", "authors": [{"url": "http://openlibrary.org/authors/OL244960A/Joanne_S._Williamson", "name": "Joanne S. Williamson"}], "number_of_pages": 237, "pagination": "xvii, 237 p. ;", "by_statement": "Joanne Williamson.", "identifiers": {"goodreads": ["613497"], "librarything": ["33463"], "isbn_10": ["1883937388"], "lccn": ["98073485"], "openlibrary": ["OL395004M"]}, "classifications": {"lc_classifications": ["PZ7.W672 Hi 1999"], "dewey_decimal_class": ["[Fic]"]}, "publishers": [{"name": "Bethlehem Books"}], "publish_places": [{"name": "Warsaw, ND"}], "publish_date": "1999", "subjects": [{"name": "Bible", "url": "https://openlibrary.org/subjects/bible"}, {"name": "Canaanites", "url": "https://openlibrary.org/subjects/canaanites"}, {"name": "Fiction", "url": "https://openlibrary.org/subjects/fiction"}, {"name": "History", "url": "https://openlibrary.org/subjects/history"}, {"name": "History of Biblical events", "url": "https://openlibrary.org/subjects/history_of_biblical_events"}, {"name": "Jews", "url": "https://openlibrary.org/subjects/jews"}, {"name": "Juvenile fiction", "url": "https://openlibrary.org/subjects/juvenile_fiction"}, {"name": "Hittites", "url": "https://openlibrary.org/subjects/hittites"}, {"name": "Middle east, history", "url": "https://openlibrary.org/subjects/middle_east,_history"}, {"name": "Juvenile Fiction", "url": "https://openlibrary.org/subjects/juvenile_fiction"}], "subject_places": [{"name": "Palestine", "url": "https://openlibrary.org/subjects/place:palestine"}], "subject_people": [{"name": "Barak (Biblical figure)", "url": "https://openlibrary.org/subjects/person:barak_(biblical_figure)"}, {"name": "Deborah (Biblical judge)", "url": "https://openlibrary.org/subjects/person:deborah_(biblical_judge)"}, {"name": "Sisera (Biblical figure)", "url": "https://openlibrary.org/subjects/person:sisera_(biblical_figure)"}], "subject_times": [{"name": "To 70 A.D.", "url": "https://openlibrary.org/subjects/time:to_70_a.d."}], "notes": "\"Ages 10-up\"--P. 4 of cover.", "ebooks": [{"preview_url": "https://archive.org/details/hittitewarrior00will", "availability": "borrow", "formats": {}, "borrow_url": "https://openlibrary.org/books/OL395004M/Hittite_warrior/borrow", "checkedout": true}], "cover": {"small": "https://covers.openlibrary.org/b/id/930599-S.jpg", "medium": "https://covers.openlibrary.org/b/id/930599-M.jpg", "large": "https://covers.openlibrary.org/b/id/930599-L.jpg"}}}
|
||||
@@ -0,0 +1 @@
|
||||
{"ISBN:9781883937676": {"url": "http://openlibrary.org/books/OL3958151M/Shadow_hawk", "key": "/books/OL3958151M", "title": "Shadow hawk", "authors": [{"url": "http://openlibrary.org/authors/OL27951A/Andre_Norton", "name": "Andre Norton"}], "number_of_pages": 246, "pagination": "246 p. ;", "by_statement": "Andre Norton.", "identifiers": {"librarything": ["34114"], "goodreads": ["83108"], "isbn_10": ["1883937671"], "lccn": ["2001092576"], "oclc": ["52047589"], "openlibrary": ["OL3958151M"]}, "classifications": {"lc_classifications": ["PZ7.N82 Sh 2001"], "dewey_decimal_class": ["[Fic]"]}, "publishers": [{"name": "Bethlehem Books"}, {"name": "Ignatius Press"}], "publish_places": [{"name": "Bathgate, N.D"}, {"name": "San Francisco"}], "publish_date": "2001", "subjects": [{"name": "History", "url": "https://openlibrary.org/subjects/history"}, {"name": "Juvenile fiction", "url": "https://openlibrary.org/subjects/juvenile_fiction"}, {"name": "Egypt in fiction", "url": "https://openlibrary.org/subjects/egypt_in_fiction"}, {"name": "Fiction", "url": "https://openlibrary.org/subjects/fiction"}, {"name": "Children's stories", "url": "https://openlibrary.org/subjects/children's_stories"}, {"name": "Egypt -- History -- To 332 B.C. -- Juvenile fiction.", "url": "https://openlibrary.org/subjects/egypt_--_history_--_to_332_b.c._--_juvenile_fiction."}, {"name": "Fiction, science fiction, general", "url": "https://openlibrary.org/subjects/fiction,_science_fiction,_general"}], "subject_places": [{"name": "Egypt", "url": "https://openlibrary.org/subjects/place:egypt"}], "subject_times": [{"name": "To 332 B.C.", "url": "https://openlibrary.org/subjects/time:to_332_b.c."}], "ebooks": [{"preview_url": "https://archive.org/details/shadowhawk0000nort", "availability": "borrow", "formats": {}, "borrow_url": "https://openlibrary.org/books/OL3958151M/Shadow_hawk/borrow", "checkedout": false}], "cover": {"small": "https://covers.openlibrary.org/b/id/930617-S.jpg", "medium": "https://covers.openlibrary.org/b/id/930617-M.jpg", "large": "https://covers.openlibrary.org/b/id/930617-L.jpg"}}}
|
||||
Reference in New Issue
Block a user