#include "AppDriver.hpp" #include "LibraryViewerApplication.hpp" #include "UnitTest++/UnitTest++.h" using namespace tp; using namespace tp::ui; namespace { constexpr halnf kPaintBudgetMs = 4; constexpr int kMeasuredFrames = 30; constexpr ualni kPaintedWidgetsBudget = 150; halnf averagePaintMs(LibraryViewerApplication& application, AppDriver& driver) { halnf total = 0; for (int frame = 0; frame < kMeasuredFrames; frame++) { application.ui().resetStats(); application.gui().requestPaint(); driver.frame(); total += (halnf) application.ui().stats().paintNs / 1.0e6f; } return total / kMeasuredFrames; } } SUITE(LibraryViewerIntegration) { TEST(ThousandsOfTracksPaintWithinBudget) { LibraryViewerApplication application("library/Library.json"); AppDriver driver(application); CHECK(application.library().mTraks.size() > 2000); const halnf atTop = averagePaintMs(application, driver); CHECK(atTop < kPaintBudgetMs); CHECK(application.ui().stats().paintedWidgets < kPaintedWidgetsBudget); for (int notch = 0; notch < 200; notch++) driver.scroll({ 300, 300 }, -3); driver.advance(500); const halnf scrolled = averagePaintMs(application, driver); CHECK(scrolled < kPaintBudgetMs); printf("library paint: %.3f ms at top, %.3f ms scrolled\n", atTop, scrolled); } TEST(ClickingTrackSelectsIt) { LibraryViewerApplication application("library/Library.json"); AppDriver driver(application); driver.click(*application.gui().visibleTracks()[0]); CHECK(application.gui().selectedTrack() != nullptr); } } SUITE(LibraryViewerChrome) { TEST(DefaultMenuBarCarriesLibraryMenus) { LibraryViewerApplication application("library/Library.json"); AppDriver driver(application); CHECK(application.isMenuBarVisible()); CHECK_EQUAL(3u, application.menuBar().titles().size()); CHECK(application.menuBar().windowRect().pos.y < application.gui().windowRect().pos.y + 1); const RectF player = application.gui().player.windowRect(); CHECK(player.pos.y + player.size.y > application.gui().windowRect().size.y - 4); } TEST(SearchingNarrowsTheRealLibrary) { LibraryViewerApplication application("library/Library.json"); AppDriver driver(application); const size_t all = application.gui().visibleTracks().size(); driver.click(application.gui().search); driver.type("jack"); CHECK(application.gui().visibleTracks().size() < all); CHECK(!application.gui().visibleTracks().empty()); } } SUITE(LibraryViewerInputCoalescing) { TEST(MotionBurstWithinOneFrameIsDeliveredOnce) { LibraryViewerApplication application("library/Library.json"); AppDriver driver(application); const CoalescingStatistics before = application.window().inputStatistics(); WindowInputObserver& input = application.window().injectInput(); for (int step = 0; step < 50; step++) input.onPointerMoved({ 100.0f + (halnf) step, 200.0f }); driver.frame(); const CoalescingStatistics after = application.window().inputStatistics(); CHECK_EQUAL(50u, after.received - before.received); CHECK_EQUAL(1u, after.delivered - before.delivered); } TEST(ClickInsideBurstStillLandsOnItsPosition) { LibraryViewerApplication application("library/Library.json"); AppDriver driver(application); const RectF target = application.gui().visibleTracks()[1]->windowRect(); WindowInputObserver& input = application.window().injectInput(); input.onPointerMoved({ 5, 5 }); input.onPointerMoved(target.center()); input.onPointerButton(InputID::MOUSE1, true); input.onPointerButton(InputID::MOUSE1, false); input.onPointerMoved({ 5, 5 }); driver.frame(); CHECK(application.gui().selectedTrack() == &application.gui().visibleTracks()[1]->track()); } } SUITE(LibraryViewerResize) { TEST(MaximizeAppliesOneConfigurePerFrameAndRelayouts) { LibraryViewerApplication application("library/Library.json"); AppDriver driver(application); const Vec2F before = application.window().getSize(); const CoalescingStatistics start = application.window().inputStatistics(); application.window().toggleMaximize(); for (int frame = 0; frame < 30 && application.window().getSize() == before; frame++) driver.frame(); const CoalescingStatistics end = application.window().inputStatistics(); CHECK(application.window().getSize().x > before.x || application.window().getSize().y > before.y); CHECK(end.configuresApplied - start.configuresApplied >= 1); CHECK(end.configuresApplied - start.configuresApplied <= end.configuresReceived - start.configuresReceived); CHECK_CLOSE(application.window().getSize().x, application.gui().windowRect().size.x, 1.0f); } }