1/****************************************************************************
2**
3** Copyright (C) 2015 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** As a special exception, The Qt Company gives you certain additional
27** rights. These rights are described in The Qt Company LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33
34//TESTED_COMPONENT=src/versit
35
36#include "tst_qversitcontactexporter.h"
37#include <QtVersit/qversitcontactexporter.h>
38#include <QtVersit/qversitdocument.h>
39#include <QtVersit/qversitproperty.h>
40#include <QtContacts/qcontacts.h>
41#include <QtContacts/qcontactmanagerengine.h>
42#include <QString>
43#include <QStringList>
44#include <QList>
45#include <QPixmap>
46#include <QtTest/QtTest>
47
48QTCONTACTS_USE_NAMESPACE
49QTVERSIT_USE_NAMESPACE
50
51class MyQVersitContactExporterDetailHandler : public QVersitContactExporterDetailHandler
52{
53public:
54 MyQVersitContactExporterDetailHandler() : mPreProcess(false)
55 {
56 }
57
58 bool preProcessDetail(const QContact& contact,
59 const QContactDetail& detail,
60 QVersitDocument* document)
61 {
62 Q_UNUSED(contact)
63 Q_UNUSED(document)
64 mPreProcessedDetails.append(t: detail);
65 return mPreProcess;
66 }
67
68 bool postProcessDetail(const QContact& contact,
69 const QContactDetail& detail,
70 bool alreadyProcessed,
71 QVersitDocument* document)
72 {
73 Q_UNUSED(contact)
74 Q_UNUSED(document)
75 if (!alreadyProcessed)
76 mUnknownDetails.append(t: detail);
77 else
78 mPostProcessedDetails.append(t: detail);
79 return false;
80 }
81
82 void clear()
83 {
84 mPreProcess = false;
85 mDefinitionNamesToProcess.clear();
86 mUnknownDetails.clear();
87 mPreProcessedDetails.clear();
88 mPostProcessedDetails.clear();
89 }
90
91 // a hook to control what preProcess returns:
92 bool mPreProcess;
93 QStringList mDefinitionNamesToProcess;
94 QList<QContactDetail> mUnknownDetails;
95 QList<QContactDetail> mPreProcessedDetails;
96 QList<QContactDetail> mPostProcessedDetails;
97};
98
99/* This class just logs the arguments to the last call to postProcessDetail */
100class MyQVersitContactExporterDetailHandlerV2 : public QVersitContactExporterDetailHandlerV2
101{
102public:
103 MyQVersitContactExporterDetailHandlerV2()
104 {
105 }
106
107 void detailProcessed(const QContact& contact,
108 const QContactDetail& detail,
109 const QVersitDocument& document,
110 QSet<int>* processedFields,
111 QList<QVersitProperty>* toBeRemoved,
112 QList<QVersitProperty>* toBeAdded)
113 {
114 mContact = contact;
115 mDetail = detail;
116 mDocument = document;
117 mProcessedFields = *processedFields;
118 mToBeRemoved = *toBeRemoved;
119 mToBeAdded = *toBeAdded;
120 }
121
122 void contactProcessed(const QContact& contact, QVersitDocument* document)
123 {
124 mEndContact = contact;
125 mEndDocument = *document;
126 }
127
128 QContact mContact;
129 QContactDetail mDetail;
130 QSet<int> mProcessedFields;
131 QVersitDocument mDocument;
132 QList<QVersitProperty> mToBeRemoved;
133 QList<QVersitProperty> mToBeAdded;
134
135 QContact mEndContact;
136 QVersitDocument mEndDocument;
137};
138
139class MyQVersitResourceHandler : public QVersitResourceHandler
140{
141public:
142 MyQVersitResourceHandler()
143 : mLoadResourceCalled(false),
144 mLoadSuccess(true)
145 {
146 }
147
148 bool loadResource(const QString& location, QByteArray* contents, QString* mimeType)
149 {
150 mLocation = location;
151 *contents = mSimulatedData;
152 *mimeType = mSimulatedMimeType;
153 mLoadResourceCalled = true;
154 return mLoadSuccess;
155 }
156
157 bool saveResource(const QByteArray &contents, const QVersitProperty &property, QString *location)
158 {
159 Q_UNUSED(contents)
160 Q_UNUSED(property)
161 Q_UNUSED(location)
162 return false;
163 }
164
165 void clear()
166 {
167 mSimulatedData.clear();
168 mSimulatedMimeType.clear();
169 mLocation.clear();
170 mLoadResourceCalled = false;
171 mLoadSuccess = true;
172 }
173
174 QByteArray mSimulatedData;
175 QString mSimulatedMimeType;
176 QString mLocation;
177 bool mLoadResourceCalled;
178 bool mLoadSuccess; // A hook to control what loadResource returns.
179};
180
181const static QByteArray SAMPLE_GIF(QByteArray::fromBase64(
182 base64: "R0lGODlhEgASAIAAAAAAAP///yH5BAEAAAEALAAAAAASABIAAAIdjI+py+0G"
183 "wEtxUmlPzRDnzYGfN3KBaKGT6rDmGxQAOw=="));
184
185const QString TEST_PHOTO_FILE(QStringLiteral("versitTest001.jpg"));
186const QString TEST_AUDIO_FILE(QStringLiteral("versitTest001.wav"));
187
188// Checks that the property has a value of the given expectedType and the given expectedValue.
189#define CHECK_VALUE(property,expectedValueType,expectedValue) {\
190 QCOMPARE(property.valueType(), expectedValueType); \
191 QVariant value = property.variantValue(); \
192 QCOMPARE(value.type(), QVariant::StringList); \
193 QCOMPARE(value.toStringList(), expectedValue); \
194}
195#define CHECK_FLOATING_POINT_VALUE(property, expectedValueType, expectedValue, isDouble) {\
196 QCOMPARE(property.valueType(), expectedValueType); \
197 QVariant value = property.variantValue(); \
198 QCOMPARE(value.type(), QVariant::StringList); \
199 QVERIFY(value.toStringList().size() == 2); \
200 QVERIFY(expectedValue.size() == 2); \
201 QString actualString = value.toStringList().at(1); \
202 actualString.replace('[',"").replace(']',"").replace('\n', ""); \
203 QString expectedString = expectedValue.at(1); \
204 expectedString.replace('[',"").replace(']',"").replace('\n', ""); \
205 if (isDouble) { \
206 double actualD = actualString.toDouble(); \
207 double expectedD = expectedString.toDouble(); \
208 QCOMPARE(value.toStringList().first(), expectedValue.first()); /* name */ \
209 QCOMPARE(actualD, expectedD); /* value */ \
210 } else { \
211 float actualF = actualString.toFloat(); \
212 float expectedF = expectedString.toFloat(); \
213 QCOMPARE(value.toStringList().first(), expectedValue.first()); /* name */ \
214 QCOMPARE(actualF, expectedF); /* value */ \
215 } \
216}
217
218
219void tst_QVersitContactExporter::init()
220{
221 mExporter = new QVersitContactExporter();
222 mResourceHandler = new MyQVersitResourceHandler;
223 mExporter->setResourceHandler(mResourceHandler);
224}
225
226void tst_QVersitContactExporter::cleanup()
227{
228 QVERIFY(mExporter->resourceHandler() == mResourceHandler);
229 mExporter->setResourceHandler(0);
230 delete mResourceHandler;
231 delete mExporter;
232}
233
234void tst_QVersitContactExporter::testConvertContact()
235{
236 QContact contact;
237
238 // Adding name to the contact
239 QContactName name;
240 name.setFirstName(QStringLiteral("Moido"));
241 contact.saveDetail(detail: &name);
242
243 // Adding phone number to the Contact.
244 QContactPhoneNumber phoneNumber;
245 phoneNumber.setNumber(QStringLiteral("12345678"));
246 contact.saveDetail(detail: &phoneNumber);
247
248 // Convert contact into versit properties
249 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
250 QList<QVersitDocument> documents = mExporter->documents();
251
252 // Contact should have N and TEL properties
253 QCOMPARE(documents.size(), 1);
254 QCOMPARE(documents.first().properties().count(), 2);
255}
256
257void tst_QVersitContactExporter::testEmptyContact()
258{
259 QContact contact1; // empty
260 QList<QContact> contacts;
261 contacts << contact1;
262
263 QVERIFY(!mExporter->exportContacts(contacts)); // Fail on empty contact1
264 QMap<int, QVersitContactExporter::Error> errorMap = mExporter->errorMap();
265 QCOMPARE(errorMap.size(), 1);
266 QList<QVersitDocument> documents = mExporter->documents();
267 QCOMPARE(documents.size(), 0); // empty contact not exported
268}
269
270void tst_QVersitContactExporter::testContactDetailHandler()
271{
272 int invalidData = 123456;
273 MyQVersitContactExporterDetailHandler detailHandler;;
274 mExporter->setDetailHandler(&detailHandler);
275
276 // Test1: Un-supported Avatar Test
277 QContact contact(createContactWithName(QStringLiteral("asdf")));
278 QContactDetail unknownDetail;
279 unknownDetail.setValue(field: invalidData, QStringLiteral("Detail"));
280 contact.saveDetail(detail: &unknownDetail);
281 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
282 QVersitDocument document = mExporter->documents().first();
283 QCOMPARE(countProperties(document), 0);
284 QList<QContactDetail> unknownDetails = detailHandler.mUnknownDetails;
285 QVERIFY(unknownDetails.size() > 0);
286 QContactDetail::DetailType type = unknownDetail.type();
287 QContactDetail detail = findDetailByType(details: unknownDetails,search: type);
288 QCOMPARE(type, detail.type());
289
290 // Test2: Un-supported Online Account
291 QContactOnlineAccount onlineAccount;
292 QString testUri = QStringLiteral("sip:abc@temp.com");
293 onlineAccount.setAccountUri(testUri);
294 QList<int> expectedSubtypes;
295
296 expectedSubtypes << invalidData;
297
298 onlineAccount.setSubTypes(expectedSubtypes);
299 contact.saveDetail(detail: &onlineAccount);
300 detailHandler.clear();
301 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
302 document = mExporter->documents().first();
303 QCOMPARE(countProperties(document), 0);
304 unknownDetails = detailHandler.mUnknownDetails;
305 QVERIFY(unknownDetails.size() > 0);
306 type = onlineAccount.type();
307 detail = findDetailByType(details: unknownDetails, search: type);
308 QCOMPARE(type, detail.type());
309
310 QVERIFY(mExporter->detailHandler() == &detailHandler);
311 mExporter->setDetailHandler(static_cast<QVersitContactExporterDetailHandler*>(0));
312}
313
314void tst_QVersitContactExporter::testContactDetailHandlerV2()
315{
316 int invalidData = 123456;
317 MyQVersitContactExporterDetailHandlerV2 detailHandler;
318 mExporter->setDetailHandler(&detailHandler);
319
320 QContact contact(createContactWithName(QStringLiteral("asdf")));
321 QContactPhoneNumber phone;
322 phone.setNumber(QStringLiteral("1234"));
323 phone.setValue(field: invalidData, QStringLiteral("Value"));
324 contact.saveDetail(detail: &phone);
325 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
326
327 QCOMPARE(detailHandler.mProcessedFields.size(), 3);
328 QVERIFY(detailHandler.mProcessedFields.contains(QContactPhoneNumber::FieldContext));
329 QVERIFY(detailHandler.mProcessedFields.contains(QContactPhoneNumber::FieldSubTypes));
330 QVERIFY(detailHandler.mProcessedFields.contains(QContactPhoneNumber::FieldNumber));
331 QVersitProperty expectedProperty;
332 expectedProperty.setName(QStringLiteral("TEL"));
333 expectedProperty.setValue(QStringLiteral("1234"));
334 QCOMPARE(detailHandler.mToBeAdded.size(), 1);
335 QCOMPARE(detailHandler.mToBeAdded.first(), expectedProperty);
336
337 mExporter->setDetailHandler(static_cast<QVersitContactExporterDetailHandlerV2*>(0));
338}
339
340void tst_QVersitContactExporter::testEncodeName()
341{
342 QContact contact;
343 QContactName name;
344
345 // Test 1: An empty contact - can't be exported
346 QVERIFY(!mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard21Type));
347 QCOMPARE(mExporter->documents().size(), 0);
348
349 // Test 2: Special characters are NOT backslash escaped by the exporter, only by the writer.
350 name.setFirstName(QStringLiteral("Fi;rst")); // check that semicolon is left intact
351 name.setLastName(QStringLiteral("Last"));
352 name.setMiddleName(QStringLiteral("Middle"));
353 name.setPrefix(QStringLiteral("Prefix"));
354 name.setSuffix(QStringLiteral("Suffix"));
355 contact.saveDetail(detail: &name);
356 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard21Type));
357 QVersitDocument document = mExporter->documents().first();
358 QCOMPARE(document.properties().count(), 1);
359
360 QVersitProperty nameProperty = findPropertyByName(document, QStringLiteral("N"));
361 QCOMPARE(nameProperty.parameters().count(), 0);
362 QCOMPARE(nameProperty.name(), QStringLiteral("N"));
363 CHECK_VALUE(nameProperty, QVersitProperty::CompoundType,
364 QStringList() << QStringLiteral("Last") << QStringLiteral("Fi;rst")
365 << QStringLiteral("Middle") << QStringLiteral("Prefix") << QStringLiteral("Suffix"));
366
367 // Test 3: Just QContactName
368 contact.clearDetails();
369 name = QContactName();
370 name.setFirstName(QStringLiteral("First"));
371 name.setLastName(QStringLiteral("Last"));
372 name.setMiddleName(QStringLiteral("Middle"));
373 contact.saveDetail(detail: &name);
374 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard21Type));
375 document = mExporter->documents().first();
376 QCOMPARE(document.properties().count(), 1);
377 // Unlike older versions, FN is not generated
378 nameProperty = findPropertyByName(document, QStringLiteral("N"));
379 QCOMPARE(nameProperty.name(), QStringLiteral("N"));
380 CHECK_VALUE(nameProperty, QVersitProperty::CompoundType, QStringList()
381 << QStringLiteral("Last") << QStringLiteral("First") << QStringLiteral("Middle")
382 << QString() << QString());
383
384 // Test 4: Just nickname
385 contact.clearDetails();
386 QContactNickname nickname;
387 nickname.setNickname(QStringLiteral("Nickname"));
388 contact.saveDetail(detail: &nickname);
389 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard21Type));
390 document = mExporter->documents().first();
391 QCOMPARE(document.properties().count(), 2); // N and NICKNAME
392 // Unlike older versions, FN is not generated
393 nameProperty = findPropertyByName(document, QStringLiteral("N"));
394 QCOMPARE(nameProperty.name(), QStringLiteral("N"));
395 CHECK_VALUE(nameProperty, QVersitProperty::CompoundType, QStringList()
396 << QString() << QString() << QString()
397 << QString() << QString());
398
399 // Test 5: Just organization
400 contact.clearDetails();
401 QContactOrganization org;
402 org.setName(QStringLiteral("Organization"));
403 contact.saveDetail(detail: &org);
404 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard21Type));
405 document = mExporter->documents().first();
406 QCOMPARE(document.properties().count(), 2); // N and ORG
407 // Unlike older versions, FN is not generated
408 nameProperty = findPropertyByName(document, QStringLiteral("N"));
409 QCOMPARE(nameProperty.name(), QStringLiteral("N"));
410 CHECK_VALUE(nameProperty, QVersitProperty::CompoundType, QStringList()
411 << QString() << QString() << QString()
412 << QString() << QString());
413
414 // Test 6: Display label but no name set
415 contact.clearDetails();
416 QContactDisplayLabel displaylabel;
417 displaylabel.setLabel(QStringLiteral("Bobby Tables"));
418 contact.saveDetail(detail: &displaylabel);
419 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard21Type));
420 document = mExporter->documents().first();
421 QCOMPARE(document.properties().count(), 2); // N
422 // Unlike older versions, FN is not generated from display label
423 nameProperty = findPropertyByName(document, QStringLiteral("N"));
424 QCOMPARE(nameProperty.name(), QStringLiteral("N"));
425 CHECK_VALUE(nameProperty, QVersitProperty::CompoundType, QStringList()
426 << QString() << QString() << QString() << QString() << QString());
427}
428
429void tst_QVersitContactExporter::testEncodePhoneNumber()
430{
431 QContact contact(createContactWithName(QStringLiteral("asdf")));
432 QContactPhoneNumber phoneNumber;
433 QContactPhoneNumber::SubType expectedSubType = QContactPhoneNumber::SubTypeMobile;
434 QList<int> expectedSubTypes;
435 expectedSubTypes << expectedSubType;
436 phoneNumber.setNumber(QStringLiteral("12345678"));
437 phoneNumber.setContexts(QContactDetail::ContextHome);
438 phoneNumber.setSubTypes(expectedSubTypes);
439 contact.saveDetail(detail: &phoneNumber);
440 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
441 QVersitDocument document = mExporter->documents().first();
442 QCOMPARE(countProperties(document), 1);
443 QVersitProperty property = findPropertyByName(document, QStringLiteral("TEL"));
444 QVERIFY(!property.isEmpty());
445 // Check parameters
446 QCOMPARE(property.parameters().count(), 2);
447 QVERIFY(property.parameters().contains(
448 QStringLiteral("TYPE"),QStringLiteral("HOME")));
449 QVERIFY(property.parameters().contains(
450 QStringLiteral("TYPE"),QStringLiteral("CELL")));
451 // Check value
452 QCOMPARE(property.value(), phoneNumber.number());
453
454 QContactPhoneNumber assistantNumber;
455 assistantNumber.setNumber(QStringLiteral("4321"));
456 assistantNumber.setContexts(QContactDetail::ContextWork);
457 expectedSubTypes.clear();
458 expectedSubTypes << QContactPhoneNumber::SubTypeAssistant
459 << QContactPhoneNumber::SubTypeLandline;
460 assistantNumber.setSubTypes(expectedSubTypes);
461 contact.saveDetail(detail: &assistantNumber);
462 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
463 document = mExporter->documents().first();
464 QCOMPARE(countProperties(document), 2);
465 property = findPropertyByName(document, QStringLiteral("X-ASSISTANT-TEL"));
466 QVERIFY(!property.isEmpty());
467 QCOMPARE(property.parameters().count(), 2);
468 QVERIFY(property.parameters().contains(
469 QStringLiteral("TYPE"),QStringLiteral("WORK")));
470 QVERIFY(property.parameters().contains(
471 QStringLiteral("TYPE"), QStringLiteral("VOICE")));
472 QCOMPARE(property.value(), assistantNumber.number());
473}
474
475void tst_QVersitContactExporter::testEncodeEmailAddress()
476{
477 QContact contact(createContactWithName(QStringLiteral("asdf")));
478 QContactEmailAddress email;
479 email.setEmailAddress(QStringLiteral("test@test"));
480 email.setContexts(QContactDetail::ContextHome);
481 contact.saveDetail(detail: &email);
482 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
483 QVersitDocument document = mExporter->documents().first();
484 QCOMPARE(countProperties(document), 1);
485 QVersitProperty property = findPropertyByName(document, QStringLiteral("EMAIL"));
486 QVERIFY(!property.isEmpty());
487 // Check parameters
488 QCOMPARE(property.parameters().count(), 1);
489 QVERIFY(property.parameters().contains(
490 QStringLiteral("TYPE"),QStringLiteral("HOME")));
491 // Check value
492 QCOMPARE(property.value(), email.emailAddress());
493}
494
495void tst_QVersitContactExporter::testEncodeStreetAddress()
496{
497 QContact contact(createContactWithName(QStringLiteral("asdf")));
498 QContactAddress address;
499 QContactAddress::SubType expectedSubType;
500 QList<int> expectedSubTypes;
501 expectedSubType = QContactAddress::SubTypePostal;
502 expectedSubTypes << expectedSubType;
503 address.setPostOfficeBox(QStringLiteral("1234"));
504 address.setCountry(QStringLiteral("Finland"));
505 address.setPostcode(QStringLiteral("00440"));
506 // Special characters are not escaped by the exporter, but by the writer
507 address.setStreet(QStringLiteral("HKKI; 1X 90"));
508 address.setLocality(QStringLiteral("Helsinki"));
509 address.setContexts(QContactDetail::ContextHome);
510 address.setSubTypes(expectedSubTypes);
511 contact.saveDetail(detail: &address);
512 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard21Type));
513 QVersitDocument document = mExporter->documents().first();
514 QCOMPARE(countProperties(document), 1);
515 QVersitProperty property = findPropertyByName(document, QStringLiteral("ADR"));
516 QVERIFY(!property.isEmpty());
517 // Check parameters
518 QCOMPARE(property.parameters().count(), 2);
519 QVERIFY(property.parameters().contains(
520 QStringLiteral("TYPE"),QStringLiteral("HOME")));
521 QVERIFY(property.parameters().contains(
522 QStringLiteral("TYPE"),QStringLiteral("POSTAL")));
523 // Check name
524 QCOMPARE(property.name(), QStringLiteral("ADR"));
525 CHECK_VALUE(property, QVersitProperty::CompoundType,
526 QStringList() << QStringLiteral("1234") << QString() << QStringLiteral("HKKI; 1X 90")
527 << QStringLiteral("Helsinki") << QString() << QStringLiteral("00440")
528 << QStringLiteral("Finland"));
529}
530
531void tst_QVersitContactExporter::testEncodeUrl()
532{
533 QContact contact(createContactWithName(QStringLiteral("asdf")));
534 QContactUrl url;
535 url.setUrl(QStringLiteral("http://www.myhome.com"));
536 url.setContexts(QContactDetail::ContextHome);
537 url.setSubType(QContactUrl::SubTypeHomePage);
538 contact.saveDetail(detail: &url);
539 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
540 QVersitDocument document = mExporter->documents().first();
541 QCOMPARE(countProperties(document), 1);
542 QVersitProperty property = findPropertyByName(document, QStringLiteral("URL"));
543 QVERIFY(!property.isEmpty());
544 // Check parameters
545 QCOMPARE(property.parameters().count(), 1);
546 QVERIFY(property.parameters().contains(
547 QStringLiteral("TYPE"),QStringLiteral("HOME")));
548 // Check value
549 QCOMPARE(property.value(), url.url());
550}
551
552void tst_QVersitContactExporter::testEncodeUid()
553{
554 QContact contact(createContactWithName(QStringLiteral("asdf")));
555 QContactGuid guid;
556
557 guid.setContexts(QContactDetail::ContextHome);
558 guid.setGuid(QStringLiteral("0101222"));
559 contact.saveDetail(detail: &guid);
560 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard21Type));
561 QVersitDocument document = mExporter->documents().first();
562 QCOMPARE(countProperties(document), 1);
563 QVersitProperty property = findPropertyByName(document, QStringLiteral("UID"));
564 QVERIFY(!property.isEmpty());
565 // Check parameters
566 // Contexts are not allowed for UID
567 QCOMPARE(property.parameters().count(), 0);
568 // Check value
569 QCOMPARE(property.value(), guid.guid());
570}
571
572void tst_QVersitContactExporter::testEncodeRev()
573{
574 QContact contact(createContactWithName(QStringLiteral("asdf")));
575 QContactTimestamp timeStamp;
576
577 // Last modified time found
578 QDateTime revisionTime =
579 QDateTime::fromString(
580 QStringLiteral("M1d1y200906:01:02"),
581 QStringLiteral("'M'M'd'd'y'yyyyhh:mm:ss"));
582 revisionTime.setTimeSpec(Qt::UTC);
583 timeStamp.setLastModified(revisionTime);
584 // Contexts not allowed in REV property, check that they are not added
585 timeStamp.setContexts(QContactDetail::ContextHome);
586 contact.saveDetail(detail: &timeStamp);
587 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
588 QVersitDocument document = mExporter->documents().first();
589 QCOMPARE(countProperties(document), 1);
590 QVersitProperty property = findPropertyByName(document, QStringLiteral("REV"));
591 QVERIFY(!property.isEmpty());
592 QCOMPARE(property.parameters().count(), 0);
593 QString expectedValueUTCEncoded = QStringLiteral("2009-01-01T06:01:02Z");
594 QCOMPARE(property.value(), expectedValueUTCEncoded);
595
596 // Last modified time not found, use the creation time
597 QDateTime emptyTime;
598 timeStamp.setLastModified(emptyTime);
599 timeStamp.setCreated(revisionTime);
600 contact.saveDetail(detail: &timeStamp);
601 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
602 document = mExporter->documents().first();
603 QCOMPARE(countProperties(document), 1);
604 property = findPropertyByName(document, QStringLiteral("REV"));
605 QVERIFY(!property.isEmpty());
606 QCOMPARE(property.value(), expectedValueUTCEncoded);
607
608 // Last modified time found, Local Time spec not UTC
609 QDateTime localTime;
610 revisionTime.setTimeSpec(Qt::LocalTime);
611 timeStamp.setLastModified(revisionTime);
612 localTime.setTimeSpec(Qt::LocalTime);
613 timeStamp.setCreated(localTime);
614 contact.saveDetail(detail: &timeStamp);
615 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
616 document = mExporter->documents().first();
617 QCOMPARE(countProperties(document), 1);
618 property = findPropertyByName(document, QStringLiteral("REV"));
619 QVERIFY(!property.isEmpty());
620 QString expectedValueEncoded = QStringLiteral("2009-01-01T06:01:02");
621 QCOMPARE(property.value(), expectedValueEncoded);
622
623 // Last modified time not found, creation time not found
624 timeStamp.setLastModified(emptyTime);
625 timeStamp.setCreated(emptyTime);
626 contact.saveDetail(detail: &timeStamp);
627 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
628 document = mExporter->documents().first();
629 QCOMPARE(countProperties(document), 0);
630}
631
632void tst_QVersitContactExporter::testEncodeVersion()
633{
634 QContact contact(createContactWithName(QStringLiteral("asdf")));
635 QContactVersion version;
636 int sequenceNumber = 4711;
637 QByteArray extendedVersion("134f23dbb2");
638 version.setSequenceNumber(sequenceNumber);
639 version.setExtendedVersion(extendedVersion);
640 // Contexts not allowed in X-QTPROJECT-VERSION property, check that they are not added.
641 version.setContexts(QContactDetail::ContextHome);
642 contact.saveDetail(detail: &version);
643 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
644 QVersitDocument document = mExporter->documents().first();
645 QCOMPARE(countProperties(document), 1);
646 QVersitProperty property = findPropertyByName(document, QStringLiteral("X-QTPROJECT-VERSION"));
647 QVERIFY(!property.isEmpty());
648 QCOMPARE(property.parameters().count(), 0);
649 CHECK_VALUE(property, QVersitProperty::CompoundType,
650 QStringList() << QStringLiteral("4711") << QStringLiteral("134f23dbb2"));
651}
652
653void tst_QVersitContactExporter::testEncodeBirthDay()
654{
655 QContact contact(createContactWithName(QStringLiteral("asdf")));
656 QDate date(2009,1,1);
657 QContactBirthday birthDay;
658 birthDay.setDate(date);
659 // Contexts not allowed in BDAY property, check that they are not added
660 birthDay.setContexts(QContactDetail::ContextHome);
661 contact.saveDetail(detail: &birthDay);
662 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
663 QVersitDocument document = mExporter->documents().first();
664 QCOMPARE(countProperties(document), 1);
665 QVersitProperty property = findPropertyByName(document, QStringLiteral("BDAY"));
666 QVERIFY(!property.isEmpty());
667 QCOMPARE(property.parameters().count(), 0);
668 QCOMPARE(property.value(), QStringLiteral("2009-01-01"));
669
670 birthDay.setDateTime(QDateTime(QDate(2009, 1, 1), QTime(1, 2, 3)));
671 contact.saveDetail(detail: &birthDay);
672 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
673 document = mExporter->documents().first();
674 property = findPropertyByName(document, QStringLiteral("BDAY"));
675 QCOMPARE(property.value(), QStringLiteral("2009-01-01T01:02:03"));
676}
677
678void tst_QVersitContactExporter::testEncodeNote()
679{
680 QContact contact(createContactWithName(QStringLiteral("asdf")));
681 QContactNote note;
682 note.setNote(QStringLiteral("My Note"));
683 // Contexts not allowed in NOTE property, check that they are not added
684 note.setContexts(QContactDetail::ContextHome);
685 contact.saveDetail(detail: &note);
686 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
687 QVersitDocument document = mExporter->documents().first();
688 QCOMPARE(countProperties(document), 1);
689 QVersitProperty property = findPropertyByName(document, QStringLiteral("NOTE"));
690 QVERIFY(!property.isEmpty());
691 QCOMPARE(property.parameters().count(), 0);
692 QCOMPARE(property.value(), note.note());
693}
694
695void tst_QVersitContactExporter::testEncodeGeoLocation()
696{
697 QContact contact(createContactWithName(QStringLiteral("asdf")));
698 QContactGeoLocation geoLocation;
699 QString longitude = QStringLiteral("99.9");
700 geoLocation.setLongitude(longitude.toDouble());
701 QString latitude = QStringLiteral("98.9");
702 geoLocation.setLatitude(latitude.toDouble());
703 // Contexts not allowed in GEO property, check that they are not added
704 geoLocation.setContexts(QContactDetail::ContextHome);
705 contact.saveDetail(detail: &geoLocation);
706 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
707 QVersitDocument document = mExporter->documents().first();
708 QCOMPARE(countProperties(document), 1);
709 QVersitProperty property = findPropertyByName(document, QStringLiteral("GEO"));
710 QVERIFY(!property.isEmpty());
711 QCOMPARE(property.parameters().count(), 0);
712 QCOMPARE(property.name(), QStringLiteral("GEO"));
713 CHECK_VALUE(property, QVersitProperty::CompoundType,
714 QStringList() << QStringLiteral("98.9") << QStringLiteral("99.9"));
715}
716
717void tst_QVersitContactExporter::testEncodeOrganization()
718{
719 QContact contact(createContactWithName(QStringLiteral("asdf")));
720 QContactOrganization organization;
721 QVersitDocument document;
722 QVersitProperty property;
723 QString title(QStringLiteral("Developer"));
724
725 // TITLE
726 organization.setTitle(title);
727 contact.saveDetail(detail: &organization);
728 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
729 document = mExporter->documents().first();
730 QCOMPARE(countProperties(document), 1);
731 property = findPropertyByName(document, QStringLiteral("TITLE"));
732 QVERIFY(!property.isEmpty());
733 QCOMPARE(property.value(), title);
734
735 // ORG with name
736 organization.setTitle(QString());
737 organization.setName(QStringLiteral("Nokia"));
738 contact.saveDetail(detail: &organization);
739 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
740 document = mExporter->documents().first();
741 QCOMPARE(countProperties(document), 1);
742 property = findPropertyByName(document, QStringLiteral("ORG"));
743 QCOMPARE(property.name(), QStringLiteral("ORG"));
744 CHECK_VALUE(property, QVersitProperty::CompoundType, QStringList(QStringLiteral("Nokia")));
745
746 // ORG with department/unit
747 organization.setName(QString());
748 QStringList departments(QStringLiteral("R&D"));
749 departments.append(QStringLiteral("Qt"));
750 organization.setDepartment(departments);
751 contact.saveDetail(detail: &organization);
752 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
753 document = mExporter->documents().first();
754 QCOMPARE(countProperties(document), 1);
755 property = findPropertyByName(document, QStringLiteral("ORG"));
756 QCOMPARE(property.name(), QStringLiteral("ORG"));
757 CHECK_VALUE(property, QVersitProperty::CompoundType, QStringList()
758 << QString() << QStringLiteral("R&D") << QStringLiteral("Qt"));
759
760 // ORG with name and department/unit
761 organization.setName(QStringLiteral("Nokia"));
762 contact.saveDetail(detail: &organization);
763 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
764 document = mExporter->documents().first();
765 QCOMPARE(countProperties(document), 1);
766 property = findPropertyByName(document, QStringLiteral("ORG"));
767 QCOMPARE(property.name(), QStringLiteral("ORG"));
768 CHECK_VALUE(property, QVersitProperty::CompoundType, QStringList()
769 << QStringLiteral("Nokia") << QStringLiteral("R&D") << QStringLiteral("Qt"));
770
771 // TITLE and ORG
772 organization.setTitle(QStringLiteral("Developer"));
773 contact.saveDetail(detail: &organization);
774 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
775 document = mExporter->documents().first();
776 QCOMPARE(countProperties(document), 2);
777 property = findPropertyByName(document, QStringLiteral("TITLE"));
778 QVERIFY(!property.isEmpty());
779 QCOMPARE(property.value(), title);
780 property = findPropertyByName(document, QStringLiteral("ORG"));
781 QVERIFY(!property.isEmpty());
782 QCOMPARE(property.name(), QStringLiteral("ORG"));
783 CHECK_VALUE(property, QVersitProperty::CompoundType, QStringList()
784 << QStringLiteral("Nokia") << QStringLiteral("R&D") << QStringLiteral("Qt"));
785
786 // ORG LOGO Test1: LOGO as remote Resouce
787 const QString url = QStringLiteral("http://myhome.com/test.jpg");
788 contact = createContactWithName(QStringLiteral("asdf"));
789 organization = QContactOrganization();
790 organization.setLogoUrl(url);
791 contact.saveDetail(detail: &organization);
792 mResourceHandler->mSimulatedMimeType = QStringLiteral("image/jpeg");
793 mExporter->setResourceHandler(mResourceHandler);
794 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
795 document = mExporter->documents().first();
796 QVERIFY(!mResourceHandler->mLoadResourceCalled);
797
798 // Source type is encoded, but media type is not for a URL.
799 property = findPropertyByName(document, QStringLiteral("LOGO"));
800 QVERIFY(!property.isEmpty());
801 QCOMPARE(property.parameters().count(), 1);
802
803 QVERIFY(property.parameters().contains(
804 QStringLiteral("VALUE"), QStringLiteral("uri")));
805
806 //Check property value
807 QCOMPARE(property.value(), url);
808
809 // ORG LOGO Test2: LOGO File.
810 mResourceHandler->mSimulatedData = "simulated data";
811 contact = createContactWithName(QStringLiteral("asdf"));
812 organization = QContactOrganization();
813 organization.setLogoUrl(TEST_PHOTO_FILE);
814 contact.saveDetail(detail: &organization);
815 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
816 document = mExporter->documents().first();
817 QVERIFY(mResourceHandler->mLoadResourceCalled);
818 QCOMPARE(mResourceHandler->mLocation, TEST_PHOTO_FILE);
819
820 // It should be stored in the property as a QVariant of QByteArray
821 property = findPropertyByName(document, QStringLiteral("LOGO"));
822 QVERIFY(!property.isEmpty());
823 QMultiHash<QString,QString> parameters = property.parameters();
824 // Media type is encoded
825 QCOMPARE(parameters.count(), 1);
826 QVERIFY(parameters.contains(
827 QStringLiteral("TYPE"), QStringLiteral("JPEG")));
828 // Verify value.
829 QVariant variantValue = property.variantValue();
830 QVERIFY(variantValue.type() == QVariant::ByteArray);
831 QCOMPARE(variantValue.value<QByteArray>(), mResourceHandler->mSimulatedData);
832
833 // Assistant Name Test.
834 contact = createContactWithName(QStringLiteral("asdf"));
835 organization = QContactOrganization();
836 organization.setAssistantName(QStringLiteral("myAssistant"));
837 contact.saveDetail(detail: &organization);
838 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
839 document = mExporter->documents().first();
840 QCOMPARE(countProperties(document), 1);
841 property = findPropertyByName(document, QStringLiteral("X-ASSISTANT"));
842 QVERIFY(!property.isEmpty());
843 QCOMPARE(property.value(), QStringLiteral("myAssistant"));
844
845 // Test: Role
846 contact = createContactWithName(QStringLiteral("asdf"));
847 organization = QContactOrganization();
848 organization.setRole(QStringLiteral("Executive"));
849 contact.saveDetail(detail: &organization);
850 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
851 document = mExporter->documents().first();
852 QCOMPARE(countProperties(document), 1);
853 property = findPropertyByName(document, QStringLiteral("ROLE"));
854 QVERIFY(!property.isEmpty());
855 QCOMPARE(property.value(), QStringLiteral("Executive"));
856
857}
858
859void tst_QVersitContactExporter::testEncodeAvatar()
860{
861 QContact contact = createContactWithName(QStringLiteral("asdf"));
862 QContactAvatar contactAvatar;
863 mResourceHandler->mSimulatedData = "simulated data";
864 mResourceHandler->mSimulatedMimeType = QStringLiteral("image/jpeg");
865
866 // Test1: Web URL
867 const QString url = QStringLiteral("http://www.myhome.com/test.jpg");
868 contactAvatar.setImageUrl(url);
869 contact.saveDetail(detail: &contactAvatar);
870 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
871 QVersitDocument document = mExporter->documents().first();
872 QVersitProperty property = findPropertyByName(document, QStringLiteral("PHOTO"));
873 QVERIFY(!property.isEmpty());
874 QCOMPARE(property.parameters().count(), 1);
875 QCOMPARE(property.value(), url);
876 QVERIFY(!mResourceHandler->mLoadResourceCalled);
877
878 // Test 2: Local Media PHOTO
879 contactAvatar.setImageUrl(TEST_PHOTO_FILE);
880 contact.saveDetail(detail: &contactAvatar);
881 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
882 document = mExporter->documents().first();
883 QVERIFY(mResourceHandler->mLoadResourceCalled);
884// This is commented out due to test failure
885// QCOMPARE(mResourceHandler->mLocation, TEST_PHOTO_FILE);
886 // verify the value
887 property = findPropertyByName(document, QStringLiteral("PHOTO"));
888 QVERIFY(!property.isEmpty());
889 QVariant variantValue = property.variantValue();
890 QVERIFY(variantValue.type() == QVariant::ByteArray);
891 QCOMPARE(variantValue.value<QByteArray>(), mResourceHandler->mSimulatedData);
892 QVERIFY(property.parameters().contains(QStringLiteral("TYPE"),
893 QStringLiteral("JPEG")));
894}
895
896
897void tst_QVersitContactExporter::testEncodeEmbeddedContent()
898{
899 QContact contact = createContactWithName(QStringLiteral("asdf"));
900 QContactAvatar contactAvatar;
901 QVariant variantValue;
902
903 // Test 1: URL
904 const QString url = QStringLiteral("http://www.myhome.com/test.jpg");
905 contactAvatar.setImageUrl(url);
906 contact.saveDetail(detail: &contactAvatar);
907 mResourceHandler->mSimulatedMimeType = QStringLiteral("image/jpeg");
908 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
909 QVersitDocument document = mExporter->documents().first();
910 QVERIFY(!mResourceHandler->mLoadResourceCalled);
911 QVersitProperty photoProperty = findPropertyByName(document, QStringLiteral("PHOTO"));
912 QVERIFY(!photoProperty.isEmpty());
913 QCOMPARE(photoProperty.parameters().count(), 1);
914 QVERIFY(photoProperty.parameters().contains(
915 QStringLiteral("VALUE"),QStringLiteral("URL")));
916 QCOMPARE(photoProperty.value(), url);
917
918 // Test 2: Local PHOTO, image loaded by the loader
919 contactAvatar.setImageUrl(TEST_PHOTO_FILE);
920 contact.saveDetail(detail: &contactAvatar);
921 mResourceHandler->clear();
922 mResourceHandler->mSimulatedMimeType = QStringLiteral("image/jpeg");
923 mResourceHandler->mSimulatedData = "simulated image data";
924 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
925 document = mExporter->documents().first();
926 QVERIFY(mResourceHandler->mLoadResourceCalled);
927 photoProperty = findPropertyByName(document, QStringLiteral("PHOTO"));
928 QVERIFY(!photoProperty.isEmpty());
929 QCOMPARE(photoProperty.parameters().count(), 1);
930 QVERIFY(photoProperty.parameters().contains(QStringLiteral("TYPE"),
931 QStringLiteral("JPEG")));
932 variantValue = photoProperty.variantValue();
933 QVERIFY(variantValue.type() == QVariant::ByteArray);
934 QCOMPARE(variantValue.value<QByteArray>(), mResourceHandler->mSimulatedData);
935
936 // Without a resource handler
937 mExporter->setResourceHandler(0);
938 contactAvatar.setImageUrl(TEST_PHOTO_FILE);
939 contact.saveDetail(detail: &contactAvatar);
940 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
941 document = mExporter->documents().first();
942 QCOMPARE(countProperties(document), 0);
943
944 mExporter->setResourceHandler(mResourceHandler);
945}
946
947void tst_QVersitContactExporter::testEncodeRingtone()
948{
949 // Test local ringtone
950 QContactRingtone ringtone;
951 mResourceHandler->clear();
952 mResourceHandler->mSimulatedMimeType = QStringLiteral("audio/wav");
953 mResourceHandler->mSimulatedData = "simulated audio data";
954 ringtone.setAudioRingtoneUrl(TEST_AUDIO_FILE);
955 QContact contact(createContactWithName(QStringLiteral("asdf")));
956 contact.saveDetail(detail: &ringtone);
957 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
958 QVersitDocument document = mExporter->documents().first();
959 QVERIFY(mResourceHandler->mLoadResourceCalled);
960 QVersitProperty soundProperty = findPropertyByName(document, QStringLiteral("SOUND"));
961 QVERIFY(!soundProperty.isEmpty());
962 QCOMPARE(soundProperty.parameters().count(), 1);
963 QVERIFY(soundProperty.parameters().contains(
964 QStringLiteral("TYPE"),
965 QStringLiteral("WAV")));
966 QVariant variantValue = soundProperty.variantValue();
967 QVERIFY(variantValue.type() == QVariant::ByteArray);
968 QCOMPARE(variantValue.value<QByteArray>(), mResourceHandler->mSimulatedData);
969
970 // Test url ringtone
971 QContactRingtone urlRingtone;
972 QContact urlContact(createContactWithName(QStringLiteral("asdf")));
973 const QUrl url(QStringLiteral("http://qt.nokia.com/audioringtoneurl"));
974 urlRingtone.setAudioRingtoneUrl(url);
975 urlContact.saveDetail(detail: &urlRingtone);
976 QVERIFY(mExporter->exportContacts(QList<QContact>() << urlContact, QVersitDocument::VCard30Type));
977 document = mExporter->documents().first();
978 soundProperty = findPropertyByName(document, QStringLiteral("SOUND"));
979 QVERIFY(!soundProperty.isEmpty());
980 QCOMPARE(soundProperty.parameters().count(), 1);
981 QVERIFY(soundProperty.parameters().contains(
982 QStringLiteral("VALUE"),QStringLiteral("URL")));
983 QCOMPARE(soundProperty.value(), url.toString());
984}
985
986void tst_QVersitContactExporter::testEncodeParameters()
987{
988 QContact contact(createContactWithName(QStringLiteral("asdf")));
989 QContactPhoneNumber phoneNumber;
990 phoneNumber.setNumber(QStringLiteral("12345678"));
991 QList<int> subtypes;
992 subtypes.append(t: QContactPhoneNumber::SubTypeMobile);
993 subtypes.append(t: QContactPhoneNumber::SubTypeVideo);
994 // Add a not supported subtype in vCard, to make sure its not encoded.
995 subtypes.append(t: QContactPhoneNumber::SubTypeDtmfMenu);
996 phoneNumber.setSubTypes(subtypes);
997 contact.saveDetail(detail: &phoneNumber);
998 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
999 QVersitDocument document = mExporter->documents().first();
1000 QCOMPARE(countProperties(document), 1);
1001 QVersitProperty property = findPropertyByName(document, QStringLiteral("TEL"));
1002 QVERIFY(!property.isEmpty());
1003 QCOMPARE(property.parameters().count(), 2);
1004 QVERIFY(property.parameters().contains(
1005 QStringLiteral("TYPE"), QStringLiteral("CELL")));
1006 QVERIFY(property.parameters().contains(
1007 QStringLiteral("TYPE"),QStringLiteral("VIDEO")));
1008}
1009
1010void tst_QVersitContactExporter::testEncodeGender()
1011{
1012 QContact contact(createContactWithName(QStringLiteral("asdf")));
1013
1014 // Check that empty gender detail is encoded as Unspecified
1015 QContactGender gender;
1016 contact.saveDetail(detail: &gender);
1017 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1018 QVersitDocument document = mExporter->documents().first();
1019 QCOMPARE(countProperties(document), 1);
1020 QVersitProperty property = findPropertyByName(document, QStringLiteral("X-GENDER"));
1021 QVERIFY(!property.isEmpty());
1022 QCOMPARE(property.parameters().count(), 0);
1023 QCOMPARE(property.value(), QStringLiteral("Unspecified"));
1024
1025 // Check that all valid values are encoded properly.
1026 gender.setGender(QContactGender::GenderMale);
1027 gender.setContexts(QContactGender::ContextHome); // Should not be encoded
1028 contact.saveDetail(detail: &gender);
1029 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1030 document = mExporter->documents().first();
1031 QCOMPARE(countProperties(document), 1);
1032 property = findPropertyByName(document, QStringLiteral("X-GENDER"));
1033 QVERIFY(!property.isEmpty());
1034 QCOMPARE(property.parameters().count(), 0);
1035 QCOMPARE(property.value(), QStringLiteral("Male"));
1036
1037 gender.setGender(QContactGender::GenderFemale);
1038 contact.saveDetail(detail: &gender);
1039 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1040 document = mExporter->documents().first();
1041 QCOMPARE(countProperties(document), 1);
1042 property = findPropertyByName(document, QStringLiteral("X-GENDER"));
1043 QVERIFY(!property.isEmpty());
1044 QCOMPARE(property.parameters().count(), 0);
1045 QCOMPARE(property.value(), QStringLiteral("Female"));
1046
1047 gender.setGender(QContactGender::GenderUnspecified);
1048 contact.saveDetail(detail: &gender);
1049 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1050 document = mExporter->documents().first();
1051 QCOMPARE(countProperties(document), 1);
1052 property = findPropertyByName(document, QStringLiteral("X-GENDER"));
1053 QVERIFY(!property.isEmpty());
1054 QCOMPARE(property.parameters().count(), 0);
1055 QCOMPARE(property.value(), QStringLiteral("Unspecified"));
1056 //TODO: Add a helper function in this test module to convert gender versity property to gender enum
1057}
1058
1059void tst_QVersitContactExporter::testEncodeNickName()
1060{
1061 QContact contact(createContactWithName(QStringLiteral("asdf")));
1062
1063 // Add an extra detail
1064 QContactGender gender;
1065 gender.setGender(QContactGender::GenderMale);
1066 contact.saveDetail(detail: &gender);
1067
1068 // One nickname given
1069 QContactNickname firstNickname;
1070 firstNickname.setNickname(QStringLiteral("Homie"));
1071 contact.saveDetail(detail: &firstNickname);
1072 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1073 QVersitDocument document = mExporter->documents().first();
1074 QCOMPARE(countProperties(document), 2);
1075 QVersitProperty property = findPropertyByName(document, QStringLiteral("X-NICKNAME"));
1076 QCOMPARE(property.name(), QStringLiteral("X-NICKNAME"));
1077 CHECK_VALUE(property, QVersitProperty::ListType, QStringList(QStringLiteral("Homie")));
1078
1079 // Two nicknames given, should be collated into a single property
1080 contact = createContactWithName(QStringLiteral("asdf"));
1081 contact.saveDetail(detail: &gender);
1082 contact.saveDetail(detail: &firstNickname);
1083 QContactNickname secondNickname;
1084 secondNickname.setNickname(QStringLiteral("Jay"));
1085 contact.saveDetail(detail: &secondNickname);
1086 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1087 document = mExporter->documents().first();
1088 QCOMPARE(countProperties(document), 2);
1089 property = findPropertyByName(document, QStringLiteral("X-NICKNAME"));
1090 QVERIFY(!property.isEmpty());
1091 QCOMPARE(property.name(), QStringLiteral("X-NICKNAME"));
1092 CHECK_VALUE(property, QVersitProperty::ListType,
1093 QStringList() << QStringLiteral("Homie") << QStringLiteral("Jay"));
1094}
1095
1096void tst_QVersitContactExporter::testEncodeTag()
1097{
1098 QContact contact(createContactWithName(QStringLiteral("asdf")));
1099
1100 // Add an extra detail
1101 QContactGender gender;
1102 gender.setGender(QContactGender::GenderMale);
1103 contact.saveDetail(detail: &gender);
1104
1105 // One tag given
1106 QContactTag firstTag;
1107 firstTag.setTag(QStringLiteral("red"));
1108 contact.saveDetail(detail: &firstTag);
1109 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1110 QVersitDocument document = mExporter->documents().first();
1111 QCOMPARE(countProperties(document), 2);
1112 QVersitProperty property = findPropertyByName(document, QStringLiteral("CATEGORIES"));
1113 QCOMPARE(property.name(), QStringLiteral("CATEGORIES"));
1114 CHECK_VALUE(property, QVersitProperty::ListType, QStringList(QStringLiteral("red")));
1115
1116 // Two tags given, should be collated into a single property
1117 contact = createContactWithName(QStringLiteral("asdf"));
1118 contact.saveDetail(detail: &firstTag);
1119 contact.saveDetail(detail: &gender);
1120 QContactTag secondTag;
1121 secondTag.setTag(QStringLiteral("green"));
1122 contact.saveDetail(detail: &secondTag);
1123 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1124 document = mExporter->documents().first();
1125 QCOMPARE(countProperties(document), 2);
1126 property = findPropertyByName(document, QStringLiteral("CATEGORIES"));
1127 QCOMPARE(property.name(), QStringLiteral("CATEGORIES"));
1128 CHECK_VALUE(property, QVersitProperty::ListType,
1129 QStringList() << QStringLiteral("red") << QStringLiteral("green"));
1130}
1131
1132void tst_QVersitContactExporter::testEncodeAnniversary()
1133{
1134 QContact contact(createContactWithName(QStringLiteral("asdf")));
1135 QContactAnniversary anniversary;
1136 QDate date(2009,1,1);
1137 anniversary.setOriginalDate(date);
1138 anniversary.setContexts(QContactDetail::ContextHome);
1139 anniversary.setSubType(QContactAnniversary::SubTypeWedding);
1140 contact.saveDetail(detail: &anniversary);
1141 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1142 QVersitDocument document = mExporter->documents().first();
1143 QCOMPARE(countProperties(document), 1);
1144 QVersitProperty property = findPropertyByName(document, QStringLiteral("X-ANNIVERSARY"));
1145 QVERIFY(!property.isEmpty());
1146 // The contexts and subtypes are not defined for X-ANNIVERSARY property
1147 QCOMPARE(property.parameters().count(), 0);
1148 // Check value
1149 QCOMPARE(property.value(), date.toString(Qt::ISODate));
1150}
1151
1152
1153void tst_QVersitContactExporter::testEncodeOnlineAccount()
1154{
1155 QContact contact(createContactWithName(QStringLiteral("asdf")));
1156 QContactOnlineAccount onlineAccount;
1157 QString accountUri(QStringLiteral("sip:abc@temp.com"));
1158 QList<int> expectedSubTypes;
1159 QContactOnlineAccount::SubType expectedSubType;
1160 int invalidData = 123456;
1161
1162 onlineAccount.setAccountUri(accountUri);
1163
1164 // Video sharing
1165 expectedSubType = QContactOnlineAccount::SubTypeVideoShare;
1166 expectedSubTypes << expectedSubType;
1167 onlineAccount.setSubTypes(expectedSubTypes);
1168 onlineAccount.setContexts(QContactDetail::ContextHome);
1169 contact.saveDetail(detail: &onlineAccount);
1170 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1171 QVersitDocument document = mExporter->documents().first();
1172 QCOMPARE(countProperties(document), 1);
1173 QVersitProperty property = findPropertyByName(document, QStringLiteral("X-SIP"));
1174 QVERIFY(!property.isEmpty());
1175 // Check parameters
1176 QCOMPARE(property.parameters().count(), 2);
1177 QVERIFY(property.parameters().contains(
1178 QStringLiteral("TYPE"),QStringLiteral("HOME")));
1179 QVERIFY(property.parameters().contains(
1180 QStringLiteral("TYPE"),QStringLiteral("SWIS")));
1181 // Check value
1182 QCOMPARE(property.value(), accountUri);
1183
1184 // VoIP
1185 expectedSubTypes.clear();
1186 expectedSubType = QContactOnlineAccount::SubTypeSipVoip;
1187 expectedSubTypes << expectedSubType;
1188 onlineAccount.setSubTypes(expectedSubTypes);
1189 onlineAccount.setContexts(QContactDetail::ContextWork);
1190 contact.saveDetail(detail: &onlineAccount);
1191 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1192 document = mExporter->documents().first();
1193 QCOMPARE(countProperties(document), 1);
1194 property = findPropertyByName(document, QStringLiteral("X-SIP"));
1195 QVERIFY(!property.isEmpty());
1196 // Check parameters
1197 QCOMPARE(property.parameters().count(), 2);
1198 QVERIFY(property.parameters().contains(
1199 QStringLiteral("TYPE"),QStringLiteral("WORK")));
1200 QVERIFY(property.parameters().contains(
1201 QStringLiteral("TYPE"),QStringLiteral("VOIP")));
1202 // Check value
1203 QCOMPARE(property.value(), accountUri);
1204
1205 // Plain SIP
1206 expectedSubTypes.clear();
1207 expectedSubType = QContactOnlineAccount::SubTypeSip;
1208 expectedSubTypes << expectedSubType;
1209 onlineAccount.setSubTypes(expectedSubTypes);
1210 onlineAccount.setContexts(QContactDetail::ContextWork);
1211 contact.saveDetail(detail: &onlineAccount);
1212 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1213 document = mExporter->documents().first();
1214 QCOMPARE(countProperties(document), 1);
1215 property = findPropertyByName(document, QStringLiteral("X-SIP"));
1216 QVERIFY(!property.isEmpty());
1217 // Check parameters, SIP not added as a TYPE parameter
1218 QCOMPARE(property.parameters().count(), 1);
1219 QVERIFY(property.parameters().contains(
1220 QStringLiteral("TYPE"),QStringLiteral("WORK")));
1221 // Check value
1222 QCOMPARE(property.value(), accountUri);
1223
1224 // IMPP / X-IMPP
1225 expectedSubTypes.clear();
1226 expectedSubType = QContactOnlineAccount::SubTypeImpp;
1227 expectedSubTypes << expectedSubType;
1228 onlineAccount.setSubTypes(expectedSubTypes);
1229 onlineAccount.setContexts(QContactDetail::ContextHome);
1230 contact.saveDetail(detail: &onlineAccount);
1231 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1232 document = mExporter->documents().first();
1233 QCOMPARE(countProperties(document), 1);
1234 property = findPropertyByName(document, QStringLiteral("X-IMPP"));
1235 QVERIFY(!property.isEmpty());
1236 // Check parameters, SIP not added as a TYPE parameter
1237 QCOMPARE(property.parameters().count(), 1);
1238 QVERIFY(property.parameters().contains(
1239 QStringLiteral("TYPE"),QStringLiteral("HOME")));
1240 // Check value
1241 QCOMPARE(property.value(), accountUri);
1242
1243 // Other subtypes not converted
1244 expectedSubTypes.clear();
1245 expectedSubType = static_cast<QContactOnlineAccount::SubType>(invalidData);
1246 expectedSubTypes << expectedSubType;
1247 onlineAccount.setSubTypes(expectedSubTypes);
1248 contact.saveDetail(detail: &onlineAccount);
1249 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1250 document = mExporter->documents().first();
1251 QCOMPARE(countProperties(document), 0);
1252
1253 // Test protocols Jabber, AIM, ICQ, MSN, Yahoo, Skype
1254 contact.clearDetails();
1255 onlineAccount = QContactOnlineAccount();
1256 onlineAccount.setProtocol(QContactOnlineAccount::ProtocolJabber);
1257 onlineAccount.setAccountUri("a");
1258 contact.saveDetail(detail: &onlineAccount);
1259 onlineAccount = QContactOnlineAccount();
1260 onlineAccount.setProtocol(QContactOnlineAccount::ProtocolAim);
1261 onlineAccount.setAccountUri("b");
1262 contact.saveDetail(detail: &onlineAccount);
1263 onlineAccount = QContactOnlineAccount();
1264 onlineAccount.setProtocol(QContactOnlineAccount::ProtocolIcq);
1265 onlineAccount.setAccountUri("c");
1266 contact.saveDetail(detail: &onlineAccount);
1267 onlineAccount = QContactOnlineAccount();
1268 onlineAccount.setProtocol(QContactOnlineAccount::ProtocolMsn);
1269 onlineAccount.setAccountUri("d");
1270 contact.saveDetail(detail: &onlineAccount);
1271 onlineAccount = QContactOnlineAccount();
1272 onlineAccount.setProtocol(QContactOnlineAccount::ProtocolQq);
1273 onlineAccount.setAccountUri("e");
1274 contact.saveDetail(detail: &onlineAccount);
1275 onlineAccount = QContactOnlineAccount();
1276 onlineAccount.setProtocol(QContactOnlineAccount::ProtocolYahoo);
1277 onlineAccount.setAccountUri("f");
1278 contact.saveDetail(detail: &onlineAccount);
1279 onlineAccount = QContactOnlineAccount();
1280 onlineAccount.setProtocol(QContactOnlineAccount::ProtocolSkype);
1281 onlineAccount.setAccountUri("g");
1282 contact.saveDetail(detail: &onlineAccount);
1283
1284 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1285 document = mExporter->documents().first();
1286
1287 property = findPropertyByName(document, QStringLiteral("X-JABBER"));
1288 QVERIFY(!property.isEmpty());
1289 QVERIFY(property.value() == "a");
1290 property = findPropertyByName(document, QStringLiteral("X-AIM"));
1291 QVERIFY(!property.isEmpty());
1292 QVERIFY(property.value() == "b");
1293 property = findPropertyByName(document, QStringLiteral("X-ICQ"));
1294 QVERIFY(!property.isEmpty());
1295 QVERIFY(property.value() == "c");
1296 property = findPropertyByName(document, QStringLiteral("X-MSN"));
1297 QVERIFY(!property.isEmpty());
1298 QVERIFY(property.value() == "d");
1299 property = findPropertyByName(document, QStringLiteral("X-QQ"));
1300 QVERIFY(!property.isEmpty());
1301 QVERIFY(property.value() == "e");
1302 property = findPropertyByName(document, QStringLiteral("X-YAHOO"));
1303 QVERIFY(!property.isEmpty());
1304 QVERIFY(property.value() == "f");
1305 property = findPropertyByName(document, QStringLiteral("X-SKYPE"));
1306 QVERIFY(!property.isEmpty());
1307 QVERIFY(property.value() == "g");
1308}
1309
1310void tst_QVersitContactExporter::testEncodeFamily()
1311{
1312 QContact contact(createContactWithName(QStringLiteral("asdf")));
1313 QContactFamily family;
1314
1315 // No spouse, no family
1316 family.setContexts(QContactDetail::ContextHome);
1317 contact.saveDetail(detail: &family);
1318 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1319 QVersitDocument document = mExporter->documents().first();
1320 QCOMPARE(countProperties(document), 0);
1321
1322 // Only spouse present
1323 QString spouse = QStringLiteral("ABC");
1324 family.setSpouse(spouse);
1325 contact.saveDetail(detail: &family);
1326 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1327 document = mExporter->documents().first();
1328 QCOMPARE(countProperties(document), 1);
1329 QVersitProperty spouseProperty = findPropertyByName(document, QStringLiteral("X-SPOUSE"));
1330 QVERIFY(!spouseProperty.isEmpty());
1331 QCOMPARE(spouseProperty.parameters().count(), 0);
1332 QCOMPARE(spouseProperty.value(), spouse);
1333
1334 // Spouse and children
1335 QStringList children;
1336 children << QStringLiteral("A") << QStringLiteral("B") ;
1337 family.setChildren(children);
1338 family.setSpouse(spouse);
1339 contact.saveDetail(detail: &family);
1340 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1341 document = mExporter->documents().first();
1342 QCOMPARE(countProperties(document), 2);
1343 spouseProperty = findPropertyByName(document, QStringLiteral("X-SPOUSE"));
1344 QVERIFY(!spouseProperty.isEmpty());
1345 QCOMPARE(spouseProperty.parameters().count(), 0);
1346 QCOMPARE(spouseProperty.value(), spouse);
1347 QVersitProperty childrenProperty = findPropertyByName(document, QStringLiteral("X-CHILDREN"));
1348 QVERIFY(!spouseProperty.isEmpty());
1349 QCOMPARE(childrenProperty.parameters().count(), 0);
1350 QCOMPARE(childrenProperty.name(), QStringLiteral("X-CHILDREN"));
1351 CHECK_VALUE(childrenProperty, QVersitProperty::ListType, children);
1352}
1353
1354void tst_QVersitContactExporter::testEncodeFavorite()
1355{
1356 QContact contact(createContactWithName(QStringLiteral("asdf")));
1357 QContactFavorite favorite;
1358 int favoriteIndex = 1;
1359 favorite.setIndex(favoriteIndex);
1360 favorite.setFavorite(true);
1361 contact.saveDetail(detail: &favorite);
1362
1363 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1364
1365 QVersitDocument document = mExporter->documents().first();
1366 QCOMPARE(countProperties(document), 1);
1367 QVersitProperty favoriteProperty = findPropertyByName(document, QStringLiteral("X-QTPROJECT-FAVORITE"));
1368 QVERIFY(!favoriteProperty.isEmpty());
1369 QCOMPARE(favoriteProperty.parameters().count(), 0);
1370 CHECK_VALUE(favoriteProperty, QVersitProperty::CompoundType,
1371 QStringList() << QStringLiteral("true") << QString::number(favoriteIndex));
1372}
1373
1374void tst_QVersitContactExporter::testEncodeExtendedDetail()
1375{
1376 QFETCH(QString, extendedDetailName);
1377 QFETCH(QVariant, extendedDetailData);
1378 QFETCH(QString, extendedDetailDataInProperty);
1379 QFETCH(bool, extendedDetailPropertyCreated);
1380 QContact contact(createContactWithName(QStringLiteral("asdf")));
1381 QContactExtendedDetail extendedDetail;
1382 extendedDetail.setName(extendedDetailName);
1383 extendedDetail.setData(extendedDetailData);
1384 contact.saveDetail(detail: &extendedDetail);
1385
1386 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1387
1388 QVersitDocument document = mExporter->documents().first();
1389 if (!extendedDetailPropertyCreated) {
1390 QCOMPARE(countProperties(document), 0);
1391 return;
1392 }
1393 QCOMPARE(countProperties(document), 1);
1394 QVersitProperty property = findPropertyByName(document, QStringLiteral("X-QTPROJECT-EXTENDED-DETAIL"));
1395 QVERIFY(!property.isEmpty());
1396 QCOMPARE(property.parameters().count(), 0);
1397 QStringList expectedValue = QStringList() << extendedDetailName << extendedDetailDataInProperty;
1398 if (static_cast<QMetaType::Type>(extendedDetailData.type()) == QMetaType::Double) {
1399 CHECK_FLOATING_POINT_VALUE(property, QVersitProperty::CompoundType, expectedValue, true);
1400 } else if (static_cast<QMetaType::Type>(extendedDetailData.type()) == QMetaType::Float) {
1401 CHECK_FLOATING_POINT_VALUE(property, QVersitProperty::CompoundType, expectedValue, false);
1402 } else {
1403 CHECK_VALUE(property, QVersitProperty::CompoundType, expectedValue);
1404 }
1405}
1406
1407void tst_QVersitContactExporter::testEncodeExtendedDetail_data()
1408{
1409 QTest::addColumn<QString>(name: "extendedDetailName");
1410 QTest::addColumn<QVariant>(name: "extendedDetailData");
1411 QTest::addColumn<QString>(name: "extendedDetailDataInProperty");
1412 QTest::addColumn<bool>(name: "extendedDetailPropertyCreated");
1413
1414 QString jsonArrayWith("[\n %1\n]\n");
1415 QString jsonArrayWithString = jsonArrayWith.arg(a: "\"%1\"");
1416 {
1417 QTest::newRow(dataTag: "string data")
1418 << QString("name")
1419 << QVariant(QString("data"))
1420 << jsonArrayWithString.arg(a: "data")
1421 << true;
1422 QTest::newRow(dataTag: "string data, empty")
1423 << QString("name")
1424 << QVariant(QString(""))
1425 << jsonArrayWithString.arg(a: "")
1426 << true;
1427 QTest::newRow(dataTag: "string data, containing reserved characters")
1428 << QString("name")
1429 << QVariant(QString(",;:\\"))
1430 << jsonArrayWithString.arg(a: ",;:\\\\")
1431 << true;
1432 }
1433
1434 {
1435 QTest::newRow(dataTag: "double data")
1436 << QString("name")
1437 << QVariant((double)2.0)
1438 << jsonArrayWith.arg(a: "2")
1439 << true;
1440 QTest::newRow(dataTag: "double data, negative")
1441 << QString("name")
1442 << QVariant((double)-1.0)
1443 << jsonArrayWith.arg(a: "-1")
1444 << true;
1445 QTest::newRow(dataTag: "double data, multiple digits")
1446 << QString("name")
1447 << QVariant::fromValue<double>(value: 10.199999999999999)
1448 << jsonArrayWith.arg(a: "10.199999999999999")
1449 << true;
1450 }
1451
1452 {
1453 QTest::newRow(dataTag: "boolean data")
1454 << QString("name")
1455 << QVariant(true)
1456 << jsonArrayWith.arg(a: "true")
1457 << true;
1458 }
1459
1460 {
1461 QTest::newRow(dataTag: "integer data, serialized as number/double")
1462 << QString("name")
1463 << QVariant((int)2)
1464 << jsonArrayWith.arg(a: "2")
1465 << true;
1466 QTest::newRow(dataTag: "integer data, serialized as number/double")
1467 << QString("name")
1468 << QVariant((int)-10)
1469 << jsonArrayWith.arg(a: "-10")
1470 << true;
1471 }
1472 {
1473 QTest::newRow(dataTag: "datetime data (using local time)")
1474 << QString("name")
1475 << QVariant(QDateTime::fromString(s: "1997-07-16T19:20:30.123+01:00", f: Qt::ISODate))
1476 << jsonArrayWithString.arg(a: "1997-07-16T19:20:30+01:00")
1477 << true;
1478 QTest::newRow(dataTag: "datetime data (using UTC)")
1479 << QString("name")
1480 << QVariant(QDateTime::fromString(s: "1997-07-16T19:20:30.123+01:00", f: Qt::ISODate).toUTC())
1481 << jsonArrayWithString.arg(a: "1997-07-16T18:20:30Z")
1482 << true;
1483 QTest::newRow(dataTag: "datetime data (using local time with unspecified timezone)")
1484 << QString("name")
1485 << QVariant(QDateTime::fromString(s: "1997-07-16T19:20:30", f: Qt::ISODate))
1486 << jsonArrayWithString.arg(a: "1997-07-16T19:20:30")
1487 << true;
1488 }
1489
1490 {
1491 QTest::newRow(dataTag: "list data")
1492 << QString("name")
1493 << QVariant(QVariantList() << QString("string 1") << QString("string 2"))
1494 << QString("[\n [\n \"string 1\",\n \"string 2\"\n ]\n]\n")
1495 << true;
1496 }
1497
1498 {
1499 QVariantMap map;
1500 map["key 1"] = QString("string 1");
1501 map["key 2"] = QString("string 2");
1502 QTest::newRow(dataTag: "map data")
1503 << QString("name")
1504 << QVariant(map)
1505 << QString("[\n {\n \"key 1\": \"string 1\",\n \"key 2\": \"string 2\"\n }\n]\n")
1506 << true;
1507 }
1508
1509 {
1510 QVariantMap map;
1511 map["key"] = QVariantList() << (double)1 << (double)2;
1512 QTest::newRow(dataTag: "map data, containing a nested list")
1513 << QString("name")
1514 << QVariant(map)
1515 << QString("[\n {\n \"key\": [\n 1,\n 2\n ]\n }\n]\n")
1516 << true;
1517 }
1518
1519 {
1520 QTest::newRow(dataTag: "empty string as name")
1521 << QString("")
1522 << QVariant(QString("data"))
1523 << jsonArrayWithString.arg(a: "data")
1524 << true;
1525 QTest::newRow(dataTag: "name containing reserved characters")
1526 << QString(",;:\\")
1527 << QVariant(QString("data"))
1528 << jsonArrayWithString.arg(a: "data")
1529 << true;
1530 }
1531
1532 {
1533 QTest::newRow(dataTag: "empty variant as data")
1534 << QString("name")
1535 << QVariant()
1536 << jsonArrayWith.arg(a: "null")
1537 << true;
1538 }
1539
1540 {
1541 QVariantHash hash;
1542 hash["key 1"] = QString("string 1");
1543 hash["key 2"] = QString("string 2");
1544 QTest::newRow(dataTag: "hash data")
1545 << QString("name")
1546 << QVariant(hash)
1547 << QString("[\n {\n \"key 1\": \"string 1\",\n \"key 2\": \"string 2\"\n }\n]\n")
1548 << true;
1549 }
1550
1551 {
1552 QTest::newRow(dataTag: "data type not supported")
1553 << QString("name")
1554 << QVariant(QSize(1, 1))
1555 << QString()
1556 << false;
1557 }
1558}
1559
1560void tst_QVersitContactExporter::testEncodeMultipleExtendedDetails()
1561{
1562 QContact contact(createContactWithName(QStringLiteral("asdf")));
1563 QContactExtendedDetail extendedDetail1;
1564 extendedDetail1.setName(QStringLiteral("detailName1"));
1565 extendedDetail1.setData(QStringLiteral("detailData1"));
1566 contact.saveDetail(detail: &extendedDetail1);
1567 QContactExtendedDetail extendedDetail2;
1568 extendedDetail2.setName(QStringLiteral("detailName2"));
1569 extendedDetail2.setData(QStringLiteral("detailData2"));
1570 contact.saveDetail(detail: &extendedDetail2);
1571 QList<QContactExtendedDetail> expected;
1572 expected << extendedDetail1 << extendedDetail2;
1573
1574 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1575
1576 QVersitDocument document = mExporter->documents().first();
1577 QCOMPARE(countProperties(document), 2);
1578 QList<QVersitProperty> actual;
1579 foreach (const QVersitProperty &property, document.properties()) {
1580 if (property.name() == QStringLiteral("X-QTPROJECT-EXTENDED-DETAIL"))
1581 actual << property;
1582 }
1583 for (int i = 0; i < actual.size(); i++) {
1584 QVERIFY(!actual[i].isEmpty());
1585 QCOMPARE(actual[i].parameters().count(), 0);
1586 QString jsonArrayWith("[\n %1\n]\n");
1587 QString jsonArrayWithString = jsonArrayWith.arg(a: "\"%1\"");
1588 CHECK_VALUE(actual[i], QVersitProperty::CompoundType,
1589 QStringList()
1590 << expected[i].name()
1591 << jsonArrayWithString.arg(expected[i].data().toString()));
1592 }
1593}
1594
1595void tst_QVersitContactExporter::testDefaultResourceHandler()
1596{
1597 QVersitDefaultResourceHandler handler;
1598 QByteArray contents;
1599 QString mimeType;
1600 handler.loadResource(QStringLiteral("test.jpg"), contents: &contents, mimeType: &mimeType);
1601 QCOMPARE(mimeType, QStringLiteral("image/jpeg"));
1602
1603 QVersitProperty property;
1604 QString location;
1605 QVERIFY(!handler.saveResource("test contents", property, &location));
1606}
1607
1608void tst_QVersitContactExporter::testEncodeEmailWithContextOther()
1609{
1610 QContact contact(createContactWithName(QStringLiteral("asdf")));
1611 QContactEmailAddress email;
1612 email.setEmailAddress(QStringLiteral("test@test"));
1613 email.setContexts(QContactDetail::ContextOther);
1614 contact.saveDetail(detail: &email);
1615 QVERIFY(mExporter->exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
1616 QVersitDocument document = mExporter->documents().first();
1617 QCOMPARE(countProperties(document), 1);
1618 QVersitProperty property = findPropertyByName(document, QStringLiteral("EMAIL"));
1619 QVERIFY(!property.isEmpty());
1620 // Check parameters
1621 QCOMPARE(property.parameters().count(), 1);
1622 QVERIFY(property.parameters().contains(
1623 QStringLiteral("TYPE"),QStringLiteral("OTHER")));
1624 // Check value
1625 QCOMPARE(property.value(), email.emailAddress());
1626}
1627
1628// Test utility functions
1629QContact tst_QVersitContactExporter::createContactWithName(QString name)
1630{
1631 QContact contact;
1632 QContactName nameDetail;
1633 nameDetail.setFirstName(name);
1634 contact.saveDetail(detail: &nameDetail);
1635 return contact;
1636}
1637
1638/* Counts the properties, excluding the ones generated by a
1639 * "createContactWithName" contact and excluding default-generated properties
1640 */
1641int tst_QVersitContactExporter::countProperties(const QVersitDocument& document)
1642{
1643 int count = 0;
1644 foreach (const QVersitProperty& property, document.properties()) {
1645 if (property.name() != QStringLiteral("FN")
1646 && property.name() != QStringLiteral("N")
1647 && property.name() != QStringLiteral("X-NOKIA-QCONTACTFIELD"))
1648 count++;
1649 }
1650 return count;
1651}
1652
1653QContactDetail tst_QVersitContactExporter::findDetailByType(
1654 QList<QContactDetail> details,
1655 QContactDetail::DetailType search)
1656{
1657 QContactDetail detail;
1658 for (int i= 0; i < details.count(); i++) {
1659 if ( details.at(i).type() == search )
1660 detail = details.at(i);
1661 }
1662 return detail;
1663}
1664
1665QVersitProperty tst_QVersitContactExporter::findPropertyByName(
1666 const QVersitDocument &document, const QString &propertyName)
1667{
1668 foreach (const QVersitProperty& property, document.properties()) {
1669 if (property.name() == propertyName)
1670 return property;
1671 }
1672 return QVersitProperty();
1673}
1674
1675QTEST_MAIN(tst_QVersitContactExporter)
1676
1677

source code of qtpim/tests/auto/versit/qversitcontactexporter/tst_qversitcontactexporter.cpp