Format according to the black standard

This commit is contained in:
Serene-Arc
2022-12-03 15:11:17 +10:00
parent 96cd7d7147
commit 0873a4a2b2
60 changed files with 2160 additions and 1790 deletions

View File

@@ -9,15 +9,21 @@ from bdfr.archive_entry.comment_archive_entry import CommentArchiveEntry
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_comment_id', 'expected_dict'), (
('gstd4hk', {
'author': 'james_pic',
'subreddit': 'Python',
'submission': 'mgi4op',
'submission_title': '76% Faster CPython',
'distinguished': None,
}),
))
@pytest.mark.parametrize(
("test_comment_id", "expected_dict"),
(
(
"gstd4hk",
{
"author": "james_pic",
"subreddit": "Python",
"submission": "mgi4op",
"submission_title": "76% Faster CPython",
"distinguished": None,
},
),
),
)
def test_get_comment_details(test_comment_id: str, expected_dict: dict, reddit_instance: praw.Reddit):
comment = reddit_instance.comment(id=test_comment_id)
test_entry = CommentArchiveEntry(comment)
@@ -27,13 +33,16 @@ def test_get_comment_details(test_comment_id: str, expected_dict: dict, reddit_i
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_comment_id', 'expected_min_comments'), (
('gstd4hk', 4),
('gsvyste', 3),
('gsxnvvb', 5),
))
@pytest.mark.parametrize(
("test_comment_id", "expected_min_comments"),
(
("gstd4hk", 4),
("gsvyste", 3),
("gsxnvvb", 5),
),
)
def test_get_comment_replies(test_comment_id: str, expected_min_comments: int, reddit_instance: praw.Reddit):
comment = reddit_instance.comment(id=test_comment_id)
test_entry = CommentArchiveEntry(comment)
result = test_entry.compile()
assert len(result.get('replies')) >= expected_min_comments
assert len(result.get("replies")) >= expected_min_comments

View File

@@ -9,9 +9,7 @@ from bdfr.archive_entry.submission_archive_entry import SubmissionArchiveEntry
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_submission_id', 'min_comments'), (
('m3reby', 27),
))
@pytest.mark.parametrize(("test_submission_id", "min_comments"), (("m3reby", 27),))
def test_get_comments(test_submission_id: str, min_comments: int, reddit_instance: praw.Reddit):
test_submission = reddit_instance.submission(id=test_submission_id)
test_archive_entry = SubmissionArchiveEntry(test_submission)
@@ -21,21 +19,27 @@ def test_get_comments(test_submission_id: str, min_comments: int, reddit_instanc
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_submission_id', 'expected_dict'), (
('m3reby', {
'author': 'sinjen-tos',
'id': 'm3reby',
'link_flair_text': 'image',
'pinned': False,
'spoiler': False,
'over_18': False,
'locked': False,
'distinguished': None,
'created_utc': 1615583837,
'permalink': '/r/australia/comments/m3reby/this_little_guy_fell_out_of_a_tree_and_in_front/'
}),
# TODO: add deleted user test case
))
@pytest.mark.parametrize(
("test_submission_id", "expected_dict"),
(
(
"m3reby",
{
"author": "sinjen-tos",
"id": "m3reby",
"link_flair_text": "image",
"pinned": False,
"spoiler": False,
"over_18": False,
"locked": False,
"distinguished": None,
"created_utc": 1615583837,
"permalink": "/r/australia/comments/m3reby/this_little_guy_fell_out_of_a_tree_and_in_front/",
},
),
# TODO: add deleted user test case
),
)
def test_get_post_details(test_submission_id: str, expected_dict: dict, reddit_instance: praw.Reddit):
test_submission = reddit_instance.submission(id=test_submission_id)
test_archive_entry = SubmissionArchiveEntry(test_submission)

View File

@@ -11,29 +11,29 @@ import pytest
from bdfr.oauth2 import OAuth2TokenManager
@pytest.fixture(scope='session')
@pytest.fixture(scope="session")
def reddit_instance():
rd = praw.Reddit(
client_id='U-6gk4ZCh3IeNQ',
client_secret='7CZHY6AmKweZME5s50SfDGylaPg',
user_agent='test',
client_id="U-6gk4ZCh3IeNQ",
client_secret="7CZHY6AmKweZME5s50SfDGylaPg",
user_agent="test",
)
return rd
@pytest.fixture(scope='session')
@pytest.fixture(scope="session")
def authenticated_reddit_instance():
test_config_path = Path('./tests/test_config.cfg')
test_config_path = Path("./tests/test_config.cfg")
if not test_config_path.exists():
pytest.skip('Refresh token must be provided to authenticate with OAuth2')
pytest.skip("Refresh token must be provided to authenticate with OAuth2")
cfg_parser = configparser.ConfigParser()
cfg_parser.read(test_config_path)
if not cfg_parser.has_option('DEFAULT', 'user_token'):
pytest.skip('Refresh token must be provided to authenticate with OAuth2')
if not cfg_parser.has_option("DEFAULT", "user_token"):
pytest.skip("Refresh token must be provided to authenticate with OAuth2")
token_manager = OAuth2TokenManager(cfg_parser, test_config_path)
reddit_instance = praw.Reddit(
client_id=cfg_parser.get('DEFAULT', 'client_id'),
client_secret=cfg_parser.get('DEFAULT', 'client_secret'),
client_id=cfg_parser.get("DEFAULT", "client_id"),
client_secret=cfg_parser.get("DEFAULT", "client_secret"),
user_agent=socket.gethostname(),
token_manager=token_manager,
)

View File

