| import importlib |
| import os |
| import re |
| from types import SimpleNamespace |
| from urllib.parse import parse_qs, quote, urlparse |
|
|
| from fastapi.testclient import TestClient |
|
|
| os.environ.setdefault("SYSTEM", "spaces") |
| os.environ.setdefault("SPACE_ID", "test/certificate-generator") |
| os.environ.setdefault("SPACE_HOST", "test-certificate-generator.hf.space") |
| os.environ.setdefault("OAUTH_CLIENT_ID", "test-client") |
| os.environ.setdefault("OAUTH_CLIENT_SECRET", "test-secret") |
| os.environ.setdefault("OAUTH_SCOPES", "openid profile") |
| os.environ.setdefault("OPENID_PROVIDER_URL", "https://huggingface.co") |
| os.environ.setdefault("GRADIO_SSR_MODE", "true") |
|
|
| certificate_app = importlib.import_module("app") |
|
|
|
|
| def test_oauth_login_clears_stale_session_before_redirecting(): |
| with TestClient(certificate_app.app) as client: |
| response = client.get("/oauth-login", follow_redirects=False) |
|
|
| assert response.status_code == 303 |
| assert response.headers["location"] == "/login/huggingface?_target_url=/" |
| cookie = response.headers["set-cookie"].lower() |
| assert 'session=""' in cookie |
| assert "max-age=0" in cookie |
| assert "httponly" in cookie |
| assert "samesite=none" in cookie |
| assert "secure" in cookie |
|
|
|
|
| def test_auth_control_uses_sandbox_safe_navigation(): |
| logged_out = certificate_app.auth_control(None) |
| logged_in = certificate_app.auth_control( |
| SimpleNamespace(username='person<script>alert("x")</script>') |
| ) |
|
|
| assert 'href="/oauth-login"' in logged_out |
| assert 'target="_blank"' in logged_out |
| assert 'href="/logout?_target_url=/"' in logged_in |
| assert 'target="_self"' in logged_in |
| assert 'target="_top"' not in logged_out + logged_in |
| assert "<script>" not in logged_in |
| assert "<script>" in logged_in |
|
|
|
|
| def test_root_frontend_asset_is_served(): |
| """Catch broken asset paths when mounting Gradio at the Space root.""" |
| with TestClient(certificate_app.app) as client: |
| response = client.get("/") |
| assert response.status_code == 200 |
|
|
| assets = re.findall(r'(?:src|href)="(\.?/assets/[^"]+)"', response.text) |
| assert assets, "root page did not reference a Gradio frontend asset" |
|
|
| asset_path = assets[0].removeprefix(".") |
| asset_response = client.get(asset_path) |
|
|
| assert asset_response.status_code == 200 |
|
|
|
|
| def eligible_profile(): |
| username = next(iter(certificate_app.ELIGIBLE)) |
| return SimpleNamespace(username=username, name="Test Participant") |
|
|
|
|
| def test_linkedin_url_includes_public_certificate_url(): |
| url = certificate_app.linkedin_url( |
| "https://huggingface.co/datasets/example/certificates/resolve/main/test.png", |
| "test-user", |
| ) |
| params = parse_qs(urlparse(url).query) |
|
|
| assert params["certUrl"] == [ |
| "https://huggingface.co/datasets/example/certificates/resolve/main/test.png" |
| ] |
| assert params["certId"] == ["test-user"] |
|
|
|
|
| def test_publish_certificate_uses_stable_public_path(monkeypatch): |
| upload = {} |
| monkeypatch.setenv("HF_TOKEN", "test-token") |
| monkeypatch.setattr( |
| certificate_app, |
| "upload_file", |
| lambda **kwargs: upload.update(kwargs), |
| ) |
|
|
| url = certificate_app.publish_certificate("Test-User", "/tmp/certificate.png") |
|
|
| assert upload == { |
| "path_or_fileobj": "/tmp/certificate.png", |
| "path_in_repo": "certificates/test-user.png", |
| "repo_id": certificate_app.CERTIFICATES_DATASET, |
| "repo_type": "dataset", |
| "token": "test-token", |
| } |
| assert url.endswith("/resolve/main/certificates/test-user.png") |
|
|
|
|
| def test_certificate_is_not_published_without_opt_in(monkeypatch): |
| profile = eligible_profile() |
| monkeypatch.setattr(certificate_app, "render_html", lambda html: "/tmp/certificate.png") |
|
|
| def unexpected_upload(username, image_path): |
| raise AssertionError("certificate should not be published") |
|
|
| monkeypatch.setattr(certificate_app, "publish_certificate", unexpected_upload) |
|
|
| image_path, note, linkedin = certificate_app.create_certificate("Test", False, profile) |
|
|
| assert image_path == "/tmp/certificate.png" |
| assert "was not published" in note |
| assert quote(certificate_app.SPACE_URL, safe="") in linkedin["value"] |
|
|
|
|
| def test_certificate_is_published_after_opt_in(monkeypatch): |
| profile = eligible_profile() |
| public_url = "https://huggingface.co/datasets/example/certificates/resolve/main/test.png" |
| monkeypatch.setattr(certificate_app, "render_html", lambda html: "/tmp/certificate.png") |
| monkeypatch.setattr( |
| certificate_app, |
| "publish_certificate", |
| lambda username, image_path: public_url, |
| ) |
|
|
| image_path, note, linkedin = certificate_app.create_certificate("Test", True, profile) |
|
|
| assert image_path == "/tmp/certificate.png" |
| assert public_url in note |
| assert quote(public_url, safe="") in linkedin["value"] |
|
|