diff --git a/CMakeLists.txt b/CMakeLists.txt index 419eca9..4f491da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,6 +298,8 @@ if (BUILD_TESTS) add_executable(kte_tests tests/TestRunner.cc tests/Test.h + tests/TestHarness.h + tests/test_daily_driver_harness.cc tests/test_buffer_io.cc tests/test_piece_table.cc tests/test_search.cc diff --git a/tests/TestHarness.h b/tests/TestHarness.h new file mode 100644 index 0000000..f73fdf3 --- /dev/null +++ b/tests/TestHarness.h @@ -0,0 +1,138 @@ +// TestHarness.h - small helper layer for driving kte headlessly in tests +#pragma once + +#include +#include +#include + +#include "Buffer.h" +#include "Command.h" +#include "Editor.h" + +namespace ktet { +inline void +InstallDefaultCommandsOnce() +{ + static bool installed = false; + if (!installed) { + InstallDefaultCommands(); + installed = true; + } +} + + +class TestHarness { +public: + TestHarness() + { + InstallDefaultCommandsOnce(); + editor_.SetDimensions(24, 80); + + Buffer b; + b.SetVirtualName("+TEST+"); + editor_.AddBuffer(std::move(b)); + } + + + Editor & + EditorRef() + { + return editor_; + } + + + Buffer & + Buf() + { + return *editor_.CurrentBuffer(); + } + + + [[nodiscard]] const Buffer & + Buf() const + { + return *editor_.CurrentBuffer(); + } + + + bool + Exec(CommandId id, const std::string &arg = std::string(), int ucount = 0) + { + if (ucount > 0) { + editor_.SetUniversalArg(1, ucount); + } else { + editor_.UArgClear(); + } + return Execute(editor_, id, arg); + } + + + bool + InsertText(std::string_view text) + { + if (text.find('\n') != std::string_view::npos || text.find('\r') != std::string_view::npos) + return false; + return Exec(CommandId::InsertText, std::string(text)); + } + + + void + TypeText(std::string_view text) + { + for (char ch: text) { + if (ch == '\n') { + Exec(CommandId::Newline); + } else if (ch == '\r') { + // ignore + } else { + Exec(CommandId::InsertText, std::string(1, ch)); + } + } + } + + + [[nodiscard]] std::string + Text() const + { + const auto &rows = Buf().Rows(); + std::string out; + for (std::size_t i = 0; i < rows.size(); ++i) { + out += static_cast(rows[i]); + if (i + 1 < rows.size()) + out.push_back('\n'); + } + return out; + } + + + [[nodiscard]] std::string + Line(std::size_t y) const + { + return Buf().GetLineString(y); + } + + + bool + SaveAs(const std::string &path, std::string &err) + { + return Buf().SaveAs(path, err); + } + + + bool + Undo(int ucount = 0) + { + return Exec(CommandId::Undo, std::string(), ucount); + } + + + bool + Redo(int ucount = 0) + { + return Exec(CommandId::Redo, std::string(), ucount); + } + +private: + Editor editor_; +}; +} // namespace ktet \ No newline at end of file diff --git a/tests/test_daily_driver_harness.cc b/tests/test_daily_driver_harness.cc new file mode 100644 index 0000000..38db85c --- /dev/null +++ b/tests/test_daily_driver_harness.cc @@ -0,0 +1,12 @@ +#include "Test.h" + +#include "tests/TestHarness.h" + + +TEST (DailyDriverHarness_Smoke_CanCreateBufferAndInsertText) +{ + ktet::TestHarness h; + + ASSERT_TRUE(h.InsertText("hello")); + ASSERT_EQ(h.Line(0), std::string("hello")); +} \ No newline at end of file