@@ -10,67 +10,78 @@ from click.testing import CliRunner
from bdfr.__main__ import cli
does_test_config_exist = Path('./tests/test_config.cfg').exists()
does_test_config_exist = Path("./tests/test_config.cfg").exists()
def copy_test_config(run_path: Path):
shutil.copy(Path('./tests/test_config.cfg'), Path(run_path, 'test_config.cfg'))
shutil.copy(Path("./tests/test_config.cfg"), Path(run_path, "test_config.cfg"))
def create_basic_args_for_archive_runner(test_args: list[str], run_path: Path):
copy_test_config(run_path)
out = [
'archive',
"archive",
str(run_path),
'-v',
'--config', str(Path(run_path, 'test_config.cfg')),
'--log', str(Path(run_path, 'test_log.txt')),
"-v",
"--config",
str(Path(run_path, "test_config.cfg")),
"--log",
str(Path(run_path, "test_log.txt")),
] + test_args
return out
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['-l', 'gstd4hk'],
['-l', 'm2601g', '-f', 'yaml'],
['-l', 'n60t4c', '-f', 'xml'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["-l", "gstd4hk"],
["-l", "m2601g", "-f", "yaml"],
["-l", "n60t4c", "-f", "xml"],
),
)
def test_cli_archive_single(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_archive_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert re.search(r'Writing entry .*? to file in .*? format', result.output)
assert re.search(r"Writing entry .*? to file in .*? format", result.output)
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--subreddit', 'Mindustry', '-L', 25],
['--subreddit', 'Mindustry', '-L', 25, '--format', 'xml'],
['--subreddit', 'Mindustry', '-L', 25, '--format', 'yaml'],
['--subreddit', 'Mindustry', '-L', 25, '--sort', 'new'],
['--subreddit', 'Mindustry', '-L', 25, '--time', 'day'],
['--subreddit', 'Mindustry', '-L', 25, '--time', 'day', '--sort', 'new'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["--subreddit", "Mindustry", "-L", 25],
["--subreddit", "Mindustry", "-L", 25, "--format", "xml"],
["--subreddit", "Mindustry", "-L", 25, "--format", "yaml"],
["--subreddit", "Mindustry", "-L", 25, "--sort", "new"],
["--subreddit", "Mindustry", "-L", 25, "--time", "day"],
["--subreddit", "Mindustry", "-L", 25, "--time", "day", "--sort", "new"],
),
)
def test_cli_archive_subreddit(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_archive_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert re.search(r'Writing entry .*? to file in .*? format', result.output)
assert re.search(r"Writing entry .*? to file in .*? format", result.output)
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--user', 'me', '--authenticate', '--all-comments', '-L', '10'],
['--user', 'me', '--user', 'djnish', '--authenticate', '--all-comments', '-L', '10'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["--user", "me", "--authenticate", "--all-comments", "-L", "10"],
["--user", "me", "--user", "djnish", "--authenticate", "--all-comments", "-L", "10"],
),
)
def test_cli_archive_all_user_comments(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_archive_runner(test_args, tmp_path)
@@ -80,89 +91,88 @@ def test_cli_archive_all_user_comments(test_args: list[str], tmp_path: Path):
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--comment-context', '--link', 'gxqapql'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize("test_args", (["--comment-context", "--link", "gxqapql"],))
def test_cli_archive_full_context(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_archive_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'Converting comment' in result.output
assert "Converting comment" in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.slow
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--subreddit', 'all', '-L', 100],
['--subreddit', 'all', '-L', 100, '--sort', 'new'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["--subreddit", "all", "-L", 100],
["--subreddit", "all", "-L", 100, "--sort", "new"],
),
)
def test_cli_archive_long(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_archive_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert re.search(r'Writing entry .*? to file in .*? format', result.output)
assert re.search(r"Writing entry .*? to file in .*? format", result.output)
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--ignore-user', 'ArjanEgges', '-l', 'm3hxzd'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize("test_args", (["--ignore-user", "ArjanEgges", "-l", "m3hxzd"],))
def test_cli_archive_ignore_user(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_archive_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'being an ignored user' in result.output
assert 'Attempting to archive submission' not in result.output
assert "being an ignored user" in result.output
assert "Attempting to archive submission" not in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--file-scheme', '{TITLE}', '-l', 'suy011'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize("test_args", (["--file-scheme", "{TITLE}", "-l", "suy011"],))
def test_cli_archive_file_format(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_archive_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'Attempting to archive submission' in result.output
assert re.search('format at /.+?/Judge says Trump and two adult', result.output)
assert "Attempting to archive submission" in result.output
assert re.search("format at /.+?/Judge says Trump and two adult", result.output)
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['-l', 'm2601g', '--exclude-id', 'm2601g'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize("test_args", (["-l", "m2601g", "--exclude-id", "m2601g"],))
def test_cli_archive_links_exclusion(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_archive_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'in exclusion list' in result.output
assert 'Attempting to archive' not in result.output
assert "in exclusion list" in result.output
assert "Attempting to archive" not in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['-l', 'ijy4ch'], # user deleted post
['-l', 'kw4wjm'], # post from banned subreddit
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["-l", "ijy4ch"], # user deleted post
["-l", "kw4wjm"], # post from banned subreddit
),
)
def test_cli_archive_soft_fail(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_archive_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'failed to be archived due to a PRAW exception' in result.output
assert 'Attempting to archive' not in result.output
assert "failed to be archived due to a PRAW exception" in result.output
assert "Attempting to archive" not in result.output

View File

@@ -9,54 +9,62 @@ from click.testing import CliRunner
from bdfr.__main__ import cli
does_test_config_exist = Path('./tests/test_config.cfg').exists()
does_test_config_exist = Path("./tests/test_config.cfg").exists()
def copy_test_config(run_path: Path):
shutil.copy(Path('./tests/test_config.cfg'), Path(run_path, 'test_config.cfg'))
shutil.copy(Path("./tests/test_config.cfg"), Path(run_path, "test_config.cfg"))
def create_basic_args_for_cloner_runner(test_args: list[str], tmp_path: Path):
copy_test_config(tmp_path)
out = [
'clone',
"clone",
str(tmp_path),
'-v',
'--config', str(Path(tmp_path, 'test_config.cfg')),
'--log', str(Path(tmp_path, 'test_log.txt')),
"-v",
"--config",
str(Path(tmp_path, "test_config.cfg")),
"--log",
str(Path(tmp_path, "test_log.txt")),
] + test_args
return out
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['-l', '6l7778'],
['-s', 'TrollXChromosomes/', '-L', 1],
['-l', 'eiajjw'],
['-l', 'xl0lhi'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["-l", "6l7778"],
["-s", "TrollXChromosomes/", "-L", 1],
["-l", "eiajjw"],
["-l", "xl0lhi"],
),
)
def test_cli_scrape_general(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_cloner_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'Downloaded submission' in result.output
assert 'Record for entry item' in result.output
assert "Downloaded submission" in result.output
assert "Record for entry item" in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['-l', 'ijy4ch'], # user deleted post
['-l', 'kw4wjm'], # post from banned subreddit
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["-l", "ijy4ch"], # user deleted post
["-l", "kw4wjm"], # post from banned subreddit
),
)
def test_cli_scrape_soft_fail(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_cloner_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'Downloaded submission' not in result.output
assert 'Record for entry item' not in result.output
assert "Downloaded submission" not in result.output
assert "Record for entry item" not in result.output

View File

@@ -9,97 +9,107 @@ from click.testing import CliRunner
from bdfr.__main__ import cli
does_test_config_exist = Path('./tests/test_config.cfg').exists()
does_test_config_exist = Path("./tests/test_config.cfg").exists()
def copy_test_config(run_path: Path):
shutil.copy(Path('./tests/test_config.cfg'), Path(run_path, './test_config.cfg'))
shutil.copy(Path("./tests/test_config.cfg"), Path(run_path, "./test_config.cfg"))
def create_basic_args_for_download_runner(test_args: list[str], run_path: Path):
copy_test_config(run_path)
out = [
'download', str(run_path),
'-v',
'--config', str(Path(run_path, './test_config.cfg')),
'--log', str(Path(run_path, 'test_log.txt')),
"download",
str(run_path),
"-v",
"--config",
str(Path(run_path, "./test_config.cfg")),
"--log",
str(Path(run_path, "test_log.txt")),
] + test_args
return out
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['-s', 'Mindustry', '-L', 3],
['-s', 'r/Mindustry', '-L', 3],
['-s', 'r/mindustry', '-L', 3],
['-s', 'mindustry', '-L', 3],
['-s', 'https://www.reddit.com/r/TrollXChromosomes/', '-L', 3],
['-s', 'r/TrollXChromosomes/', '-L', 3],
['-s', 'TrollXChromosomes/', '-L', 3],
['-s', 'trollxchromosomes', '-L', 3],
['-s', 'trollxchromosomes,mindustry,python', '-L', 3],
['-s', 'trollxchromosomes, mindustry, python', '-L', 3],
['-s', 'trollxchromosomes', '-L', 3, '--time', 'day'],
['-s', 'trollxchromosomes', '-L', 3, '--sort', 'new'],
['-s', 'trollxchromosomes', '-L', 3, '--time', 'day', '--sort', 'new'],
['-s', 'trollxchromosomes', '-L', 3, '--search', 'women'],
['-s', 'trollxchromosomes', '-L', 3, '--time', 'day', '--search', 'women'],
['-s', 'trollxchromosomes', '-L', 3, '--sort', 'new', '--search', 'women'],
['-s', 'trollxchromosomes', '-L', 3, '--time', 'day', '--sort', 'new', '--search', 'women'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["-s", "Mindustry", "-L", 3],
["-s", "r/Mindustry", "-L", 3],
["-s", "r/mindustry", "-L", 3],
["-s", "mindustry", "-L", 3],
["-s", "https://www.reddit.com/r/TrollXChromosomes/", "-L", 3],
["-s", "r/TrollXChromosomes/", "-L", 3],
["-s", "TrollXChromosomes/", "-L", 3],
["-s", "trollxchromosomes", "-L", 3],
["-s", "trollxchromosomes,mindustry,python", "-L", 3],
["-s", "trollxchromosomes, mindustry, python", "-L", 3],
["-s", "trollxchromosomes", "-L", 3, "--time", "day"],
["-s", "trollxchromosomes", "-L", 3, "--sort", "new"],
["-s", "trollxchromosomes", "-L", 3, "--time", "day", "--sort", "new"],
["-s", "trollxchromosomes", "-L", 3, "--search", "women"],
["-s", "trollxchromosomes", "-L", 3, "--time", "day", "--search", "women"],
["-s", "trollxchromosomes", "-L", 3, "--sort", "new", "--search", "women"],
["-s", "trollxchromosomes", "-L", 3, "--time", "day", "--sort", "new", "--search", "women"],
),
)
def test_cli_download_subreddits(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'Added submissions from subreddit ' in result.output
assert 'Downloaded submission' in result.output
assert "Added submissions from subreddit " in result.output
assert "Downloaded submission" in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.slow
@pytest.mark.authenticated
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['-s', 'hentai', '-L', 10, '--search', 'red', '--authenticate'],
['--authenticate', '--subscribed', '-L', 10],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["-s", "hentai", "-L", 10, "--search", "red", "--authenticate"],
["--authenticate", "--subscribed", "-L", 10],
),
)
def test_cli_download_search_subreddits_authenticated(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'Added submissions from subreddit ' in result.output
assert 'Downloaded submission' in result.output
assert "Added submissions from subreddit " in result.output
assert "Downloaded submission" in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.authenticated
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--subreddit', 'friends', '-L', 10, '--authenticate'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize("test_args", (["--subreddit", "friends", "-L", 10, "--authenticate"],))
def test_cli_download_user_specific_subreddits(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'Added submissions from subreddit ' in result.output
assert "Added submissions from subreddit " in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['-l', '6l7778'],
['-l', 'https://reddit.com/r/EmpireDidNothingWrong/comments/6l7778/technically_true/'],
['-l', 'm3hxzd'], # Really long title used to overflow filename limit
['-l', 'm5bqkf'], # Resource leading to a 404
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["-l", "6l7778"],
["-l", "https://reddit.com/r/EmpireDidNothingWrong/comments/6l7778/technically_true/"],
["-l", "m3hxzd"], # Really long title used to overflow filename limit
["-l", "m5bqkf"], # Resource leading to a 404
),
)
def test_cli_download_links(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
@@ -109,64 +119,66 @@ def test_cli_download_links(test_args: list[str], tmp_path: Path):
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--user', 'helen_darten', '-m', 'cuteanimalpics', '-L', 10],
['--user', 'helen_darten', '-m', 'cuteanimalpics', '-L', 10, '--sort', 'rising'],
['--user', 'helen_darten', '-m', 'cuteanimalpics', '-L', 10, '--time', 'week'],
['--user', 'helen_darten', '-m', 'cuteanimalpics', '-L', 10, '--time', 'week', '--sort', 'rising'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["--user", "helen_darten", "-m", "cuteanimalpics", "-L", 10],
["--user", "helen_darten", "-m", "cuteanimalpics", "-L", 10, "--sort", "rising"],
["--user", "helen_darten", "-m", "cuteanimalpics", "-L", 10, "--time", "week"],
["--user", "helen_darten", "-m", "cuteanimalpics", "-L", 10, "--time", "week", "--sort", "rising"],
),
)
def test_cli_download_multireddit(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'Added submissions from multireddit ' in result.output
assert "Added submissions from multireddit " in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--user', 'helen_darten', '-m', 'xxyyzzqwerty', '-L', 10],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize("test_args", (["--user", "helen_darten", "-m", "xxyyzzqwerty", "-L", 10],))
def test_cli_download_multireddit_nonexistent(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'Failed to get submissions for multireddit' in result.output
assert 'received 404 HTTP response' in result.output
assert "Failed to get submissions for multireddit" in result.output
assert "received 404 HTTP response" in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.authenticated
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--user', 'djnish', '--submitted', '--user', 'FriesWithThat', '-L', 10],
['--user', 'me', '--upvoted', '--authenticate', '-L', 10],
['--user', 'me', '--saved', '--authenticate', '-L', 10],
['--user', 'me', '--submitted', '--authenticate', '-L', 10],
['--user', 'djnish', '--submitted', '-L', 10],
['--user', 'djnish', '--submitted', '-L', 10, '--time', 'month'],
['--user', 'djnish', '--submitted', '-L', 10, '--sort', 'controversial'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["--user", "djnish", "--submitted", "--user", "FriesWithThat", "-L", 10],
["--user", "me", "--upvoted", "--authenticate", "-L", 10],
["--user", "me", "--saved", "--authenticate", "-L", 10],
["--user", "me", "--submitted", "--authenticate", "-L", 10],
["--user", "djnish", "--submitted", "-L", 10],
["--user", "djnish", "--submitted", "-L", 10, "--time", "month"],
["--user", "djnish", "--submitted", "-L", 10, "--sort", "controversial"],
),
)
def test_cli_download_user_data_good(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'Downloaded submission ' in result.output
assert "Downloaded submission " in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.authenticated
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--user', 'me', '-L', 10, '--folder-scheme', ''],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize("test_args", (["--user", "me", "-L", 10, "--folder-scheme", ""],))
def test_cli_download_user_data_bad_me_unauthenticated(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
@@ -177,42 +189,41 @@ def test_cli_download_user_data_bad_me_unauthenticated(test_args: list[str], tmp
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--subreddit', 'python', '-L', 1, '--search-existing'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize("test_args", (["--subreddit", "python", "-L", 1, "--search-existing"],))
def test_cli_download_search_existing(test_args: list[str], tmp_path: Path):
Path(tmp_path, 'test.txt').touch()
Path(tmp_path, "test.txt").touch()
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'Calculating hashes for' in result.output
assert "Calculating hashes for" in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--subreddit', 'tumblr', '-L', '25', '--skip', 'png', '--skip', 'jpg'],
['--subreddit', 'MaliciousCompliance', '-L', '25', '--skip', 'txt'],
['--subreddit', 'tumblr', '-L', '10', '--skip-domain', 'i.redd.it'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["--subreddit", "tumblr", "-L", "25", "--skip", "png", "--skip", "jpg"],
["--subreddit", "MaliciousCompliance", "-L", "25", "--skip", "txt"],
["--subreddit", "tumblr", "-L", "10", "--skip-domain", "i.redd.it"],
),
)
def test_cli_download_download_filters(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert any((string in result.output for string in ('Download filter removed ', 'filtered due to URL')))
assert any((string in result.output for string in ("Download filter removed ", "filtered due to URL")))
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.slow
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--subreddit', 'all', '-L', '100', '--sort', 'new'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize("test_args", (["--subreddit", "all", "-L", "100", "--sort", "new"],))
def test_cli_download_long(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
@@ -223,34 +234,40 @@ def test_cli_download_long(test_args: list[str], tmp_path: Path):
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.slow
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--user', 'sdclhgsolgjeroij', '--submitted', '-L', 10],
['--user', 'me', '--upvoted', '-L', 10],
['--user', 'sdclhgsolgjeroij', '--upvoted', '-L', 10],
['--subreddit', 'submitters', '-L', 10], # Private subreddit
['--subreddit', 'donaldtrump', '-L', 10], # Banned subreddit
['--user', 'djnish', '--user', 'helen_darten', '-m', 'cuteanimalpics', '-L', 10],
['--subreddit', 'friends', '-L', 10],
['-l', 'ijy4ch'], # user deleted post
['-l', 'kw4wjm'], # post from banned subreddit
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["--user", "sdclhgsolgjeroij", "--submitted", "-L", 10],
["--user", "me", "--upvoted", "-L", 10],
["--user", "sdclhgsolgjeroij", "--upvoted", "-L", 10],
["--subreddit", "submitters", "-L", 10], # Private subreddit
["--subreddit", "donaldtrump", "-L", 10], # Banned subreddit
["--user", "djnish", "--user", "helen_darten", "-m", "cuteanimalpics", "-L", 10],
["--subreddit", "friends", "-L", 10],
["-l", "ijy4ch"], # user deleted post
["-l", "kw4wjm"], # post from banned subreddit
),
)
def test_cli_download_soft_fail(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'Downloaded' not in result.output
assert "Downloaded" not in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.slow
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--time', 'random'],
['--sort', 'random'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["--time", "random"],
["--sort", "random"],
),
)
def test_cli_download_hard_fail(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
@@ -260,114 +277,122 @@ def test_cli_download_hard_fail(test_args: list[str], tmp_path: Path):
def test_cli_download_use_default_config(tmp_path: Path):
runner = CliRunner()
test_args = ['download', '-vv', str(tmp_path)]
test_args = ["download", "-vv", str(tmp_path)]
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['-l', '6l7778', '--exclude-id', '6l7778'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize("test_args", (["-l", "6l7778", "--exclude-id", "6l7778"],))
def test_cli_download_links_exclusion(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'in exclusion list' in result.output
assert 'Downloaded submission ' not in result.output
assert "in exclusion list" in result.output
assert "Downloaded submission " not in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['-l', '6l7778', '--skip-subreddit', 'EmpireDidNothingWrong'],
['-s', 'trollxchromosomes', '--skip-subreddit', 'trollxchromosomes', '-L', '3'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["-l", "6l7778", "--skip-subreddit", "EmpireDidNothingWrong"],
["-s", "trollxchromosomes", "--skip-subreddit", "trollxchromosomes", "-L", "3"],
),
)
def test_cli_download_subreddit_exclusion(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'in skip list' in result.output
assert 'Downloaded submission ' not in result.output
assert "in skip list" in result.output
assert "Downloaded submission " not in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--file-scheme', '{TITLE}'],
['--file-scheme', '{TITLE}_test_{SUBREDDIT}'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["--file-scheme", "{TITLE}"],
["--file-scheme", "{TITLE}_test_{SUBREDDIT}"],
),
)
def test_cli_download_file_scheme_warning(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'Some files might not be downloaded due to name conflicts' in result.output
assert "Some files might not be downloaded due to name conflicts" in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['-l', 'n9w9fo', '--disable-module', 'SelfPost'],
['-l', 'nnb9vs', '--disable-module', 'VReddit'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
"test_args",
(
["-l", "n9w9fo", "--disable-module", "SelfPost"],
["-l", "nnb9vs", "--disable-module", "VReddit"],
),
)
def test_cli_download_disable_modules(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'skipped due to disabled module' in result.output
assert 'Downloaded submission' not in result.output
assert "skipped due to disabled module" in result.output
assert "Downloaded submission" not in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
def test_cli_download_include_id_file(tmp_path: Path):
test_file = Path(tmp_path, 'include.txt')
test_args = ['--include-id-file', str(test_file)]
test_file.write_text('odr9wg\nody576')
test_file = Path(tmp_path, "include.txt")
test_args = ["--include-id-file", str(test_file)]
test_file.write_text("odr9wg\nody576")
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'Downloaded submission' in result.output
assert "Downloaded submission" in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--ignore-user', 'ArjanEgges', '-l', 'm3hxzd'],
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize("test_args", (["--ignore-user", "ArjanEgges", "-l", "m3hxzd"],))
def test_cli_download_ignore_user(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'Downloaded submission' not in result.output
assert 'being an ignored user' in result.output
assert "Downloaded submission" not in result.output
assert "being an ignored user" in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize(('test_args', 'was_filtered'), (
(['-l', 'ljyy27', '--min-score', '50'], True),
(['-l', 'ljyy27', '--min-score', '1'], False),
(['-l', 'ljyy27', '--max-score', '1'], True),
(['-l', 'ljyy27', '--max-score', '100'], False),
))
@pytest.mark.skipif(not does_test_config_exist, reason="A test config file is required for integration tests")
@pytest.mark.parametrize(
("test_args", "was_filtered"),
(
(["-l", "ljyy27", "--min-score", "50"], True),
(["-l", "ljyy27", "--min-score", "1"], False),
(["-l", "ljyy27", "--max-score", "1"], True),
(["-l", "ljyy27", "--max-score", "100"], False),
),
)
def test_cli_download_score_filter(test_args: list[str], was_filtered: bool, tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert ('filtered due to score' in result.output) == was_filtered
assert ("filtered due to score" in result.output) == was_filtered

View File

@@ -10,22 +10,23 @@ from bdfr.site_downloaders.fallback_downloaders.ytdlp_fallback import YtdlpFallb
@pytest.mark.online
@pytest.mark.parametrize(('test_url', 'expected'), (
('https://www.reddit.com/r/specializedtools/comments/n2nw5m/bamboo_splitter/', True),
('https://www.youtube.com/watch?v=P19nvJOmqCc', True),
('https://www.example.com/test', False),
('https://milesmatrix.bandcamp.com/album/la-boum/', False),
('https://v.redd.it/dlr54z8p182a1', True),
))
@pytest.mark.parametrize(
("test_url", "expected"),
(
("https://www.reddit.com/r/specializedtools/comments/n2nw5m/bamboo_splitter/", True),
("https://www.youtube.com/watch?v=P19nvJOmqCc", True),
("https://www.example.com/test", False),
("https://milesmatrix.bandcamp.com/album/la-boum/", False),
("https://v.redd.it/dlr54z8p182a1", True),
),
)
def test_can_handle_link(test_url: str, expected: bool):
result = YtdlpFallback.can_handle_link(test_url)
assert result == expected
@pytest.mark.online
@pytest.mark.parametrize('test_url', (
'https://milesmatrix.bandcamp.com/album/la-boum/',
))
@pytest.mark.parametrize("test_url", ("https://milesmatrix.bandcamp.com/album/la-boum/",))
def test_info_extraction_bad(test_url: str):
with pytest.raises(NotADownloadableLinkError):
YtdlpFallback.get_video_attributes(test_url)
@@ -33,12 +34,18 @@ def test_info_extraction_bad(test_url: str):
@pytest.mark.online
@pytest.mark.slow
@pytest.mark.parametrize(('test_url', 'expected_hash'), (
('https://streamable.com/dt46y', 'b7e465adaade5f2b6d8c2b4b7d0a2878'),
('https://streamable.com/t8sem', '49b2d1220c485455548f1edbc05d4ecf'),
('https://www.reddit.com/r/specializedtools/comments/n2nw5m/bamboo_splitter/', '6c6ff46e04b4e33a755ae2a9b5a45ac5'),
('https://v.redd.it/9z1dnk3xr5k61', '226cee353421c7aefb05c92424cc8cdd'),
))
@pytest.mark.parametrize(
("test_url", "expected_hash"),
(
("https://streamable.com/dt46y", "b7e465adaade5f2b6d8c2b4b7d0a2878"),
("https://streamable.com/t8sem", "49b2d1220c485455548f1edbc05d4ecf"),
(
"https://www.reddit.com/r/specializedtools/comments/n2nw5m/bamboo_splitter/",
"6c6ff46e04b4e33a755ae2a9b5a45ac5",
),
("https://v.redd.it/9z1dnk3xr5k61", "226cee353421c7aefb05c92424cc8cdd"),
),
)
def test_find_resources(test_url: str, expected_hash: str):
test_submission = MagicMock()
test_submission.url = test_url

View File

@@ -10,10 +10,13 @@ from bdfr.site_downloaders.delay_for_reddit import DelayForReddit
@pytest.mark.online
@pytest.mark.parametrize(('test_url', 'expected_hash'), (
('https://www.delayforreddit.com/dfr/calvin6123/MjU1Njc5NQ==', '3300f28c2f9358d05667985c9c04210d'),
('https://www.delayforreddit.com/dfr/RoXs_26/NDAwMzAyOQ==', '09b7b01719dff45ab197bdc08b90f78a'),
))
@pytest.mark.parametrize(
("test_url", "expected_hash"),
(
("https://www.delayforreddit.com/dfr/calvin6123/MjU1Njc5NQ==", "3300f28c2f9358d05667985c9c04210d"),
("https://www.delayforreddit.com/dfr/RoXs_26/NDAwMzAyOQ==", "09b7b01719dff45ab197bdc08b90f78a"),
),
)
def test_download_resource(test_url: str, expected_hash: str):
mock_submission = Mock()
mock_submission.url = test_url

View File

@@ -10,10 +10,13 @@ from bdfr.site_downloaders.direct import Direct
@pytest.mark.online
@pytest.mark.parametrize(('test_url', 'expected_hash'), (
('https://giant.gfycat.com/DefinitiveCanineCrayfish.mp4', '48f9bd4dbec1556d7838885612b13b39'),
('https://giant.gfycat.com/DazzlingSilkyIguana.mp4', '808941b48fc1e28713d36dd7ed9dc648'),
))
@pytest.mark.parametrize(
("test_url", "expected_hash"),
(
("https://giant.gfycat.com/DefinitiveCanineCrayfish.mp4", "48f9bd4dbec1556d7838885612b13b39"),
("https://giant.gfycat.com/DazzlingSilkyIguana.mp4", "808941b48fc1e28713d36dd7ed9dc648"),
),
)
def test_download_resource(test_url: str, expected_hash: str):
mock_submission = Mock()
mock_submission.url = test_url

View File

@@ -21,67 +21,82 @@ from bdfr.site_downloaders.youtube import Youtube
@pytest.mark.online
@pytest.mark.parametrize(('test_submission_url', 'expected_class'), (
('https://www.reddit.com/r/TwoXChromosomes/comments/lu29zn/i_refuse_to_live_my_life'
'_in_anything_but_comfort/', SelfPost),
('https://i.redd.it/affyv0axd5k61.png', Direct),
('https://i.imgur.com/bZx1SJQ.jpg', Imgur),
('https://imgur.com/BuzvZwb.gifv', Imgur),
('https://imgur.com/a/MkxAzeg', Imgur),
('https://m.imgur.com/a/py3RW0j', Imgur),
('https://www.reddit.com/gallery/lu93m7', Gallery),
('https://gfycat.com/concretecheerfulfinwhale', Gfycat),
('https://www.erome.com/a/NWGw0F09', Erome),
('https://youtube.com/watch?v=Gv8Wz74FjVA', Youtube),
('https://redgifs.com/watch/courageousimpeccablecanvasback', Redgifs),
('https://www.gifdeliverynetwork.com/repulsivefinishedandalusianhorse', Redgifs),
('https://youtu.be/DevfjHOhuFc', Youtube),
('https://m.youtube.com/watch?v=kr-FeojxzUM', Youtube),
('https://dynasty-scans.com/system/images_images/000/017/819/original/80215103_p0.png?1612232781', Direct),
('https://v.redd.it/9z1dnk3xr5k61', VReddit),
('https://streamable.com/dt46y', YtdlpFallback),
('https://vimeo.com/channels/31259/53576664', YtdlpFallback),
('http://video.pbs.org/viralplayer/2365173446/', YtdlpFallback),
('https://www.pornhub.com/view_video.php?viewkey=ph5a2ee0461a8d0', PornHub),
('https://www.patreon.com/posts/minecart-track-59346560', Gallery),
))
@pytest.mark.parametrize(
("test_submission_url", "expected_class"),
(
(
"https://www.reddit.com/r/TwoXChromosomes/comments/lu29zn/i_refuse_to_live_my_life"
"_in_anything_but_comfort/",
SelfPost,
),
("https://i.redd.it/affyv0axd5k61.png", Direct),
("https://i.imgur.com/bZx1SJQ.jpg", Imgur),
("https://imgur.com/BuzvZwb.gifv", Imgur),
("https://imgur.com/a/MkxAzeg", Imgur),
("https://m.imgur.com/a/py3RW0j", Imgur),
("https://www.reddit.com/gallery/lu93m7", Gallery),
("https://gfycat.com/concretecheerfulfinwhale", Gfycat),
("https://www.erome.com/a/NWGw0F09", Erome),
("https://youtube.com/watch?v=Gv8Wz74FjVA", Youtube),
("https://redgifs.com/watch/courageousimpeccablecanvasback", Redgifs),
("https://www.gifdeliverynetwork.com/repulsivefinishedandalusianhorse", Redgifs),
("https://youtu.be/DevfjHOhuFc", Youtube),
("https://m.youtube.com/watch?v=kr-FeojxzUM", Youtube),
("https://dynasty-scans.com/system/images_images/000/017/819/original/80215103_p0.png?1612232781", Direct),
("https://v.redd.it/9z1dnk3xr5k61", VReddit),
("https://streamable.com/dt46y", YtdlpFallback),
("https://vimeo.com/channels/31259/53576664", YtdlpFallback),
("http://video.pbs.org/viralplayer/2365173446/", YtdlpFallback),
("https://www.pornhub.com/view_video.php?viewkey=ph5a2ee0461a8d0", PornHub),
("https://www.patreon.com/posts/minecart-track-59346560", Gallery),
),
)
def test_factory_lever_good(test_submission_url: str, expected_class: BaseDownloader, reddit_instance: praw.Reddit):
result = DownloadFactory.pull_lever(test_submission_url)
assert result is expected_class
@pytest.mark.parametrize('test_url', (
'random.com',
'bad',
'https://www.google.com/',
'https://www.google.com',
'https://www.google.com/test',
'https://www.google.com/test/',
))
@pytest.mark.parametrize(
"test_url",
(
"random.com",
"bad",
"https://www.google.com/",
"https://www.google.com",
"https://www.google.com/test",
"https://www.google.com/test/",
),
)
def test_factory_lever_bad(test_url: str):
with pytest.raises(NotADownloadableLinkError):
DownloadFactory.pull_lever(test_url)
@pytest.mark.parametrize(('test_url', 'expected'), (
('www.test.com/test.png', 'test.com/test.png'),
('www.test.com/test.png?test_value=random', 'test.com/test.png'),
('https://youtube.com/watch?v=Gv8Wz74FjVA', 'youtube.com/watch'),
('https://i.imgur.com/BuzvZwb.gifv', 'i.imgur.com/BuzvZwb.gifv'),
))
@pytest.mark.parametrize(
("test_url", "expected"),
(
("www.test.com/test.png", "test.com/test.png"),
("www.test.com/test.png?test_value=random", "test.com/test.png"),
("https://youtube.com/watch?v=Gv8Wz74FjVA", "youtube.com/watch"),
("https://i.imgur.com/BuzvZwb.gifv", "i.imgur.com/BuzvZwb.gifv"),
),
)
def test_sanitise_url(test_url: str, expected: str):
result = DownloadFactory.sanitise_url(test_url)
assert result == expected
@pytest.mark.parametrize(('test_url', 'expected'), (
('www.example.com/test.asp', True),
('www.example.com/test.html', True),
('www.example.com/test.js', True),
('www.example.com/test.xhtml', True),
('www.example.com/test.mp4', False),
('www.example.com/test.png', False),
))
@pytest.mark.parametrize(
("test_url", "expected"),
(
("www.example.com/test.asp", True),
("www.example.com/test.html", True),
("www.example.com/test.js", True),
("www.example.com/test.xhtml", True),
("www.example.com/test.mp4", False),
("www.example.com/test.png", False),
),
)
def test_is_web_resource(test_url: str, expected: bool):
result = DownloadFactory.is_web_resource(test_url)
assert result == expected

View File

@@ -9,31 +9,38 @@ from bdfr.site_downloaders.erome import Erome
@pytest.mark.online
@pytest.mark.parametrize(('test_url', 'expected_urls'), (
('https://www.erome.com/a/vqtPuLXh', (
r'https://[a-z]\d+.erome.com/\d{3}/vqtPuLXh/KH2qBT99_480p.mp4',
)),
('https://www.erome.com/a/ORhX0FZz', (
r'https://[a-z]\d+.erome.com/\d{3}/ORhX0FZz/9IYQocM9_480p.mp4',
r'https://[a-z]\d+.erome.com/\d{3}/ORhX0FZz/9eEDc8xm_480p.mp4',
r'https://[a-z]\d+.erome.com/\d{3}/ORhX0FZz/EvApC7Rp_480p.mp4',
r'https://[a-z]\d+.erome.com/\d{3}/ORhX0FZz/LruobtMs_480p.mp4',
r'https://[a-z]\d+.erome.com/\d{3}/ORhX0FZz/TJNmSUU5_480p.mp4',
r'https://[a-z]\d+.erome.com/\d{3}/ORhX0FZz/X11Skh6Z_480p.mp4',
r'https://[a-z]\d+.erome.com/\d{3}/ORhX0FZz/bjlTkpn7_480p.mp4'
)),
))
@pytest.mark.parametrize(
("test_url", "expected_urls"),
(
("https://www.erome.com/a/vqtPuLXh", (r"https://[a-z]\d+.erome.com/\d{3}/vqtPuLXh/KH2qBT99_480p.mp4",)),
(
"https://www.erome.com/a/ORhX0FZz",
(
r"https://[a-z]\d+.erome.com/\d{3}/ORhX0FZz/9IYQocM9_480p.mp4",
r"https://[a-z]\d+.erome.com/\d{3}/ORhX0FZz/9eEDc8xm_480p.mp4",
r"https://[a-z]\d+.erome.com/\d{3}/ORhX0FZz/EvApC7Rp_480p.mp4",
r"https://[a-z]\d+.erome.com/\d{3}/ORhX0FZz/LruobtMs_480p.mp4",
r"https://[a-z]\d+.erome.com/\d{3}/ORhX0FZz/TJNmSUU5_480p.mp4",
r"https://[a-z]\d+.erome.com/\d{3}/ORhX0FZz/X11Skh6Z_480p.mp4",
r"https://[a-z]\d+.erome.com/\d{3}/ORhX0FZz/bjlTkpn7_480p.mp4",
),
),
),
)
def test_get_link(test_url: str, expected_urls: tuple[str]):
result = Erome. _get_links(test_url)
result = Erome._get_links(test_url)
assert all([any([re.match(p, r) for r in result]) for p in expected_urls])
@pytest.mark.online
@pytest.mark.slow
@pytest.mark.parametrize(('test_url', 'expected_hashes_len'), (
('https://www.erome.com/a/vqtPuLXh', 1),
('https://www.erome.com/a/4tP3KI6F', 1),
))
@pytest.mark.parametrize(
("test_url", "expected_hashes_len"),
(
("https://www.erome.com/a/vqtPuLXh", 1),
("https://www.erome.com/a/4tP3KI6F", 1),
),
)
def test_download_resource(test_url: str, expected_hashes_len: int):
# Can't compare hashes for this test, Erome doesn't return the exact same file from request to request so the hash
# will change back and forth randomly

View File

@@ -9,30 +9,39 @@ from bdfr.site_downloaders.gallery import Gallery
@pytest.mark.online
@pytest.mark.parametrize(('test_ids', 'expected'), (
([
{'media_id': '18nzv9ch0hn61'},
{'media_id': 'jqkizcch0hn61'},
{'media_id': 'k0fnqzbh0hn61'},
{'media_id': 'm3gamzbh0hn61'},
], {
'https://i.redd.it/18nzv9ch0hn61.jpg',
'https://i.redd.it/jqkizcch0hn61.jpg',
'https://i.redd.it/k0fnqzbh0hn61.jpg',
'https://i.redd.it/m3gamzbh0hn61.jpg'
}),
([
{'media_id': '04vxj25uqih61'},
{'media_id': '0fnx83kpqih61'},
{'media_id': '7zkmr1wqqih61'},
{'media_id': 'u37k5gxrqih61'},
], {
'https://i.redd.it/04vxj25uqih61.png',
'https://i.redd.it/0fnx83kpqih61.png',
'https://i.redd.it/7zkmr1wqqih61.png',
'https://i.redd.it/u37k5gxrqih61.png'
}),
))
@pytest.mark.parametrize(
("test_ids", "expected"),
(
(
[
{"media_id": "18nzv9ch0hn61"},
{"media_id": "jqkizcch0hn61"},
{"media_id": "k0fnqzbh0hn61"},
{"media_id": "m3gamzbh0hn61"},
],
{
"https://i.redd.it/18nzv9ch0hn61.jpg",
"https://i.redd.it/jqkizcch0hn61.jpg",
"https://i.redd.it/k0fnqzbh0hn61.jpg",
"https://i.redd.it/m3gamzbh0hn61.jpg",
},
),
(
[
{"media_id": "04vxj25uqih61"},
{"media_id": "0fnx83kpqih61"},
{"media_id": "7zkmr1wqqih61"},
{"media_id": "u37k5gxrqih61"},
],
{
"https://i.redd.it/04vxj25uqih61.png",
"https://i.redd.it/0fnx83kpqih61.png",
"https://i.redd.it/7zkmr1wqqih61.png",
"https://i.redd.it/u37k5gxrqih61.png",
},
),
),
)
def test_gallery_get_links(test_ids: list[dict], expected: set[str]):
results = Gallery._get_links(test_ids)
assert set(results) == expected
@@ -40,32 +49,47 @@ def test_gallery_get_links(test_ids: list[dict], expected: set[str]):
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_submission_id', 'expected_hashes'), (
('m6lvrh', {
'5c42b8341dd56eebef792e86f3981c6a',
'8f38d76da46f4057bf2773a778e725ca',
'f5776f8f90491c8b770b8e0a6bfa49b3',
'fa1a43c94da30026ad19a9813a0ed2c2',
}),
('ljyy27', {
'359c203ec81d0bc00e675f1023673238',
'79262fd46bce5bfa550d878a3b898be4',
'808c35267f44acb523ce03bfa5687404',
'ec8b65bdb7f1279c4b3af0ea2bbb30c3',
}),
('obkflw', {
'65163f685fb28c5b776e0e77122718be',
'2a337eb5b13c34d3ca3f51b5db7c13e9',
}),
('rb3ub6', { # patreon post
'748a976c6cedf7ea85b6f90e7cb685c7',
'839796d7745e88ced6355504e1f74508',
'bcdb740367d0f19f97a77e614b48a42d',
'0f230b8c4e5d103d35a773fab9814ec3',
'e5192d6cb4f84c4f4a658355310bf0f9',
'91cbe172cd8ccbcf049fcea4204eb979',
})
))
@pytest.mark.parametrize(
("test_submission_id", "expected_hashes"),
(
(
"m6lvrh",
{
"5c42b8341dd56eebef792e86f3981c6a",
"8f38d76da46f4057bf2773a778e725ca",
"f5776f8f90491c8b770b8e0a6bfa49b3",
"fa1a43c94da30026ad19a9813a0ed2c2",
},
),
(
"ljyy27",
{
"359c203ec81d0bc00e675f1023673238",
"79262fd46bce5bfa550d878a3b898be4",
"808c35267f44acb523ce03bfa5687404",
"ec8b65bdb7f1279c4b3af0ea2bbb30c3",
},
),
(
"obkflw",
{
"65163f685fb28c5b776e0e77122718be",
"2a337eb5b13c34d3ca3f51b5db7c13e9",
},
),
(
"rb3ub6",
{ # patreon post
"748a976c6cedf7ea85b6f90e7cb685c7",
"839796d7745e88ced6355504e1f74508",
"bcdb740367d0f19f97a77e614b48a42d",
"0f230b8c4e5d103d35a773fab9814ec3",
"e5192d6cb4f84c4f4a658355310bf0f9",
"91cbe172cd8ccbcf049fcea4204eb979",
},
),
),
)
def test_gallery_download(test_submission_id: str, expected_hashes: set[str], reddit_instance: praw.Reddit):
test_submission = reddit_instance.submission(id=test_submission_id)
gallery = Gallery(test_submission)
@@ -75,10 +99,13 @@ def test_gallery_download(test_submission_id: str, expected_hashes: set[str], re
assert set(hashes) == expected_hashes
@pytest.mark.parametrize('test_id', (
'n0pyzp',
'nxyahw',
))
@pytest.mark.parametrize(
"test_id",
(
"n0pyzp",
"nxyahw",
),
)
def test_gallery_download_raises_right_error(test_id: str, reddit_instance: praw.Reddit):
test_submission = reddit_instance.submission(id=test_id)
gallery = Gallery(test_submission)

View File

@@ -10,20 +10,26 @@ from bdfr.site_downloaders.gfycat import Gfycat
@pytest.mark.online
@pytest.mark.parametrize(('test_url', 'expected_url'), (
('https://gfycat.com/definitivecaninecrayfish', 'https://giant.gfycat.com/DefinitiveCanineCrayfish.mp4'),
('https://gfycat.com/dazzlingsilkyiguana', 'https://giant.gfycat.com/DazzlingSilkyIguana.mp4'),
))
@pytest.mark.parametrize(
("test_url", "expected_url"),
(
("https://gfycat.com/definitivecaninecrayfish", "https://giant.gfycat.com/DefinitiveCanineCrayfish.mp4"),
("https://gfycat.com/dazzlingsilkyiguana", "https://giant.gfycat.com/DazzlingSilkyIguana.mp4"),
),
)
def test_get_link(test_url: str, expected_url: str):
result = Gfycat._get_link(test_url)
assert result.pop() == expected_url
@pytest.mark.online
@pytest.mark.parametrize(('test_url', 'expected_hash'), (
('https://gfycat.com/definitivecaninecrayfish', '48f9bd4dbec1556d7838885612b13b39'),
('https://gfycat.com/dazzlingsilkyiguana', '808941b48fc1e28713d36dd7ed9dc648'),
))
@pytest.mark.parametrize(
("test_url", "expected_hash"),
(
("https://gfycat.com/definitivecaninecrayfish", "48f9bd4dbec1556d7838885612b13b39"),
("https://gfycat.com/dazzlingsilkyiguana", "808941b48fc1e28713d36dd7ed9dc648"),
),
)
def test_download_resource(test_url: str, expected_hash: str):
mock_submission = Mock()
mock_submission.url = test_url

View File

@@ -11,166 +11,167 @@ from bdfr.site_downloaders.imgur import Imgur
@pytest.mark.online
@pytest.mark.parametrize(('test_url', 'expected_gen_dict', 'expected_image_dict'), (
@pytest.mark.parametrize(
("test_url", "expected_gen_dict", "expected_image_dict"),
(
'https://imgur.com/a/xWZsDDP',
{'num_images': '1', 'id': 'xWZsDDP', 'hash': 'xWZsDDP'},
[
{'hash': 'ypa8YfS', 'title': '', 'ext': '.png', 'animated': False}
]
(
"https://imgur.com/a/xWZsDDP",
{"num_images": "1", "id": "xWZsDDP", "hash": "xWZsDDP"},
[{"hash": "ypa8YfS", "title": "", "ext": ".png", "animated": False}],
),
(
"https://imgur.com/gallery/IjJJdlC",
{"num_images": 1, "id": 384898055, "hash": "IjJJdlC"},
[
{
"hash": "CbbScDt",
"description": "watch when he gets it",
"ext": ".gif",
"animated": True,
"has_sound": False,
}
],
),
(
"https://imgur.com/a/dcc84Gt",
{"num_images": "4", "id": "dcc84Gt", "hash": "dcc84Gt"},
[
{"hash": "ylx0Kle", "ext": ".jpg", "title": ""},
{"hash": "TdYfKbK", "ext": ".jpg", "title": ""},
{"hash": "pCxGbe8", "ext": ".jpg", "title": ""},
{"hash": "TSAkikk", "ext": ".jpg", "title": ""},
],
),
(
"https://m.imgur.com/a/py3RW0j",
{
"num_images": "1",
"id": "py3RW0j",
"hash": "py3RW0j",
},
[{"hash": "K24eQmK", "has_sound": False, "ext": ".jpg"}],
),
),
(
'https://imgur.com/gallery/IjJJdlC',
{'num_images': 1, 'id': 384898055, 'hash': 'IjJJdlC'},
[
{'hash': 'CbbScDt',
'description': 'watch when he gets it',
'ext': '.gif',
'animated': True,
'has_sound': False
}
],
),
(
'https://imgur.com/a/dcc84Gt',
{'num_images': '4', 'id': 'dcc84Gt', 'hash': 'dcc84Gt'},
[
{'hash': 'ylx0Kle', 'ext': '.jpg', 'title': ''},
{'hash': 'TdYfKbK', 'ext': '.jpg', 'title': ''},
{'hash': 'pCxGbe8', 'ext': '.jpg', 'title': ''},
{'hash': 'TSAkikk', 'ext': '.jpg', 'title': ''},
]
),
(
'https://m.imgur.com/a/py3RW0j',
{'num_images': '1', 'id': 'py3RW0j', 'hash': 'py3RW0j', },
[
{'hash': 'K24eQmK', 'has_sound': False, 'ext': '.jpg'}
],
),
))
)
def test_get_data_album(test_url: str, expected_gen_dict: dict, expected_image_dict: list[dict]):
result = Imgur._get_data(test_url)
assert all([result.get(key) == expected_gen_dict[key] for key in expected_gen_dict.keys()])
# Check if all the keys from the test dict are correct in at least one of the album entries
assert any([all([image.get(key) == image_dict[key] for key in image_dict.keys()])
for image_dict in expected_image_dict for image in result['album_images']['images']])
assert any(
[
all([image.get(key) == image_dict[key] for key in image_dict.keys()])
for image_dict in expected_image_dict
for image in result["album_images"]["images"]
]
)
@pytest.mark.online
@pytest.mark.parametrize(('test_url', 'expected_image_dict'), (
@pytest.mark.parametrize(
("test_url", "expected_image_dict"),
(
'https://i.imgur.com/dLk3FGY.gifv',
{'hash': 'dLk3FGY', 'title': '', 'ext': '.mp4', 'animated': True}
("https://i.imgur.com/dLk3FGY.gifv", {"hash": "dLk3FGY", "title": "", "ext": ".mp4", "animated": True}),
(
"https://imgur.com/65FqTpT.gifv",
{"hash": "65FqTpT", "title": "", "description": "", "animated": True, "mimetype": "video/mp4"},
),
),
(
'https://imgur.com/65FqTpT.gifv',
{
'hash': '65FqTpT',
'title': '',
'description': '',
'animated': True,
'mimetype': 'video/mp4'
},
),
))
)
def test_get_data_gif(test_url: str, expected_image_dict: dict):
result = Imgur._get_data(test_url)
assert all([result.get(key) == expected_image_dict[key] for key in expected_image_dict.keys()])
@pytest.mark.parametrize('test_extension', (
'.gif',
'.png',
'.jpg',
'.mp4'
))
@pytest.mark.parametrize("test_extension", (".gif", ".png", ".jpg", ".mp4"))
def test_imgur_extension_validation_good(test_extension: str):
result = Imgur._validate_extension(test_extension)
assert result == test_extension
@pytest.mark.parametrize('test_extension', (
'.jpeg',
'bad',
'.avi',
'.test',
'.flac',
))
@pytest.mark.parametrize(
"test_extension",
(
".jpeg",
"bad",
".avi",
".test",
".flac",
),
)
def test_imgur_extension_validation_bad(test_extension: str):
with pytest.raises(SiteDownloaderError):
Imgur._validate_extension(test_extension)
@pytest.mark.online
@pytest.mark.parametrize(('test_url', 'expected_hashes'), (
@pytest.mark.parametrize(
("test_url", "expected_hashes"),
(
'https://imgur.com/a/xWZsDDP',
('f551d6e6b0fef2ce909767338612e31b',)
),
(
'https://imgur.com/gallery/IjJJdlC',
('740b006cf9ec9d6f734b6e8f5130bdab',),
),
(
'https://imgur.com/a/dcc84Gt',
("https://imgur.com/a/xWZsDDP", ("f551d6e6b0fef2ce909767338612e31b",)),
(
'cf1158e1de5c3c8993461383b96610cf',
'28d6b791a2daef8aa363bf5a3198535d',
'248ef8f2a6d03eeb2a80d0123dbaf9b6',
'029c475ce01b58fdf1269d8771d33913',
"https://imgur.com/gallery/IjJJdlC",
("740b006cf9ec9d6f734b6e8f5130bdab",),
),
(
"https://imgur.com/a/dcc84Gt",
(
"cf1158e1de5c3c8993461383b96610cf",
"28d6b791a2daef8aa363bf5a3198535d",
"248ef8f2a6d03eeb2a80d0123dbaf9b6",
"029c475ce01b58fdf1269d8771d33913",
),
),
(
"https://imgur.com/a/eemHCCK",
(
"9cb757fd8f055e7ef7aa88addc9d9fa5",
"b6cb6c918e2544e96fb7c07d828774b5",
"fb6c913d721c0bbb96aa65d7f560d385",
),
),
(
"https://i.imgur.com/lFJai6i.gifv",
("01a6e79a30bec0e644e5da12365d5071",),
),
(
"https://i.imgur.com/ywSyILa.gifv?",
("56d4afc32d2966017c38d98568709b45",),
),
(
"https://imgur.com/ubYwpbk.GIFV",
("d4a774aac1667783f9ed3a1bd02fac0c",),
),
(
"https://i.imgur.com/j1CNCZY.gifv",
("58e7e6d972058c18b7ecde910ca147e3",),
),
(
"https://i.imgur.com/uTvtQsw.gifv",
("46c86533aa60fc0e09f2a758513e3ac2",),
),
(
"https://i.imgur.com/OGeVuAe.giff",
("77389679084d381336f168538793f218",),
),
(
"https://i.imgur.com/OGeVuAe.gift",
("77389679084d381336f168538793f218",),
),
(
"https://i.imgur.com/3SKrQfK.jpg?1",
("aa299e181b268578979cad176d1bd1d0",),
),
(
"https://i.imgur.com/cbivYRW.jpg?3",
("7ec6ceef5380cb163a1d498c359c51fd",),
),
(
"http://i.imgur.com/s9uXxlq.jpg?5.jpg",
("338de3c23ee21af056b3a7c154e2478f",),
),
),
(
'https://imgur.com/a/eemHCCK',
(
'9cb757fd8f055e7ef7aa88addc9d9fa5',
'b6cb6c918e2544e96fb7c07d828774b5',
'fb6c913d721c0bbb96aa65d7f560d385',
),
),
(
'https://i.imgur.com/lFJai6i.gifv',
('01a6e79a30bec0e644e5da12365d5071',),
),
(
'https://i.imgur.com/ywSyILa.gifv?',
('56d4afc32d2966017c38d98568709b45',),
),
(
'https://imgur.com/ubYwpbk.GIFV',
('d4a774aac1667783f9ed3a1bd02fac0c',),
),
(
'https://i.imgur.com/j1CNCZY.gifv',
('58e7e6d972058c18b7ecde910ca147e3',),
),
(
'https://i.imgur.com/uTvtQsw.gifv',
('46c86533aa60fc0e09f2a758513e3ac2',),
),
(
'https://i.imgur.com/OGeVuAe.giff',
('77389679084d381336f168538793f218',),
),
(
'https://i.imgur.com/OGeVuAe.gift',
('77389679084d381336f168538793f218',),
),
(
'https://i.imgur.com/3SKrQfK.jpg?1',
('aa299e181b268578979cad176d1bd1d0',),
),
(
'https://i.imgur.com/cbivYRW.jpg?3',
('7ec6ceef5380cb163a1d498c359c51fd',),
),
(
'http://i.imgur.com/s9uXxlq.jpg?5.jpg',
('338de3c23ee21af056b3a7c154e2478f',),
),
))
)
def test_find_resources(test_url: str, expected_hashes: list[str]):
mock_download = Mock()
mock_download.url = test_url

View File

@@ -12,9 +12,10 @@ from bdfr.site_downloaders.pornhub import PornHub
@pytest.mark.online
@pytest.mark.slow
@pytest.mark.parametrize(('test_url', 'expected_hash'), (
('https://www.pornhub.com/view_video.php?viewkey=ph6074c59798497', 'ad52a0f4fce8f99df0abed17de1d04c7'),
))
@pytest.mark.parametrize(
("test_url", "expected_hash"),
(("https://www.pornhub.com/view_video.php?viewkey=ph6074c59798497", "ad52a0f4fce8f99df0abed17de1d04c7"),),
)
def test_hash_resources_good(test_url: str, expected_hash: str):
test_submission = MagicMock()
test_submission.url = test_url
@@ -27,9 +28,7 @@ def test_hash_resources_good(test_url: str, expected_hash: str):
@pytest.mark.online
@pytest.mark.parametrize('test_url', (
'https://www.pornhub.com/view_video.php?viewkey=ph5ede121f0d3f8',
))
@pytest.mark.parametrize("test_url", ("https://www.pornhub.com/view_video.php?viewkey=ph5ede121f0d3f8",))
def test_find_resources_good(test_url: str):
test_submission = MagicMock()
test_submission.url = test_url

View File

@@ -1,8 +1,8 @@
#!/usr/bin/env python3
# coding=utf-8
from unittest.mock import Mock
import re
from unittest.mock import Mock
import pytest
@@ -11,45 +11,55 @@ from bdfr.site_downloaders.redgifs import Redgifs
@pytest.mark.online
@pytest.mark.parametrize(('test_url', 'expected'), (
('https://redgifs.com/watch/frighteningvictorioussalamander',
{'FrighteningVictoriousSalamander.mp4'}),
('https://redgifs.com/watch/springgreendecisivetaruca',
{'SpringgreenDecisiveTaruca.mp4'}),
('https://www.redgifs.com/watch/palegoldenrodrawhalibut',
{'PalegoldenrodRawHalibut.mp4'}),
('https://redgifs.com/watch/hollowintentsnowyowl',
{'HollowIntentSnowyowl-large.jpg'}),
('https://www.redgifs.com/watch/lustrousstickywaxwing',
{'EntireEnchantingHypsilophodon-large.jpg',
'FancyMagnificentAdamsstaghornedbeetle-large.jpg',
'LustrousStickyWaxwing-large.jpg',
'ParchedWindyArmyworm-large.jpg',
'ThunderousColorlessErmine-large.jpg',
'UnripeUnkemptWoodpecker-large.jpg'}),
))
@pytest.mark.parametrize(
("test_url", "expected"),
(
("https://redgifs.com/watch/frighteningvictorioussalamander", {"FrighteningVictoriousSalamander.mp4"}),
("https://redgifs.com/watch/springgreendecisivetaruca", {"SpringgreenDecisiveTaruca.mp4"}),
("https://www.redgifs.com/watch/palegoldenrodrawhalibut", {"PalegoldenrodRawHalibut.mp4"}),
("https://redgifs.com/watch/hollowintentsnowyowl", {"HollowIntentSnowyowl-large.jpg"}),
(
"https://www.redgifs.com/watch/lustrousstickywaxwing",
{
"EntireEnchantingHypsilophodon-large.jpg",
"FancyMagnificentAdamsstaghornedbeetle-large.jpg",
"LustrousStickyWaxwing-large.jpg",
"ParchedWindyArmyworm-large.jpg",
"ThunderousColorlessErmine-large.jpg",
"UnripeUnkemptWoodpecker-large.jpg",
},
),
),
)
def test_get_link(test_url: str, expected: set[str]):
result = Redgifs._get_link(test_url)
result = list(result)
patterns = [r'https://thumbs\d\.redgifs\.com/' + e + r'.*' for e in expected]
patterns = [r"https://thumbs\d\.redgifs\.com/" + e + r".*" for e in expected]
assert all([re.match(p, r) for p in patterns] for r in result)
@pytest.mark.online
@pytest.mark.parametrize(('test_url', 'expected_hashes'), (
('https://redgifs.com/watch/frighteningvictorioussalamander', {'4007c35d9e1f4b67091b5f12cffda00a'}),
('https://redgifs.com/watch/springgreendecisivetaruca', {'8dac487ac49a1f18cc1b4dabe23f0869'}),
('https://redgifs.com/watch/leafysaltydungbeetle', {'076792c660b9c024c0471ef4759af8bd'}),
('https://www.redgifs.com/watch/palegoldenrodrawhalibut', {'46d5aa77fe80c6407de1ecc92801c10e'}),
('https://redgifs.com/watch/hollowintentsnowyowl', {'5ee51fa15e0a58e98f11dea6a6cca771'}),
('https://www.redgifs.com/watch/lustrousstickywaxwing',
{'b461e55664f07bed8d2f41d8586728fa',
'30ba079a8ed7d7adf17929dc3064c10f',
'0d4f149d170d29fc2f015c1121bab18b',
'53987d99cfd77fd65b5fdade3718f9f1',
'fb2e7d972846b83bf4016447d3060d60',
'44fb28f72ec9a5cca63fa4369ab4f672'}),
))
@pytest.mark.parametrize(
("test_url", "expected_hashes"),
(
("https://redgifs.com/watch/frighteningvictorioussalamander", {"4007c35d9e1f4b67091b5f12cffda00a"}),
("https://redgifs.com/watch/springgreendecisivetaruca", {"8dac487ac49a1f18cc1b4dabe23f0869"}),
("https://redgifs.com/watch/leafysaltydungbeetle", {"076792c660b9c024c0471ef4759af8bd"}),
("https://www.redgifs.com/watch/palegoldenrodrawhalibut", {"46d5aa77fe80c6407de1ecc92801c10e"}),
("https://redgifs.com/watch/hollowintentsnowyowl", {"5ee51fa15e0a58e98f11dea6a6cca771"}),
(
"https://www.redgifs.com/watch/lustrousstickywaxwing",
{
"b461e55664f07bed8d2f41d8586728fa",
"30ba079a8ed7d7adf17929dc3064c10f",
"0d4f149d170d29fc2f015c1121bab18b",
"53987d99cfd77fd65b5fdade3718f9f1",
"fb2e7d972846b83bf4016447d3060d60",
"44fb28f72ec9a5cca63fa4369ab4f672",
},
),
),
)
def test_download_resource(test_url: str, expected_hashes: set[str]):
mock_submission = Mock()
mock_submission.url = test_url
@@ -62,18 +72,30 @@ def test_download_resource(test_url: str, expected_hashes: set[str]):
@pytest.mark.online
@pytest.mark.parametrize(('test_url', 'expected_link', 'expected_hash'), (
('https://redgifs.com/watch/flippantmemorablebaiji', {'FlippantMemorableBaiji-mobile.mp4'},
{'41a5fb4865367ede9f65fc78736f497a'}),
('https://redgifs.com/watch/thirstyunfortunatewaterdragons', {'thirstyunfortunatewaterdragons-mobile.mp4'},
{'1a51dad8fedb594bdd84f027b3cbe8af'}),
('https://redgifs.com/watch/conventionalplainxenopterygii', {'conventionalplainxenopterygii-mobile.mp4'},
{'2e1786b3337da85b80b050e2c289daa4'})
))
@pytest.mark.parametrize(
("test_url", "expected_link", "expected_hash"),
(
(
"https://redgifs.com/watch/flippantmemorablebaiji",
{"FlippantMemorableBaiji-mobile.mp4"},
{"41a5fb4865367ede9f65fc78736f497a"},
),
(
"https://redgifs.com/watch/thirstyunfortunatewaterdragons",
{"thirstyunfortunatewaterdragons-mobile.mp4"},
{"1a51dad8fedb594bdd84f027b3cbe8af"},
),
(
"https://redgifs.com/watch/conventionalplainxenopterygii",
{"conventionalplainxenopterygii-mobile.mp4"},
{"2e1786b3337da85b80b050e2c289daa4"},
),
),
)
def test_hd_soft_fail(test_url: str, expected_link: set[str], expected_hash: set[str]):
link = Redgifs._get_link(test_url)
link = list(link)
patterns = [r'https://thumbs\d\.redgifs\.com/' + e + r'.*' for e in expected_link]
patterns = [r"https://thumbs\d\.redgifs\.com/" + e + r".*" for e in expected_link]
assert all([re.match(p, r) for p in patterns] for r in link)
mock_submission = Mock()
mock_submission.url = test_url

View File

@@ -10,11 +10,14 @@ from bdfr.site_downloaders.self_post import SelfPost
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_submission_id', 'expected_hash'), (
('ltmivt', '7d2c9e4e989e5cf2dca2e55a06b1c4f6'),
('ltoaan', '221606386b614d6780c2585a59bd333f'),
('d3sc8o', 'c1ff2b6bd3f6b91381dcd18dfc4ca35f'),
))
@pytest.mark.parametrize(
("test_submission_id", "expected_hash"),
(
("ltmivt", "7d2c9e4e989e5cf2dca2e55a06b1c4f6"),
("ltoaan", "221606386b614d6780c2585a59bd333f"),
("d3sc8o", "c1ff2b6bd3f6b91381dcd18dfc4ca35f"),
),
)
def test_find_resource(test_submission_id: str, expected_hash: str, reddit_instance: praw.Reddit):
submission = reddit_instance.submission(id=test_submission_id)
downloader = SelfPost(submission)

View File

@@ -8,55 +8,83 @@ from bdfr.resource import Resource
from bdfr.site_downloaders.vidble import Vidble
@pytest.mark.parametrize(('test_url', 'expected'), (
('/RDFbznUvcN_med.jpg', '/RDFbznUvcN.jpg'),
))
@pytest.mark.parametrize(("test_url", "expected"), (("/RDFbznUvcN_med.jpg", "/RDFbznUvcN.jpg"),))
def test_change_med_url(test_url: str, expected: str):
result = Vidble.change_med_url(test_url)
assert result == expected
@pytest.mark.online
@pytest.mark.parametrize(('test_url', 'expected'), (
('https://www.vidble.com/show/UxsvAssYe5', {
'https://www.vidble.com/UxsvAssYe5.gif',
}),
('https://vidble.com/show/RDFbznUvcN', {
'https://www.vidble.com/RDFbznUvcN.jpg',
}),
('https://vidble.com/album/h0jTLs6B', {
'https://www.vidble.com/XG4eAoJ5JZ.jpg',
'https://www.vidble.com/IqF5UdH6Uq.jpg',
'https://www.vidble.com/VWuNsnLJMD.jpg',
'https://www.vidble.com/sMmM8O650W.jpg',
}),
('https://www.vidble.com/pHuwWkOcEb', {
'https://www.vidble.com/pHuwWkOcEb.jpg',
}),
))
@pytest.mark.parametrize(
("test_url", "expected"),
(
(
"https://www.vidble.com/show/UxsvAssYe5",
{
"https://www.vidble.com/UxsvAssYe5.gif",
},
),
(
"https://vidble.com/show/RDFbznUvcN",
{
"https://www.vidble.com/RDFbznUvcN.jpg",
},
),
(
"https://vidble.com/album/h0jTLs6B",
{
"https://www.vidble.com/XG4eAoJ5JZ.jpg",
"https://www.vidble.com/IqF5UdH6Uq.jpg",
"https://www.vidble.com/VWuNsnLJMD.jpg",
"https://www.vidble.com/sMmM8O650W.jpg",
},
),
(
"https://www.vidble.com/pHuwWkOcEb",
{
"https://www.vidble.com/pHuwWkOcEb.jpg",
},
),
),
)
def test_get_links(test_url: str, expected: set[str]):
results = Vidble.get_links(test_url)
assert results == expected
@pytest.mark.online
@pytest.mark.parametrize(('test_url', 'expected_hashes'), (
('https://www.vidble.com/show/UxsvAssYe5', {
'0ef2f8e0e0b45936d2fb3e6fbdf67e28',
}),
('https://vidble.com/show/RDFbznUvcN', {
'c2dd30a71e32369c50eed86f86efff58',
}),
('https://vidble.com/album/h0jTLs6B', {
'3b3cba02e01c91f9858a95240b942c71',
'dd6ecf5fc9e936f9fb614eb6a0537f99',
'b31a942cd8cdda218ed547bbc04c3a27',
'6f77c570b451eef4222804bd52267481',
}),
('https://www.vidble.com/pHuwWkOcEb', {
'585f486dd0b2f23a57bddbd5bf185bc7',
}),
))
@pytest.mark.parametrize(
("test_url", "expected_hashes"),
(
(
"https://www.vidble.com/show/UxsvAssYe5",
{
"0ef2f8e0e0b45936d2fb3e6fbdf67e28",
},
),
(
"https://vidble.com/show/RDFbznUvcN",
{
"c2dd30a71e32369c50eed86f86efff58",
},
),
(
"https://vidble.com/album/h0jTLs6B",
{
"3b3cba02e01c91f9858a95240b942c71",
"dd6ecf5fc9e936f9fb614eb6a0537f99",
"b31a942cd8cdda218ed547bbc04c3a27",
"6f77c570b451eef4222804bd52267481",
},
),
(
"https://www.vidble.com/pHuwWkOcEb",
{
"585f486dd0b2f23a57bddbd5bf185bc7",
},
),
),
)
def test_find_resources(test_url: str, expected_hashes: set[str]):
mock_download = Mock()
mock_download.url = test_url

View File

@@ -12,9 +12,10 @@ from bdfr.site_downloaders.vreddit import VReddit
@pytest.mark.online
@pytest.mark.slow
@pytest.mark.parametrize(('test_url', 'expected_hash'), (
('https://reddit.com/r/Unexpected/comments/z4xsuj/omg_thats_so_cute/', '1ffab5e5c0cc96db18108e4f37e8ca7f'),
))
@pytest.mark.parametrize(
("test_url", "expected_hash"),
(("https://reddit.com/r/Unexpected/comments/z4xsuj/omg_thats_so_cute/", "1ffab5e5c0cc96db18108e4f37e8ca7f"),),
)
def test_find_resources_good(test_url: str, expected_hash: str):
test_submission = MagicMock()
test_submission.url = test_url
@@ -27,10 +28,13 @@ def test_find_resources_good(test_url: str, expected_hash: str):
@pytest.mark.online
@pytest.mark.parametrize('test_url', (
'https://www.polygon.com/disney-plus/2020/5/14/21249881/gargoyles-animated-series-disney-plus-greg-weisman'
'-interview-oj-simpson-goliath-chronicles',
))
@pytest.mark.parametrize(
"test_url",
(
"https://www.polygon.com/disney-plus/2020/5/14/21249881/gargoyles-animated-series-disney-plus-greg-weisman"
"-interview-oj-simpson-goliath-chronicles",
),
)
def test_find_resources_bad(test_url: str):
test_submission = MagicMock()
test_submission.url = test_url

View File

@@ -12,10 +12,13 @@ from bdfr.site_downloaders.youtube import Youtube
@pytest.mark.online
@pytest.mark.slow
@pytest.mark.parametrize(('test_url', 'expected_hash'), (
('https://www.youtube.com/watch?v=uSm2VDgRIUs', '2d60b54582df5b95ec72bb00b580d2ff'),
('https://www.youtube.com/watch?v=GcI7nxQj7HA', '5db0fc92a0a7fb9ac91e63505eea9cf0'),
))
@pytest.mark.parametrize(
("test_url", "expected_hash"),
(
("https://www.youtube.com/watch?v=uSm2VDgRIUs", "2d60b54582df5b95ec72bb00b580d2ff"),
("https://www.youtube.com/watch?v=GcI7nxQj7HA", "5db0fc92a0a7fb9ac91e63505eea9cf0"),
),
)
def test_find_resources_good(test_url: str, expected_hash: str):
test_submission = MagicMock()
test_submission.url = test_url
@@ -28,10 +31,13 @@ def test_find_resources_good(test_url: str, expected_hash: str):
@pytest.mark.online
@pytest.mark.parametrize('test_url', (
'https://www.polygon.com/disney-plus/2020/5/14/21249881/gargoyles-animated-series-disney-plus-greg-weisman'
'-interview-oj-simpson-goliath-chronicles',
))
@pytest.mark.parametrize(
"test_url",
(
"https://www.polygon.com/disney-plus/2020/5/14/21249881/gargoyles-animated-series-disney-plus-greg-weisman"
"-interview-oj-simpson-goliath-chronicles",
),
)
def test_find_resources_bad(test_url: str):
test_submission = MagicMock()
test_submission.url = test_url

View File

@@ -12,15 +12,18 @@ from bdfr.archiver import Archiver
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_submission_id', 'test_format'), (
('m3reby', 'xml'),
('m3reby', 'json'),
('m3reby', 'yaml'),
))
@pytest.mark.parametrize(
("test_submission_id", "test_format"),
(
("m3reby", "xml"),
("m3reby", "json"),
("m3reby", "yaml"),
),
)
def test_write_submission_json(test_submission_id: str, tmp_path: Path, test_format: str, reddit_instance: praw.Reddit):
archiver_mock = MagicMock()
archiver_mock.args.format = test_format
test_path = Path(tmp_path, 'test')
test_path = Path(tmp_path, "test")
test_submission = reddit_instance.submission(id=test_submission_id)
archiver_mock.file_name_formatter.format_path.return_value = test_path
Archiver.write_entry(archiver_mock, test_submission)

View File

@@ -8,13 +8,16 @@ import pytest
from bdfr.configuration import Configuration
@pytest.mark.parametrize('arg_dict', (
{'directory': 'test_dir'},
{
'directory': 'test_dir',
'no_dupes': True,
},
))
@pytest.mark.parametrize(
"arg_dict",
(
{"directory": "test_dir"},
{
"directory": "test_dir",
"no_dupes": True,
},
),
)
def test_process_click_context(arg_dict: dict):
test_config = Configuration()
test_context = MagicMock()
@@ -25,9 +28,9 @@ def test_process_click_context(arg_dict: dict):
def test_yaml_file_read():
file = './tests/yaml_test_configuration.yaml'
file = "./tests/yaml_test_configuration.yaml"
test_config = Configuration()
test_config.parse_yaml_options(file)
assert test_config.subreddit == ['EarthPorn', 'TwoXChromosomes', 'Mindustry']
assert test_config.sort == 'new'
assert test_config.subreddit == ["EarthPorn", "TwoXChromosomes", "Mindustry"]
assert test_config.sort == "new"
assert test_config.limit == 10

View File

@@ -20,7 +20,7 @@ from bdfr.site_authenticator import SiteAuthenticator
@pytest.fixture()
def args() -> Configuration:
args = Configuration()
args.time_format = 'ISO'
args.time_format = "ISO"
return args
@@ -30,7 +30,8 @@ def downloader_mock(args: Configuration):
downloader_mock.args = args
downloader_mock.sanitise_subreddit_name = RedditConnector.sanitise_subreddit_name
downloader_mock.create_filtered_listing_generator = lambda x: RedditConnector.create_filtered_listing_generator(
downloader_mock, x)
downloader_mock, x
)
downloader_mock.split_args_input = RedditConnector.split_args_input
downloader_mock.master_hash_list = {}
return downloader_mock
@@ -55,16 +56,22 @@ def assert_all_results_are_submissions_or_comments(result_limit: int, results: l
def test_determine_directories(tmp_path: Path, downloader_mock: MagicMock):
downloader_mock.args.directory = tmp_path / 'test'
downloader_mock.args.directory = tmp_path / "test"
downloader_mock.config_directories.user_config_dir = tmp_path
RedditConnector.determine_directories(downloader_mock)
assert Path(tmp_path / 'test').exists()
assert Path(tmp_path / "test").exists()
@pytest.mark.parametrize(('skip_extensions', 'skip_domains'), (
([], []),
(['.test'], ['test.com'],),
))
@pytest.mark.parametrize(
("skip_extensions", "skip_domains"),
(
([], []),
(
[".test"],
["test.com"],
),
),
)
def test_create_download_filter(skip_extensions: list[str], skip_domains: list[str], downloader_mock: MagicMock):
downloader_mock.args.skip = skip_extensions
downloader_mock.args.skip_domain = skip_domains
@@ -75,14 +82,17 @@ def test_create_download_filter(skip_extensions: list[str], skip_domains: list[s
assert result.excluded_extensions == skip_extensions
@pytest.mark.parametrize(('test_time', 'expected'), (
('all', 'all'),
('hour', 'hour'),
('day', 'day'),
('week', 'week'),
('random', 'all'),
('', 'all'),
))
@pytest.mark.parametrize(
("test_time", "expected"),
(
("all", "all"),
("hour", "hour"),
("day", "day"),
("week", "week"),
("random", "all"),
("", "all"),
),
)
def test_create_time_filter(test_time: str, expected: str, downloader_mock: MagicMock):
downloader_mock.args.time = test_time
result = RedditConnector.create_time_filter(downloader_mock)
@@ -91,12 +101,15 @@ def test_create_time_filter(test_time: str, expected: str, downloader_mock: Magi
assert result.name.lower() == expected
@pytest.mark.parametrize(('test_sort', 'expected'), (
('', 'hot'),
('hot', 'hot'),
('controversial', 'controversial'),
('new', 'new'),
))
@pytest.mark.parametrize(
("test_sort", "expected"),
(
("", "hot"),
("hot", "hot"),
("controversial", "controversial"),
("new", "new"),
),
)
def test_create_sort_filter(test_sort: str, expected: str, downloader_mock: MagicMock):
downloader_mock.args.sort = test_sort
result = RedditConnector.create_sort_filter(downloader_mock)
@@ -105,13 +118,16 @@ def test_create_sort_filter(test_sort: str, expected: str, downloader_mock: Magi
assert result.name.lower() == expected
@pytest.mark.parametrize(('test_file_scheme', 'test_folder_scheme'), (
('{POSTID}', '{SUBREDDIT}'),
('{REDDITOR}_{TITLE}_{POSTID}', '{SUBREDDIT}'),
('{POSTID}', 'test'),
('{POSTID}', ''),
('{POSTID}', '{SUBREDDIT}/{REDDITOR}'),
))
@pytest.mark.parametrize(
("test_file_scheme", "test_folder_scheme"),
(
("{POSTID}", "{SUBREDDIT}"),
("{REDDITOR}_{TITLE}_{POSTID}", "{SUBREDDIT}"),
("{POSTID}", "test"),
("{POSTID}", ""),
("{POSTID}", "{SUBREDDIT}/{REDDITOR}"),
),
)
def test_create_file_name_formatter(test_file_scheme: str, test_folder_scheme: str, downloader_mock: MagicMock):
downloader_mock.args.file_scheme = test_file_scheme
downloader_mock.args.folder_scheme = test_folder_scheme
@@ -119,14 +135,17 @@ def test_create_file_name_formatter(test_file_scheme: str, test_folder_scheme: s
assert isinstance(result, FileNameFormatter)
assert result.file_format_string == test_file_scheme
assert result.directory_format_string == test_folder_scheme.split('/')
assert result.directory_format_string == test_folder_scheme.split("/")
@pytest.mark.parametrize(('test_file_scheme', 'test_folder_scheme'), (
('', ''),
('', '{SUBREDDIT}'),
('test', '{SUBREDDIT}'),
))
@pytest.mark.parametrize(
("test_file_scheme", "test_folder_scheme"),
(
("", ""),
("", "{SUBREDDIT}"),
("test", "{SUBREDDIT}"),
),
)
def test_create_file_name_formatter_bad(test_file_scheme: str, test_folder_scheme: str, downloader_mock: MagicMock):
downloader_mock.args.file_scheme = test_file_scheme
downloader_mock.args.folder_scheme = test_folder_scheme
@@ -141,15 +160,17 @@ def test_create_authenticator(downloader_mock: MagicMock):
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize('test_submission_ids', (
('lvpf4l',),
('lvpf4l', 'lvqnsn'),
('lvpf4l', 'lvqnsn', 'lvl9kd'),
))
@pytest.mark.parametrize(
"test_submission_ids",
(
("lvpf4l",),
("lvpf4l", "lvqnsn"),
("lvpf4l", "lvqnsn", "lvl9kd"),
),
)
def test_get_submissions_from_link(
test_submission_ids: list[str],
reddit_instance: praw.Reddit,
downloader_mock: MagicMock):
test_submission_ids: list[str], reddit_instance: praw.Reddit, downloader_mock: MagicMock
):
downloader_mock.args.link = test_submission_ids
downloader_mock.reddit_instance = reddit_instance
results = RedditConnector.get_submissions_from_link(downloader_mock)
@@ -159,25 +180,28 @@ def test_get_submissions_from_link(
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_subreddits', 'limit', 'sort_type', 'time_filter', 'max_expected_len'), (
(('Futurology',), 10, 'hot', 'all', 10),
(('Futurology', 'Mindustry, Python'), 10, 'hot', 'all', 30),
(('Futurology',), 20, 'hot', 'all', 20),
(('Futurology', 'Python'), 10, 'hot', 'all', 20),
(('Futurology',), 100, 'hot', 'all', 100),
(('Futurology',), 0, 'hot', 'all', 0),
(('Futurology',), 10, 'top', 'all', 10),
(('Futurology',), 10, 'top', 'week', 10),
(('Futurology',), 10, 'hot', 'week', 10),
))
@pytest.mark.parametrize(
("test_subreddits", "limit", "sort_type", "time_filter", "max_expected_len"),
(
(("Futurology",), 10, "hot", "all", 10),
(("Futurology", "Mindustry, Python"), 10, "hot", "all", 30),
(("Futurology",), 20, "hot", "all", 20),
(("Futurology", "Python"), 10, "hot", "all", 20),
(("Futurology",), 100, "hot", "all", 100),
(("Futurology",), 0, "hot", "all", 0),
(("Futurology",), 10, "top", "all", 10),
(("Futurology",), 10, "top", "week", 10),
(("Futurology",), 10, "hot", "week", 10),
),
)
def test_get_subreddit_normal(
test_subreddits: list[str],
limit: int,
sort_type: str,
time_filter: str,
max_expected_len: int,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
test_subreddits: list[str],
limit: int,
sort_type: str,
time_filter: str,
max_expected_len: int,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
):
downloader_mock.args.limit = limit
downloader_mock.args.sort = sort_type
@@ -197,26 +221,29 @@ def test_get_subreddit_normal(
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_time', 'test_delta'), (
('hour', timedelta(hours=1)),
('day', timedelta(days=1)),
('week', timedelta(days=7)),
('month', timedelta(days=31)),
('year', timedelta(days=365)),
))
@pytest.mark.parametrize(
("test_time", "test_delta"),
(
("hour", timedelta(hours=1)),
("day", timedelta(days=1)),
("week", timedelta(days=7)),
("month", timedelta(days=31)),
("year", timedelta(days=365)),
),
)
def test_get_subreddit_time_verification(
test_time: str,
test_delta: timedelta,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
test_time: str,
test_delta: timedelta,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
):
downloader_mock.args.limit = 10
downloader_mock.args.sort = 'top'
downloader_mock.args.sort = "top"
downloader_mock.args.time = test_time
downloader_mock.time_filter = RedditConnector.create_time_filter(downloader_mock)
downloader_mock.sort_filter = RedditConnector.create_sort_filter(downloader_mock)
downloader_mock.determine_sort_function.return_value = RedditConnector.determine_sort_function(downloader_mock)
downloader_mock.args.subreddit = ['all']
downloader_mock.args.subreddit = ["all"]
downloader_mock.reddit_instance = reddit_instance
results = RedditConnector.get_subreddits(downloader_mock)
results = [sub for res1 in results for sub in res1]
@@ -230,20 +257,23 @@ def test_get_subreddit_time_verification(
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_subreddits', 'search_term', 'limit', 'time_filter', 'max_expected_len'), (
(('Python',), 'scraper', 10, 'all', 10),
(('Python',), '', 10, 'all', 0),
(('Python',), 'djsdsgewef', 10, 'all', 0),
(('Python',), 'scraper', 10, 'year', 10),
))
@pytest.mark.parametrize(
("test_subreddits", "search_term", "limit", "time_filter", "max_expected_len"),
(
(("Python",), "scraper", 10, "all", 10),
(("Python",), "", 10, "all", 0),
(("Python",), "djsdsgewef", 10, "all", 0),
(("Python",), "scraper", 10, "year", 10),
),
)
def test_get_subreddit_search(
test_subreddits: list[str],
search_term: str,
time_filter: str,
limit: int,
max_expected_len: int,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
test_subreddits: list[str],
search_term: str,
time_filter: str,
limit: int,
max_expected_len: int,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
):
downloader_mock._determine_sort_function.return_value = praw.models.Subreddit.hot
downloader_mock.args.limit = limit
@@ -265,17 +295,20 @@ def test_get_subreddit_search(
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_user', 'test_multireddits', 'limit'), (
('helen_darten', ('cuteanimalpics',), 10),
('korfor', ('chess',), 100),
))
@pytest.mark.parametrize(
("test_user", "test_multireddits", "limit"),
(
("helen_darten", ("cuteanimalpics",), 10),
("korfor", ("chess",), 100),
),
)
# Good sources at https://www.reddit.com/r/multihub/
def test_get_multireddits_public(
test_user: str,
test_multireddits: list[str],
limit: int,
reddit_instance: praw.Reddit,
downloader_mock: MagicMock,
test_user: str,
test_multireddits: list[str],
limit: int,
reddit_instance: praw.Reddit,
downloader_mock: MagicMock,
):
downloader_mock.determine_sort_function.return_value = praw.models.Subreddit.hot
downloader_mock.sort_filter = RedditTypes.SortType.HOT
@@ -283,11 +316,10 @@ def test_get_multireddits_public(
downloader_mock.args.multireddit = test_multireddits
downloader_mock.args.user = [test_user]
downloader_mock.reddit_instance = reddit_instance
downloader_mock.create_filtered_listing_generator.return_value = \
RedditConnector.create_filtered_listing_generator(
downloader_mock,
reddit_instance.multireddit(redditor=test_user, name=test_multireddits[0]),
)
downloader_mock.create_filtered_listing_generator.return_value = RedditConnector.create_filtered_listing_generator(
downloader_mock,
reddit_instance.multireddit(redditor=test_user, name=test_multireddits[0]),
)
results = RedditConnector.get_multireddits(downloader_mock)
results = [sub for res in results for sub in res]
assert all([isinstance(res, praw.models.Submission) for res in results])
@@ -297,11 +329,14 @@ def test_get_multireddits_public(
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_user', 'limit'), (
('danigirl3694', 10),
('danigirl3694', 50),
('CapitanHam', None),
))
@pytest.mark.parametrize(
("test_user", "limit"),
(
("danigirl3694", 10),
("danigirl3694", 50),
("CapitanHam", None),
),
)
def test_get_user_submissions(test_user: str, limit: int, downloader_mock: MagicMock, reddit_instance: praw.Reddit):
downloader_mock.args.limit = limit
downloader_mock.determine_sort_function.return_value = praw.models.Subreddit.hot
@@ -310,11 +345,10 @@ def test_get_user_submissions(test_user: str, limit: int, downloader_mock: Magic
downloader_mock.args.user = [test_user]
downloader_mock.authenticated = False
downloader_mock.reddit_instance = reddit_instance
downloader_mock.create_filtered_listing_generator.return_value = \
RedditConnector.create_filtered_listing_generator(
downloader_mock,
reddit_instance.redditor(test_user).submissions,
)
downloader_mock.create_filtered_listing_generator.return_value = RedditConnector.create_filtered_listing_generator(
downloader_mock,
reddit_instance.redditor(test_user).submissions,
)
results = RedditConnector.get_user_data(downloader_mock)
results = assert_all_results_are_submissions(limit, results)
assert all([res.author.name == test_user for res in results])
@@ -324,21 +358,24 @@ def test_get_user_submissions(test_user: str, limit: int, downloader_mock: Magic
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.authenticated
@pytest.mark.parametrize('test_flag', (
'upvoted',
'saved',
))
@pytest.mark.parametrize(
"test_flag",
(
"upvoted",
"saved",
),
)
def test_get_user_authenticated_lists(
test_flag: str,
downloader_mock: MagicMock,
authenticated_reddit_instance: praw.Reddit,
test_flag: str,
downloader_mock: MagicMock,
authenticated_reddit_instance: praw.Reddit,
):
downloader_mock.args.__dict__[test_flag] = True
downloader_mock.reddit_instance = authenticated_reddit_instance
downloader_mock.args.limit = 10
downloader_mock.determine_sort_function.return_value = praw.models.Subreddit.hot
downloader_mock.sort_filter = RedditTypes.SortType.HOT
downloader_mock.args.user = [RedditConnector.resolve_user_name(downloader_mock, 'me')]
downloader_mock.args.user = [RedditConnector.resolve_user_name(downloader_mock, "me")]
results = RedditConnector.get_user_data(downloader_mock)
assert_all_results_are_submissions_or_comments(10, results)
@@ -359,54 +396,63 @@ def test_get_subscribed_subreddits(downloader_mock: MagicMock, authenticated_red
assert results
@pytest.mark.parametrize(('test_name', 'expected'), (
('Mindustry', 'Mindustry'),
('Futurology', 'Futurology'),
('r/Mindustry', 'Mindustry'),
('TrollXChromosomes', 'TrollXChromosomes'),
('r/TrollXChromosomes', 'TrollXChromosomes'),
('https://www.reddit.com/r/TrollXChromosomes/', 'TrollXChromosomes'),
('https://www.reddit.com/r/TrollXChromosomes', 'TrollXChromosomes'),
('https://www.reddit.com/r/Futurology/', 'Futurology'),
('https://www.reddit.com/r/Futurology', 'Futurology'),
))
@pytest.mark.parametrize(
("test_name", "expected"),
(
("Mindustry", "Mindustry"),
("Futurology", "Futurology"),
("r/Mindustry", "Mindustry"),
("TrollXChromosomes", "TrollXChromosomes"),
("r/TrollXChromosomes", "TrollXChromosomes"),
("https://www.reddit.com/r/TrollXChromosomes/", "TrollXChromosomes"),
("https://www.reddit.com/r/TrollXChromosomes", "TrollXChromosomes"),
("https://www.reddit.com/r/Futurology/", "Futurology"),
("https://www.reddit.com/r/Futurology", "Futurology"),
),
)
def test_sanitise_subreddit_name(test_name: str, expected: str):
result = RedditConnector.sanitise_subreddit_name(test_name)
assert result == expected
@pytest.mark.parametrize(('test_subreddit_entries', 'expected'), (
(['test1', 'test2', 'test3'], {'test1', 'test2', 'test3'}),
(['test1,test2', 'test3'], {'test1', 'test2', 'test3'}),
(['test1, test2', 'test3'], {'test1', 'test2', 'test3'}),
(['test1; test2', 'test3'], {'test1', 'test2', 'test3'}),
(['test1, test2', 'test1,test2,test3', 'test4'], {'test1', 'test2', 'test3', 'test4'}),
([''], {''}),
(['test'], {'test'}),
))
@pytest.mark.parametrize(
("test_subreddit_entries", "expected"),
(
(["test1", "test2", "test3"], {"test1", "test2", "test3"}),
(["test1,test2", "test3"], {"test1", "test2", "test3"}),
(["test1, test2", "test3"], {"test1", "test2", "test3"}),
(["test1; test2", "test3"], {"test1", "test2", "test3"}),
(["test1, test2", "test1,test2,test3", "test4"], {"test1", "test2", "test3", "test4"}),
([""], {""}),
(["test"], {"test"}),
),
)
def test_split_subreddit_entries(test_subreddit_entries: list[str], expected: set[str]):
results = RedditConnector.split_args_input(test_subreddit_entries)
assert results == expected
def test_read_submission_ids_from_file(downloader_mock: MagicMock, tmp_path: Path):
test_file = tmp_path / 'test.txt'
test_file.write_text('aaaaaa\nbbbbbb')
test_file = tmp_path / "test.txt"
test_file.write_text("aaaaaa\nbbbbbb")
results = RedditConnector.read_id_files([str(test_file)])
assert results == {'aaaaaa', 'bbbbbb'}
assert results == {"aaaaaa", "bbbbbb"}
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize('test_redditor_name', (
'nasa',
'crowdstrike',
'HannibalGoddamnit',
))
@pytest.mark.parametrize(
"test_redditor_name",
(
"nasa",
"crowdstrike",
"HannibalGoddamnit",
),
)
def test_check_user_existence_good(
test_redditor_name: str,
reddit_instance: praw.Reddit,
downloader_mock: MagicMock,
test_redditor_name: str,
reddit_instance: praw.Reddit,
downloader_mock: MagicMock,
):
downloader_mock.reddit_instance = reddit_instance
RedditConnector.check_user_existence(downloader_mock, test_redditor_name)
@@ -414,42 +460,46 @@ def test_check_user_existence_good(
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize('test_redditor_name', (
'lhnhfkuhwreolo',
'adlkfmnhglojh',
))
@pytest.mark.parametrize(
"test_redditor_name",
(
"lhnhfkuhwreolo",
"adlkfmnhglojh",
),
)
def test_check_user_existence_nonexistent(
test_redditor_name: str,
reddit_instance: praw.Reddit,
downloader_mock: MagicMock,
test_redditor_name: str,
reddit_instance: praw.Reddit,
downloader_mock: MagicMock,
):
downloader_mock.reddit_instance = reddit_instance
with pytest.raises(BulkDownloaderException, match='Could not find'):
with pytest.raises(BulkDownloaderException, match="Could not find"):
RedditConnector.check_user_existence(downloader_mock, test_redditor_name)
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize('test_redditor_name', (
'Bree-Boo',
))
@pytest.mark.parametrize("test_redditor_name", ("Bree-Boo",))
def test_check_user_existence_banned(
test_redditor_name: str,
reddit_instance: praw.Reddit,
downloader_mock: MagicMock,
test_redditor_name: str,
reddit_instance: praw.Reddit,
downloader_mock: MagicMock,
):
downloader_mock.reddit_instance = reddit_instance
with pytest.raises(BulkDownloaderException, match='is banned'):
with pytest.raises(BulkDownloaderException, match="is banned"):
RedditConnector.check_user_existence(downloader_mock, test_redditor_name)
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_subreddit_name', 'expected_message'), (
('donaldtrump', 'cannot be found'),
('submitters', 'private and cannot be scraped'),
('lhnhfkuhwreolo', 'does not exist')
))
@pytest.mark.parametrize(
("test_subreddit_name", "expected_message"),
(
("donaldtrump", "cannot be found"),
("submitters", "private and cannot be scraped"),
("lhnhfkuhwreolo", "does not exist"),
),
)
def test_check_subreddit_status_bad(test_subreddit_name: str, expected_message: str, reddit_instance: praw.Reddit):
test_subreddit = reddit_instance.subreddit(test_subreddit_name)
with pytest.raises(BulkDownloaderException, match=expected_message):
@@ -458,12 +508,15 @@ def test_check_subreddit_status_bad(test_subreddit_name: str, expected_message:
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize('test_subreddit_name', (
'Python',
'Mindustry',
'TrollXChromosomes',
'all',
))
@pytest.mark.parametrize(
"test_subreddit_name",
(
"Python",
"Mindustry",
"TrollXChromosomes",
"all",
),
)
def test_check_subreddit_status_good(test_subreddit_name: str, reddit_instance: praw.Reddit):
test_subreddit = reddit_instance.subreddit(test_subreddit_name)
RedditConnector.check_subreddit_status(test_subreddit)

View File

@@ -11,55 +11,67 @@ from bdfr.resource import Resource
@pytest.fixture()
def download_filter() -> DownloadFilter:
return DownloadFilter(['mp4', 'mp3'], ['test.com', 'reddit.com', 'img.example.com'])
return DownloadFilter(["mp4", "mp3"], ["test.com", "reddit.com", "img.example.com"])
@pytest.mark.parametrize(('test_extension', 'expected'), (
('.mp4', False),
('.avi', True),
('.random.mp3', False),
('mp4', False),
))
@pytest.mark.parametrize(
("test_extension", "expected"),
(
(".mp4", False),
(".avi", True),
(".random.mp3", False),
("mp4", False),
),
)
def test_filter_extension(test_extension: str, expected: bool, download_filter: DownloadFilter):
result = download_filter._check_extension(test_extension)
assert result == expected
@pytest.mark.parametrize(('test_url', 'expected'), (
('test.mp4', True),
('http://reddit.com/test.mp4', False),
('http://reddit.com/test.gif', False),
('https://www.example.com/test.mp4', True),
('https://www.example.com/test.png', True),
('https://i.example.com/test.png', True),
('https://img.example.com/test.png', False),
('https://i.test.com/test.png', False),
))
@pytest.mark.parametrize(
("test_url", "expected"),
(
("test.mp4", True),
("http://reddit.com/test.mp4", False),
("http://reddit.com/test.gif", False),
("https://www.example.com/test.mp4", True),
("https://www.example.com/test.png", True),
("https://i.example.com/test.png", True),
("https://img.example.com/test.png", False),
("https://i.test.com/test.png", False),
),
)
def test_filter_domain(test_url: str, expected: bool, download_filter: DownloadFilter):
result = download_filter._check_domain(test_url)
assert result == expected
@pytest.mark.parametrize(('test_url', 'expected'), (
('test.mp4', False),
('test.gif', True),
('https://www.example.com/test.mp4', False),
('https://www.example.com/test.png', True),
('http://reddit.com/test.mp4', False),
('http://reddit.com/test.gif', False),
))
@pytest.mark.parametrize(
("test_url", "expected"),
(
("test.mp4", False),
("test.gif", True),
("https://www.example.com/test.mp4", False),
("https://www.example.com/test.png", True),
("http://reddit.com/test.mp4", False),
("http://reddit.com/test.gif", False),
),
)
def test_filter_all(test_url: str, expected: bool, download_filter: DownloadFilter):
test_resource = Resource(MagicMock(), test_url, lambda: None)
result = download_filter.check_resource(test_resource)
assert result == expected
@pytest.mark.parametrize('test_url', (
'test.mp3',
'test.mp4',
'http://reddit.com/test.mp4',
't',
))
@pytest.mark.parametrize(
"test_url",
(
"test.mp3",
"test.mp4",
"http://reddit.com/test.mp4",
"t",
),
)
def test_filter_empty_filter(test_url: str):
download_filter = DownloadFilter()
test_resource = Resource(MagicMock(), test_url, lambda: None)

View File

@@ -18,7 +18,7 @@ from bdfr.downloader import RedditDownloader
@pytest.fixture()
def args() -> Configuration:
args = Configuration()
args.time_format = 'ISO'
args.time_format = "ISO"
return args
@@ -32,29 +32,32 @@ def downloader_mock(args: Configuration):
return downloader_mock
@pytest.mark.parametrize(('test_ids', 'test_excluded', 'expected_len'), (
(('aaaaaa',), (), 1),
(('aaaaaa',), ('aaaaaa',), 0),
((), ('aaaaaa',), 0),
(('aaaaaa', 'bbbbbb'), ('aaaaaa',), 1),
(('aaaaaa', 'bbbbbb', 'cccccc'), ('aaaaaa',), 2),
))
@patch('bdfr.site_downloaders.download_factory.DownloadFactory.pull_lever')
@pytest.mark.parametrize(
("test_ids", "test_excluded", "expected_len"),
(
(("aaaaaa",), (), 1),
(("aaaaaa",), ("aaaaaa",), 0),
((), ("aaaaaa",), 0),
(("aaaaaa", "bbbbbb"), ("aaaaaa",), 1),
(("aaaaaa", "bbbbbb", "cccccc"), ("aaaaaa",), 2),
),
)
@patch("bdfr.site_downloaders.download_factory.DownloadFactory.pull_lever")
def test_excluded_ids(
mock_function: MagicMock,
test_ids: tuple[str],
test_excluded: tuple[str],
expected_len: int,
downloader_mock: MagicMock,
mock_function: MagicMock,
test_ids: tuple[str],
test_excluded: tuple[str],
expected_len: int,
downloader_mock: MagicMock,
):
downloader_mock.excluded_submission_ids = test_excluded
mock_function.return_value = MagicMock()
mock_function.return_value.__name__ = 'test'
mock_function.return_value.__name__ = "test"
test_submissions = []
for test_id in test_ids:
m = MagicMock()
m.id = test_id
m.subreddit.display_name.return_value = 'https://www.example.com/'
m.subreddit.display_name.return_value = "https://www.example.com/"
m.__class__ = praw.models.Submission
test_submissions.append(m)
downloader_mock.reddit_lists = [test_submissions]
@@ -65,32 +68,27 @@ def test_excluded_ids(
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize('test_submission_id', (
'm1hqw6',
))
@pytest.mark.parametrize("test_submission_id", ("m1hqw6",))
def test_mark_hard_link(
test_submission_id: str,
downloader_mock: MagicMock,
tmp_path: Path,
reddit_instance: praw.Reddit
test_submission_id: str, downloader_mock: MagicMock, tmp_path: Path, reddit_instance: praw.Reddit
):
downloader_mock.reddit_instance = reddit_instance
downloader_mock.args.make_hard_links = True
downloader_mock.download_directory = tmp_path
downloader_mock.args.folder_scheme = ''
downloader_mock.args.file_scheme = '{POSTID}'
downloader_mock.args.folder_scheme = ""
downloader_mock.args.file_scheme = "{POSTID}"
downloader_mock.file_name_formatter = RedditConnector.create_file_name_formatter(downloader_mock)
submission = downloader_mock.reddit_instance.submission(id=test_submission_id)
original = Path(tmp_path, f'{test_submission_id}.png')
original = Path(tmp_path, f"{test_submission_id}.png")
RedditDownloader._download_submission(downloader_mock, submission)
assert original.exists()
downloader_mock.args.file_scheme = 'test2_{POSTID}'
downloader_mock.args.file_scheme = "test2_{POSTID}"
downloader_mock.file_name_formatter = RedditConnector.create_file_name_formatter(downloader_mock)
RedditDownloader._download_submission(downloader_mock, submission)
test_file_1_stats = original.stat()
test_file_2_inode = Path(tmp_path, f'test2_{test_submission_id}.png').stat().st_ino
test_file_2_inode = Path(tmp_path, f"test2_{test_submission_id}.png").stat().st_ino
assert test_file_1_stats.st_nlink == 2
assert test_file_1_stats.st_ino == test_file_2_inode
@@ -98,20 +96,18 @@ def test_mark_hard_link(
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_submission_id', 'test_creation_date'), (
('ndzz50', 1621204841.0),
))
@pytest.mark.parametrize(("test_submission_id", "test_creation_date"), (("ndzz50", 1621204841.0),))
def test_file_creation_date(
test_submission_id: str,
test_creation_date: float,
downloader_mock: MagicMock,
tmp_path: Path,
reddit_instance: praw.Reddit
test_submission_id: str,
test_creation_date: float,
downloader_mock: MagicMock,
tmp_path: Path,
reddit_instance: praw.Reddit,
):
downloader_mock.reddit_instance = reddit_instance
downloader_mock.download_directory = tmp_path
downloader_mock.args.folder_scheme = ''
downloader_mock.args.file_scheme = '{POSTID}'
downloader_mock.args.folder_scheme = ""
downloader_mock.args.file_scheme = "{POSTID}"
downloader_mock.file_name_formatter = RedditConnector.create_file_name_formatter(downloader_mock)
submission = downloader_mock.reddit_instance.submission(id=test_submission_id)
@@ -123,27 +119,25 @@ def test_file_creation_date(
def test_search_existing_files():
results = RedditDownloader.scan_existing_files(Path('.'))
results = RedditDownloader.scan_existing_files(Path("."))
assert len(results.keys()) != 0
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_submission_id', 'test_hash'), (
('m1hqw6', 'a912af8905ae468e0121e9940f797ad7'),
))
@pytest.mark.parametrize(("test_submission_id", "test_hash"), (("m1hqw6", "a912af8905ae468e0121e9940f797ad7"),))
def test_download_submission_hash_exists(
test_submission_id: str,
test_hash: str,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
tmp_path: Path,
capsys: pytest.CaptureFixture
test_submission_id: str,
test_hash: str,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
tmp_path: Path,
capsys: pytest.CaptureFixture,
):
setup_logging(3)
downloader_mock.reddit_instance = reddit_instance
downloader_mock.download_filter.check_url.return_value = True
downloader_mock.args.folder_scheme = ''
downloader_mock.args.folder_scheme = ""
downloader_mock.args.no_dupes = True
downloader_mock.file_name_formatter = RedditConnector.create_file_name_formatter(downloader_mock)
downloader_mock.download_directory = tmp_path
@@ -153,47 +147,44 @@ def test_download_submission_hash_exists(
folder_contents = list(tmp_path.iterdir())
output = capsys.readouterr()
assert not folder_contents
assert re.search(r'Resource hash .*? downloaded elsewhere', output.out)
assert re.search(r"Resource hash .*? downloaded elsewhere", output.out)
@pytest.mark.online
@pytest.mark.reddit
def test_download_submission_file_exists(
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
tmp_path: Path,
capsys: pytest.CaptureFixture
downloader_mock: MagicMock, reddit_instance: praw.Reddit, tmp_path: Path, capsys: pytest.CaptureFixture
):
setup_logging(3)
downloader_mock.reddit_instance = reddit_instance
downloader_mock.download_filter.check_url.return_value = True
downloader_mock.args.folder_scheme = ''
downloader_mock.args.folder_scheme = ""
downloader_mock.file_name_formatter = RedditConnector.create_file_name_formatter(downloader_mock)
downloader_mock.download_directory = tmp_path
submission = downloader_mock.reddit_instance.submission(id='m1hqw6')
Path(tmp_path, 'Arneeman_Metagaming isn\'t always a bad thing_m1hqw6.png').touch()
submission = downloader_mock.reddit_instance.submission(id="m1hqw6")
Path(tmp_path, "Arneeman_Metagaming isn't always a bad thing_m1hqw6.png").touch()
RedditDownloader._download_submission(downloader_mock, submission)
folder_contents = list(tmp_path.iterdir())
output = capsys.readouterr()
assert len(folder_contents) == 1
assert 'Arneeman_Metagaming isn\'t always a bad thing_m1hqw6.png'\
' from submission m1hqw6 already exists' in output.out
assert (
"Arneeman_Metagaming isn't always a bad thing_m1hqw6.png" " from submission m1hqw6 already exists" in output.out
)
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_submission_id', 'expected_files_len'), (
('ljyy27', 4),
))
@pytest.mark.parametrize(("test_submission_id", "expected_files_len"), (("ljyy27", 4),))
def test_download_submission(
test_submission_id: str,
expected_files_len: int,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
tmp_path: Path):
test_submission_id: str,
expected_files_len: int,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
tmp_path: Path,
):
downloader_mock.reddit_instance = reddit_instance
downloader_mock.download_filter.check_url.return_value = True
downloader_mock.args.folder_scheme = ''
downloader_mock.args.folder_scheme = ""
downloader_mock.file_name_formatter = RedditConnector.create_file_name_formatter(downloader_mock)
downloader_mock.download_directory = tmp_path
submission = downloader_mock.reddit_instance.submission(id=test_submission_id)
@@ -204,103 +195,95 @@ def test_download_submission(
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_submission_id', 'min_score'), (
('ljyy27', 1),
))
@pytest.mark.parametrize(("test_submission_id", "min_score"), (("ljyy27", 1),))
def test_download_submission_min_score_above(
test_submission_id: str,
min_score: int,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
tmp_path: Path,
capsys: pytest.CaptureFixture,
test_submission_id: str,
min_score: int,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
tmp_path: Path,
capsys: pytest.CaptureFixture,
):
setup_logging(3)
downloader_mock.reddit_instance = reddit_instance
downloader_mock.download_filter.check_url.return_value = True
downloader_mock.args.folder_scheme = ''
downloader_mock.args.folder_scheme = ""
downloader_mock.args.min_score = min_score
downloader_mock.file_name_formatter = RedditConnector.create_file_name_formatter(downloader_mock)
downloader_mock.download_directory = tmp_path
submission = downloader_mock.reddit_instance.submission(id=test_submission_id)
RedditDownloader._download_submission(downloader_mock, submission)
output = capsys.readouterr()
assert 'filtered due to score' not in output.out
assert "filtered due to score" not in output.out
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_submission_id', 'min_score'), (
('ljyy27', 25),
))
@pytest.mark.parametrize(("test_submission_id", "min_score"), (("ljyy27", 25),))
def test_download_submission_min_score_below(
test_submission_id: str,
min_score: int,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
tmp_path: Path,
capsys: pytest.CaptureFixture,
test_submission_id: str,
min_score: int,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
tmp_path: Path,
capsys: pytest.CaptureFixture,
):
setup_logging(3)
downloader_mock.reddit_instance = reddit_instance
downloader_mock.download_filter.check_url.return_value = True
downloader_mock.args.folder_scheme = ''
downloader_mock.args.folder_scheme = ""
downloader_mock.args.min_score = min_score
downloader_mock.file_name_formatter = RedditConnector.create_file_name_formatter(downloader_mock)
downloader_mock.download_directory = tmp_path
submission = downloader_mock.reddit_instance.submission(id=test_submission_id)
RedditDownloader._download_submission(downloader_mock, submission)
output = capsys.readouterr()
assert 'filtered due to score' in output.out
assert "filtered due to score" in output.out
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_submission_id', 'max_score'), (
('ljyy27', 25),
))
@pytest.mark.parametrize(("test_submission_id", "max_score"), (("ljyy27", 25),))
def test_download_submission_max_score_below(
test_submission_id: str,
max_score: int,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
tmp_path: Path,
capsys: pytest.CaptureFixture,
test_submission_id: str,
max_score: int,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
tmp_path: Path,
capsys: pytest.CaptureFixture,
):
setup_logging(3)
downloader_mock.reddit_instance = reddit_instance
downloader_mock.download_filter.check_url.return_value = True
downloader_mock.args.folder_scheme = ''
downloader_mock.args.folder_scheme = ""
downloader_mock.args.max_score = max_score
downloader_mock.file_name_formatter = RedditConnector.create_file_name_formatter(downloader_mock)
downloader_mock.download_directory = tmp_path
submission = downloader_mock.reddit_instance.submission(id=test_submission_id)
RedditDownloader._download_submission(downloader_mock, submission)
output = capsys.readouterr()
assert 'filtered due to score' not in output.out
assert "filtered due to score" not in output.out
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_submission_id', 'max_score'), (
('ljyy27', 1),
))
@pytest.mark.parametrize(("test_submission_id", "max_score"), (("ljyy27", 1),))
def test_download_submission_max_score_above(
test_submission_id: str,
max_score: int,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
tmp_path: Path,
capsys: pytest.CaptureFixture,
test_submission_id: str,
max_score: int,
downloader_mock: MagicMock,
reddit_instance: praw.Reddit,
tmp_path: Path,
capsys: pytest.CaptureFixture,
):
setup_logging(3)
downloader_mock.reddit_instance = reddit_instance
downloader_mock.download_filter.check_url.return_value = True
downloader_mock.args.folder_scheme = ''
downloader_mock.args.folder_scheme = ""
downloader_mock.args.max_score = max_score
downloader_mock.file_name_formatter = RedditConnector.create_file_name_formatter(downloader_mock)
downloader_mock.download_directory = tmp_path
submission = downloader_mock.reddit_instance.submission(id=test_submission_id)
RedditDownloader._download_submission(downloader_mock, submission)
output = capsys.readouterr()
assert 'filtered due to score' in output.out
assert "filtered due to score" in output.out

