diff --git a/cmake/ftxui_test.cmake b/cmake/ftxui_test.cmake index d9d112c8..b2fb59a1 100644 --- a/cmake/ftxui_test.cmake +++ b/cmake/ftxui_test.cmake @@ -24,14 +24,16 @@ endif() add_executable(tests src/ftxui/component/animation_test.cpp + src/ftxui/component/button_test.cpp + src/ftxui/component/collapsible_test.cpp src/ftxui/component/component_test.cpp src/ftxui/component/component_test.cpp src/ftxui/component/container_test.cpp src/ftxui/component/input_test.cpp src/ftxui/component/menu_test.cpp src/ftxui/component/radiobox_test.cpp - src/ftxui/component/resizable_split_test.cpp src/ftxui/component/receiver_test.cpp + src/ftxui/component/resizable_split_test.cpp src/ftxui/component/screen_interactive_test.cpp src/ftxui/component/terminal_input_parser_test.cpp src/ftxui/component/toggle_test.cpp diff --git a/src/ftxui/component/button_test.cpp b/src/ftxui/component/button_test.cpp new file mode 100644 index 00000000..f727c5b9 --- /dev/null +++ b/src/ftxui/component/button_test.cpp @@ -0,0 +1,177 @@ +#include // for Message +#include // for TestPartResult, SuiteApiResolver, TestFactoryImpl +#include // for allocator, __shared_ptr_access, shared_ptr +#include // for string, basic_string +#include // for vector + +#include "ftxui/component/captured_mouse.hpp" // for ftxui +#include "ftxui/component/component.hpp" // for container +#include "ftxui/component/component_base.hpp" // for ComponentBase +#include "ftxui/component/component_options.hpp" // for MenuOption +#include "ftxui/component/event.hpp" // for Event, Event::ArrowDown, Event::Return +#include "ftxui/util/ref.hpp" // for Ref +#include "gtest/gtest_pred_impl.h" // for Test, EXPECT_EQ, TEST + +namespace ftxui { + +namespace { + +Event MousePressed(int x, int y) { + Mouse mouse; + mouse.button = Mouse::Left; + mouse.motion = Mouse::Pressed; + mouse.shift = false; + mouse.meta = false; + mouse.control = false; + mouse.x = x; + mouse.y = y; + return Event::Mouse("jjj", mouse); +} + +} // namespace + +using namespace std::chrono_literals; + +TEST(ButtonTest, Basic) { + int press_count = 0; + std::string last_press = ""; + auto btn1 = Button("btn1", [&] { + press_count++; + last_press = "btn1"; + }); + auto btn2 = Button("btn2", [&] { + press_count++; + last_press = "btn2"; + }); + + int selected = 0; + auto container = Container::Horizontal({ + btn1, + btn2, + }, &selected); + + (void)container->Render(); + + EXPECT_EQ(selected, 0); + EXPECT_TRUE(btn1->Focused()); + EXPECT_FALSE(btn2->Focused()); + + container->OnEvent(Event::ArrowLeft); + EXPECT_EQ(selected, 0); + EXPECT_TRUE(btn1->Focused()); + EXPECT_FALSE(btn2->Focused()); + + container->OnEvent(Event::ArrowRight); + EXPECT_EQ(selected, 1); + EXPECT_FALSE(btn1->Focused()); + EXPECT_TRUE(btn2->Focused()); + + container->OnEvent(Event::ArrowRight); + EXPECT_EQ(selected, 1); + EXPECT_FALSE(btn1->Focused()); + EXPECT_TRUE(btn2->Focused()); + + EXPECT_EQ(press_count, 0); + + container->OnEvent(Event::Return); + EXPECT_EQ(press_count, 1); + EXPECT_EQ(last_press, "btn2"); + + container->OnEvent(Event::Return); + EXPECT_EQ(press_count, 2); + EXPECT_EQ(last_press, "btn2"); + + container->OnEvent(Event::ArrowLeft); + container->OnEvent(Event::Return); + EXPECT_EQ(press_count, 3); + EXPECT_EQ(last_press, "btn1"); + + (void)container->Render(); +} + +TEST(ButtonTest, Animation) { + int press_count = 0; + std::string last_press = ""; + auto option = ButtonOption::Animated(); + auto btn1 = Button("btn1", [&] { + press_count++; + last_press = "btn1"; + }, option); + auto btn2 = Button("btn2", [&] { + press_count++; + last_press = "btn2"; + }, option); + + int selected = 0; + auto container = Container::Horizontal({ + btn1, + btn2, + }, &selected); + + { + Screen screen(12, 3); + Render(screen, container->Render()); + EXPECT_EQ( + screen.ToString(), + "\x1B[1m\x1B[38;5;250m\x1B[48;5;16m \x1B[22m " + "\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;5;250m\x1B[48;5;16m btn1 \x1B[22m " + "btn2 \x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;5;250m\x1B[48;5;16m " + "\x1B[22m \x1B[39m\x1B[49m"); + } + selected = 1; + { + Screen screen(12, 3); + Render(screen, container->Render()); + EXPECT_EQ( + screen.ToString(), + "\x1B[38;5;250m\x1B[48;5;16m \x1B[1m " + "\x1B[22m\x1B[39m\x1B[49m\r\n\x1B[38;5;250m\x1B[48;5;16m btn1 \x1B[1m " + "btn2 \x1B[22m\x1B[39m\x1B[49m\r\n\x1B[38;5;250m\x1B[48;5;16m " + "\x1B[1m \x1B[22m\x1B[39m\x1B[49m"); + } + animation::Params params(2s); + container->OnAnimation(params); + { + Screen screen(12, 3); + Render(screen, container->Render()); + EXPECT_EQ( + screen.ToString(), + "\x1B[38;5;250m\x1B[48;5;16m \x1B[1m\x1B[38;5;231m\x1B[48;5;244m " + " \x1B[22m\x1B[39m\x1B[49m\r\n\x1B[38;5;250m\x1B[48;5;16m btn1 " + "\x1B[1m\x1B[38;5;231m\x1B[48;5;244m btn2 " + "\x1B[22m\x1B[39m\x1B[49m\r\n\x1B[38;5;250m\x1B[48;5;16m " + "\x1B[1m\x1B[38;5;231m\x1B[48;5;244m \x1B[22m\x1B[39m\x1B[49m"); + } + EXPECT_EQ(selected, 1); + container->OnEvent(MousePressed(3, 1)); + EXPECT_EQ(selected, 0); + { + Screen screen(12, 3); + Render(screen, container->Render()); + EXPECT_EQ(screen.ToString(), + "\x1B[1m\x1B[38;5;253m\x1B[48;5;238m " + "\x1B[22m\x1B[38;5;231m\x1B[48;5;244m " + "\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;5;253m\x1B[48;5;238m btn1 " + "\x1B[22m\x1B[38;5;231m\x1B[48;5;244m btn2 " + "\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;5;253m\x1B[48;5;238m " + "\x1B[22m\x1B[38;5;231m\x1B[48;5;244m \x1B[39m\x1B[49m"); + } + container->OnAnimation(params); + { + Screen screen(12, 3); + Render(screen, container->Render()); + EXPECT_EQ(screen.ToString(), + "\x1B[1m\x1B[38;5;231m\x1B[48;5;244m " + "\x1B[22m\x1B[38;5;250m\x1B[48;5;16m " + "\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;5;231m\x1B[48;5;244m btn1 " + "\x1B[22m\x1B[38;5;250m\x1B[48;5;16m btn2 " + "\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;5;231m\x1B[48;5;244m " + "\x1B[22m\x1B[38;5;250m\x1B[48;5;16m \x1B[39m\x1B[49m"); + } +} + +} // namespace ftxui + +// Copyright 2022 Arthur Sonzogni. All rights reserved. +// Use of this source code is governed by the MIT license that can be found in +// the LICENSE file. diff --git a/src/ftxui/component/collapsible_test.cpp b/src/ftxui/component/collapsible_test.cpp new file mode 100644 index 00000000..a00adbea --- /dev/null +++ b/src/ftxui/component/collapsible_test.cpp @@ -0,0 +1,57 @@ +#include // for Message +#include // for TestPartResult, SuiteApiResolver, TestFactoryImpl +#include // for allocator, __shared_ptr_access, shared_ptr +#include // for string, basic_string +#include // for vector + +#include "ftxui/component/captured_mouse.hpp" // for ftxui +#include "ftxui/component/component.hpp" // for collapsible +#include "ftxui/component/component_base.hpp" // for ComponentBase +#include "ftxui/component/component_options.hpp" // for MenuOption +#include "ftxui/component/event.hpp" // for Event, Event::ArrowDown, Event::Return +#include "ftxui/util/ref.hpp" // for Ref +#include "gtest/gtest_pred_impl.h" // for Test, EXPECT_EQ, TEST + +namespace ftxui { + +TEST(CollapsibleTest, Basic) { + auto child = Renderer([] { return text("child"); }); + bool show = false; + auto collapsible = Collapsible("parent", child, &show); + + EXPECT_TRUE(collapsible->Focused()); + EXPECT_FALSE(child->Focused()); + EXPECT_FALSE(collapsible->OnEvent(Event::ArrowDown)); + EXPECT_TRUE(collapsible->Focused()); + EXPECT_FALSE(child->Focused()); + + { + Screen screen(8, 3); + Render(screen, collapsible->Render()); + EXPECT_EQ(screen.ToString(), + "\xE2\x96\xB6 \x1B[1m\x1B[7mparent\x1B[22m\x1B[27m\r\n" + " \r\n" + " "); + } + + collapsible->OnEvent(Event::Return); + EXPECT_EQ(show, true); + + { + Screen screen(8, 3); + Render(screen, collapsible->Render()); + EXPECT_EQ(screen.ToString(), + "\xE2\x96\xBC \x1B[1m\x1B[7mparent\x1B[22m\x1B[27m\r\n" + "child \r\n" + " "); + } + + collapsible->OnEvent(Event::Return); + EXPECT_EQ(show, false); +} + +} // namespace ftxui + +// Copyright 2022 Arthur Sonzogni. All rights reserved. +// Use of this source code is governed by the MIT license that can be found in +// the LICENSE file. diff --git a/src/ftxui/component/menu_test.cpp b/src/ftxui/component/menu_test.cpp index 8f43b9b9..5bfa651e 100644 --- a/src/ftxui/component/menu_test.cpp +++ b/src/ftxui/component/menu_test.cpp @@ -45,51 +45,111 @@ TEST(MenuTest, RemoveEntries) { EXPECT_EQ(focused_entry, 1); } -TEST(MenuTest, Directions) { +TEST(MenuTest, DirectionDown) { int selected = 0; std::vector entries = {"1", "2", "3"}; MenuOption option; auto menu = Menu(&entries, &selected, &option); - { - option.direction = MenuOption::Down; - Screen screen(4, 3); - Render(screen, menu->Render()); - EXPECT_EQ(screen.ToString(), - "\x1B[1m\x1B[7m> 1 \x1B[22m\x1B[27m\r\n" - " 2 \r\n" - " 3 "); - } + selected = 0; + option.direction = MenuOption::Down; + Screen screen(4, 3); + Render(screen, menu->Render()); + EXPECT_EQ(screen.ToString(), + "\x1B[1m\x1B[7m> 1 \x1B[22m\x1B[27m\r\n" + " 2 \r\n" + " 3 "); - { - option.direction = MenuOption::Up; - Screen screen(4, 3); - Render(screen, menu->Render()); - EXPECT_EQ(screen.ToString(), - " 3 \r\n" - " 2 \r\n" - "\x1B[1m\x1B[7m> 1 \x1B[22m\x1B[27m"); - } + menu->OnEvent(Event::ArrowUp); + EXPECT_EQ(selected, 0); + menu->OnEvent(Event::ArrowDown); + EXPECT_EQ(selected, 1); + menu->OnEvent(Event::ArrowDown); + EXPECT_EQ(selected, 2); + menu->OnEvent(Event::ArrowDown); + EXPECT_EQ(selected, 2); + menu->OnEvent(Event::ArrowLeft); + EXPECT_EQ(selected, 2); + menu->OnEvent(Event::ArrowRight); + EXPECT_EQ(selected, 2); +} - { - option.direction = MenuOption::Right; - Screen screen(10, 1); - Render(screen, menu->Render()); - EXPECT_EQ(screen.ToString(), - "\x1B[1m\x1B[7m> 1\x1B[22m\x1B[27m" - " 2" - " 3 "); - } +TEST(MenuTest, DirectionsUp) { + int selected = 0; + std::vector entries = {"1", "2", "3"}; + MenuOption option; + auto menu = Menu(&entries, &selected, &option); + option.direction = MenuOption::Up; + Screen screen(4, 3); + Render(screen, menu->Render()); + EXPECT_EQ(screen.ToString(), + " 3 \r\n" + " 2 \r\n" + "\x1B[1m\x1B[7m> 1 \x1B[22m\x1B[27m"); + menu->OnEvent(Event::ArrowDown); + EXPECT_EQ(selected, 0); + menu->OnEvent(Event::ArrowUp); + EXPECT_EQ(selected, 1); + menu->OnEvent(Event::ArrowUp); + EXPECT_EQ(selected, 2); + menu->OnEvent(Event::ArrowUp); + EXPECT_EQ(selected, 2); + menu->OnEvent(Event::ArrowLeft); + EXPECT_EQ(selected, 2); + menu->OnEvent(Event::ArrowRight); + EXPECT_EQ(selected, 2); +} - { - option.direction = MenuOption::Left; - Screen screen(10, 1); - Render(screen, menu->Render()); - EXPECT_EQ(screen.ToString(), - " 3" - " 2" - "\x1B[1m\x1B[7m> 1\x1B[22m\x1B[27m "); - } +TEST(MenuTest, DirectionsRight) { + int selected = 0; + std::vector entries = {"1", "2", "3"}; + MenuOption option; + auto menu = Menu(&entries, &selected, &option); + option.direction = MenuOption::Right; + Screen screen(10, 1); + Render(screen, menu->Render()); + EXPECT_EQ(screen.ToString(), + "\x1B[1m\x1B[7m> 1\x1B[22m\x1B[27m" + " 2" + " 3 "); + menu->OnEvent(Event::ArrowLeft); + EXPECT_EQ(selected, 0); + menu->OnEvent(Event::ArrowRight); + EXPECT_EQ(selected, 1); + menu->OnEvent(Event::ArrowRight); + EXPECT_EQ(selected, 2); + menu->OnEvent(Event::ArrowRight); + EXPECT_EQ(selected, 2); + menu->OnEvent(Event::ArrowUp); + EXPECT_EQ(selected, 2); + menu->OnEvent(Event::ArrowDown); + EXPECT_EQ(selected, 2); +} + +TEST(MenuTest, DirectionsLeft) { + int selected = 0; + std::vector entries = {"1", "2", "3"}; + MenuOption option; + auto menu = Menu(&entries, &selected, &option); + option.direction = MenuOption::Left; + Screen screen(10, 1); + Render(screen, menu->Render()); + EXPECT_EQ(screen.ToString(), + " 3" + " 2" + "\x1B[1m\x1B[7m> 1\x1B[22m\x1B[27m "); + menu->OnEvent(Event::ArrowRight); + EXPECT_EQ(selected, 0); + menu->OnEvent(Event::ArrowLeft); + EXPECT_EQ(selected, 1); + menu->OnEvent(Event::ArrowLeft); + EXPECT_EQ(selected, 2); + menu->OnEvent(Event::ArrowLeft); + EXPECT_EQ(selected, 2); + menu->OnEvent(Event::ArrowUp); + EXPECT_EQ(selected, 2); + menu->OnEvent(Event::ArrowDown); + EXPECT_EQ(selected, 2); } TEST(MenuTest, AnimationsHorizontal) {