File: tst_displaylabelgroups.cpp

package info (click to toggle)
qtcontacts-sqlite 0.3.20-4
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 3,952 kB
  • sloc: cpp: 32,880; ansic: 1,269; xml: 62; makefile: 32; sh: 18
file content (347 lines) | stat: -rw-r--r-- 12,903 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
/*
 * Copyright (C) 2019 Jolla Ltd.
 * Copyright (C) 2019 - 2020 Open Mobile Platform LLC.
 *
 * You may use this file under the terms of the BSD license as follows:
 *
 * "Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *   * Neither the name of Nemo Mobile nor the names of its contributors
 *     may be used to endorse or promote products derived from this
 *     software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
 */

#include <QtGlobal>

#include <QtTest/QtTest>

#include <QContactManager>
#include <QContact>
#include <QContactName>
#include <QContactDisplayLabel>
#include <QContactPhoneNumber>
#include <QContactHobby>

#include "contactmanagerengine.h"

#include "qtcontacts-extensions.h"
#include "qtcontacts-extensions_manager_impl.h"

QTCONTACTS_USE_NAMESPACE

Q_DECLARE_METATYPE(QList<QContactId>)

class tst_DisplayLabelGroups : public QObject
{
    Q_OBJECT

public:
    tst_DisplayLabelGroups();
    ~tst_DisplayLabelGroups();

public slots:
    void initTestCase();
    void cleanupTestCase();
    void init();
    void cleanup();

private slots:
    void testDisplayLabelGroups();

private:
    QContactManager *m_cm;
    QSet<QContactId> m_createdIds;
};

tst_DisplayLabelGroups::tst_DisplayLabelGroups()
{
    qRegisterMetaType<QContactId>("QContactId");
    qRegisterMetaType<QList<QContactId> >("QList<QContactId>");

    QMap<QString, QString> parameters;
    parameters.insert(QString::fromLatin1("autoTest"), QString::fromLatin1("true"));
    parameters.insert(QString::fromLatin1("mergePresenceChanges"), QString::fromLatin1("true"));
    m_cm = new QContactManager(QString::fromLatin1("org.nemomobile.contacts.sqlite"), parameters);
    QTest::qWait(250); // creating self contact etc will cause some signals to be emitted.  ignore them.
    connect(m_cm, &QContactManager::contactsAdded, [this] (const QList<QContactId> &ids) {
        for (const QContactId &id : ids) {
            this->m_createdIds.insert(id);
        }
    });
}

tst_DisplayLabelGroups::~tst_DisplayLabelGroups()
{
    QTest::qWait(250); // wait for signals.
    if (!m_createdIds.isEmpty()) {
        m_cm->removeContacts(m_createdIds.toList());
        m_createdIds.clear();
    }
    delete m_cm;
}

void tst_DisplayLabelGroups::initTestCase()
{
}

void tst_DisplayLabelGroups::init()
{
}

void tst_DisplayLabelGroups::cleanupTestCase()
{
    QTest::qWait(250); // wait for signals.
    if (!m_createdIds.isEmpty()) {
        m_cm->removeContacts(m_createdIds.toList());
        m_createdIds.clear();
    }
}

void tst_DisplayLabelGroups::cleanup()
{
    QTest::qWait(250); // wait for signals.
    if (!m_createdIds.isEmpty()) {
        m_cm->removeContacts(m_createdIds.toList());
        m_createdIds.clear();
    }
}

#define DETERMINE_ACTUAL_ORDER_AND_GROUPS \
    do { \
        actualOrder.clear(); \
        actualGroups.clear(); \
        for (const QContact &c : sorted) { \
            actualOrder += c.detail<QContactPhoneNumber>().number(); \
            if (c.detail<QContactPhoneNumber>().number().isEmpty()) { \
                actualOrder += c.detail<QContactHobby>().hobby(); \
            } \
            actualGroups += c.detail<QContactDisplayLabel>().value(QContactDisplayLabel__FieldLabelGroup).toString(); \
        } \
    } while (0)

