#include "gtest/gtest.h" #include "lumacs/macro_manager.hpp" #include "lumacs/editor_core.hpp" #include #include #include using namespace lumacs; // Fixture for MacroManager tests class MacroManagerTest : public ::testing::Test { protected: EditorCore core; // MacroManager's constructor requires an EditorCore& std::unique_ptr macro_manager; void SetUp() override { macro_manager = std::make_unique(core); } void TearDown() override { // Nothing specific needed } }; TEST_F(MacroManagerTest, InitialState) { ASSERT_FALSE(macro_manager->is_recording_macro()); ASSERT_TRUE(macro_manager->get_last_macro().empty()); } TEST_F(MacroManagerTest, StartAndEndRecording) { macro_manager->start_kbd_macro(); ASSERT_TRUE(macro_manager->is_recording_macro()); macro_manager->record_key_sequence("a"); macro_manager->record_key_sequence("b"); macro_manager->record_key_sequence("C-c"); macro_manager->end_kbd_macro_or_call(); ASSERT_FALSE(macro_manager->is_recording_macro()); ASSERT_FALSE(macro_manager->get_last_macro().empty()); ASSERT_EQ(macro_manager->get_last_macro().size(), 3); ASSERT_EQ(macro_manager->get_last_macro()[0], "a"); ASSERT_EQ(macro_manager->get_last_macro()[1], "b"); ASSERT_EQ(macro_manager->get_last_macro()[2], "C-c"); } TEST_F(MacroManagerTest, CallLastMacroWithoutRecording) { // Should not crash, and should not execute anything macro_manager->end_kbd_macro_or_call(); // Call when not recording and no last macro ASSERT_FALSE(macro_manager->is_recording_macro()); ASSERT_TRUE(macro_manager->get_last_macro().empty()); } TEST_F(MacroManagerTest, CallLastMacroExecutesKeys) { // This test is harder to verify directly in a unit test. // Executing the macro involves calling core.process_key, which // affects the editor's state (buffer, cursor). // For now, we can only verify the MacroManager's internal state. // A proper test would require mocking EditorCore::process_key or // making an integration test. macro_manager->start_kbd_macro(); macro_manager->record_key_sequence("h"); macro_manager->record_key_sequence("e"); macro_manager->record_key_sequence("l"); macro_manager->record_key_sequence("l"); macro_manager->record_key_sequence("o"); macro_manager->end_kbd_macro_or_call(); // This stores the macro // Calling the last macro will execute the recorded sequence. // We expect the macro to be executed. // However, without mocking core.process_key, we can only test MacroManager's state. // The previous test already verified the macro is recorded. // Let's ensure calling it doesn't crash. macro_manager->end_kbd_macro_or_call(); // This calls the last recorded macro ASSERT_FALSE(macro_manager->is_recording_macro()); // Still not recording ASSERT_FALSE(macro_manager->get_last_macro().empty()); // Macro should still be there } TEST_F(MacroManagerTest, ConsecutiveMacroRecording) { macro_manager->start_kbd_macro(); macro_manager->record_key_sequence("a"); macro_manager->end_kbd_macro_or_call(); ASSERT_EQ(macro_manager->get_last_macro().size(), 1); ASSERT_EQ(macro_manager->get_last_macro()[0], "a"); macro_manager->start_kbd_macro(); macro_manager->record_key_sequence("b"); macro_manager->record_key_sequence("c"); macro_manager->end_kbd_macro_or_call(); ASSERT_EQ(macro_manager->get_last_macro().size(), 2); ASSERT_EQ(macro_manager->get_last_macro()[0], "b"); ASSERT_EQ(macro_manager->get_last_macro()[1], "c"); } TEST_F(MacroManagerTest, MacroRecordingDuringMacroExecution) { // This tests Emacs' behavior: if you start recording during a macro call, // the executed keys are recorded into the new macro. // This requires mocking EditorCore's process_key. // For now, simple check: macro_manager->start_kbd_macro(); macro_manager->record_key_sequence("a"); macro_manager->end_kbd_macro_or_call(); // Macro: [a] // Simulate calling the macro, and during its call, start recording another // This can't be fully tested without a way to intercept process_key calls // and inject start_kbd_macro(). // We'll rely on integration tests for this. }