[tests] Speed up tests
This commit is contained in:
@ -82,8 +82,7 @@ types-requests = "^2.27"
|
|||||||
bandit = "^1.7.4"
|
bandit = "^1.7.4"
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
minversion = "6.0"
|
addopts = "-ra -q --reuse-db --no-migrations"
|
||||||
addopts = "-ra -q --reuse-db"
|
|
||||||
testpaths = ["tests"]
|
testpaths = ["tests"]
|
||||||
DJANGO_SETTINGS_MODULE='vrobbler.settings-testing'
|
DJANGO_SETTINGS_MODULE='vrobbler.settings-testing'
|
||||||
|
|
||||||
|
|||||||
98
tests/videos_tests/test_api.py
Normal file
98
tests/videos_tests/test_api.py
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import pytest
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from rest_framework.authtoken.models import Token
|
||||||
|
|
||||||
|
from videos.models import Channel, Series, Video
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def auth_headers():
|
||||||
|
user = User.objects.create(email="api@test.com")
|
||||||
|
token = Token.objects.create(user=user)
|
||||||
|
return {"HTTP_AUTHORIZATION": f"Token {token.key}"}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def channel():
|
||||||
|
return Channel.objects.create(name="Test Channel")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def series():
|
||||||
|
return Series.objects.create(
|
||||||
|
name="Test Series",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def video(channel):
|
||||||
|
return Video.objects.create(
|
||||||
|
title="Test Video",
|
||||||
|
imdb_id="tt1234567",
|
||||||
|
channel=channel,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
class TestVideoAPI:
|
||||||
|
def test_list_videos(self, client, auth_headers, video):
|
||||||
|
response = client.get("/api/v1/videos/", **auth_headers)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert len(response.data["results"]) == 1
|
||||||
|
assert response.data["results"][0]["title"] == "Test Video"
|
||||||
|
|
||||||
|
def test_get_video(self, client, auth_headers, video):
|
||||||
|
response = client.get(f"/api/v1/videos/{video.id}/", **auth_headers)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.data["title"] == "Test Video"
|
||||||
|
|
||||||
|
def test_filter_videos_by_channel(self, client, auth_headers, channel, video):
|
||||||
|
response = client.get(f"/api/v1/videos/?channel={channel.id}", **auth_headers)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert len(response.data["results"]) == 1
|
||||||
|
assert response.data["results"][0]["channel"] == channel.id
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
class TestChannelAPI:
|
||||||
|
def test_list_channels(self, client, auth_headers, channel):
|
||||||
|
response = client.get("/api/v1/channels/", **auth_headers)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert len(response.data["results"]) == 1
|
||||||
|
assert response.data["results"][0]["name"] == "Test Channel"
|
||||||
|
|
||||||
|
def test_get_channel(self, client, auth_headers, channel):
|
||||||
|
response = client.get(f"/api/v1/channels/{channel.id}/", **auth_headers)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.data["name"] == "Test Channel"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
class TestSeriesAPI:
|
||||||
|
def test_list_series(self, client, auth_headers, series):
|
||||||
|
response = client.get("/api/v1/series/", **auth_headers)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert len(response.data["results"]) == 1
|
||||||
|
assert response.data["results"][0]["name"] == "Test Series"
|
||||||
|
|
||||||
|
def test_get_series(self, client, auth_headers, series):
|
||||||
|
response = client.get(f"/api/v1/series/{series.id}/", **auth_headers)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.data["name"] == "Test Series"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
class TestVideoAPIUnauthorized:
|
||||||
|
def test_list_videos_unauthenticated(self, client, video):
|
||||||
|
response = client.get("/api/v1/videos/")
|
||||||
|
assert response.status_code == 401
|
||||||
|
|
||||||
|
def test_list_channels_unauthenticated(self, client, channel):
|
||||||
|
response = client.get("/api/v1/channels/")
|
||||||
|
assert response.status_code == 401
|
||||||
|
|
||||||
|
def test_list_series_unauthenticated(self, client, series):
|
||||||
|
response = client.get("/api/v1/series/")
|
||||||
|
assert response.status_code == 401
|
||||||
@ -1,10 +1,14 @@
|
|||||||
|
import pytest
|
||||||
from videos.sources.imdb import lookup_video_from_imdb
|
from videos.sources.imdb import lookup_video_from_imdb
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip(reason="Should not hit IMDB api in CI")
|
||||||
def test_lookup_imdb_without_tt():
|
def test_lookup_imdb_without_tt():
|
||||||
metadata = lookup_video_from_imdb("8946378")
|
metadata = lookup_video_from_imdb("8946378")
|
||||||
print(metadata.__dict__)
|
|
||||||
assert not metadata.imdb_id
|
assert not metadata.imdb_id
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip(reason="Should not hit IMDB api in CI")
|
||||||
def test_lookup_imdb_with_tt():
|
def test_lookup_imdb_with_tt():
|
||||||
metadata = lookup_video_from_imdb("tt8946378")
|
metadata = lookup_video_from_imdb("tt8946378")
|
||||||
assert metadata.title == "Knives Out"
|
assert metadata.title == "Knives Out"
|
||||||
|
|||||||
@ -64,7 +64,10 @@ def mopidy_scrobble_media(post_data: dict, user_id: int) -> Scrobble:
|
|||||||
if media_type == Scrobble.MediaType.PODCAST_EPISODE:
|
if media_type == Scrobble.MediaType.PODCAST_EPISODE:
|
||||||
parsed_data = parse_mopidy_uri(post_data.get("mopidy_uri", ""))
|
parsed_data = parse_mopidy_uri(post_data.get("mopidy_uri", ""))
|
||||||
if not parsed_data:
|
if not parsed_data:
|
||||||
logger.warning("Tried to scrobble podcast but no uri found", extra={"post_data": post_data})
|
logger.warning(
|
||||||
|
"Tried to scrobble podcast but no uri found",
|
||||||
|
extra={"post_data": post_data},
|
||||||
|
)
|
||||||
return Scrobble()
|
return Scrobble()
|
||||||
|
|
||||||
media_obj = PodcastEpisode.find_or_create(**parsed_data)
|
media_obj = PodcastEpisode.find_or_create(**parsed_data)
|
||||||
@ -167,7 +170,10 @@ def web_scrobbler_scrobble_media(
|
|||||||
|
|
||||||
|
|
||||||
def manual_scrobble_video(
|
def manual_scrobble_video(
|
||||||
video_id: str, user_id: int, source: str = "IMDb", action: Optional[str] = None
|
video_id: str,
|
||||||
|
user_id: int,
|
||||||
|
source: str = "IMDb",
|
||||||
|
action: Optional[str] = None,
|
||||||
):
|
):
|
||||||
video = Video.find_or_create(video_id)
|
video = Video.find_or_create(video_id)
|
||||||
|
|
||||||
@ -200,7 +206,10 @@ def manual_scrobble_video(
|
|||||||
|
|
||||||
|
|
||||||
def manual_scrobble_event(
|
def manual_scrobble_event(
|
||||||
thesportsdb_id: str, user_id: int, source: str = "TheSportsDB", action: Optional[str] = None
|
thesportsdb_id: str,
|
||||||
|
user_id: int,
|
||||||
|
source: str = "TheSportsDB",
|
||||||
|
action: Optional[str] = None,
|
||||||
):
|
):
|
||||||
data_dict = lookup_event_from_thesportsdb(thesportsdb_id)
|
data_dict = lookup_event_from_thesportsdb(thesportsdb_id)
|
||||||
|
|
||||||
@ -215,7 +224,10 @@ def manual_scrobble_event(
|
|||||||
|
|
||||||
|
|
||||||
def manual_scrobble_video_game(
|
def manual_scrobble_video_game(
|
||||||
hltb_id: str, user_id: int, source: str = "HLTB", action: Optional[str] = None
|
hltb_id: str,
|
||||||
|
user_id: int,
|
||||||
|
source: str = "HLTB",
|
||||||
|
action: Optional[str] = None,
|
||||||
):
|
):
|
||||||
game = VideoGame.objects.filter(hltb_id=hltb_id).first()
|
game = VideoGame.objects.filter(hltb_id=hltb_id).first()
|
||||||
if not game:
|
if not game:
|
||||||
@ -255,7 +267,10 @@ def manual_scrobble_video_game(
|
|||||||
|
|
||||||
|
|
||||||
def manual_scrobble_book(
|
def manual_scrobble_book(
|
||||||
title: str, user_id: int, source: str = "Google Books", action: Optional[str] = None
|
title: str,
|
||||||
|
user_id: int,
|
||||||
|
source: str = "Google Books",
|
||||||
|
action: Optional[str] = None,
|
||||||
):
|
):
|
||||||
log = {}
|
log = {}
|
||||||
page = None
|
page = None
|
||||||
@ -280,7 +295,9 @@ def manual_scrobble_book(
|
|||||||
if not page:
|
if not page:
|
||||||
page = 1
|
page = 1
|
||||||
|
|
||||||
logger.info("[scrobblers] Book page included in scrobble, should update!")
|
logger.info(
|
||||||
|
"[scrobblers] Book page included in scrobble, should update!"
|
||||||
|
)
|
||||||
|
|
||||||
source = READCOMICSONLINE_URL.replace("https://", "")
|
source = READCOMICSONLINE_URL.replace("https://", "")
|
||||||
|
|
||||||
@ -306,8 +323,9 @@ def manual_scrobble_book(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
scrobble = Scrobble.create_or_update(
|
||||||
scrobble = Scrobble.create_or_update(book, user_id, scrobble_dict, read_log_page=page)
|
book, user_id, scrobble_dict, read_log_page=page
|
||||||
|
)
|
||||||
|
|
||||||
if action == "stop":
|
if action == "stop":
|
||||||
if url:
|
if url:
|
||||||
@ -322,7 +340,10 @@ def manual_scrobble_book(
|
|||||||
|
|
||||||
|
|
||||||
def manual_scrobble_board_game(
|
def manual_scrobble_board_game(
|
||||||
bggeek_id: str, user_id: int, source: str = "BGG", action: Optional[str] = None
|
bggeek_id: str,
|
||||||
|
user_id: int,
|
||||||
|
source: str = "BGG",
|
||||||
|
action: Optional[str] = None,
|
||||||
) -> Scrobble | None:
|
) -> Scrobble | None:
|
||||||
boardgame = BoardGame.find_or_create(bggeek_id)
|
boardgame = BoardGame.find_or_create(bggeek_id)
|
||||||
|
|
||||||
@ -524,7 +545,10 @@ def email_scrobble_board_game(
|
|||||||
|
|
||||||
|
|
||||||
def manual_scrobble_from_url(
|
def manual_scrobble_from_url(
|
||||||
url: str, user_id: int, source: str = "Vrobbler", action: Optional[str] = None
|
url: str,
|
||||||
|
user_id: int,
|
||||||
|
source: str = "Vrobbler",
|
||||||
|
action: Optional[str] = None,
|
||||||
) -> Scrobble:
|
) -> Scrobble:
|
||||||
"""We have scrobblable media URLs, and then any other webpages that
|
"""We have scrobblable media URLs, and then any other webpages that
|
||||||
we want to scrobble as a media type in and of itself. This checks whether
|
we want to scrobble as a media type in and of itself. This checks whether
|
||||||
@ -840,7 +864,12 @@ def emacs_scrobble_task(
|
|||||||
return scrobble
|
return scrobble
|
||||||
|
|
||||||
|
|
||||||
def manual_scrobble_task(url: str, user_id: int, source: str = "Vrobbler", action: Optional[str] = None):
|
def manual_scrobble_task(
|
||||||
|
url: str,
|
||||||
|
user_id: int,
|
||||||
|
source: str = "Vrobbler",
|
||||||
|
action: Optional[str] = None,
|
||||||
|
):
|
||||||
source_id = re.findall(r"\d+", url)[0]
|
source_id = re.findall(r"\d+", url)[0]
|
||||||
|
|
||||||
description = ""
|
description = ""
|
||||||
@ -872,7 +901,10 @@ def manual_scrobble_task(url: str, user_id: int, source: str = "Vrobbler", actio
|
|||||||
|
|
||||||
|
|
||||||
def manual_scrobble_webpage(
|
def manual_scrobble_webpage(
|
||||||
url: str, user_id: int, source: str = "Bookmarklet", action: Optional[str] = None
|
url: str,
|
||||||
|
user_id: int,
|
||||||
|
source: str = "Bookmarklet",
|
||||||
|
action: Optional[str] = None,
|
||||||
):
|
):
|
||||||
webpage = WebPage.find_or_create({"url": url})
|
webpage = WebPage.find_or_create({"url": url})
|
||||||
|
|
||||||
@ -999,7 +1031,10 @@ def web_scrobbler_scrobble_video_or_song(
|
|||||||
|
|
||||||
|
|
||||||
def manual_scrobble_beer(
|
def manual_scrobble_beer(
|
||||||
untappd_id: str, user_id: int, source: str = "Untappd", action: Optional[str] = None
|
untappd_id: str,
|
||||||
|
user_id: int,
|
||||||
|
source: str = "Untappd",
|
||||||
|
action: Optional[str] = None,
|
||||||
):
|
):
|
||||||
beer = Beer.find_or_create(untappd_id)
|
beer = Beer.find_or_create(untappd_id)
|
||||||
|
|
||||||
@ -1028,7 +1063,10 @@ def manual_scrobble_beer(
|
|||||||
|
|
||||||
|
|
||||||
def manual_scrobble_puzzle(
|
def manual_scrobble_puzzle(
|
||||||
ipdb_id: str, user_id: int, source: str = "IPDb", action: Optional[str] = None
|
ipdb_id: str,
|
||||||
|
user_id: int,
|
||||||
|
source: str = "IPDb",
|
||||||
|
action: Optional[str] = None,
|
||||||
):
|
):
|
||||||
puzzle = Puzzle.find_or_create(ipdb_id)
|
puzzle = Puzzle.find_or_create(ipdb_id)
|
||||||
|
|
||||||
@ -1057,7 +1095,10 @@ def manual_scrobble_puzzle(
|
|||||||
|
|
||||||
|
|
||||||
def manual_scrobble_brickset(
|
def manual_scrobble_brickset(
|
||||||
brickset_id: str, user_id: int, source: str = "BrickSet", action: Optional[str] = None
|
brickset_id: str,
|
||||||
|
user_id: int,
|
||||||
|
source: str = "BrickSet",
|
||||||
|
action: Optional[str] = None,
|
||||||
):
|
):
|
||||||
brickset = BrickSet.find_or_create(brickset_id)
|
brickset = BrickSet.find_or_create(brickset_id)
|
||||||
|
|
||||||
|
|||||||
@ -1 +1,21 @@
|
|||||||
from vrobbler.settings import *
|
from vrobbler.settings import *
|
||||||
|
|
||||||
|
TESTING = True
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
"default": {
|
||||||
|
"ENGINE": "django.db.backends.sqlite3",
|
||||||
|
"NAME": "/tmp/testdb.sqlite3",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CACHES = {
|
||||||
|
"default": {
|
||||||
|
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
|
||||||
|
"LOCATION": "unique-snowflake",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PASSWORD_HASHERS = [
|
||||||
|
"django.contrib.auth.hashers.MD5PasswordHasher",
|
||||||
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user