Skip to content

Commit 3c44e1b

Browse files
Fix/ 343 Unify validation messaging (#346)
* fix(api): unify validation messaging * fix(api): handle typed tab changes
1 parent 291c6d5 commit 3c44e1b

13 files changed

Lines changed: 632 additions & 582 deletions

app/tests/conftest.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@
44
from sqlalchemy import create_engine
55
from sqlalchemy.orm import sessionmaker
66
from sqlalchemy.pool import StaticPool
7-
from app.database import Base
8-
9-
os.environ.setdefault("JWT_SECRET", "test-jwt-secret")
10-
os.environ.setdefault("GITHUB_CLIENT_ID", "test-github-client-id")
11-
os.environ.setdefault("GITHUB_SECRET", "test-github-secret")
12-
os.environ.setdefault("GITHUB_REDIRECT", "http://localhost:5173/login/callback")
13-
os.environ.setdefault("AUTH_DEV_MODE_APPROVE_ALL_LOGINS", "true")
14-
os.environ.setdefault("COOKIE_SECURE", "false")
7+
8+
os.environ["JWT_SECRET"] = "test-jwt-secret"
9+
os.environ["GITHUB_CLIENT_ID"] = "test-github-client-id"
10+
os.environ["GITHUB_SECRET"] = "test-github-secret"
11+
os.environ["GITHUB_REDIRECT"] = "http://localhost:5173/login/callback"
12+
os.environ["AUTH_DEV_MODE_APPROVE_ALL_LOGINS"] = "true"
13+
os.environ["COOKIE_SECURE"] = "false"
14+
os.environ["APP_BASE_URL"] = "http://localhost:8000"
15+
16+
from app.database import Base # noqa: E402
1517

1618

1719
@pytest.fixture(scope="function")

tests/datasets/test_upload_url_endpoint.py renamed to app/tests/integration/test_upload_url_endpoint.py

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ def _clean_scan_result(file_name: str = "data.csv") -> dict:
107107
}
108108

109109

