test: suite pytest (36 tests) et CI Gitea Actions
Modèles (chemin DB, migration 0.1.0, ordre, réconciliation), classification, client Gitea (pagination, en-tête, écritures), API (CSRF, write-back, codes d'erreur, 502 propre), auth Basic et fail-closed. Tous verts; pyflakes propre.
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
"""Model layer: env-driven DB path, migrations, ordering, reconciliation."""
|
||||
|
||||
import os
|
||||
import sqlite3
|
||||
|
||||
from app import models
|
||||
|
||||
|
||||
def test_db_path_honours_env_var():
|
||||
# Regression for audit point C1: the path the Dockerfile sets must win.
|
||||
assert models.db_path() == os.environ["KANBANTE_DB_PATH"]
|
||||
|
||||
|
||||
def test_board_state_ignores_unknown_column_rows():
|
||||
# Regression for audit point I4: a legacy row must not KeyError the board.
|
||||
with models.get_db() as conn:
|
||||
conn.execute(
|
||||
"INSERT INTO board_state (repo_full_name, issue_number, column_name) "
|
||||
"VALUES ('a/b', 99, 'ancienne_colonne')"
|
||||
)
|
||||
state = models.get_board_state("a/b")
|
||||
assert all(cards == [] for cards in state.values())
|
||||
|
||||
|
||||
def test_migration_from_v01_schema(tmp_path, monkeypatch):
|
||||
legacy = tmp_path / "legacy.db"
|
||||
conn = sqlite3.connect(legacy)
|
||||
conn.executescript(
|
||||
"""
|
||||
CREATE TABLE board_state (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
repo_full_name TEXT NOT NULL,
|
||||
issue_number INTEGER NOT NULL,
|
||||
column_name TEXT NOT NULL DEFAULT 'backlog',
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
UNIQUE(repo_full_name, issue_number)
|
||||
);
|
||||
CREATE TABLE project_notes (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
repo_full_name TEXT NOT NULL,
|
||||
note TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
UNIQUE(repo_full_name)
|
||||
);
|
||||
INSERT INTO board_state (repo_full_name, issue_number, column_name)
|
||||
VALUES ('a/b', 1, 'todo'), ('a/b', 2, 'colonne_disparue');
|
||||
INSERT INTO project_notes (repo_full_name, note) VALUES ('a/b', 'salut');
|
||||
"""
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
monkeypatch.setenv("KANBANTE_DB_PATH", str(legacy))
|
||||
models.init_db()
|
||||
|
||||
with models.get_db() as conn:
|
||||
board_cols = [r[1] for r in conn.execute("PRAGMA table_info(board_state)")]
|
||||
notes_cols = [r[1] for r in conn.execute("PRAGMA table_info(project_notes)")]
|
||||
remaining = conn.execute("SELECT COUNT(*) FROM board_state").fetchone()[0]
|
||||
assert "position" in board_cols
|
||||
assert "updated_at" in notes_cols
|
||||
assert remaining == 1 # valid row kept, unknown-column row dropped
|
||||
assert models.get_notes("a/b") == "salut"
|
||||
|
||||
|
||||
def test_move_and_column_order_persisted():
|
||||
models.move_issue("a/b", 1, "todo")
|
||||
models.move_issue("a/b", 2, "todo")
|
||||
models.set_column_order("a/b", "todo", [2, 1])
|
||||
state = models.get_board_state("a/b")
|
||||
assert [c["issue_number"] for c in state["todo"]] == [2, 1]
|
||||
|
||||
|
||||
def test_reconcile_closed_to_done_and_purge_deleted():
|
||||
models.move_issue("a/b", 1, "in_progress")
|
||||
models.move_issue("a/b", 2, "todo")
|
||||
models.move_issue("a/b", 3, "review")
|
||||
changed = models.reconcile_board_state("a/b", open_numbers={1}, closed_numbers={2})
|
||||
assert changed == {"closed_to_done": 1, "purged": 1}
|
||||
state = models.get_board_state("a/b")
|
||||
assert [c["issue_number"] for c in state["in_progress"]] == [1]
|
||||
assert [c["issue_number"] for c in state["done"]] == [2]
|
||||
assert all(
|
||||
c["issue_number"] != 3 for cards in state.values() for c in cards
|
||||
)
|
||||
|
||||
|
||||
def test_notes_roundtrip():
|
||||
assert models.get_notes("a/b") is None
|
||||
models.set_notes("a/b", "première version")
|
||||
models.set_notes("a/b", "deuxième version")
|
||||
assert models.get_notes("a/b") == "deuxième version"
|
||||
|
||||
|
||||
def test_move_issue_rejects_invalid_column():
|
||||
import pytest
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
models.move_issue("a/b", 1, "pas_une_colonne")
|
||||
Reference in New Issue
Block a user