169 lines
5.4 KiB
Python
169 lines
5.4 KiB
Python
import os
|
|
import shutil
|
|
|
|
import pytest
|
|
from fasthtml.components import Div
|
|
|
|
from components.undo_redo.components.UndoRedo import UndoRedo
|
|
from components.undo_redo.constants import UndoRedoAttrs
|
|
from core.dbengine import DbEngine
|
|
from core.settings_management import SettingsManager, MemoryDbEngine
|
|
from helpers import matches, div_icon, Contains, DoesNotContain
|
|
from my_mocks import tabs_manager
|
|
|
|
DB_ENGINE_ROOT = "undo_redo_test_db"
|
|
TEST_DB_ENTRY = "TestDbEntry"
|
|
TEST_DB_KEY = "TestDbKey"
|
|
|
|
|
|
class TestCommand:
|
|
def __init__(self, value):
|
|
self.value = value
|
|
|
|
def __eq__(self, other):
|
|
if not isinstance(other, TestCommand):
|
|
return False
|
|
|
|
return self.value == other.value
|
|
|
|
def __hash__(self):
|
|
return hash(self.value)
|
|
|
|
|
|
@pytest.fixture()
|
|
def engine(session):
|
|
if os.path.exists(DB_ENGINE_ROOT):
|
|
shutil.rmtree(DB_ENGINE_ROOT)
|
|
|
|
engine = DbEngine(DB_ENGINE_ROOT)
|
|
engine.init(session["user_id"])
|
|
|
|
yield engine
|
|
|
|
shutil.rmtree(DB_ENGINE_ROOT)
|
|
|
|
|
|
@pytest.fixture()
|
|
def settings_manager(engine):
|
|
return SettingsManager(engine=engine)
|
|
|
|
|
|
@pytest.fixture
|
|
def undo_redo(session, tabs_manager, settings_manager):
|
|
return UndoRedo(session,
|
|
UndoRedo.create_component_id(session),
|
|
settings_manager=settings_manager,
|
|
tabs_manager=tabs_manager)
|
|
|
|
|
|
def init_command(session, settings_manager, undo_redo, value, on_undo=None):
|
|
settings_manager.save(session, TEST_DB_ENTRY, {TEST_DB_KEY: TestCommand(value)})
|
|
undo_redo.snapshot(UndoRedoAttrs(f"Set value to {value}", on_undo=on_undo), TEST_DB_ENTRY, TEST_DB_KEY)
|
|
|
|
|
|
def test_i_can_render(undo_redo):
|
|
actual = undo_redo.__ft__()
|
|
expected = Div(
|
|
Div(div_icon("undo", cls=Contains("mmt-btn-disabled")), data_tooltip="Nothing to undo."),
|
|
Div(div_icon("redo", cls=Contains("mmt-btn-disabled")), data_tooltip="Nothing to redo."),
|
|
id=undo_redo.get_id(),
|
|
)
|
|
|
|
assert matches(actual, expected)
|
|
|
|
|
|
def test_i_can_render_when_undoing_and_redoing(session, settings_manager, undo_redo):
|
|
init_command(session, settings_manager, undo_redo, "1")
|
|
init_command(session, settings_manager, undo_redo, "2")
|
|
|
|
actual = undo_redo.__ft__()
|
|
expected = Div(
|
|
Div(div_icon("undo", cls=DoesNotContain("mmt-btn-disabled")), data_tooltip="Undo 'Set value to 2'."),
|
|
Div(div_icon("redo", cls=Contains("mmt-btn-disabled")), data_tooltip="Nothing to redo."),
|
|
id=undo_redo.get_id(),
|
|
)
|
|
assert matches(actual, expected)
|
|
|
|
undo_redo.undo() # The command is now undone. We can redo it and undo the first command.
|
|
actual = undo_redo.__ft__()
|
|
expected = Div(
|
|
Div(div_icon("undo", cls=DoesNotContain("mmt-btn-disabled")), data_tooltip="Undo 'Set value to 1'."),
|
|
Div(div_icon("redo", cls=DoesNotContain("mmt-btn-disabled")), data_tooltip="Redo 'Set value to 2'."),
|
|
id=undo_redo.get_id(),
|
|
)
|
|
assert matches(actual, expected)
|
|
|
|
undo_redo.undo() # Undo again, I cannot undo anymore.
|
|
actual = undo_redo.__ft__()
|
|
expected = Div(
|
|
Div(div_icon("undo", cls=Contains("mmt-btn-disabled"))),
|
|
Div(div_icon("redo", cls=DoesNotContain("mmt-btn-disabled"))),
|
|
id=undo_redo.get_id(),
|
|
)
|
|
assert matches(actual, expected)
|
|
|
|
undo_redo.redo() # Redo once.
|
|
actual = undo_redo.__ft__()
|
|
expected = Div(
|
|
Div(div_icon("undo", cls=DoesNotContain("mmt-btn-disabled"))),
|
|
Div(div_icon("redo", cls=DoesNotContain("mmt-btn-disabled"))),
|
|
id=undo_redo.get_id(),
|
|
)
|
|
assert matches(actual, expected)
|
|
|
|
undo_redo.redo() # Redo a second time.
|
|
actual = undo_redo.__ft__()
|
|
expected = Div(
|
|
Div(div_icon("undo", cls=DoesNotContain("mmt-btn-disabled"))),
|
|
Div(div_icon("redo", cls=Contains("mmt-btn-disabled"))),
|
|
id=undo_redo.get_id(),
|
|
)
|
|
assert matches(actual, expected)
|
|
|
|
|
|
def test_values_are_correctly_reset(session, settings_manager, undo_redo):
|
|
# checks that the values are correctly returned
|
|
# Only checks that hx_swap_oob="true" is automatically put when id is present in the return
|
|
|
|
def on_undo():
|
|
current = settings_manager.get(session, TEST_DB_ENTRY, TEST_DB_KEY)
|
|
return Div(current.value, id='an_id')
|
|
|
|
init_command(session, settings_manager, undo_redo, "1", on_undo=on_undo)
|
|
init_command(session, settings_manager, undo_redo, "2", on_undo=on_undo)
|
|
|
|
self, res = undo_redo.undo()
|
|
expected = Div("1", id='an_id', hx_swap_oob="true")
|
|
assert matches(res, expected)
|
|
|
|
self, res = undo_redo.redo()
|
|
expected = Div("2", id='an_id', hx_swap_oob="true")
|
|
assert matches(res, expected)
|
|
|
|
|
|
def test_i_can_manage_when_the_entry_was_not_present(session, settings_manager, undo_redo):
|
|
def on_undo():
|
|
snapshot = settings_manager.load(session, TEST_DB_ENTRY)
|
|
if TEST_DB_KEY in snapshot:
|
|
return Div(snapshot[TEST_DB_KEY].value, id='an_id')
|
|
else:
|
|
return Div("**Not Found**", id='an_id')
|
|
|
|
init_command(session, settings_manager, undo_redo, "1", on_undo=on_undo)
|
|
|
|
self, res = undo_redo.undo()
|
|
expected = Div("**Not Found**", id='an_id', hx_swap_oob="true")
|
|
assert matches(res, expected)
|
|
|
|
|
|
def test_history_is_rewritten_when_pushing_a_command_after_undo(session, settings_manager, undo_redo):
|
|
init_command(session, settings_manager, undo_redo, "1")
|
|
init_command(session, settings_manager, undo_redo, "2")
|
|
init_command(session, settings_manager, undo_redo, "3")
|
|
|
|
undo_redo.undo()
|
|
undo_redo.undo()
|
|
init_command(session, settings_manager, undo_redo, "5")
|
|
|
|
assert len(undo_redo.history) == 3 # do not forget that history always has a default command with digest = None
|