e18d56c838
Seed five curated, read-only post-processing templates so a non-expert gets instant good-looking output before discovering the filter pipeline. Each is an opinionated chain of existing filters (auto-crop/saturation/contrast/colour- temperature/temporal-blur) tuned for a use case (films, games, evening ambience, low-flicker, crisp cool-white). Mirrors the built-in-gradient pattern: adds is_builtin to PostprocessingTemplate, seeds missing looks on store init (idempotent, additive — no migration), and makes built-ins read-only (update/delete raise -> 400; clone to customise). Surfaced via the existing template picker + is_builtin in the response/type. 7 unit tests (seeding, idempotency, read-only protection, round-trip); full suite green (1926 passed). (A runtime intensity slider is a follow-up — it needs a filter-chain parameterisation layer.)
82 lines
2.7 KiB
Python
82 lines
2.7 KiB
Python
"""Tests for built-in curated 'look' postprocessing templates."""
|
|
|
|
import pytest
|
|
|
|
from ledgrab.core.filters.registry import FilterRegistry
|
|
from ledgrab.storage.postprocessing_template import PostprocessingTemplate
|
|
from ledgrab.storage.postprocessing_template_store import (
|
|
_BUILTIN_LOOKS,
|
|
PostprocessingTemplateStore,
|
|
)
|
|
|
|
|
|
def test_builtins_are_seeded(tmp_db):
|
|
store = PostprocessingTemplateStore(tmp_db)
|
|
for key in _BUILTIN_LOOKS:
|
|
tpl = store.get_template(f"pp_builtin_{key}")
|
|
assert tpl.is_builtin is True
|
|
assert tpl.filters # non-empty chain
|
|
|
|
|
|
def test_builtin_filters_use_registered_ids(tmp_db):
|
|
store = PostprocessingTemplateStore(tmp_db)
|
|
for key in _BUILTIN_LOOKS:
|
|
tpl = store.get_template(f"pp_builtin_{key}")
|
|
for fi in tpl.filters:
|
|
assert FilterRegistry.is_registered(fi.filter_id), fi.filter_id
|
|
|
|
|
|
def test_seeding_is_idempotent(tmp_db):
|
|
PostprocessingTemplateStore(tmp_db)
|
|
store2 = PostprocessingTemplateStore(tmp_db)
|
|
ids = [t.id for t in store2.get_all_templates() if t.id.startswith("pp_builtin_")]
|
|
assert sorted(ids) == sorted(f"pp_builtin_{k}" for k in _BUILTIN_LOOKS)
|
|
|
|
|
|
def test_builtin_update_is_blocked(tmp_db):
|
|
store = PostprocessingTemplateStore(tmp_db)
|
|
with pytest.raises(ValueError, match="read-only"):
|
|
store.update_template("pp_builtin_vivid", name="Hacked")
|
|
|
|
|
|
def test_builtin_delete_is_blocked(tmp_db):
|
|
store = PostprocessingTemplateStore(tmp_db)
|
|
with pytest.raises(ValueError, match="cannot be deleted"):
|
|
store.delete_template("pp_builtin_vivid")
|
|
|
|
|
|
def test_user_template_still_editable_and_deletable(tmp_db):
|
|
store = PostprocessingTemplateStore(tmp_db)
|
|
tpl = store.create_template("My Look", filters=[])
|
|
assert tpl.is_builtin is False
|
|
store.update_template(tpl.id, description="changed")
|
|
store.delete_template(tpl.id)
|
|
with pytest.raises(ValueError):
|
|
store.get_template(tpl.id)
|
|
|
|
|
|
def test_is_builtin_round_trips_through_dict():
|
|
tpl = PostprocessingTemplate.from_dict(
|
|
{
|
|
"id": "pp_x",
|
|
"name": "x",
|
|
"filters": [],
|
|
"created_at": "2026-01-01T00:00:00+00:00",
|
|
"updated_at": "2026-01-01T00:00:00+00:00",
|
|
"is_builtin": True,
|
|
}
|
|
)
|
|
assert tpl.is_builtin is True
|
|
assert tpl.to_dict()["is_builtin"] is True
|
|
# legacy dict without the field defaults to False
|
|
legacy = PostprocessingTemplate.from_dict(
|
|
{
|
|
"id": "pp_y",
|
|
"name": "y",
|
|
"filters": [],
|
|
"created_at": "2026-01-01T00:00:00+00:00",
|
|
"updated_at": "2026-01-01T00:00:00+00:00",
|
|
}
|
|
)
|
|
assert legacy.is_builtin is False
|