test_download_integration.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. #!/usr/bin/env python3
  2. # coding=utf-8
  3. import shutil
  4. from pathlib import Path
  5. import pytest
  6. from click.testing import CliRunner
  7. from bdfr.__main__ import cli
  8. does_test_config_exist = Path('./tests/test_config.cfg').exists()
  9. def copy_test_config(run_path: Path):
  10. shutil.copy(Path('./tests/test_config.cfg'), Path(run_path, './test_config.cfg'))
  11. def create_basic_args_for_download_runner(test_args: list[str], run_path: Path):
  12. copy_test_config(run_path)
  13. out = [
  14. 'download', str(run_path),
  15. '-v',
  16. '--config', str(Path(run_path, './test_config.cfg')),
  17. '--log', str(Path(run_path, 'test_log.txt')),
  18. ] + test_args
  19. return out
  20. @pytest.mark.online
  21. @pytest.mark.reddit
  22. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  23. @pytest.mark.parametrize('test_args', (
  24. ['-s', 'Mindustry', '-L', 3],
  25. ['-s', 'r/Mindustry', '-L', 3],
  26. ['-s', 'r/mindustry', '-L', 3],
  27. ['-s', 'mindustry', '-L', 3],
  28. ['-s', 'https://www.reddit.com/r/TrollXChromosomes/', '-L', 3],
  29. ['-s', 'r/TrollXChromosomes/', '-L', 3],
  30. ['-s', 'TrollXChromosomes/', '-L', 3],
  31. ['-s', 'trollxchromosomes', '-L', 3],
  32. ['-s', 'trollxchromosomes,mindustry,python', '-L', 3],
  33. ['-s', 'trollxchromosomes, mindustry, python', '-L', 3],
  34. ['-s', 'trollxchromosomes', '-L', 3, '--time', 'day'],
  35. ['-s', 'trollxchromosomes', '-L', 3, '--sort', 'new'],
  36. ['-s', 'trollxchromosomes', '-L', 3, '--time', 'day', '--sort', 'new'],
  37. ['-s', 'trollxchromosomes', '-L', 3, '--search', 'women'],
  38. ['-s', 'trollxchromosomes', '-L', 3, '--time', 'day', '--search', 'women'],
  39. ['-s', 'trollxchromosomes', '-L', 3, '--sort', 'new', '--search', 'women'],
  40. ['-s', 'trollxchromosomes', '-L', 3, '--time', 'day', '--sort', 'new', '--search', 'women'],
  41. ))
  42. def test_cli_download_subreddits(test_args: list[str], tmp_path: Path):
  43. runner = CliRunner()
  44. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  45. result = runner.invoke(cli, test_args)
  46. assert result.exit_code == 0
  47. assert 'Added submissions from subreddit ' in result.output
  48. assert 'Downloaded submission' in result.output
  49. @pytest.mark.online
  50. @pytest.mark.reddit
  51. @pytest.mark.slow
  52. @pytest.mark.authenticated
  53. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  54. @pytest.mark.parametrize('test_args', (
  55. ['-s', 'hentai', '-L', 10, '--search', 'red', '--authenticate'],
  56. ['--authenticate', '--subscribed', '-L', 10],
  57. ))
  58. def test_cli_download_search_subreddits_authenticated(test_args: list[str], tmp_path: Path):
  59. runner = CliRunner()
  60. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  61. result = runner.invoke(cli, test_args)
  62. assert result.exit_code == 0
  63. assert 'Added submissions from subreddit ' in result.output
  64. assert 'Downloaded submission' in result.output
  65. @pytest.mark.online
  66. @pytest.mark.reddit
  67. @pytest.mark.authenticated
  68. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  69. @pytest.mark.parametrize('test_args', (
  70. ['--subreddit', 'friends', '-L', 10, '--authenticate'],
  71. ))
  72. def test_cli_download_user_specific_subreddits(test_args: list[str], tmp_path: Path):
  73. runner = CliRunner()
  74. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  75. result = runner.invoke(cli, test_args)
  76. assert result.exit_code == 0
  77. assert 'Added submissions from subreddit ' in result.output
  78. @pytest.mark.online
  79. @pytest.mark.reddit
  80. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  81. @pytest.mark.parametrize('test_args', (
  82. ['-l', '6l7778'],
  83. ['-l', 'https://reddit.com/r/EmpireDidNothingWrong/comments/6l7778/technically_true/'],
  84. ['-l', 'm3hxzd'], # Really long title used to overflow filename limit
  85. ['-l', 'm5bqkf'], # Resource leading to a 404
  86. ))
  87. def test_cli_download_links(test_args: list[str], tmp_path: Path):
  88. runner = CliRunner()
  89. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  90. result = runner.invoke(cli, test_args)
  91. assert result.exit_code == 0
  92. @pytest.mark.online
  93. @pytest.mark.reddit
  94. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  95. @pytest.mark.parametrize('test_args', (
  96. ['--user', 'helen_darten', '-m', 'cuteanimalpics', '-L', 10],
  97. ['--user', 'helen_darten', '-m', 'cuteanimalpics', '-L', 10, '--sort', 'rising'],
  98. ['--user', 'helen_darten', '-m', 'cuteanimalpics', '-L', 10, '--time', 'week'],
  99. ['--user', 'helen_darten', '-m', 'cuteanimalpics', '-L', 10, '--time', 'week', '--sort', 'rising'],
  100. ))
  101. def test_cli_download_multireddit(test_args: list[str], tmp_path: Path):
  102. runner = CliRunner()
  103. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  104. result = runner.invoke(cli, test_args)
  105. assert result.exit_code == 0
  106. assert 'Added submissions from multireddit ' in result.output
  107. @pytest.mark.online
  108. @pytest.mark.reddit
  109. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  110. @pytest.mark.parametrize('test_args', (
  111. ['--user', 'helen_darten', '-m', 'xxyyzzqwerty', '-L', 10],
  112. ))
  113. def test_cli_download_multireddit_nonexistent(test_args: list[str], tmp_path: Path):
  114. runner = CliRunner()
  115. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  116. result = runner.invoke(cli, test_args)
  117. assert result.exit_code == 0
  118. assert 'Failed to get submissions for multireddit' in result.output
  119. assert 'received 404 HTTP response' in result.output
  120. @pytest.mark.online
  121. @pytest.mark.reddit
  122. @pytest.mark.authenticated
  123. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  124. @pytest.mark.parametrize('test_args', (
  125. ['--user', 'djnish', '--submitted', '--user', 'FriesWithThat', '-L', 10],
  126. ['--user', 'me', '--upvoted', '--authenticate', '-L', 10],
  127. ['--user', 'me', '--saved', '--authenticate', '-L', 10],
  128. ['--user', 'me', '--submitted', '--authenticate', '-L', 10],
  129. ['--user', 'djnish', '--submitted', '-L', 10],
  130. ['--user', 'djnish', '--submitted', '-L', 10, '--time', 'month'],
  131. ['--user', 'djnish', '--submitted', '-L', 10, '--sort', 'controversial'],
  132. ))
  133. def test_cli_download_user_data_good(test_args: list[str], tmp_path: Path):
  134. runner = CliRunner()
  135. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  136. result = runner.invoke(cli, test_args)
  137. assert result.exit_code == 0
  138. assert 'Downloaded submission ' in result.output
  139. @pytest.mark.online
  140. @pytest.mark.reddit
  141. @pytest.mark.authenticated
  142. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  143. @pytest.mark.parametrize('test_args', (
  144. ['--user', 'me', '-L', 10, '--folder-scheme', ''],
  145. ))
  146. def test_cli_download_user_data_bad_me_unauthenticated(test_args: list[str], tmp_path: Path):
  147. runner = CliRunner()
  148. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  149. result = runner.invoke(cli, test_args)
  150. assert result.exit_code == 0
  151. assert 'To use "me" as a user, an authenticated Reddit instance must be used' in result.output
  152. @pytest.mark.online
  153. @pytest.mark.reddit
  154. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  155. @pytest.mark.parametrize('test_args', (
  156. ['--subreddit', 'python', '-L', 1, '--search-existing'],
  157. ))
  158. def test_cli_download_search_existing(test_args: list[str], tmp_path: Path):
  159. Path(tmp_path, 'test.txt').touch()
  160. runner = CliRunner()
  161. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  162. result = runner.invoke(cli, test_args)
  163. assert result.exit_code == 0
  164. assert 'Calculating hashes for' in result.output
  165. @pytest.mark.online
  166. @pytest.mark.reddit
  167. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  168. @pytest.mark.parametrize('test_args', (
  169. ['--subreddit', 'tumblr', '-L', '25', '--skip', 'png', '--skip', 'jpg'],
  170. ['--subreddit', 'MaliciousCompliance', '-L', '25', '--skip', 'txt'],
  171. ['--subreddit', 'tumblr', '-L', '10', '--skip-domain', 'i.redd.it'],
  172. ))
  173. def test_cli_download_download_filters(test_args: list[str], tmp_path: Path):
  174. runner = CliRunner()
  175. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  176. result = runner.invoke(cli, test_args)
  177. assert result.exit_code == 0
  178. assert any((string in result.output for string in ('Download filter removed ', 'filtered due to URL')))
  179. @pytest.mark.online
  180. @pytest.mark.reddit
  181. @pytest.mark.slow
  182. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  183. @pytest.mark.parametrize('test_args', (
  184. ['--subreddit', 'all', '-L', '100', '--sort', 'new'],
  185. ))
  186. def test_cli_download_long(test_args: list[str], tmp_path: Path):
  187. runner = CliRunner()
  188. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  189. result = runner.invoke(cli, test_args)
  190. assert result.exit_code == 0
  191. @pytest.mark.online
  192. @pytest.mark.reddit
  193. @pytest.mark.slow
  194. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  195. @pytest.mark.parametrize('test_args', (
  196. ['--user', 'sdclhgsolgjeroij', '--submitted', '-L', 10],
  197. ['--user', 'me', '--upvoted', '-L', 10],
  198. ['--user', 'sdclhgsolgjeroij', '--upvoted', '-L', 10],
  199. ['--subreddit', 'submitters', '-L', 10], # Private subreddit
  200. ['--subreddit', 'donaldtrump', '-L', 10], # Banned subreddit
  201. ['--user', 'djnish', '--user', 'helen_darten', '-m', 'cuteanimalpics', '-L', 10],
  202. ['--subreddit', 'friends', '-L', 10],
  203. ))
  204. def test_cli_download_soft_fail(test_args: list[str], tmp_path: Path):
  205. runner = CliRunner()
  206. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  207. result = runner.invoke(cli, test_args)
  208. assert result.exit_code == 0
  209. assert 'Downloaded' not in result.output
  210. @pytest.mark.online
  211. @pytest.mark.reddit
  212. @pytest.mark.slow
  213. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  214. @pytest.mark.parametrize('test_args', (
  215. ['--time', 'random'],
  216. ['--sort', 'random'],
  217. ))
  218. def test_cli_download_hard_fail(test_args: list[str], tmp_path: Path):
  219. runner = CliRunner()
  220. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  221. result = runner.invoke(cli, test_args)
  222. assert result.exit_code != 0
  223. def test_cli_download_use_default_config(tmp_path: Path):
  224. runner = CliRunner()
  225. test_args = ['download', '-vv', str(tmp_path)]
  226. result = runner.invoke(cli, test_args)
  227. assert result.exit_code == 0
  228. @pytest.mark.online
  229. @pytest.mark.reddit
  230. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  231. @pytest.mark.parametrize('test_args', (
  232. ['-l', '6l7778', '--exclude-id', '6l7778'],
  233. ))
  234. def test_cli_download_links_exclusion(test_args: list[str], tmp_path: Path):
  235. runner = CliRunner()
  236. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  237. result = runner.invoke(cli, test_args)
  238. assert result.exit_code == 0
  239. assert 'in exclusion list' in result.output
  240. assert 'Downloaded submission ' not in result.output
  241. @pytest.mark.online
  242. @pytest.mark.reddit
  243. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  244. @pytest.mark.parametrize('test_args', (
  245. ['-l', '6l7778', '--skip-subreddit', 'EmpireDidNothingWrong'],
  246. ['-s', 'trollxchromosomes', '--skip-subreddit', 'trollxchromosomes', '-L', '3'],
  247. ))
  248. def test_cli_download_subreddit_exclusion(test_args: list[str], tmp_path: Path):
  249. runner = CliRunner()
  250. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  251. result = runner.invoke(cli, test_args)
  252. assert result.exit_code == 0
  253. assert 'in skip list' in result.output
  254. assert 'Downloaded submission ' not in result.output
  255. @pytest.mark.online
  256. @pytest.mark.reddit
  257. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  258. @pytest.mark.parametrize('test_args', (
  259. ['--file-scheme', '{TITLE}'],
  260. ['--file-scheme', '{TITLE}_test_{SUBREDDIT}'],
  261. ))
  262. def test_cli_download_file_scheme_warning(test_args: list[str], tmp_path: Path):
  263. runner = CliRunner()
  264. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  265. result = runner.invoke(cli, test_args)
  266. assert result.exit_code == 0
  267. assert 'Some files might not be downloaded due to name conflicts' in result.output
  268. @pytest.mark.online
  269. @pytest.mark.reddit
  270. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  271. @pytest.mark.parametrize('test_args', (
  272. ['-l', 'n9w9fo', '--disable-module', 'SelfPost'],
  273. ['-l', 'nnb9vs', '--disable-module', 'VReddit'],
  274. ))
  275. def test_cli_download_disable_modules(test_args: list[str], tmp_path: Path):
  276. runner = CliRunner()
  277. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  278. result = runner.invoke(cli, test_args)
  279. assert result.exit_code == 0
  280. assert 'skipped due to disabled module' in result.output
  281. assert 'Downloaded submission' not in result.output
  282. @pytest.mark.online
  283. @pytest.mark.reddit
  284. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  285. def test_cli_download_include_id_file(tmp_path: Path):
  286. test_file = Path(tmp_path, 'include.txt')
  287. test_args = ['--include-id-file', str(test_file)]
  288. test_file.write_text('odr9wg\nody576')
  289. runner = CliRunner()
  290. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  291. result = runner.invoke(cli, test_args)
  292. assert result.exit_code == 0
  293. assert 'Downloaded submission' in result.output
  294. @pytest.mark.online
  295. @pytest.mark.reddit
  296. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  297. @pytest.mark.parametrize('test_args', (
  298. ['--ignore-user', 'ArjanEgges', '-l', 'm3hxzd'],
  299. ))
  300. def test_cli_download_ignore_user(test_args: list[str], tmp_path: Path):
  301. runner = CliRunner()
  302. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  303. result = runner.invoke(cli, test_args)
  304. assert result.exit_code == 0
  305. assert 'Downloaded submission' not in result.output
  306. assert 'being an ignored user' in result.output
  307. @pytest.mark.online
  308. @pytest.mark.reddit
  309. @pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
  310. @pytest.mark.parametrize(('test_args', 'was_filtered'), (
  311. (['-l', 'ljyy27', '--min-score', '50'], True),
  312. (['-l', 'ljyy27', '--min-score', '1'], False),
  313. (['-l', 'ljyy27', '--max-score', '1'], True),
  314. (['-l', 'ljyy27', '--max-score', '100'], False),
  315. ))
  316. def test_cli_download_score_filter(test_args: list[str], was_filtered: bool, tmp_path: Path):
  317. runner = CliRunner()
  318. test_args = create_basic_args_for_download_runner(test_args, tmp_path)
  319. result = runner.invoke(cli, test_args)
  320. assert result.exit_code == 0
  321. assert ('filtered due to score' in result.output) == was_filtered