View File

@@ -22,26 +22,26 @@ from bdfr.site_downloaders.self_post import SelfPost
@pytest.fixture()
def submission() -> MagicMock:
test = MagicMock()
test.title = 'name'
test.subreddit.display_name = 'randomreddit'
test.author.name = 'person'
test.id = '12345'
test.title = "name"
test.subreddit.display_name = "randomreddit"
test.author.name = "person"
test.id = "12345"
test.score = 1000
test.link_flair_text = 'test_flair'
test.link_flair_text = "test_flair"
test.created_utc = datetime(2021, 4, 21, 9, 30, 0).timestamp()
test.__class__ = praw.models.Submission
return test
def do_test_string_equality(result: Union[Path, str], expected: str) -> bool:
if platform.system() == 'Windows':
if platform.system() == "Windows":
expected = FileNameFormatter._format_for_windows(expected)
return str(result).endswith(expected)
def do_test_path_equality(result: Path, expected: str) -> bool:
if platform.system() == 'Windows':
expected = expected.split('/')
if platform.system() == "Windows":
expected = expected.split("/")
expected = [FileNameFormatter._format_for_windows(part) for part in expected]
expected = Path(*expected)
else:
@@ -49,35 +49,41 @@ def do_test_path_equality(result: Path, expected: str) -> bool:
return str(result).endswith(str(expected))
@pytest.fixture(scope='session')
@pytest.fixture(scope="session")
def reddit_submission(reddit_instance: praw.Reddit) -> praw.models.Submission:
return reddit_instance.submission(id='w22m5l')
return reddit_instance.submission(id="w22m5l")
@pytest.mark.parametrize(('test_format_string', 'expected'), (
('{SUBREDDIT}', 'randomreddit'),
('{REDDITOR}', 'person'),
('{POSTID}', '12345'),
('{UPVOTES}', '1000'),
('{FLAIR}', 'test_flair'),
('{DATE}', '2021-04-21T09:30:00'),
('{REDDITOR}_{TITLE}_{POSTID}', 'person_name_12345'),
))
@pytest.mark.parametrize(
("test_format_string", "expected"),
(
("{SUBREDDIT}", "randomreddit"),
("{REDDITOR}", "person"),
("{POSTID}", "12345"),
("{UPVOTES}", "1000"),
("{FLAIR}", "test_flair"),
("{DATE}", "2021-04-21T09:30:00"),
("{REDDITOR}_{TITLE}_{POSTID}", "person_name_12345"),
),
)
def test_format_name_mock(test_format_string: str, expected: str, submission: MagicMock):
test_formatter = FileNameFormatter(test_format_string, '', 'ISO')
test_formatter = FileNameFormatter(test_format_string, "", "ISO")
result = test_formatter._format_name(submission, test_format_string)
assert do_test_string_equality(result, expected)
@pytest.mark.parametrize(('test_string', 'expected'), (
('', False),
('test', False),
('{POSTID}', True),
('POSTID', False),
('{POSTID}_test', True),
('test_{TITLE}', True),
('TITLE_POSTID', False),
))
@pytest.mark.parametrize(
("test_string", "expected"),
(
("", False),
("test", False),
("{POSTID}", True),
("POSTID", False),
("{POSTID}_test", True),
("test_{TITLE}", True),
("TITLE_POSTID", False),
),
)
def test_check_format_string_validity(test_string: str, expected: bool):
result = FileNameFormatter.validate_string(test_string)
assert result == expected
@@ -85,84 +91,98 @@ def test_check_format_string_validity(test_string: str, expected: bool):
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_format_string', 'expected'), (
('{SUBREDDIT}', 'formula1'),
('{REDDITOR}', 'Kirsty-Blue'),
('{POSTID}', 'w22m5l'),
('{FLAIR}', 'Social Media rall'),
('{SUBREDDIT}_{TITLE}', 'formula1_George Russel acknowledges the Twitter trend about him'),
('{REDDITOR}_{TITLE}_{POSTID}', 'Kirsty-Blue_George Russel acknowledges the Twitter trend about him_w22m5l')
))
@pytest.mark.parametrize(
("test_format_string", "expected"),
(
("{SUBREDDIT}", "formula1"),
("{REDDITOR}", "Kirsty-Blue"),
("{POSTID}", "w22m5l"),
("{FLAIR}", "Social Media rall"),
("{SUBREDDIT}_{TITLE}", "formula1_George Russel acknowledges the Twitter trend about him"),
("{REDDITOR}_{TITLE}_{POSTID}", "Kirsty-Blue_George Russel acknowledges the Twitter trend about him_w22m5l"),
),
)
def test_format_name_real(test_format_string: str, expected: str, reddit_submission: praw.models.Submission):
test_formatter = FileNameFormatter(test_format_string, '', '')
test_formatter = FileNameFormatter(test_format_string, "", "")
result = test_formatter._format_name(reddit_submission, test_format_string)
assert do_test_string_equality(result, expected)
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('format_string_directory', 'format_string_file', 'expected'), (
@pytest.mark.parametrize(
("format_string_directory", "format_string_file", "expected"),
(
'{SUBREDDIT}',
'{POSTID}',
'test/formula1/w22m5l.png',
(
"{SUBREDDIT}",
"{POSTID}",
"test/formula1/w22m5l.png",
),
(
"{SUBREDDIT}",
"{TITLE}_{POSTID}",
"test/formula1/George Russel acknowledges the Twitter trend about him_w22m5l.png",
),
(
"{SUBREDDIT}",
"{REDDITOR}_{TITLE}_{POSTID}",
"test/formula1/Kirsty-Blue_George Russel acknowledges the Twitter trend about him_w22m5l.png",
),
),
(
'{SUBREDDIT}',
'{TITLE}_{POSTID}',
'test/formula1/George Russel acknowledges the Twitter trend about him_w22m5l.png',
),
(
'{SUBREDDIT}',
'{REDDITOR}_{TITLE}_{POSTID}',
'test/formula1/Kirsty-Blue_George Russel acknowledges the Twitter trend about him_w22m5l.png',
),
))
)
def test_format_full(
format_string_directory: str,
format_string_file: str,
expected: str,
reddit_submission: praw.models.Submission):
test_resource = Resource(reddit_submission, 'i.reddit.com/blabla.png', lambda: None)
test_formatter = FileNameFormatter(format_string_file, format_string_directory, 'ISO')
result = test_formatter.format_path(test_resource, Path('test'))
format_string_directory: str, format_string_file: str, expected: str, reddit_submission: praw.models.Submission
):
test_resource = Resource(reddit_submission, "i.reddit.com/blabla.png", lambda: None)
test_formatter = FileNameFormatter(format_string_file, format_string_directory, "ISO")
result = test_formatter.format_path(test_resource, Path("test"))
assert do_test_path_equality(result, expected)
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('format_string_directory', 'format_string_file'), (
('{SUBREDDIT}', '{POSTID}'),
('{SUBREDDIT}', '{UPVOTES}'),
('{SUBREDDIT}', '{UPVOTES}{POSTID}'),
))
@pytest.mark.parametrize(
("format_string_directory", "format_string_file"),
(
("{SUBREDDIT}", "{POSTID}"),
("{SUBREDDIT}", "{UPVOTES}"),
("{SUBREDDIT}", "{UPVOTES}{POSTID}"),
),
)
def test_format_full_conform(
format_string_directory: str,
format_string_file: str,
reddit_submission: praw.models.Submission):
test_resource = Resource(reddit_submission, 'i.reddit.com/blabla.png', lambda: None)
test_formatter = FileNameFormatter(format_string_file, format_string_directory, 'ISO')
test_formatter.format_path(test_resource, Path('test'))
format_string_directory: str, format_string_file: str, reddit_submission: praw.models.Submission
):
test_resource = Resource(reddit_submission, "i.reddit.com/blabla.png", lambda: None)
test_formatter = FileNameFormatter(format_string_file, format_string_directory, "ISO")
test_formatter.format_path(test_resource, Path("test"))
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('format_string_directory', 'format_string_file', 'index', 'expected'), (
('{SUBREDDIT}', '{POSTID}', None, 'test/formula1/w22m5l.png'),
('{SUBREDDIT}', '{POSTID}', 1, 'test/formula1/w22m5l_1.png'),
('{SUBREDDIT}', '{POSTID}', 2, 'test/formula1/w22m5l_2.png'),
('{SUBREDDIT}', '{TITLE}_{POSTID}', 2, 'test/formula1/George Russel acknowledges the Twitter trend about him_w22m5l_2.png'),
))
@pytest.mark.parametrize(
("format_string_directory", "format_string_file", "index", "expected"),
(
("{SUBREDDIT}", "{POSTID}", None, "test/formula1/w22m5l.png"),
("{SUBREDDIT}", "{POSTID}", 1, "test/formula1/w22m5l_1.png"),
("{SUBREDDIT}", "{POSTID}", 2, "test/formula1/w22m5l_2.png"),
(
"{SUBREDDIT}",
"{TITLE}_{POSTID}",
2,
"test/formula1/George Russel acknowledges the Twitter trend about him_w22m5l_2.png",
),
),
)
def test_format_full_with_index_suffix(
format_string_directory: str,
format_string_file: str,
index: Optional[int],
expected: str,
reddit_submission: praw.models.Submission,
format_string_directory: str,
format_string_file: str,
index: Optional[int],
expected: str,
reddit_submission: praw.models.Submission,
):
test_resource = Resource(reddit_submission, 'i.reddit.com/blabla.png', lambda: None)
test_formatter = FileNameFormatter(format_string_file, format_string_directory, 'ISO')
result = test_formatter.format_path(test_resource, Path('test'), index)
test_resource = Resource(reddit_submission, "i.reddit.com/blabla.png", lambda: None)
test_formatter = FileNameFormatter(format_string_file, format_string_directory, "ISO")
result = test_formatter.format_path(test_resource, Path("test"), index)
assert do_test_path_equality(result, expected)
@@ -170,99 +190,114 @@ def test_format_multiple_resources():
mocks = []
for i in range(1, 5):
new_mock = MagicMock()
new_mock.url = 'https://example.com/test.png'
new_mock.extension = '.png'
new_mock.source_submission.title = 'test'
new_mock.url = "https://example.com/test.png"
new_mock.extension = ".png"
new_mock.source_submission.title = "test"
new_mock.source_submission.__class__ = praw.models.Submission
mocks.append(new_mock)
test_formatter = FileNameFormatter('{TITLE}', '', 'ISO')
results = test_formatter.format_resource_paths(mocks, Path('.'))
test_formatter = FileNameFormatter("{TITLE}", "", "ISO")
results = test_formatter.format_resource_paths(mocks, Path("."))
results = set([str(res[0].name) for res in results])
expected = {'test_1.png', 'test_2.png', 'test_3.png', 'test_4.png'}
expected = {"test_1.png", "test_2.png", "test_3.png", "test_4.png"}
assert results == expected
@pytest.mark.parametrize(('test_filename', 'test_ending'), (
('A' * 300, '.png'),
('A' * 300, '_1.png'),
('a' * 300, '_1000.jpeg'),
('😍💕✨' * 100, '_1.png'),
))
@pytest.mark.parametrize(
("test_filename", "test_ending"),
(
("A" * 300, ".png"),
("A" * 300, "_1.png"),
("a" * 300, "_1000.jpeg"),
("😍💕✨" * 100, "_1.png"),
),
)
def test_limit_filename_length(test_filename: str, test_ending: str):
result = FileNameFormatter.limit_file_name_length(test_filename, test_ending, Path('.'))
result = FileNameFormatter.limit_file_name_length(test_filename, test_ending, Path("."))
assert len(result.name) <= 255
assert len(result.name.encode('utf-8')) <= 255
assert len(result.name.encode("utf-8")) <= 255
assert len(str(result)) <= FileNameFormatter.find_max_path_length()
assert isinstance(result, Path)
@pytest.mark.parametrize(('test_filename', 'test_ending', 'expected_end'), (
('test_aaaaaa', '_1.png', 'test_aaaaaa_1.png'),
('test_aataaa', '_1.png', 'test_aataaa_1.png'),
('test_abcdef', '_1.png', 'test_abcdef_1.png'),
('test_aaaaaa', '.png', 'test_aaaaaa.png'),
('test', '_1.png', 'test_1.png'),
('test_m1hqw6', '_1.png', 'test_m1hqw6_1.png'),
('A' * 300 + '_bbbccc', '.png', '_bbbccc.png'),
('A' * 300 + '_bbbccc', '_1000.jpeg', '_bbbccc_1000.jpeg'),
('😍💕✨' * 100 + '_aaa1aa', '_1.png', '_aaa1aa_1.png'),
))
@pytest.mark.parametrize(
("test_filename", "test_ending", "expected_end"),
(
("test_aaaaaa", "_1.png", "test_aaaaaa_1.png"),
("test_aataaa", "_1.png", "test_aataaa_1.png"),
("test_abcdef", "_1.png", "test_abcdef_1.png"),
("test_aaaaaa", ".png", "test_aaaaaa.png"),
("test", "_1.png", "test_1.png"),
("test_m1hqw6", "_1.png", "test_m1hqw6_1.png"),
("A" * 300 + "_bbbccc", ".png", "_bbbccc.png"),
("A" * 300 + "_bbbccc", "_1000.jpeg", "_bbbccc_1000.jpeg"),
("😍💕✨" * 100 + "_aaa1aa", "_1.png", "_aaa1aa_1.png"),
),
)
def test_preserve_id_append_when_shortening(test_filename: str, test_ending: str, expected_end: str):
result = FileNameFormatter.limit_file_name_length(test_filename, test_ending, Path('.'))
result = FileNameFormatter.limit_file_name_length(test_filename, test_ending, Path("."))
assert len(result.name) <= 255
assert len(result.name.encode('utf-8')) <= 255
assert len(result.name.encode("utf-8")) <= 255
assert result.name.endswith(expected_end)
assert len(str(result)) <= FileNameFormatter.find_max_path_length()
@pytest.mark.skipif(sys.platform == 'win32', reason='Test broken on windows github')
@pytest.mark.skipif(sys.platform == "win32", reason="Test broken on windows github")
def test_shorten_filename_real(submission: MagicMock, tmp_path: Path):
submission.title = 'A' * 500
submission.author.name = 'test'
submission.subreddit.display_name = 'test'
submission.id = 'BBBBBB'
test_resource = Resource(submission, 'www.example.com/empty', lambda: None, '.jpeg')
test_formatter = FileNameFormatter('{REDDITOR}_{TITLE}_{POSTID}', '{SUBREDDIT}', 'ISO')
submission.title = "A" * 500
submission.author.name = "test"
submission.subreddit.display_name = "test"
submission.id = "BBBBBB"
test_resource = Resource(submission, "www.example.com/empty", lambda: None, ".jpeg")
test_formatter = FileNameFormatter("{REDDITOR}_{TITLE}_{POSTID}", "{SUBREDDIT}", "ISO")
result = test_formatter.format_path(test_resource, tmp_path)
result.parent.mkdir(parents=True)
result.touch()
@pytest.mark.parametrize(('test_name', 'test_ending'), (
('a', 'b'),
('a', '_bbbbbb.jpg'),
('a' * 20, '_bbbbbb.jpg'),
('a' * 50, '_bbbbbb.jpg'),
('a' * 500, '_bbbbbb.jpg'),
))
@pytest.mark.parametrize(
("test_name", "test_ending"),
(
("a", "b"),
("a", "_bbbbbb.jpg"),
("a" * 20, "_bbbbbb.jpg"),
("a" * 50, "_bbbbbb.jpg"),
("a" * 500, "_bbbbbb.jpg"),
),
)
def test_shorten_path(test_name: str, test_ending: str, tmp_path: Path):
result = FileNameFormatter.limit_file_name_length(test_name, test_ending, tmp_path)
assert len(str(result.name)) <= 255
assert len(str(result.name).encode('UTF-8')) <= 255
assert len(str(result.name).encode('cp1252')) <= 255
assert len(str(result.name).encode("UTF-8")) <= 255
assert len(str(result.name).encode("cp1252")) <= 255
assert len(str(result)) <= FileNameFormatter.find_max_path_length()
@pytest.mark.parametrize(('test_string', 'expected'), (
('test', 'test'),
('test😍', 'test'),
('test.png', 'test.png'),
('test*', 'test'),
('test**', 'test'),
('test?*', 'test'),
('test_???.png', 'test_.png'),
('test_???😍.png', 'test_.png'),
))
@pytest.mark.parametrize(
("test_string", "expected"),
(
("test", "test"),
("test😍", "test"),
("test.png", "test.png"),
("test*", "test"),
("test**", "test"),
("test?*", "test"),
("test_???.png", "test_.png"),
("test_???😍.png", "test_.png"),
),
)
def test_format_file_name_for_windows(test_string: str, expected: str):
result = FileNameFormatter._format_for_windows(test_string)
assert result == expected
@pytest.mark.parametrize(('test_string', 'expected'), (
('test', 'test'),
('test😍', 'test'),
('😍', ''),
))
@pytest.mark.parametrize(
("test_string", "expected"),
(
("test", "test"),
("test😍", "test"),
("😍", ""),
),
)
def test_strip_emojies(test_string: str, expected: str):
result = FileNameFormatter._strip_emojis(test_string)
assert result == expected
@@ -270,121 +305,151 @@ def test_strip_emojies(test_string: str, expected: str):
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_submission_id', 'expected'), (
('mfuteh', {
'title': 'Why Do Interviewers Ask Linked List Questions?',
'redditor': 'mjgardner',
}),
))
@pytest.mark.parametrize(
("test_submission_id", "expected"),
(
(
"mfuteh",
{
"title": "Why Do Interviewers Ask Linked List Questions?",
"redditor": "mjgardner",
},
),
),
)
def test_generate_dict_for_submission(test_submission_id: str, expected: dict, reddit_instance: praw.Reddit):
test_submission = reddit_instance.submission(id=test_submission_id)
test_formatter = FileNameFormatter('{TITLE}', '', 'ISO')
test_formatter = FileNameFormatter("{TITLE}", "", "ISO")
result = test_formatter._generate_name_dict_from_submission(test_submission)
assert all([result.get(key) == expected[key] for key in expected.keys()])
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_comment_id', 'expected'), (
('gsq0yuw', {
'title': 'Why Do Interviewers Ask Linked List Questions?',
'redditor': 'Doctor-Dapper',
'postid': 'gsq0yuw',
'flair': '',
}),
))
@pytest.mark.parametrize(
("test_comment_id", "expected"),
(
(
"gsq0yuw",
{
"title": "Why Do Interviewers Ask Linked List Questions?",
"redditor": "Doctor-Dapper",
"postid": "gsq0yuw",
"flair": "",
},
),
),
)
def test_generate_dict_for_comment(test_comment_id: str, expected: dict, reddit_instance: praw.Reddit):
test_comment = reddit_instance.comment(id=test_comment_id)
test_formatter = FileNameFormatter('{TITLE}', '', 'ISO')
test_formatter = FileNameFormatter("{TITLE}", "", "ISO")
result = test_formatter._generate_name_dict_from_comment(test_comment)
assert all([result.get(key) == expected[key] for key in expected.keys()])
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_file_scheme', 'test_folder_scheme', 'test_comment_id', 'expected_name'), (
('{POSTID}', '', 'gsoubde', 'gsoubde.json'),
('{REDDITOR}_{POSTID}', '', 'gsoubde', 'DELETED_gsoubde.json'),
))
@pytest.mark.parametrize(
("test_file_scheme", "test_folder_scheme", "test_comment_id", "expected_name"),
(
("{POSTID}", "", "gsoubde", "gsoubde.json"),
("{REDDITOR}_{POSTID}", "", "gsoubde", "DELETED_gsoubde.json"),
),
)
def test_format_archive_entry_comment(
test_file_scheme: str,
test_folder_scheme: str,
test_comment_id: str,
expected_name: str,
tmp_path: Path,
reddit_instance: praw.Reddit,
test_file_scheme: str,
test_folder_scheme: str,
test_comment_id: str,
expected_name: str,
tmp_path: Path,
reddit_instance: praw.Reddit,
):
test_comment = reddit_instance.comment(id=test_comment_id)
test_formatter = FileNameFormatter(test_file_scheme, test_folder_scheme, 'ISO')
test_entry = Resource(test_comment, '', lambda: None, '.json')
test_formatter = FileNameFormatter(test_file_scheme, test_folder_scheme, "ISO")
test_entry = Resource(test_comment, "", lambda: None, ".json")
result = test_formatter.format_path(test_entry, tmp_path)
assert do_test_string_equality(result, expected_name)
@pytest.mark.parametrize(('test_folder_scheme', 'expected'), (
('{REDDITOR}/{SUBREDDIT}', 'person/randomreddit'),
('{POSTID}/{SUBREDDIT}/{REDDITOR}', '12345/randomreddit/person'),
))
@pytest.mark.parametrize(
("test_folder_scheme", "expected"),
(
("{REDDITOR}/{SUBREDDIT}", "person/randomreddit"),
("{POSTID}/{SUBREDDIT}/{REDDITOR}", "12345/randomreddit/person"),
),
)
def test_multilevel_folder_scheme(
test_folder_scheme: str,
expected: str,
tmp_path: Path,
submission: MagicMock,
test_folder_scheme: str,
expected: str,
tmp_path: Path,
submission: MagicMock,
):
test_formatter = FileNameFormatter('{POSTID}', test_folder_scheme, 'ISO')
test_formatter = FileNameFormatter("{POSTID}", test_folder_scheme, "ISO")
test_resource = MagicMock()
test_resource.source_submission = submission
test_resource.extension = '.png'
test_resource.extension = ".png"
result = test_formatter.format_path(test_resource, tmp_path)
result = result.relative_to(tmp_path)
assert do_test_path_equality(result.parent, expected)
assert len(result.parents) == (len(expected.split('/')) + 1)
assert len(result.parents) == (len(expected.split("/")) + 1)
@pytest.mark.parametrize(('test_name_string', 'expected'), (
('test', 'test'),
('😍', '😍'),
('test😍', 'test😍'),
('test😍 ', 'test😍 '),
('test😍 \\u2019', 'test😍 '),
('Using that real good [1\\4]', 'Using that real good [1\\4]'),
))
@pytest.mark.parametrize(
("test_name_string", "expected"),
(
("test", "test"),
("😍", "😍"),
("test😍", "test😍"),
("test😍 ", "test😍 "),
("test😍 \\u2019", "test😍 "),
("Using that real good [1\\4]", "Using that real good [1\\4]"),
),
)
def test_preserve_emojis(test_name_string: str, expected: str, submission: MagicMock):
submission.title = test_name_string
test_formatter = FileNameFormatter('{TITLE}', '', 'ISO')
result = test_formatter._format_name(submission, '{TITLE}')
test_formatter = FileNameFormatter("{TITLE}", "", "ISO")
result = test_formatter._format_name(submission, "{TITLE}")
assert do_test_string_equality(result, expected)
@pytest.mark.parametrize(('test_string', 'expected'), (
('test \\u2019', 'test '),
('My cat\\u2019s paws are so cute', 'My cats paws are so cute'),
))
@pytest.mark.parametrize(
("test_string", "expected"),
(
("test \\u2019", "test "),
("My cat\\u2019s paws are so cute", "My cats paws are so cute"),
),
)
def test_convert_unicode_escapes(test_string: str, expected: str):
result = FileNameFormatter._convert_unicode_escapes(test_string)
assert result == expected
@pytest.mark.parametrize(('test_datetime', 'expected'), (
(datetime(2020, 1, 1, 8, 0, 0), '2020-01-01T08:00:00'),
(datetime(2020, 1, 1, 8, 0), '2020-01-01T08:00:00'),
(datetime(2021, 4, 21, 8, 30, 21), '2021-04-21T08:30:21'),
))
@pytest.mark.parametrize(
("test_datetime", "expected"),
(
(datetime(2020, 1, 1, 8, 0, 0), "2020-01-01T08:00:00"),
(datetime(2020, 1, 1, 8, 0), "2020-01-01T08:00:00"),
(datetime(2021, 4, 21, 8, 30, 21), "2021-04-21T08:30:21"),
),
)
def test_convert_timestamp(test_datetime: datetime, expected: str):
test_timestamp = test_datetime.timestamp()
test_formatter = FileNameFormatter('{POSTID}', '', 'ISO')
test_formatter = FileNameFormatter("{POSTID}", "", "ISO")
result = test_formatter._convert_timestamp(test_timestamp)
assert result == expected
@pytest.mark.parametrize(('test_time_format', 'expected'), (
('ISO', '2021-05-02T13:33:00'),
('%Y_%m', '2021_05'),
('%Y-%m-%d', '2021-05-02'),
))
@pytest.mark.parametrize(
("test_time_format", "expected"),
(
("ISO", "2021-05-02T13:33:00"),
("%Y_%m", "2021_05"),
("%Y-%m-%d", "2021-05-02"),
),
)
def test_time_string_formats(test_time_format: str, expected: str):
test_time = datetime(2021, 5, 2, 13, 33)
test_formatter = FileNameFormatter('{TITLE}', '', test_time_format)
test_formatter = FileNameFormatter("{TITLE}", "", test_time_format)
result = test_formatter._convert_timestamp(test_time.timestamp())
assert result == expected
@@ -395,29 +460,32 @@ def test_get_max_path_length():
def test_windows_max_path(tmp_path: Path):
with unittest.mock.patch('platform.system', return_value='Windows'):
with unittest.mock.patch('bdfr.file_name_formatter.FileNameFormatter.find_max_path_length', return_value=260):
result = FileNameFormatter.limit_file_name_length('test' * 100, '_1.png', tmp_path)
with unittest.mock.patch("platform.system", return_value="Windows"):
with unittest.mock.patch("bdfr.file_name_formatter.FileNameFormatter.find_max_path_length", return_value=260):
result = FileNameFormatter.limit_file_name_length("test" * 100, "_1.png", tmp_path)
assert len(str(result)) <= 260
assert len(result.name) <= (260 - len(str(tmp_path)))
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.parametrize(('test_reddit_id', 'test_downloader', 'expected_names'), (
('gphmnr', YtdlpFallback, {'He has a lot to say today.mp4'}),
('d0oir2', YtdlpFallback, {"Crunk's finest moment. Welcome to the new subreddit!.mp4"}),
('jiecu', SelfPost, {'[deleted by user].txt'}),
))
@pytest.mark.parametrize(
("test_reddit_id", "test_downloader", "expected_names"),
(
("gphmnr", YtdlpFallback, {"He has a lot to say today.mp4"}),
("d0oir2", YtdlpFallback, {"Crunk's finest moment. Welcome to the new subreddit!.mp4"}),
("jiecu", SelfPost, {"[deleted by user].txt"}),
),
)
def test_name_submission(
test_reddit_id: str,
test_downloader: Type[BaseDownloader],
expected_names: set[str],
reddit_instance: praw.reddit.Reddit,
test_reddit_id: str,
test_downloader: Type[BaseDownloader],
expected_names: set[str],
reddit_instance: praw.reddit.Reddit,
):
test_submission = reddit_instance.submission(id=test_reddit_id)
test_resources = test_downloader(test_submission).find_resources()
test_formatter = FileNameFormatter('{TITLE}', '', '')
results = test_formatter.format_resource_paths(test_resources, Path('.'))
test_formatter = FileNameFormatter("{TITLE}", "", "")
results = test_formatter.format_resource_paths(test_resources, Path("."))
results = set([r[0].name for r in results])
assert results == expected_names

