test_douban.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #!/usr/bin/env python3
  2. import json
  3. import logging
  4. import os
  5. import sys
  6. import unittest
  7. from unittest import mock
  8. testdir = os.path.realpath(os.path.dirname(os.path.realpath(__file__)) + "/../../../")
  9. sys.path.append(testdir)
  10. import webserver.main
  11. from webserver.plugins.meta.douban import CHROME_HEADERS, DoubanBookApi
  12. webserver.main.init_calibre()
  13. DOUBAN_BOOK = {
  14. "id": "35737227",
  15. "author": ["[美]马修·卡拉柯"],
  16. "author_intro": "本书首次出版于2008年,是作者的第一本专著。在这本书中,马修·卡拉柯引用了动物行为学、进化论以及海德格尔的研究,",
  17. "translators": ["庞红蕊"],
  18. "images": {
  19. "small": "https://img9.doubanio.com/view/subject/s/public/s34101604.jpg",
  20. "medium": "https://img9.doubanio.com/view/subject/l/public/s34101604.jpg",
  21. "large": "https://img9.doubanio.com/view/subject/l/public/s34101604.jpg",
  22. },
  23. "binding": "平装",
  24. "category": "",
  25. "rating": {"average": 7.0},
  26. "isbn13": "9787570220601",
  27. "pages": "217",
  28. "price": "48.00元",
  29. "pubdate": "2022-1",
  30. "publisher": "长江文艺出版社",
  31. "producer": "",
  32. "serials": "",
  33. "subtitle": "从海德格尔到德里达的动物问题",
  34. "summary": "“要在观念和实际生活中公正地对待动物,这于人类而言是一个巨大的转变",
  35. "title": "动物志",
  36. "tags": [
  37. {"name": "动物"},
  38. {"name": "哲学"},
  39. {"name": "海德格尔"},
  40. {"name": "阿甘本"},
  41. {"name": "观念史"},
  42. {"name": "文学理论"},
  43. {"name": "政治哲学"},
  44. {"name": "德里达"},
  45. ],
  46. "origin": "Zoographies",
  47. }
  48. DOUBAN_SEARCH = {
  49. "code": 0,
  50. "msg": "",
  51. "books": [
  52. {
  53. "id": "35674151",
  54. "author": ["[英] 詹姆斯·切希尔", "谭羚迪"],
  55. "author_intro": "",
  56. "translators": [],
  57. "images": {
  58. "small": "",
  59. "medium": "",
  60. "large": "https://img3.doubanio.com/view/subject/s/public/s34050330.jpg",
  61. },
  62. "binding": "",
  63. "category": "",
  64. "rating": {"average": 9.2},
  65. "isbn13": "",
  66. "pages": "",
  67. "price": "",
  68. "pubdate": "2021",
  69. "publisher": "后浪丨湖南美术出版社",
  70. "producer": "",
  71. "serials": "",
  72. "subtitle": "",
  73. "summary": "◎获奖记录\n☆ 2017年英国地图制图学会综合大奖\n☆ 约翰·巴塞洛缪专题地图奖\n◎编辑推荐",
  74. "title": "动物去哪里",
  75. "tags": [],
  76. "origin": "",
  77. },
  78. {
  79. "id": "26889178",
  80. "author": ["乙一", "张筱森"],
  81. "author_intro": "",
  82. "translators": [],
  83. "images": {
  84. "small": "",
  85. "medium": "",
  86. "large": "https://img9.doubanio.com/view/subject/s/public/s33653515.jpg",
  87. },
  88. "binding": "",
  89. "category": "",
  90. "rating": {"average": 8.6},
  91. "isbn13": "",
  92. "pages": "",
  93. "price": "",
  94. "pubdate": "2016",
  95. "publisher": "人民文学出版社",
  96. "producer": "",
  97. "serials": "",
  98. "subtitle": "",
  99. "summary": "",
  100. "title": "动物园",
  101. "tags": [],
  102. "origin": "",
  103. },
  104. {
  105. "id": "34897038",
  106. "author": ["[英] 米莉·玛洛塔", "孙依静"],
  107. "author_intro": "",
  108. "translators": [],
  109. "images": {
  110. "small": "",
  111. "medium": "",
  112. "large": "https://img2.doubanio.com/view/subject/s/public/s33525533.jpg",
  113. },
  114. "binding": "",
  115. "category": "",
  116. "rating": {"average": 9.1},
  117. "isbn13": "",
  118. "pages": "",
  119. "price": "",
  120. "pubdate": "2020",
  121. "publisher": "后浪丨四川美术出版社",
  122. "producer": "",
  123. "serials": "",
  124. "subtitle": "",
  125. "summary": "芳踪难觅的栗腹鹭,钟爱旅行的勺嘴鹬\n感情专一的虎尾海马,雌雄难辨的曲纹唇鱼",
  126. "title": "地球上最孤单的动物",
  127. "tags": [],
  128. "origin": "",
  129. },
  130. {
  131. "id": "26579268",
  132. "author": ["[法] 纪尧姆·杜帕", "梅茇仁"],
  133. "author_intro": "",
  134. "translators": [],
  135. "images": {
  136. "small": "",
  137. "medium": "",
  138. "large": "https://img1.doubanio.com/view/subject/s/public/s29432778.jpg",
  139. },
  140. "binding": "",
  141. "category": "",
  142. "rating": {"average": 9.3},
  143. "isbn13": "",
  144. "pages": "",
  145. "price": "",
  146. "pubdate": "2015",
  147. "publisher": "明天出版社",
  148. "producer": "",
  149. "serials": "",
  150. "subtitle": "",
  151. "summary": "动物到底是如何看东西的,这一点仍然是个谜。猫的眼睛会看到怎样的东西?公牛真的害怕红色的吗?",
  152. "title": "动物眼中的世界",
  153. "tags": [],
  154. "origin": "",
  155. },
  156. {
  157. "id": "2035179",
  158. "author": ["[英] 乔治·奥威尔", "荣如德"],
  159. "author_intro": "",
  160. "translators": [],
  161. "images": {
  162. "small": "",
  163. "medium": "",
  164. "large": "https://img3.doubanio.com/view/subject/s/public/s2347590.jpg",
  165. },
  166. "binding": "",
  167. "category": "",
  168. "rating": {"average": 9.3},
  169. "isbn13": "",
  170. "pages": "",
  171. "price": "",
  172. "pubdate": "2007",
  173. "publisher": "上海译文出版社",
  174. "producer": "",
  175. "serials": "",
  176. "subtitle": "",
  177. "summary": "《动物农场》是奥威尔最优秀的作品之一,是一则入木三分的反乌托的政治讽喻寓言。",
  178. "title": "动物农场",
  179. "tags": [],
  180. "origin": "",
  181. },
  182. ],
  183. }
  184. class TestDoubanApi(unittest.TestCase):
  185. @mock.patch("requests.get")
  186. def test_metadata(self, mk):
  187. api = DoubanBookApi("apikey", "baseurl")
  188. book = dict(DOUBAN_BOOK)
  189. image = unittest.TestResult()
  190. image.content = b"image-body"
  191. mk.return_value = image
  192. mi = api._metadata(book)
  193. self.assertEqual(mi.title, book["title"])
  194. self.assertEqual(mi.authors, ["马修·卡拉柯"])
  195. self.assertEqual(mi.author, "马修·卡拉柯")
  196. self.assertEqual(mi.cover_data, ("jpg", b"image-body"))
  197. self.assertEqual(mi.rating, 7)
  198. self.assertEqual(mi.pubdate.strftime("%Y-%m-%d"), "2022-01-01")
  199. book["author"] = []
  200. mi = api._metadata(book)
  201. self.assertEqual(mi.authors, ["佚名"])
  202. self.assertEqual(mi.author, "佚名")
  203. @mock.patch("requests.get")
  204. def test_isbn_and_id(self, mk):
  205. testcases = [
  206. {"result": None, "case": {}, "err": RuntimeError("Yo!")},
  207. {"result": None, "case": {"status_code": 404, "content": ""}},
  208. {"result": None, "case": {"status_code": 200, "content": "bad_json"}},
  209. {"result": dict(DOUBAN_BOOK), "case": {"status_code": 200, "content": json.dumps(DOUBAN_BOOK)}},
  210. ]
  211. api = DoubanBookApi("key", "baseurl")
  212. for case in testcases:
  213. mk.side_effect = case.get("err", None)
  214. fake = mk.return_value
  215. for k, v in case["case"].items():
  216. setattr(fake, k, v)
  217. fake.json = lambda: json.loads(case["case"]["content"])
  218. d = api.get_book_by_isbn("123")
  219. self.assertEqual(d, case["result"])
  220. mk.assert_called_with("baseurl/v2/book/isbn/123", headers=CHROME_HEADERS, params={"apikey": "key"})
  221. d = api.get_book_by_id("456")
  222. self.assertEqual(d, case["result"])
  223. mk.assert_called_with("baseurl/v2/book/id/456", headers=CHROME_HEADERS, params={"apikey": "key"})
  224. @mock.patch("requests.get")
  225. def test_search_books(self, mk):
  226. api = DoubanBookApi("key", "baseurl")
  227. fake = mk.return_value
  228. fake.status_code = 200
  229. fake.json.return_value = dict(DOUBAN_SEARCH)
  230. title = "动物"
  231. d = api.search_books(title)
  232. self.assertEqual(d, DOUBAN_SEARCH["books"])
  233. mk.assert_called_with(
  234. "baseurl/v2/book/search",
  235. headers=CHROME_HEADERS,
  236. params={"q": title.encode("UTF-8"), "count": 2, "apikey": "key"},
  237. )
  238. @mock.patch("requests.get")
  239. def test_get_book_by_title(self, mk):
  240. r2 = mock.Mock()
  241. r2.status_code = 200
  242. r2.json.return_value = dict(DOUBAN_SEARCH)
  243. mk.return_value = r2
  244. api = DoubanBookApi("key", "baseurl")
  245. title = "动物园"
  246. author = None
  247. book = api.get_book_by_title(title, author)
  248. self.assertEqual(book["title"], "动物园")
  249. self.assertEqual(book["id"], "26889178")
  250. @mock.patch("requests.get")
  251. def test_get_book(self, mk):
  252. mk.return_value.status_code = 200
  253. mk.return_value.json.return_value = dict(DOUBAN_BOOK)
  254. api = DoubanBookApi("key", "baseurl", copy_image=False)
  255. q = mock.Mock()
  256. q.douban_id = 123
  257. book = api.get_book(q)
  258. self.assertEqual(book.title, DOUBAN_BOOK["title"])
  259. q = mock.Mock()
  260. q.isbn = 123
  261. book = api.get_book(q)
  262. self.assertEqual(book.title, DOUBAN_BOOK["title"])
  263. @mock.patch("requests.get")
  264. def test_get_book2(self, mk):
  265. r1 = mock.Mock()
  266. r1.status_code = 404
  267. r2 = mock.Mock()
  268. r2.status_code = 200
  269. r2.json.return_value = dict(DOUBAN_SEARCH)
  270. mk.side_effect = [r1, r2]
  271. api = DoubanBookApi("key", "baseurl", copy_image=False)
  272. q = mock.Mock()
  273. q.douban_id = 123
  274. q.isbn = 123
  275. q.title = "动物园"
  276. q.author_sort = None
  277. book = api.get_book(q)
  278. self.assertEqual(book.title, "动物园")
  279. self.assertEqual(book.provider_value, "26889178")
  280. if __name__ == "__main__":
  281. logging.basicConfig(
  282. level=logging.DEBUG,
  283. format="%(levelname)5s %(pathname)s:%(lineno)d %(message)s",
  284. )
  285. unittest.main()