110+
def _app_state(client: TestClient) -> Any:
111+
return cast(Any, client.app).state
112+
113+
110114
def _downloadable_dataset_object(
111115
*,
112116
object_key: str,
@@ -198,7 +202,7 @@ def test_upload_url_creates_pending_dataset_and_returns_presigned_url(
198202
expected_storage_key = f"datasets/fixed_{filename}"
199203

200204
monkeypatch.setattr(
201-
client.app.state.storage,
205+
_app_state(client).storage,
202206
"create_upload_target",
203207
lambda _filename, **kwargs: UploadTarget(
204208
storage_key=expected_storage_key,
@@ -281,7 +285,7 @@ def test_local_direct_upload_allows_dataset_owner(
281285
)
282286

283287
assert response.status_code == 200
284-
storage = cast(Any, client.app).state.storage
288+
storage = _app_state(client).storage
285289
assert storage.read_bytes(storage_key) == b"feature,target\n1,0\n"
286290

287291

@@ -314,7 +318,7 @@ def test_local_direct_upload_rejects_non_owner(client: TestClient, db_session_fa
314318
)
315319

316320
assert response.status_code == 403
317-
storage = cast(Any, client.app).state.storage
321+
storage = _app_state(client).storage
318322
assert storage.object_exists(storage_key) is False
319323

320324

@@ -344,7 +348,7 @@ def create_upload_target(filename: str, **kwargs):
344348
)
345349

346350
monkeypatch.setattr(
347-
client.app.state.storage,
351+
_app_state(client).storage,
348352
"create_upload_target",
349353
create_upload_target,
350354
)
@@ -392,7 +396,7 @@ def create_upload_target(filename: str, **kwargs):
392396
)
393397

394398
monkeypatch.setattr(
395-
client.app.state.storage,
399+
_app_state(client).storage,
396400
"create_upload_target",
397401
create_upload_target,
398402
)
@@ -433,7 +437,7 @@ def test_upload_url_allows_same_dataset_name_with_different_checksum(
433437
db.commit()
434438

435439
monkeypatch.setattr(
436-
client.app.state.storage,
440+
_app_state(client).storage,
437441
"create_upload_target",
438442
lambda filename, **kwargs: UploadTarget(
439443
storage_key=f"datasets/fixed_{filename}",
@@ -480,7 +484,7 @@ def test_upload_url_allows_duplicate_dataset_name_for_different_owner(
480484
db.commit()
481485

482486
monkeypatch.setattr(
483-
client.app.state.storage,
487+
_app_state(client).storage,
484488
"create_upload_target",
485489
lambda filename, **kwargs: UploadTarget(
486490
storage_key=f"datasets/fixed_{filename}",
@@ -523,7 +527,7 @@ def test_confirm_upload_triggers_scan_and_returns_202(
523527
)
524528
)
525529
db.commit()
526-
client.app.state.storage.write_bytes(
530+
_app_state(client).storage.write_bytes(
527531
"datasets/generated_data.csv", b"feature,target\n1,0\n"
528532
)
529533

@@ -598,7 +602,7 @@ def test_confirm_upload_marks_dataset_objects_uploaded(
598602
)
599603
db.commit()
600604

601-
client.app.state.storage.write_bytes(storage_key, b"a,b\n1,2\n")
605+
_app_state(client).storage.write_bytes(storage_key, b"a,b\n1,2\n")
602606
scan_calls = []
603607

604608
def fake_scan(**kwargs):
@@ -788,10 +792,10 @@ def test_download_multiple_dataset_objects_preserves_directory_structure(
788792
)
789793
db.commit()
790794

791-
client.app.state.storage.write_bytes(
795+
_app_state(client).storage.write_bytes(
792796
final_storage_keys[0], b"split,value\ntrain,1\n"
793797
)
794-
client.app.state.storage.write_bytes(
798+
_app_state(client).storage.write_bytes(
795799
final_storage_keys[1], b"split,value\ntest,2\n"
796800
)
797801

@@ -814,13 +818,13 @@ def test_upload_url_returns_direct_s3_upload_contract(
814818
uploader_id = uuid.uuid4()
815819
access_token = _create_access_token_for_user(db_session_factory, uploader_id)
816820
storage = _FakeS3Storage()
817-
monkeypatch.setattr(client.app.state, "storage", storage)
821+
monkeypatch.setattr(_app_state(client), "storage", storage)
818822
monkeypatch.setattr(
819-
client.app.state,
823+
_app_state(client),
820824
"settings",
821825
replace(
822-
client.app.state.settings,
823-
upload=replace(client.app.state.settings.upload, expires_seconds=120),
826+
_app_state(client).settings,
827+
upload=replace(_app_state(client).settings.upload, expires_seconds=120),
824828
),
825829
)
826830

@@ -872,7 +876,7 @@ def test_upload_url_marks_large_s3_upload_contract_as_multipart(
872876
uploader_id = uuid.uuid4()
873877
access_token = _create_access_token_for_user(db_session_factory, uploader_id)
874878
storage = _FakeS3Storage()
875-
monkeypatch.setattr(client.app.state, "storage", storage)
879+
monkeypatch.setattr(_app_state(client), "storage", storage)
876880

877881
response = client.post(
878882
"/api/datasets/upload-url",
@@ -897,7 +901,7 @@ def test_upload_url_persists_directory_structure_metadata_from_description(
897901
access_token = _create_access_token_for_user(db_session_factory, uploader_id)
898902

899903
monkeypatch.setattr(
900-
client.app.state.storage,
904+
_app_state(client).storage,
901905
"create_upload_target",
902906
lambda filename, **kwargs: UploadTarget(
903907
storage_key=f"datasets/batch/{Path(filename).name}",
@@ -981,7 +985,7 @@ def test_confirm_upload_verifies_s3_object_and_blocks_scan_on_failure(
981985
uploader_id = uuid.uuid4()
982986
access_token = _create_access_token_for_user(db_session_factory, uploader_id)
983987
storage = _FakeS3Storage()
984-
monkeypatch.setattr(client.app.state, "storage", storage)
988+
monkeypatch.setattr(_app_state(client), "storage", storage)
985989

986990
create_response = client.post(
987991
"/api/datasets/upload-url",
@@ -1054,7 +1058,7 @@ def test_upload_url_accepts_unsupported_format_and_persists_content_type(
10541058
expected_storage_key = f"datasets/fixed_{filename}"
10551059

10561060
monkeypatch.setattr(
1057-
client.app.state.storage,
1061+
_app_state(client).storage,
10581062
"create_upload_target",
10591063
lambda _filename, **kwargs: UploadTarget(
10601064
storage_key=expected_storage_key,
@@ -1231,7 +1235,7 @@ def fake_create_upload_target(filename: str, prefix: str | None = None):
12311235
)
12321236

12331237
monkeypatch.setattr(
1234-
client.app.state.storage, "create_upload_target", fake_create_upload_target
1238+
_app_state(client).storage, "create_upload_target", fake_create_upload_target
12351239
)
12361240

12371241
response = client.post(

app/tests/unit/storage/test_config_and_factory.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ def test_settings_defaults(monkeypatch):
1212
monkeypatch.delenv("CLAMD_HOST", raising=False)
1313
monkeypatch.delenv("CLAMD_PORT", raising=False)
1414
monkeypatch.delenv("CLAMD_TIMEOUT_SECONDS", raising=False)
15+
monkeypatch.delenv("UPLOAD_TARGET", raising=False)
16+
monkeypatch.delenv("UPLOAD_LOCATION", raising=False)
17+
monkeypatch.delenv("UPLOAD_URL_EXPIRES_SECONDS", raising=False)
1518
monkeypatch.delenv("COOKIE_SECURE", raising=False)
1619
monkeypatch.delenv("APP_BASE_URL", raising=False)
1720

@@ -28,6 +31,9 @@ def test_settings_defaults(monkeypatch):
2831
assert settings.github_issues.owner == "koevoet1221"
2932
assert settings.github_issues.repo == "openmlupload-testing"
3033
assert settings.app_base_url == "http://localhost:8000"
34+
assert settings.upload.target == "uploads"
35+
assert settings.upload.location == "default"
36+
assert settings.upload.expires_seconds == 3600
3137

3238

3339
def test_cookie_secure_can_be_disabled_for_local_http(monkeypatch):
@@ -46,6 +52,25 @@ def test_app_base_url_can_be_overridden(monkeypatch):
4652
assert settings.app_base_url == "https://upload.example.com"
4753

4854

55+
def test_upload_settings_can_be_overridden(monkeypatch):
56+
monkeypatch.setenv("UPLOAD_TARGET", "team-uploads")
57+
monkeypatch.setenv("UPLOAD_LOCATION", "eu")
58+
monkeypatch.setenv("UPLOAD_URL_EXPIRES_SECONDS", "7200")
59+
60+
settings = Settings.from_env()
61+
62+
assert settings.upload.target == "team-uploads"
63+
assert settings.upload.location == "eu"
64+
assert settings.upload.expires_seconds == 7200
65+
66+
67+
def test_invalid_presigned_url_expiry_raises(monkeypatch):
68+
monkeypatch.setenv("UPLOAD_URL_EXPIRES_SECONDS", "0")
69+
70+
with pytest.raises(ValueError):
71+
Settings.from_env()
72+
73+
4974
def test_invalid_backend_raises(monkeypatch):
5075
monkeypatch.setenv("STORAGE_BACKEND", "dropbox")
5176

0 commit comments

Comments
 (0)