Changes committed
This commit is contained in:
0
docengine/tests/repositories/__init__.py
Normal file
0
docengine/tests/repositories/__init__.py
Normal file
278
docengine/tests/repositories/test_document_repository.py
Normal file
278
docengine/tests/repositories/test_document_repository.py
Normal file
@@ -0,0 +1,278 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
|
||||
import pytest
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.models.document import (
|
||||
Document,
|
||||
DocumentImage,
|
||||
DocumentPage,
|
||||
DocumentTable,
|
||||
DocumentTextBlock,
|
||||
TemplateMatch,
|
||||
)
|
||||
from app.repositories.document_repository import (
|
||||
DocumentPageRepository,
|
||||
DocumentRepository,
|
||||
DocumentTextBlockRepository,
|
||||
TemplateMatchRepository,
|
||||
)
|
||||
from tests.conftest import (
|
||||
create_test_document,
|
||||
create_test_fingerprint,
|
||||
create_test_page,
|
||||
create_test_template,
|
||||
create_test_text_block,
|
||||
create_test_user,
|
||||
)
|
||||
|
||||
|
||||
class TestDocumentRepository:
|
||||
"""Tests for DocumentRepository CRUD."""
|
||||
|
||||
def test_create_document(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
doc = create_test_document(db, user=user, filename="created.pdf")
|
||||
assert doc.id is not None
|
||||
assert doc.original_filename == "created.pdf"
|
||||
assert doc.status == "pending"
|
||||
|
||||
def test_get_by_id(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
doc = create_test_document(db, user=user)
|
||||
repo = DocumentRepository(db)
|
||||
found = repo.get_by_id(doc.id)
|
||||
assert found is not None
|
||||
assert found.id == doc.id
|
||||
|
||||
def test_get_by_id_not_found(self, db: Session) -> None:
|
||||
repo = DocumentRepository(db)
|
||||
assert repo.get_by_id(uuid.uuid4()) is None
|
||||
|
||||
def test_get_with_pages(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
doc = create_test_document(db, user=user)
|
||||
page1 = create_test_page(db, doc, page_number=1)
|
||||
page2 = create_test_page(db, doc, page_number=2)
|
||||
create_test_text_block(db, page1, text="Page 1 text")
|
||||
|
||||
repo = DocumentRepository(db)
|
||||
result = repo.get_with_pages(doc.id)
|
||||
assert result is not None
|
||||
assert len(result.pages) == 2
|
||||
|
||||
def test_update_status(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
doc = create_test_document(db, user=user, status="pending")
|
||||
repo = DocumentRepository(db)
|
||||
repo.update_status(doc.id, "processing")
|
||||
db.flush()
|
||||
|
||||
updated = repo.get_by_id(doc.id)
|
||||
assert updated is not None
|
||||
assert updated.status == "processing"
|
||||
|
||||
def test_update_status_with_error(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
doc = create_test_document(db, user=user, status="processing")
|
||||
repo = DocumentRepository(db)
|
||||
repo.update_status(doc.id, "failed", error_message="OCR engine crashed")
|
||||
db.flush()
|
||||
|
||||
updated = repo.get_by_id(doc.id)
|
||||
assert updated is not None
|
||||
assert updated.status == "failed"
|
||||
assert updated.error_message == "OCR engine crashed"
|
||||
|
||||
def test_get_all_with_pagination(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
for i in range(5):
|
||||
create_test_document(db, user=user, filename=f"pagdoc_{i}.pdf")
|
||||
|
||||
repo = DocumentRepository(db)
|
||||
page1 = repo.get_all(offset=0, limit=3)
|
||||
assert len(page1) == 3
|
||||
|
||||
page2 = repo.get_all(offset=3, limit=3)
|
||||
assert len(page2) == 2
|
||||
|
||||
def test_get_all_with_status_filter(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
create_test_document(db, user=user, filename="pend.pdf", status="pending")
|
||||
create_test_document(db, user=user, filename="comp.pdf", status="completed")
|
||||
create_test_document(db, user=user, filename="fail.pdf", status="failed")
|
||||
|
||||
repo = DocumentRepository(db)
|
||||
pending = repo.get_all(offset=0, limit=100, filters={"status": "pending"})
|
||||
assert all(d.status == "pending" for d in pending)
|
||||
|
||||
def test_count(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
create_test_document(db, user=user, filename="cnt1.pdf")
|
||||
create_test_document(db, user=user, filename="cnt2.pdf")
|
||||
|
||||
repo = DocumentRepository(db)
|
||||
total = repo.count()
|
||||
assert total >= 2
|
||||
|
||||
def test_count_with_filter(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
create_test_document(db, user=user, filename="cnt_p.pdf", status="pending")
|
||||
create_test_document(db, user=user, filename="cnt_c.pdf", status="completed")
|
||||
|
||||
repo = DocumentRepository(db)
|
||||
pending_count = repo.count(filters={"status": "pending"})
|
||||
assert pending_count >= 1
|
||||
|
||||
def test_delete(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
doc = create_test_document(db, user=user)
|
||||
repo = DocumentRepository(db)
|
||||
repo.delete(doc)
|
||||
db.flush()
|
||||
|
||||
assert repo.get_by_id(doc.id) is None
|
||||
|
||||
def test_get_by_checksum(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
doc = create_test_document(db, user=user)
|
||||
repo = DocumentRepository(db)
|
||||
found = repo.get_by_checksum(doc.checksum)
|
||||
assert found is not None
|
||||
assert found.id == doc.id
|
||||
|
||||
|
||||
class TestDocumentPageRepository:
|
||||
"""Tests for DocumentPageRepository."""
|
||||
|
||||
def test_create_page(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
doc = create_test_document(db, user=user)
|
||||
page = create_test_page(db, doc, page_number=1)
|
||||
assert page.id is not None
|
||||
assert page.document_id == doc.id
|
||||
assert page.page_number == 1
|
||||
|
||||
def test_get_pages_by_document(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
doc = create_test_document(db, user=user)
|
||||
create_test_page(db, doc, page_number=1)
|
||||
create_test_page(db, doc, page_number=2)
|
||||
create_test_page(db, doc, page_number=3)
|
||||
|
||||
repo = DocumentPageRepository(db)
|
||||
pages = repo.get_document_pages(doc.id)
|
||||
assert len(pages) == 3
|
||||
assert [p.page_number for p in pages] == [1, 2, 3]
|
||||
|
||||
|
||||
class TestDocumentTextBlockRepository:
|
||||
"""Tests for DocumentTextBlockRepository."""
|
||||
|
||||
def test_create_text_block(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
doc = create_test_document(db, user=user)
|
||||
page = create_test_page(db, doc)
|
||||
block = create_test_text_block(db, page, text="Hello World")
|
||||
assert block.id is not None
|
||||
assert block.text == "Hello World"
|
||||
assert block.page_id == page.id
|
||||
|
||||
def test_get_blocks_by_page(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
doc = create_test_document(db, user=user)
|
||||
page = create_test_page(db, doc)
|
||||
create_test_text_block(db, page, text="First", sequence=0)
|
||||
create_test_text_block(db, page, text="Second", sequence=1, y=120.0)
|
||||
create_test_text_block(db, page, text="Third", sequence=2, y=140.0)
|
||||
|
||||
repo = DocumentTextBlockRepository(db)
|
||||
blocks = repo.get_page_text_blocks(page.id)
|
||||
assert len(blocks) == 3
|
||||
|
||||
def test_get_blocks_by_type(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
doc = create_test_document(db, user=user)
|
||||
page = create_test_page(db, doc)
|
||||
create_test_text_block(db, page, text="Header", block_type="header")
|
||||
create_test_text_block(db, page, text="Body", block_type="text", y=200.0)
|
||||
create_test_text_block(db, page, text="Footer", block_type="footer", y=700.0)
|
||||
|
||||
repo = DocumentTextBlockRepository(db)
|
||||
headers = repo.get_by_block_type(page.id, "header")
|
||||
assert len(headers) == 1
|
||||
assert headers[0].text == "Header"
|
||||
|
||||
|
||||
class TestTemplateMatchRepository:
|
||||
"""Tests for TemplateMatchRepository."""
|
||||
|
||||
def test_create_match(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
doc = create_test_document(db, user=user, status="completed")
|
||||
template = create_test_template(db, created_by=user)
|
||||
|
||||
match = TemplateMatch(
|
||||
id=uuid.uuid4(),
|
||||
document_id=doc.id,
|
||||
format_id=template.id,
|
||||
confidence_score=0.85,
|
||||
selected=True,
|
||||
)
|
||||
db.add(match)
|
||||
db.flush()
|
||||
|
||||
repo = TemplateMatchRepository(db)
|
||||
matches = repo.get_document_matches(doc.id)
|
||||
assert len(matches) == 1
|
||||
assert matches[0].confidence_score == 0.85
|
||||
|
||||
def test_get_selected_match(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
doc = create_test_document(db, user=user, status="completed")
|
||||
t1 = create_test_template(db, name="Low", created_by=user)
|
||||
t2 = create_test_template(db, name="High", created_by=user)
|
||||
|
||||
db.add(TemplateMatch(
|
||||
id=uuid.uuid4(), document_id=doc.id, format_id=t1.id,
|
||||
confidence_score=0.5, selected=False,
|
||||
))
|
||||
db.add(TemplateMatch(
|
||||
id=uuid.uuid4(), document_id=doc.id, format_id=t2.id,
|
||||
confidence_score=0.95, selected=True,
|
||||
))
|
||||
db.flush()
|
||||
|
||||
repo = TemplateMatchRepository(db)
|
||||
best = repo.get_selected_match(doc.id)
|
||||
assert best is not None
|
||||
assert best.format_id == t2.id
|
||||
assert best.confidence_score == 0.95
|
||||
|
||||
def test_get_document_matches_ordered(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
doc = create_test_document(db, user=user, status="completed")
|
||||
t1 = create_test_template(db, name="T1", created_by=user)
|
||||
t2 = create_test_template(db, name="T2", created_by=user)
|
||||
t3 = create_test_template(db, name="T3", created_by=user)
|
||||
|
||||
db.add(TemplateMatch(
|
||||
id=uuid.uuid4(), document_id=doc.id, format_id=t1.id,
|
||||
confidence_score=0.3, selected=False,
|
||||
))
|
||||
db.add(TemplateMatch(
|
||||
id=uuid.uuid4(), document_id=doc.id, format_id=t2.id,
|
||||
confidence_score=0.9, selected=True,
|
||||
))
|
||||
db.add(TemplateMatch(
|
||||
id=uuid.uuid4(), document_id=doc.id, format_id=t3.id,
|
||||
confidence_score=0.6, selected=False,
|
||||
))
|
||||
db.flush()
|
||||
|
||||
repo = TemplateMatchRepository(db)
|
||||
matches = repo.get_document_matches(doc.id)
|
||||
scores = [m.confidence_score for m in matches]
|
||||
assert scores == sorted(scores, reverse=True)
|
||||
292
docengine/tests/repositories/test_user_repository.py
Normal file
292
docengine/tests/repositories/test_user_repository.py
Normal file
@@ -0,0 +1,292 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from datetime import UTC, datetime, timedelta
|
||||
|
||||
import pytest
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.models.user import RefreshToken, Role, User
|
||||
from app.repositories.user_repository import (
|
||||
AuditLogRepository,
|
||||
RefreshTokenRepository,
|
||||
RoleRepository,
|
||||
UserRepository,
|
||||
)
|
||||
from tests.conftest import create_test_role, create_test_user
|
||||
|
||||
|
||||
class TestUserRepository:
|
||||
"""Tests for UserRepository CRUD operations."""
|
||||
|
||||
def test_create_user(self, db: Session) -> None:
|
||||
repo = UserRepository(db)
|
||||
user = repo.create_user(
|
||||
username="repo_user",
|
||||
email="repo@test.com",
|
||||
hashed_password="$2b$12$fakehash",
|
||||
full_name="Repo User",
|
||||
)
|
||||
assert user.id is not None
|
||||
assert user.username == "repo_user"
|
||||
assert user.email == "repo@test.com"
|
||||
assert user.is_active is True
|
||||
assert user.is_superuser is False
|
||||
|
||||
def test_get_by_username(self, db: Session) -> None:
|
||||
user = create_test_user(db, username="findme")
|
||||
repo = UserRepository(db)
|
||||
found = repo.get_by_username("findme")
|
||||
assert found is not None
|
||||
assert found.id == user.id
|
||||
|
||||
def test_get_by_username_not_found(self, db: Session) -> None:
|
||||
repo = UserRepository(db)
|
||||
assert repo.get_by_username("nonexistent") is None
|
||||
|
||||
def test_get_by_email(self, db: Session) -> None:
|
||||
user = create_test_user(db, email="email@test.com")
|
||||
repo = UserRepository(db)
|
||||
found = repo.get_by_email("email@test.com")
|
||||
assert found is not None
|
||||
assert found.id == user.id
|
||||
|
||||
def test_get_by_email_not_found(self, db: Session) -> None:
|
||||
repo = UserRepository(db)
|
||||
assert repo.get_by_email("nobody@test.com") is None
|
||||
|
||||
def test_get_by_id(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
repo = UserRepository(db)
|
||||
found = repo.get_by_id(user.id)
|
||||
assert found is not None
|
||||
assert found.username == user.username
|
||||
|
||||
def test_get_by_id_not_found(self, db: Session) -> None:
|
||||
repo = UserRepository(db)
|
||||
assert repo.get_by_id(uuid.uuid4()) is None
|
||||
|
||||
def test_update_last_login(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
assert user.last_login is None
|
||||
repo = UserRepository(db)
|
||||
updated = repo.update_last_login(user)
|
||||
assert updated.last_login is not None
|
||||
|
||||
def test_get_active_users(self, db: Session) -> None:
|
||||
create_test_user(db, username="active1", is_active=True)
|
||||
create_test_user(db, username="active2", is_active=True)
|
||||
create_test_user(db, username="inactive1", is_active=False)
|
||||
|
||||
repo = UserRepository(db)
|
||||
active = repo.get_active_users()
|
||||
usernames = [u.username for u in active]
|
||||
assert "active1" in usernames
|
||||
assert "active2" in usernames
|
||||
assert "inactive1" not in usernames
|
||||
|
||||
def test_create_user_with_roles(self, db: Session) -> None:
|
||||
create_test_role(db, name="admin")
|
||||
create_test_role(db, name="user")
|
||||
|
||||
repo = UserRepository(db)
|
||||
user = repo.create_user(
|
||||
username="roled_user",
|
||||
email="roled@test.com",
|
||||
hashed_password="$2b$12$fakehash",
|
||||
role_names=["admin", "user"],
|
||||
)
|
||||
role_names = [r.name for r in user.roles]
|
||||
assert "admin" in role_names
|
||||
assert "user" in role_names
|
||||
|
||||
def test_assign_roles(self, db: Session) -> None:
|
||||
create_test_role(db, name="viewer")
|
||||
user = create_test_user(db)
|
||||
repo = UserRepository(db)
|
||||
updated = repo.assign_roles(user, ["viewer"])
|
||||
role_names = [r.name for r in updated.roles]
|
||||
assert "viewer" in role_names
|
||||
|
||||
def test_delete_user(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
repo = UserRepository(db)
|
||||
assert repo.delete_by_id(user.id) is True
|
||||
assert repo.get_by_id(user.id) is None
|
||||
|
||||
def test_delete_nonexistent_user(self, db: Session) -> None:
|
||||
repo = UserRepository(db)
|
||||
assert repo.delete_by_id(uuid.uuid4()) is False
|
||||
|
||||
def test_exists(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
repo = UserRepository(db)
|
||||
assert repo.exists(user.id) is True
|
||||
assert repo.exists(uuid.uuid4()) is False
|
||||
|
||||
def test_count(self, db: Session) -> None:
|
||||
create_test_user(db, username="count1")
|
||||
create_test_user(db, username="count2")
|
||||
repo = UserRepository(db)
|
||||
assert repo.count() >= 2
|
||||
|
||||
|
||||
class TestRoleRepository:
|
||||
"""Tests for RoleRepository."""
|
||||
|
||||
def test_create_role(self, db: Session) -> None:
|
||||
repo = RoleRepository(db)
|
||||
role = repo.create_role(name="editor", description="Can edit documents")
|
||||
assert role.id is not None
|
||||
assert role.name == "editor"
|
||||
|
||||
def test_get_by_name(self, db: Session) -> None:
|
||||
create_test_role(db, name="tester")
|
||||
repo = RoleRepository(db)
|
||||
found = repo.get_by_name("tester")
|
||||
assert found is not None
|
||||
assert found.name == "tester"
|
||||
|
||||
def test_get_by_name_not_found(self, db: Session) -> None:
|
||||
repo = RoleRepository(db)
|
||||
assert repo.get_by_name("nonexistent_role") is None
|
||||
|
||||
def test_get_all_roles(self, db: Session) -> None:
|
||||
create_test_role(db, name="role_a")
|
||||
create_test_role(db, name="role_b")
|
||||
repo = RoleRepository(db)
|
||||
roles = repo.get_all_roles()
|
||||
names = [r.name for r in roles]
|
||||
assert "role_a" in names
|
||||
assert "role_b" in names
|
||||
|
||||
|
||||
class TestRefreshTokenRepository:
|
||||
"""Tests for RefreshTokenRepository."""
|
||||
|
||||
def test_create_token(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
repo = RefreshTokenRepository(db)
|
||||
expires = datetime.now(UTC) + timedelta(days=7)
|
||||
token = repo.create_token(
|
||||
user_id=user.id,
|
||||
token="test_refresh_token_abc",
|
||||
expires_at=expires,
|
||||
)
|
||||
assert token.id is not None
|
||||
assert token.user_id == user.id
|
||||
assert token.revoked is False
|
||||
|
||||
def test_get_by_token(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
repo = RefreshTokenRepository(db)
|
||||
expires = datetime.now(UTC) + timedelta(days=7)
|
||||
repo.create_token(user_id=user.id, token="findable_token", expires_at=expires)
|
||||
|
||||
found = repo.get_by_token("findable_token")
|
||||
assert found is not None
|
||||
assert found.user_id == user.id
|
||||
|
||||
def test_get_by_token_not_found(self, db: Session) -> None:
|
||||
repo = RefreshTokenRepository(db)
|
||||
assert repo.get_by_token("nonexistent_token") is None
|
||||
|
||||
def test_get_by_revoked_token_returns_none(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
repo = RefreshTokenRepository(db)
|
||||
expires = datetime.now(UTC) + timedelta(days=7)
|
||||
repo.create_token(user_id=user.id, token="revoked_token", expires_at=expires)
|
||||
repo.revoke_token("revoked_token")
|
||||
db.flush()
|
||||
|
||||
assert repo.get_by_token("revoked_token") is None
|
||||
|
||||
def test_revoke_token(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
repo = RefreshTokenRepository(db)
|
||||
expires = datetime.now(UTC) + timedelta(days=7)
|
||||
repo.create_token(user_id=user.id, token="to_revoke", expires_at=expires)
|
||||
|
||||
assert repo.revoke_token("to_revoke") is True
|
||||
assert repo.get_by_token("to_revoke") is None
|
||||
|
||||
def test_revoke_nonexistent_token(self, db: Session) -> None:
|
||||
repo = RefreshTokenRepository(db)
|
||||
assert repo.revoke_token("does_not_exist") is False
|
||||
|
||||
def test_revoke_all_user_tokens(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
repo = RefreshTokenRepository(db)
|
||||
expires = datetime.now(UTC) + timedelta(days=7)
|
||||
repo.create_token(user_id=user.id, token="token_1", expires_at=expires)
|
||||
repo.create_token(user_id=user.id, token="token_2", expires_at=expires)
|
||||
repo.create_token(user_id=user.id, token="token_3", expires_at=expires)
|
||||
|
||||
count = repo.revoke_all_user_tokens(user.id)
|
||||
assert count == 3
|
||||
assert repo.get_by_token("token_1") is None
|
||||
assert repo.get_by_token("token_2") is None
|
||||
assert repo.get_by_token("token_3") is None
|
||||
|
||||
def test_cleanup_expired_tokens(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
repo = RefreshTokenRepository(db)
|
||||
|
||||
# Create expired token
|
||||
expired = datetime.now(UTC) - timedelta(days=1)
|
||||
repo.create_token(user_id=user.id, token="expired_tok", expires_at=expired)
|
||||
|
||||
# Create valid token
|
||||
valid = datetime.now(UTC) + timedelta(days=7)
|
||||
repo.create_token(user_id=user.id, token="valid_tok", expires_at=valid)
|
||||
|
||||
count = repo.cleanup_expired_tokens()
|
||||
assert count >= 1
|
||||
|
||||
|
||||
class TestAuditLogRepository:
|
||||
"""Tests for AuditLogRepository."""
|
||||
|
||||
def test_log_action(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
repo = AuditLogRepository(db)
|
||||
log = repo.log_action(
|
||||
action="login",
|
||||
resource_type="auth",
|
||||
user_id=user.id,
|
||||
ip_address="127.0.0.1",
|
||||
user_agent="TestAgent/1.0",
|
||||
)
|
||||
assert log.id is not None
|
||||
assert log.action == "login"
|
||||
assert log.resource_type == "auth"
|
||||
|
||||
def test_log_action_without_user(self, db: Session) -> None:
|
||||
repo = AuditLogRepository(db)
|
||||
log = repo.log_action(
|
||||
action="anonymous_access",
|
||||
resource_type="documents",
|
||||
)
|
||||
assert log.id is not None
|
||||
assert log.user_id is None
|
||||
|
||||
def test_get_user_logs(self, db: Session) -> None:
|
||||
user = create_test_user(db)
|
||||
repo = AuditLogRepository(db)
|
||||
repo.log_action(action="view", resource_type="documents", user_id=user.id)
|
||||
repo.log_action(action="edit", resource_type="templates", user_id=user.id)
|
||||
|
||||
logs = repo.get_user_logs(user.id)
|
||||
assert len(logs) >= 2
|
||||
|
||||
def test_get_resource_logs(self, db: Session) -> None:
|
||||
repo = AuditLogRepository(db)
|
||||
resource_id = str(uuid.uuid4())
|
||||
repo.log_action(action="create", resource_type="documents", resource_id=resource_id)
|
||||
repo.log_action(action="update", resource_type="documents", resource_id=resource_id)
|
||||
|
||||
logs = repo.get_resource_logs("documents", resource_id)
|
||||
assert len(logs) >= 2
|
||||
for log in logs:
|
||||
assert log.resource_type == "documents"
|
||||
assert log.resource_id == resource_id
|
||||
Reference in New Issue
Block a user