tests: move outside of the package
This commit is contained in:
@@ -1,2 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
@@ -1,38 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
import praw
|
||||
import pytest
|
||||
|
||||
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',
|
||||
}),
|
||||
))
|
||||
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)
|
||||
result = test_entry.compile()
|
||||
assert all([result.get(key) == expected_dict[key] for key in expected_dict.keys()])
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@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
|
||||
@@ -1,36 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
import praw
|
||||
import pytest
|
||||
|
||||
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),
|
||||
))
|
||||
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)
|
||||
results = test_archive_entry._get_comments()
|
||||
assert len(results) >= min_comments
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@pytest.mark.parametrize(('test_submission_id', 'expected_dict'), (
|
||||
('m3reby', {
|
||||
'author': 'sinjen-tos',
|
||||
'id': 'm3reby',
|
||||
'link_flair_text': 'image',
|
||||
}),
|
||||
('m3kua3', {'author': 'DELETED'}),
|
||||
))
|
||||
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)
|
||||
test_archive_entry._get_post_details()
|
||||
assert all([test_archive_entry.post_details.get(key) == expected_dict[key] for key in expected_dict.keys()])
|
||||
@@ -1,34 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
import configparser
|
||||
import socket
|
||||
from pathlib import Path
|
||||
|
||||
import praw
|
||||
import pytest
|
||||
|
||||
from bdfr.oauth2 import OAuth2TokenManager
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def reddit_instance():
|
||||
rd = praw.Reddit(client_id='U-6gk4ZCh3IeNQ', client_secret='7CZHY6AmKweZME5s50SfDGylaPg', user_agent='test')
|
||||
return rd
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def authenticated_reddit_instance():
|
||||
test_config_path = Path('test_config.cfg')
|
||||
if not test_config_path.exists():
|
||||
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')
|
||||
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'),
|
||||
user_agent=socket.gethostname(),
|
||||
token_manager=token_manager)
|
||||
return reddit_instance
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
|
||||
from bdfr.resource import Resource
|
||||
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'),
|
||||
))
|
||||
def test_download_resource(test_url: str, expected_hash: str):
|
||||
mock_submission = Mock()
|
||||
mock_submission.url = test_url
|
||||
test_site = Direct(mock_submission)
|
||||
resources = test_site.find_resources()
|
||||
assert len(resources) == 1
|
||||
assert isinstance(resources[0], Resource)
|
||||
resources[0].download(120)
|
||||
assert resources[0].hash.hexdigest() == expected_hash
|
||||
@@ -1,71 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
import praw
|
||||
import pytest
|
||||
|
||||
from bdfr.exceptions import NotADownloadableLinkError
|
||||
from bdfr.site_downloaders.base_downloader import BaseDownloader
|
||||
from bdfr.site_downloaders.direct import Direct
|
||||
from bdfr.site_downloaders.download_factory import DownloadFactory
|
||||
from bdfr.site_downloaders.erome import Erome
|
||||
from bdfr.site_downloaders.gallery import Gallery
|
||||
from bdfr.site_downloaders.gfycat import Gfycat
|
||||
from bdfr.site_downloaders.gif_delivery_network import GifDeliveryNetwork
|
||||
from bdfr.site_downloaders.imgur import Imgur
|
||||
from bdfr.site_downloaders.redgifs import Redgifs
|
||||
from bdfr.site_downloaders.self_post import SelfPost
|
||||
from bdfr.site_downloaders.vreddit import VReddit
|
||||
from bdfr.site_downloaders.youtube import Youtube
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('test_submission_url', 'expected_class'), (
|
||||
('https://v.redd.it/9z1dnk3xr5k61', VReddit),
|
||||
('https://www.reddit.com/r/TwoXChromosomes/comments/lu29zn/i_refuse_to_live_my_life'
|
||||
'_in_anything_but_comfort/', SelfPost),
|
||||
('https://i.imgur.com/bZx1SJQ.jpg', Direct),
|
||||
('https://i.redd.it/affyv0axd5k61.png', Direct),
|
||||
('https://imgur.com/3ls94yv.jpeg', Direct),
|
||||
('https://i.imgur.com/BuzvZwb.gifv', Imgur),
|
||||
('https://imgur.com/BuzvZwb.gifv', Imgur),
|
||||
('https://i.imgur.com/6fNdLst.gif', Direct),
|
||||
('https://imgur.com/a/MkxAzeg', 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', GifDeliveryNetwork),
|
||||
('https://youtu.be/DevfjHOhuFc', Youtube),
|
||||
('https://m.youtube.com/watch?v=kr-FeojxzUM', Youtube),
|
||||
('https://i.imgur.com/3SKrQfK.jpg?1', Direct),
|
||||
('https://dynasty-scans.com/system/images_images/000/017/819/original/80215103_p0.png?1612232781', Direct),
|
||||
('https://m.imgur.com/a/py3RW0j', Imgur),
|
||||
))
|
||||
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/',
|
||||
))
|
||||
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'),
|
||||
))
|
||||
def test_sanitise_urll(test_url: str, expected: str):
|
||||
result = DownloadFactory._sanitise_url(test_url)
|
||||
assert result == expected
|
||||
@@ -1,57 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from bdfr.site_downloaders.erome import Erome
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.parametrize(('test_url', 'expected_urls'), (
|
||||
('https://www.erome.com/a/vqtPuLXh', (
|
||||
'https://s11.erome.com/365/vqtPuLXh/KH2qBT99_480p.mp4',
|
||||
)),
|
||||
('https://www.erome.com/a/ORhX0FZz', (
|
||||
'https://s4.erome.com/355/ORhX0FZz/9IYQocM9_480p.mp4',
|
||||
'https://s4.erome.com/355/ORhX0FZz/9eEDc8xm_480p.mp4',
|
||||
'https://s4.erome.com/355/ORhX0FZz/EvApC7Rp_480p.mp4',
|
||||
'https://s4.erome.com/355/ORhX0FZz/LruobtMs_480p.mp4',
|
||||
'https://s4.erome.com/355/ORhX0FZz/TJNmSUU5_480p.mp4',
|
||||
'https://s4.erome.com/355/ORhX0FZz/X11Skh6Z_480p.mp4',
|
||||
'https://s4.erome.com/355/ORhX0FZz/bjlTkpn7_480p.mp4'
|
||||
)),
|
||||
))
|
||||
def test_get_link(test_url: str, expected_urls: tuple[str]):
|
||||
result = Erome. _get_links(test_url)
|
||||
assert set(result) == set(expected_urls)
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.slow
|
||||
@pytest.mark.parametrize(('test_url', 'expected_hashes'), (
|
||||
('https://www.erome.com/a/vqtPuLXh', {
|
||||
'5da2a8d60d87bed279431fdec8e7d72f'
|
||||
}),
|
||||
('https://www.erome.com/i/ItASD33e', {
|
||||
'b0d73fedc9ce6995c2f2c4fdb6f11eff'
|
||||
}),
|
||||
('https://www.erome.com/a/lGrcFxmb', {
|
||||
'0e98f9f527a911dcedde4f846bb5b69f',
|
||||
'25696ae364750a5303fc7d7dc78b35c1',
|
||||
'63775689f438bd393cde7db6d46187de',
|
||||
'a1abf398cfd4ef9cfaf093ceb10c746a',
|
||||
'bd9e1a4ea5ef0d6ba47fb90e337c2d14'
|
||||
}),
|
||||
))
|
||||
def test_download_resource(test_url: str, expected_hashes: tuple[str]):
|
||||
# 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
|
||||
mock_submission = MagicMock()
|
||||
mock_submission.url = test_url
|
||||
test_site = Erome(mock_submission)
|
||||
resources = test_site.find_resources()
|
||||
[res.download(120) for res in resources]
|
||||
resource_hashes = [res.hash.hexdigest() for res in resources]
|
||||
assert len(resource_hashes) == len(expected_hashes)
|
||||
@@ -1,60 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
import praw
|
||||
import pytest
|
||||
|
||||
from bdfr.site_downloaders.gallery import Gallery
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.parametrize(('test_url', 'expected'), (
|
||||
('https://www.reddit.com/gallery/m6lvrh', {
|
||||
'https://preview.redd.it/18nzv9ch0hn61.jpg?width=4160&'
|
||||
'format=pjpg&auto=webp&s=470a825b9c364e0eace0036882dcff926f821de8',
|
||||
'https://preview.redd.it/jqkizcch0hn61.jpg?width=4160&'
|
||||
'format=pjpg&auto=webp&s=ae4f552a18066bb6727676b14f2451c5feecf805',
|
||||
'https://preview.redd.it/k0fnqzbh0hn61.jpg?width=4160&'
|
||||
'format=pjpg&auto=webp&s=c6a10fececdc33983487c16ad02219fd3fc6cd76',
|
||||
'https://preview.redd.it/m3gamzbh0hn61.jpg?width=4160&'
|
||||
'format=pjpg&auto=webp&s=0dd90f324711851953e24873290b7f29ec73c444'
|
||||
}),
|
||||
('https://www.reddit.com/gallery/ljyy27', {
|
||||
'https://preview.redd.it/04vxj25uqih61.png?width=92&'
|
||||
'format=png&auto=webp&s=6513f3a5c5128ee7680d402cab5ea4fb2bbeead4',
|
||||
'https://preview.redd.it/0fnx83kpqih61.png?width=241&'
|
||||
'format=png&auto=webp&s=655e9deb6f499c9ba1476eaff56787a697e6255a',
|
||||
'https://preview.redd.it/7zkmr1wqqih61.png?width=237&'
|
||||
'format=png&auto=webp&s=19de214e634cbcad9959f19570c616e29be0c0b0',
|
||||
'https://preview.redd.it/u37k5gxrqih61.png?width=443&'
|
||||
'format=png&auto=webp&s=e74dae31841fe4a2545ffd794d3b25b9ff0eb862'
|
||||
}),
|
||||
))
|
||||
def test_gallery_get_links(test_url: str, expected: set[str]):
|
||||
results = Gallery._get_links(test_url)
|
||||
assert set(results) == expected
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@pytest.mark.parametrize(('test_submission_id', 'expected_hashes'), (
|
||||
('m6lvrh', {
|
||||
'6c8a892ae8066cbe119218bcaac731e1',
|
||||
'93ce177f8cb7994906795f4615114d13',
|
||||
'9a293adf19354f14582608cf22124574',
|
||||
'b73e2c3daee02f99404644ea02f1ae65'
|
||||
}),
|
||||
('ljyy27', {
|
||||
'1bc38bed88f9c4770e22a37122d5c941',
|
||||
'2539a92b78f3968a069df2dffe2279f9',
|
||||
'37dea50281c219b905e46edeefc1a18d',
|
||||
'ec4924cf40549728dcf53dd40bc7a73c'
|
||||
}),
|
||||
))
|
||||
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)
|
||||
results = gallery.find_resources()
|
||||
[res.download(120) for res in results]
|
||||
hashes = [res.hash.hexdigest() for res in results]
|
||||
assert set(hashes) == expected_hashes
|
||||
@@ -1,36 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
|
||||
from bdfr.resource import Resource
|
||||
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'),
|
||||
('https://gfycat.com/webbedimpurebutterfly', 'https://thumbs2.redgifs.com/WebbedImpureButterfly.mp4'),
|
||||
))
|
||||
def test_get_link(test_url: str, expected_url: str):
|
||||
result = Gfycat._get_link(test_url)
|
||||
assert result == expected_url
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@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
|
||||
test_site = Gfycat(mock_submission)
|
||||
resources = test_site.find_resources()
|
||||
assert len(resources) == 1
|
||||
assert isinstance(resources[0], Resource)
|
||||
resources[0].download(120)
|
||||
assert resources[0].hash.hexdigest() == expected_hash
|
||||
@@ -1,37 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
|
||||
from bdfr.resource import Resource
|
||||
from bdfr.site_downloaders.gif_delivery_network import GifDeliveryNetwork
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.parametrize(('test_url', 'expected'), (
|
||||
('https://www.gifdeliverynetwork.com/regalshoddyhorsechestnutleafminer',
|
||||
'https://thumbs2.redgifs.com/RegalShoddyHorsechestnutleafminer.mp4'),
|
||||
('https://www.gifdeliverynetwork.com/maturenexthippopotamus',
|
||||
'https://thumbs2.redgifs.com/MatureNextHippopotamus.mp4'),
|
||||
))
|
||||
def test_get_link(test_url: str, expected: str):
|
||||
result = GifDeliveryNetwork._get_link(test_url)
|
||||
assert result == expected
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.parametrize(('test_url', 'expected_hash'), (
|
||||
('https://www.gifdeliverynetwork.com/maturenexthippopotamus', '9bec0a9e4163a43781368ed5d70471df'),
|
||||
('https://www.gifdeliverynetwork.com/regalshoddyhorsechestnutleafminer', '8afb4e2c090a87140230f2352bf8beba'),
|
||||
))
|
||||
def test_download_resource(test_url: str, expected_hash: str):
|
||||
mock_submission = Mock()
|
||||
mock_submission.url = test_url
|
||||
test_site = GifDeliveryNetwork(mock_submission)
|
||||
resources = test_site.find_resources()
|
||||
assert len(resources) == 1
|
||||
assert isinstance(resources[0], Resource)
|
||||
resources[0].download(120)
|
||||
assert resources[0].hash.hexdigest() == expected_hash
|
||||
@@ -1,135 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
|
||||
from bdfr.exceptions import SiteDownloaderError
|
||||
from bdfr.resource import Resource
|
||||
from bdfr.site_downloaders.imgur import Imgur
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@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/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']])
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.parametrize(('test_url', 'expected_image_dict'), (
|
||||
(
|
||||
'https://i.imgur.com/dLk3FGY.gifv',
|
||||
{'hash': 'dLk3FGY', 'title': '', 'ext': '.mp4', 'animated': True}
|
||||
),
|
||||
(
|
||||
'https://imgur.com/BuzvZwb.gifv',
|
||||
{
|
||||
'hash': 'BuzvZwb',
|
||||
'title': '',
|
||||
'description': 'Akron Glass Works',
|
||||
'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'
|
||||
))
|
||||
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',
|
||||
))
|
||||
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'), (
|
||||
(
|
||||
'https://imgur.com/a/xWZsDDP',
|
||||
('f551d6e6b0fef2ce909767338612e31b',)
|
||||
),
|
||||
(
|
||||
'https://imgur.com/gallery/IjJJdlC',
|
||||
('7227d4312a9779b74302724a0cfa9081',),
|
||||
),
|
||||
(
|
||||
'https://imgur.com/a/dcc84Gt',
|
||||
(
|
||||
'cf1158e1de5c3c8993461383b96610cf',
|
||||
'28d6b791a2daef8aa363bf5a3198535d',
|
||||
'248ef8f2a6d03eeb2a80d0123dbaf9b6',
|
||||
'029c475ce01b58fdf1269d8771d33913',
|
||||
),
|
||||
),
|
||||
))
|
||||
def test_find_resources(test_url: str, expected_hashes: list[str]):
|
||||
mock_download = Mock()
|
||||
mock_download.url = test_url
|
||||
downloader = Imgur(mock_download)
|
||||
results = downloader.find_resources()
|
||||
assert all([isinstance(res, Resource) for res in results])
|
||||
[res.download(120) for res in results]
|
||||
hashes = set([res.hash.hexdigest() for res in results])
|
||||
assert len(results) == len(expected_hashes)
|
||||
assert hashes == set(expected_hashes)
|
||||
@@ -1,37 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
|
||||
from bdfr.resource import Resource
|
||||
from bdfr.site_downloaders.redgifs import Redgifs
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.parametrize(('test_url', 'expected'), (
|
||||
('https://redgifs.com/watch/frighteningvictorioussalamander',
|
||||
'https://thumbs2.redgifs.com/FrighteningVictoriousSalamander.mp4'),
|
||||
('https://redgifs.com/watch/springgreendecisivetaruca',
|
||||
'https://thumbs2.redgifs.com/SpringgreenDecisiveTaruca.mp4'),
|
||||
))
|
||||
def test_get_link(test_url: str, expected: str):
|
||||
result = Redgifs._get_link(test_url)
|
||||
assert result == expected
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.parametrize(('test_url', 'expected_hash'), (
|
||||
('https://redgifs.com/watch/frighteningvictorioussalamander', '4007c35d9e1f4b67091b5f12cffda00a'),
|
||||
('https://redgifs.com/watch/springgreendecisivetaruca', '8dac487ac49a1f18cc1b4dabe23f0869'),
|
||||
))
|
||||
def test_download_resource(test_url: str, expected_hash: str):
|
||||
mock_submission = Mock()
|
||||
mock_submission.url = test_url
|
||||
test_site = Redgifs(mock_submission)
|
||||
resources = test_site.find_resources()
|
||||
assert len(resources) == 1
|
||||
assert isinstance(resources[0], Resource)
|
||||
resources[0].download(120)
|
||||
assert resources[0].hash.hexdigest() == expected_hash
|
||||
@@ -1,24 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
import praw
|
||||
import pytest
|
||||
|
||||
from bdfr.resource import Resource
|
||||
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'),
|
||||
))
|
||||
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)
|
||||
results = downloader.find_resources()
|
||||
assert len(results) == 1
|
||||
assert isinstance(results[0], Resource)
|
||||
assert results[0].hash.hexdigest() == expected_hash
|
||||
@@ -1,23 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
import praw
|
||||
import pytest
|
||||
|
||||
from bdfr.resource import Resource
|
||||
from bdfr.site_downloaders.vreddit import VReddit
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@pytest.mark.parametrize(('test_submission_id'), (
|
||||
('lu8l8g'),
|
||||
))
|
||||
def test_find_resources(test_submission_id: str, reddit_instance: praw.Reddit):
|
||||
test_submission = reddit_instance.submission(id=test_submission_id)
|
||||
downloader = VReddit(test_submission)
|
||||
resources = downloader.find_resources()
|
||||
assert len(resources) == 1
|
||||
assert isinstance(resources[0], Resource)
|
||||
resources[0].download(120)
|
||||
assert resources[0].content is not None
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from bdfr.resource import Resource
|
||||
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', 'f70b704b4b78b9bb5cd032bfc26e4971'),
|
||||
('https://www.youtube.com/watch?v=m-tKnjFwleU', '30314930d853afff8ebc7d8c36a5b833'),
|
||||
))
|
||||
def test_find_resources(test_url: str, expected_hash: str):
|
||||
test_submission = MagicMock()
|
||||
test_submission.url = test_url
|
||||
downloader = Youtube(test_submission)
|
||||
resources = downloader.find_resources()
|
||||
assert len(resources) == 1
|
||||
assert isinstance(resources[0], Resource)
|
||||
resources[0].download(120)
|
||||
assert resources[0].hash.hexdigest() == expected_hash
|
||||
@@ -1,57 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import praw
|
||||
import pytest
|
||||
|
||||
from bdfr.archive_entry.submission_archive_entry import SubmissionArchiveEntry
|
||||
from bdfr.archiver import Archiver
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@pytest.mark.parametrize('test_submission_id', (
|
||||
'm3reby',
|
||||
))
|
||||
def test_write_submission_json(test_submission_id: str, tmp_path: Path, reddit_instance: praw.Reddit):
|
||||
archiver_mock = MagicMock()
|
||||
test_path = Path(tmp_path, 'test.json')
|
||||
test_submission = reddit_instance.submission(id=test_submission_id)
|
||||
archiver_mock.file_name_formatter.format_path.return_value = test_path
|
||||
test_entry = SubmissionArchiveEntry(test_submission)
|
||||
Archiver._write_entry_json(archiver_mock, test_entry)
|
||||
archiver_mock._write_content_to_disk.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@pytest.mark.parametrize('test_submission_id', (
|
||||
'm3reby',
|
||||
))
|
||||
def test_write_submission_xml(test_submission_id: str, tmp_path: Path, reddit_instance: praw.Reddit):
|
||||
archiver_mock = MagicMock()
|
||||
test_path = Path(tmp_path, 'test.xml')
|
||||
test_submission = reddit_instance.submission(id=test_submission_id)
|
||||
archiver_mock.file_name_formatter.format_path.return_value = test_path
|
||||
test_entry = SubmissionArchiveEntry(test_submission)
|
||||
Archiver._write_entry_xml(archiver_mock, test_entry)
|
||||
archiver_mock._write_content_to_disk.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@pytest.mark.parametrize('test_submission_id', (
|
||||
'm3reby',
|
||||
))
|
||||
def test_write_submission_yaml(test_submission_id: str, tmp_path: Path, reddit_instance: praw.Reddit):
|
||||
archiver_mock = MagicMock()
|
||||
archiver_mock.download_directory = tmp_path
|
||||
test_path = Path(tmp_path, 'test.yaml')
|
||||
test_submission = reddit_instance.submission(id=test_submission_id)
|
||||
archiver_mock.file_name_formatter.format_path.return_value = test_path
|
||||
test_entry = SubmissionArchiveEntry(test_submission)
|
||||
Archiver._write_entry_yaml(archiver_mock, test_entry)
|
||||
archiver_mock._write_content_to_disk.assert_called_once()
|
||||
@@ -1,24 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from bdfr.configuration import Configuration
|
||||
|
||||
|
||||
@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()
|
||||
test_context.params = arg_dict
|
||||
test_config.process_click_arguments(test_context)
|
||||
test_config = vars(test_config)
|
||||
assert all([test_config[arg] == arg_dict[arg] for arg in arg_dict.keys()])
|
||||
@@ -1,58 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
import pytest
|
||||
|
||||
from bdfr.download_filter import DownloadFilter
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def download_filter() -> DownloadFilter:
|
||||
return DownloadFilter(['mp4', 'mp3'], ['test.com', 'reddit.com'])
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('test_url', 'expected'), (
|
||||
('test.mp4', False),
|
||||
('test.avi', True),
|
||||
('test.random.mp3', False),
|
||||
))
|
||||
def test_filter_extension(test_url: str, expected: bool, download_filter: DownloadFilter):
|
||||
result = download_filter._check_extension(test_url)
|
||||
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),
|
||||
))
|
||||
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),
|
||||
))
|
||||
def test_filter_all(test_url: str, expected: bool, download_filter: DownloadFilter):
|
||||
result = download_filter.check_url(test_url)
|
||||
assert result == expected
|
||||
|
||||
|
||||
@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()
|
||||
result = download_filter.check_url(test_url)
|
||||
assert result is True
|
||||
@@ -1,460 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Iterator
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import praw
|
||||
import praw.models
|
||||
import pytest
|
||||
|
||||
from bdfr.__main__ import setup_logging
|
||||
from bdfr.configuration import Configuration
|
||||
from bdfr.download_filter import DownloadFilter
|
||||
from bdfr.downloader import RedditDownloader, RedditTypes
|
||||
from bdfr.exceptions import BulkDownloaderException
|
||||
from bdfr.file_name_formatter import FileNameFormatter
|
||||
from bdfr.site_authenticator import SiteAuthenticator
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def args() -> Configuration:
|
||||
args = Configuration()
|
||||
return args
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def downloader_mock(args: Configuration):
|
||||
downloader_mock = MagicMock()
|
||||
downloader_mock.args = args
|
||||
downloader_mock._sanitise_subreddit_name = RedditDownloader._sanitise_subreddit_name
|
||||
downloader_mock._split_args_input = RedditDownloader._split_args_input
|
||||
downloader_mock.master_hash_list = {}
|
||||
return downloader_mock
|
||||
|
||||
|
||||
def assert_all_results_are_submissions(result_limit: int, results: list[Iterator]):
|
||||
results = [sub for res in results for sub in res]
|
||||
assert all([isinstance(res, praw.models.Submission) for res in results])
|
||||
if result_limit is not None:
|
||||
assert len(results) == result_limit
|
||||
return results
|
||||
|
||||
|
||||
def test_determine_directories(tmp_path: Path, downloader_mock: MagicMock):
|
||||
downloader_mock.args.directory = tmp_path / 'test'
|
||||
downloader_mock.config_directories.user_config_dir = tmp_path
|
||||
RedditDownloader._determine_directories(downloader_mock)
|
||||
assert Path(tmp_path / 'test').exists()
|
||||
|
||||
|
||||
@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
|
||||
result = RedditDownloader._create_download_filter(downloader_mock)
|
||||
|
||||
assert isinstance(result, DownloadFilter)
|
||||
assert result.excluded_domains == skip_domains
|
||||
assert result.excluded_extensions == skip_extensions
|
||||
|
||||
|
||||
@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 = RedditDownloader._create_time_filter(downloader_mock)
|
||||
|
||||
assert isinstance(result, RedditTypes.TimeType)
|
||||
assert result.name.lower() == expected
|
||||
|
||||
|
||||
@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 = RedditDownloader._create_sort_filter(downloader_mock)
|
||||
|
||||
assert isinstance(result, RedditTypes.SortType)
|
||||
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}'),
|
||||
))
|
||||
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
|
||||
result = RedditDownloader._create_file_name_formatter(downloader_mock)
|
||||
|
||||
assert isinstance(result, FileNameFormatter)
|
||||
assert result.file_format_string == test_file_scheme
|
||||
assert result.directory_format_string == test_folder_scheme.split('/')
|
||||
|
||||
|
||||
@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
|
||||
with pytest.raises(BulkDownloaderException):
|
||||
RedditDownloader._create_file_name_formatter(downloader_mock)
|
||||
|
||||
|
||||
def test_create_authenticator(downloader_mock: MagicMock):
|
||||
result = RedditDownloader._create_authenticator(downloader_mock)
|
||||
assert isinstance(result, SiteAuthenticator)
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@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):
|
||||
downloader_mock.args.link = test_submission_ids
|
||||
downloader_mock.reddit_instance = reddit_instance
|
||||
results = RedditDownloader._get_submissions_from_link(downloader_mock)
|
||||
assert all([isinstance(sub, praw.models.Submission) for res in results for sub in res])
|
||||
assert len(results[0]) == len(test_submission_ids)
|
||||
|
||||
|
||||
@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),
|
||||
))
|
||||
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,
|
||||
):
|
||||
downloader_mock._determine_sort_function.return_value = praw.models.Subreddit.hot
|
||||
downloader_mock.args.limit = limit
|
||||
downloader_mock.args.sort = sort_type
|
||||
downloader_mock.args.subreddit = test_subreddits
|
||||
downloader_mock.reddit_instance = reddit_instance
|
||||
downloader_mock.sort_filter = RedditDownloader._create_sort_filter(downloader_mock)
|
||||
results = RedditDownloader._get_subreddits(downloader_mock)
|
||||
test_subreddits = downloader_mock._split_args_input(test_subreddits)
|
||||
results = [sub for res1 in results for sub in res1]
|
||||
assert all([isinstance(res1, praw.models.Submission) for res1 in results])
|
||||
assert all([res.subreddit.display_name in test_subreddits for res in results])
|
||||
assert len(results) <= max_expected_len
|
||||
|
||||
|
||||
@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', 10),
|
||||
(('Python',), 'djsdsgewef', 10, 'all', 0),
|
||||
(('Python',), 'scraper', 10, 'year', 10),
|
||||
(('Python',), 'scraper', 10, 'hour', 1),
|
||||
))
|
||||
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,
|
||||
):
|
||||
downloader_mock._determine_sort_function.return_value = praw.models.Subreddit.hot
|
||||
downloader_mock.args.limit = limit
|
||||
downloader_mock.args.search = search_term
|
||||
downloader_mock.args.subreddit = test_subreddits
|
||||
downloader_mock.reddit_instance = reddit_instance
|
||||
downloader_mock.sort_filter = RedditTypes.SortType.HOT
|
||||
downloader_mock.args.time = time_filter
|
||||
downloader_mock.time_filter = RedditDownloader._create_time_filter(downloader_mock)
|
||||
results = RedditDownloader._get_subreddits(downloader_mock)
|
||||
results = [sub for res in results for sub in res]
|
||||
assert all([isinstance(res, praw.models.Submission) for res in results])
|
||||
assert all([res.subreddit.display_name in test_subreddits for res in results])
|
||||
assert len(results) <= max_expected_len
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@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,
|
||||
):
|
||||
downloader_mock._determine_sort_function.return_value = praw.models.Subreddit.hot
|
||||
downloader_mock.sort_filter = RedditTypes.SortType.HOT
|
||||
downloader_mock.args.limit = limit
|
||||
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 = \
|
||||
RedditDownloader._create_filtered_listing_generator(
|
||||
downloader_mock,
|
||||
reddit_instance.multireddit(test_user, test_multireddits[0]),
|
||||
)
|
||||
results = RedditDownloader._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])
|
||||
assert len(results) == limit
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@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
|
||||
downloader_mock.sort_filter = RedditTypes.SortType.HOT
|
||||
downloader_mock.args.submitted = True
|
||||
downloader_mock.args.user = test_user
|
||||
downloader_mock.authenticated = False
|
||||
downloader_mock.reddit_instance = reddit_instance
|
||||
downloader_mock._create_filtered_listing_generator.return_value = \
|
||||
RedditDownloader._create_filtered_listing_generator(
|
||||
downloader_mock,
|
||||
reddit_instance.redditor(test_user).submissions,
|
||||
)
|
||||
results = RedditDownloader._get_user_data(downloader_mock)
|
||||
results = assert_all_results_are_submissions(limit, results)
|
||||
assert all([res.author.name == test_user for res in results])
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@pytest.mark.authenticated
|
||||
@pytest.mark.parametrize('test_flag', (
|
||||
'upvoted',
|
||||
'saved',
|
||||
))
|
||||
def test_get_user_authenticated_lists(
|
||||
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.user = 'me'
|
||||
downloader_mock.args.limit = 10
|
||||
downloader_mock._determine_sort_function.return_value = praw.models.Subreddit.hot
|
||||
downloader_mock.sort_filter = RedditTypes.SortType.HOT
|
||||
RedditDownloader._resolve_user_name(downloader_mock)
|
||||
results = RedditDownloader._get_user_data(downloader_mock)
|
||||
assert_all_results_are_submissions(10, results)
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@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):
|
||||
downloader_mock.reddit_instance = reddit_instance
|
||||
downloader_mock.download_filter.check_url.return_value = True
|
||||
downloader_mock.args.folder_scheme = ''
|
||||
downloader_mock.file_name_formatter = RedditDownloader._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)
|
||||
folder_contents = list(tmp_path.iterdir())
|
||||
assert len(folder_contents) == expected_files_len
|
||||
|
||||
|
||||
@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
|
||||
):
|
||||
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.file_name_formatter = RedditDownloader._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()
|
||||
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 already exists' in output.out
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@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
|
||||
):
|
||||
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.no_dupes = True
|
||||
downloader_mock.file_name_formatter = RedditDownloader._create_file_name_formatter(downloader_mock)
|
||||
downloader_mock.download_directory = tmp_path
|
||||
downloader_mock.master_hash_list = {test_hash: None}
|
||||
submission = downloader_mock.reddit_instance.submission(id=test_submission_id)
|
||||
RedditDownloader._download_submission(downloader_mock, submission)
|
||||
folder_contents = list(tmp_path.iterdir())
|
||||
output = capsys.readouterr()
|
||||
assert len(folder_contents) == 0
|
||||
assert re.search(r'Resource hash .*? downloaded elsewhere', output.out)
|
||||
|
||||
|
||||
@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 = RedditDownloader._sanitise_subreddit_name(test_name)
|
||||
assert result == expected
|
||||
|
||||
|
||||
def test_search_existing_files():
|
||||
results = RedditDownloader.scan_existing_files(Path('.'))
|
||||
assert len(results.keys()) >= 40
|
||||
|
||||
|
||||
@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'})
|
||||
))
|
||||
def test_split_subreddit_entries(test_subreddit_entries: list[str], expected: set[str]):
|
||||
results = RedditDownloader._split_args_input(test_subreddit_entries)
|
||||
assert results == expected
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@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
|
||||
):
|
||||
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.file_name_formatter = RedditDownloader._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')
|
||||
|
||||
RedditDownloader._download_submission(downloader_mock, submission)
|
||||
assert original.exists()
|
||||
|
||||
downloader_mock.args.file_scheme = 'test2_{POSTID}'
|
||||
downloader_mock.file_name_formatter = RedditDownloader._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
|
||||
|
||||
assert test_file_1_stats.st_nlink == 2
|
||||
assert test_file_1_stats.st_ino == test_file_2_inode
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('test_ids', 'test_excluded', 'expected_len'), (
|
||||
(('aaaaaa',), (), 1),
|
||||
(('aaaaaa',), ('aaaaaa',), 0),
|
||||
((), ('aaaaaa',), 0),
|
||||
(('aaaaaa', 'bbbbbb'), ('aaaaaa',), 1),
|
||||
))
|
||||
def test_excluded_ids(test_ids: tuple[str], test_excluded: tuple[str], expected_len: int, downloader_mock: MagicMock):
|
||||
downloader_mock.excluded_submission_ids = test_excluded
|
||||
test_submissions = []
|
||||
for test_id in test_ids:
|
||||
m = MagicMock()
|
||||
m.id = test_id
|
||||
test_submissions.append(m)
|
||||
downloader_mock.reddit_lists = [test_submissions]
|
||||
RedditDownloader.download(downloader_mock)
|
||||
assert downloader_mock._download_submission.call_count == expected_len
|
||||
|
||||
|
||||
def test_read_excluded_submission_ids_from_file(downloader_mock: MagicMock, tmp_path: Path):
|
||||
test_file = tmp_path / 'test.txt'
|
||||
test_file.write_text('aaaaaa\nbbbbbb')
|
||||
downloader_mock.args.exclude_id_file = [test_file]
|
||||
results = RedditDownloader._read_excluded_ids(downloader_mock)
|
||||
assert results == {'aaaaaa', 'bbbbbb'}
|
||||
@@ -1,320 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import praw.models
|
||||
import pytest
|
||||
|
||||
from bdfr.file_name_formatter import FileNameFormatter
|
||||
from bdfr.resource import Resource
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def submission() -> MagicMock:
|
||||
test = MagicMock()
|
||||
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.created_utc = 123456789
|
||||
test.__class__ = praw.models.Submission
|
||||
return test
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def reddit_submission(reddit_instance: praw.Reddit) -> praw.models.Submission:
|
||||
return reddit_instance.submission(id='lgilgt')
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('format_string', 'expected'), (
|
||||
('{SUBREDDIT}', 'randomreddit'),
|
||||
('{REDDITOR}', 'person'),
|
||||
('{POSTID}', '12345'),
|
||||
('{UPVOTES}', '1000'),
|
||||
('{FLAIR}', 'test_flair'),
|
||||
('{DATE}', '123456789'),
|
||||
('{REDDITOR}_{TITLE}_{POSTID}', 'person_name_12345'),
|
||||
('{RANDOM}', '{RANDOM}'),
|
||||
))
|
||||
def test_format_name_mock(format_string: str, expected: str, submission: MagicMock):
|
||||
result = FileNameFormatter._format_name(submission, format_string)
|
||||
assert result == expected
|
||||
|
||||
|
||||
@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
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@pytest.mark.parametrize(('format_string', 'expected'), (
|
||||
('{SUBREDDIT}', 'Mindustry'),
|
||||
('{REDDITOR}', 'Gamer_player_boi'),
|
||||
('{POSTID}', 'lgilgt'),
|
||||
('{FLAIR}', 'Art'),
|
||||
('{SUBREDDIT}_{TITLE}', 'Mindustry_Toxopid that is NOT humane >:('),
|
||||
('{REDDITOR}_{TITLE}_{POSTID}', 'Gamer_player_boi_Toxopid that is NOT humane >:(_lgilgt')
|
||||
))
|
||||
def test_format_name_real(format_string: str, expected: str, reddit_submission: praw.models.Submission):
|
||||
result = FileNameFormatter._format_name(reddit_submission, format_string)
|
||||
assert result == expected
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@pytest.mark.parametrize(('format_string_directory', 'format_string_file', 'expected'), (
|
||||
(
|
||||
'{SUBREDDIT}',
|
||||
'{POSTID}',
|
||||
'test/Mindustry/lgilgt.png',
|
||||
),
|
||||
(
|
||||
'{SUBREDDIT}',
|
||||
'{TITLE}_{POSTID}',
|
||||
'test/Mindustry/Toxopid that is NOT humane >:(_lgilgt.png',
|
||||
),
|
||||
(
|
||||
'{SUBREDDIT}',
|
||||
'{REDDITOR}_{TITLE}_{POSTID}',
|
||||
'test/Mindustry/Gamer_player_boi_Toxopid that is NOT humane >:(_lgilgt.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')
|
||||
test_formatter = FileNameFormatter(format_string_file, format_string_directory)
|
||||
result = test_formatter.format_path(test_resource, Path('test'))
|
||||
assert str(result) == expected
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@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')
|
||||
test_formatter = FileNameFormatter(format_string_file, format_string_directory)
|
||||
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/Mindustry/lgilgt.png'),
|
||||
('{SUBREDDIT}', '{POSTID}', 1, 'test/Mindustry/lgilgt_1.png'),
|
||||
('{SUBREDDIT}', '{POSTID}', 2, 'test/Mindustry/lgilgt_2.png'),
|
||||
('{SUBREDDIT}', '{TITLE}_{POSTID}', 2, 'test/Mindustry/Toxopid that is NOT humane >:(_lgilgt_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,
|
||||
):
|
||||
test_resource = Resource(reddit_submission, 'i.reddit.com/blabla.png')
|
||||
test_formatter = FileNameFormatter(format_string_file, format_string_directory)
|
||||
result = test_formatter.format_path(test_resource, Path('test'), index)
|
||||
assert str(result) == expected
|
||||
|
||||
|
||||
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.source_submission.__class__ = praw.models.Submission
|
||||
mocks.append(new_mock)
|
||||
test_formatter = FileNameFormatter('{TITLE}', '')
|
||||
results = test_formatter.format_resource_paths(mocks, Path('.'))
|
||||
results = set([str(res[0]) for res in results])
|
||||
assert results == {'test_1.png', 'test_2.png', 'test_3.png', 'test_4.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)
|
||||
assert len(result) <= 255
|
||||
assert len(result.encode('utf-8')) <= 255
|
||||
assert isinstance(result, str)
|
||||
|
||||
|
||||
@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)
|
||||
assert len(result) <= 255
|
||||
assert len(result.encode('utf-8')) <= 255
|
||||
assert isinstance(result, str)
|
||||
assert result.endswith(expected_end)
|
||||
|
||||
|
||||
def test_shorten_filenames(submission: MagicMock, tmp_path: Path):
|
||||
submission.title = 'A' * 300
|
||||
submission.author.name = 'test'
|
||||
submission.subreddit.display_name = 'test'
|
||||
submission.id = 'BBBBBB'
|
||||
test_resource = Resource(submission, 'www.example.com/empty', '.jpeg')
|
||||
test_formatter = FileNameFormatter('{REDDITOR}_{TITLE}_{POSTID}', '{SUBREDDIT}')
|
||||
result = test_formatter.format_path(test_resource, tmp_path)
|
||||
result.parent.mkdir(parents=True)
|
||||
result.touch()
|
||||
|
||||
|
||||
@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'),
|
||||
('😍', ''),
|
||||
))
|
||||
def test_strip_emojies(test_string: str, expected: str):
|
||||
result = FileNameFormatter._strip_emojis(test_string)
|
||||
assert result == expected
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@pytest.mark.reddit
|
||||
@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)
|
||||
result = FileNameFormatter._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': '',
|
||||
}),
|
||||
))
|
||||
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)
|
||||
result = FileNameFormatter._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'),
|
||||
))
|
||||
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_comment = reddit_instance.comment(id=test_comment_id)
|
||||
test_formatter = FileNameFormatter(test_file_scheme, test_folder_scheme)
|
||||
test_entry = Resource(test_comment, '', '.json')
|
||||
result = test_formatter.format_path(test_entry, tmp_path)
|
||||
assert result.name == expected_name
|
||||
|
||||
|
||||
@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_formatter = FileNameFormatter('{POSTID}', test_folder_scheme)
|
||||
test_resource = MagicMock()
|
||||
test_resource.source_submission = submission
|
||||
test_resource.extension = '.png'
|
||||
result = test_formatter.format_path(test_resource, tmp_path)
|
||||
result = result.relative_to(tmp_path)
|
||||
assert str(result.parent) == expected
|
||||
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]'),
|
||||
))
|
||||
def test_preserve_emojis(test_name_string: str, expected: str, submission: MagicMock):
|
||||
submission.title = test_name_string
|
||||
result = FileNameFormatter._format_name(submission, '{TITLE}')
|
||||
assert result == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('test_string', 'expected'), (
|
||||
('test \\u2019', 'test ’'),
|
||||
('My cat\\u2019s paws are so cute', 'My cat’s paws are so cute'),
|
||||
))
|
||||
def test_convert_unicode_escapes(test_string: str, expected: str):
|
||||
result = FileNameFormatter._convert_unicode_escapes(test_string)
|
||||
assert result == expected
|
||||
@@ -1,315 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
from bdfr.__main__ import cli
|
||||
|
||||
does_test_config_exist = Path('test_config.cfg').exists()
|
||||
|
||||
@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', 1],
|
||||
['-s', 'r/Mindustry', '-L', 1],
|
||||
['-s', 'r/mindustry', '-L', 1],
|
||||
['-s', 'mindustry', '-L', 1],
|
||||
['-s', 'https://www.reddit.com/r/TrollXChromosomes/', '-L', 1],
|
||||
['-s', 'r/TrollXChromosomes/', '-L', 1],
|
||||
['-s', 'TrollXChromosomes/', '-L', 1],
|
||||
['-s', 'trollxchromosomes', '-L', 1],
|
||||
['-s', 'trollxchromosomes,mindustry,python', '-L', 1],
|
||||
['-s', 'trollxchromosomes, mindustry, python', '-L', 1],
|
||||
['-s', 'trollxchromosomes', '-L', 1, '--time', 'day'],
|
||||
['-s', 'trollxchromosomes', '-L', 1, '--sort', 'new'],
|
||||
['-s', 'trollxchromosomes', '-L', 1, '--time', 'day', '--sort', 'new'],
|
||||
['-s', 'trollxchromosomes', '-L', 1, '--search', 'women'],
|
||||
['-s', 'trollxchromosomes', '-L', 1, '--time', 'day', '--search', 'women'],
|
||||
['-s', 'trollxchromosomes', '-L', 1, '--sort', 'new', '--search', 'women'],
|
||||
['-s', 'trollxchromosomes', '-L', 1, '--time', 'day', '--sort', 'new', '--search', 'women'],
|
||||
))
|
||||
def test_cli_download_subreddits(test_args: list[str], tmp_path: Path):
|
||||
runner = CliRunner()
|
||||
test_args = ['download', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
result = runner.invoke(cli, test_args)
|
||||
assert result.exit_code == 0
|
||||
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', 'm2601g'],
|
||||
['-l', 'https://www.reddit.com/r/TrollXChromosomes/comments/m2601g/its_a_step_in_the_right_direction/'],
|
||||
['-l', 'm3hxzd'], # Really long title used to overflow filename limit
|
||||
['-l', 'm3kua3'], # Has a deleted user
|
||||
['-l', 'm5bqkf'], # Resource leading to a 404
|
||||
))
|
||||
def test_cli_download_links(test_args: list[str], tmp_path: Path):
|
||||
runner = CliRunner()
|
||||
test_args = ['download', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
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', (
|
||||
['--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 = ['download', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
result = runner.invoke(cli, test_args)
|
||||
assert result.exit_code == 0
|
||||
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],
|
||||
))
|
||||
def test_cli_download_multireddit_nonexistent(test_args: list[str], tmp_path: Path):
|
||||
runner = CliRunner()
|
||||
test_args = ['download', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
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
|
||||
|
||||
|
||||
@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', '--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 = ['download', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
result = runner.invoke(cli, test_args)
|
||||
assert result.exit_code == 0
|
||||
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', ''],
|
||||
))
|
||||
def test_cli_download_user_data_bad_me_unauthenticated(test_args: list[str], tmp_path: Path):
|
||||
runner = CliRunner()
|
||||
test_args = ['download', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
result = runner.invoke(cli, test_args)
|
||||
assert result.exit_code == 0
|
||||
assert 'To use "me" as a user, an authenticated Reddit instance must be used' 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', 'python', '-L', 10, '--search-existing'],
|
||||
))
|
||||
def test_cli_download_search_existing(test_args: list[str], tmp_path: Path):
|
||||
Path(tmp_path, 'test.txt').touch()
|
||||
runner = CliRunner()
|
||||
test_args = ['download', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
result = runner.invoke(cli, test_args)
|
||||
assert result.exit_code == 0
|
||||
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'],
|
||||
))
|
||||
def test_cli_download_download_filters(test_args: list[str], tmp_path: Path):
|
||||
runner = CliRunner()
|
||||
test_args = ['download', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
result = runner.invoke(cli, test_args)
|
||||
assert result.exit_code == 0
|
||||
assert 'Download filter removed submission' 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', '--sort', 'new'],
|
||||
))
|
||||
def test_cli_download_long(test_args: list[str], tmp_path: Path):
|
||||
runner = CliRunner()
|
||||
test_args = ['download', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
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', 'gstd4hk'],
|
||||
['-l', 'm2601g'],
|
||||
))
|
||||
def test_cli_archive_single(test_args: list[str], tmp_path: Path):
|
||||
runner = CliRunner()
|
||||
test_args = ['archive', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
result = runner.invoke(cli, test_args)
|
||||
assert result.exit_code == 0
|
||||
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'],
|
||||
))
|
||||
def test_cli_archive_subreddit(test_args: list[str], tmp_path: Path):
|
||||
runner = CliRunner()
|
||||
test_args = ['archive', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
result = runner.invoke(cli, test_args)
|
||||
assert result.exit_code == 0
|
||||
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'],
|
||||
))
|
||||
def test_cli_archive_all_user_comments(test_args: list[str], tmp_path: Path):
|
||||
runner = CliRunner()
|
||||
test_args = ['archive', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
result = runner.invoke(cli, test_args)
|
||||
assert result.exit_code == 0
|
||||
|
||||
|
||||
@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'],
|
||||
))
|
||||
def test_cli_archive_long(test_args: list[str], tmp_path: Path):
|
||||
runner = CliRunner()
|
||||
test_args = ['archive', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
result = runner.invoke(cli, test_args)
|
||||
assert result.exit_code == 0
|
||||
assert re.search(r'Writing entry .*? to file in .*? format', 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', (
|
||||
['--user', 'sdclhgsolgjeroij', '--submitted', '-L', 10],
|
||||
['--user', 'me', '--upvoted', '-L', 10],
|
||||
['--user', 'sdclhgsolgjeroij', '--upvoted', '-L', 10],
|
||||
))
|
||||
def test_cli_download_soft_fail(test_args: list[str], tmp_path: Path):
|
||||
runner = CliRunner()
|
||||
test_args = ['download', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
result = runner.invoke(cli, test_args)
|
||||
assert result.exit_code == 0
|
||||
|
||||
|
||||
@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'],
|
||||
))
|
||||
def test_cli_download_hard_fail(test_args: list[str], tmp_path: Path):
|
||||
runner = CliRunner()
|
||||
test_args = ['download', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
result = runner.invoke(cli, test_args)
|
||||
assert result.exit_code != 0
|
||||
|
||||
|
||||
def test_cli_download_use_default_config(tmp_path: Path):
|
||||
runner = CliRunner()
|
||||
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', 'm2601g', '--exclude-id', 'm2601g'],
|
||||
))
|
||||
def test_cli_download_links_exclusion(test_args: list[str], tmp_path: Path):
|
||||
runner = CliRunner()
|
||||
test_args = ['download', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
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
|
||||
|
||||
|
||||
@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', '--skip-subreddit', 'trollxchromosomes'],
|
||||
['-s', 'trollxchromosomes', '--skip-subreddit', 'trollxchromosomes', '-L', '3'],
|
||||
))
|
||||
def test_cli_download_subreddit_exclusion(test_args: list[str], tmp_path: Path):
|
||||
runner = CliRunner()
|
||||
test_args = ['download', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
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
|
||||
|
||||
|
||||
@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}'],
|
||||
))
|
||||
def test_cli_file_scheme_warning(test_args: list[str], tmp_path: Path):
|
||||
runner = CliRunner()
|
||||
test_args = ['download', str(tmp_path), '-v', '--config', 'test_config.cfg'] + test_args
|
||||
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
|
||||
@@ -1,71 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
import configparser
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from bdfr.exceptions import BulkDownloaderException
|
||||
from bdfr.oauth2 import OAuth2Authenticator, OAuth2TokenManager
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def example_config() -> configparser.ConfigParser:
|
||||
out = configparser.ConfigParser()
|
||||
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'},
|
||||
{'*', },
|
||||
))
|
||||
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'}),
|
||||
))
|
||||
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'},
|
||||
))
|
||||
def test_check_scopes_bad(test_scopes: set[str]):
|
||||
with pytest.raises(BulkDownloaderException):
|
||||
OAuth2Authenticator._check_scopes(test_scopes)
|
||||
|
||||
|
||||
def test_token_manager_read(example_config: configparser.ConfigParser):
|
||||
mock_authoriser = MagicMock()
|
||||
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')
|
||||
|
||||
|
||||
def test_token_manager_write(example_config: configparser.ConfigParser, tmp_path: Path):
|
||||
test_path = tmp_path / 'test.cfg'
|
||||
mock_authoriser = MagicMock()
|
||||
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 open(test_path, 'r') as file:
|
||||
file_contents = file.read()
|
||||
assert 'user_token = changed_token' in file_contents
|
||||
@@ -1,36 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
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'),
|
||||
))
|
||||
def test_resource_get_extension(test_url: str, expected: str):
|
||||
test_resource = Resource(MagicMock(), test_url)
|
||||
result = test_resource._determine_extension()
|
||||
assert result == expected
|
||||
|
||||
|
||||
@pytest.mark.online
|
||||
@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)
|
||||
test_resource.download(120)
|
||||
assert test_resource.hash.hexdigest() == expected_hash
|
||||
Reference in New Issue
Block a user