mirror of
				https://github.com/ArthurSonzogni/FTXUI.git
				synced 2025-11-04 13:38:14 +08:00 
			
		
		
		
	Add coverage for terminal_input_parser.
This commit is contained in:
		@@ -136,12 +136,11 @@ TerminalInputParser::Output TerminalInputParser::ParseUTF8() {
 | 
			
		||||
  unsigned int first_zero = 8;            // NOLINT
 | 
			
		||||
  for (unsigned int i = 0; i < 8; ++i) {  // NOLINT
 | 
			
		||||
    mask |= selector;
 | 
			
		||||
    if (head & selector) {
 | 
			
		||||
      selector >>= 1U;
 | 
			
		||||
      continue;
 | 
			
		||||
    if (!(head & selector)) {
 | 
			
		||||
      first_zero = i;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    first_zero = i;
 | 
			
		||||
    break;
 | 
			
		||||
    selector >>= 1U;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Accumulate the value of the first byte.
 | 
			
		||||
 
 | 
			
		||||
@@ -72,7 +72,7 @@ TEST(Event, EscapeKeyEnoughWait) {
 | 
			
		||||
  EXPECT_FALSE(event_receiver->Receive(&received));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(Event, MouseLeftClick) {
 | 
			
		||||
TEST(Event, MouseLeftClickPressed) {
 | 
			
		||||
  auto event_receiver = MakeReceiver<Task>();
 | 
			
		||||
  {
 | 
			
		||||
    auto parser = TerminalInputParser(event_receiver->MakeSender());
 | 
			
		||||
@@ -95,6 +95,56 @@ TEST(Event, MouseLeftClick) {
 | 
			
		||||
  EXPECT_EQ(Mouse::Left, std::get<Event>(received).mouse().button);
 | 
			
		||||
  EXPECT_EQ(12, std::get<Event>(received).mouse().x);
 | 
			
		||||
  EXPECT_EQ(42, std::get<Event>(received).mouse().y);
 | 
			
		||||
  EXPECT_EQ(std::get<Event>(received).mouse().motion, Mouse::Pressed);
 | 
			
		||||
  EXPECT_FALSE(event_receiver->Receive(&received));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(Event, MouseLeftClickReleased) {
 | 
			
		||||
  auto event_receiver = MakeReceiver<Task>();
 | 
			
		||||
  {
 | 
			
		||||
    auto parser = TerminalInputParser(event_receiver->MakeSender());
 | 
			
		||||
    parser.Add('\x1B');
 | 
			
		||||
    parser.Add('[');
 | 
			
		||||
    parser.Add('3');
 | 
			
		||||
    parser.Add('2');
 | 
			
		||||
    parser.Add(';');
 | 
			
		||||
    parser.Add('1');
 | 
			
		||||
    parser.Add('2');
 | 
			
		||||
    parser.Add(';');
 | 
			
		||||
    parser.Add('4');
 | 
			
		||||
    parser.Add('2');
 | 
			
		||||
    parser.Add('m');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Task received;
 | 
			
		||||
  EXPECT_TRUE(event_receiver->Receive(&received));
 | 
			
		||||
  EXPECT_TRUE(std::get<Event>(received).is_mouse());
 | 
			
		||||
  EXPECT_EQ(Mouse::Left, std::get<Event>(received).mouse().button);
 | 
			
		||||
  EXPECT_EQ(12, std::get<Event>(received).mouse().x);
 | 
			
		||||
  EXPECT_EQ(42, std::get<Event>(received).mouse().y);
 | 
			
		||||
  EXPECT_EQ(std::get<Event>(received).mouse().motion, Mouse::Released);
 | 
			
		||||
  EXPECT_FALSE(event_receiver->Receive(&received));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(Event, MouseReporting) {
 | 
			
		||||
  auto event_receiver = MakeReceiver<Task>();
 | 
			
		||||
  {
 | 
			
		||||
    auto parser = TerminalInputParser(event_receiver->MakeSender());
 | 
			
		||||
    parser.Add('\x1B');
 | 
			
		||||
    parser.Add('[');
 | 
			
		||||
    parser.Add('1');
 | 
			
		||||
    parser.Add('2');
 | 
			
		||||
    parser.Add(';');
 | 
			
		||||
    parser.Add('4');
 | 
			
		||||
    parser.Add('2');
 | 
			
		||||
    parser.Add('R');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Task received;
 | 
			
		||||
  EXPECT_TRUE(event_receiver->Receive(&received));
 | 
			
		||||
  EXPECT_TRUE(std::get<Event>(received).is_cursor_reporting());
 | 
			
		||||
  EXPECT_EQ(42, std::get<Event>(received).cursor_x());
 | 
			
		||||
  EXPECT_EQ(12, std::get<Event>(received).cursor_y());
 | 
			
		||||
  EXPECT_FALSE(event_receiver->Receive(&received));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -232,6 +282,105 @@ TEST(Event, UTF8) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(Event, NewLine) {
 | 
			
		||||
  for (char newline : {'\r', '\n'}) {
 | 
			
		||||
    auto event_receiver = MakeReceiver<Task>();
 | 
			
		||||
    {
 | 
			
		||||
      auto parser = TerminalInputParser(event_receiver->MakeSender());
 | 
			
		||||
      parser.Add(newline);
 | 
			
		||||
    }
 | 
			
		||||
    Task received;
 | 
			
		||||
    EXPECT_TRUE(event_receiver->Receive(&received));
 | 
			
		||||
    EXPECT_TRUE(std::get<Event>(received) == Event::Return);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(Event, Control) {
 | 
			
		||||
  struct TestCase {
 | 
			
		||||
    char input;
 | 
			
		||||
    bool cancel;
 | 
			
		||||
  };
 | 
			
		||||
  std::vector<TestCase> cases;
 | 
			
		||||
  for (int i = 0; i < 32; ++i) {
 | 
			
		||||
    if (i == 13 || i == 24 || i == 26 || i == 27)
 | 
			
		||||
      continue;
 | 
			
		||||
    cases.push_back({char(i), false});
 | 
			
		||||
  }
 | 
			
		||||
  cases.push_back({char(24), true});
 | 
			
		||||
  cases.push_back({char(26), true});
 | 
			
		||||
  cases.push_back({char(127), false});
 | 
			
		||||
 | 
			
		||||
  for(auto test : cases) {
 | 
			
		||||
    auto event_receiver = MakeReceiver<Task>();
 | 
			
		||||
    {
 | 
			
		||||
      auto parser = TerminalInputParser(event_receiver->MakeSender());
 | 
			
		||||
      parser.Add(test.input);
 | 
			
		||||
    }
 | 
			
		||||
    Task received;
 | 
			
		||||
    if (test.cancel) {
 | 
			
		||||
      EXPECT_FALSE(event_receiver->Receive(&received));
 | 
			
		||||
    } else {
 | 
			
		||||
      EXPECT_TRUE(event_receiver->Receive(&received));
 | 
			
		||||
      EXPECT_EQ(std::get<Event>(received), Event::Special({test.input}));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(Event, Special) {
 | 
			
		||||
  auto str = [](std::string input) {
 | 
			
		||||
    std::vector<unsigned char> output;
 | 
			
		||||
    for (auto it : input)
 | 
			
		||||
      output.push_back(it);
 | 
			
		||||
    return output;
 | 
			
		||||
  };
 | 
			
		||||
  struct {
 | 
			
		||||
    std::vector<unsigned char> input;
 | 
			
		||||
    Event expected;
 | 
			
		||||
  } kTestCase[] = {
 | 
			
		||||
      {str("\x1B[D"), Event::ArrowLeft},
 | 
			
		||||
      {str("\x1B[C"), Event::ArrowRight},
 | 
			
		||||
      {str("\x1B[A"), Event::ArrowUp},
 | 
			
		||||
      {str("\x1B[B"), Event::ArrowDown},
 | 
			
		||||
      {{127}, Event::Backspace},
 | 
			
		||||
      {str("\x1B[3~"), Event::Delete},
 | 
			
		||||
      //{str("\x1B"), Event::Escape},
 | 
			
		||||
      {{10}, Event::Return},
 | 
			
		||||
      {{9}, Event::Tab},
 | 
			
		||||
      {{27, 91, 90}, Event::TabReverse},
 | 
			
		||||
      //{str("\x1B[OP"), Event::F1},
 | 
			
		||||
      //{str("\x1B[OQ"), Event::F2},
 | 
			
		||||
      //{str("\x1B[OR"), Event::F3},
 | 
			
		||||
      //{str("\x1B[OS"), Event::F4},
 | 
			
		||||
      {str("\x1B[15~"), Event::F5},
 | 
			
		||||
      {str("\x1B[17~"), Event::F6},
 | 
			
		||||
      {str("\x1B[18~"), Event::F7},
 | 
			
		||||
      {str("\x1B[19~"), Event::F8},
 | 
			
		||||
      {str("\x1B[20~"), Event::F9},
 | 
			
		||||
      {str("\x1B[21~"), Event::F10},
 | 
			
		||||
      {str("\x1B[21~"), Event::F11},
 | 
			
		||||
      {str("\x1B[24~"), Event::F12},
 | 
			
		||||
      {{27, 91, 72}, Event::Home},
 | 
			
		||||
      {{27, 91, 70}, Event::End},
 | 
			
		||||
      {{27, 91, 53, 126}, Event::PageUp},
 | 
			
		||||
      {{27, 91, 54, 126}, Event::PageDown},
 | 
			
		||||
      {{0}, Event::Custom},
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  for (auto test : kTestCase) {
 | 
			
		||||
    auto event_receiver = MakeReceiver<Task>();
 | 
			
		||||
    {
 | 
			
		||||
      auto parser = TerminalInputParser(event_receiver->MakeSender());
 | 
			
		||||
      for (auto input : test.input) {
 | 
			
		||||
        parser.Add(input);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    Task received;
 | 
			
		||||
    EXPECT_TRUE(event_receiver->Receive(&received));
 | 
			
		||||
    EXPECT_EQ(std::get<Event>(received), test.expected);
 | 
			
		||||
    EXPECT_FALSE(event_receiver->Receive(&received));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace ftxui
 | 
			
		||||
 | 
			
		||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
 | 
			
		||||
 
 | 
			
		||||
@@ -20,33 +20,49 @@ int Hash(const std::string s) {
 | 
			
		||||
TEST(BorderTest, GoldPoint) {
 | 
			
		||||
  Terminal::SetColorSupport(Terminal::Color::TrueColor);
 | 
			
		||||
  auto element = canvas([](Canvas& c) {  //
 | 
			
		||||
    c.DrawPoint(3, 3, 1, Color::Red);
 | 
			
		||||
    c.DrawPoint(3, 3, 1);
 | 
			
		||||
    c.DrawPointToggle(2, 8);
 | 
			
		||||
    c.DrawPointLine(3, 7, 10, 19, Color::Blue);
 | 
			
		||||
    c.DrawPointCircle(10, 5, 3, Color::Yellow);
 | 
			
		||||
    c.DrawPointCircleFilled(20, 5, 3, Color::Green);
 | 
			
		||||
    c.DrawPointEllipse(10, 10, 5, 2, Color::Blue);
 | 
			
		||||
    c.DrawPointEllipseFilled(10, 20, 5, 2, Color::DarkGreen);
 | 
			
		||||
    c.DrawPointToggle(2, 8);
 | 
			
		||||
    c.DrawPointToggle(2, 8);
 | 
			
		||||
    c.DrawPointLine(3, 7, 10, 19);
 | 
			
		||||
    c.DrawPointCircle(10, 5, 3);
 | 
			
		||||
    c.DrawPointCircleFilled(20, 5, 3);
 | 
			
		||||
    c.DrawPointEllipse(10, 10, 5, 2);
 | 
			
		||||
    c.DrawPointEllipseFilled(10, 20, 5, 2);
 | 
			
		||||
  });
 | 
			
		||||
  Screen screen(30, 10);
 | 
			
		||||
  Render(screen, element);
 | 
			
		||||
  EXPECT_EQ(Hash(screen.ToString()), 17651);
 | 
			
		||||
  EXPECT_EQ(Hash(screen.ToString()), 1069);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(BorderTest, GoldBlock) {
 | 
			
		||||
  Terminal::SetColorSupport(Terminal::Color::TrueColor);
 | 
			
		||||
  auto element = canvas([](Canvas& c) {  //
 | 
			
		||||
    c.DrawBlock(3, 3, 1, Color::Red);
 | 
			
		||||
    c.DrawBlock(3, 3, 1);
 | 
			
		||||
    c.DrawBlockToggle(2, 8);
 | 
			
		||||
    c.DrawBlockLine(3, 7, 10, 19, Color::Blue);
 | 
			
		||||
    c.DrawBlockCircle(10, 5, 3, Color::Yellow);
 | 
			
		||||
    c.DrawBlockCircleFilled(20, 5, 3, Color::Green);
 | 
			
		||||
    c.DrawBlockEllipse(10, 10, 5, 2, Color::Blue);
 | 
			
		||||
    c.DrawBlockEllipseFilled(10, 20, 5, 2, Color::DarkGreen);
 | 
			
		||||
    c.DrawBlockToggle(2, 8);
 | 
			
		||||
    c.DrawBlockToggle(2, 8);
 | 
			
		||||
    c.DrawBlockLine(3, 7, 10, 19);
 | 
			
		||||
    c.DrawBlockCircle(10, 5, 3);
 | 
			
		||||
    c.DrawBlockCircleFilled(20, 5, 3);
 | 
			
		||||
    c.DrawBlockEllipse(10, 10, 5, 2);
 | 
			
		||||
    c.DrawBlockEllipseFilled(10, 20, 5, 2);
 | 
			
		||||
  });
 | 
			
		||||
  Screen screen(30, 10);
 | 
			
		||||
  Render(screen, element);
 | 
			
		||||
  EXPECT_EQ(Hash(screen.ToString()), 14383);
 | 
			
		||||
  EXPECT_EQ(Hash(screen.ToString()), 472);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(BorderTest, GoldText) {
 | 
			
		||||
  Terminal::SetColorSupport(Terminal::Color::TrueColor);
 | 
			
		||||
  Canvas c(10, 10);
 | 
			
		||||
  c.DrawText(0, 0, "test");
 | 
			
		||||
  c.DrawText(0, 5, "test");
 | 
			
		||||
  c.DrawText(0, 10, "test");
 | 
			
		||||
  auto element = canvas(c);
 | 
			
		||||
  Screen screen(30, 10);
 | 
			
		||||
  Render(screen, element);
 | 
			
		||||
  EXPECT_EQ(Hash(screen.ToString()), 10447);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace ftxui
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user