View File

@@ -14,38 +14,58 @@ from bdfr.oauth2 import OAuth2Authenticator, OAuth2TokenManager
@pytest.fixture()
def example_config() -> configparser.ConfigParser:
out = configparser.ConfigParser()
config_dict = {'DEFAULT': {'user_token': 'example'}}
config_dict = {"DEFAULT": {"user_token": "example"}}
out.read_dict(config_dict)
return out
@pytest.mark.online
@pytest.mark.parametrize('test_scopes', (
{'history', },
{'history', 'creddits'},
{'account', 'flair'},
{'*', },
))
@pytest.mark.parametrize(
"test_scopes",
(
{
"history",
},
{"history", "creddits"},
{"account", "flair"},
{
"*",
},
),
)
def test_check_scopes(test_scopes: set[str]):
OAuth2Authenticator._check_scopes(test_scopes)
@pytest.mark.parametrize(('test_scopes', 'expected'), (
('history', {'history', }),
('history creddits', {'history', 'creddits'}),
('history, creddits, account', {'history', 'creddits', 'account'}),
('history,creddits,account,flair', {'history', 'creddits', 'account', 'flair'}),
))
@pytest.mark.parametrize(
("test_scopes", "expected"),
(
(
"history",
{
"history",
},
),
("history creddits", {"history", "creddits"}),
("history, creddits, account", {"history", "creddits", "account"}),
("history,creddits,account,flair", {"history", "creddits", "account", "flair"}),
),
)
def test_split_scopes(test_scopes: str, expected: set[str]):
result = OAuth2Authenticator.split_scopes(test_scopes)
assert result == expected
@pytest.mark.online
@pytest.mark.parametrize('test_scopes', (
{'random', },
{'scope', 'another_scope'},
))
@pytest.mark.parametrize(
"test_scopes",
(
{
"random",
},
{"scope", "another_scope"},
),
)
def test_check_scopes_bad(test_scopes: set[str]):
with pytest.raises(BulkDownloaderException):
OAuth2Authenticator._check_scopes(test_scopes)
@@ -56,16 +76,16 @@ def test_token_manager_read(example_config: configparser.ConfigParser):
mock_authoriser.refresh_token = None
test_manager = OAuth2TokenManager(example_config, MagicMock())
test_manager.pre_refresh_callback(mock_authoriser)
assert mock_authoriser.refresh_token == example_config.get('DEFAULT', 'user_token')
assert mock_authoriser.refresh_token == example_config.get("DEFAULT", "user_token")
def test_token_manager_write(example_config: configparser.ConfigParser, tmp_path: Path):
test_path = tmp_path / 'test.cfg'
test_path = tmp_path / "test.cfg"
mock_authoriser = MagicMock()
mock_authoriser.refresh_token = 'changed_token'
mock_authoriser.refresh_token = "changed_token"
test_manager = OAuth2TokenManager(example_config, test_path)
test_manager.post_refresh_callback(mock_authoriser)
assert example_config.get('DEFAULT', 'user_token') == 'changed_token'
with test_path.open('r') as file:
assert example_config.get("DEFAULT", "user_token") == "changed_token"
with test_path.open("r") as file:
file_contents = file.read()
assert 'user_token = changed_token' in file_contents
assert "user_token = changed_token" in file_contents

