mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-12-08 14:25:41 +03:00
fix tests to use mock auth
This commit is contained in:
parent
1819044553
commit
07d158aac2
@ -62,12 +62,15 @@ def create_fastapi_app(
|
|||||||
stats_emitter: StatsEmitter,
|
stats_emitter: StatsEmitter,
|
||||||
event_metadata_updater: EventMetadataPublisher,
|
event_metadata_updater: EventMetadataPublisher,
|
||||||
config_publisher: CameraConfigUpdatePublisher,
|
config_publisher: CameraConfigUpdatePublisher,
|
||||||
|
enforce_default_admin: bool = True,
|
||||||
):
|
):
|
||||||
logger.info("Starting FastAPI app")
|
logger.info("Starting FastAPI app")
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
debug=False,
|
debug=False,
|
||||||
swagger_ui_parameters={"apisSorter": "alpha", "operationsSorter": "alpha"},
|
swagger_ui_parameters={"apisSorter": "alpha", "operationsSorter": "alpha"},
|
||||||
dependencies=[Depends(require_admin_by_default())],
|
dependencies=[Depends(require_admin_by_default())]
|
||||||
|
if enforce_default_admin
|
||||||
|
else [],
|
||||||
)
|
)
|
||||||
|
|
||||||
# update the request_address with the x-forwarded-for header from nginx
|
# update the request_address with the x-forwarded-for header from nginx
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
from fastapi import Request
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
from peewee_migrate import Router
|
from peewee_migrate import Router
|
||||||
from playhouse.sqlite_ext import SqliteExtDatabase
|
from playhouse.sqlite_ext import SqliteExtDatabase
|
||||||
from playhouse.sqliteq import SqliteQueueDatabase
|
from playhouse.sqliteq import SqliteQueueDatabase
|
||||||
@ -16,6 +18,20 @@ from frigate.review.types import SeverityEnum
|
|||||||
from frigate.test.const import TEST_DB, TEST_DB_CLEANUPS
|
from frigate.test.const import TEST_DB, TEST_DB_CLEANUPS
|
||||||
|
|
||||||
|
|
||||||
|
class AuthTestClient(TestClient):
|
||||||
|
"""TestClient that automatically adds auth headers to all requests."""
|
||||||
|
|
||||||
|
def request(self, *args, **kwargs):
|
||||||
|
# Add default auth headers if not already present
|
||||||
|
headers = kwargs.get("headers") or {}
|
||||||
|
if "remote-user" not in headers:
|
||||||
|
headers["remote-user"] = "admin"
|
||||||
|
if "remote-role" not in headers:
|
||||||
|
headers["remote-role"] = "admin"
|
||||||
|
kwargs["headers"] = headers
|
||||||
|
return super().request(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class BaseTestHttp(unittest.TestCase):
|
class BaseTestHttp(unittest.TestCase):
|
||||||
def setUp(self, models):
|
def setUp(self, models):
|
||||||
# setup clean database for each test run
|
# setup clean database for each test run
|
||||||
@ -113,7 +129,9 @@ class BaseTestHttp(unittest.TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def create_app(self, stats=None, event_metadata_publisher=None):
|
def create_app(self, stats=None, event_metadata_publisher=None):
|
||||||
return create_fastapi_app(
|
from frigate.api.auth import get_allowed_cameras_for_filter, get_current_user
|
||||||
|
|
||||||
|
app = create_fastapi_app(
|
||||||
FrigateConfig(**self.minimal_config),
|
FrigateConfig(**self.minimal_config),
|
||||||
self.db,
|
self.db,
|
||||||
None,
|
None,
|
||||||
@ -123,8 +141,33 @@ class BaseTestHttp(unittest.TestCase):
|
|||||||
stats,
|
stats,
|
||||||
event_metadata_publisher,
|
event_metadata_publisher,
|
||||||
None,
|
None,
|
||||||
|
enforce_default_admin=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Default test mocks for authentication
|
||||||
|
# Tests can override these in their setUp if needed
|
||||||
|
# This mock uses headers set by AuthTestClient
|
||||||
|
async def mock_get_current_user(request: Request):
|
||||||
|
username = request.headers.get("remote-user")
|
||||||
|
role = request.headers.get("remote-role")
|
||||||
|
if not username or not role:
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
|
||||||
|
return JSONResponse(
|
||||||
|
content={"message": "No authorization headers."}, status_code=401
|
||||||
|
)
|
||||||
|
return {"username": username, "role": role}
|
||||||
|
|
||||||
|
async def mock_get_allowed_cameras_for_filter(request: Request):
|
||||||
|
return list(self.minimal_config.get("cameras", {}).keys())
|
||||||
|
|
||||||
|
app.dependency_overrides[get_current_user] = mock_get_current_user
|
||||||
|
app.dependency_overrides[get_allowed_cameras_for_filter] = (
|
||||||
|
mock_get_allowed_cameras_for_filter
|
||||||
|
)
|
||||||
|
|
||||||
|
return app
|
||||||
|
|
||||||
def insert_mock_event(
|
def insert_mock_event(
|
||||||
self,
|
self,
|
||||||
id: str,
|
id: str,
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
from unittest.mock import Mock
|
from unittest.mock import Mock
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
|
||||||
|
|
||||||
from frigate.models import Event, Recordings, ReviewSegment
|
from frigate.models import Event, Recordings, ReviewSegment
|
||||||
from frigate.stats.emitter import StatsEmitter
|
from frigate.stats.emitter import StatsEmitter
|
||||||
from frigate.test.http_api.base_http_test import BaseTestHttp
|
from frigate.test.http_api.base_http_test import AuthTestClient, BaseTestHttp
|
||||||
|
|
||||||
|
|
||||||
class TestHttpApp(BaseTestHttp):
|
class TestHttpApp(BaseTestHttp):
|
||||||
@ -20,7 +18,7 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
stats.get_latest_stats.return_value = self.test_stats
|
stats.get_latest_stats.return_value = self.test_stats
|
||||||
app = super().create_app(stats)
|
app = super().create_app(stats)
|
||||||
|
|
||||||
with TestClient(app) as client:
|
with AuthTestClient(app) as client:
|
||||||
response = client.get("/stats")
|
response = client.get("/stats")
|
||||||
response_json = response.json()
|
response_json = response.json()
|
||||||
assert response_json == self.test_stats
|
assert response_json == self.test_stats
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from fastapi import HTTPException, Request
|
from fastapi import HTTPException, Request
|
||||||
from fastapi.testclient import TestClient
|
|
||||||
|
|
||||||
from frigate.api.auth import (
|
from frigate.api.auth import (
|
||||||
get_allowed_cameras_for_filter,
|
get_allowed_cameras_for_filter,
|
||||||
get_current_user,
|
get_current_user,
|
||||||
)
|
)
|
||||||
from frigate.models import Event, Recordings, ReviewSegment
|
from frigate.models import Event, Recordings, ReviewSegment
|
||||||
from frigate.test.http_api.base_http_test import BaseTestHttp
|
from frigate.test.http_api.base_http_test import AuthTestClient, BaseTestHttp
|
||||||
|
|
||||||
|
|
||||||
class TestCameraAccessEventReview(BaseTestHttp):
|
class TestCameraAccessEventReview(BaseTestHttp):
|
||||||
@ -16,9 +15,17 @@ class TestCameraAccessEventReview(BaseTestHttp):
|
|||||||
super().setUp([Event, ReviewSegment, Recordings])
|
super().setUp([Event, ReviewSegment, Recordings])
|
||||||
self.app = super().create_app()
|
self.app = super().create_app()
|
||||||
|
|
||||||
# Mock get_current_user to return valid user for all tests
|
# Mock get_current_user for all tests
|
||||||
async def mock_get_current_user():
|
async def mock_get_current_user(request: Request):
|
||||||
return {"username": "test_user", "role": "user"}
|
username = request.headers.get("remote-user")
|
||||||
|
role = request.headers.get("remote-role")
|
||||||
|
if not username or not role:
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
|
||||||
|
return JSONResponse(
|
||||||
|
content={"message": "No authorization headers."}, status_code=401
|
||||||
|
)
|
||||||
|
return {"username": username, "role": role}
|
||||||
|
|
||||||
self.app.dependency_overrides[get_current_user] = mock_get_current_user
|
self.app.dependency_overrides[get_current_user] = mock_get_current_user
|
||||||
|
|
||||||
@ -30,21 +37,25 @@ class TestCameraAccessEventReview(BaseTestHttp):
|
|||||||
super().insert_mock_event("event1", camera="front_door")
|
super().insert_mock_event("event1", camera="front_door")
|
||||||
super().insert_mock_event("event2", camera="back_door")
|
super().insert_mock_event("event2", camera="back_door")
|
||||||
|
|
||||||
self.app.dependency_overrides[get_allowed_cameras_for_filter] = lambda: [
|
async def mock_cameras(request: Request):
|
||||||
"front_door"
|
return ["front_door"]
|
||||||
]
|
|
||||||
with TestClient(self.app) as client:
|
self.app.dependency_overrides[get_allowed_cameras_for_filter] = mock_cameras
|
||||||
|
with AuthTestClient(self.app) as client:
|
||||||
resp = client.get("/events")
|
resp = client.get("/events")
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
ids = [e["id"] for e in resp.json()]
|
ids = [e["id"] for e in resp.json()]
|
||||||
assert "event1" in ids
|
assert "event1" in ids
|
||||||
assert "event2" not in ids
|
assert "event2" not in ids
|
||||||
|
|
||||||
self.app.dependency_overrides[get_allowed_cameras_for_filter] = lambda: [
|
async def mock_cameras(request: Request):
|
||||||
"front_door",
|
return [
|
||||||
"back_door",
|
"front_door",
|
||||||
]
|
"back_door",
|
||||||
with TestClient(self.app) as client:
|
]
|
||||||
|
|
||||||
|
self.app.dependency_overrides[get_allowed_cameras_for_filter] = mock_cameras
|
||||||
|
with AuthTestClient(self.app) as client:
|
||||||
resp = client.get("/events")
|
resp = client.get("/events")
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
ids = [e["id"] for e in resp.json()]
|
ids = [e["id"] for e in resp.json()]
|
||||||
@ -54,21 +65,25 @@ class TestCameraAccessEventReview(BaseTestHttp):
|
|||||||
super().insert_mock_review_segment("rev1", camera="front_door")
|
super().insert_mock_review_segment("rev1", camera="front_door")
|
||||||
super().insert_mock_review_segment("rev2", camera="back_door")
|
super().insert_mock_review_segment("rev2", camera="back_door")
|
||||||
|
|
||||||
self.app.dependency_overrides[get_allowed_cameras_for_filter] = lambda: [
|
async def mock_cameras(request: Request):
|
||||||
"front_door"
|
return ["front_door"]
|
||||||
]
|
|
||||||
with TestClient(self.app) as client:
|
self.app.dependency_overrides[get_allowed_cameras_for_filter] = mock_cameras
|
||||||
|
with AuthTestClient(self.app) as client:
|
||||||
resp = client.get("/review")
|
resp = client.get("/review")
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
ids = [r["id"] for r in resp.json()]
|
ids = [r["id"] for r in resp.json()]
|
||||||
assert "rev1" in ids
|
assert "rev1" in ids
|
||||||
assert "rev2" not in ids
|
assert "rev2" not in ids
|
||||||
|
|
||||||
self.app.dependency_overrides[get_allowed_cameras_for_filter] = lambda: [
|
async def mock_cameras(request: Request):
|
||||||
"front_door",
|
return [
|
||||||
"back_door",
|
"front_door",
|
||||||
]
|
"back_door",
|
||||||
with TestClient(self.app) as client:
|
]
|
||||||
|
|
||||||
|
self.app.dependency_overrides[get_allowed_cameras_for_filter] = mock_cameras
|
||||||
|
with AuthTestClient(self.app) as client:
|
||||||
resp = client.get("/review")
|
resp = client.get("/review")
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
ids = [r["id"] for r in resp.json()]
|
ids = [r["id"] for r in resp.json()]
|
||||||
@ -84,7 +99,7 @@ class TestCameraAccessEventReview(BaseTestHttp):
|
|||||||
raise HTTPException(status_code=403, detail="Access denied")
|
raise HTTPException(status_code=403, detail="Access denied")
|
||||||
|
|
||||||
with patch("frigate.api.event.require_camera_access", mock_require_allowed):
|
with patch("frigate.api.event.require_camera_access", mock_require_allowed):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
resp = client.get("/events/event1")
|
resp = client.get("/events/event1")
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
assert resp.json()["id"] == "event1"
|
assert resp.json()["id"] == "event1"
|
||||||
@ -94,7 +109,7 @@ class TestCameraAccessEventReview(BaseTestHttp):
|
|||||||
raise HTTPException(status_code=403, detail="Access denied")
|
raise HTTPException(status_code=403, detail="Access denied")
|
||||||
|
|
||||||
with patch("frigate.api.event.require_camera_access", mock_require_disallowed):
|
with patch("frigate.api.event.require_camera_access", mock_require_disallowed):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
resp = client.get("/events/event1")
|
resp = client.get("/events/event1")
|
||||||
assert resp.status_code == 403
|
assert resp.status_code == 403
|
||||||
|
|
||||||
@ -108,7 +123,7 @@ class TestCameraAccessEventReview(BaseTestHttp):
|
|||||||
raise HTTPException(status_code=403, detail="Access denied")
|
raise HTTPException(status_code=403, detail="Access denied")
|
||||||
|
|
||||||
with patch("frigate.api.review.require_camera_access", mock_require_allowed):
|
with patch("frigate.api.review.require_camera_access", mock_require_allowed):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
resp = client.get("/review/rev1")
|
resp = client.get("/review/rev1")
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
assert resp.json()["id"] == "rev1"
|
assert resp.json()["id"] == "rev1"
|
||||||
@ -118,7 +133,7 @@ class TestCameraAccessEventReview(BaseTestHttp):
|
|||||||
raise HTTPException(status_code=403, detail="Access denied")
|
raise HTTPException(status_code=403, detail="Access denied")
|
||||||
|
|
||||||
with patch("frigate.api.review.require_camera_access", mock_require_disallowed):
|
with patch("frigate.api.review.require_camera_access", mock_require_disallowed):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
resp = client.get("/review/rev1")
|
resp = client.get("/review/rev1")
|
||||||
assert resp.status_code == 403
|
assert resp.status_code == 403
|
||||||
|
|
||||||
@ -126,21 +141,25 @@ class TestCameraAccessEventReview(BaseTestHttp):
|
|||||||
super().insert_mock_event("event1", camera="front_door")
|
super().insert_mock_event("event1", camera="front_door")
|
||||||
super().insert_mock_event("event2", camera="back_door")
|
super().insert_mock_event("event2", camera="back_door")
|
||||||
|
|
||||||
self.app.dependency_overrides[get_allowed_cameras_for_filter] = lambda: [
|
async def mock_cameras(request: Request):
|
||||||
"front_door"
|
return ["front_door"]
|
||||||
]
|
|
||||||
with TestClient(self.app) as client:
|
self.app.dependency_overrides[get_allowed_cameras_for_filter] = mock_cameras
|
||||||
|
with AuthTestClient(self.app) as client:
|
||||||
resp = client.get("/events", params={"cameras": "all"})
|
resp = client.get("/events", params={"cameras": "all"})
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
ids = [e["id"] for e in resp.json()]
|
ids = [e["id"] for e in resp.json()]
|
||||||
assert "event1" in ids
|
assert "event1" in ids
|
||||||
assert "event2" not in ids
|
assert "event2" not in ids
|
||||||
|
|
||||||
self.app.dependency_overrides[get_allowed_cameras_for_filter] = lambda: [
|
async def mock_cameras(request: Request):
|
||||||
"front_door",
|
return [
|
||||||
"back_door",
|
"front_door",
|
||||||
]
|
"back_door",
|
||||||
with TestClient(self.app) as client:
|
]
|
||||||
|
|
||||||
|
self.app.dependency_overrides[get_allowed_cameras_for_filter] = mock_cameras
|
||||||
|
with AuthTestClient(self.app) as client:
|
||||||
resp = client.get("/events", params={"cameras": "all"})
|
resp = client.get("/events", params={"cameras": "all"})
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
ids = [e["id"] for e in resp.json()]
|
ids = [e["id"] for e in resp.json()]
|
||||||
@ -150,20 +169,24 @@ class TestCameraAccessEventReview(BaseTestHttp):
|
|||||||
super().insert_mock_event("event1", camera="front_door")
|
super().insert_mock_event("event1", camera="front_door")
|
||||||
super().insert_mock_event("event2", camera="back_door")
|
super().insert_mock_event("event2", camera="back_door")
|
||||||
|
|
||||||
self.app.dependency_overrides[get_allowed_cameras_for_filter] = lambda: [
|
async def mock_cameras(request: Request):
|
||||||
"front_door"
|
return ["front_door"]
|
||||||
]
|
|
||||||
with TestClient(self.app) as client:
|
self.app.dependency_overrides[get_allowed_cameras_for_filter] = mock_cameras
|
||||||
|
with AuthTestClient(self.app) as client:
|
||||||
resp = client.get("/events/summary")
|
resp = client.get("/events/summary")
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
summary_list = resp.json()
|
summary_list = resp.json()
|
||||||
assert len(summary_list) == 1
|
assert len(summary_list) == 1
|
||||||
|
|
||||||
self.app.dependency_overrides[get_allowed_cameras_for_filter] = lambda: [
|
async def mock_cameras(request: Request):
|
||||||
"front_door",
|
return [
|
||||||
"back_door",
|
"front_door",
|
||||||
]
|
"back_door",
|
||||||
with TestClient(self.app) as client:
|
]
|
||||||
|
|
||||||
|
self.app.dependency_overrides[get_allowed_cameras_for_filter] = mock_cameras
|
||||||
|
with AuthTestClient(self.app) as client:
|
||||||
resp = client.get("/events/summary")
|
resp = client.get("/events/summary")
|
||||||
summary_list = resp.json()
|
summary_list = resp.json()
|
||||||
assert len(summary_list) == 2
|
assert len(summary_list) == 2
|
||||||
|
|||||||
@ -2,14 +2,13 @@ from datetime import datetime
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
from unittest.mock import Mock
|
from unittest.mock import Mock
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
|
||||||
from playhouse.shortcuts import model_to_dict
|
from playhouse.shortcuts import model_to_dict
|
||||||
|
|
||||||
from frigate.api.auth import get_allowed_cameras_for_filter, get_current_user
|
from frigate.api.auth import get_allowed_cameras_for_filter, get_current_user
|
||||||
from frigate.comms.event_metadata_updater import EventMetadataPublisher
|
from frigate.comms.event_metadata_updater import EventMetadataPublisher
|
||||||
from frigate.models import Event, Recordings, ReviewSegment, Timeline
|
from frigate.models import Event, Recordings, ReviewSegment, Timeline
|
||||||
from frigate.stats.emitter import StatsEmitter
|
from frigate.stats.emitter import StatsEmitter
|
||||||
from frigate.test.http_api.base_http_test import BaseTestHttp
|
from frigate.test.http_api.base_http_test import AuthTestClient, BaseTestHttp, Request
|
||||||
from frigate.test.test_storage import _insert_mock_event
|
from frigate.test.test_storage import _insert_mock_event
|
||||||
|
|
||||||
|
|
||||||
@ -18,14 +17,26 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
super().setUp([Event, Recordings, ReviewSegment, Timeline])
|
super().setUp([Event, Recordings, ReviewSegment, Timeline])
|
||||||
self.app = super().create_app()
|
self.app = super().create_app()
|
||||||
|
|
||||||
# Mock auth to bypass camera access for tests
|
# Mock get_current_user for all tests
|
||||||
async def mock_get_current_user(request: Any):
|
async def mock_get_current_user(request: Request):
|
||||||
return {"username": "test_user", "role": "admin"}
|
username = request.headers.get("remote-user")
|
||||||
|
role = request.headers.get("remote-role")
|
||||||
|
if not username or not role:
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
|
||||||
|
return JSONResponse(
|
||||||
|
content={"message": "No authorization headers."}, status_code=401
|
||||||
|
)
|
||||||
|
return {"username": username, "role": role}
|
||||||
|
|
||||||
self.app.dependency_overrides[get_current_user] = mock_get_current_user
|
self.app.dependency_overrides[get_current_user] = mock_get_current_user
|
||||||
self.app.dependency_overrides[get_allowed_cameras_for_filter] = lambda: [
|
|
||||||
"front_door"
|
async def mock_get_allowed_cameras_for_filter(request: Request):
|
||||||
]
|
return ["front_door"]
|
||||||
|
|
||||||
|
self.app.dependency_overrides[get_allowed_cameras_for_filter] = (
|
||||||
|
mock_get_allowed_cameras_for_filter
|
||||||
|
)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.app.dependency_overrides.clear()
|
self.app.dependency_overrides.clear()
|
||||||
@ -35,20 +46,20 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
################################### GET /events Endpoint #########################################################
|
################################### GET /events Endpoint #########################################################
|
||||||
####################################################################################################################
|
####################################################################################################################
|
||||||
def test_get_event_list_no_events(self):
|
def test_get_event_list_no_events(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
events = client.get("/events").json()
|
events = client.get("/events").json()
|
||||||
assert len(events) == 0
|
assert len(events) == 0
|
||||||
|
|
||||||
def test_get_event_list_no_match_event_id(self):
|
def test_get_event_list_no_match_event_id(self):
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_event(id)
|
super().insert_mock_event(id)
|
||||||
events = client.get("/events", params={"event_id": "abc"}).json()
|
events = client.get("/events", params={"event_id": "abc"}).json()
|
||||||
assert len(events) == 0
|
assert len(events) == 0
|
||||||
|
|
||||||
def test_get_event_list_match_event_id(self):
|
def test_get_event_list_match_event_id(self):
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_event(id)
|
super().insert_mock_event(id)
|
||||||
events = client.get("/events", params={"event_id": id}).json()
|
events = client.get("/events", params={"event_id": id}).json()
|
||||||
assert len(events) == 1
|
assert len(events) == 1
|
||||||
@ -58,7 +69,7 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
now = int(datetime.now().timestamp())
|
now = int(datetime.now().timestamp())
|
||||||
|
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_event(id, now, now + 1)
|
super().insert_mock_event(id, now, now + 1)
|
||||||
events = client.get(
|
events = client.get(
|
||||||
"/events", params={"max_length": 1, "min_length": 1}
|
"/events", params={"max_length": 1, "min_length": 1}
|
||||||
@ -69,7 +80,7 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
def test_get_event_list_no_match_max_length(self):
|
def test_get_event_list_no_match_max_length(self):
|
||||||
now = int(datetime.now().timestamp())
|
now = int(datetime.now().timestamp())
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
super().insert_mock_event(id, now, now + 2)
|
super().insert_mock_event(id, now, now + 2)
|
||||||
events = client.get("/events", params={"max_length": 1}).json()
|
events = client.get("/events", params={"max_length": 1}).json()
|
||||||
@ -78,7 +89,7 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
def test_get_event_list_no_match_min_length(self):
|
def test_get_event_list_no_match_min_length(self):
|
||||||
now = int(datetime.now().timestamp())
|
now = int(datetime.now().timestamp())
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
super().insert_mock_event(id, now, now + 2)
|
super().insert_mock_event(id, now, now + 2)
|
||||||
events = client.get("/events", params={"min_length": 3}).json()
|
events = client.get("/events", params={"min_length": 3}).json()
|
||||||
@ -88,7 +99,7 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
id2 = "54321.random"
|
id2 = "54321.random"
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_event(id)
|
super().insert_mock_event(id)
|
||||||
events = client.get("/events").json()
|
events = client.get("/events").json()
|
||||||
assert len(events) == 1
|
assert len(events) == 1
|
||||||
@ -108,14 +119,14 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
def test_get_event_list_no_match_has_clip(self):
|
def test_get_event_list_no_match_has_clip(self):
|
||||||
now = int(datetime.now().timestamp())
|
now = int(datetime.now().timestamp())
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
super().insert_mock_event(id, now, now + 2)
|
super().insert_mock_event(id, now, now + 2)
|
||||||
events = client.get("/events", params={"has_clip": 0}).json()
|
events = client.get("/events", params={"has_clip": 0}).json()
|
||||||
assert len(events) == 0
|
assert len(events) == 0
|
||||||
|
|
||||||
def test_get_event_list_has_clip(self):
|
def test_get_event_list_has_clip(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
super().insert_mock_event(id, has_clip=True)
|
super().insert_mock_event(id, has_clip=True)
|
||||||
events = client.get("/events", params={"has_clip": 1}).json()
|
events = client.get("/events", params={"has_clip": 1}).json()
|
||||||
@ -123,7 +134,7 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
assert events[0]["id"] == id
|
assert events[0]["id"] == id
|
||||||
|
|
||||||
def test_get_event_list_sort_score(self):
|
def test_get_event_list_sort_score(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
id2 = "54321.random"
|
id2 = "54321.random"
|
||||||
super().insert_mock_event(id, top_score=37, score=37, data={"score": 50})
|
super().insert_mock_event(id, top_score=37, score=37, data={"score": 50})
|
||||||
@ -141,7 +152,7 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
def test_get_event_list_sort_start_time(self):
|
def test_get_event_list_sort_start_time(self):
|
||||||
now = int(datetime.now().timestamp())
|
now = int(datetime.now().timestamp())
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
id2 = "54321.random"
|
id2 = "54321.random"
|
||||||
super().insert_mock_event(id, start_time=now + 3)
|
super().insert_mock_event(id, start_time=now + 3)
|
||||||
@ -159,7 +170,7 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
def test_get_good_event(self):
|
def test_get_good_event(self):
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_event(id)
|
super().insert_mock_event(id)
|
||||||
event = client.get(f"/events/{id}").json()
|
event = client.get(f"/events/{id}").json()
|
||||||
|
|
||||||
@ -171,7 +182,7 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
bad_id = "654321.other"
|
bad_id = "654321.other"
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_event(id)
|
super().insert_mock_event(id)
|
||||||
event_response = client.get(f"/events/{bad_id}")
|
event_response = client.get(f"/events/{bad_id}")
|
||||||
assert event_response.status_code == 404
|
assert event_response.status_code == 404
|
||||||
@ -180,7 +191,7 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
def test_delete_event(self):
|
def test_delete_event(self):
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_event(id)
|
super().insert_mock_event(id)
|
||||||
event = client.get(f"/events/{id}").json()
|
event = client.get(f"/events/{id}").json()
|
||||||
assert event
|
assert event
|
||||||
@ -193,7 +204,7 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
def test_event_retention(self):
|
def test_event_retention(self):
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_event(id)
|
super().insert_mock_event(id)
|
||||||
client.post(f"/events/{id}/retain", headers={"remote-role": "admin"})
|
client.post(f"/events/{id}/retain", headers={"remote-role": "admin"})
|
||||||
event = client.get(f"/events/{id}").json()
|
event = client.get(f"/events/{id}").json()
|
||||||
@ -212,12 +223,11 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
morning = 1656590400 # 06/30/2022 6 am (GMT)
|
morning = 1656590400 # 06/30/2022 6 am (GMT)
|
||||||
evening = 1656633600 # 06/30/2022 6 pm (GMT)
|
evening = 1656633600 # 06/30/2022 6 pm (GMT)
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_event(morning_id, morning)
|
super().insert_mock_event(morning_id, morning)
|
||||||
super().insert_mock_event(evening_id, evening)
|
super().insert_mock_event(evening_id, evening)
|
||||||
# both events come back
|
# both events come back
|
||||||
events = client.get("/events").json()
|
events = client.get("/events").json()
|
||||||
print("events!!!", events)
|
|
||||||
assert events
|
assert events
|
||||||
assert len(events) == 2
|
assert len(events) == 2
|
||||||
# morning event is excluded
|
# morning event is excluded
|
||||||
@ -248,7 +258,7 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
|
|
||||||
mock_event_updater.publish.side_effect = update_event
|
mock_event_updater.publish.side_effect = update_event
|
||||||
|
|
||||||
with TestClient(app) as client:
|
with AuthTestClient(app) as client:
|
||||||
super().insert_mock_event(id)
|
super().insert_mock_event(id)
|
||||||
new_sub_label_response = client.post(
|
new_sub_label_response = client.post(
|
||||||
f"/events/{id}/sub_label",
|
f"/events/{id}/sub_label",
|
||||||
@ -285,7 +295,7 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
|
|
||||||
mock_event_updater.publish.side_effect = update_event
|
mock_event_updater.publish.side_effect = update_event
|
||||||
|
|
||||||
with TestClient(app) as client:
|
with AuthTestClient(app) as client:
|
||||||
super().insert_mock_event(id)
|
super().insert_mock_event(id)
|
||||||
client.post(
|
client.post(
|
||||||
f"/events/{id}/sub_label",
|
f"/events/{id}/sub_label",
|
||||||
@ -301,7 +311,7 @@ class TestHttpApp(BaseTestHttp):
|
|||||||
####################################################################################################################
|
####################################################################################################################
|
||||||
def test_get_metrics(self):
|
def test_get_metrics(self):
|
||||||
"""ensure correct prometheus metrics api response"""
|
"""ensure correct prometheus metrics api response"""
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
ts_start = datetime.now().timestamp()
|
ts_start = datetime.now().timestamp()
|
||||||
ts_end = ts_start + 30
|
ts_end = ts_start + 30
|
||||||
_insert_mock_event(
|
_insert_mock_event(
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
"""Unit tests for recordings/media API endpoints."""
|
"""Unit tests for recordings/media API endpoints."""
|
||||||
|
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
from fastapi.testclient import TestClient
|
from fastapi import Request
|
||||||
|
|
||||||
from frigate.api.auth import get_allowed_cameras_for_filter, get_current_user
|
from frigate.api.auth import get_allowed_cameras_for_filter, get_current_user
|
||||||
from frigate.models import Recordings
|
from frigate.models import Recordings
|
||||||
from frigate.test.http_api.base_http_test import BaseTestHttp
|
from frigate.test.http_api.base_http_test import AuthTestClient, BaseTestHttp
|
||||||
|
|
||||||
|
|
||||||
class TestHttpMedia(BaseTestHttp):
|
class TestHttpMedia(BaseTestHttp):
|
||||||
@ -19,15 +18,26 @@ class TestHttpMedia(BaseTestHttp):
|
|||||||
super().setUp([Recordings])
|
super().setUp([Recordings])
|
||||||
self.app = super().create_app()
|
self.app = super().create_app()
|
||||||
|
|
||||||
# Mock auth to bypass camera access for tests
|
# Mock get_current_user for all tests
|
||||||
async def mock_get_current_user(request: Any):
|
async def mock_get_current_user(request: Request):
|
||||||
return {"username": "test_user", "role": "admin"}
|
username = request.headers.get("remote-user")
|
||||||
|
role = request.headers.get("remote-role")
|
||||||
|
if not username or not role:
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
|
||||||
|
return JSONResponse(
|
||||||
|
content={"message": "No authorization headers."}, status_code=401
|
||||||
|
)
|
||||||
|
return {"username": username, "role": role}
|
||||||
|
|
||||||
self.app.dependency_overrides[get_current_user] = mock_get_current_user
|
self.app.dependency_overrides[get_current_user] = mock_get_current_user
|
||||||
self.app.dependency_overrides[get_allowed_cameras_for_filter] = lambda: [
|
|
||||||
"front_door",
|
async def mock_get_allowed_cameras_for_filter(request: Request):
|
||||||
"back_door",
|
return ["front_door"]
|
||||||
]
|
|
||||||
|
self.app.dependency_overrides[get_allowed_cameras_for_filter] = (
|
||||||
|
mock_get_allowed_cameras_for_filter
|
||||||
|
)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
"""Clean up after tests."""
|
"""Clean up after tests."""
|
||||||
@ -52,7 +62,7 @@ class TestHttpMedia(BaseTestHttp):
|
|||||||
# March 11, 2024 at 12:00 PM EDT (after DST)
|
# March 11, 2024 at 12:00 PM EDT (after DST)
|
||||||
march_11_noon = tz.localize(datetime(2024, 3, 11, 12, 0, 0)).timestamp()
|
march_11_noon = tz.localize(datetime(2024, 3, 11, 12, 0, 0)).timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
# Insert recordings for each day
|
# Insert recordings for each day
|
||||||
Recordings.insert(
|
Recordings.insert(
|
||||||
id="recording_march_9",
|
id="recording_march_9",
|
||||||
@ -128,7 +138,7 @@ class TestHttpMedia(BaseTestHttp):
|
|||||||
# November 4, 2024 at 12:00 PM EST (after DST)
|
# November 4, 2024 at 12:00 PM EST (after DST)
|
||||||
nov_4_noon = tz.localize(datetime(2024, 11, 4, 12, 0, 0)).timestamp()
|
nov_4_noon = tz.localize(datetime(2024, 11, 4, 12, 0, 0)).timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
# Insert recordings for each day
|
# Insert recordings for each day
|
||||||
Recordings.insert(
|
Recordings.insert(
|
||||||
id="recording_nov_2",
|
id="recording_nov_2",
|
||||||
@ -195,7 +205,7 @@ class TestHttpMedia(BaseTestHttp):
|
|||||||
# March 10, 2024 at 3:00 PM EDT (after DST transition)
|
# March 10, 2024 at 3:00 PM EDT (after DST transition)
|
||||||
march_10_afternoon = tz.localize(datetime(2024, 3, 10, 15, 0, 0)).timestamp()
|
march_10_afternoon = tz.localize(datetime(2024, 3, 10, 15, 0, 0)).timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
# Insert recordings for front_door on March 9
|
# Insert recordings for front_door on March 9
|
||||||
Recordings.insert(
|
Recordings.insert(
|
||||||
id="front_march_9",
|
id="front_march_9",
|
||||||
@ -250,7 +260,7 @@ class TestHttpMedia(BaseTestHttp):
|
|||||||
# This is 1.5 hours of actual time but spans the "missing" hour
|
# This is 1.5 hours of actual time but spans the "missing" hour
|
||||||
after_transition = tz.localize(datetime(2024, 3, 10, 3, 30, 0)).timestamp()
|
after_transition = tz.localize(datetime(2024, 3, 10, 3, 30, 0)).timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
Recordings.insert(
|
Recordings.insert(
|
||||||
id="recording_during_transition",
|
id="recording_during_transition",
|
||||||
path="/media/recordings/transition.mp4",
|
path="/media/recordings/transition.mp4",
|
||||||
@ -283,7 +293,7 @@ class TestHttpMedia(BaseTestHttp):
|
|||||||
march_9_utc = datetime(2024, 3, 9, 17, 0, 0, tzinfo=timezone.utc).timestamp()
|
march_9_utc = datetime(2024, 3, 9, 17, 0, 0, tzinfo=timezone.utc).timestamp()
|
||||||
march_10_utc = datetime(2024, 3, 10, 17, 0, 0, tzinfo=timezone.utc).timestamp()
|
march_10_utc = datetime(2024, 3, 10, 17, 0, 0, tzinfo=timezone.utc).timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
Recordings.insert(
|
Recordings.insert(
|
||||||
id="recording_march_9_utc",
|
id="recording_march_9_utc",
|
||||||
path="/media/recordings/march_9_utc.mp4",
|
path="/media/recordings/march_9_utc.mp4",
|
||||||
@ -325,7 +335,7 @@ class TestHttpMedia(BaseTestHttp):
|
|||||||
"""
|
"""
|
||||||
Test recordings summary when no recordings exist.
|
Test recordings summary when no recordings exist.
|
||||||
"""
|
"""
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
response = client.get(
|
response = client.get(
|
||||||
"/recordings/summary",
|
"/recordings/summary",
|
||||||
params={"timezone": "America/New_York", "cameras": "all"},
|
params={"timezone": "America/New_York", "cameras": "all"},
|
||||||
@ -342,7 +352,7 @@ class TestHttpMedia(BaseTestHttp):
|
|||||||
tz = pytz.timezone("America/New_York")
|
tz = pytz.timezone("America/New_York")
|
||||||
march_10_noon = tz.localize(datetime(2024, 3, 10, 12, 0, 0)).timestamp()
|
march_10_noon = tz.localize(datetime(2024, 3, 10, 12, 0, 0)).timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
# Insert recordings for both cameras
|
# Insert recordings for both cameras
|
||||||
Recordings.insert(
|
Recordings.insert(
|
||||||
id="front_recording",
|
id="front_recording",
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi import Request
|
||||||
from peewee import DoesNotExist
|
from peewee import DoesNotExist
|
||||||
|
|
||||||
from frigate.api.auth import get_allowed_cameras_for_filter, get_current_user
|
from frigate.api.auth import get_allowed_cameras_for_filter, get_current_user
|
||||||
from frigate.models import Event, Recordings, ReviewSegment, UserReviewStatus
|
from frigate.models import Event, Recordings, ReviewSegment, UserReviewStatus
|
||||||
from frigate.review.types import SeverityEnum
|
from frigate.review.types import SeverityEnum
|
||||||
from frigate.test.http_api.base_http_test import BaseTestHttp
|
from frigate.test.http_api.base_http_test import AuthTestClient, BaseTestHttp
|
||||||
|
|
||||||
|
|
||||||
class TestHttpReview(BaseTestHttp):
|
class TestHttpReview(BaseTestHttp):
|
||||||
@ -16,14 +16,26 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
self.user_id = "admin"
|
self.user_id = "admin"
|
||||||
|
|
||||||
# Mock get_current_user for all tests
|
# Mock get_current_user for all tests
|
||||||
async def mock_get_current_user():
|
# This mock uses headers set by AuthTestClient
|
||||||
return {"username": self.user_id, "role": "admin"}
|
async def mock_get_current_user(request: Request):
|
||||||
|
username = request.headers.get("remote-user")
|
||||||
|
role = request.headers.get("remote-role")
|
||||||
|
if not username or not role:
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
|
||||||
|
return JSONResponse(
|
||||||
|
content={"message": "No authorization headers."}, status_code=401
|
||||||
|
)
|
||||||
|
return {"username": username, "role": role}
|
||||||
|
|
||||||
self.app.dependency_overrides[get_current_user] = mock_get_current_user
|
self.app.dependency_overrides[get_current_user] = mock_get_current_user
|
||||||
|
|
||||||
self.app.dependency_overrides[get_allowed_cameras_for_filter] = lambda: [
|
async def mock_get_allowed_cameras_for_filter(request: Request):
|
||||||
"front_door"
|
return ["front_door"]
|
||||||
]
|
|
||||||
|
self.app.dependency_overrides[get_allowed_cameras_for_filter] = (
|
||||||
|
mock_get_allowed_cameras_for_filter
|
||||||
|
)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.app.dependency_overrides.clear()
|
self.app.dependency_overrides.clear()
|
||||||
@ -57,7 +69,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
but ends after is included in the results."""
|
but ends after is included in the results."""
|
||||||
now = datetime.now().timestamp()
|
now = datetime.now().timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_review_segment("123456.random", now, now + 2)
|
super().insert_mock_review_segment("123456.random", now, now + 2)
|
||||||
response = client.get("/review")
|
response = client.get("/review")
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
@ -67,7 +79,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
def test_get_review_no_filters(self):
|
def test_get_review_no_filters(self):
|
||||||
now = datetime.now().timestamp()
|
now = datetime.now().timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
super().insert_mock_review_segment(id, now - 2, now - 1)
|
super().insert_mock_review_segment(id, now - 2, now - 1)
|
||||||
response = client.get("/review")
|
response = client.get("/review")
|
||||||
@ -81,7 +93,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
"""Test that review items outside the range are not returned."""
|
"""Test that review items outside the range are not returned."""
|
||||||
now = datetime.now().timestamp()
|
now = datetime.now().timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
super().insert_mock_review_segment(id, now - 2, now - 1)
|
super().insert_mock_review_segment(id, now - 2, now - 1)
|
||||||
super().insert_mock_review_segment(f"{id}2", now + 4, now + 5)
|
super().insert_mock_review_segment(f"{id}2", now + 4, now + 5)
|
||||||
@ -97,7 +109,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
def test_get_review_with_time_filter(self):
|
def test_get_review_with_time_filter(self):
|
||||||
now = datetime.now().timestamp()
|
now = datetime.now().timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
super().insert_mock_review_segment(id, now, now + 2)
|
super().insert_mock_review_segment(id, now, now + 2)
|
||||||
params = {
|
params = {
|
||||||
@ -113,7 +125,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
def test_get_review_with_limit_filter(self):
|
def test_get_review_with_limit_filter(self):
|
||||||
now = datetime.now().timestamp()
|
now = datetime.now().timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
id2 = "654321.random"
|
id2 = "654321.random"
|
||||||
super().insert_mock_review_segment(id, now, now + 2)
|
super().insert_mock_review_segment(id, now, now + 2)
|
||||||
@ -132,7 +144,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
def test_get_review_with_severity_filters_no_matches(self):
|
def test_get_review_with_severity_filters_no_matches(self):
|
||||||
now = datetime.now().timestamp()
|
now = datetime.now().timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
super().insert_mock_review_segment(id, now, now + 2, SeverityEnum.detection)
|
super().insert_mock_review_segment(id, now, now + 2, SeverityEnum.detection)
|
||||||
params = {
|
params = {
|
||||||
@ -149,7 +161,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
def test_get_review_with_severity_filters(self):
|
def test_get_review_with_severity_filters(self):
|
||||||
now = datetime.now().timestamp()
|
now = datetime.now().timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
super().insert_mock_review_segment(id, now, now + 2, SeverityEnum.detection)
|
super().insert_mock_review_segment(id, now, now + 2, SeverityEnum.detection)
|
||||||
params = {
|
params = {
|
||||||
@ -165,7 +177,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
def test_get_review_with_all_filters(self):
|
def test_get_review_with_all_filters(self):
|
||||||
now = datetime.now().timestamp()
|
now = datetime.now().timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
super().insert_mock_review_segment(id, now, now + 2)
|
super().insert_mock_review_segment(id, now, now + 2)
|
||||||
params = {
|
params = {
|
||||||
@ -188,7 +200,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
################################### GET /review/summary Endpoint #################################################
|
################################### GET /review/summary Endpoint #################################################
|
||||||
####################################################################################################################
|
####################################################################################################################
|
||||||
def test_get_review_summary_all_filters(self):
|
def test_get_review_summary_all_filters(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_review_segment("123456.random")
|
super().insert_mock_review_segment("123456.random")
|
||||||
params = {
|
params = {
|
||||||
"cameras": "front_door",
|
"cameras": "front_door",
|
||||||
@ -219,7 +231,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
self.assertEqual(response_json, expected_response)
|
self.assertEqual(response_json, expected_response)
|
||||||
|
|
||||||
def test_get_review_summary_no_filters(self):
|
def test_get_review_summary_no_filters(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_review_segment("123456.random")
|
super().insert_mock_review_segment("123456.random")
|
||||||
response = client.get("/review/summary")
|
response = client.get("/review/summary")
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
@ -247,7 +259,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
five_days_ago = datetime.today() - timedelta(days=5)
|
five_days_ago = datetime.today() - timedelta(days=5)
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_review_segment(
|
super().insert_mock_review_segment(
|
||||||
"123456.random", now.timestamp() - 2, now.timestamp() - 1
|
"123456.random", now.timestamp() - 2, now.timestamp() - 1
|
||||||
)
|
)
|
||||||
@ -291,7 +303,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
five_days_ago = datetime.today() - timedelta(days=5)
|
five_days_ago = datetime.today() - timedelta(days=5)
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_review_segment("123456.random", now.timestamp())
|
super().insert_mock_review_segment("123456.random", now.timestamp())
|
||||||
five_days_ago_ts = five_days_ago.timestamp()
|
five_days_ago_ts = five_days_ago.timestamp()
|
||||||
for i in range(20):
|
for i in range(20):
|
||||||
@ -342,7 +354,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
def test_get_review_summary_multiple_in_same_day_with_reviewed(self):
|
def test_get_review_summary_multiple_in_same_day_with_reviewed(self):
|
||||||
five_days_ago = datetime.today() - timedelta(days=5)
|
five_days_ago = datetime.today() - timedelta(days=5)
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
five_days_ago_ts = five_days_ago.timestamp()
|
five_days_ago_ts = five_days_ago.timestamp()
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
id = f"123456_{i}.random_alert_not_reviewed"
|
id = f"123456_{i}.random_alert_not_reviewed"
|
||||||
@ -393,14 +405,14 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
####################################################################################################################
|
####################################################################################################################
|
||||||
|
|
||||||
def test_post_reviews_viewed_no_body(self):
|
def test_post_reviews_viewed_no_body(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_review_segment("123456.random")
|
super().insert_mock_review_segment("123456.random")
|
||||||
response = client.post("/reviews/viewed")
|
response = client.post("/reviews/viewed")
|
||||||
# Missing ids
|
# Missing ids
|
||||||
assert response.status_code == 422
|
assert response.status_code == 422
|
||||||
|
|
||||||
def test_post_reviews_viewed_no_body_ids(self):
|
def test_post_reviews_viewed_no_body_ids(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_review_segment("123456.random")
|
super().insert_mock_review_segment("123456.random")
|
||||||
body = {"ids": [""]}
|
body = {"ids": [""]}
|
||||||
response = client.post("/reviews/viewed", json=body)
|
response = client.post("/reviews/viewed", json=body)
|
||||||
@ -408,7 +420,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
assert response.status_code == 422
|
assert response.status_code == 422
|
||||||
|
|
||||||
def test_post_reviews_viewed_non_existent_id(self):
|
def test_post_reviews_viewed_non_existent_id(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
super().insert_mock_review_segment(id)
|
super().insert_mock_review_segment(id)
|
||||||
body = {"ids": ["1"]}
|
body = {"ids": ["1"]}
|
||||||
@ -425,7 +437,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_post_reviews_viewed(self):
|
def test_post_reviews_viewed(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
super().insert_mock_review_segment(id)
|
super().insert_mock_review_segment(id)
|
||||||
body = {"ids": [id]}
|
body = {"ids": [id]}
|
||||||
@ -445,14 +457,14 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
################################### POST reviews/delete Endpoint ################################################
|
################################### POST reviews/delete Endpoint ################################################
|
||||||
####################################################################################################################
|
####################################################################################################################
|
||||||
def test_post_reviews_delete_no_body(self):
|
def test_post_reviews_delete_no_body(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_review_segment("123456.random")
|
super().insert_mock_review_segment("123456.random")
|
||||||
response = client.post("/reviews/delete", headers={"remote-role": "admin"})
|
response = client.post("/reviews/delete", headers={"remote-role": "admin"})
|
||||||
# Missing ids
|
# Missing ids
|
||||||
assert response.status_code == 422
|
assert response.status_code == 422
|
||||||
|
|
||||||
def test_post_reviews_delete_no_body_ids(self):
|
def test_post_reviews_delete_no_body_ids(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
super().insert_mock_review_segment("123456.random")
|
super().insert_mock_review_segment("123456.random")
|
||||||
body = {"ids": [""]}
|
body = {"ids": [""]}
|
||||||
response = client.post(
|
response = client.post(
|
||||||
@ -462,7 +474,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
assert response.status_code == 422
|
assert response.status_code == 422
|
||||||
|
|
||||||
def test_post_reviews_delete_non_existent_id(self):
|
def test_post_reviews_delete_non_existent_id(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
super().insert_mock_review_segment(id)
|
super().insert_mock_review_segment(id)
|
||||||
body = {"ids": ["1"]}
|
body = {"ids": ["1"]}
|
||||||
@ -479,7 +491,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
assert review_ids_in_db_after[0].id == id
|
assert review_ids_in_db_after[0].id == id
|
||||||
|
|
||||||
def test_post_reviews_delete(self):
|
def test_post_reviews_delete(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
super().insert_mock_review_segment(id)
|
super().insert_mock_review_segment(id)
|
||||||
body = {"ids": [id]}
|
body = {"ids": [id]}
|
||||||
@ -495,7 +507,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
assert len(review_ids_in_db_after) == 0
|
assert len(review_ids_in_db_after) == 0
|
||||||
|
|
||||||
def test_post_reviews_delete_many(self):
|
def test_post_reviews_delete_many(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
ids = ["123456.random", "654321.random"]
|
ids = ["123456.random", "654321.random"]
|
||||||
for id in ids:
|
for id in ids:
|
||||||
super().insert_mock_review_segment(id)
|
super().insert_mock_review_segment(id)
|
||||||
@ -527,7 +539,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
def test_review_activity_motion_no_data_for_time_range(self):
|
def test_review_activity_motion_no_data_for_time_range(self):
|
||||||
now = datetime.now().timestamp()
|
now = datetime.now().timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
params = {
|
params = {
|
||||||
"after": now,
|
"after": now,
|
||||||
"before": now + 3,
|
"before": now + 3,
|
||||||
@ -540,7 +552,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
def test_review_activity_motion(self):
|
def test_review_activity_motion(self):
|
||||||
now = int(datetime.now().timestamp())
|
now = int(datetime.now().timestamp())
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
one_m = int((datetime.now() + timedelta(minutes=1)).timestamp())
|
one_m = int((datetime.now() + timedelta(minutes=1)).timestamp())
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
id2 = "123451.random"
|
id2 = "123451.random"
|
||||||
@ -573,7 +585,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
################################### GET /review/event/{event_id} Endpoint #######################################
|
################################### GET /review/event/{event_id} Endpoint #######################################
|
||||||
####################################################################################################################
|
####################################################################################################################
|
||||||
def test_review_event_not_found(self):
|
def test_review_event_not_found(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
response = client.get("/review/event/123456.random")
|
response = client.get("/review/event/123456.random")
|
||||||
assert response.status_code == 404
|
assert response.status_code == 404
|
||||||
response_json = response.json()
|
response_json = response.json()
|
||||||
@ -585,7 +597,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
def test_review_event_not_found_in_data(self):
|
def test_review_event_not_found_in_data(self):
|
||||||
now = datetime.now().timestamp()
|
now = datetime.now().timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
id = "123456.random"
|
id = "123456.random"
|
||||||
super().insert_mock_review_segment(id, now + 1, now + 2)
|
super().insert_mock_review_segment(id, now + 1, now + 2)
|
||||||
response = client.get(f"/review/event/{id}")
|
response = client.get(f"/review/event/{id}")
|
||||||
@ -599,7 +611,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
def test_review_get_specific_event(self):
|
def test_review_get_specific_event(self):
|
||||||
now = datetime.now().timestamp()
|
now = datetime.now().timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
event_id = "123456.event.random"
|
event_id = "123456.event.random"
|
||||||
super().insert_mock_event(event_id)
|
super().insert_mock_event(event_id)
|
||||||
review_id = "123456.review.random"
|
review_id = "123456.review.random"
|
||||||
@ -626,7 +638,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
################################### GET /review/{review_id} Endpoint #######################################
|
################################### GET /review/{review_id} Endpoint #######################################
|
||||||
####################################################################################################################
|
####################################################################################################################
|
||||||
def test_review_not_found(self):
|
def test_review_not_found(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
response = client.get("/review/123456.random")
|
response = client.get("/review/123456.random")
|
||||||
assert response.status_code == 404
|
assert response.status_code == 404
|
||||||
response_json = response.json()
|
response_json = response.json()
|
||||||
@ -638,7 +650,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
def test_get_review(self):
|
def test_get_review(self):
|
||||||
now = datetime.now().timestamp()
|
now = datetime.now().timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
review_id = "123456.review.random"
|
review_id = "123456.review.random"
|
||||||
super().insert_mock_review_segment(review_id, now + 1, now + 2)
|
super().insert_mock_review_segment(review_id, now + 1, now + 2)
|
||||||
response = client.get(f"/review/{review_id}")
|
response = client.get(f"/review/{review_id}")
|
||||||
@ -662,7 +674,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
####################################################################################################################
|
####################################################################################################################
|
||||||
|
|
||||||
def test_delete_review_viewed_review_not_found(self):
|
def test_delete_review_viewed_review_not_found(self):
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
review_id = "123456.random"
|
review_id = "123456.random"
|
||||||
response = client.delete(f"/review/{review_id}/viewed")
|
response = client.delete(f"/review/{review_id}/viewed")
|
||||||
assert response.status_code == 404
|
assert response.status_code == 404
|
||||||
@ -675,7 +687,7 @@ class TestHttpReview(BaseTestHttp):
|
|||||||
def test_delete_review_viewed(self):
|
def test_delete_review_viewed(self):
|
||||||
now = datetime.now().timestamp()
|
now = datetime.now().timestamp()
|
||||||
|
|
||||||
with TestClient(self.app) as client:
|
with AuthTestClient(self.app) as client:
|
||||||
review_id = "123456.review.random"
|
review_id = "123456.review.random"
|
||||||
super().insert_mock_review_segment(review_id, now + 1, now + 2)
|
super().insert_mock_review_segment(review_id, now + 1, now + 2)
|
||||||
self._insert_user_review_status(review_id, reviewed=True)
|
self._insert_user_review_status(review_id, reviewed=True)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user