Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions .github/workflows/ci-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,22 @@ jobs:
enable-cache: true

- name: Install Python dependencies
run: uv sync --locked --extra dev --python "${PYTHON_VERSION}" --no-python-downloads
run: |
uv sync \
--locked \
--extra dev \
--python "${PYTHON_VERSION}" \
--no-build \
--no-install-project \
--no-python-downloads

- name: Install npm dependencies
run: npm ci --ignore-scripts

- name: Test with pytest
id: pytest
shell: bash
run: uv run --no-sync python -m pytest tests
run: uv run --no-build --no-sync python -m pytest tests

- name: Test with Jest
id: jest
Expand Down
9 changes: 7 additions & 2 deletions .github/workflows/update-db.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,19 @@ jobs:
enable-cache: true

- name: Install Python dependencies
run: uv sync --locked --python "${PYTHON_VERSION}" --no-python-downloads
run: uv sync --locked --python "${PYTHON_VERSION}" --no-build --no-install-project --no-python-downloads

- name: Update
env:
TWITCH_CLIENT_ID: ${{ secrets.TWITCH_CLIENT_ID }}
TWITCH_CLIENT_SECRET: ${{ secrets.TWITCH_CLIENT_SECRET }}
YOUTUBE_API_KEY: ${{ secrets.YOUTUBE_API_KEY }}
run: uv run --no-sync python -u ./src/update_db.py ${{ github.event_name == 'pull_request' && '-t' || '' }}
run: |
uv run \
--no-build \
--no-sync \
python -u ./src/update_db.py \
${{ github.event_name == 'pull_request' && '-t' || '' }}

- name: Prepare Artifacts # uploading artifacts will fail if not zipped due to very large quantity of files
shell: bash
Expand Down
8 changes: 4 additions & 4 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import pytest


@pytest.fixture()
@pytest.fixture
def mock_args(tmp_path):
"""Return a minimal args Namespace that update_db functions expect."""
ns = argparse.Namespace(
Expand All @@ -18,7 +18,7 @@ def mock_args(tmp_path):
return ns


@pytest.fixture()
@pytest.fixture
def sample_game():
return {
'id': 1,
Expand All @@ -29,7 +29,7 @@ def sample_game():
}


@pytest.fixture()
@pytest.fixture
def sample_platform():
return {
'id': 6,
Expand All @@ -38,7 +38,7 @@ def sample_platform():
}


@pytest.fixture()
@pytest.fixture
def sample_character():
return {
'id': 99,
Expand Down
54 changes: 27 additions & 27 deletions tests/unit/test_update_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ def test_igdb_authorization(requests_mock):


@pytest.mark.parametrize('indent', [None, 4])
def test_write_json_files(tmp_path, indent):
udb.args = _make_args(tmp_path, indent=indent)
def test_write_json_files(tmp_path, indent, monkeypatch):
monkeypatch.setattr(udb, 'args', _make_args(tmp_path, indent=indent))
data = {'key': 'value', 'num': 42}
file_path = str(tmp_path / 'test_dir' / 'myfile')

Expand All @@ -47,8 +47,8 @@ def test_write_json_files(tmp_path, indent):
assert written == data


def test_write_json_files_creates_directory(tmp_path):
udb.args = _make_args(tmp_path)
def test_write_json_files_creates_directory(tmp_path, monkeypatch):
monkeypatch.setattr(udb, 'args', _make_args(tmp_path))
nested = str(tmp_path / 'a' / 'b' / 'c' / 'file')
udb.write_json_files(file_path=nested, data={'x': 1})
assert (tmp_path / 'a' / 'b' / 'c' / 'file.json').exists()
Expand All @@ -58,16 +58,16 @@ def test_write_json_files_creates_directory(tmp_path):
(False, 1000, 3),
(True, 2, 2),
])
def test_fetch_endpoint_pagination(tmp_path, test_mode, test_limit, expected_count):
udb.args = _make_args(tmp_path, test_mode=test_mode, test_limit=test_limit)
def test_fetch_endpoint_pagination(tmp_path, test_mode, test_limit, expected_count, monkeypatch):
monkeypatch.setattr(udb, 'args', _make_args(tmp_path, test_mode=test_mode, test_limit=test_limit))

page1 = json.dumps([{'id': 1, 'name': 'A'}, {'id': 2, 'name': 'B'}]).encode()
page2 = json.dumps([{'id': 3, 'name': 'C'}]).encode()
empty = json.dumps([]).encode()

mock_wrapper = MagicMock()
mock_wrapper.api_request.side_effect = [page1, page2, empty]
udb.wrapper = mock_wrapper
monkeypatch.setattr(udb, 'wrapper', mock_wrapper)

