import pytest from fasthtml.components import Div from components.undo_redo.components.UndoRedo import UndoRedo from core.settings_management import SettingsManager, MemoryDbEngine from helpers import matches, div_icon, Contains, DoesNotContain from my_mocks import tabs_manager @pytest.fixture def undo_redo(session, tabs_manager): return UndoRedo(session, UndoRedo.create_component_id(session), settings_manager=SettingsManager(engine=MemoryDbEngine()), tabs_manager=tabs_manager) 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(undo_redo): undo_redo.push(UndoableCommand(0, 1)) undo_redo.push(UndoableCommand(1, 2)) actual = undo_redo.__ft__() expected = Div( Div(div_icon("undo", cls=DoesNotContain("mmt-btn-disabled")), data_tooltip="Undo 'Set new value'."), 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 new value'."), Div(div_icon("redo", cls=DoesNotContain("mmt-btn-disabled")), data_tooltip="Redo 'Set new value'."), 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_i_can_undo_and_redo(undo_redo): undo_redo.push(UndoableCommand(0, 1)) undo_redo.push(UndoableCommand(1, 2)) self, res = undo_redo.undo() expected = Div(1, hx_swap_oob="true") assert matches(res, expected) self, res = undo_redo.redo() expected = Div(2, hx_swap_oob="true") assert matches(res, expected) def test_history_is_rewritten_when_pushing_a_command(undo_redo): undo_redo.push(UndoableCommand(0, 1)) undo_redo.push(UndoableCommand(1, 2)) undo_redo.push(UndoableCommand(2, 3)) undo_redo.undo() undo_redo.undo() undo_redo.push(UndoableCommand(1, 5)) assert len(undo_redo.history) == 2