Files
iobj/tests/test_storage.py

155 lines
5.2 KiB
Python
Raw Normal View History

import tempfile
from datetime import date
import pytest
from iobj.models import ObjectCreate, ObjectType, ObjectUpdate, SearchQuery
from iobj.storage import ObjectStore
@pytest.fixture
def store():
with tempfile.TemporaryDirectory() as tmp:
s = ObjectStore(tmp)
yield s
s.close()
def _mk(**kwargs) -> ObjectCreate:
defaults = dict(
type=ObjectType.RECAP,
object_date=date(2026, 7, 1),
project="NordBytes",
tags=["frontend"],
title="Test title",
body="Some body text about BDD tests",
)
defaults.update(kwargs)
return ObjectCreate(**defaults)
def test_create_and_get_roundtrip(store):
obj = store.create(_mk())
fetched = store.get(obj.id)
assert fetched is not None
assert fetched.id == obj.id
assert fetched.title == "Test title"
assert fetched.project == "NordBytes"
def test_get_missing_returns_none(store):
assert store.get("does-not-exist") is None
def test_shard_file_created_per_month(store):
store.create(_mk(object_date=date(2026, 1, 15)))
store.create(_mk(object_date=date(2026, 3, 2)))
shard_files = sorted(p.name for p in store.data_dir.glob("*.json"))
assert shard_files == ["2026-01.json", "2026-03.json"]
def test_update_changes_fields(store):
obj = store.create(_mk())
updated = store.update(obj.id, ObjectUpdate(title="New title", tags=["backend"]))
assert updated.title == "New title"
assert updated.tags == ["backend"]
assert updated.body == obj.body # untouched field preserved
def test_update_moves_shard_when_date_changes(store):
obj = store.create(_mk(object_date=date(2026, 1, 1)))
store.update(obj.id, ObjectUpdate(object_date=date(2026, 6, 1)))
shard_files = sorted(p.name for p in store.data_dir.glob("*.json"))
assert "2026-06.json" in shard_files
moved = store.get(obj.id)
assert moved.object_date == date(2026, 6, 1)
def test_update_missing_returns_none(store):
assert store.update("nope", ObjectUpdate(title="x")) is None
def test_delete_removes_object(store):
obj = store.create(_mk())
assert store.delete(obj.id) is True
assert store.get(obj.id) is None
def test_delete_missing_returns_false(store):
assert store.delete("nope") is False
def test_search_filters_by_type(store):
store.create(_mk(type=ObjectType.RECAP))
store.create(_mk(type=ObjectType.GIT_COMMIT, title="commit one"))
results = store.search(SearchQuery(type=ObjectType.GIT_COMMIT))
assert len(results) == 1
assert results[0].title == "commit one"
def test_search_filters_by_project_case_insensitive(store):
store.create(_mk(project="NordBytes"))
store.create(_mk(project="Egmont"))
results = store.search(SearchQuery(project="nordbytes"))
assert len(results) == 1
assert results[0].project == "NordBytes"
def test_search_filters_by_tag(store):
store.create(_mk(tags=["frontend", "bdd"]))
store.create(_mk(tags=["backend"]))
results = store.search(SearchQuery(tag="bdd"))
assert len(results) == 1
def test_search_filters_by_date_range(store):
store.create(_mk(object_date=date(2026, 1, 5), title="jan"))
store.create(_mk(object_date=date(2026, 6, 5), title="jun"))
store.create(_mk(object_date=date(2026, 12, 5), title="dec"))
results = store.search(SearchQuery(date_from=date(2026, 2, 1), date_to=date(2026, 7, 1)))
assert len(results) == 1
assert results[0].title == "jun"
def test_search_free_text_matches_title_and_body(store):
store.create(_mk(title="BDD patterns", body="irrelevant"))
store.create(_mk(title="irrelevant", body="mentions BDD somewhere"))
store.create(_mk(title="nothing", body="nothing"))
results = store.search(SearchQuery(q="bdd"))
assert len(results) == 2
def test_search_free_text_matches_payload(store):
store.create(_mk(title="commit", payload={"sha": "abc123def", "author": "Henrik Jess"}))
store.create(_mk(title="other commit", payload={"sha": "zzz999", "author": "Someone Else"}))
results = store.search(SearchQuery(q="abc123def"))
assert len(results) == 1
assert results[0].title == "commit"
results = store.search(SearchQuery(q="henrik"))
assert len(results) == 1
assert results[0].title == "commit"
def test_search_respects_limit_and_offset_and_sort_order(store):
for i in range(5):
store.create(_mk(object_date=date(2026, 1, 1 + i), title=f"obj{i}"))
all_results = store.search(SearchQuery(limit=100))
assert [r.title for r in all_results] == ["obj4", "obj3", "obj2", "obj1", "obj0"]
page = store.search(SearchQuery(limit=2, offset=1))
assert [r.title for r in page] == ["obj3", "obj2"]
def test_search_combines_multiple_filters(store):
store.create(_mk(project="NordBytes", tags=["bdd"], title="match", object_date=date(2026, 5, 5)))
store.create(_mk(project="NordBytes", tags=["other"], title="no-tag-match", object_date=date(2026, 5, 5)))
store.create(_mk(project="Egmont", tags=["bdd"], title="wrong-project", object_date=date(2026, 5, 5)))
results = store.search(SearchQuery(project="NordBytes", tag="bdd"))
assert len(results) == 1
assert results[0].title == "match"
def test_search_no_shards_returns_empty(store):
assert store.search(SearchQuery()) == []