1 /*
2     SPDX-FileCopyrightText: 2013 Andreas Cord-Landwehr <cordlandwehr@kde.org>
3 
4     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
5 */
6 
7 #include "test_courseresource.h"
8 #include "../mocks/languagestub.h"
9 #include "core/language.h"
10 #include "core/phonemegroup.h"
11 #include "core/phrase.h"
12 #include "core/resources/courseresource.h"
13 #include "core/unit.h"
14 #include "resourcerepositorystub.h"
15 #include <QDebug>
16 #include <QFile>
17 #include <QIODevice>
18 #include <QSignalSpy>
19 #include <QTemporaryFile>
20 #include <QTest>
21 #include <QXmlSchema>
22 #include <QXmlSchemaValidator>
23 
TestCourseResource()24 TestCourseResource::TestCourseResource()
25 {
26 }
27 
init()28 void TestCourseResource::init()
29 {
30 }
31 
cleanup()32 void TestCourseResource::cleanup()
33 {
34 }
35 
loadCourseResource()36 void TestCourseResource::loadCourseResource()
37 {
38     std::shared_ptr<ILanguage> language(new LanguageStub("de"));
39     auto group = std::static_pointer_cast<LanguageStub>(language)->addPhonemeGroup("id", "title");
40     group->addPhoneme("g", "G");
41     group->addPhoneme("u", "U");
42     std::vector<std::shared_ptr<ILanguage>> languages;
43     languages.push_back(language);
44     ResourceRepositoryStub repository(languages);
45 
46     const QString courseDirectory = qApp->applicationDirPath() + "/../autotests/unittests/data/courses/de/";
47     const QString courseFile = courseDirectory + "de.xml";
48 
49     auto course = CourseResource::create(QUrl::fromLocalFile(courseFile), &repository);
50     QCOMPARE(course->file().toLocalFile(), courseFile);
51     QCOMPARE(course->id(), "de");
52     QCOMPARE(course->foreignId(), "artikulate-basic");
53     QCOMPARE(course->title(), "Artikulate Deutsch");
54     QCOMPARE(course->description(), "Ein Kurs in (hoch-)deutscher Aussprache.");
55     QVERIFY(course->language() != nullptr);
56     QCOMPARE(course->language()->id(), "de");
57     QCOMPARE(course->units().count(), 1);
58     QCOMPARE(course->units().first()->course(), course);
59 
60     const auto unit = course->units().first();
61     QVERIFY(unit != nullptr);
62     QCOMPARE(unit->id(), "1");
63     QCOMPARE(unit->title(), QStringLiteral("Auf der Straße"));
64     QCOMPARE(unit->foreignId(), "{dd60f04a-eb37-44b7-9787-67aaf7d3578d}");
65     QCOMPARE(unit->course(), course);
66 
67     QCOMPARE(unit->phrases().count(), 3);
68     // note: this test takes the silent assumption that phrases are added to the list in same
69     //   order as they are defined in the file. This assumption should be made explicit or dropped
70     const auto firstPhrase = unit->phrases().first();
71     QVERIFY(firstPhrase != nullptr);
72     QCOMPARE(firstPhrase->id(), "1");
73     QCOMPARE(firstPhrase->foreignId(), "{3a4c1926-60d7-44c6-80d1-03165a641c75}");
74     QCOMPARE(firstPhrase->text(), "Guten Tag.");
75     QCOMPARE(firstPhrase->soundFileUrl(), courseDirectory + "de_01.ogg");
76     QCOMPARE(firstPhrase->type(), Phrase::Type::Sentence);
77     QCOMPARE(firstPhrase->phonemes().count(), 2);
78 }
79 
loadCourseResourceSkipIncomplete()80 void TestCourseResource::loadCourseResourceSkipIncomplete()
81 {
82     std::shared_ptr<ILanguage> language(new LanguageStub("de"));
83     auto group = std::static_pointer_cast<LanguageStub>(language)->addPhonemeGroup("id", "title");
84     group->addPhoneme("g", "G");
85     group->addPhoneme("u", "U");
86     std::vector<std::shared_ptr<ILanguage>> languages;
87     languages.push_back(language);
88     ResourceRepositoryStub repository(languages);
89 
90     const QString courseDirectory = "data/courses/de/";
91     const QString courseFile = courseDirectory + "de.xml";
92 
93     auto course = CourseResource::create(QUrl::fromLocalFile(courseFile), &repository, true);
94     QCOMPARE(course->file().toLocalFile(), courseFile);
95     QCOMPARE(course->id(), "de");
96     QCOMPARE(course->units().count(), 1);
97     QCOMPARE(course->units().first()->course(), course);
98 
99     const auto unit = course->units().first();
100     QVERIFY(unit != nullptr);
101     QCOMPARE(unit->id(), "1");
102     QCOMPARE(unit->phrases().count(), 2);
103 }
104 
unitAddAndRemoveHandling()105 void TestCourseResource::unitAddAndRemoveHandling()
106 {
107     // boilerplate
108     std::shared_ptr<ILanguage> language(new LanguageStub("de"));
109     ResourceRepositoryStub repository({language});
110 
111     const QString courseDirectory = qApp->applicationDirPath() + "/../autotests/unittests/data/courses/de/";
112     const QString courseFile = courseDirectory + "de.xml";
113     auto course = CourseResource::create(QUrl::fromLocalFile(courseFile), &repository);
114 
115     // begin of test
116     auto unit = Unit::create();
117     unit->setId("testunit");
118     const int initialUnitNumber = course->units().count();
119     QCOMPARE(initialUnitNumber, 1);
120     QSignalSpy spyAboutToBeAdded(course.get(), SIGNAL(unitAboutToBeAdded(std::shared_ptr<Unit>, int)));
121     QSignalSpy spyAdded(course.get(), SIGNAL(unitAdded()));
122     QCOMPARE(spyAboutToBeAdded.count(), 0);
123     QCOMPARE(spyAdded.count(), 0);
124     auto sharedUnit = course->addUnit(std::move(unit));
125     QCOMPARE(course->units().count(), initialUnitNumber + 1);
126     QCOMPARE(spyAboutToBeAdded.count(), 1);
127     QCOMPARE(spyAdded.count(), 1);
128     QCOMPARE(sharedUnit->course(), course);
129 }
130 
coursePropertyChanges()131 void TestCourseResource::coursePropertyChanges()
132 {
133     // boilerplate
134     std::shared_ptr<ILanguage> language(new LanguageStub("de"));
135     ResourceRepositoryStub repository({language});
136 
137     const QString courseDirectory = qApp->applicationDirPath() + "/../autotests/unittests/data/courses/de/";
138     const QString courseFile = courseDirectory + "de.xml";
139     auto course = CourseResource::create(QUrl::fromLocalFile(courseFile), &repository);
140 
141     // id
142     {
143         const QString value = "newId";
144         QSignalSpy spy(course.get(), SIGNAL(idChanged()));
145         QCOMPARE(spy.count(), 0);
146         course->setId(value);
147         QCOMPARE(course->id(), value);
148         QCOMPARE(spy.count(), 1);
149     }
150 
151     // foreign id
152     {
153         const QString value = "newForeignId";
154         QSignalSpy spy(course.get(), SIGNAL(foreignIdChanged()));
155         QCOMPARE(spy.count(), 0);
156         course->setForeignId(value);
157         QCOMPARE(course->foreignId(), value);
158         QCOMPARE(spy.count(), 1);
159     }
160 
161     // title
162     {
163         const QString value = "newTitle";
164         QSignalSpy spy(course.get(), SIGNAL(titleChanged()));
165         QCOMPARE(spy.count(), 0);
166         course->setTitle(value);
167         QCOMPARE(course->title(), value);
168         QCOMPARE(spy.count(), 1);
169     }
170 
171     // title
172     {
173         const QString value = "newI18nTitle";
174         QSignalSpy spy(course.get(), SIGNAL(i18nTitleChanged()));
175         QCOMPARE(spy.count(), 0);
176         course->setI18nTitle(value);
177         QCOMPARE(course->i18nTitle(), value);
178         QCOMPARE(spy.count(), 1);
179     }
180 
181     // description
182     {
183         const QString value = "newDescription";
184         QSignalSpy spy(course.get(), SIGNAL(descriptionChanged()));
185         QCOMPARE(spy.count(), 0);
186         course->setDescription(value);
187         QCOMPARE(course->description(), value);
188         QCOMPARE(spy.count(), 1);
189     }
190 
191     // language
192     {
193         std::shared_ptr<Language> testLanguage;
194         QSignalSpy spy(course.get(), SIGNAL(languageChanged()));
195         QCOMPARE(spy.count(), 0);
196         course->setLanguage(testLanguage);
197         QCOMPARE(course->language(), testLanguage);
198         QCOMPARE(spy.count(), 1);
199     }
200 }
201 
202 QTEST_GUILESS_MAIN(TestCourseResource)
203