#include "TestLayouts.h" #include "layout/KeyGeometry.h" #include "layout/LayoutLoader.h" #include #include using namespace Qt::StringLiterals; 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 templateIsValid() { QString error; QVERIFY2(LayoutLoader::validate(TestLayouts::builtinTemplate(), &error), qPrintable(error)); } void rejectsLettersWithoutRow() { QString error; QVERIFY(!LayoutLoader::parse(R"({"id": "t", "layers": [{"name": "l", "rows": [[{"type": "letters"}]]}]})", &error)); } // Stretch keys must even out rows whatever the keymap's letter counts. void builtLayersHaveEvenRows_data() { QTest::addColumn("xkbLayout"); QTest::addColumn("mode"); for (const char *layout : {"us", "sk", "se", "de", "fr", "ru", "gr"}) { QTest::addRow("%s compact", layout) << QString::fromLatin1(layout) << KeyboardMode::Compact; QTest::addRow("%s full", layout) << QString::fromLatin1(layout) << KeyboardMode::Full; } } void builtLayersHaveEvenRows() { QFETCH(QString, xkbLayout); QFETCH(KeyboardMode, mode); const Layout layout = TestLayouts::build(qPrintable(xkbLayout), mode); for (const Layer &layer : layout.layers) { const QList rects = computeKeyRects(layer, {1000, 300}); qsizetype i = 0; for (const Row &row : layer.rows) { const QRectF first = rects[i]; const QRectF last = rects[i + row.size() - 1]; QVERIFY2(qAbs(first.left() - rects.first().left()) < 0.01, qPrintable(layer.name)); QVERIFY2(qAbs(last.right() - rects[layer.rows.first().size() - 1].right()) < 0.01, qPrintable(layer.name)); i += row.size(); } } } void templateHasKeySections() { const Layout layout = TestLayouts::builtinTemplate(); QStringList ids; for (const Section §ion : layout.sections) ids.append(section.id); QCOMPARE(ids, (QStringList{u"function"_s, u"navigation"_s, u"numpad"_s})); } void parsesKeysymKeys() { QString error; const auto layout = LayoutLoader::parse( R"({"id": "t", "layers": [{"name": "l", "rows": [[{"type": "keysym", "keysym": "Home", "repeat": true}]]}]})", &error); QVERIFY2(layout, qPrintable(error)); const KeyDef &key = layout->layers[0].rows[0][0]; QCOMPARE(key.keysym, quint32(XKB_KEY_Home)); QCOMPARE(key.label, u"Home"); // the keysym name unless labelled QVERIFY(key.repeat); } void rejectsUnknownKeysym() { QString error; QVERIFY(!LayoutLoader::parse( R"({"id": "t", "layers": [{"name": "l", "rows": [[{"type": "keysym", "keysym": "Nope"}]]}]})", &error)); } }; QTEST_GUILESS_MAIN(TestLayoutLoader) #include "tst_layoutloader.moc"