File indexing completed on 2024-10-06 05:12:52
0001 /* This file is part of Kairo Timer 0002 0003 SPDX-FileCopyrightText: 2016 (c) Kevin Ottens <ervin@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0006 0007 */ 0008 0009 #include <QtTest> 0010 #include <QSignalSpy> 0011 0012 #include <memory> 0013 0014 #include "timercontrol.h" 0015 0016 class TimerControlTest : public QObject 0017 { 0018 Q_OBJECT 0019 private slots: 0020 void shouldHaveDefaultState() 0021 { 0022 // GIVEN 0023 auto control = std::make_unique<TimerControl>(); 0024 0025 // THEN 0026 QCOMPARE(control->model(), TimerModel{}); 0027 QCOMPARE(control->text(), QString()); 0028 QCOMPARE(control->value(), 0); 0029 QCOMPARE(control->formattedValue(), QStringLiteral("00:00.0")); 0030 QCOMPARE(control->duration(), -1); 0031 QCOMPARE(control->isRunning(), false); 0032 } 0033 0034 void shouldDeriveValuesFromModel_data() 0035 { 0036 QTest::addColumn<TimerModel>("model"); 0037 QTest::addColumn<QString>("expectedText"); 0038 QTest::addColumn<int>("expectedValue"); 0039 QTest::addColumn<QString>("expectedFormattedValue"); 0040 QTest::addColumn<int>("expectedDuration"); 0041 0042 QTest::newRow("invalid") << TimerModel{} << QString() << 0 << QStringLiteral("00:00.0") <<-1; 0043 QTest::newRow("countdown") << TimerModel{"foo", 10000} << "foo" << 10000 << QStringLiteral("00:10.0") << 10000; 0044 QTest::newRow("countdown") << TimerModel{"baz", 1050300} << "baz" << 1050300 << QStringLiteral("17:30.3") << 1050300; 0045 QTest::newRow("countdown") << TimerModel{"baz", 34570900} << "baz" << 34570900 << QStringLiteral("576:10.9") << 34570900; 0046 QTest::newRow("stopwatch") << TimerModel{"bar"} << "bar" << 0 << QStringLiteral("00:00.0") << 0; 0047 } 0048 0049 void shouldDeriveValuesFromModel() 0050 { 0051 // GIVEN 0052 auto control = std::make_unique<TimerControl>(); 0053 auto modelSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::modelChanged); 0054 auto textSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::textChanged); 0055 auto valueSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::valueChanged); 0056 auto durationSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::durationChanged); 0057 0058 QFETCH(TimerModel, model); 0059 QFETCH(QString, expectedText); 0060 QFETCH(int, expectedValue); 0061 QFETCH(QString, expectedFormattedValue); 0062 QFETCH(int, expectedDuration); 0063 0064 // WHEN 0065 control->setModel(model); 0066 0067 // THEN 0068 QCOMPARE(control->model(), model); 0069 QCOMPARE(control->text(), expectedText); 0070 QCOMPARE(control->value(), expectedValue); 0071 QCOMPARE(control->formattedValue(), expectedFormattedValue); 0072 QCOMPARE(control->duration(), expectedDuration); 0073 0074 if (model.isValid()) { 0075 QCOMPARE(modelSpy->size(), 1); 0076 QCOMPARE(modelSpy->takeFirst().first().value<TimerModel>(), model); 0077 0078 QCOMPARE(textSpy->size(), 1); 0079 QCOMPARE(textSpy->takeFirst().first().toString(), expectedText); 0080 0081 if (model.duration() >= 0) { 0082 QCOMPARE(durationSpy->size(), 1); 0083 QCOMPARE(durationSpy->takeFirst().first().toInt(), expectedDuration); 0084 } else { 0085 QCOMPARE(durationSpy->size(), 0); 0086 } 0087 0088 if (model.duration() != 0) { 0089 QCOMPARE(valueSpy->size(), 1); 0090 QCOMPARE(valueSpy->takeFirst().first().toInt(), expectedValue); 0091 } else { 0092 QCOMPARE(valueSpy->size(), 0); 0093 } 0094 } else { 0095 QCOMPARE(textSpy->size(), 0); 0096 QCOMPARE(valueSpy->size(), 0); 0097 QCOMPARE(durationSpy->size(), 0); 0098 } 0099 0100 // WHEN 0101 control->setModel(model); 0102 0103 // THEN 0104 QCOMPARE(textSpy->size(), 0); 0105 QCOMPARE(valueSpy->size(), 0); 0106 QCOMPARE(durationSpy->size(), 0); 0107 } 0108 0109 void shouldDeriveValuesFromMovedModel_data() 0110 { 0111 shouldDeriveValuesFromModel_data(); 0112 } 0113 0114 void shouldDeriveValuesFromMovedModel() 0115 { 0116 // GIVEN 0117 auto control = std::make_unique<TimerControl>(); 0118 auto textSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::textChanged); 0119 auto valueSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::valueChanged); 0120 auto durationSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::durationChanged); 0121 0122 QFETCH(TimerModel, model); 0123 QFETCH(QString, expectedText); 0124 QFETCH(int, expectedValue); 0125 QFETCH(QString, expectedFormattedValue); 0126 QFETCH(int, expectedDuration); 0127 0128 // WHEN 0129 auto copy = model; 0130 control->setModel(std::move(copy)); // This should move it in place 0131 0132 // THEN 0133 QCOMPARE(control->model(), model); 0134 QCOMPARE(control->text(), expectedText); 0135 QCOMPARE(control->value(), expectedValue); 0136 QCOMPARE(control->formattedValue(), expectedFormattedValue); 0137 QCOMPARE(control->duration(), expectedDuration); 0138 0139 if (model.isValid()) { 0140 QCOMPARE(textSpy->size(), 1); 0141 QCOMPARE(textSpy->takeFirst().first().toString(), expectedText); 0142 0143 if (model.duration() >= 0) { 0144 QCOMPARE(durationSpy->size(), 1); 0145 QCOMPARE(durationSpy->takeFirst().first().toInt(), expectedDuration); 0146 } else { 0147 QCOMPARE(durationSpy->size(), 0); 0148 } 0149 0150 if (model.duration() != 0) { 0151 QCOMPARE(valueSpy->size(), 1); 0152 QCOMPARE(valueSpy->takeFirst().first().toInt(), expectedValue); 0153 } else { 0154 QCOMPARE(valueSpy->size(), 0); 0155 } 0156 } else { 0157 QCOMPARE(textSpy->size(), 0); 0158 QCOMPARE(valueSpy->size(), 0); 0159 } 0160 0161 // WHEN 0162 control->setModel(std::move(model)); 0163 0164 // THEN 0165 QCOMPARE(textSpy->size(), 0); 0166 QCOMPARE(valueSpy->size(), 0); 0167 QCOMPARE(durationSpy->size(), 0); 0168 } 0169 0170 void shouldDoNothingWhileRunningInvalid() 0171 { 0172 // GIVEN 0173 auto control = std::make_unique<TimerControl>(); 0174 auto textSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::textChanged); 0175 auto valueSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::valueChanged); 0176 auto durationSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::durationChanged); 0177 auto runningSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::runningChanged); 0178 auto finishedSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::timerFinished); 0179 control->setModel(TimerModel{}); 0180 0181 // WHEN 0182 control->setRunning(true); 0183 QTest::qWait(100); 0184 0185 // THEN 0186 QCOMPARE(control->isRunning(), true); 0187 QCOMPARE(textSpy->size(), 0); 0188 QCOMPARE(valueSpy->size(), 0); 0189 QCOMPARE(durationSpy->size(), 0); 0190 QCOMPARE(runningSpy->size(), 1); 0191 QCOMPARE(runningSpy->takeFirst().first().toBool(), true); 0192 QCOMPARE(finishedSpy->size(), 1); 0193 } 0194 0195 void shouldRunCountdown() 0196 { 0197 // GIVEN 0198 auto control = std::make_unique<TimerControl>(); 0199 auto textSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::textChanged); 0200 auto valueSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::valueChanged); 0201 auto durationSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::durationChanged); 0202 auto runningSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::runningChanged); 0203 auto finishedSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::timerFinished); 0204 0205 control->setModel(TimerModel{"rest", 100}); 0206 textSpy->clear(); 0207 valueSpy->clear(); 0208 durationSpy->clear(); 0209 0210 // WHEN 0211 control->setRunning(true); 0212 QTest::qWait(105); 0213 0214 // THEN 0215 QCOMPARE(control->isRunning(), true); 0216 QCOMPARE(textSpy->size(), 0); 0217 QCOMPARE(durationSpy->size(), 0); 0218 QCOMPARE(valueSpy->size(), 10); 0219 for (int value = 100; value != 0; value -= 10) { 0220 QCOMPARE(valueSpy->takeFirst().first().toInt(), value - 10); 0221 } 0222 QCOMPARE(runningSpy->size(), 1); 0223 QCOMPARE(runningSpy->takeFirst().first().toBool(), true); 0224 QCOMPARE(finishedSpy->size(), 1); 0225 } 0226 0227 void shouldRunStopwatch() 0228 { 0229 // GIVEN 0230 auto control = std::make_unique<TimerControl>(); 0231 auto textSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::textChanged); 0232 auto valueSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::valueChanged); 0233 auto durationSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::durationChanged); 0234 auto runningSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::runningChanged); 0235 auto finishedSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::timerFinished); 0236 0237 control->setModel(TimerModel{"run"}); 0238 textSpy->clear(); 0239 valueSpy->clear(); 0240 durationSpy->clear(); 0241 0242 // WHEN 0243 control->setRunning(true); 0244 QTest::qWait(105); 0245 control->setRunning(false); 0246 0247 // THEN 0248 QCOMPARE(control->isRunning(), false); 0249 QCOMPARE(textSpy->size(), 0); 0250 QCOMPARE(durationSpy->size(), 0); 0251 QCOMPARE(valueSpy->size(), 10); 0252 for (int value = 0; value != 100; value += 10) { 0253 QCOMPARE(valueSpy->takeFirst().first().toInt(), value + 10); 0254 } 0255 QCOMPARE(runningSpy->size(), 2); 0256 QCOMPARE(runningSpy->takeFirst().first().toBool(), true); 0257 QCOMPARE(runningSpy->takeFirst().first().toBool(), false); 0258 QCOMPARE(finishedSpy->size(), 0); 0259 } 0260 0261 void shouldKeepRunningDuringModelChanges() 0262 { 0263 // GIVEN 0264 auto control = std::make_unique<TimerControl>(); 0265 auto textSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::textChanged); 0266 auto valueSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::valueChanged); 0267 auto durationSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::durationChanged); 0268 auto runningSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::runningChanged); 0269 auto finishedSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::timerFinished); 0270 auto skippedSpy = std::make_unique<QSignalSpy>(control.get(), &TimerControl::timerSkipped); 0271 0272 control->setModel(TimerModel{"run"}); 0273 textSpy->clear(); 0274 valueSpy->clear(); 0275 durationSpy->clear(); 0276 0277 // WHEN 0278 control->setRunning(true); 0279 QTest::qWait(25); 0280 control->setModel(TimerModel{"rest", 100}); 0281 QTest::qWait(105); 0282 control->setModel(TimerModel{"run"}); 0283 QTest::qWait(35); 0284 control->setModel(TimerModel{"rest again", 100}); 0285 QTest::qWait(55); 0286 control->setRunning(false); 0287 0288 // THEN 0289 QCOMPARE(control->isRunning(), false); 0290 QCOMPARE(runningSpy->size(), 2); 0291 QCOMPARE(runningSpy->takeFirst().first().toBool(), true); 0292 QCOMPARE(runningSpy->takeFirst().first().toBool(), false); 0293 0294 QCOMPARE(textSpy->size(), 3); 0295 QCOMPARE(textSpy->takeFirst().first().toString(), QString("rest")); 0296 QCOMPARE(textSpy->takeFirst().first().toString(), QString("run")); 0297 QCOMPARE(textSpy->takeFirst().first().toString(), QString("rest again")); 0298 0299 const auto expectedValues = QVector<int>{10, 20, 100, 90, 80, 70, 60, 50, 40, 30, 20, 10, 0, 10, 20, 30, 100, 90, 80, 70, 60, 50}; 0300 auto values = QVector<int>(); 0301 while (!valueSpy->isEmpty()) 0302 values << valueSpy->takeFirst().first().toInt(); 0303 qDebug() << values; 0304 qDebug() << expectedValues; 0305 QCOMPARE(values, expectedValues); 0306 0307 const auto expectedDurations = QVector<int>{100, 0, 100}; 0308 auto durations = QVector<int>(); 0309 while (!durationSpy->isEmpty()) 0310 durations << durationSpy->takeFirst().first().toInt(); 0311 qDebug() << durations; 0312 qDebug() << expectedDurations; 0313 QCOMPARE(values, expectedValues); 0314 0315 QCOMPARE(finishedSpy->size(), 1); 0316 QCOMPARE(skippedSpy->size(), 2); 0317 } 0318 0319 void shouldCreateModels() 0320 { 0321 // GIVEN 0322 auto control = std::make_unique<TimerControl>(); 0323 0324 // THEN 0325 auto model = TimerModel{}; 0326 QCOMPARE(control->createModel(), model); 0327 0328 model = TimerModel{"foo"}; 0329 QCOMPARE(control->createModel("foo"), model); 0330 0331 model = TimerModel{"bar", 1000}; 0332 QCOMPARE(control->createModel("bar", 1000), model); 0333 } 0334 }; 0335 0336 QTEST_MAIN(TimerControlTest) 0337 0338 #include "timercontroltest.moc"