#include "UI/ProjectTabLayout.h" #include // projectTabOverflow is geometry: made-up ids and widths. namespace { const QUuid a = QUuid::createUuid(), b = QUuid::createUuid(), c = QUuid::createUuid(), d = QUuid::createUuid(), e = QUuid::createUuid(); // Every tab 100 wide. std::map widths(const std::vector &ids) { std::map result; for (const QUuid &id : ids) result.insert({id, 100}); return result; } const std::function pill = [](int) { return 80.0; }; std::vector ids(const ProjectTabOverflow &layout) { std::vector result; for (const ProjectTabSlot &slot : layout.visible) result.push_back(slot.id); return result; } std::vector xs(const ProjectTabOverflow &layout) { std::vector result; for (const ProjectTabSlot &slot : layout.visible) result.push_back(slot.x); return result; } } class ProjectTabLayoutTests : public QObject { Q_OBJECT private slots: void everythingFitsShowsAllTabsWithNoPill(); void overflowHidesTheLeftmostTabsAndPillsThem(); void selectedTabInTheHiddenSetIsPinnedRightOfThePill(); void overflowLabelIsSingularForOneTab(); void unmeasuredWidthShowsEverythingRatherThanGuessing(); void aWiderSelectedTabStillFits(); void thePillsWidthFollowsTheHiddenCount(); }; void ProjectTabLayoutTests::everythingFitsShowsAllTabsWithNoPill() { const std::vector order{a, b, c}; const ProjectTabOverflow result = projectTabOverflow(order, widths(order), c, 400, pill); QVERIFY(result.hiddenIDs.empty()); QVERIFY(!result.pill); QVERIFY(ids(result) == order); QVERIFY((xs(result) == std::vector{0, 106, 212})); QCOMPARE(result.contentWidth(), 312.0); // Exactly the room it needs still fits. QVERIFY(!projectTabOverflow(order, widths(order), c, 312, pill).pill); QVERIFY(projectTabOverflow(order, widths(order), c, 311.5, pill).pill); QVERIFY(projectTabOverflow({}, {}, c, 400, pill) == ProjectTabOverflow()); QCOMPARE(ProjectTabOverflow().contentWidth(), 0.0); } void ProjectTabLayoutTests::overflowHidesTheLeftmostTabsAndPillsThem() { const std::vector order{a, b, c, d, e}; // The pill and two tabs: 292; a third needs 398. const ProjectTabOverflow result = projectTabOverflow(order, widths(order), e, 300, pill); QVERIFY((result.hiddenIDs == std::vector{a, b, c})); QVERIFY((ids(result) == std::vector{d, e})); QVERIFY((result.pill.value() == ProjectTabPillSlot{0, 80})); QCOMPARE(result.visible.front().x, 86.0); QCOMPARE(result.visible.front().width, 100.0); QCOMPARE(result.contentWidth(), 292.0); // 292 exactly still holds two; a third at 398. QCOMPARE(projectTabOverflow(order, widths(order), e, 292, pill).visible.size(), size_t(2)); QCOMPARE(projectTabOverflow(order, widths(order), e, 397, pill).visible.size(), size_t(2)); QCOMPARE(projectTabOverflow(order, widths(order), e, 398, pill).visible.size(), size_t(3)); // Too narrow for even one: one tab stays. QVERIFY((ids(projectTabOverflow(order, widths(order), e, 50, pill)) == std::vector{e})); } void ProjectTabLayoutTests::selectedTabInTheHiddenSetIsPinnedRightOfThePill() { const std::vector order{a, b, c, d, e}; // a takes the first slot; d, bumped, hides in order. const ProjectTabOverflow result = projectTabOverflow(order, widths(order), a, 300, pill); QVERIFY((ids(result) == std::vector{a, e})); QVERIFY((result.hiddenIDs == std::vector{b, c, d})); QCOMPARE(result.pill.value().width, 80.0); QVERIFY((xs(result) == std::vector{86, 192})); } void ProjectTabLayoutTests::overflowLabelIsSingularForOneTab() { QCOMPARE(projectTabOverflowLabel(1), QString("1 more tab")); QCOMPARE(projectTabOverflowLabel(2), QString("2 more tabs")); QCOMPARE(projectTabOverflowLabel(11), QString("11 more tabs")); } void ProjectTabLayoutTests::unmeasuredWidthShowsEverythingRatherThanGuessing() { const std::vector order{a, b, c, d, e}; const ProjectTabOverflow result = projectTabOverflow(order, widths(order), a, 0, pill); QVERIFY(result.hiddenIDs.empty()); QVERIFY(!result.pill); QCOMPARE(result.visible.size(), size_t(5)); } // A long-titled hidden tab still leaves a row that fits. void ProjectTabLayoutTests::aWiderSelectedTabStillFits() { std::vector order; std::map sizes; for (int index = 0; index < 8; ++index) { order.push_back(QUuid::createUuid()); sizes.insert({order.back(), 80}); } sizes[order[0]] = 190; const ProjectTabOverflow layout = projectTabOverflow(order, sizes, order[0], 500, [](int) { return 90.0; }); QVERIFY2(layout.contentWidth() <= 500, qPrintable(QString::number(layout.contentWidth()))); QCOMPARE(layout.visible.front().id, order[0]); // Pill 90, 190, two of 80; three would make 522. QVERIFY((ids(layout) == std::vector{order[0], order[6], order[7]})); QVERIFY((layout.hiddenIDs == std::vector{order[1], order[2], order[3], order[4], order[5]})); QCOMPARE(layout.contentWidth(), 90 + 6 + 190 + 6 + 80 + 6 + 80.0); // Wide enough, it stands alone after the pill. const std::vector five{a, b, c, d, e}; std::map wide = widths(five); wide[a] = 290; const ProjectTabOverflow alone = projectTabOverflow(five, wide, a, 400, pill); QVERIFY((ids(alone) == std::vector{a})); QVERIFY((alone.hiddenIDs == std::vector{b, c, d, e})); } // The pill's width is asked by its hidden count. void ProjectTabLayoutTests::thePillsWidthFollowsTheHiddenCount() { const std::vector order{a, b, c, d, e}; std::vector asked; const ProjectTabOverflow result = projectTabOverflow(order, widths(order), e, 300, [&](int hidden) { asked.push_back(hidden); return 50.0 + hidden; }); // Three hidden fits (265); the last ask places it. QVERIFY((asked == std::vector{0, 1, 2, 3, 3})); QVERIFY((ids(result) == std::vector{d, e})); QCOMPARE(result.pill.value().width, 53.0); QCOMPARE(result.visible.front().x, 59.0); } QTEST_GUILESS_MAIN(ProjectTabLayoutTests) #include "ProjectTabLayoutTests.moc"