edited230126

This commit is contained in:
2026-01-23 18:07:29 +01:00
parent 32312fe4f2
commit 138136e835
18 changed files with 1354 additions and 283 deletions

View File

@@ -0,0 +1,93 @@
import os
import tempfile
# Ensure repo root is on sys.path when running as a script.
import sys
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
if ROOT not in sys.path:
sys.path.insert(0, ROOT)
from app import create_app
from app.extensions import db
from app.models import Company, Playlist, PlaylistItem, User
def main():
# Use a temporary SQLite DB so this doesn't touch your real instance DB.
fd, path = tempfile.mkstemp(prefix="rssfeed-test-", suffix=".sqlite")
os.close(fd)
try:
os.environ["DATABASE_URL"] = f"sqlite:///{path}"
os.environ["SECRET_KEY"] = "test-secret"
app = create_app()
with app.app_context():
db.create_all()
c = Company(name="TestCo")
db.session.add(c)
db.session.commit()
u = User(username="test@example.com", email="test@example.com", is_admin=False, company_id=c.id)
u.set_password("passw0rd123")
db.session.add(u)
db.session.commit()
p = Playlist(company_id=c.id, name="Playlist")
db.session.add(p)
db.session.commit()
i1 = PlaylistItem(playlist_id=p.id, item_type="webpage", url="https://example.com/1", position=1)
i2 = PlaylistItem(playlist_id=p.id, item_type="webpage", url="https://example.com/2", position=2)
i3 = PlaylistItem(playlist_id=p.id, item_type="webpage", url="https://example.com/3", position=3)
db.session.add_all([i1, i2, i3])
db.session.commit()
client = app.test_client()
# Login
res = client.post(
"/auth/login",
data={"email": "test@example.com", "password": "passw0rd123"},
follow_redirects=False,
)
if res.status_code not in (302, 303):
raise SystemExit(f"Login failed: {res.status_code}")
# Reorder: 3,2,1
reorder_url = f"/company/playlists/{p.id}/items/reorder"
res = client.post(
reorder_url,
data={"order": f"{i3.id},{i2.id},{i1.id}"},
headers={"Accept": "application/json", "X-Requested-With": "XMLHttpRequest"},
)
if res.status_code != 200:
raise SystemExit(f"Reorder failed: {res.status_code} {res.data!r}")
data = res.get_json(silent=True) or {}
if not data.get("ok"):
raise SystemExit(f"Unexpected reorder response: {data}")
db.session.expire_all()
ordered = (
PlaylistItem.query.filter_by(playlist_id=p.id)
.order_by(PlaylistItem.position.asc())
.all()
)
got = [x.id for x in ordered]
expected = [i3.id, i2.id, i1.id]
if got != expected:
raise SystemExit(f"Order not persisted. expected={expected} got={got}")
print("OK: reorder endpoint persists positions")
finally:
try:
os.remove(path)
except OSError:
pass
if __name__ == "__main__":
main()

View File

@@ -20,6 +20,10 @@ def main():
required = {
"/admin/companies/<int:company_id>/delete",
"/admin/displays/<int:display_id>/name",
"/company/displays/<int:display_id>",
"/company/items/<int:item_id>/duration",
"/company/playlists/<int:playlist_id>/items/reorder",
"/auth/change-password",
"/auth/forgot-password",
"/auth/reset-password/<token>",

View File

@@ -0,0 +1,91 @@
import io
import os
import sys
import tempfile
# Ensure repo root is on sys.path when running as a script.
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
if ROOT not in sys.path:
sys.path.insert(0, ROOT)
from app import create_app
from app.extensions import db
from app.models import Company, Playlist, User
def main():
# Use a temporary SQLite DB so this doesn't touch your real instance DB.
fd, path = tempfile.mkstemp(prefix="rssfeed-test-", suffix=".sqlite")
os.close(fd)
try:
os.environ["DATABASE_URL"] = f"sqlite:///{path}"
os.environ["SECRET_KEY"] = "test-secret"
app = create_app()
app.config["TESTING"] = True
with app.app_context():
db.create_all()
c = Company(name="TestCo")
db.session.add(c)
db.session.commit()
u = User(username="test@example.com", email="test@example.com", is_admin=False, company_id=c.id)
u.set_password("passw0rd123")
db.session.add(u)
db.session.commit()
p = Playlist(company_id=c.id, name="Playlist")
db.session.add(p)
db.session.commit()
client = app.test_client()
# Login
res = client.post(
"/auth/login",
data={"email": "test@example.com", "password": "passw0rd123"},
follow_redirects=False,
)
if res.status_code not in (302, 303):
raise SystemExit(f"Login failed: {res.status_code}")
# We don't want to allocate a 250MB+ buffer in a test.
# Instead, temporarily monkeypatch the route's MAX_VIDEO_BYTES down to 1 byte,
# then upload a 2-byte payload.
import app.routes.company as company_routes
old_limit = company_routes.MAX_VIDEO_BYTES
company_routes.MAX_VIDEO_BYTES = 1
try:
data = {
"item_type": "video",
"title": "Big",
"duration_seconds": "10",
"response": "json",
"file": (io.BytesIO(b"xx"), "big.mp4"),
}
url = f"/company/playlists/{p.id}/items"
res = client.post(url, data=data, content_type="multipart/form-data")
finally:
company_routes.MAX_VIDEO_BYTES = old_limit
if res.status_code != 413:
raise SystemExit(f"Expected 413 for too-large video, got: {res.status_code} {res.data!r}")
js = res.get_json(silent=True) or {}
if js.get("ok") is not False:
raise SystemExit(f"Unexpected response: {js}")
if "250" not in (js.get("error") or ""):
raise SystemExit(f"Unexpected error message: {js}")
print("OK: video uploads >250MB are rejected with 413")
finally:
try:
os.remove(path)
except OSError:
pass
if __name__ == "__main__":
main()