import pytest from httpx import AsyncClient from pydantic import ValidationError from app.schemas import SampleCreate @pytest.mark.parametrize( "uri", [ "gs://bucket/dir/sample.vcf.gz", "gs://my.bucket-1/a/b.bcf", "gs://bucket/x.vcf", "/data/example.vcf.gz", "/data/giab/hg002.chr22.vcf.bgz", ], ) def test_vcf_uri_accepts_gcs_objects_and_files_under_the_data_root(uri: str) -> None: assert SampleCreate(name="s", vcf_uri=uri).vcf_uri == uri @pytest.mark.parametrize( "uri", [ "-c/tmp/evil.config", # would be parsed as a Nextflow option "--outdir=/etc", "/etc/passwd", # outside the data root "/data/../etc/shadow.vcf", # traversal out of it "data/example.vcf.gz", # relative: depends on the API's working directory "gs://bucket/notes.txt", # not a VCF/BCF "https://example.com/x.vcf.gz", "gs:///x.vcf.gz", "/data/x.vcf.gz\n--foo", # control characters "", ], ) def test_vcf_uri_rejects_everything_else(uri: str) -> None: with pytest.raises(ValidationError): SampleCreate(name="s", vcf_uri=uri) async def test_bad_vcf_uri_is_422_at_the_api(client: AsyncClient) -> None: r = await client.post("/api/samples", json={"name": "s", "vcf_uri": "/etc/passwd"}) assert r.status_code == 422 async def test_cors_allows_only_configured_origins(client: AsyncClient) -> None: allowed = await client.get("/health", headers={"Origin": "http://localhost:5173"}) assert allowed.headers.get("access-control-allow-origin") == "http://localhost:5173" other = await client.get("/health", headers={"Origin": "https://evil.example"}) assert "access-control-allow-origin" not in other.headers