aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_carddelegate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_carddelegate.cpp')
-rw-r--r--tests/test_carddelegate.cpp128
1 files changed, 128 insertions, 0 deletions
diff --git a/tests/test_carddelegate.cpp b/tests/test_carddelegate.cpp
index d5e55b5..a14671d 100644
--- a/tests/test_carddelegate.cpp
+++ b/tests/test_carddelegate.cpp
@@ -18,6 +18,9 @@
#include "carddelegate.h"
+#include "cardlayout.h"
+#include "tagchip.h"
+#include "tagcolors.h"
#include "threadlistmodel.h"
#include <QTest>
@@ -30,6 +33,9 @@ private slots:
void theAccentLiftsAMutedAccountColour();
void theAccentKeepsEachAccountTellableApart();
void anAccountWithNoColourFallsBackToTheNeutralLine();
+ void aSiblingChipIsMutedButStaysLegibleAndRecognisable();
+ void aSiblingChipFontIsSmallerThanItsOwnTier();
+ void aSiblingChipsPaddingShrinksWithItsFont();
};
namespace {
@@ -131,5 +137,127 @@ void TestCardDelegate::anAccountWithNoColourFallsBackToTheNeutralLine()
ThreadListModel::threadLineColour());
}
+void TestCardDelegate::aSiblingChipIsMutedButStaysLegibleAndRecognisable()
+{
+ // Item 111: a card shows its own tags at full size and the rest of the
+ // conversation's smaller and muted. "Muted" has two hard requirements that
+ // a look at the screen will not catch, so they are asserted here.
+ for (const QColor &colour : sampleAccounts()) {
+ const QColor muted = CardDelegate::mutedChipColour(colour);
+
+ // Actually muted, or the tier is not distinguishable at all.
+ QVERIFY2(saturationOf(muted) < saturationOf(colour),
+ qPrintable(QStringLiteral("%1 was not drained at all")
+ .arg(colour.name())));
+
+ // Same HUE. A sibling's `signed` has to stay recognisably the same
+ // colour as a full-size `signed` elsewhere in the list, or the muting
+ // reads as a different tag rather than a quieter one.
+ float h1 = 0, h2 = 0, s = 0, l = 0, a = 0;
+ colour.getHslF(&h1, &s, &l, &a);
+ muted.getHslF(&h2, &s, &l, &a);
+ QVERIFY2(qAbs(h1 - h2) < 0.001f,
+ qPrintable(QStringLiteral("%1 changed hue when muted")
+ .arg(colour.name())));
+
+ // Same LIGHTNESS, which is what keeps the text legible: TagColors
+ // picks the text colour from the fill, and a fill that drifted toward
+ // black or white could flip that choice or land mid-grey where neither
+ // works. Blending toward the background would do exactly that, which
+ // is the mistake accentLineColour() records.
+ QCOMPARE(lightnessOf(muted), lightnessOf(colour));
+ QCOMPARE(TagColors::textColourOn(muted),
+ TagColors::textColourOn(colour));
+ }
+
+ // An invalid colour stays invalid rather than becoming a real one.
+ QVERIFY(!CardDelegate::mutedChipColour(QColor()).isValid());
+}
+
+void TestCardDelegate::aSiblingChipFontIsSmallerThanItsOwnTier()
+{
+ // Size is what says whose tag a chip is, so the two tiers must differ, and
+ // by enough to SEE. The first version subtracted a point from smallFont(),
+ // and the user reported the tiers as indistinguishable: on their 14pt
+ // desktop that gave 13 and 12, a 7% step.
+ //
+ // The step is now a fraction of the card font, so it does not shrink as
+ // the desktop's font grows. Asserted as a ratio rather than as a size, to
+ // keep this about the DISTINCTION rather than about the constant.
+ QFont card;
+ card.setPointSizeF(14.0); // The user's own desktop size.
+ const qreal own = CardLayout::smallFont(card).pointSizeF();
+ const qreal sibling = CardLayout::siblingFont(card).pointSizeF();
+
+ QVERIFY(sibling < own);
+ QVERIFY2(sibling < own * 0.85,
+ qPrintable(QStringLiteral("sibling %1pt against own %2pt is under "
+ "a 15%% step, which reads as the same "
+ "size")
+ .arg(sibling)
+ .arg(own)));
+
+ // Proportional, not a fixed subtraction: the step must survive a larger
+ // desktop font rather than becoming proportionally smaller.
+ QFont big;
+ big.setPointSizeF(28.0);
+ QVERIFY(CardLayout::siblingFont(big).pointSizeF()
+ < CardLayout::smallFont(big).pointSizeF() * 0.85);
+
+ // The pixel branch too: qt6ct sets fonts in PIXELS, and pointSizeF() is -1
+ // for those, so a point-only implementation silently returns the original
+ // size and both tiers render identically. CLAUDE.md records this trap.
+ QFont pixels;
+ pixels.setPixelSize(14);
+ QVERIFY(pixels.pointSizeF() < 0);
+ QVERIFY2(CardLayout::siblingFont(pixels).pixelSize()
+ < CardLayout::smallFont(pixels).pixelSize(),
+ "a pixel-sized desktop font gives both tiers the same size, so "
+ "the distinction disappears entirely");
+
+ // Floored rather than shrinking without limit.
+ QFont tiny;
+ tiny.setPointSizeF(6.0);
+ QVERIFY(CardLayout::siblingFont(tiny).pointSizeF() >= 6.0);
+}
+
+void TestCardDelegate::aSiblingChipsPaddingShrinksWithItsFont()
+{
+ // Half of "smaller" is the padding, and leaving it fixed is why the first
+ // version still looked the same size. kPaddingX is 9 a side: on a sibling
+ // chip that is 18px of padding around roughly 30px of text, so the chip
+ // stayed wide while its letters shrank, which reads as "same chip, smaller
+ // text" rather than as a smaller chip.
+ QFont card;
+ card.setPointSizeF(14.0);
+ const QFontMetrics ownMetrics(CardLayout::smallFont(card));
+ const QFontMetrics siblingMetrics(CardLayout::siblingFont(card));
+
+ const QString tag = QStringLiteral("signed");
+ // Through CardDelegate::chipSize(), which is what the paint loop calls.
+ // Calling TagChip::sizeFor() directly here proved what THAT function does
+ // and nothing about whether the delegate asks it for a scaled padding: a
+ // mutation dropping the scale at the call site survived that version of
+ // this test.
+ const QSize own = CardDelegate::chipSize(ownMetrics, tag, true);
+ const QSize scaled = CardDelegate::chipSize(siblingMetrics, tag, false);
+ const QSize unscaled = TagChip::sizeFor(siblingMetrics, tag);
+
+ // The font alone is not enough: scaling the padding as well takes off
+ // measurably more width.
+ QVERIFY2(scaled.width() < unscaled.width(),
+ "the padding did not scale, so the chip keeps full-size margins "
+ "around smaller letters");
+ QVERIFY(scaled.width() < own.width());
+ QVERIFY(scaled.height() < own.height());
+
+ // Floored rather than collapsing to nothing: the corner radius is half the
+ // height, so a chip with no horizontal padding has its text on the curve.
+ const QSize tiny = TagChip::sizeFor(siblingMetrics, tag, 0.0);
+ QVERIFY2(tiny.width() > siblingMetrics.horizontalAdvance(tag),
+ "a zero scale left no horizontal padding at all, so the text sits "
+ "on the chip's rounded end");
+}
+
QTEST_MAIN(TestCardDelegate)
#include "test_carddelegate.moc"