bloombase/plants/tests/test_identify_views.py
Stephan Kerkman b16df6caa4 feat: implement step 2 species confirm view and template
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 17:45:35 +02:00

118 lines
4.5 KiB
Python

import pytest
from django.test import Client
from django.urls import reverse
import io
from unittest.mock import patch
from django.core.files.uploadedfile import SimpleUploadedFile
@pytest.fixture
def client():
return Client()
def test_upload_get(client):
resp = client.get(reverse('identify_upload'))
assert resp.status_code == 200
def test_confirm_redirects_without_session(client):
resp = client.get(reverse('identify_confirm'))
assert resp.status_code == 302
assert reverse('identify_upload') in resp['Location']
def test_fields_redirects_without_session(client):
resp = client.get(reverse('identify_fields'))
assert resp.status_code == 302
assert reverse('identify_upload') in resp['Location']
def _fake_image(name='test.jpg'):
return SimpleUploadedFile(name, b'fake-image-bytes', content_type='image/jpeg')
def test_upload_post_no_images(client):
resp = client.post(reverse('identify_upload'), {})
assert resp.status_code == 200
assert b'select at least one' in resp.content.lower() or b'Please' in resp.content
@pytest.mark.django_db
def test_upload_post_calls_plantnet_and_redirects(client, settings):
settings.PLANTNET_API_KEY = 'test-key'
fake_matches = [
{'scientific_name': 'Liatris spicata', 'common_names': ['Blazing star'],
'score': 0.94, 'gbif_id': '123', 'family': 'Asteraceae', 'genus': 'Liatris'},
]
with patch('plants.views.identify.plantnet.identify', return_value=fake_matches):
with patch('plants.views.identify.default_storage') as mock_storage:
mock_storage.save.return_value = 'plants/temp_identify/abc_0.jpg'
mock_storage.path.return_value = '/tmp/abc_0.jpg'
resp = client.post(reverse('identify_upload'), {
'images': [_fake_image()],
'organs': ['flower'],
})
assert resp.status_code == 302
assert reverse('identify_confirm') in resp['Location']
assert client.session['identify_matches'] == fake_matches
def test_upload_post_plantnet_error_rerenders(client, settings):
settings.PLANTNET_API_KEY = 'test-key'
from plants.services.plantnet import PlantNetError
with patch('plants.views.identify.plantnet.identify',
side_effect=PlantNetError('No match found')):
with patch('plants.views.identify.default_storage') as mock_storage:
mock_storage.save.return_value = 'plants/temp_identify/abc_0.jpg'
mock_storage.path.return_value = '/tmp/abc_0.jpg'
mock_storage.exists.return_value = True
resp = client.post(reverse('identify_upload'), {
'images': [_fake_image()],
'organs': ['flower'],
})
assert resp.status_code == 200
assert b'No match found' in resp.content
def _set_matches(client):
session = client.session
session['identify_matches'] = [
{'scientific_name': 'Liatris spicata', 'common_names': ['Blazing star'],
'score': 0.94, 'gbif_id': '123', 'family': 'Asteraceae', 'genus': 'Liatris'},
{'scientific_name': 'Liatris pycnostachya', 'common_names': ['Prairie blazing star'],
'score': 0.04, 'gbif_id': '456', 'family': 'Asteraceae', 'genus': 'Liatris'},
]
session['identify_image_paths'] = [{'path': 'plants/temp_identify/x_0.jpg', 'organ': 'flower'}]
session.save()
@pytest.mark.django_db
def test_confirm_get_with_session(client):
_set_matches(client)
resp = client.get(reverse('identify_confirm'))
assert resp.status_code == 200
assert b'Liatris spicata' in resp.content
@pytest.mark.django_db
def test_confirm_post_stores_selection_and_redirects(client):
_set_matches(client)
with patch('plants.views.identify.vpc_search', return_value=[
{'slug': 'liatris-spicata', 'common_name': 'Liatris spicata', 'scientific_name': 'Liatris spicata', 'thumbnail_url': '', 'source': 'vpc'},
]):
resp = client.post(reverse('identify_confirm'), {'match_idx': '0'})
assert resp.status_code == 302
assert reverse('identify_fields') in resp['Location']
assert client.session['identify_selected']['scientific_name'] == 'Liatris spicata'
assert len(client.session['identify_vpc_results']) == 1
@pytest.mark.django_db
def test_confirm_post_handles_vpc_failure(client):
_set_matches(client)
from plants.services.vpc import VPCError
with patch('plants.views.identify.vpc_search', side_effect=VPCError('down')):
resp = client.post(reverse('identify_confirm'), {'match_idx': '0'})
assert resp.status_code == 302
assert client.session['identify_vpc_results'] == []