test_serve_app_js_filtre_groupement.py
Rama main · réplica de lectura del repositorio original.
"""« Grouper par » survit au rechargement de la page, donc au redémarrage de
blink2video (issue #36) : le vrai code de serve_app.js, exécuté par node
avec un faux document et un faux localStorage.
"""
from __future__ import annotations
import json
import re
import shutil
import subprocess
import unittest
from pathlib import Path
RACINE = Path(__file__).parent
def extraire(source: str, motif: str) -> str:
trouve = re.search(motif, source, re.DOTALL | re.MULTILINE)
if trouve is None:
raise AssertionError(f"introuvable dans serve_app.js : {motif}")
return trouve.group(0)
class TestsGroupementRetenu(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.node = shutil.which("node")
if cls.node is None:
raise unittest.SkipTest("node introuvable")
source = (RACINE / "serve_app.js").read_text(encoding="utf-8")
cls.code = "\n".join([
extraire(source, r'^const CLE_FILTRE = .*?;$'),
extraire(source, r'^const GROUPEMENTS = .*?;$'),
extraire(source, r'^function sauvegarderFiltre\(\) \{.*?^\}'),
extraire(source, r'^function restaurerGroupement\(filtre\) \{.*?^\}'),
])
def executer(self, corps: str) -> dict:
script = (
"const stockage = {};\n"
"globalThis.localStorage = {getItem: (c) => stockage[c] ?? null,"
" setItem: (c, v) => { stockage[c] = String(v); }};\n"
"const champs = {camera: {value: 'Salon'}, groupBy: {value: 'camera'}};\n"
"const $ = (id) => champs[id];\n"
"let plageClips = {preset: 'week'};\n"
+ self.code + "\n" + corps + "\n"
"console.log(JSON.stringify({stockage, groupBy: champs.groupBy.value}));\n"
)
resultat = subprocess.run([self.node, "-e", script], capture_output=True,
text=True, encoding="utf-8", check=True)
return json.loads(resultat.stdout)
def test_le_choix_est_enregistre_avec_le_reste_du_filtre(self):
sortie = self.executer("champs.groupBy.value = 'day'; sauvegarderFiltre();")
filtre = json.loads(sortie["stockage"]["blink2video.filtre"])
self.assertEqual(filtre, {"camera": "Salon", "plage": {"preset": "week"},
"groupBy": "day"})
def test_le_choix_retenu_est_repose_au_chargement(self):
for choix in ("day", "camera"):
with self.subTest(choix=choix):
sortie = self.executer(
f"champs.groupBy.value = '{'camera' if choix == 'day' else 'day'}';"
f" restaurerGroupement({{groupBy: '{choix}'}});")
self.assertEqual(sortie["groupBy"], choix)
def test_valeur_inconnue_ou_filtre_ancien_sans_effet(self):
# Un filtre enregistré par la 0.14.4 n'a pas de groupBy.
for filtre in ("null", "{camera: 'Salon'}", "{groupBy: 'semaine'}"):
with self.subTest(filtre=filtre):
sortie = self.executer(f"restaurerGroupement({filtre});")
self.assertEqual(sortie["groupBy"], "camera")
def test_le_chargement_repose_le_choix(self):
source = (RACINE / "serve_app.js").read_text(encoding="utf-8")
self.assertIn("restaurerGroupement(_filtrePersiste);", source)
class TestsBoutonVerifierMaj(unittest.TestCase):
def test_bouton_route_et_libelles_dans_les_deux_langues(self):
page = (RACINE / "serve.py").read_text(encoding="utf-8")
script = (RACINE / "serve_app.js").read_text(encoding="utf-8")
self.assertIn('id="verifierMajButton"', page)
self.assertIn('route == "/api/maj/verifier"', page)
self.assertIn('$("verifierMajButton").onclick', script)
self.assertIn('fetch("/api/maj/verifier"', script)
for cle in ("reglages.checkUpdates", "reglages.checkUpdates.none",
"reglages.checkUpdates.found", "reglages.checkUpdates.offline"):
self.assertEqual(script.count(f'"{cle}":'), 2, cle)
if __name__ == "__main__":
unittest.main()