Fixed unit tests
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
|
||||
from fastcore.xml import FT
|
||||
from fasthtml.components import *
|
||||
|
||||
from components.BaseComponent import BaseComponentSingleton
|
||||
@@ -8,6 +9,7 @@ from components.undo_redo.assets.icons import icon_redo, icon_undo
|
||||
from components.undo_redo.commands import UndoRedoCommandManager
|
||||
from components.undo_redo.constants import UNDO_REDO_INSTANCE_ID, UndoRedoAttrs
|
||||
from components_helpers import mk_icon, mk_tooltip
|
||||
from core.settings_management import NoDefault
|
||||
|
||||
logger = logging.getLogger("UndoRedoApp")
|
||||
|
||||
@@ -64,13 +66,19 @@ class UndoRedo(BaseComponentSingleton):
|
||||
previous_state = self._settings_manager.load(self._session, None, digest=previous.digest)
|
||||
|
||||
# reapply the state
|
||||
current_state[current.key] = previous_state[current.key]
|
||||
if previous_state is not NoDefault:
|
||||
current_state[current.key] = previous_state[current.key]
|
||||
else:
|
||||
del current_state[current.key]
|
||||
self._settings_manager.save(self._session, current.entry, current_state)
|
||||
|
||||
self.index -= 1
|
||||
|
||||
if current.attrs.on_undo is not None:
|
||||
return self, current.attrs.on_undo()
|
||||
ret = current.attrs.on_undo()
|
||||
if isinstance(ret, FT) and 'id' in ret.attrs:
|
||||
ret.attrs["hx-swap-oob"] = "true"
|
||||
return self, ret
|
||||
else:
|
||||
return self
|
||||
|
||||
@@ -87,13 +95,19 @@ class UndoRedo(BaseComponentSingleton):
|
||||
next_state = self._settings_manager.load(self._session, None, digest=next_.digest)
|
||||
|
||||
# reapply the state
|
||||
current_state[current.key] = next_state[current.key]
|
||||
if current_state is not NoDefault:
|
||||
current_state[current.key] = next_state[current.key]
|
||||
else:
|
||||
current_state = {current.key : next_state[current.key]}
|
||||
self._settings_manager.save(self._session, current.entry, current_state)
|
||||
|
||||
self.index += 1
|
||||
|
||||
if current.attrs.on_undo is not None:
|
||||
return self, current.attrs.on_redo()
|
||||
if current.attrs.on_redo is not None:
|
||||
ret = current.attrs.on_undo()
|
||||
if isinstance(ret, FT) and 'id' in ret.attrs:
|
||||
ret.attrs["hx-swap-oob"] = "true"
|
||||
return self, ret
|
||||
else:
|
||||
return self
|
||||
|
||||
@@ -125,7 +139,7 @@ class UndoRedo(BaseComponentSingleton):
|
||||
|
||||
def _mk_redo(self):
|
||||
if self._can_redo():
|
||||
command = self.history[self.index]
|
||||
command = self.history[self.index + 1]
|
||||
return mk_tooltip(mk_icon(icon_redo,
|
||||
size=24,
|
||||
**self._commands.redo()),
|
||||
|
||||
@@ -1,20 +1,66 @@
|
||||
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):
|
||||
def undo_redo(session, tabs_manager, settings_manager):
|
||||
return UndoRedo(session,
|
||||
UndoRedo.create_component_id(session),
|
||||
settings_manager=SettingsManager(engine=MemoryDbEngine()),
|
||||
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(
|
||||
@@ -26,13 +72,13 @@ def test_i_can_render(undo_redo):
|
||||
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))
|
||||
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 new value'."),
|
||||
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(),
|
||||
)
|
||||
@@ -41,8 +87,8 @@ def test_i_can_render_when_undoing_and_redoing(undo_redo):
|
||||
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'."),
|
||||
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)
|
||||
@@ -75,26 +121,48 @@ def test_i_can_render_when_undoing_and_redoing(undo_redo):
|
||||
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))
|
||||
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, hx_swap_oob="true")
|
||||
expected = Div("1", id='an_id', hx_swap_oob="true")
|
||||
assert matches(res, expected)
|
||||
|
||||
self, res = undo_redo.redo()
|
||||
expected = Div(2, hx_swap_oob="true")
|
||||
expected = Div("2", id='an_id', 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))
|
||||
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()
|
||||
undo_redo.push(UndoableCommand(1, 5))
|
||||
init_command(session, settings_manager, undo_redo, "5")
|
||||
|
||||
assert len(undo_redo.history) == 2
|
||||
assert len(undo_redo.history) == 3 # do not forget that history always has a default command with digest = None
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
from fastcore.basics import NotStr
|
||||
from fasthtml.components import *
|
||||
from fasthtml.xtend import Script
|
||||
|
||||
from components.undo_redo.components.UndoRedo import UndoRedo
|
||||
from components.workflows.components.WorkflowDesigner import WorkflowDesigner, COMPONENT_TYPES
|
||||
from components.workflows.constants import ProcessorTypes
|
||||
from components.workflows.db_management import WorkflowsDesignerSettings, WorkflowComponent, Connection
|
||||
from core.instance_manager import InstanceManager
|
||||
from core.settings_management import SettingsManager, MemoryDbEngine
|
||||
from helpers import matches, Contains
|
||||
from my_mocks import tabs_manager
|
||||
@@ -13,6 +17,27 @@ from my_mocks import tabs_manager
|
||||
TEST_WORKFLOW_DESIGNER_ID = "workflow_designer_id"
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_undo_redo(session):
|
||||
# Create a mock UndoRedo instance
|
||||
undo_redo = MagicMock(spec=UndoRedo)
|
||||
|
||||
# Store original get method
|
||||
original_get = InstanceManager.get
|
||||
|
||||
def mock_get(sess, instance_id, *args, **kwargs):
|
||||
if instance_id == UndoRedo.create_component_id(sess):
|
||||
return undo_redo
|
||||
return original_get(sess, instance_id, *args, **kwargs)
|
||||
|
||||
# Replace get method with our mock
|
||||
InstanceManager.get = mock_get
|
||||
|
||||
yield undo_redo
|
||||
|
||||
# Restore original get method after test
|
||||
InstanceManager.get = original_get
|
||||
|
||||
@pytest.fixture
|
||||
def designer(session, tabs_manager):
|
||||
return WorkflowDesigner(session=session, _id=TEST_WORKFLOW_DESIGNER_ID,
|
||||
|
||||
@@ -4,10 +4,12 @@ import pandas as pd
|
||||
import pytest
|
||||
from pandas.testing import assert_frame_equal
|
||||
|
||||
from components.undo_redo.components.UndoRedo import UndoRedo
|
||||
from components.workflows.components.WorkflowDesigner import COMPONENT_TYPES, WorkflowDesigner
|
||||
from components.workflows.components.WorkflowPlayer import WorkflowPlayer, WorkflowsPlayerError
|
||||
from components.workflows.constants import ProcessorTypes
|
||||
from components.workflows.db_management import WorkflowComponent, Connection, ComponentState, WorkflowsDesignerSettings
|
||||
from core.instance_manager import InstanceManager
|
||||
from core.settings_management import SettingsManager, MemoryDbEngine
|
||||
from my_mocks import tabs_manager
|
||||
from workflow.engine import DataProcessorError
|
||||
@@ -16,6 +18,27 @@ TEST_WORKFLOW_DESIGNER_ID = "workflow_designer_id"
|
||||
TEST_WORKFLOW_PLAYER_ID = "workflow_player_id"
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_undo_redo(session):
|
||||
# Create a mock UndoRedo instance
|
||||
undo_redo = MagicMock(spec=UndoRedo)
|
||||
|
||||
# Store original get method
|
||||
original_get = InstanceManager.get
|
||||
|
||||
def mock_get(sess, instance_id, *args, **kwargs):
|
||||
if instance_id == UndoRedo.create_component_id(sess):
|
||||
return undo_redo
|
||||
return original_get(sess, instance_id, *args, **kwargs)
|
||||
|
||||
# Replace get method with our mock
|
||||
InstanceManager.get = mock_get
|
||||
|
||||
yield undo_redo
|
||||
|
||||
# Restore original get method after test
|
||||
InstanceManager.get = original_get
|
||||
|
||||
@pytest.fixture
|
||||
def settings_manager():
|
||||
return SettingsManager(MemoryDbEngine())
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
from fasthtml.components import *
|
||||
|
||||
from components.form.components.MyForm import FormField, MyForm
|
||||
from components.undo_redo.components.UndoRedo import UndoRedo
|
||||
from components.workflows.components.Workflows import Workflows
|
||||
from core.instance_manager import InstanceManager
|
||||
from core.settings_management import SettingsManager, MemoryDbEngine
|
||||
from helpers import matches, div_icon, search_elements_by_name, Contains
|
||||
from my_mocks import tabs_manager
|
||||
@@ -18,6 +22,28 @@ def workflows(session, tabs_manager):
|
||||
tabs_manager=tabs_manager)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_undo_redo(session):
|
||||
# Create a mock UndoRedo instance
|
||||
undo_redo = MagicMock(spec=UndoRedo)
|
||||
|
||||
# Store original get method
|
||||
original_get = InstanceManager.get
|
||||
|
||||
def mock_get(sess, instance_id, *args, **kwargs):
|
||||
if instance_id == UndoRedo.create_component_id(sess):
|
||||
return undo_redo
|
||||
return original_get(sess, instance_id, *args, **kwargs)
|
||||
|
||||
# Replace get method with our mock
|
||||
InstanceManager.get = mock_get
|
||||
|
||||
yield undo_redo
|
||||
|
||||
# Restore original get method after test
|
||||
InstanceManager.get = original_get
|
||||
|
||||
|
||||
def test_render_no_workflow(workflows):
|
||||
actual = workflows.__ft__()
|
||||
expected = Div(
|
||||
|
||||
Reference in New Issue
Block a user