Spaces:
Build error
Build error
Claude
feat(ingest): IIIF-native Sprint 2 — detect IIIF Image Service at ingestion
f338ad4 unverified | """ | |
| Tests de détection du IIIF Image Service à l'ingestion. | |
| Vérifie : | |
| - Extraction depuis un canvas IIIF 3.0 avec ImageService3 | |
| - Extraction depuis un canvas IIIF 2.x avec service @id | |
| - Détection par pattern URL (Gallica, etc.) | |
| - Fallback quand aucun service n'est trouvé | |
| - Détection depuis URL directe (ingest/iiif-images) | |
| """ | |
| import pytest | |
| from app.api.v1.ingest import ( | |
| _detect_iiif_service_from_url, | |
| _extract_iiif_service, | |
| ) | |
| # --------------------------------------------------------------------------- | |
| # _extract_iiif_service — IIIF 3.0 | |
| # --------------------------------------------------------------------------- | |
| def test_extract_iiif3_with_image_service3(): | |
| """Canvas IIIF 3.0 avec service ImageService3 explicite.""" | |
| canvas = { | |
| "width": 3543, | |
| "height": 4724, | |
| "items": [{ | |
| "items": [{ | |
| "body": { | |
| "id": "https://gallica.bnf.fr/iiif/ark:/12148/btv1b8432314s/f29/full/max/0/default.jpg", | |
| "type": "Image", | |
| "service": [{ | |
| "id": "https://gallica.bnf.fr/iiif/ark:/12148/btv1b8432314s/f29", | |
| "type": "ImageService3", | |
| "profile": "level2", | |
| }], | |
| }, | |
| }], | |
| }], | |
| } | |
| svc_url, w, h = _extract_iiif_service(canvas) | |
| assert svc_url == "https://gallica.bnf.fr/iiif/ark:/12148/btv1b8432314s/f29" | |
| assert w == 3543 | |
| assert h == 4724 | |
| def test_extract_iiif3_with_image_service2(): | |
| """Canvas IIIF 3.0 avec un service de type ImageService2.""" | |
| canvas = { | |
| "width": 2000, | |
| "height": 3000, | |
| "items": [{ | |
| "items": [{ | |
| "body": { | |
| "id": "https://example.com/image/1/full/max/0/default.jpg", | |
| "type": "Image", | |
| "service": [{ | |
| "id": "https://example.com/image/1", | |
| "type": "ImageService2", | |
| "profile": "level1", | |
| }], | |
| }, | |
| }], | |
| }], | |
| } | |
| svc_url, w, h = _extract_iiif_service(canvas) | |
| assert svc_url == "https://example.com/image/1" | |
| assert w == 2000 | |
| def test_extract_iiif3_service_as_dict(): | |
| """Le champ service peut être un dict au lieu d'une liste.""" | |
| canvas = { | |
| "width": 1000, | |
| "height": 1500, | |
| "items": [{ | |
| "items": [{ | |
| "body": { | |
| "id": "https://example.com/img/full/max/0/default.jpg", | |
| "service": { | |
| "id": "https://example.com/img", | |
| "type": "ImageService3", | |
| }, | |
| }, | |
| }], | |
| }], | |
| } | |
| svc_url, _, _ = _extract_iiif_service(canvas) | |
| assert svc_url == "https://example.com/img" | |
| def test_extract_iiif3_fallback_url_pattern(): | |
| """Sans service explicite, détecte le pattern Image API dans body.id.""" | |
| canvas = { | |
| "width": 3000, | |
| "height": 4000, | |
| "items": [{ | |
| "items": [{ | |
| "body": { | |
| "id": "https://gallica.bnf.fr/iiif/ark:/12148/btv1b8432314s/f29/full/max/0/default.jpg", | |
| "type": "Image", | |
| # Pas de "service" ! | |
| }, | |
| }], | |
| }], | |
| } | |
| svc_url, w, h = _extract_iiif_service(canvas) | |
| assert svc_url == "https://gallica.bnf.fr/iiif/ark:/12148/btv1b8432314s/f29" | |
| assert w == 3000 | |
| def test_extract_iiif3_no_service_no_pattern(): | |
| """Canvas sans service et sans pattern Image API → None.""" | |
| canvas = { | |
| "width": 800, | |
| "height": 600, | |
| "items": [{ | |
| "items": [{ | |
| "body": { | |
| "id": "https://example.com/static/page1.jpg", | |
| "type": "Image", | |
| }, | |
| }], | |
| }], | |
| } | |
| svc_url, w, h = _extract_iiif_service(canvas) | |
| assert svc_url is None | |
| assert w == 800 | |
| assert h == 600 | |
| # --------------------------------------------------------------------------- | |
| # _extract_iiif_service — IIIF 2.x | |
| # --------------------------------------------------------------------------- | |
| def test_extract_iiif2_with_service(): | |
| """Canvas IIIF 2.x avec service dans resource.""" | |
| canvas = { | |
| "width": 4000, | |
| "height": 5000, | |
| "images": [{ | |
| "resource": { | |
| "@id": "https://example.com/image/2/full/full/0/default.jpg", | |
| "service": { | |
| "@id": "https://example.com/image/2", | |
| "@type": "ImageService2", | |
| }, | |
| }, | |
| }], | |
| } | |
| svc_url, w, h = _extract_iiif_service(canvas) | |
| assert svc_url == "https://example.com/image/2" | |
| assert w == 4000 | |
| def test_extract_iiif2_fallback_url_pattern(): | |
| """IIIF 2.x : détection par pattern dans resource @id.""" | |
| canvas = { | |
| "width": 2500, | |
| "height": 3500, | |
| "images": [{ | |
| "resource": { | |
| "@id": "https://iiif.bodleian.ox.ac.uk/image/abc123/full/full/0/default.jpg", | |
| }, | |
| }], | |
| } | |
| svc_url, _, _ = _extract_iiif_service(canvas) | |
| assert svc_url == "https://iiif.bodleian.ox.ac.uk/image/abc123" | |
| def test_extract_iiif2_no_service(): | |
| """IIIF 2.x sans service et URL statique → None.""" | |
| canvas = { | |
| "width": 1200, | |
| "height": 1600, | |
| "images": [{ | |
| "resource": { | |
| "@id": "https://example.com/images/scan.png", | |
| }, | |
| }], | |
| } | |
| svc_url, w, h = _extract_iiif_service(canvas) | |
| assert svc_url is None | |
| assert w == 1200 | |
| # --------------------------------------------------------------------------- | |
| # _extract_iiif_service — cas limites | |
| # --------------------------------------------------------------------------- | |
| def test_extract_empty_canvas(): | |
| """Canvas vide → None sans crash.""" | |
| svc_url, w, h = _extract_iiif_service({}) | |
| assert svc_url is None | |
| assert w is None | |
| assert h is None | |
| def test_extract_service_url_trailing_slash_stripped(): | |
| """L'URL du service ne doit pas se terminer par /.""" | |
| canvas = { | |
| "width": 1000, | |
| "height": 1000, | |
| "items": [{ | |
| "items": [{ | |
| "body": { | |
| "id": "https://example.com/img/full/max/0/default.jpg", | |
| "service": [{ | |
| "id": "https://example.com/img/", | |
| "type": "ImageService3", | |
| }], | |
| }, | |
| }], | |
| }], | |
| } | |
| svc_url, _, _ = _extract_iiif_service(canvas) | |
| assert svc_url == "https://example.com/img" | |
| assert not svc_url.endswith("/") | |
| # --------------------------------------------------------------------------- | |
| # _detect_iiif_service_from_url — détection depuis URL directe | |
| # --------------------------------------------------------------------------- | |
| def test_detect_from_gallica_url(): | |
| """URL Gallica complète → service URL déduit.""" | |
| url = "https://gallica.bnf.fr/iiif/ark:/12148/btv1b8432314s/f29/full/max/0/default.jpg" | |
| assert _detect_iiif_service_from_url(url) == "https://gallica.bnf.fr/iiif/ark:/12148/btv1b8432314s/f29" | |
| def test_detect_from_iiif_url_with_size(): | |
| """URL avec taille spécifique → service URL déduit.""" | |
| url = "https://example.com/iiif/img1/full/!1500,1500/0/default.jpg" | |
| assert _detect_iiif_service_from_url(url) == "https://example.com/iiif/img1" | |
| def test_detect_from_static_url_returns_none(): | |
| """URL statique (pas de pattern IIIF) → None.""" | |
| url = "https://example.com/images/page1.jpg" | |
| assert _detect_iiif_service_from_url(url) is None | |
| def test_detect_from_iiif_url_different_format(): | |
| """URL avec format PNG au lieu de JPEG.""" | |
| url = "https://example.com/iiif/img2/full/max/0/default.png" | |
| assert _detect_iiif_service_from_url(url) == "https://example.com/iiif/img2" | |