void tst_DisplayLabelGroups::testDisplayLabelGroups()
{
#ifndef HAS_MLITE
    QSKIP("Test has wrong expectations if MLITE is not available");
#endif
    // this test relies on the display label grouping
    // semantics provided by the testdlggplugin.
    // it also relies on the displayLabelGroupPreferredProperty()
    // being the value: QContactName::LastName.
    // `dconf read /org/nemomobile/contacts/group_property`
    // should return 'lastName' rather than 'firstName'.
    // set with:
    // `dconf write /org/nemomobile/contacts/group_property "'lastName'"`

    // create some contacts
    QContact c1, c2, c3, c4, c5, c6, c7, c8, c9;
    QContactName n1, n2, n3, n4, n5, n6, n7, n8, n9;
    QContactDisplayLabel d1, d2, d3, d4, d5, d6, d7, d8, d9;
    QContactPhoneNumber p1, p2, p3, p4, p5, p6, p7, p8, p9;

    n1.setLastName("A"); // length=1, so group='1'
    n1.setFirstName("Test");
    d1.setLabel("Test A Contact");
    p1.setNumber("1");
    c1.saveDetail(&n1);
    c1.saveDetail(&d1);
    c1.saveDetail(&p1);

    n2.setLastName("BBBBB"); // length=5, so group='5'
    n2.setFirstName("Test");
    d2.setLabel("Test B Contact");
    p2.setNumber("2");
    c2.saveDetail(&n2);
    c2.saveDetail(&d2);
    c2.saveDetail(&p2);

    n3.setLastName("CCCCCCCC"); // length=8, so group='E'
    n3.setFirstName("Test");
    d3.setLabel("Test C Contact");
    p3.setNumber("3");
    c3.saveDetail(&n3);
    c3.saveDetail(&d3);
    c3.saveDetail(&p3);

    n4.setLastName("DDDDDDD"); // length=7, so group='O'
    n4.setFirstName("Test");
    d4.setLabel("Test D Contact");
    p4.setNumber("4");
    c4.saveDetail(&n4);
    c4.saveDetail(&d4);
    c4.saveDetail(&p4);

    n5.setLastName("EEE"); // length=3, so group='3'
    n5.setFirstName("Test");
    d5.setLabel("Test E Contact");
    p5.setNumber("5");
    c5.saveDetail(&n5);
    c5.saveDetail(&d5);
    c5.saveDetail(&p5);

    n6.setLastName(""); // length=0, so group='Z'
    n6.setFirstName("");
    d6.setLabel("");
    p6.setNumber("");
    c6.saveDetail(&n6);
    c6.saveDetail(&d6);
    c6.saveDetail(&p6);
    // phone number can be used to generate a display label
    // so don't use that.  but hobby will not!  so use that.
    QContactHobby h6;
    h6.setHobby("6");
    c6.saveDetail(&h6);

    n7.setLastName("GGGGGG"); // length=6, so group='E'
    n7.setFirstName("Aardvark");  // should first-name sort before c3 and c7.
    d7.setLabel("Test G Contact");
    p7.setNumber("7");
    c7.saveDetail(&n7);
    c7.saveDetail(&d7);
    c7.saveDetail(&p7);

    n8.setLastName("HHHH"); // length=4, so group='4'
    n8.setFirstName("Test");
    d8.setLabel("Test H Contact");
    p8.setNumber("8");
    c8.saveDetail(&n8);
    c8.saveDetail(&d8);
    c8.saveDetail(&p8);

    n9.setLastName("CCCCCCCC"); // length = 8, so group='E'; same as c3.
    n9.setFirstName("Abel");  // should first-name sort before c3 but after c7.
    d9.setLabel("Test I Contact");
    p9.setNumber("9");
    c9.saveDetail(&n9);
    c9.saveDetail(&d9);
    c9.saveDetail(&p9);

    // store them to the database
    QVERIFY(m_cm->saveContact(&c1));
    QVERIFY(m_cm->saveContact(&c2));
    QVERIFY(m_cm->saveContact(&c3));
    QVERIFY(m_cm->saveContact(&c4));
    QVERIFY(m_cm->saveContact(&c5));
    QVERIFY(m_cm->saveContact(&c6));
    QVERIFY(m_cm->saveContact(&c7));
    QVERIFY(m_cm->saveContact(&c8));
    QVERIFY(m_cm->saveContact(&c9));

    // Ensure that they sort as we expect the test plugin to sort them.
    // Note that because we only have a single sort order defined,
    // any contacts which have the same display label group
    // may be returned in any order by the backend.
    QContactSortOrder displayLabelGroupSort;
    displayLabelGroupSort.setDetailType(QContactDisplayLabel::Type, QContactDisplayLabel__FieldLabelGroup);
    QList<QContact> sorted = m_cm->contacts(displayLabelGroupSort);
    QString actualOrder, actualGroups;
    DETERMINE_ACTUAL_ORDER_AND_GROUPS;
    // fixup for potential ambiguity in sort order.  3, 7 and 9 all sort equally.
    actualOrder.replace(QChar('7'), QChar('3'));
    actualOrder.replace(QChar('9'), QChar('3'));
    QCOMPARE(actualOrder,  QStringLiteral("615824333"));
    QCOMPARE(actualGroups, QStringLiteral("Z1345OEEE"));


    // Now sort by display label group followed by last name.
    // We expect the same sorting as display-group-only sorting,
    // except that contact 9's last name causes it to be sorted before contact 7.
    // The ordering between 3 and 9 is not disambiguated by the sort order.
    QContactSortOrder lastNameSort;
    lastNameSort.setDetailType(QContactName::Type, QContactName::FieldLastName);
    sorted = m_cm->contacts(QList<QContactSortOrder>() << displayLabelGroupSort << lastNameSort);
    DETERMINE_ACTUAL_ORDER_AND_GROUPS;
    // fixup for potential ambiguity in sort order.  3 and 9 sort equally.
    actualOrder.replace(QChar('9'), QChar('3'));
    QCOMPARE(actualOrder,  QStringLiteral("615824337"));
    QCOMPARE(actualGroups, QStringLiteral("Z1345OEEE"));

    // Now sort by display label group followed by first name.
    // We expect the same sorting as display-group-only sorting,
    // except that contact 7's first name causes it to be sorted before contact 3 and contact 9,
    // and contact 9's first name causes it to be sorted before contact 3.
    QContactSortOrder firstNameSort;
    firstNameSort.setDetailType(QContactName::Type, QContactName::FieldFirstName);
    sorted = m_cm->contacts(QList<QContactSortOrder>() << displayLabelGroupSort << firstNameSort);
    DETERMINE_ACTUAL_ORDER_AND_GROUPS;
    QCOMPARE(actualOrder,  QStringLiteral("615824793"));
    QCOMPARE(actualGroups, QStringLiteral("Z1345OEEE"));

    // Now sort by display label group followed by last name followed by first name.
    // We expect the same sorting as display-group-only sorting,
    // except that contact 9's last name causes it to be sorted before contact 7,
    // and contact 9 should sort before contact 3 due to the first name.
    sorted = m_cm->contacts(QList<QContactSortOrder>() << displayLabelGroupSort << lastNameSort << firstNameSort);
    DETERMINE_ACTUAL_ORDER_AND_GROUPS;
    QCOMPARE(actualOrder,  QStringLiteral("615824937"));
    QCOMPARE(actualGroups, QStringLiteral("Z1345OEEE"));

    // Now add a contact which has a special name such that the test
    // display label group generator plugin will generate a group
    // for it which was previously "unknown", i.e. dynamic group.
    // We expect that group to be added before '#' but after other groups.
    QtContactsSqliteExtensions::ContactManagerEngine *cme =
        QtContactsSqliteExtensions::contactManagerEngine(*m_cm);
    const QStringList oldContactDisplayLabelGroups = cme->displayLabelGroups();
    QSignalSpy dlgcSpy(cme, SIGNAL(displayLabelGroupsChanged(QStringList)));

    QContact c10, c11;
    QContactName n10, n11;
    QContactDisplayLabel d10, d11;
    QContactPhoneNumber p10, p11;

    n10.setLastName("10ten"); // first letter is digit, should be in #.
    n10.setFirstName("Ten");
    d10.setLabel("Test J Contact");
    p10.setNumber("J");
    c10.saveDetail(&n10);
    c10.saveDetail(&d10);
    c10.saveDetail(&p10);

    n11.setLastName("tst_displaylabelgroups_unknown_dlg"); // special case, dynamic group &.
    n11.setFirstName("Eleven");
    d11.setLabel("Test K Contact");
    p11.setNumber("K");
    c11.saveDetail(&n11);
    c11.saveDetail(&d11);
    c11.saveDetail(&p11);

    QVERIFY(m_cm->saveContact(&c10));
    QVERIFY(m_cm->saveContact(&c11));

    // ensure that the resultant sort order is expected
    sorted = m_cm->contacts(QList<QContactSortOrder>() << displayLabelGroupSort << lastNameSort << firstNameSort);
    DETERMINE_ACTUAL_ORDER_AND_GROUPS;
    QCOMPARE(actualOrder,  QStringLiteral("615824937KJ"));
    QCOMPARE(actualGroups, QStringLiteral("Z1345OEEE&#"));

    // should have received signal that display label groups have changed.
    QTest::qWait(250);
    QCOMPARE(dlgcSpy.count(), 1);
    QStringList expected(oldContactDisplayLabelGroups);
    expected.insert(expected.indexOf(QStringLiteral("#")), QStringLiteral("&")); // & group should have been inserted before #.
    QList<QVariant> data = dlgcSpy.takeFirst();
    QCOMPARE(data.first().value<QStringList>(), expected);
}

QTEST_MAIN(tst_DisplayLabelGroups)
#include "tst_displaylabelgroups.moc"