View File

@@ -8,18 +8,21 @@ import pytest
from bdfr.resource import Resource
@pytest.mark.parametrize(('test_url', 'expected'), (
('test.png', '.png'),
('another.mp4', '.mp4'),
('test.jpeg', '.jpeg'),
('http://www.random.com/resource.png', '.png'),
('https://www.resource.com/test/example.jpg', '.jpg'),
('hard.png.mp4', '.mp4'),
('https://preview.redd.it/7zkmr1wqqih61.png?width=237&format=png&auto=webp&s=19de214e634cbcad99', '.png'),
('test.jpg#test', '.jpg'),
('test.jpg?width=247#test', '.jpg'),
('https://www.test.com/test/test2/example.png?random=test#thing', '.png'),
))
@pytest.mark.parametrize(
("test_url", "expected"),
(
("test.png", ".png"),
("another.mp4", ".mp4"),
("test.jpeg", ".jpeg"),
("http://www.random.com/resource.png", ".png"),
("https://www.resource.com/test/example.jpg", ".jpg"),
("hard.png.mp4", ".mp4"),
("https://preview.redd.it/7zkmr1wqqih61.png?width=237&format=png&auto=webp&s=19de214e634cbcad99", ".png"),
("test.jpg#test", ".jpg"),
("test.jpg?width=247#test", ".jpg"),
("https://www.test.com/test/test2/example.png?random=test#thing", ".png"),
),
)
def test_resource_get_extension(test_url: str, expected: str):
test_resource = Resource(MagicMock(), test_url, lambda: None)
result = test_resource._determine_extension()
@@ -27,9 +30,10 @@ def test_resource_get_extension(test_url: str, expected: str):
@pytest.mark.online
@pytest.mark.parametrize(('test_url', 'expected_hash'), (
('https://www.iana.org/_img/2013.1/iana-logo-header.svg', '426b3ac01d3584c820f3b7f5985d6623'),
))
@pytest.mark.parametrize(
("test_url", "expected_hash"),
(("https://www.iana.org/_img/2013.1/iana-logo-header.svg", "426b3ac01d3584c820f3b7f5985d6623"),),
)
def test_download_online_resource(test_url: str, expected_hash: str):
test_resource = Resource(MagicMock(), test_url, Resource.retry_download(test_url))
test_resource.download()