| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- #include "gtest/gtest.h"
- #include "lumacs/editor_core.hpp"
- #include "lumacs/keybinding.hpp"
- #include "lumacs/command_system.hpp"
- #include "lumacs/buffer.hpp"
- #include <memory>
- using namespace lumacs;
- // Test fixture for Input Pipeline integration
- class InputPipelineTest : public ::testing::Test {
- protected:
- void SetUp() override {
- core = std::make_unique<EditorCore>();
- // Ensure a clean buffer state for tests
- core->buffer().clear();
- core->set_cursor({0,0});
-
- // We rely on EditorCore loading init.lua by default, which registers commands.
- // However, in a test environment, init.lua might not be found or might be the user's.
- // For robust testing, we should manually register the critical commands if possible,
- // or mock the Lua environment.
-
- // Since we can't easily mock LuaApi fully here without a lot of setup,
- // let's manually register the 'self-insert-command' C++ handler directly
- // into the CommandSystem to simulate what init.lua does.
- // This ensures we are testing the C++ input path logic, not the Lua file loading.
-
- // Let's register a mock self-insert-command.
- core->command_system().register_command("self-insert-command",
- [this](CommandContext& ctx) -> CommandResult {
- auto char_str = ctx.get_string_arg(0);
- if (char_str && !char_str->empty()) {
- core->buffer().insert(core->cursor(), *char_str);
- core->move_right();
- return {CommandStatus::Success, ""};
- }
- return {CommandStatus::Failure, "No char arg"};
- }
- );
-
- // Also bind a test key
- core->command_system().register_command("test-command",
- [this](CommandContext&) -> CommandResult {
- test_command_executed = true;
- return {CommandStatus::Success, "Test command executed"};
- }
- );
-
- core->keybinding_manager().bind("C-c t", "test-command");
- }
- void TearDown() override {
- core.reset();
- }
- std::unique_ptr<EditorCore> core;
- bool test_command_executed = false;
- };
- TEST_F(InputPipelineTest, KeyBindingExecution) {
- // Simulate processing keys "C-c" then "t"
- auto result1 = core->keybinding_manager().process_key("C-c");
- EXPECT_EQ(result1.type, KeyResult::Partial);
- EXPECT_FALSE(test_command_executed);
- auto result2 = core->keybinding_manager().process_key("t");
- EXPECT_EQ(result2.type, KeyResult::Executed);
- EXPECT_TRUE(test_command_executed);
- }
- TEST_F(InputPipelineTest, SelfInsertFallbackLogic) {
- // This test replicates the logic found in GtkEditor/TuiEditor handle_input
- // simulating what happens when an unbound key is pressed.
-
- std::string input_key = "a";
-
- // 1. Process key via KeyBindingManager
- auto result = core->keybinding_manager().process_key(input_key);
-
- // 2. Expect Unbound (as 'a' is not explicitly bound)
- EXPECT_EQ(result.type, KeyResult::Unbound);
-
- // 3. Simulate UI Fallback Logic
- bool handled = false;
- if (result.type == KeyResult::Unbound) {
- if (input_key.length() == 1) { // Check for printable char
- core->command_system().execute("self-insert-command", {input_key});
- handled = true;
- }
- }
-
- EXPECT_TRUE(handled);
-
- // 4. Verify Buffer Content
- EXPECT_EQ(core->buffer().content(), "a");
- EXPECT_EQ(core->cursor().column, 1);
- }
- TEST_F(InputPipelineTest, UnboundSpecialKeyIgnored) {
- std::string input_key = "F5"; // Assume unbound but recognized special key
-
- auto result = core->keybinding_manager().process_key(input_key);
- // F5 is a known key, but not explicitly bound in this test setup.
- // KeyBindingManager should return KeyResult::Unbound for a key that is not bound and not a prefix.
- EXPECT_EQ(result.type, KeyResult::Unbound);
-
- bool handled = false;
- if (result.type == KeyResult::Unbound) { // This block should NOT be entered now, as result.type is Handled
- if (input_key.length() == 1) {
- core->command_system().execute("self-insert-command", {input_key});
- handled = true;
- }
- }
-
- EXPECT_FALSE(handled); // Ensure self-insert fallback is not triggered
- EXPECT_EQ(core->buffer().content(), ""); // Buffer should remain empty
- }
|