2
* This file is part of Maliit Plugins
4
* Copyright (C) 2012 Openismus GmbH. All rights reserved.
6
* Contact: maliit-discuss@lists.maliit.org
8
* Redistribution and use in source and binary forms, with or without modification,
9
* are permitted provided that the following conditions are met:
11
* Redistributions of source code must retain the above copyright notice, this list
12
* of conditions and the following disclaimer.
13
* Redistributions in binary form must reproduce the above copyright notice, this list
14
* of conditions and the following disclaimer in the documentation and/or other materials
15
* provided with the distribution.
16
* Neither the name of Nokia Corporation nor the names of its contributors may be
17
* used to endorse or promote products derived from this software without specific
18
* prior written permission.
20
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23
* THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
#include "coreutils.h"
35
#include "models/key.h"
36
#include "models/keydescription.h"
37
#include "models/keyboard.h"
38
#include "models/styleattributes.h"
39
#include "logic/keyboardloader.h"
40
#include "logic/keyareaconverter.h"
41
#include "logic/style.h"
42
#include "logic/layouthelper.h"
48
using namespace MaliitKeyboard;
50
typedef QSharedPointer<KeyboardLoader> SharedKeyboardLoader;
52
typedef QPair<QString, QString> DictionaryValue;
53
typedef QMap<QString, QString> Dictionary;
55
typedef QPair<Key, KeyDescription> KeyDescriptionPair;
57
Q_DECLARE_METATYPE(Dictionary)
58
Q_DECLARE_METATYPE(Keyboard)
62
SharedKeyboardLoader getLoader(const QString &id)
64
SharedKeyboardLoader loader(new KeyboardLoader);
66
loader->setActiveId(id);
70
Keyboard stringToKeyboard(const QString &str)
77
} expected_char = ExpectFirstSeparator;
81
bool left_spacer(false);
83
Q_FOREACH(const QChar &c, str) {
84
switch (expected_char) {
86
expected_char = ExpectSeparator;
93
KeyDescription key_desc;
98
key_desc.left_spacer = left_spacer;
99
key_desc.right_spacer = false;
101
kb.key_descriptions.append(key_desc);
106
case ExpectFirstSeparator:
107
case ExpectSeparator:
108
expected_char = ExpectKey;
110
switch (c.toLatin1()) {
115
if (not kb.key_descriptions.isEmpty()) {
116
KeyDescription& last(kb.key_descriptions.last());
118
if (last.row == row) {
119
last.right_spacer = true;
126
qFatal("A bug in test - wrong separator (expected either | or space)");
132
qFatal("A bug in test - wrong expected char type.");
137
if (expected_char == ExpectSeparator) {
138
qFatal("A bug in test - last char should be a separator");
145
Dictionary &operator<<(Dictionary &dict, const DictionaryValue &value)
147
dict.insert(value.first, value.second);
151
Keyboard &operator<<(Keyboard &keyboard, const KeyDescriptionPair &value)
153
keyboard.keys.append(value.first);
154
keyboard.key_descriptions.append(value.second);
158
KeyDescriptionPair createActionPair(Key::Action action = Key::ActionInsert,
159
KeyDescription::Icon icon_type = KeyDescription::NoIcon,
160
const QByteArray &icon = "")
165
key.setAction(action);
167
desc.icon = icon_type;
168
return KeyDescriptionPair(key, desc);
171
KeyDescriptionPair createPair(const QString &text,
183
desc.left_spacer = left_spacer;
184
desc.right_spacer = right_spacer;
186
return KeyDescriptionPair(key, desc);
189
void clearKeyboard(Keyboard &kb)
192
kb.key_descriptions.clear();
193
kb.style_name.clear();
196
Key getKey(const QString &text,
197
Key::Action action = Key::ActionInsert)
204
key.setAction(action);
209
} // unnamed namespace
211
class TestLanguageLayoutLoading
217
void compareKeyboards(const Keyboard &kb1, const Keyboard &kb2)
219
QCOMPARE(kb1.keys.size(), kb2.keys.size());
220
QCOMPARE(kb1.key_descriptions.size(), kb2.key_descriptions.size());
221
QCOMPARE(kb1.keys.size(), kb1.key_descriptions.size());
223
for (int iter(0); iter < kb1.keys.size(); ++iter) {
224
QCOMPARE(kb1.keys[iter].label().text(), kb2.keys[iter].label().text());
226
const KeyDescription& kd1(kb1.key_descriptions[iter]);
227
const KeyDescription& kd2(kb2.key_descriptions[iter]);
229
QCOMPARE(kd1.row, kd2.row);
230
QCOMPARE(kd1.left_spacer, kd2.left_spacer);
231
QCOMPARE(kd1.right_spacer, kd2.right_spacer);
235
// QCOMPARE is a macro with "return;" statement in it. So it does not quit
236
// the test immediately on failure when it is used in a function called by
237
// our test routine. So we are adding another ugly macro. Wheee...
238
#define COMPARE_KEYBOARDS(gotten_keyboard, expected_keyboard) \
239
compareKeyboards(gotten_keyboard, expected_keyboard); \
240
if (QTest::currentTestFailed()) { \
244
Q_SLOT void initTestCase()
246
QVERIFY(qputenv("MALIIT_PLUGINS_DATADIR", TEST_DATADIR));
247
QVERIFY(qputenv("MALIIT_KEYBOARD_DATADIR", TEST_MALIIT_KEYBOARD_DATADIR));
248
QVERIFY(qputenv("UBUNTU_KEYBOARD_DATA_DIR", TEST_MALIIT_KEYBOARD_DATADIR));
251
Q_SLOT void testSanity_data()
253
QTest::addColumn<QString>("string_desc");
254
QTest::addColumn<Keyboard>("expected_keyboard");
257
QTest::newRow("Empty string - empty keyboard")
262
QTest::newRow("Complicated string")
265
<< createPair("a", 0, true, true)
266
<< createPair("b", 0, true, true)
267
<< createPair("c", 1, true, false)
268
<< createPair("d", 1, false, false));
272
Q_SLOT void testSanity()
274
QFETCH(QString, string_desc);
275
QFETCH(Keyboard, expected_keyboard);
277
COMPARE_KEYBOARDS(stringToKeyboard(string_desc), expected_keyboard);
280
// Q_SLOT void testGeneral_data()
282
// QTest::addColumn<QString>("keyboard_id");
283
// QTest::addColumn<QString>("expected_keyboard");
284
// QTest::addColumn<QString>("expected_shifted_keyboard");
285
// QTest::addColumn<QString>("expected_number_keyboard");
286
// QTest::addColumn<QString>("expected_phone_number_keyboard");
287
// QTest::addColumn<Dictionary>("expected_dead_keyboards");
288
// QTest::addColumn<Dictionary>("expected_shifted_dead_keyboards");
289
// QTest::addColumn<Dictionary>("expected_extended_keyboards");
290
// QTest::addColumn<QStringList>("expected_symbols_keyboards");
296
// QTest::newRow("General test")
297
// << "general_test1"
303
// << DictionaryValue(QString::fromUtf8("´"), "|q|e|\n p a ")
304
// << DictionaryValue(";", "|q|r|\n p a ")
305
// << DictionaryValue("'", "|q|t|\n p a "))
307
// << DictionaryValue(QString::fromUtf8("´"), "|Q|E|\n p a ")
308
// << DictionaryValue(";", "|Q|r|\n p a ")
309
// << DictionaryValue("'", "|Q|T|\n p a "))
311
// << DictionaryValue("q", "|y|u|\n|i|o|")
312
// << DictionaryValue("Q", "|Y|U|\n|I|O|"))
321
// Q_SLOT void testGeneral()
323
// QFETCH(QString, keyboard_id);
324
// QFETCH(QString, expected_keyboard);
325
// QFETCH(QString, expected_shifted_keyboard);
326
// QFETCH(QString, expected_number_keyboard);
327
// QFETCH(QString, expected_phone_number_keyboard);
328
// QFETCH(Dictionary, expected_dead_keyboards);
329
// QFETCH(Dictionary, expected_shifted_dead_keyboards);
330
// QFETCH(Dictionary, expected_extended_keyboards);
331
// QFETCH(QStringList, expected_symbols_keyboards);
333
// SharedKeyboardLoader loader(getLoader(keyboard_id));
335
// QVERIFY(loader->ids().indexOf(keyboard_id) != -1);
336
// qDebug() << "Keyboard";
337
// COMPARE_KEYBOARDS(loader->keyboard(), stringToKeyboard(expected_keyboard));
338
// qDebug() << "Shifted eyboard";
339
// COMPARE_KEYBOARDS(loader->shiftedKeyboard(), stringToKeyboard(expected_shifted_keyboard));
340
// qDebug() << "Number keyboard";
341
// COMPARE_KEYBOARDS(loader->numberKeyboard(), stringToKeyboard(expected_number_keyboard));
342
// qDebug() << "Phonenumber keyboard";
343
// COMPARE_KEYBOARDS(loader->phoneNumberKeyboard(), stringToKeyboard(expected_phone_number_keyboard));
345
// Q_FOREACH(const QString &dead_text, expected_dead_keyboards.keys()) {
349
// dead_label.setText(dead_text);
350
// dead_key.setLabel(dead_label);
351
// qDebug() << "Dead keyboard for:" << dead_text;
352
// COMPARE_KEYBOARDS(loader->deadKeyboard(dead_key), stringToKeyboard(expected_dead_keyboards[dead_text]));
355
// Q_FOREACH(const QString &dead_text, expected_shifted_dead_keyboards.keys()) {
359
// dead_label.setText(dead_text);
360
// dead_key.setLabel(dead_label);
361
// qDebug() << "Shifted dead keyboard for:" << dead_text;
362
// COMPARE_KEYBOARDS(loader->shiftedDeadKeyboard(dead_key), stringToKeyboard(expected_shifted_dead_keyboards[dead_text]));
365
// for (int iter(0); iter <= expected_symbols_keyboards.size(); ++iter) {
366
// int index(iter % expected_symbols_keyboards.size());
368
// qDebug() << "Symbols keyboard, page:" << iter << "(expected page:" << index << ")";
369
// COMPARE_KEYBOARDS(loader->symbolsKeyboard(iter), stringToKeyboard(expected_symbols_keyboards[index]));
373
// Q_SLOT void testStyle_data()
375
// QTest::addColumn<QString>("keyboard_id");
376
// QTest::addColumn<QString>("expected_style");
378
// QTest::newRow("No style given in xml")
382
// QTest::newRow("Style given in xml")
384
// << "four_symbols";
387
// Q_SLOT void testStyle()
389
// QFETCH(QString, keyboard_id);
390
// QFETCH(QString, expected_style);
392
// SharedKeyboardLoader loader(getLoader(keyboard_id));
393
// QCOMPARE(loader->keyboard().style_name, expected_style);
396
// Q_SLOT void testAction_data()
398
// QTest::addColumn<QString>("keyboard_id");
399
// QTest::addColumn<Keyboard>("expected_keyboard");
403
// QTest::newRow("Implicit insert action")
406
// << createActionPair());
407
// clearKeyboard(kb);
409
// QTest::newRow("Explicit actions")
412
// << createActionPair()
413
// << createActionPair(Key::ActionShift)
414
// << createActionPair(Key::ActionBackspace)
415
// << createActionPair(Key::ActionReturn));
416
// clearKeyboard(kb);
418
// QTest::newRow("Dead action")
421
// << createActionPair(Key::ActionDead));
422
// clearKeyboard(kb);
425
// Q_SLOT void testAction()
427
// QFETCH(QString, keyboard_id);
428
// QFETCH(Keyboard, expected_keyboard);
430
// SharedKeyboardLoader loader(getLoader(keyboard_id));
431
// Keyboard gotten_keyboard(loader->keyboard());
433
// QCOMPARE(gotten_keyboard.keys.size(), expected_keyboard.keys.size());
435
// for (int iter(0); iter < expected_keyboard.keys.size(); ++iter) {
436
// const Key &gotten_key(gotten_keyboard.keys[iter]);
437
// const Key &expected_key(expected_keyboard.keys[iter]);
439
// QCOMPARE(gotten_key.action(), expected_key.action());
443
// Q_SLOT void testIcon_data()
445
// QTest::addColumn<QString>("keyboard_id");
446
// QTest::addColumn<Keyboard>("expected_keyboard");
449
// QTest::newRow("Default icons")
452
// << createActionPair(Key::ActionBackspace, KeyDescription::BackspaceIcon)
453
// << createActionPair(Key::ActionReturn, KeyDescription::ReturnIcon)
454
// << createActionPair(Key::ActionShift, KeyDescription::ShiftIcon)
455
// << createActionPair(Key::ActionClose, KeyDescription::CloseIcon));
456
// clearKeyboard(kb);
458
// QTest::newRow("Custom or empty icons")
461
// << createActionPair()
462
// << createActionPair(Key::ActionInsert, KeyDescription::CustomIcon, "overriden_icon"));
463
// clearKeyboard(kb);
465
// /* TODO: Commented out for now, as it is not not possible to override
466
// icons for some action keys and I don't know if we want to allow
467
// this. I would say that we indeed do want.
469
// QTest::newRow("Overriden icons")
472
// << actionPair(Key::ActionClose, KeyDescription::CustomIcon, "overriden_icon"));
473
// clearKeyboard(kb);
477
// Q_SLOT void testIcon()
479
// QFETCH(QString, keyboard_id);
480
// QFETCH(Keyboard, expected_keyboard);
482
// SharedKeyboardLoader loader(getLoader(keyboard_id));
483
// Keyboard gotten_keyboard(loader->keyboard());
485
// QCOMPARE(gotten_keyboard.keys.size(), expected_keyboard.keys.size());
487
// for (int iter(0); iter < expected_keyboard.keys.size(); ++iter) {
488
// const Key& gotten_key(gotten_keyboard.keys[iter]);
489
// const Key& expected_key(expected_keyboard.keys[iter]);
490
// const KeyDescription& gotten_desc(gotten_keyboard.key_descriptions[iter]);
491
// const KeyDescription& expected_desc(expected_keyboard.key_descriptions[iter]);
493
// QCOMPARE(gotten_key.action(), expected_key.action());
494
// QCOMPARE(gotten_desc.icon, expected_desc.icon);
495
// QCOMPARE(gotten_key.icon(), expected_key.icon());
499
Q_SLOT void testExtended_data()
501
QTest::addColumn<QString>("keyboard_id");
502
QTest::addColumn<Key>("pressed_key");
503
QTest::addColumn<QString>("expected_keyboard");
505
// TODO: we should get rid of this prepending stuff and fix the language
508
QTest::newRow("Extended keyboard for unshifted key (also notice prepending)")
514
// QTest::newRow("Extended keyboard for shifted key (also notice prepending)")
515
// << "extended_test"
519
// QTest::newRow("Ignore spacers in extended keyboard")
520
// << "extended_test"
524
// QTest::newRow("Extended keyboard with multiple rows (also notice lack of prepending)")
525
// << "extended_test"
527
// << "|h|i|\n|j|k|";
529
// QTest::newRow("Extended keyboard for empty label (also notice lack of prepending the key with empty label)")
530
// << "extended_test"
534
QTest::newRow("No extended keyboard for spacebars.")
536
<< getKey("", Key::ActionSpace)
539
// QTest::newRow("No non-action-insert prepending")
540
// << "extended_test"
541
// << getKey("close", Key::ActionClose)
545
Q_SLOT void testExtended()
547
QFETCH(QString, keyboard_id);
548
QFETCH(Key, pressed_key);
549
QFETCH(QString, expected_keyboard);
551
SharedKeyboardLoader loader(getLoader(keyboard_id));
553
COMPARE_KEYBOARDS(loader->extendedKeyboard(pressed_key), stringToKeyboard(expected_keyboard));
556
Q_SLOT void testStylingProfile()
558
const Logic::LayoutHelper::Orientation orientation(Logic::LayoutHelper::Landscape);
560
QCOMPARE(style.availableProfiles().size(), 1);
561
QCOMPARE(style.availableProfiles().first(), QString("test-profile"));
562
QCOMPARE(style.profile(), QString());
563
QCOMPARE(style.attributes()->fontSize(orientation), 0.0);
564
QCOMPARE(style.extendedKeysAttributes()->fontSize(orientation), 0.0);
565
QCOMPARE(style.directory(Style::Images), QString());
566
QCOMPARE(style.directory(Style::Fonts), QString());
567
QCOMPARE(style.directory(Style::Sounds), QString());
569
QSignalSpy profile_changed_spy(&style, SIGNAL(profileChanged()));
570
style.setProfile("test-profile");
571
QCOMPARE(profile_changed_spy.count(), 1);
572
QCOMPARE(style.profile(), QString("test-profile"));
573
QCOMPARE(style.attributes()->fontSize(orientation), 10.0);
574
QCOMPARE(style.extendedKeysAttributes()->fontSize(orientation), 0.0);
576
const QString test_profile_dir(QString::fromLatin1(TEST_MALIIT_KEYBOARD_DATADIR)
577
+ "/styles/test-profile");
578
QCOMPARE(style.directory(Style::Images), test_profile_dir + "/images");
579
QCOMPARE(style.directory(Style::Fonts), test_profile_dir + "/fonts");
580
QCOMPARE(style.directory(Style::Sounds), test_profile_dir + "/sounds");
583
// Q_SLOT void testKeyGeometryStyling_data()
585
// QTest::addColumn<int>("key_index");
586
// QTest::addColumn<QString>("expected_label");
587
// QTest::addColumn<int>("expected_left_distance");
588
// QTest::addColumn<int>("expected_right_distance");
589
// QTest::addColumn<int>("expected_left_edge");
590
// QTest::addColumn<int>("expected_right_edge");
592
// QTest::newRow("1st row: ' a|b ', testing geometry of 'a'.")
593
// << 0 << QString("a") << 25 << 5 << 0 << 50;
595
// QTest::newRow("1st row: ' a|b ', testing geometry of 'b'.")
596
// << 1 << QString("b") << 5 << 25 << 50 << 100;
599
// Q_SLOT void testKeyGeometryStyling()
601
// QFETCH(int, key_index);
602
// QFETCH(QString, expected_label);
603
// QFETCH(int, expected_left_distance);
604
// QFETCH(int, expected_right_distance);
605
// QFETCH(int, expected_left_edge);
606
// QFETCH(int, expected_right_edge);
609
// style.setProfile("test-profile");
610
// StyleAttributes *attributes = style.attributes();
611
// SharedKeyboardLoader loader(getLoader("styling_profile_test"));
612
// Logic::KeyAreaConverter converter(attributes, loader.data());
614
// const KeyArea key_area(converter.keyArea());
615
// const Key key(key_area.keys().at(key_index));
617
// QCOMPARE(key.label().text(), expected_label);
618
// QCOMPARE(key.margins().left(), expected_left_distance);
619
// QCOMPARE(key.margins().right(), expected_right_distance);
620
// QCOMPARE(key.rect().x(), expected_left_edge);
621
// QCOMPARE(key.rect().x() + key.rect().width(), expected_right_edge);
625
QTEST_MAIN(TestLanguageLayoutLoading)
626
#include "ut_language-layout-loading.moc"