80 lines
3.0 KiB
C++
80 lines
3.0 KiB
C++
#include <doctest/doctest.h>
|
|
|
|
#include "fgc/ui/Scroll.h"
|
|
|
|
#include <initializer_list>
|
|
|
|
using namespace fgc;
|
|
|
|
TEST_CASE("scrollMax is zero when the content fits") {
|
|
CHECK(scrollMax(10, 20) == 0);
|
|
CHECK(scrollMax(20, 20) == 0);
|
|
CHECK(scrollMax(21, 20) == 1);
|
|
CHECK(scrollMax(100, 20) == 80);
|
|
}
|
|
|
|
TEST_CASE("an unmeasured view pins to the top") {
|
|
// First frame after an overlay opens: reflect() has not run yet, so every
|
|
// height is 0. Scrolling must be a no-op rather than a guess.
|
|
CHECK(scrollMax(500, 0) == 0);
|
|
CHECK(scrollClamp(42, 500, 0) == 0);
|
|
CHECK(scrollBy(0, 1, 500, 0) == 0);
|
|
CHECK(scrollPage(0, 1, 500, 0) == 0);
|
|
CHECK(scrollMax(500, -3) == 0);
|
|
}
|
|
|
|
TEST_CASE("scrollClamp pulls a stale position back into range") {
|
|
// The pane was scrolled to the bottom of a long dump, then the dump was
|
|
// replaced by a shorter one: the view must not stay parked past the end.
|
|
CHECK(scrollClamp(80, 100, 20) == 80);
|
|
CHECK(scrollClamp(80, 30, 20) == 10);
|
|
CHECK(scrollClamp(80, 10, 20) == 0);
|
|
CHECK(scrollClamp(-5, 100, 20) == 0);
|
|
}
|
|
|
|
TEST_CASE("scrollBy steps one line and stops at the ends") {
|
|
CHECK(scrollBy(0, 1, 100, 20) == 1);
|
|
CHECK(scrollBy(5, -1, 100, 20) == 4);
|
|
CHECK(scrollBy(0, -1, 100, 20) == 0); // already at the top
|
|
CHECK(scrollBy(80, 1, 100, 20) == 80); // already at the bottom
|
|
}
|
|
|
|
TEST_CASE("scrollPage keeps two lines of overlap") {
|
|
CHECK(scrollPage(0, 1, 100, 20) == 18);
|
|
CHECK(scrollPage(18, -1, 100, 20) == 0);
|
|
// PgDn then PgUp returns exactly where it started, away from the ends.
|
|
CHECK(scrollPage(scrollPage(30, 1, 200, 20), -1, 200, 20) == 30);
|
|
}
|
|
|
|
TEST_CASE("scrollPage still advances in a one-line pane") {
|
|
// view_h - 2 would be negative; the step floor keeps the keys usable.
|
|
CHECK(scrollPage(0, 1, 100, 1) == 1);
|
|
CHECK(scrollPage(0, 1, 100, 2) == 1);
|
|
}
|
|
|
|
TEST_CASE("gridRowsPerColumn keeps short grids compact") {
|
|
// Under the column cap the grid looks exactly as it did before: 18 per column.
|
|
CHECK(gridRowsPerColumn(0, 3, 18) == 18);
|
|
CHECK(gridRowsPerColumn(1, 3, 18) == 18);
|
|
CHECK(gridRowsPerColumn(30, 3, 18) == 18);
|
|
CHECK(gridRowsPerColumn(54, 3, 18) == 18); // exactly 3 full columns
|
|
}
|
|
|
|
TEST_CASE("gridRowsPerColumn grows downward past the column cap") {
|
|
// Past the cap the grid must get taller, not wider, or it runs off the
|
|
// right edge where vertical scrolling cannot reach it.
|
|
CHECK(gridRowsPerColumn(55, 3, 18) == 19);
|
|
CHECK(gridRowsPerColumn(200, 3, 18) == 67);
|
|
// Never more than max_cols columns.
|
|
for (std::size_t n : std::initializer_list<std::size_t>{55, 100, 200, 999}) {
|
|
const std::size_t rows = gridRowsPerColumn(n, 3, 18);
|
|
CHECK((n + rows - 1) / rows <= 3);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("gridRowsPerColumn tolerates degenerate parameters") {
|
|
CHECK(gridRowsPerColumn(10, 0, 18) == 18); // max_cols 0 => treated as 1
|
|
CHECK(gridRowsPerColumn(100, 0, 1) == 100);
|
|
CHECK(gridRowsPerColumn(10, 3, 0) >= 1);
|
|
}
|