1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 #include <QCoreApplication>
30 #include <QString>
31 #include <QtTest/QtTest>
32 
33 #if QT_CONFIG(process)
34 #include <QtCore/QProcessEnvironment>
35 #endif
36 #include <QtPositioning/QGeoCircle>
37 #include <QtLocation/QGeoServiceProvider>
38 #include <QtLocation/QPlaceEditorial>
39 #include <QtLocation/QPlaceImage>
40 #include <QtLocation/QPlaceManager>
41 #include <QtLocation/QPlaceResult>
42 #include <QtLocation/QPlaceReview>
43 #include <QtLocation/QPlaceSearchReply>
44 #include "../../placemanager_utils/placemanager_utils.h"
45 
46 QT_USE_NAMESPACE
47 
48 class tst_QPlaceManagerNokia : public PlaceManagerUtils
49 {
50     Q_OBJECT
51 public:
52     enum ExpectedResults {
53         AnyResults, //zero or more results expected
54         SomeResults, //at least one result expected
55         NoResults // zero results expected
56     };
57 
58     tst_QPlaceManagerNokia();
59 
60 private Q_SLOTS:
61     void initTestCase();
62     void search();
63     void search_data();
64     void searchResultFields();
65     void recommendations();
66     void recommendations_data();
67     void details();
68     void categories();
69     void suggestions();
70     void suggestions_data();
71     void suggestionsMisc();
72     void locale();
73     void content();
74     void content_data();
75     void unsupportedFunctions();
76 
77 private:
78     void commonAreas(QList<QByteArray> *dataTags, QList<QGeoShape> *areas,
79                       QList<QPlaceReply::Error> *errors,
80                       QList<ExpectedResults> *results);
81 
82     static const QLatin1String ValidKnownPlaceId;
83     static const QLatin1String ProxyEnv;
84     static const QLatin1String AppIdEnv;
85     static const QLatin1String TokenEnv;
86 
87     QGeoServiceProvider *provider;
88 };
89 
90 Q_DECLARE_METATYPE(tst_QPlaceManagerNokia::ExpectedResults)
91 
92 // ValidKnownPlaceId is the id of a place with a full complement of place content. Editorials,
93 // reviews, images, recommendations. If it disappears these tests will fail.
94 // Currently it is set to an Eiffel Tower tourist office.
95 const QLatin1String tst_QPlaceManagerNokia::ValidKnownPlaceId("250u09tu-4561b8da952f4fd79c4e1998c3fcf032");
96 
97 const QLatin1String tst_QPlaceManagerNokia::ProxyEnv("NOKIA_PLUGIN_PROXY");
98 const QLatin1String tst_QPlaceManagerNokia::AppIdEnv("NOKIA_APPID");
99 const QLatin1String tst_QPlaceManagerNokia::TokenEnv("NOKIA_TOKEN");
100 
tst_QPlaceManagerNokia()101 tst_QPlaceManagerNokia::tst_QPlaceManagerNokia()
102 {
103 }
104 
initTestCase()105 void tst_QPlaceManagerNokia::initTestCase()
106 {
107     QVariantMap params;
108     QStringList providers = QGeoServiceProvider::availableServiceProviders();
109     QVERIFY(providers.contains("here"));
110 #if QT_CONFIG(process)
111     QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
112 
113     if (!(env.contains(AppIdEnv) && env.contains(TokenEnv)))
114         QSKIP("NOKIA_APPID and NOKIA_TOKEN environment variables not set");\
115 
116     params.insert(QStringLiteral("here.app_id"), env.value(AppIdEnv));
117     params.insert(QStringLiteral("here.token"), env.value(TokenEnv));
118 
119     if (env.contains(ProxyEnv))
120         params.insert(QStringLiteral("here.proxy"), env.value(ProxyEnv));
121 #else
122     QSKIP("Cannot parse process environment, NOKIA_APPID and NOKIA_TOKEN not set");
123 #endif
124     provider = new QGeoServiceProvider("here", params);
125     placeManager = provider->placeManager();
126     QVERIFY(placeManager);
127 }
128 
search()129 void tst_QPlaceManagerNokia::search()
130 {
131     QFETCH(QGeoShape, area);
132     QFETCH(QString, searchTerm);
133     QFETCH(QList<QPlaceCategory>, categories);
134     QFETCH(QPlaceReply::Error, error);
135     QFETCH(ExpectedResults, expectedResults);
136 
137     QPlaceSearchRequest searchRequest;
138     searchRequest.setSearchArea(area);
139     searchRequest.setSearchTerm(searchTerm);
140     if (categories.count() == 1)
141         searchRequest.setCategory(categories.first());
142     else
143         searchRequest.setCategories(categories);
144 
145     QList<QPlace> results;
146     QVERIFY(doSearch(searchRequest, &results, error));
147 
148     if (expectedResults == NoResults)
149         QVERIFY(results.count() == 0);
150     else if (expectedResults == SomeResults)
151         QVERIFY(results.count() > 0);
152 }
153 
search_data()154 void tst_QPlaceManagerNokia::search_data()
155 {
156     QTest::addColumn<QGeoShape>("area");
157     QTest::addColumn<QString>("searchTerm");
158     QTest::addColumn<QList<QPlaceCategory> >("categories");
159     QTest::addColumn<QPlaceSearchRequest::RelevanceHint>("hint");
160     QTest::addColumn<QPlaceReply::Error> ("error");
161     QTest::addColumn<ExpectedResults>("expectedResults");
162 
163     for (int i = 0; i < 3; i++) {
164         QByteArray suffix;
165         QGeoShape area;
166         if (i==0) {
167             area = QGeoCircle(QGeoCoordinate(-27.5, 153));
168             suffix = " (Circle - center only)";
169         } else if (i==1) {
170             area = QGeoCircle(QGeoCoordinate(-27.5, 153), 5000);
171             suffix = " (Circle - with radius specified)";
172         } else {
173             area = QGeoRectangle(QGeoCoordinate(-26.5, 152), QGeoCoordinate(-28.5, 154));
174             suffix = " (Rectangle)";
175         }
176 
177         QByteArray dataTag = QByteArray("coordinate only") + suffix;
178         QTest::newRow(dataTag) << area
179                                << QString()
180                                << QList<QPlaceCategory>()
181                                << QPlaceSearchRequest::UnspecifiedHint
182                                << QPlaceReply::NoError
183                                << SomeResults;
184 
185         dataTag = QByteArray("seach term") + suffix;
186         QTest::newRow(dataTag) << area
187                                << "sushi"
188                                << QList<QPlaceCategory>()
189                                << QPlaceSearchRequest::UnspecifiedHint
190                                << QPlaceReply::NoError
191                                << SomeResults;
192 
193         QPlaceCategory eatDrinkCat;
194         eatDrinkCat.setCategoryId(QStringLiteral("eat-drink"));
195         dataTag = QByteArray("single valid category") + suffix;
196         QTest::newRow(dataTag) << area
197                                << QString()
198                                << (QList<QPlaceCategory>()
199                                    << eatDrinkCat)
200                                << QPlaceSearchRequest::UnspecifiedHint
201                                << QPlaceReply::NoError
202                                << SomeResults;
203 
204         QPlaceCategory accommodationCat;
205         accommodationCat.setCategoryId(QStringLiteral("accommodation"));
206         dataTag = QByteArray("multiple valid categories") + suffix;
207         QTest::newRow(dataTag) << area
208                                << QString()
209                                << (QList<QPlaceCategory>()
210                                    << eatDrinkCat
211                                    << accommodationCat)
212                                << QPlaceSearchRequest::UnspecifiedHint
213                                << QPlaceReply::NoError
214                                << SomeResults;
215 
216         QPlaceCategory nonExistentCat;
217         nonExistentCat.setCategoryId(QStringLiteral("klingon cuisine"));
218         dataTag  = QByteArray("non-existent category") + suffix;
219         QTest::newRow(dataTag) << area
220                                << QString()
221                                << (QList<QPlaceCategory>()
222                                    << nonExistentCat)
223                                << QPlaceSearchRequest::UnspecifiedHint
224                                << QPlaceReply::NoError
225                                << NoResults;
226 
227         dataTag = QByteArray("search term and category") + suffix;
228         QTest::newRow(dataTag) << area
229                                << "sushi"
230                                << (QList<QPlaceCategory>()
231                                    << eatDrinkCat)
232                                << QPlaceSearchRequest::UnspecifiedHint
233                                << QPlaceReply::BadArgumentError
234                                << NoResults;
235     }
236 
237 
238     //invalid areas and boundary testing
239     QList<QByteArray> dataTags;
240     QList<QGeoShape> areas;
241     QList<QPlaceReply::Error> errors;
242     QList<ExpectedResults> results;
243     commonAreas(&dataTags, &areas, &errors, &results);
244 
245     for (int i = 0; i < dataTags.count(); ++i) {
246         QTest::newRow(dataTags.at(i)) << areas.at(i)
247                                       << "sushi"
248                                       << QList<QPlaceCategory>()
249                                       << QPlaceSearchRequest::UnspecifiedHint
250                                       << errors.at(i)
251                                       << results.at(i);
252     }
253 
254     //relevancy hints will be ignored by the backend, but should give a valid result
255     QTest::newRow("check using a distance relevancy hint")
256             << static_cast<QGeoShape>(QGeoCircle(QGeoCoordinate(-27.5, 153)))
257             << QStringLiteral("sushi")
258             << QList<QPlaceCategory>()
259             << QPlaceSearchRequest::DistanceHint
260             << QPlaceReply::NoError
261             << AnyResults;
262 
263     QTest::newRow("check using lexical place name hint")
264             << static_cast<QGeoShape>(QGeoCircle(QGeoCoordinate(-27.5, 153)))
265             << QStringLiteral("sushi")
266             << QList<QPlaceCategory>()
267             << QPlaceSearchRequest::LexicalPlaceNameHint
268             << QPlaceReply::NoError
269             << AnyResults;
270 }
271 
searchResultFields()272 void tst_QPlaceManagerNokia::searchResultFields()
273 {
274     //check that using a distance relevancy hint will give a valid result
275     //even though it will be ignored by the backend.
276     QPlaceSearchRequest searchRequest;
277     searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(-27.5, 153)));
278     searchRequest.setSearchTerm(QStringLiteral("sushi"));
279 
280     QPlaceSearchReply *reply = placeManager->search(searchRequest);
281     QSignalSpy spy(reply, SIGNAL(finished()));
282     QTRY_VERIFY_WITH_TIMEOUT(spy.count() == 1, Timeout);
283     QVERIFY(reply->results().count() > 0);
284 
285     //check that search results have basic data filled in
286     QPlaceResult result= reply->results().at(0);
287     QVERIFY(!result.title().isEmpty());
288     QVERIFY(!result.icon().url().isEmpty());
289     QVERIFY(!qIsNaN(result.distance()));
290     QVERIFY(!result.place().name().isEmpty());
291     QVERIFY(result.place().location().coordinate().isValid());
292     QVERIFY(!result.place().location().address().text().isEmpty());
293     QVERIFY(!result.place().location().address().isTextGenerated());
294     QVERIFY(result.place().categories().count() == 1);//only primary category retrieved on
295                                                       //search
296 
297     //sponsored and ratings fields are optional and thus have not been explicitly tested.
298 }
299 
recommendations()300 void tst_QPlaceManagerNokia::recommendations()
301 {
302     QFETCH(QString, recommendationId);
303     QFETCH(QString, searchTerm);
304     QFETCH(QGeoShape, searchArea);
305     QFETCH(QList<QPlaceCategory>, categories);
306     QFETCH(QPlaceReply::Error, error);
307 
308     QPlaceSearchRequest searchRequest;
309     searchRequest.setRecommendationId(recommendationId);
310     searchRequest.setSearchTerm(searchTerm);
311     searchRequest.setSearchArea(searchArea);
312     searchRequest.setCategories(categories);
313 
314     QList<QPlace> results;
315     QVERIFY(doSearch(searchRequest, &results, error));
316 
317     if (error == QPlaceReply::NoError)
318         QVERIFY(results.count() > 0);
319 }
320 
recommendations_data()321 void tst_QPlaceManagerNokia::recommendations_data()
322 {
323     QTest::addColumn<QString>("recommendationId");
324     QTest::addColumn<QString>("searchTerm");
325     QTest::addColumn<QGeoShape>("searchArea");
326     QTest::addColumn<QList<QPlaceCategory> >("categories");
327     QTest::addColumn<QPlaceReply::Error>("error");
328 
329     QPlaceCategory eatDrinkCat;
330     eatDrinkCat.setCategoryId(QStringLiteral("eat-drink"));
331 
332     QTest::newRow("search recommendations with valid id")
333             << QString(ValidKnownPlaceId)
334             << QString()
335             << QGeoShape()
336             << QList<QPlaceCategory>()
337             << QPlaceReply::NoError;
338 
339     QTest::newRow("search for recommendations with invalid id")
340             << QStringLiteral("does_not_exist_id")
341             << QString()
342             << QGeoShape()
343             << QList<QPlaceCategory>()
344             << QPlaceReply::PlaceDoesNotExistError;
345 
346     QTest::newRow("search for recommendations with id and search term")
347             << QString(ValidKnownPlaceId)
348             << QStringLiteral("sushi")
349             << QGeoShape()
350             << QList<QPlaceCategory>()
351             << QPlaceReply::BadArgumentError;
352 
353     QTest::newRow("search for recommendations with an id and category")
354             << QString(ValidKnownPlaceId)
355             << QString()
356             << QGeoShape()
357             << (QList<QPlaceCategory>() << eatDrinkCat)
358             << QPlaceReply::BadArgumentError;
359 
360     QTest::newRow("search for recommendations with id, search term and category")
361             << QString(ValidKnownPlaceId)
362             << QStringLiteral("sushi")
363             << QGeoShape()
364             << (QList<QPlaceCategory>() << eatDrinkCat)
365             << QPlaceReply::BadArgumentError;
366 
367     QTest::newRow("search for recommendations with an id and search area")
368             << QString(ValidKnownPlaceId)
369             << QString()
370             << static_cast<QGeoShape>(QGeoCircle(QGeoCoordinate(-27.5, 153)))
371             << QList<QPlaceCategory>()
372             << QPlaceReply::BadArgumentError;
373 }
374 
details()375 void tst_QPlaceManagerNokia::details()
376 {
377     QSKIP("Fetching details from HERE place server always fails - QTBUG-44837");
378     //fetch the details of a valid place
379     QPlace place;
380     QVERIFY(doFetchDetails(ValidKnownPlaceId, &place));
381     QVERIFY(!place.name().isEmpty());
382     QVERIFY(!place.icon().url().isEmpty());
383     QStringList contactTypes = place.contactTypes();
384     QVERIFY(!contactTypes.isEmpty());
385     foreach (const QString &contactType, contactTypes) {
386         QList<QPlaceContactDetail> details = place.contactDetails(contactType);
387         QVERIFY(details.count() > 0);
388         foreach (const QPlaceContactDetail &detail, details) {
389             QVERIFY(!detail.label().isEmpty());
390             QVERIFY(!detail.value().isEmpty());
391         }
392     }
393 
394     QVERIFY(place.location().coordinate().isValid());
395     QVERIFY(!place.location().address().isEmpty());
396     QVERIFY(!place.location().address().text().isEmpty());
397     QVERIFY(!place.location().address().isTextGenerated());
398 
399     QVERIFY(place.ratings().average() >= 1 && place.ratings().average() <= 5);
400     QVERIFY(place.ratings().maximum() == 5);
401     QVERIFY(place.ratings().count() >  0);
402 
403     QVERIFY(place.categories().count() > 0);
404     foreach (const QPlaceCategory &category, place.categories()) {
405         QVERIFY(!category.name().isEmpty());
406         QVERIFY(!category.categoryId().isEmpty());
407         QVERIFY(!category.icon().url().isEmpty());
408     }
409 
410     QVERIFY(!place.extendedAttributeTypes().isEmpty());
411     QVERIFY(place.visibility() == QLocation::PublicVisibility);
412     QVERIFY(place.detailsFetched());
413 
414     //attributions are optional and thus have not been explicitly tested.
415 
416     //fetch the details of a non-existent place
417     QVERIFY(doFetchDetails(QStringLiteral("does_not_exist"), &place,
418                            QPlaceReply::PlaceDoesNotExistError));
419 }
420 
categories()421 void tst_QPlaceManagerNokia::categories()
422 {
423     QVERIFY(doInitializeCategories());
424 
425     QList<QPlaceCategory> categories = placeManager->childCategories();
426     QVERIFY(categories.count() > 0);
427     foreach (const QPlaceCategory &category, categories) {
428         //check that we have valid fields
429         QVERIFY(!category.categoryId().isEmpty());
430         QVERIFY(!category.name().isEmpty());
431         QVERIFY(!category.icon().url().isEmpty());
432 
433         //check we can retrieve the very same category by id
434         QCOMPARE(placeManager->category(category.categoryId()), category);
435 
436         //the here plugin supports a two-level level category tree
437         QVERIFY(placeManager->parentCategoryId(category.categoryId()).isEmpty());
438         const QList<QPlaceCategory> childCats =
439                 placeManager->childCategories(category.categoryId());
440         if (!childCats.isEmpty()) {
441             foreach (const QPlaceCategory &child, childCats) {
442                 // only two levels of categories hence 2.nd level has no further children
443                 QVERIFY(placeManager->childCategories(child.categoryId()).isEmpty());
444                 QVERIFY(placeManager->parentCategoryId(child.categoryId()) == category.categoryId());
445             }
446         }
447     }
448 }
449 
suggestions()450 void tst_QPlaceManagerNokia::suggestions()
451 {
452     QFETCH(QGeoShape, area);
453     QFETCH(QString, searchTerm);
454     QFETCH(QPlaceReply::Error, error);
455     QFETCH(ExpectedResults, expectedResults);
456 
457     QPlaceSearchRequest searchRequest;
458     searchRequest.setSearchArea(area);
459     searchRequest.setSearchTerm(searchTerm);
460 
461     QStringList results;
462     QVERIFY(doSearchSuggestions(searchRequest, &results, error));
463 
464     if (expectedResults == NoResults)
465         QVERIFY(results.count() == 0);
466     else if (expectedResults == SomeResults)
467         QVERIFY(results.count() > 0);
468 }
469 
470 
suggestions_data()471 void tst_QPlaceManagerNokia::suggestions_data()
472 {
473     QTest::addColumn<QGeoShape>("area");
474     QTest::addColumn<QString>("searchTerm");
475     QTest::addColumn<QPlaceReply::Error> ("error");
476     QTest::addColumn<ExpectedResults>("expectedResults");
477 
478     for (int i = 0; i < 3; i++) {
479         QByteArray suffix;
480         QGeoShape area;
481         if (i == 0) {
482             area = QGeoCircle(QGeoCoordinate(-27.5, 153));
483             suffix = " (Circle - center only)";
484         } else if (i == 1) {
485             area = QGeoCircle(QGeoCoordinate(-27.5, 153), 5000);
486             suffix = " (Circle - with radius specified)";
487         } else {
488             area = QGeoRectangle(QGeoCoordinate(-26.5, 152), QGeoCoordinate(-28.5, 154));
489             suffix = " (Rectangle)";
490         }
491 
492         QByteArray dataTag = QByteArray("valid usage") + suffix;
493         QTest::newRow(dataTag) << area
494                                << "sus"
495                                << QPlaceReply::NoError
496                                << SomeResults;
497     }
498 
499     //invalid areas and boundary testing
500     QList<QByteArray> dataTags;
501     QList<QGeoShape> areas;
502     QList<QPlaceReply::Error> errors;
503     QList<ExpectedResults> results;
504     commonAreas(&dataTags, &areas, &errors, &results);
505 
506     for (int i = 0; i < dataTags.count(); ++i) {
507         QTest::newRow(dataTags.at(i)) << areas.at(i)
508                                       << "sus"
509                                       << errors.at(i)
510                                       << results.at(i);
511     }
512 
513     QTest::newRow("no text") << static_cast<QGeoShape>(QGeoCircle(QGeoCoordinate(-27.5, 153)))
514                              << QString()
515                              << QPlaceReply::NoError
516                              << NoResults;
517 }
518 
suggestionsMisc()519 void tst_QPlaceManagerNokia::suggestionsMisc()
520 {
521     //check providing a distance relevancy hint (should be ignored)
522     QPlaceSearchRequest searchRequest;
523     QStringList results;
524     searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(-27.5, 153)));
525     searchRequest.setSearchTerm(QStringLiteral("sus"));
526     searchRequest.setRelevanceHint(QPlaceSearchRequest::DistanceHint);
527     QVERIFY(doSearchSuggestions(searchRequest, &results, QPlaceReply::NoError));
528     QVERIFY(results.count() > 0);
529     searchRequest.clear();
530 
531     //check porviding a lexical place name relevancy hint (should be ignored)
532     searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(-27.5, 153)));
533     searchRequest.setSearchTerm(QStringLiteral("sus"));
534     searchRequest.setRelevanceHint(QPlaceSearchRequest::LexicalPlaceNameHint);
535     QVERIFY(doSearchSuggestions(searchRequest, &results, QPlaceReply::NoError));
536     QVERIFY(results.count() > 0);
537     searchRequest.clear();
538 
539     //check providing a category
540     QPlaceCategory eatDrinkCat;
541     eatDrinkCat.setCategoryId(QStringLiteral("eat-drink"));
542     searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(-27.5, 153)));
543     searchRequest.setSearchTerm(QStringLiteral("sus"));
544     searchRequest.setCategory(eatDrinkCat);
545     QVERIFY(doSearchSuggestions(searchRequest, &results, QPlaceReply::BadArgumentError));
546     QCOMPARE(results.count(), 0);
547     searchRequest.clear();
548 
549     //check providing a recommendation id
550     searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(-27.5, 153)));
551     searchRequest.setSearchTerm(QStringLiteral("sus"));
552     searchRequest.setRecommendationId("id");
553     QVERIFY(doSearchSuggestions(searchRequest, &results, QPlaceReply::BadArgumentError));
554 }
555 
locale()556 void tst_QPlaceManagerNokia::locale()
557 {
558     //check that the defualt locale is set
559     QCOMPARE(placeManager->locales().count(), 1);
560     QCOMPARE(placeManager->locales().at(0), QLocale());
561 
562     //check that we can set different locales for the categories
563     placeManager->setLocale(QLocale("en"));
564     QVERIFY(doInitializeCategories());
565     QList<QPlaceCategory> enCategories = placeManager->childCategories();
566     QVERIFY(enCategories.count() > 0);
567 
568     placeManager->setLocale(QLocale("fi"));
569     QVERIFY(doInitializeCategories());
570     QList<QPlaceCategory> fiCategories = placeManager->childCategories();
571 
572     foreach (const QPlaceCategory enCat, enCategories) {
573         foreach (const QPlaceCategory fiCat, fiCategories) {
574             if (enCat.categoryId() == fiCat.categoryId()) {
575                 QVERIFY(fiCat.name() != enCat.name());
576                 QVERIFY(fiCat == placeManager->category(fiCat.categoryId()));
577             }
578         }
579     }
580 
581     // we are skipping the check below because we are requesting
582     // details for a place without a search before. This implies
583     // URL templating must be possible which the HERE place
584     // server refuses.
585 
586     QSKIP("remainder of test skipped due to QTBUG-44837");
587 
588     //check that setting a locale will affect place detail fetches.
589     QPlace place;
590     placeManager->setLocale(QLocale("en"));
591     QVERIFY(doFetchDetails(ValidKnownPlaceId,
592                            &place));
593     QString englishName = place.name();
594     placeManager->setLocale(QLocale("fr"));
595     QVERIFY(doFetchDetails(ValidKnownPlaceId,
596                            &place));
597     QVERIFY(englishName != place.name());
598 }
599 
content()600 void tst_QPlaceManagerNokia::content()
601 {
602     QFETCH(QPlaceContent::Type, type);
603 
604     //check fetching of content
605     QPlaceContentRequest request;
606     request.setContentType(type);
607     request.setPlaceId(ValidKnownPlaceId);
608     QPlaceContent::Collection results;
609     QVERIFY(doFetchContent(request, &results));
610 
611     QVERIFY(results.count() > 0);
612 
613     for (auto iter = results.cbegin(), end = results.cend(); iter != end; ++iter) {
614         switch (type) {
615         case (QPlaceContent::ImageType): {
616             QPlaceImage image = iter.value();
617             QVERIFY(!image.url().isEmpty());
618             break;
619         } case (QPlaceContent::ReviewType) : {
620             QPlaceReview review = iter.value();
621             QVERIFY(!review.dateTime().isValid());
622             QVERIFY(!review.text().isEmpty());
623             QVERIFY(review.rating() >= 1 && review.rating() <= 5);
624 
625             //title and language fields are optional and thus have not been
626             //explicitly tested
627             break;
628         } case (QPlaceContent::EditorialType): {
629             QPlaceEditorial editorial = iter.value();
630             QVERIFY(!editorial.text().isEmpty());
631 
632             //The language field is optional and thus has not been
633             //explicitly tested.
634             break;
635         } default:
636             QFAIL("Unknown content type");
637         }
638     }
639 
640     //check total count
641     QPlaceContentReply *contentReply = placeManager->getPlaceContent(request);
642     QSignalSpy contentSpy(contentReply, SIGNAL(finished()));
643     QTRY_VERIFY_WITH_TIMEOUT(contentSpy.count() ==1, Timeout);
644     QVERIFY(contentReply->totalCount() > 0);
645 
646     if (contentReply->totalCount() >= 2) {
647         //try testing with a limit
648         request.setLimit(1);
649         QPlaceContent::Collection newResults;
650         QVERIFY(doFetchContent(request, &newResults));
651         QCOMPARE(newResults.count(), 1);
652         QCOMPARE(newResults.values().first(), results.value(0));
653     }
654 }
655 
content_data()656 void tst_QPlaceManagerNokia::content_data()
657 {
658     QTest::addColumn<QPlaceContent::Type>("type");
659 
660     QTest::newRow("images") << QPlaceContent::ImageType;
661     QTest::newRow("reviews") << QPlaceContent::ReviewType;
662     QTest::newRow("editorials") << QPlaceContent::EditorialType;
663 }
664 
unsupportedFunctions()665 void tst_QPlaceManagerNokia::unsupportedFunctions()
666 {
667     QPlace place;
668     place.setName(QStringLiteral("Brisbane"));
669 
670     QVERIFY(doSavePlace(place, QPlaceReply::UnsupportedError));
671     QVERIFY(doRemovePlace(place, QPlaceReply::UnsupportedError));
672 
673     QPlaceCategory category;
674     category.setName(QStringLiteral("Accommodation"));
675     QVERIFY(doSaveCategory(category, QPlaceReply::UnsupportedError));
676     QVERIFY(doRemoveCategory(category, QPlaceReply::UnsupportedError));
677 }
678 
commonAreas(QList<QByteArray> * dataTags,QList<QGeoShape> * areas,QList<QPlaceReply::Error> * errors,QList<ExpectedResults> * results)679 void tst_QPlaceManagerNokia::commonAreas(QList<QByteArray> *dataTags,
680                                           QList<QGeoShape> *areas,
681                                           QList<QPlaceReply::Error> *errors,
682                                           QList<ExpectedResults> *results)
683 {
684     Q_ASSERT(dataTags);
685     Q_ASSERT(areas);
686     dataTags->append("Unknown shape for search area");
687     areas->append(QGeoShape());
688     errors->append(QPlaceReply::BadArgumentError);
689     results->append(NoResults);
690 
691     dataTags->append("NaN coordinate");
692     areas->append(QGeoCircle(QGeoCoordinate()));
693     errors->append(QPlaceReply::BadArgumentError);
694     results->append(NoResults);
695 
696     dataTags->append("Valid latitude (upper boundary)");
697     areas->append(QGeoCircle(QGeoCoordinate(90.0, 45)));
698     errors->append(QPlaceReply::NoError);
699     results->append(AnyResults);
700 
701     dataTags->append("Invalid latitude (upper boundary)");
702     areas->append(QGeoCircle(QGeoCoordinate(90.1, 45)));
703     errors->append(QPlaceReply::BadArgumentError);
704     results->append(NoResults);
705 
706     dataTags->append("Valid latitude (lower boundary)");
707     areas->append(QGeoCircle(QGeoCoordinate(-90.0, 45)));
708     errors->append(QPlaceReply::NoError);
709     results->append(AnyResults);
710 
711     dataTags->append("Invalid latitude (lower boundary)");
712     areas->append(QGeoCircle(QGeoCoordinate(-90.1, 45)));
713     errors->append(QPlaceReply::BadArgumentError);
714     results->append(NoResults);
715 
716     dataTags->append("Valid longitude (lower boundary)");
717     areas->append(QGeoCircle(QGeoCoordinate(-45, -180.0)));
718     errors->append(QPlaceReply::NoError);
719     results->append(AnyResults);
720 
721     dataTags->append("Invalid longitude (lower boundary)");
722     areas->append(QGeoCircle(QGeoCoordinate(-45, -180.1)));
723     errors->append(QPlaceReply::BadArgumentError);
724     results->append(NoResults);
725 
726     dataTags->append("Valid longitude (upper boundary)");
727     areas->append(QGeoCircle(QGeoCoordinate(-45, 180.0)));
728     errors->append(QPlaceReply::NoError);
729     results->append(AnyResults);
730 
731     dataTags->append("Invalid longitude (upper boundary)");
732     areas->append(QGeoCircle(QGeoCoordinate(-45, 180.1)));
733     errors->append(QPlaceReply::BadArgumentError);
734     results->append(NoResults);
735 
736     dataTags->append("Invalid rectangular area");
737     areas->append(QGeoRectangle(QGeoCoordinate(20,20),
738                   QGeoCoordinate(30,10)));
739     errors->append(QPlaceReply::BadArgumentError);
740     results->append(NoResults);
741 }
742 
743 QTEST_GUILESS_MAIN(tst_QPlaceManagerNokia)
744 
745 #include "tst_places.moc"
746