Changeset View
Changeset View
Standalone View
Standalone View
autotests/kjsfunctionstest.cpp
- This file was added.
1 | /*************************************************************************** | ||||
---|---|---|---|---|---|
2 | * Copyright (C) 2019 by João Netto <joaonetto901@gmail.com> * | ||||
3 | * * | ||||
4 | * This program is free software; you can redistribute it and/or modify * | ||||
5 | * it under the terms of the GNU General Public License as published by * | ||||
6 | * the Free Software Foundation; either version 2 of the License, or * | ||||
7 | * (at your option) any later version. * | ||||
8 | ***************************************************************************/ | ||||
9 | | ||||
10 | #include <QtTest> | ||||
11 | | ||||
12 | #include <QAbstractItemModel> | ||||
13 | #include <QMap> | ||||
14 | #include <QAbstractButton> | ||||
15 | #include <QMessageBox> | ||||
16 | #include <QMimeType> | ||||
17 | #include <QMimeDatabase> | ||||
18 | #include <QThread> | ||||
19 | #include "../settings_core.h" | ||||
20 | #include "core/action.h" | ||||
21 | #include "core/document.h" | ||||
22 | #include "core/scripter.h" | ||||
23 | #include <core/script/event_p.h> | ||||
24 | #include <core/page.h> | ||||
25 | #include <core/form.h> | ||||
26 | | ||||
27 | #include "../generators/poppler/config-okular-poppler.h" | ||||
28 | | ||||
29 | class MessageBoxHelper : public QObject | ||||
30 | { | ||||
31 | Q_OBJECT | ||||
32 | | ||||
33 | public: | ||||
34 | MessageBoxHelper(QMessageBox::StandardButton b, QString message, QMessageBox::Icon icon, QString title, bool hasCheckBox ) | ||||
35 | : m_button(b), m_clicked(false), m_message(std::move(message)), m_icon(icon), m_title(std::move(title)), m_checkBox(hasCheckBox) | ||||
36 | { | ||||
37 | QTimer::singleShot(0, this, &MessageBoxHelper::closeMessageBox); | ||||
38 | } | ||||
39 | | ||||
40 | ~MessageBoxHelper() | ||||
41 | { | ||||
42 | QVERIFY(m_clicked); | ||||
43 | } | ||||
44 | | ||||
45 | private slots: | ||||
46 | void closeMessageBox() | ||||
47 | { | ||||
48 | QWidgetList allToplevelWidgets = QApplication::topLevelWidgets(); | ||||
49 | QMessageBox *mb = nullptr; | ||||
50 | foreach ( QWidget *w, allToplevelWidgets ) { | ||||
51 | if ( w->inherits( "QMessageBox" ) ) { | ||||
52 | mb = qobject_cast< QMessageBox * >( w ); | ||||
53 | QCOMPARE( mb->text(), m_message ); | ||||
54 | QCOMPARE( mb->windowTitle(), m_title ); | ||||
55 | QCOMPARE( mb->icon(), m_icon ); | ||||
56 | QCheckBox *box = mb->checkBox(); | ||||
57 | QCOMPARE( box != nullptr, m_checkBox ); | ||||
58 | mb->button( m_button )->click(); | ||||
59 | } | ||||
60 | } | ||||
61 | if (!mb) { | ||||
62 | QTimer::singleShot(0, this, &MessageBoxHelper::closeMessageBox); | ||||
63 | return; | ||||
64 | } | ||||
65 | m_clicked = true; | ||||
66 | } | ||||
67 | | ||||
68 | private: | ||||
69 | QMessageBox::StandardButton m_button; | ||||
70 | bool m_clicked; | ||||
71 | QString m_message; | ||||
72 | QMessageBox::Icon m_icon; | ||||
73 | QString m_title; | ||||
74 | bool m_checkBox; | ||||
75 | }; | ||||
76 | | ||||
77 | | ||||
78 | class KJSFunctionsTest: public QObject | ||||
79 | { | ||||
80 | Q_OBJECT | ||||
81 | | ||||
82 | private slots: | ||||
83 | #ifdef HAVE_POPPLER_0_79 | ||||
84 | void initTestCase(); | ||||
85 | void testNthFieldName(); | ||||
86 | void testDisplay(); | ||||
87 | void testSetClearInterval(); | ||||
88 | void testSetClearTimeOut(); | ||||
89 | void testGetOCGs(); | ||||
90 | void cleanupTestCase(); | ||||
91 | void testAlert(); | ||||
92 | void testPrintD(); | ||||
93 | void testPrintD_data(); | ||||
94 | #endif | ||||
95 | private: | ||||
96 | Okular::Document *m_document; | ||||
97 | QMap<QString, Okular::FormField*> m_fields; | ||||
98 | }; | ||||
99 | | ||||
100 | #ifdef HAVE_POPPLER_0_79 | ||||
101 | | ||||
102 | void KJSFunctionsTest::initTestCase() | ||||
103 | { | ||||
104 | Okular::SettingsCore::instance( QStringLiteral("kjsfunctionstest") ); | ||||
105 | m_document = new Okular::Document( nullptr ); | ||||
106 | | ||||
107 | const QString testFile = QStringLiteral( KDESRCDIR "data/kjsfunctionstest.pdf" ); | ||||
108 | QMimeDatabase db; | ||||
109 | const QMimeType mime = db.mimeTypeForFile( testFile ); | ||||
110 | QCOMPARE( m_document->openDocument( testFile, QUrl(), mime), Okular::Document::OpenSuccess ); | ||||
111 | | ||||
112 | const Okular::Page* page = m_document->page( 0 ); | ||||
113 | for ( Okular::FormField *ff: page->formFields() ) | ||||
114 | { | ||||
115 | m_fields.insert( ff->name(), ff ); | ||||
116 | } | ||||
117 | } | ||||
118 | | ||||
119 | void KJSFunctionsTest::testNthFieldName() | ||||
120 | { | ||||
121 | for(int i = 0;i < 21;++i) | ||||
122 | { | ||||
123 | Okular::ScriptAction *action = new Okular::ScriptAction( Okular::JavaScript, QStringLiteral( "var field = Doc.getField( Doc.getNthFieldName(%1) );\ | ||||
124 | field.display = display.visible;" ).arg( i ) ); | ||||
125 | m_document->processAction( action ); | ||||
126 | QVERIFY( m_fields[QString( "0.%1" ).arg(i)]->isVisible() ); | ||||
127 | m_fields[QString( "0.%1" ).arg(i)]->setVisible( false ); | ||||
128 | delete action; | ||||
129 | } | ||||
130 | } | ||||
131 | | ||||
132 | void KJSFunctionsTest::testDisplay() | ||||
133 | { | ||||
134 | Okular::ScriptAction *action = new Okular::ScriptAction( Okular::JavaScript, | ||||
135 | QStringLiteral( "field = Doc.getField(\"0.0\");field.display=display.hidden;\ | ||||
136 | field = Doc.getField(\"0.10\");field.display=display.visible;" ) ); | ||||
137 | m_document->processAction( action ); | ||||
138 | QVERIFY( !m_fields["0.0"]->isVisible() ); | ||||
139 | QVERIFY( !m_fields["0.0"]->isPrintable() ); | ||||
140 | QVERIFY( m_fields["0.10"]->isVisible() ); | ||||
141 | QVERIFY( m_fields["0.10"]->isPrintable() ); | ||||
142 | delete action; | ||||
143 | | ||||
144 | action = new Okular::ScriptAction( Okular::JavaScript, | ||||
145 | QStringLiteral( "field = Doc.getField(\"0.10\");field.display=display.noView;\ | ||||
146 | field = Doc.getField(\"0.15\");field.display=display.noPrint;" ) ); | ||||
147 | m_document->processAction( action ); | ||||
148 | QVERIFY( !m_fields["0.10"]->isVisible() ); | ||||
149 | QVERIFY( m_fields["0.10"]->isPrintable() ); | ||||
150 | QVERIFY( m_fields["0.15"]->isVisible() ); | ||||
151 | QVERIFY( !m_fields["0.15"]->isPrintable() ); | ||||
152 | delete action; | ||||
153 | | ||||
154 | action = new Okular::ScriptAction( Okular::JavaScript, | ||||
155 | QStringLiteral( "field = Doc.getField(\"0.15\");field.display=display.hidden;\ | ||||
156 | field = Doc.getField(\"0.20\");field.display=display.visible;" ) ); | ||||
157 | m_document->processAction( action ); | ||||
158 | QVERIFY( !m_fields["0.15"]->isVisible() ); | ||||
159 | QVERIFY( !m_fields["0.15"]->isPrintable() ); | ||||
160 | QVERIFY( m_fields["0.20"]->isVisible() ); | ||||
161 | QVERIFY( m_fields["0.20"]->isPrintable() ); | ||||
162 | delete action; | ||||
163 | | ||||
164 | action = new Okular::ScriptAction( Okular::JavaScript, | ||||
165 | QStringLiteral( "field = Doc.getField(\"0.20\");field.display=display.hidden;\ | ||||
166 | field = Doc.getField(\"0.0\");field.display=display.visible;" ) ); | ||||
167 | m_document->processAction( action ); | ||||
168 | QVERIFY( !m_fields["0.20"]->isVisible() ); | ||||
169 | QVERIFY( !m_fields["0.20"]->isPrintable() ); | ||||
170 | QVERIFY( m_fields["0.0"]->isVisible() ); | ||||
171 | QVERIFY( m_fields["0.0"]->isPrintable() ); | ||||
172 | delete action; | ||||
173 | } | ||||
174 | | ||||
175 | void delay() | ||||
176 | { | ||||
177 | QTime dieTime= QTime::currentTime().addSecs( 2 ); | ||||
178 | while (QTime::currentTime() < dieTime) | ||||
179 | QCoreApplication::processEvents(QEventLoop::AllEvents, 100); | ||||
180 | } | ||||
181 | | ||||
182 | void KJSFunctionsTest::testSetClearInterval() | ||||
183 | { | ||||
184 | Okular::ScriptAction *action = new Okular::ScriptAction( Okular::JavaScript, | ||||
185 | QStringLiteral( "obj = new Object();obj.idx=0;\ | ||||
186 | obj.inc=function(){field = Doc.getField(Doc.getNthFieldName(obj.idx));\ | ||||
187 | field.display = display.visible;\ | ||||
188 | obj.idx = obj.idx + 1;};\ | ||||
189 | intv = app.setInterval('obj.inc()', 450);obj.idx;" ) ); | ||||
190 | m_document->processAction( action ); | ||||
191 | QVERIFY( m_fields["0.0"]->isVisible() ); | ||||
192 | QVERIFY( !m_fields["0.3"]->isVisible() ); | ||||
193 | delete action; | ||||
194 | delay(); | ||||
195 | | ||||
196 | action = new Okular::ScriptAction( Okular::JavaScript, | ||||
197 | QStringLiteral( "app.clearInterval(intv);obj.idx;" ) ); | ||||
198 | m_document->processAction( action ); | ||||
199 | QVERIFY( m_fields["0.3"]->isVisible() ); | ||||
200 | delete action; | ||||
201 | } | ||||
202 | | ||||
203 | void KJSFunctionsTest::testSetClearTimeOut() | ||||
204 | { | ||||
205 | Okular::ScriptAction *action = new Okular::ScriptAction( Okular::JavaScript, | ||||
206 | QStringLiteral( "intv = app.setTimeOut('obj.inc()', 1);obj.idx;" ) ); | ||||
207 | m_document->processAction( action ); | ||||
208 | QVERIFY( m_fields["0.3"]->isVisible() ); | ||||
209 | QVERIFY( !m_fields["0.4"]->isVisible() ); | ||||
210 | delay(); | ||||
211 | delete action; | ||||
212 | | ||||
213 | QVERIFY( m_fields["0.4"]->isVisible() ); | ||||
214 | | ||||
215 | action = new Okular::ScriptAction( Okular::JavaScript, | ||||
216 | QStringLiteral( "intv = app.setTimeOut('obj.inc()', 2000);obj.idx;" ) ); | ||||
217 | m_document->processAction( action ); | ||||
218 | QVERIFY( m_fields["0.4"]->isVisible() ); | ||||
219 | delete action; | ||||
220 | | ||||
221 | action = new Okular::ScriptAction( Okular::JavaScript, | ||||
222 | QStringLiteral( "app.clearTimeOut(intv);obj.idx;" ) ); | ||||
223 | m_document->processAction( action ); | ||||
224 | QVERIFY( m_fields["0.4"]->isVisible() ); | ||||
225 | delay(); | ||||
226 | QVERIFY( m_fields["0.4"]->isVisible() ); | ||||
227 | delete action; | ||||
228 | } | ||||
229 | | ||||
230 | void KJSFunctionsTest::testGetOCGs() | ||||
231 | { | ||||
232 | QAbstractItemModel *model = m_document->layersModel(); | ||||
233 | | ||||
234 | Okular::ScriptAction *action = new Okular::ScriptAction( Okular::JavaScript, | ||||
235 | QStringLiteral( "var ocg = this.getOCGs(this.pageNum);\ | ||||
236 | ocg[0].state = false;" ) ); | ||||
237 | m_document->processAction( action ); | ||||
238 | QVERIFY( !model->data( model->index( 0, 0 ), Qt::CheckStateRole ).toBool() ); | ||||
239 | delete action; | ||||
240 | | ||||
241 | action = new Okular::ScriptAction( Okular::JavaScript, | ||||
242 | QStringLiteral( "ocg[0].state = true;" ) ); | ||||
243 | m_document->processAction( action ); | ||||
244 | QVERIFY( model->data( model->index( 0, 0 ), Qt::CheckStateRole ).toBool() ); | ||||
245 | delete action; | ||||
246 | | ||||
247 | action = new Okular::ScriptAction( Okular::JavaScript, | ||||
248 | QStringLiteral( "ocg[1].state = false;" ) ); | ||||
249 | m_document->processAction( action ); | ||||
250 | QVERIFY( !model->data( model->index( 1, 0 ), Qt::CheckStateRole ).toBool() ); | ||||
251 | delete action; | ||||
252 | | ||||
253 | action = new Okular::ScriptAction( Okular::JavaScript, | ||||
254 | QStringLiteral( "ocg[1].state = true;" ) ); | ||||
255 | m_document->processAction( action ); | ||||
256 | QVERIFY( model->data( model->index( 1, 0 ), Qt::CheckStateRole ).toBool() ); | ||||
257 | delete action; | ||||
258 | | ||||
259 | action = new Okular::ScriptAction( Okular::JavaScript, | ||||
260 | QStringLiteral( "ocg[2].state = false;" ) ); | ||||
261 | m_document->processAction( action ); | ||||
262 | QVERIFY( !model->data( model->index( 2, 0 ), Qt::CheckStateRole ).toBool() ); | ||||
263 | delete action; | ||||
264 | | ||||
265 | action = new Okular::ScriptAction( Okular::JavaScript, | ||||
266 | QStringLiteral( "ocg[2].state = true;" ) ); | ||||
267 | m_document->processAction( action ); | ||||
268 | QVERIFY( model->data( model->index( 2, 0 ), Qt::CheckStateRole ).toBool() ); | ||||
269 | delete action; | ||||
270 | | ||||
271 | action = new Okular::ScriptAction( Okular::JavaScript, | ||||
272 | QStringLiteral( "ocg[3].state = false;" ) ); | ||||
273 | m_document->processAction( action ); | ||||
274 | QVERIFY( !model->data( model->index( 3, 0 ), Qt::CheckStateRole ).toBool() ); | ||||
275 | delete action; | ||||
276 | | ||||
277 | action = new Okular::ScriptAction( Okular::JavaScript, | ||||
278 | QStringLiteral( "ocg[3].state = true;" ) ); | ||||
279 | m_document->processAction( action ); | ||||
280 | QVERIFY( model->data( model->index( 3, 0 ), Qt::CheckStateRole ).toBool() ); | ||||
281 | delete action; | ||||
282 | } | ||||
283 | | ||||
284 | void KJSFunctionsTest::testAlert() | ||||
285 | { | ||||
286 | Okular::ScriptAction *action = new Okular::ScriptAction( Okular::JavaScript, QStringLiteral( "ret = app.alert( \"Random Message\" );" ) ); | ||||
287 | QScopedPointer< MessageBoxHelper > messageBoxHelper; | ||||
288 | messageBoxHelper.reset( new MessageBoxHelper( QMessageBox::Ok, QStringLiteral( "Random Message" ), QMessageBox::Critical, QStringLiteral( "Okular" ), false ) ); | ||||
289 | m_document->processAction( action ); | ||||
290 | delete action; | ||||
291 | | ||||
292 | action = new Okular::ScriptAction( Okular::JavaScript, QStringLiteral( "ret = app.alert( \"Empty Message\", 1 );" ) ); | ||||
293 | messageBoxHelper.reset( new MessageBoxHelper( QMessageBox::Ok, QStringLiteral( "Empty Message" ), QMessageBox::Warning, QStringLiteral( "Okular" ), false ) ); | ||||
294 | m_document->processAction( action ); | ||||
295 | delete action; | ||||
296 | | ||||
297 | action = new Okular::ScriptAction( Okular::JavaScript, QStringLiteral( "ret = app.alert( \"No Message\", 2, 2 );" ) ); | ||||
298 | messageBoxHelper.reset( new MessageBoxHelper( QMessageBox::Yes, QStringLiteral( "No Message" ), QMessageBox::Question, QStringLiteral( "Okular" ), false ) ); | ||||
299 | m_document->processAction( action ); | ||||
300 | delete action; | ||||
301 | | ||||
302 | action = new Okular::ScriptAction( Okular::JavaScript, QStringLiteral( "ret = app.alert( \"No\", 3, 2, \"Test Dialog\" );" ) ); | ||||
303 | messageBoxHelper.reset( new MessageBoxHelper( QMessageBox::No, QStringLiteral( "No" ), QMessageBox::Information, QStringLiteral( "Test Dialog" ), false ) ); | ||||
304 | m_document->processAction( action ); | ||||
305 | delete action; | ||||
306 | | ||||
307 | action = new Okular::ScriptAction( Okular::JavaScript, QStringLiteral( "var oCheckBox = new Object();\ | ||||
308 | ret = app.alert( \"Cancel\", 3, 3, \"Test Dialog\", 0, oCheckBox );" ) ); | ||||
309 | messageBoxHelper.reset( new MessageBoxHelper( QMessageBox::Cancel, QStringLiteral( "Cancel" ), QMessageBox::Information, QStringLiteral( "Test Dialog" ), true ) ); | ||||
310 | m_document->processAction( action ); | ||||
311 | delete action; | ||||
312 | } | ||||
313 | | ||||
314 | /** @brief Checks a single JS action against an expected result | ||||
315 | * | ||||
316 | * Runs an action with the given @p script and checks that it | ||||
317 | * does pop-up a messagebox with the given @p result text. | ||||
318 | */ | ||||
319 | class PrintDHelper | ||||
320 | { | ||||
321 | public: | ||||
322 | PrintDHelper( Okular::Document* document, const QString& script, const QString& result ) : | ||||
323 | action( new Okular::ScriptAction( Okular::JavaScript, script ) ), | ||||
324 | box( new MessageBoxHelper( QMessageBox::Ok, result, QMessageBox::Critical, QStringLiteral( "Okular" ), false ) ) | ||||
325 | { | ||||
326 | document->processAction( action.data() ); | ||||
327 | } | ||||
328 | private: | ||||
329 | QScopedPointer< Okular::ScriptAction > action; | ||||
330 | QScopedPointer< MessageBoxHelper > box; | ||||
331 | } ; | ||||
332 | | ||||
333 | | ||||
334 | void KJSFunctionsTest::testPrintD_data() | ||||
335 | { | ||||
336 | // Force consistent locale | ||||
337 | QLocale locale( QStringLiteral( "en_US" ) ); | ||||
338 | QLocale::setDefault( locale ); | ||||
339 | | ||||
340 | QTest::addColumn<QString>("script"); | ||||
341 | QTest::addColumn<QString>("result"); | ||||
342 | | ||||
343 | QTest::newRow("mmyyy") | ||||
344 | << QStringLiteral( "var date = new Date( 2010, 0, 5, 11, 10, 32, 1 );\ | ||||
345 | ret = app.alert( util.printd( \"mm\\\\yyyy\", date ) );" ) | ||||
346 | << QStringLiteral( "01\\2010" ); | ||||
347 | QTest::newRow("myy") | ||||
348 | << QStringLiteral( "ret = app.alert( util.printd( \"m\\\\yy\", date ) );" ) | ||||
349 | << QStringLiteral( "1\\10" ); | ||||
350 | QTest::newRow("ddmmHHMM") | ||||
351 | << QStringLiteral( "ret = app.alert( util.printd( \"dd\\\\mm HH:MM\", date ) );" ) | ||||
352 | << QStringLiteral( "05\\01 11:10" ); | ||||
353 | QTest::newRow("ddmmHHMMss") | ||||
354 | << QStringLiteral( "ret = app.alert( util.printd( \"dd\\\\mm HH:MM:ss\", date ) );" ) | ||||
355 | << QStringLiteral( "05\\01 11:10:32" ); | ||||
356 | QTest::newRow("yyyymmHHMMss") | ||||
357 | << QStringLiteral( "ret = app.alert( util.printd( \"yyyy\\\\mm HH:MM:ss\", date ) );" ) | ||||
358 | << QStringLiteral( "2010\\01 11:10:32" ); | ||||
359 | QTest::newRow("0") | ||||
360 | << QStringLiteral( "ret = app.alert( util.printd( 0, date ) );" ) | ||||
361 | << QStringLiteral( "D:20100105111032" ); | ||||
362 | QTest::newRow("1") | ||||
363 | << QStringLiteral( "ret = app.alert( util.printd( 1, date ) );" ) | ||||
364 | << QStringLiteral( "2010.01.05 11:10:32" ); | ||||
365 | | ||||
366 | QDate date( 2010, 1, 5 ); | ||||
367 | QTest::newRow("2") | ||||
368 | << QStringLiteral( "ret = app.alert( util.printd( 2, date ) );" ) | ||||
369 | << QString( date.toString( locale.dateFormat( QLocale::ShortFormat ) ) + QStringLiteral( " 11:10:32 AM" ) ); | ||||
370 | } | ||||
371 | | ||||
372 | void KJSFunctionsTest::testPrintD() | ||||
373 | { | ||||
374 | QFETCH(QString, script); | ||||
375 | QFETCH(QString, result); | ||||
376 | | ||||
377 | QVERIFY( script.contains( "printd" ) ); | ||||
378 | PrintDHelper test( m_document, script, result ); | ||||
379 | } | ||||
380 | | ||||
381 | void KJSFunctionsTest::cleanupTestCase() | ||||
382 | { | ||||
383 | m_document->closeDocument(); | ||||
384 | delete m_document; | ||||
385 | } | ||||
386 | | ||||
387 | #endif | ||||
388 | | ||||
389 | QTEST_MAIN( KJSFunctionsTest ) | ||||
390 | #include "kjsfunctionstest.moc" |