result = udb._fetch_endpoint(
endpoint='games',
Expand All @@ -80,8 +80,8 @@ def test_fetch_endpoint_pagination(tmp_path, test_mode, test_limit, expected_cou
assert len(result) == expected_count


def test_fetch_endpoint_http_retry(tmp_path):
udb.args = _make_args(tmp_path)
def test_fetch_endpoint_http_retry(tmp_path, monkeypatch):
monkeypatch.setattr(udb, 'args', _make_args(tmp_path))

good_page = json.dumps([{'id': 1, 'name': 'X'}]).encode()
empty = json.dumps([]).encode()
Expand All @@ -92,7 +92,7 @@ def test_fetch_endpoint_http_retry(tmp_path):
good_page,
empty,
]
udb.wrapper = mock_wrapper
monkeypatch.setattr(udb, 'wrapper', mock_wrapper)

with patch('src.update_db.time.sleep') as mock_sleep:
result = udb._fetch_endpoint(
Expand All @@ -107,12 +107,12 @@ def test_fetch_endpoint_http_retry(tmp_path):
assert 1 in result


def test_fetch_all_endpoints_writes_all_json_only_when_flagged(tmp_path):
udb.args = _make_args(tmp_path)
def test_fetch_all_endpoints_writes_all_json_only_when_flagged(tmp_path, monkeypatch):
monkeypatch.setattr(udb, 'args', _make_args(tmp_path))

mock_wrapper = MagicMock()
mock_wrapper.api_request.return_value = json.dumps([]).encode()
udb.wrapper = mock_wrapper
monkeypatch.setattr(udb, 'wrapper', mock_wrapper)

request_dict = {
'characters': {'fields': ['name'], 'write_all': True},
Expand Down Expand Up @@ -256,8 +256,8 @@ def test_append_skips_endpoint_without_append_key():
udb._append_related_items(full_dict=full_dict, request_dict=request_dict)


def test_add_platform_game_counts(tmp_path):
udb.args = _make_args(tmp_path)
def test_add_platform_game_counts(tmp_path, monkeypatch):
monkeypatch.setattr(udb, 'args', _make_args(tmp_path))
full_dict = {
'platforms': {
6: {'id': 6, 'name': 'PC', 'games': [{'id': 1}, {'id': 2}]},
Expand Down Expand Up @@ -348,8 +348,8 @@ def test_resolve_video_groups_with_cache_keeps_valid_filters_stale(tmp_path):
assert 'v3' in all_in_groups


def test_fetch_youtube_metadata(tmp_path):
udb.args = _make_args(tmp_path)
def test_fetch_youtube_metadata(tmp_path, monkeypatch):
monkeypatch.setattr(udb, 'args', _make_args(tmp_path))
full_dict = {'videos': {}}

yt_response = {
Expand All @@ -365,8 +365,8 @@ def test_fetch_youtube_metadata(tmp_path):
assert full_dict['videos']['abc']['snippet']['title'] == 'Trailer'


def test_fetch_youtube_metadata_handles_missing_items_key(tmp_path, capsys):
udb.args = _make_args(tmp_path)
def test_fetch_youtube_metadata_handles_missing_items_key(tmp_path, capsys, monkeypatch):
monkeypatch.setattr(udb, 'args', _make_args(tmp_path))
full_dict = {'videos': {}}

with patch('src.update_db.get_youtube', return_value={'error': 'quota exceeded'}):
Expand Down Expand Up @@ -427,8 +427,8 @@ def test_enrich_game_videos_skips_games_with_no_videos():
udb._enrich_game_videos(full_dict=full_dict)


def test_get_youtube(tmp_path):
udb.args = _make_args(tmp_path, youtube_api_key='yt_key_123')
def test_get_youtube(tmp_path, monkeypatch):
monkeypatch.setattr(udb, 'args', _make_args(tmp_path, youtube_api_key='yt_key_123'))

mock_response = MagicMock()
mock_response.json.return_value = {'items': []}
Expand All @@ -445,8 +445,8 @@ def test_get_youtube(tmp_path):
assert 'yt_key_123' in called_url


def test_write_stats(tmp_path):
udb.args = _make_args(tmp_path)
def test_write_stats(tmp_path, monkeypatch):
monkeypatch.setattr(udb, 'args', _make_args(tmp_path))
full_dict = {
'characters': {1: {}, 2: {}, 3: {}},
'games': {10: {}, 20: {}},
Expand All @@ -462,8 +462,8 @@ def test_write_stats(tmp_path):
assert call_kwargs['data'] == {'characters': 3, 'games': 2, 'videos': 2}


def test_get_platform_cross_reference(tmp_path):
udb.args = _make_args(tmp_path)
def test_get_platform_cross_reference(tmp_path, monkeypatch):
monkeypatch.setattr(udb, 'args', _make_args(tmp_path))

with patch('src.update_db.write_json_files') as mock_write:
udb.get_platform_cross_reference()
Expand All @@ -474,9 +474,9 @@ def test_get_platform_cross_reference(tmp_path):
assert call_kwargs['data'] is udb.platforms.cross_reference


def test_get_data_orchestration(tmp_path):
def test_get_data_orchestration(tmp_path, monkeypatch):
"""get_data() calls all helpers in order with correct data flow."""
udb.args = _make_args(tmp_path)
monkeypatch.setattr(udb, 'args', _make_args(tmp_path))

mock_full_dict = {
'games': {1: {'id': 1, 'name': 'TestGame'}},
Expand Down