"""7.59.3 — « Turn into » du menu contextuel : garde cassée + texte conservé.""" import json import shutil import subprocess from pathlib import Path import pytest ROOT = Path(__file__).resolve().parent.parent EDITOR_JS = ROOT / "static" / "js" / "page_editor_scripts.js" SRC = EDITOR_JS.read_text(encoding="utf-8") def _slice(start: str, end: str) -> str: i = SRC.index(start) j = SRC.index(end, i) return SRC[i:j].rstrip() def test_turn_into_guard_matches_objects_not_strings(): # BUG : indexOf() sur un tableau d'objets → toujours -1 → retour immédiat. assert "_BLOCK_TURN_TYPES.indexOf(type)" not in SRC assert "_BLOCK_TURN_TYPES.some(t=>t.id===type)" in SRC def test_turn_into_menu_wiring(): # menu ⋮⋮ → « Turn into » → sous-menu → choix de type assert "_blockMenuItem('submenu','↩','Turn into',{sub:'turn'})" in SRC assert "'turn-type'" in SRC # construit par _blockMenuItem assert "act==='turn-type'" in SRC assert "_blockTurnMenuOpen(" in SRC def test_turn_into_keeps_text_for_to_do_and_toggle(): # Convertir un texte en To-do / Toggle ne doit plus effacer le contenu. line = [ln for ln in SRC.splitlines() if ln.strip().startswith("turnInto(idx,type")][0] assert "type!=='to_do'&&type!=='toggle'" not in line assert "if(keep&&['image','embed','meeting','divider'" in line # ── Comportement réel : la méthode extraite de la source, exécutée sous node ─ def test_turn_into_converts_blocks_for_real(): node = shutil.which("node") if not node: pytest.skip("node absent : test comportemental turnInto ignoré") types = _slice("const _BLOCK_TURN_TYPES=[", "];") method = _slice("turnInto(idx,type", "setBlockColor(idx,key,val){") script = f""" function _rtSync(){{}} function _selClear(){{}} {types}]; const E = {{ blocks: [{{id:'b1',type:'paragraph',content:'Bonjour'}}], _blockTargets(i){{return [i];}}, sync(){{}}, pushHistory(){{}}, dirty:false, autoSave(){{}}, render(){{}}, getEl(){{return null;}}, {method} }}; E.turnInto(0,'heading_2'); const heading = {{type:E.blocks[0].type, content:E.blocks[0].content}}; E.turnInto(0,'to_do'); const to_do = {{type:E.blocks[0].type, content:E.blocks[0].content, checked:E.blocks[0].checked}}; E.turnInto(0,'button'); // type sans texte → contenu vidé const button = {{type:E.blocks[0].type, content:E.blocks[0].content}}; console.log(JSON.stringify({{heading:heading, to_do:to_do, button:button}})); """ out = subprocess.run([node, "-e", script], capture_output=True, text=True, timeout=30, encoding="utf-8") assert out.returncode == 0, out.stderr res = json.loads(out.stdout) # 1) le changement de format a lieu (avant la correction : aucune conversion) assert res["heading"] == {"type": "heading_2", "content": "Bonjour"} # 2) To-do : texte conservé comme étiquette, case décochée assert res["to_do"] == {"type": "to_do", "content": "Bonjour", "checked": False} # 3) Button (type sans texte) → contenu vidé assert res["button"] == {"type": "button", "content": ""}