gapguide-api / apps /resources /tests /test_import_checkpoints_replace.py
arifRB's picture
Deploy GapGuide backend (Docker)
ffd36e0 verified
Raw
History Blame Contribute Delete
3.24 kB
"""Tests for `import_checkpoints --replace` — refresh existing checkpoints in
place (e.g. swapping hand-authored YouTube segments for real chapter markers),
without ever blanking a resource."""
from io import StringIO
import pytest
from django.core.management import call_command
from apps.resources import importers
from apps.resources.models import Resource, ResourceCheckpoint
pytestmark = pytest.mark.django_db
def _video(n_existing):
r = Resource.objects.create(
title='Learn X', provider='YouTube',
url='https://www.youtube.com/watch?v=abc123',
difficulty_level='BEGINNER', duration=300, type='VIDEO',
)
for i in range(1, n_existing + 1):
ResourceCheckpoint.objects.create(
resource=r, order_index=i, title=f'manual {i}', source='manual',
)
return r
def _stub_extract(monkeypatch, titles, source='youtube_api'):
def fake(url, **kwargs):
return importers.ExtractResult(
checkpoints=[
importers.ExtractedCheckpoint(order_index=i, title=t)
for i, t in enumerate(titles, start=1)
],
source=source, provider='youtube',
)
# patch where the command looked it up
from apps.resources.management.commands import import_checkpoints as cmd
monkeypatch.setattr(cmd, 'extract_checkpoints', fake)
def _run(*args):
out, err = StringIO(), StringIO()
call_command('import_checkpoints', *args, stdout=out, stderr=err)
return out.getvalue() + err.getvalue()
def test_replace_swaps_when_extraction_succeeds(monkeypatch):
r = _video(5)
_stub_extract(monkeypatch, ['Intro', 'Setup', 'Deep Dive'])
_run('--type', 'VIDEO', '--replace', '--apply')
rows = list(r.checkpoints.order_by('order_index'))
assert [c.title for c in rows] == ['Intro', 'Setup', 'Deep Dive']
assert all(c.source == 'youtube_api' for c in rows)
# the 5 old manual rows are gone (replaced, not appended)
assert r.checkpoints.count() == 3
def test_replace_keeps_existing_when_extraction_under_two(monkeypatch):
r = _video(5)
_stub_extract(monkeypatch, ['only one']) # <2 → must not blank
_run('--type', 'VIDEO', '--replace', '--apply')
rows = list(r.checkpoints.order_by('order_index'))
assert [c.title for c in rows] == ['manual 1', 'manual 2', 'manual 3',
'manual 4', 'manual 5']
assert all(c.source == 'manual' for c in rows)
def test_replace_requires_apply(monkeypatch):
r = _video(5)
_stub_extract(monkeypatch, ['Intro', 'Setup'])
out = _run('--type', 'VIDEO', '--replace') # no --apply
assert 'requires --apply' in out
# untouched
assert r.checkpoints.count() == 5
assert r.checkpoints.first().source == 'manual'
def test_default_run_ignores_resources_that_have_checkpoints(monkeypatch):
"""Without --replace, a resource that already has checkpoints is skipped
(the n=0 backfill gate), so existing rows are never touched."""
r = _video(5)
_stub_extract(monkeypatch, ['Intro', 'Setup', 'Deep Dive'])
_run('--type', 'VIDEO', '--apply') # no --replace
assert r.checkpoints.count() == 5
assert r.checkpoints.first().source == 'manual'