Files
sloposk/tests/tst_layoutloader.cpp
T
ericek111andClaude Opus 5.5 be14bbcc62 Layouts, iPad-style rendering, taps, shift and layers
- JSON layouts (en-US, sv-SE inheriting number/symbol layers via base)
- LayoutModel + KeyGeometry: proportional rows, nearest-key hit testing
- KeyboardSurface: multi-pointer touch/mouse routing to the controller
- KeyboardController + ShiftState: iOS shift/caps-lock, layers, globe, dismiss
- QML view with light/dark iPad palette and drag handle
- DevHooks: SLOPOSK_AUTOTYPE, SLOPOSK_SCREENSHOT for headless checks
- Unit tests for shift, loader, geometry and controller

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 14:50:21 +02:00

92 lines
2.7 KiB
C++

#include "layout/LayoutLoader.h"
#include "layout/LayoutRepository.h"
#include <QTest>
using namespace Qt::StringLiterals;
namespace {
qreal rowUnits(const Row &row)
{
qreal units = 0;
for (const KeyDef &key : row)
units += key.width;
return units;
}
} // namespace
class TestLayoutLoader : public QObject
{
Q_OBJECT
private Q_SLOTS:
void parsesStringAndObjectKeys()
{
QString error;
const auto layout = LayoutLoader::parse(R"({
"id": "t", "layers": [{"name": "letters", "rows": [[
"q",
{"label": "e", "flick": "3", "alternates": ["é", "è"]},
{"type": "backspace", "width": 1.5}
]]}]
})", &error);
QVERIFY2(layout, qPrintable(error));
const Row &row = layout->layers.first().rows.first();
QCOMPARE(row.size(), 3);
QCOMPARE(row[0].label, u"q");
QCOMPARE(row[1].flick, u"3");
QCOMPARE(row[1].alternates, QStringList({u"é"_s, u"è"_s}));
QCOMPARE(row[2].type, KeyType::Backspace);
QCOMPARE(row[2].width, 1.5);
}
void rejectsUnknownKeyType()
{
QString error;
QVERIFY(!LayoutLoader::parse(R"({"id": "t", "layers": [{"name": "l", "rows": [[{"type": "warp"}]]}]})", &error));
QVERIFY(error.contains(u"warp"));
}
void rejectsMissingId()
{
QString error;
QVERIFY(!LayoutLoader::parse(R"({"layers": []})", &error));
}
void validateCatchesUnknownLayerTarget()
{
QString error;
const auto layout = LayoutLoader::parse(
R"({"id": "t", "layers": [{"name": "l", "rows": [[{"type": "layer", "target": "nope"}]]}]})", &error);
QVERIFY(layout);
QVERIFY(!LayoutLoader::validate(*layout, &error));
}
void builtinLayoutsAreConsistent()
{
Q_INIT_RESOURCE(layouts);
LayoutRepository repo;
repo.loadDirectory(u":/layouts"_s);
repo.finalize({});
QVERIFY(repo.indexOf(u"en-US"_s) >= 0);
QVERIFY(repo.indexOf(u"sv-SE"_s) >= 0);
for (const Layout &layout : repo.layouts()) {
QVERIFY2(layout.layer(u"numbers"_s), qPrintable(layout.id)); // sv-SE gets it from its base
for (const Layer &layer : layout.layers) {
const qreal expected = rowUnits(layer.rows.first());
for (const Row &row : layer.rows) {
QVERIFY2(qFuzzyCompare(rowUnits(row), expected),
qPrintable(u"%1/%2: rows differ in width"_s.arg(layout.id, layer.name)));
}
}
}
}
};
QTEST_GUILESS_MAIN(TestLayoutLoader)
#include "tst_layoutloader.moc"