1 /* |
|
2 Copyright (C) 2008,2009 Nokia Corporation and/or its subsidiary(-ies) |
|
3 |
|
4 This library is free software; you can redistribute it and/or |
|
5 modify it under the terms of the GNU Library General Public |
|
6 License as published by the Free Software Foundation; either |
|
7 version 2 of the License, or (at your option) any later version. |
|
8 |
|
9 This library is distributed in the hope that it will be useful, |
|
10 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 Library General Public License for more details. |
|
13 |
|
14 You should have received a copy of the GNU Library General Public License |
|
15 along with this library; see the file COPYING.LIB. If not, write to |
|
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
17 Boston, MA 02110-1301, USA. |
|
18 */ |
|
19 |
|
20 |
|
21 #include <QtTest/QtTest> |
|
22 |
|
23 #include <qwebpage.h> |
|
24 #include <qwebelement.h> |
|
25 #include <qwidget.h> |
|
26 #include <qwebview.h> |
|
27 #include <qwebframe.h> |
|
28 #include <qwebhistory.h> |
|
29 #include <QAbstractItemView> |
|
30 #include <QApplication> |
|
31 #include <QComboBox> |
|
32 #include <QPicture> |
|
33 #include <QRegExp> |
|
34 #include <QNetworkRequest> |
|
35 #include <QNetworkReply> |
|
36 #ifndef QT_NO_OPENSSL |
|
37 #include <qsslerror.h> |
|
38 #endif |
|
39 #include "../util.h" |
|
40 |
|
41 struct CustomType { |
|
42 QString string; |
|
43 }; |
|
44 Q_DECLARE_METATYPE(CustomType) |
|
45 |
|
46 Q_DECLARE_METATYPE(QBrush*) |
|
47 Q_DECLARE_METATYPE(QObjectList) |
|
48 Q_DECLARE_METATYPE(QList<int>) |
|
49 Q_DECLARE_METATYPE(Qt::BrushStyle) |
|
50 Q_DECLARE_METATYPE(QVariantList) |
|
51 Q_DECLARE_METATYPE(QVariantMap) |
|
52 |
|
53 class MyQObject : public QObject |
|
54 { |
|
55 Q_OBJECT |
|
56 |
|
57 Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty) |
|
58 Q_PROPERTY(QVariant variantProperty READ variantProperty WRITE setVariantProperty) |
|
59 Q_PROPERTY(QVariantList variantListProperty READ variantListProperty WRITE setVariantListProperty) |
|
60 Q_PROPERTY(QVariantMap variantMapProperty READ variantMapProperty WRITE setVariantMapProperty) |
|
61 Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty) |
|
62 Q_PROPERTY(QStringList stringListProperty READ stringListProperty WRITE setStringListProperty) |
|
63 Q_PROPERTY(QByteArray byteArrayProperty READ byteArrayProperty WRITE setByteArrayProperty) |
|
64 Q_PROPERTY(QBrush brushProperty READ brushProperty WRITE setBrushProperty) |
|
65 Q_PROPERTY(double hiddenProperty READ hiddenProperty WRITE setHiddenProperty SCRIPTABLE false) |
|
66 Q_PROPERTY(int writeOnlyProperty WRITE setWriteOnlyProperty) |
|
67 Q_PROPERTY(int readOnlyProperty READ readOnlyProperty) |
|
68 Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut) |
|
69 Q_PROPERTY(CustomType propWithCustomType READ propWithCustomType WRITE setPropWithCustomType) |
|
70 Q_PROPERTY(QWebElement webElementProperty READ webElementProperty WRITE setWebElementProperty) |
|
71 Q_PROPERTY(QObject* objectStarProperty READ objectStarProperty WRITE setObjectStarProperty) |
|
72 Q_ENUMS(Policy Strategy) |
|
73 Q_FLAGS(Ability) |
|
74 |
|
75 public: |
|
76 enum Policy { |
|
77 FooPolicy = 0, |
|
78 BarPolicy, |
|
79 BazPolicy |
|
80 }; |
|
81 |
|
82 enum Strategy { |
|
83 FooStrategy = 10, |
|
84 BarStrategy, |
|
85 BazStrategy |
|
86 }; |
|
87 |
|
88 enum AbilityFlag { |
|
89 NoAbility = 0x000, |
|
90 FooAbility = 0x001, |
|
91 BarAbility = 0x080, |
|
92 BazAbility = 0x200, |
|
93 AllAbility = FooAbility | BarAbility | BazAbility |
|
94 }; |
|
95 |
|
96 Q_DECLARE_FLAGS(Ability, AbilityFlag) |
|
97 |
|
98 MyQObject(QObject* parent = 0) |
|
99 : QObject(parent), |
|
100 m_intValue(123), |
|
101 m_variantValue(QLatin1String("foo")), |
|
102 m_variantListValue(QVariantList() << QVariant(123) << QVariant(QLatin1String("foo"))), |
|
103 m_stringValue(QLatin1String("bar")), |
|
104 m_stringListValue(QStringList() << QLatin1String("zig") << QLatin1String("zag")), |
|
105 m_brushValue(QColor(10, 20, 30, 40)), |
|
106 m_hiddenValue(456.0), |
|
107 m_writeOnlyValue(789), |
|
108 m_readOnlyValue(987), |
|
109 m_objectStar(0), |
|
110 m_qtFunctionInvoked(-1) |
|
111 { |
|
112 m_variantMapValue.insert("a", QVariant(123)); |
|
113 m_variantMapValue.insert("b", QVariant(QLatin1String("foo"))); |
|
114 m_variantMapValue.insert("c", QVariant::fromValue<QObject*>(this)); |
|
115 } |
|
116 |
|
117 ~MyQObject() { } |
|
118 |
|
119 int intProperty() const { |
|
120 return m_intValue; |
|
121 } |
|
122 void setIntProperty(int value) { |
|
123 m_intValue = value; |
|
124 } |
|
125 |
|
126 QVariant variantProperty() const { |
|
127 return m_variantValue; |
|
128 } |
|
129 void setVariantProperty(const QVariant &value) { |
|
130 m_variantValue = value; |
|
131 } |
|
132 |
|
133 QVariantList variantListProperty() const { |
|
134 return m_variantListValue; |
|
135 } |
|
136 void setVariantListProperty(const QVariantList &value) { |
|
137 m_variantListValue = value; |
|
138 } |
|
139 |
|
140 QVariantMap variantMapProperty() const { |
|
141 return m_variantMapValue; |
|
142 } |
|
143 void setVariantMapProperty(const QVariantMap &value) { |
|
144 m_variantMapValue = value; |
|
145 } |
|
146 |
|
147 QString stringProperty() const { |
|
148 return m_stringValue; |
|
149 } |
|
150 void setStringProperty(const QString &value) { |
|
151 m_stringValue = value; |
|
152 } |
|
153 |
|
154 QStringList stringListProperty() const { |
|
155 return m_stringListValue; |
|
156 } |
|
157 void setStringListProperty(const QStringList &value) { |
|
158 m_stringListValue = value; |
|
159 } |
|
160 |
|
161 QByteArray byteArrayProperty() const { |
|
162 return m_byteArrayValue; |
|
163 } |
|
164 void setByteArrayProperty(const QByteArray &value) { |
|
165 m_byteArrayValue = value; |
|
166 } |
|
167 |
|
168 QBrush brushProperty() const { |
|
169 return m_brushValue; |
|
170 } |
|
171 Q_INVOKABLE void setBrushProperty(const QBrush &value) { |
|
172 m_brushValue = value; |
|
173 } |
|
174 |
|
175 double hiddenProperty() const { |
|
176 return m_hiddenValue; |
|
177 } |
|
178 void setHiddenProperty(double value) { |
|
179 m_hiddenValue = value; |
|
180 } |
|
181 |
|
182 int writeOnlyProperty() const { |
|
183 return m_writeOnlyValue; |
|
184 } |
|
185 void setWriteOnlyProperty(int value) { |
|
186 m_writeOnlyValue = value; |
|
187 } |
|
188 |
|
189 int readOnlyProperty() const { |
|
190 return m_readOnlyValue; |
|
191 } |
|
192 |
|
193 QKeySequence shortcut() const { |
|
194 return m_shortcut; |
|
195 } |
|
196 void setShortcut(const QKeySequence &seq) { |
|
197 m_shortcut = seq; |
|
198 } |
|
199 |
|
200 QWebElement webElementProperty() const { |
|
201 return m_webElement; |
|
202 } |
|
203 |
|
204 void setWebElementProperty(const QWebElement& element) { |
|
205 m_webElement = element; |
|
206 } |
|
207 |
|
208 CustomType propWithCustomType() const { |
|
209 return m_customType; |
|
210 } |
|
211 void setPropWithCustomType(const CustomType &c) { |
|
212 m_customType = c; |
|
213 } |
|
214 |
|
215 QObject* objectStarProperty() const { |
|
216 return m_objectStar; |
|
217 } |
|
218 |
|
219 void setObjectStarProperty(QObject* object) { |
|
220 m_objectStar = object; |
|
221 } |
|
222 |
|
223 |
|
224 int qtFunctionInvoked() const { |
|
225 return m_qtFunctionInvoked; |
|
226 } |
|
227 |
|
228 QVariantList qtFunctionActuals() const { |
|
229 return m_actuals; |
|
230 } |
|
231 |
|
232 void resetQtFunctionInvoked() { |
|
233 m_qtFunctionInvoked = -1; |
|
234 m_actuals.clear(); |
|
235 } |
|
236 |
|
237 Q_INVOKABLE void myInvokable() { |
|
238 m_qtFunctionInvoked = 0; |
|
239 } |
|
240 Q_INVOKABLE void myInvokableWithIntArg(int arg) { |
|
241 m_qtFunctionInvoked = 1; |
|
242 m_actuals << arg; |
|
243 } |
|
244 Q_INVOKABLE void myInvokableWithLonglongArg(qlonglong arg) { |
|
245 m_qtFunctionInvoked = 2; |
|
246 m_actuals << arg; |
|
247 } |
|
248 Q_INVOKABLE void myInvokableWithFloatArg(float arg) { |
|
249 m_qtFunctionInvoked = 3; |
|
250 m_actuals << arg; |
|
251 } |
|
252 Q_INVOKABLE void myInvokableWithDoubleArg(double arg) { |
|
253 m_qtFunctionInvoked = 4; |
|
254 m_actuals << arg; |
|
255 } |
|
256 Q_INVOKABLE void myInvokableWithStringArg(const QString &arg) { |
|
257 m_qtFunctionInvoked = 5; |
|
258 m_actuals << arg; |
|
259 } |
|
260 Q_INVOKABLE void myInvokableWithIntArgs(int arg1, int arg2) { |
|
261 m_qtFunctionInvoked = 6; |
|
262 m_actuals << arg1 << arg2; |
|
263 } |
|
264 Q_INVOKABLE int myInvokableReturningInt() { |
|
265 m_qtFunctionInvoked = 7; |
|
266 return 123; |
|
267 } |
|
268 Q_INVOKABLE qlonglong myInvokableReturningLongLong() { |
|
269 m_qtFunctionInvoked = 39; |
|
270 return 456; |
|
271 } |
|
272 Q_INVOKABLE QString myInvokableReturningString() { |
|
273 m_qtFunctionInvoked = 8; |
|
274 return QLatin1String("ciao"); |
|
275 } |
|
276 Q_INVOKABLE void myInvokableWithIntArg(int arg1, int arg2) { // overload |
|
277 m_qtFunctionInvoked = 9; |
|
278 m_actuals << arg1 << arg2; |
|
279 } |
|
280 Q_INVOKABLE void myInvokableWithEnumArg(Policy policy) { |
|
281 m_qtFunctionInvoked = 10; |
|
282 m_actuals << policy; |
|
283 } |
|
284 Q_INVOKABLE void myInvokableWithQualifiedEnumArg(MyQObject::Policy policy) { |
|
285 m_qtFunctionInvoked = 36; |
|
286 m_actuals << policy; |
|
287 } |
|
288 Q_INVOKABLE Policy myInvokableReturningEnum() { |
|
289 m_qtFunctionInvoked = 37; |
|
290 return BazPolicy; |
|
291 } |
|
292 Q_INVOKABLE MyQObject::Policy myInvokableReturningQualifiedEnum() { |
|
293 m_qtFunctionInvoked = 38; |
|
294 return BazPolicy; |
|
295 } |
|
296 Q_INVOKABLE QVector<int> myInvokableReturningVectorOfInt() { |
|
297 m_qtFunctionInvoked = 11; |
|
298 return QVector<int>(); |
|
299 } |
|
300 Q_INVOKABLE void myInvokableWithVectorOfIntArg(const QVector<int> &) { |
|
301 m_qtFunctionInvoked = 12; |
|
302 } |
|
303 Q_INVOKABLE QObject* myInvokableReturningQObjectStar() { |
|
304 m_qtFunctionInvoked = 13; |
|
305 return this; |
|
306 } |
|
307 Q_INVOKABLE QObjectList myInvokableWithQObjectListArg(const QObjectList &lst) { |
|
308 m_qtFunctionInvoked = 14; |
|
309 m_actuals << qVariantFromValue(lst); |
|
310 return lst; |
|
311 } |
|
312 Q_INVOKABLE QVariant myInvokableWithVariantArg(const QVariant &v) { |
|
313 m_qtFunctionInvoked = 15; |
|
314 m_actuals << v; |
|
315 return v; |
|
316 } |
|
317 Q_INVOKABLE QVariantMap myInvokableWithVariantMapArg(const QVariantMap &vm) { |
|
318 m_qtFunctionInvoked = 16; |
|
319 m_actuals << vm; |
|
320 return vm; |
|
321 } |
|
322 Q_INVOKABLE QList<int> myInvokableWithListOfIntArg(const QList<int> &lst) { |
|
323 m_qtFunctionInvoked = 17; |
|
324 m_actuals << qVariantFromValue(lst); |
|
325 return lst; |
|
326 } |
|
327 Q_INVOKABLE QObject* myInvokableWithQObjectStarArg(QObject* obj) { |
|
328 m_qtFunctionInvoked = 18; |
|
329 m_actuals << qVariantFromValue(obj); |
|
330 return obj; |
|
331 } |
|
332 Q_INVOKABLE QBrush myInvokableWithQBrushArg(const QBrush &brush) { |
|
333 m_qtFunctionInvoked = 19; |
|
334 m_actuals << qVariantFromValue(brush); |
|
335 return brush; |
|
336 } |
|
337 Q_INVOKABLE void myInvokableWithBrushStyleArg(Qt::BrushStyle style) { |
|
338 m_qtFunctionInvoked = 43; |
|
339 m_actuals << qVariantFromValue(style); |
|
340 } |
|
341 Q_INVOKABLE void myInvokableWithVoidStarArg(void* arg) { |
|
342 m_qtFunctionInvoked = 44; |
|
343 m_actuals << qVariantFromValue(arg); |
|
344 } |
|
345 Q_INVOKABLE void myInvokableWithAmbiguousArg(int arg) { |
|
346 m_qtFunctionInvoked = 45; |
|
347 m_actuals << qVariantFromValue(arg); |
|
348 } |
|
349 Q_INVOKABLE void myInvokableWithAmbiguousArg(uint arg) { |
|
350 m_qtFunctionInvoked = 46; |
|
351 m_actuals << qVariantFromValue(arg); |
|
352 } |
|
353 Q_INVOKABLE void myInvokableWithDefaultArgs(int arg1, const QString &arg2 = "") { |
|
354 m_qtFunctionInvoked = 47; |
|
355 m_actuals << qVariantFromValue(arg1) << qVariantFromValue(arg2); |
|
356 } |
|
357 Q_INVOKABLE QObject& myInvokableReturningRef() { |
|
358 m_qtFunctionInvoked = 48; |
|
359 return *this; |
|
360 } |
|
361 Q_INVOKABLE const QObject& myInvokableReturningConstRef() const { |
|
362 const_cast<MyQObject*>(this)->m_qtFunctionInvoked = 49; |
|
363 return *this; |
|
364 } |
|
365 Q_INVOKABLE void myInvokableWithPointArg(const QPoint &arg) { |
|
366 const_cast<MyQObject*>(this)->m_qtFunctionInvoked = 50; |
|
367 m_actuals << qVariantFromValue(arg); |
|
368 } |
|
369 Q_INVOKABLE void myInvokableWithPointArg(const QPointF &arg) { |
|
370 const_cast<MyQObject*>(this)->m_qtFunctionInvoked = 51; |
|
371 m_actuals << qVariantFromValue(arg); |
|
372 } |
|
373 Q_INVOKABLE void myInvokableWithBoolArg(bool arg) { |
|
374 m_qtFunctionInvoked = 52; |
|
375 m_actuals << arg; |
|
376 } |
|
377 |
|
378 void emitMySignal() { |
|
379 emit mySignal(); |
|
380 } |
|
381 void emitMySignalWithIntArg(int arg) { |
|
382 emit mySignalWithIntArg(arg); |
|
383 } |
|
384 void emitMySignal2(bool arg) { |
|
385 emit mySignal2(arg); |
|
386 } |
|
387 void emitMySignal2() { |
|
388 emit mySignal2(); |
|
389 } |
|
390 void emitMySignalWithDateTimeArg(QDateTime dt) { |
|
391 emit mySignalWithDateTimeArg(dt); |
|
392 } |
|
393 void emitMySignalWithRegexArg(QRegExp r) { |
|
394 emit mySignalWithRegexArg(r); |
|
395 } |
|
396 |
|
397 public Q_SLOTS: |
|
398 void mySlot() { |
|
399 m_qtFunctionInvoked = 20; |
|
400 } |
|
401 void mySlotWithIntArg(int arg) { |
|
402 m_qtFunctionInvoked = 21; |
|
403 m_actuals << arg; |
|
404 } |
|
405 void mySlotWithDoubleArg(double arg) { |
|
406 m_qtFunctionInvoked = 22; |
|
407 m_actuals << arg; |
|
408 } |
|
409 void mySlotWithStringArg(const QString &arg) { |
|
410 m_qtFunctionInvoked = 23; |
|
411 m_actuals << arg; |
|
412 } |
|
413 |
|
414 void myOverloadedSlot() { |
|
415 m_qtFunctionInvoked = 24; |
|
416 } |
|
417 void myOverloadedSlot(QObject* arg) { |
|
418 m_qtFunctionInvoked = 41; |
|
419 m_actuals << qVariantFromValue(arg); |
|
420 } |
|
421 void myOverloadedSlot(bool arg) { |
|
422 m_qtFunctionInvoked = 25; |
|
423 m_actuals << arg; |
|
424 } |
|
425 void myOverloadedSlot(const QStringList &arg) { |
|
426 m_qtFunctionInvoked = 42; |
|
427 m_actuals << arg; |
|
428 } |
|
429 void myOverloadedSlot(double arg) { |
|
430 m_qtFunctionInvoked = 26; |
|
431 m_actuals << arg; |
|
432 } |
|
433 void myOverloadedSlot(float arg) { |
|
434 m_qtFunctionInvoked = 27; |
|
435 m_actuals << arg; |
|
436 } |
|
437 void myOverloadedSlot(int arg) { |
|
438 m_qtFunctionInvoked = 28; |
|
439 m_actuals << arg; |
|
440 } |
|
441 void myOverloadedSlot(const QString &arg) { |
|
442 m_qtFunctionInvoked = 29; |
|
443 m_actuals << arg; |
|
444 } |
|
445 void myOverloadedSlot(const QColor &arg) { |
|
446 m_qtFunctionInvoked = 30; |
|
447 m_actuals << arg; |
|
448 } |
|
449 void myOverloadedSlot(const QBrush &arg) { |
|
450 m_qtFunctionInvoked = 31; |
|
451 m_actuals << arg; |
|
452 } |
|
453 void myOverloadedSlot(const QDateTime &arg) { |
|
454 m_qtFunctionInvoked = 32; |
|
455 m_actuals << arg; |
|
456 } |
|
457 void myOverloadedSlot(const QDate &arg) { |
|
458 m_qtFunctionInvoked = 33; |
|
459 m_actuals << arg; |
|
460 } |
|
461 void myOverloadedSlot(const QRegExp &arg) { |
|
462 m_qtFunctionInvoked = 34; |
|
463 m_actuals << arg; |
|
464 } |
|
465 void myOverloadedSlot(const QVariant &arg) { |
|
466 m_qtFunctionInvoked = 35; |
|
467 m_actuals << arg; |
|
468 } |
|
469 void myOverloadedSlot(const QWebElement &arg) { |
|
470 m_qtFunctionInvoked = 36; |
|
471 m_actuals << QVariant::fromValue<QWebElement>(arg); |
|
472 } |
|
473 |
|
474 void qscript_call(int arg) { |
|
475 m_qtFunctionInvoked = 40; |
|
476 m_actuals << arg; |
|
477 } |
|
478 |
|
479 protected Q_SLOTS: |
|
480 void myProtectedSlot() { |
|
481 m_qtFunctionInvoked = 36; |
|
482 } |
|
483 |
|
484 private Q_SLOTS: |
|
485 void myPrivateSlot() { } |
|
486 |
|
487 Q_SIGNALS: |
|
488 void mySignal(); |
|
489 void mySignalWithIntArg(int arg); |
|
490 void mySignalWithDoubleArg(double arg); |
|
491 void mySignal2(bool arg = false); |
|
492 void mySignalWithDateTimeArg(QDateTime dt); |
|
493 void mySignalWithRegexArg(QRegExp r); |
|
494 |
|
495 private: |
|
496 int m_intValue; |
|
497 QVariant m_variantValue; |
|
498 QVariantList m_variantListValue; |
|
499 QVariantMap m_variantMapValue; |
|
500 QString m_stringValue; |
|
501 QStringList m_stringListValue; |
|
502 QByteArray m_byteArrayValue; |
|
503 QBrush m_brushValue; |
|
504 double m_hiddenValue; |
|
505 int m_writeOnlyValue; |
|
506 int m_readOnlyValue; |
|
507 QKeySequence m_shortcut; |
|
508 QWebElement m_webElement; |
|
509 CustomType m_customType; |
|
510 QObject* m_objectStar; |
|
511 int m_qtFunctionInvoked; |
|
512 QVariantList m_actuals; |
|
513 }; |
|
514 |
|
515 class MyOtherQObject : public MyQObject |
|
516 { |
|
517 public: |
|
518 MyOtherQObject(QObject* parent = 0) |
|
519 : MyQObject(parent) { } |
|
520 }; |
|
521 |
|
522 class MyEnumTestQObject : public QObject |
|
523 { |
|
524 Q_OBJECT |
|
525 Q_PROPERTY(QString p1 READ p1) |
|
526 Q_PROPERTY(QString p2 READ p2) |
|
527 Q_PROPERTY(QString p3 READ p3 SCRIPTABLE false) |
|
528 Q_PROPERTY(QString p4 READ p4) |
|
529 Q_PROPERTY(QString p5 READ p5 SCRIPTABLE false) |
|
530 Q_PROPERTY(QString p6 READ p6) |
|
531 public: |
|
532 MyEnumTestQObject(QObject* parent = 0) |
|
533 : QObject(parent) { } |
|
534 QString p1() const { |
|
535 return QLatin1String("p1"); |
|
536 } |
|
537 QString p2() const { |
|
538 return QLatin1String("p2"); |
|
539 } |
|
540 QString p3() const { |
|
541 return QLatin1String("p3"); |
|
542 } |
|
543 QString p4() const { |
|
544 return QLatin1String("p4"); |
|
545 } |
|
546 QString p5() const { |
|
547 return QLatin1String("p5"); |
|
548 } |
|
549 QString p6() const { |
|
550 return QLatin1String("p5"); |
|
551 } |
|
552 public Q_SLOTS: |
|
553 void mySlot() { } |
|
554 void myOtherSlot() { } |
|
555 Q_SIGNALS: |
|
556 void mySignal(); |
|
557 }; |
|
558 |
|
559 class tst_QWebFrame : public QObject |
|
560 { |
|
561 Q_OBJECT |
|
562 |
|
563 public: |
|
564 tst_QWebFrame(); |
|
565 virtual ~tst_QWebFrame(); |
|
566 bool eventFilter(QObject* watched, QEvent* event); |
|
567 |
|
568 public slots: |
|
569 void init(); |
|
570 void cleanup(); |
|
571 |
|
572 private slots: |
|
573 void getSetStaticProperty(); |
|
574 void getSetDynamicProperty(); |
|
575 void getSetChildren(); |
|
576 void callQtInvokable(); |
|
577 void connectAndDisconnect(); |
|
578 void classEnums(); |
|
579 void classConstructor(); |
|
580 void overrideInvokable(); |
|
581 void transferInvokable(); |
|
582 void findChild(); |
|
583 void findChildren(); |
|
584 void overloadedSlots(); |
|
585 void enumerate_data(); |
|
586 void enumerate(); |
|
587 void objectDeleted(); |
|
588 void typeConversion(); |
|
589 void arrayObjectEnumerable(); |
|
590 void symmetricUrl(); |
|
591 void progressSignal(); |
|
592 void urlChange(); |
|
593 void domCycles(); |
|
594 void requestedUrl(); |
|
595 void javaScriptWindowObjectCleared_data(); |
|
596 void javaScriptWindowObjectCleared(); |
|
597 void javaScriptWindowObjectClearedOnEvaluate(); |
|
598 void setHtml(); |
|
599 void setHtmlWithResource(); |
|
600 void setHtmlWithBaseURL(); |
|
601 void setHtmlWithJSAlert(); |
|
602 void ipv6HostEncoding(); |
|
603 void metaData(); |
|
604 #if !defined(Q_WS_MAEMO_5) |
|
605 // as maemo 5 does not use QComboBoxes to implement the popups |
|
606 // this test does not make sense for it. |
|
607 void popupFocus(); |
|
608 #endif |
|
609 void inputFieldFocus(); |
|
610 void hitTestContent(); |
|
611 void jsByteArray(); |
|
612 void ownership(); |
|
613 void nullValue(); |
|
614 void baseUrl_data(); |
|
615 void baseUrl(); |
|
616 void hasSetFocus(); |
|
617 void render(); |
|
618 void scrollPosition(); |
|
619 void scrollToAnchor(); |
|
620 void scrollbarsOff(); |
|
621 void evaluateWillCauseRepaint(); |
|
622 void qObjectWrapperWithSameIdentity(); |
|
623 void introspectQtMethods_data(); |
|
624 void introspectQtMethods(); |
|
625 |
|
626 private: |
|
627 QString evalJS(const QString&s) { |
|
628 // Convert an undefined return variant to the string "undefined" |
|
629 QVariant ret = evalJSV(s); |
|
630 if (ret.userType() == QMetaType::Void) |
|
631 return "undefined"; |
|
632 else |
|
633 return ret.toString(); |
|
634 } |
|
635 QVariant evalJSV(const QString &s) { |
|
636 return m_page->mainFrame()->evaluateJavaScript(s); |
|
637 } |
|
638 |
|
639 QString evalJS(const QString&s, QString& type) { |
|
640 return evalJSV(s, type).toString(); |
|
641 } |
|
642 QVariant evalJSV(const QString &s, QString& type) { |
|
643 // As a special measure, if we get an exception we set the type to 'error' |
|
644 // (in ecma, an Error object has typeof object, but qtscript has a convenience function) |
|
645 // Similarly, an array is an object, but we'd prefer to have a type of 'array' |
|
646 // Also, consider a QMetaType::Void QVariant to be undefined |
|
647 QString escaped = s; |
|
648 escaped.replace('\'', "\\'"); // Don't preescape your single quotes! |
|
649 evalJS("var retvalue;\ |
|
650 var typevalue; \ |
|
651 try {\ |
|
652 retvalue = eval('" + escaped + "'); \ |
|
653 typevalue = typeof retvalue; \ |
|
654 if (retvalue instanceof Array) \ |
|
655 typevalue = 'array'; \ |
|
656 } \ |
|
657 catch(e) {\ |
|
658 retvalue = e.name + ': ' + e.message;\ |
|
659 typevalue = 'error';\ |
|
660 }"); |
|
661 QVariant ret = evalJSV("retvalue"); |
|
662 if (ret.userType() != QMetaType::Void) |
|
663 type = evalJS("typevalue"); |
|
664 else { |
|
665 ret = QString("undefined"); |
|
666 type = sUndefined; |
|
667 } |
|
668 evalJS("delete retvalue; delete typevalue"); |
|
669 return ret; |
|
670 } |
|
671 QObject* firstChildByClassName(QObject* parent, const char* className) { |
|
672 const QObjectList & children = parent->children(); |
|
673 foreach (QObject* child, children) { |
|
674 if (!strcmp(child->metaObject()->className(), className)) { |
|
675 return child; |
|
676 } |
|
677 } |
|
678 return 0; |
|
679 } |
|
680 |
|
681 const QString sTrue; |
|
682 const QString sFalse; |
|
683 const QString sUndefined; |
|
684 const QString sArray; |
|
685 const QString sFunction; |
|
686 const QString sError; |
|
687 const QString sString; |
|
688 const QString sObject; |
|
689 const QString sNumber; |
|
690 |
|
691 private: |
|
692 QWebView* m_view; |
|
693 QWebPage* m_page; |
|
694 MyQObject* m_myObject; |
|
695 QWebView* m_inputFieldsTestView; |
|
696 int m_inputFieldTestPaintCount; |
|
697 }; |
|
698 |
|
699 tst_QWebFrame::tst_QWebFrame() |
|
700 : sTrue("true"), sFalse("false"), sUndefined("undefined"), sArray("array"), sFunction("function"), sError("error"), |
|
701 sString("string"), sObject("object"), sNumber("number"), m_inputFieldsTestView(0), m_inputFieldTestPaintCount(0) |
|
702 { |
|
703 } |
|
704 |
|
705 tst_QWebFrame::~tst_QWebFrame() |
|
706 { |
|
707 } |
|
708 |
|
709 bool tst_QWebFrame::eventFilter(QObject* watched, QEvent* event) |
|
710 { |
|
711 // used on the inputFieldFocus test |
|
712 if (watched == m_inputFieldsTestView) { |
|
713 if (event->type() == QEvent::Paint) |
|
714 m_inputFieldTestPaintCount++; |
|
715 } |
|
716 return QObject::eventFilter(watched, event); |
|
717 } |
|
718 |
|
719 void tst_QWebFrame::init() |
|
720 { |
|
721 m_view = new QWebView(); |
|
722 m_page = m_view->page(); |
|
723 m_myObject = new MyQObject(); |
|
724 m_page->mainFrame()->addToJavaScriptWindowObject("myObject", m_myObject); |
|
725 } |
|
726 |
|
727 void tst_QWebFrame::cleanup() |
|
728 { |
|
729 delete m_view; |
|
730 delete m_myObject; |
|
731 } |
|
732 |
|
733 void tst_QWebFrame::getSetStaticProperty() |
|
734 { |
|
735 m_page->mainFrame()->setHtml("<html><head><body></body></html>"); |
|
736 QCOMPARE(evalJS("typeof myObject.noSuchProperty"), sUndefined); |
|
737 |
|
738 // initial value (set in MyQObject constructor) |
|
739 { |
|
740 QString type; |
|
741 QVariant ret = evalJSV("myObject.intProperty", type); |
|
742 QCOMPARE(type, sNumber); |
|
743 QCOMPARE(ret.type(), QVariant::Double); |
|
744 QCOMPARE(ret.toInt(), 123); |
|
745 } |
|
746 QCOMPARE(evalJS("myObject.intProperty === 123.0"), sTrue); |
|
747 |
|
748 { |
|
749 QString type; |
|
750 QVariant ret = evalJSV("myObject.variantProperty", type); |
|
751 QCOMPARE(type, sString); |
|
752 QCOMPARE(ret.type(), QVariant::String); |
|
753 QCOMPARE(ret.toString(), QLatin1String("foo")); |
|
754 } |
|
755 QCOMPARE(evalJS("myObject.variantProperty == 'foo'"), sTrue); |
|
756 |
|
757 { |
|
758 QString type; |
|
759 QVariant ret = evalJSV("myObject.stringProperty", type); |
|
760 QCOMPARE(type, sString); |
|
761 QCOMPARE(ret.type(), QVariant::String); |
|
762 QCOMPARE(ret.toString(), QLatin1String("bar")); |
|
763 } |
|
764 QCOMPARE(evalJS("myObject.stringProperty === 'bar'"), sTrue); |
|
765 |
|
766 { |
|
767 QString type; |
|
768 QVariant ret = evalJSV("myObject.variantListProperty", type); |
|
769 QCOMPARE(type, sArray); |
|
770 QCOMPARE(ret.type(), QVariant::List); |
|
771 QVariantList vl = ret.value<QVariantList>(); |
|
772 QCOMPARE(vl.size(), 2); |
|
773 QCOMPARE(vl.at(0).toInt(), 123); |
|
774 QCOMPARE(vl.at(1).toString(), QLatin1String("foo")); |
|
775 } |
|
776 QCOMPARE(evalJS("myObject.variantListProperty.length === 2"), sTrue); |
|
777 QCOMPARE(evalJS("myObject.variantListProperty[0] === 123"), sTrue); |
|
778 QCOMPARE(evalJS("myObject.variantListProperty[1] === 'foo'"), sTrue); |
|
779 |
|
780 { |
|
781 QString type; |
|
782 QVariant ret = evalJSV("myObject.variantMapProperty", type); |
|
783 QCOMPARE(type, sObject); |
|
784 QCOMPARE(ret.type(), QVariant::Map); |
|
785 QVariantMap vm = ret.value<QVariantMap>(); |
|
786 QCOMPARE(vm.size(), 3); |
|
787 QCOMPARE(vm.value("a").toInt(), 123); |
|
788 QCOMPARE(vm.value("b").toString(), QLatin1String("foo")); |
|
789 QCOMPARE(vm.value("c").value<QObject*>(), static_cast<QObject*>(m_myObject)); |
|
790 } |
|
791 QCOMPARE(evalJS("myObject.variantMapProperty.a === 123"), sTrue); |
|
792 QCOMPARE(evalJS("myObject.variantMapProperty.b === 'foo'"), sTrue); |
|
793 QCOMPARE(evalJS("myObject.variantMapProperty.c.variantMapProperty.b === 'foo'"), sTrue); |
|
794 |
|
795 { |
|
796 QString type; |
|
797 QVariant ret = evalJSV("myObject.stringListProperty", type); |
|
798 QCOMPARE(type, sArray); |
|
799 QCOMPARE(ret.type(), QVariant::List); |
|
800 QVariantList vl = ret.value<QVariantList>(); |
|
801 QCOMPARE(vl.size(), 2); |
|
802 QCOMPARE(vl.at(0).toString(), QLatin1String("zig")); |
|
803 QCOMPARE(vl.at(1).toString(), QLatin1String("zag")); |
|
804 } |
|
805 QCOMPARE(evalJS("myObject.stringListProperty.length === 2"), sTrue); |
|
806 QCOMPARE(evalJS("typeof myObject.stringListProperty[0]"), sString); |
|
807 QCOMPARE(evalJS("myObject.stringListProperty[0]"), QLatin1String("zig")); |
|
808 QCOMPARE(evalJS("typeof myObject.stringListProperty[1]"), sString); |
|
809 QCOMPARE(evalJS("myObject.stringListProperty[1]"), QLatin1String("zag")); |
|
810 |
|
811 // property change in C++ should be reflected in script |
|
812 m_myObject->setIntProperty(456); |
|
813 QCOMPARE(evalJS("myObject.intProperty == 456"), sTrue); |
|
814 m_myObject->setIntProperty(789); |
|
815 QCOMPARE(evalJS("myObject.intProperty == 789"), sTrue); |
|
816 |
|
817 m_myObject->setVariantProperty(QLatin1String("bar")); |
|
818 QCOMPARE(evalJS("myObject.variantProperty === 'bar'"), sTrue); |
|
819 m_myObject->setVariantProperty(42); |
|
820 QCOMPARE(evalJS("myObject.variantProperty === 42"), sTrue); |
|
821 m_myObject->setVariantProperty(qVariantFromValue(QBrush())); |
|
822 //XFAIL |
|
823 // QCOMPARE(evalJS("typeof myObject.variantProperty"), sVariant); |
|
824 |
|
825 m_myObject->setStringProperty(QLatin1String("baz")); |
|
826 QCOMPARE(evalJS("myObject.stringProperty === 'baz'"), sTrue); |
|
827 m_myObject->setStringProperty(QLatin1String("zab")); |
|
828 QCOMPARE(evalJS("myObject.stringProperty === 'zab'"), sTrue); |
|
829 |
|
830 // property change in script should be reflected in C++ |
|
831 QCOMPARE(evalJS("myObject.intProperty = 123"), QLatin1String("123")); |
|
832 QCOMPARE(evalJS("myObject.intProperty == 123"), sTrue); |
|
833 QCOMPARE(m_myObject->intProperty(), 123); |
|
834 QCOMPARE(evalJS("myObject.intProperty = 'ciao!';" |
|
835 "myObject.intProperty == 0"), sTrue); |
|
836 QCOMPARE(m_myObject->intProperty(), 0); |
|
837 QCOMPARE(evalJS("myObject.intProperty = '123';" |
|
838 "myObject.intProperty == 123"), sTrue); |
|
839 QCOMPARE(m_myObject->intProperty(), 123); |
|
840 |
|
841 QCOMPARE(evalJS("myObject.stringProperty = 'ciao'"), QLatin1String("ciao")); |
|
842 QCOMPARE(evalJS("myObject.stringProperty"), QLatin1String("ciao")); |
|
843 QCOMPARE(m_myObject->stringProperty(), QLatin1String("ciao")); |
|
844 QCOMPARE(evalJS("myObject.stringProperty = 123;" |
|
845 "myObject.stringProperty"), QLatin1String("123")); |
|
846 QCOMPARE(m_myObject->stringProperty(), QLatin1String("123")); |
|
847 QCOMPARE(evalJS("myObject.stringProperty = null"), QString()); |
|
848 QCOMPARE(evalJS("myObject.stringProperty"), QString()); |
|
849 QCOMPARE(m_myObject->stringProperty(), QString()); |
|
850 QCOMPARE(evalJS("myObject.stringProperty = undefined"), sUndefined); |
|
851 QCOMPARE(evalJS("myObject.stringProperty"), QString()); |
|
852 QCOMPARE(m_myObject->stringProperty(), QString()); |
|
853 |
|
854 QCOMPARE(evalJS("myObject.variantProperty = new Number(1234);" |
|
855 "myObject.variantProperty").toDouble(), 1234.0); |
|
856 QCOMPARE(m_myObject->variantProperty().toDouble(), 1234.0); |
|
857 |
|
858 QCOMPARE(evalJS("myObject.variantProperty = new Boolean(1234);" |
|
859 "myObject.variantProperty"), sTrue); |
|
860 QCOMPARE(m_myObject->variantProperty().toBool(), true); |
|
861 |
|
862 QCOMPARE(evalJS("myObject.variantProperty = null;" |
|
863 "myObject.variantProperty.valueOf()"), sUndefined); |
|
864 QCOMPARE(m_myObject->variantProperty(), QVariant()); |
|
865 QCOMPARE(evalJS("myObject.variantProperty = undefined;" |
|
866 "myObject.variantProperty.valueOf()"), sUndefined); |
|
867 QCOMPARE(m_myObject->variantProperty(), QVariant()); |
|
868 |
|
869 QCOMPARE(evalJS("myObject.variantProperty = 'foo';" |
|
870 "myObject.variantProperty.valueOf()"), QLatin1String("foo")); |
|
871 QCOMPARE(m_myObject->variantProperty(), QVariant(QLatin1String("foo"))); |
|
872 QCOMPARE(evalJS("myObject.variantProperty = 42;" |
|
873 "myObject.variantProperty").toDouble(), 42.0); |
|
874 QCOMPARE(m_myObject->variantProperty().toDouble(), 42.0); |
|
875 |
|
876 QCOMPARE(evalJS("myObject.variantListProperty = [1, 'two', true];" |
|
877 "myObject.variantListProperty.length == 3"), sTrue); |
|
878 QCOMPARE(evalJS("myObject.variantListProperty[0] === 1"), sTrue); |
|
879 QCOMPARE(evalJS("myObject.variantListProperty[1]"), QLatin1String("two")); |
|
880 QCOMPARE(evalJS("myObject.variantListProperty[2] === true"), sTrue); |
|
881 |
|
882 QCOMPARE(evalJS("myObject.stringListProperty = [1, 'two', true];" |
|
883 "myObject.stringListProperty.length == 3"), sTrue); |
|
884 QCOMPARE(evalJS("typeof myObject.stringListProperty[0]"), sString); |
|
885 QCOMPARE(evalJS("myObject.stringListProperty[0] == '1'"), sTrue); |
|
886 QCOMPARE(evalJS("typeof myObject.stringListProperty[1]"), sString); |
|
887 QCOMPARE(evalJS("myObject.stringListProperty[1]"), QLatin1String("two")); |
|
888 QCOMPARE(evalJS("typeof myObject.stringListProperty[2]"), sString); |
|
889 QCOMPARE(evalJS("myObject.stringListProperty[2]"), QLatin1String("true")); |
|
890 evalJS("myObject.webElementProperty=document.body;"); |
|
891 QCOMPARE(evalJS("myObject.webElementProperty.tagName"), QLatin1String("BODY")); |
|
892 |
|
893 // try to delete |
|
894 QCOMPARE(evalJS("delete myObject.intProperty"), sFalse); |
|
895 QCOMPARE(evalJS("myObject.intProperty == 123"), sTrue); |
|
896 |
|
897 QCOMPARE(evalJS("delete myObject.variantProperty"), sFalse); |
|
898 QCOMPARE(evalJS("myObject.variantProperty").toDouble(), 42.0); |
|
899 |
|
900 // custom property |
|
901 QCOMPARE(evalJS("myObject.customProperty"), sUndefined); |
|
902 QCOMPARE(evalJS("myObject.customProperty = 123;" |
|
903 "myObject.customProperty == 123"), sTrue); |
|
904 QVariant v = m_page->mainFrame()->evaluateJavaScript("myObject.customProperty"); |
|
905 QCOMPARE(v.type(), QVariant::Double); |
|
906 QCOMPARE(v.toInt(), 123); |
|
907 |
|
908 // non-scriptable property |
|
909 QCOMPARE(m_myObject->hiddenProperty(), 456.0); |
|
910 QCOMPARE(evalJS("myObject.hiddenProperty"), sUndefined); |
|
911 QCOMPARE(evalJS("myObject.hiddenProperty = 123;" |
|
912 "myObject.hiddenProperty == 123"), sTrue); |
|
913 QCOMPARE(m_myObject->hiddenProperty(), 456.0); |
|
914 |
|
915 // write-only property |
|
916 QCOMPARE(m_myObject->writeOnlyProperty(), 789); |
|
917 QCOMPARE(evalJS("typeof myObject.writeOnlyProperty"), sUndefined); |
|
918 QCOMPARE(evalJS("myObject.writeOnlyProperty = 123;" |
|
919 "typeof myObject.writeOnlyProperty"), sUndefined); |
|
920 QCOMPARE(m_myObject->writeOnlyProperty(), 123); |
|
921 |
|
922 // read-only property |
|
923 QCOMPARE(m_myObject->readOnlyProperty(), 987); |
|
924 QCOMPARE(evalJS("myObject.readOnlyProperty == 987"), sTrue); |
|
925 QCOMPARE(evalJS("myObject.readOnlyProperty = 654;" |
|
926 "myObject.readOnlyProperty == 987"), sTrue); |
|
927 QCOMPARE(m_myObject->readOnlyProperty(), 987); |
|
928 |
|
929 // QObject* property |
|
930 m_myObject->setObjectStarProperty(0); |
|
931 QCOMPARE(m_myObject->objectStarProperty(), (QObject*)0); |
|
932 QCOMPARE(evalJS("myObject.objectStarProperty == null"), sTrue); |
|
933 QCOMPARE(evalJS("typeof myObject.objectStarProperty"), sObject); |
|
934 QCOMPARE(evalJS("Boolean(myObject.objectStarProperty)"), sFalse); |
|
935 QCOMPARE(evalJS("String(myObject.objectStarProperty) == 'null'"), sTrue); |
|
936 QCOMPARE(evalJS("myObject.objectStarProperty.objectStarProperty"), |
|
937 sUndefined); |
|
938 m_myObject->setObjectStarProperty(this); |
|
939 QCOMPARE(evalJS("myObject.objectStarProperty != null"), sTrue); |
|
940 QCOMPARE(evalJS("typeof myObject.objectStarProperty"), sObject); |
|
941 QCOMPARE(evalJS("Boolean(myObject.objectStarProperty)"), sTrue); |
|
942 QCOMPARE(evalJS("String(myObject.objectStarProperty) != 'null'"), sTrue); |
|
943 } |
|
944 |
|
945 void tst_QWebFrame::getSetDynamicProperty() |
|
946 { |
|
947 // initially the object does not have the property |
|
948 // In WebKit, RuntimeObjects do not inherit Object, so don't have hasOwnProperty |
|
949 |
|
950 //QCOMPARE(evalJS("myObject.hasOwnProperty('dynamicProperty')"), sFalse); |
|
951 QCOMPARE(evalJS("typeof myObject.dynamicProperty"), sUndefined); |
|
952 |
|
953 // add a dynamic property in C++ |
|
954 QCOMPARE(m_myObject->setProperty("dynamicProperty", 123), false); |
|
955 //QCOMPARE(evalJS("myObject.hasOwnProperty('dynamicProperty')"), sTrue); |
|
956 QCOMPARE(evalJS("typeof myObject.dynamicProperty != 'undefined'"), sTrue); |
|
957 QCOMPARE(evalJS("myObject.dynamicProperty == 123"), sTrue); |
|
958 |
|
959 // property change in script should be reflected in C++ |
|
960 QCOMPARE(evalJS("myObject.dynamicProperty = 'foo';" |
|
961 "myObject.dynamicProperty"), QLatin1String("foo")); |
|
962 QCOMPARE(m_myObject->property("dynamicProperty").toString(), QLatin1String("foo")); |
|
963 |
|
964 // delete the property (XFAIL - can't delete properties) |
|
965 QEXPECT_FAIL("", "can't delete properties", Continue); |
|
966 QCOMPARE(evalJS("delete myObject.dynamicProperty"), sTrue); |
|
967 /* |
|
968 QCOMPARE(m_myObject->property("dynamicProperty").isValid(), false); |
|
969 QCOMPARE(evalJS("typeof myObject.dynamicProperty"), sUndefined); |
|
970 // QCOMPARE(evalJS("myObject.hasOwnProperty('dynamicProperty')"), sFalse); |
|
971 QCOMPARE(evalJS("typeof myObject.dynamicProperty"), sUndefined); |
|
972 */ |
|
973 } |
|
974 |
|
975 void tst_QWebFrame::getSetChildren() |
|
976 { |
|
977 // initially the object does not have the child |
|
978 // (again, no hasOwnProperty) |
|
979 |
|
980 //QCOMPARE(evalJS("myObject.hasOwnProperty('child')"), sFalse); |
|
981 QCOMPARE(evalJS("typeof myObject.child"), sUndefined); |
|
982 |
|
983 // add a child |
|
984 MyQObject* child = new MyQObject(m_myObject); |
|
985 child->setObjectName("child"); |
|
986 // QCOMPARE(evalJS("myObject.hasOwnProperty('child')"), sTrue); |
|
987 QCOMPARE(evalJS("typeof myObject.child != 'undefined'"), sTrue); |
|
988 |
|
989 // add a grandchild |
|
990 MyQObject* grandChild = new MyQObject(child); |
|
991 grandChild->setObjectName("grandChild"); |
|
992 // QCOMPARE(evalJS("myObject.child.hasOwnProperty('grandChild')"), sTrue); |
|
993 QCOMPARE(evalJS("typeof myObject.child.grandChild != 'undefined'"), sTrue); |
|
994 |
|
995 // delete grandchild |
|
996 delete grandChild; |
|
997 // QCOMPARE(evalJS("myObject.child.hasOwnProperty('grandChild')"), sFalse); |
|
998 QCOMPARE(evalJS("typeof myObject.child.grandChild == 'undefined'"), sTrue); |
|
999 |
|
1000 // delete child |
|
1001 delete child; |
|
1002 // QCOMPARE(evalJS("myObject.hasOwnProperty('child')"), sFalse); |
|
1003 QCOMPARE(evalJS("typeof myObject.child == 'undefined'"), sTrue); |
|
1004 } |
|
1005 |
|
1006 Q_DECLARE_METATYPE(QVector<int>) |
|
1007 Q_DECLARE_METATYPE(QVector<double>) |
|
1008 Q_DECLARE_METATYPE(QVector<QString>) |
|
1009 |
|
1010 void tst_QWebFrame::callQtInvokable() |
|
1011 { |
|
1012 qRegisterMetaType<QObjectList>(); |
|
1013 |
|
1014 m_myObject->resetQtFunctionInvoked(); |
|
1015 QCOMPARE(evalJS("typeof myObject.myInvokable()"), sUndefined); |
|
1016 QCOMPARE(m_myObject->qtFunctionInvoked(), 0); |
|
1017 QCOMPARE(m_myObject->qtFunctionActuals(), QVariantList()); |
|
1018 |
|
1019 // extra arguments should silently be ignored |
|
1020 m_myObject->resetQtFunctionInvoked(); |
|
1021 QCOMPARE(evalJS("typeof myObject.myInvokable(10, 20, 30)"), sUndefined); |
|
1022 QCOMPARE(m_myObject->qtFunctionInvoked(), 0); |
|
1023 QCOMPARE(m_myObject->qtFunctionActuals(), QVariantList()); |
|
1024 |
|
1025 m_myObject->resetQtFunctionInvoked(); |
|
1026 QCOMPARE(evalJS("typeof myObject.myInvokableWithIntArg(123)"), sUndefined); |
|
1027 QCOMPARE(m_myObject->qtFunctionInvoked(), 1); |
|
1028 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1029 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), 123); |
|
1030 |
|
1031 m_myObject->resetQtFunctionInvoked(); |
|
1032 QCOMPARE(evalJS("typeof myObject.myInvokableWithIntArg('123')"), sUndefined); |
|
1033 QCOMPARE(m_myObject->qtFunctionInvoked(), 1); |
|
1034 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1035 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), 123); |
|
1036 |
|
1037 m_myObject->resetQtFunctionInvoked(); |
|
1038 QCOMPARE(evalJS("typeof myObject.myInvokableWithLonglongArg(123)"), sUndefined); |
|
1039 QCOMPARE(m_myObject->qtFunctionInvoked(), 2); |
|
1040 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1041 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toLongLong(), qlonglong(123)); |
|
1042 |
|
1043 m_myObject->resetQtFunctionInvoked(); |
|
1044 QCOMPARE(evalJS("typeof myObject.myInvokableWithFloatArg(123.5)"), sUndefined); |
|
1045 QCOMPARE(m_myObject->qtFunctionInvoked(), 3); |
|
1046 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1047 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toDouble(), 123.5); |
|
1048 |
|
1049 m_myObject->resetQtFunctionInvoked(); |
|
1050 QCOMPARE(evalJS("typeof myObject.myInvokableWithDoubleArg(123.5)"), sUndefined); |
|
1051 QCOMPARE(m_myObject->qtFunctionInvoked(), 4); |
|
1052 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1053 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toDouble(), 123.5); |
|
1054 |
|
1055 m_myObject->resetQtFunctionInvoked(); |
|
1056 QCOMPARE(evalJS("typeof myObject.myInvokableWithDoubleArg(new Number(1234.5))"), sUndefined); |
|
1057 QCOMPARE(m_myObject->qtFunctionInvoked(), 4); |
|
1058 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1059 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toDouble(), 1234.5); |
|
1060 |
|
1061 m_myObject->resetQtFunctionInvoked(); |
|
1062 QCOMPARE(evalJS("typeof myObject.myInvokableWithBoolArg(new Boolean(true))"), sUndefined); |
|
1063 QCOMPARE(m_myObject->qtFunctionInvoked(), 52); |
|
1064 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1065 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toBool(), true); |
|
1066 |
|
1067 m_myObject->resetQtFunctionInvoked(); |
|
1068 QCOMPARE(evalJS("typeof myObject.myInvokableWithStringArg('ciao')"), sUndefined); |
|
1069 QCOMPARE(m_myObject->qtFunctionInvoked(), 5); |
|
1070 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1071 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toString(), QLatin1String("ciao")); |
|
1072 |
|
1073 m_myObject->resetQtFunctionInvoked(); |
|
1074 QCOMPARE(evalJS("typeof myObject.myInvokableWithStringArg(123)"), sUndefined); |
|
1075 QCOMPARE(m_myObject->qtFunctionInvoked(), 5); |
|
1076 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1077 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toString(), QLatin1String("123")); |
|
1078 |
|
1079 m_myObject->resetQtFunctionInvoked(); |
|
1080 QCOMPARE(evalJS("typeof myObject.myInvokableWithStringArg(null)"), sUndefined); |
|
1081 QCOMPARE(m_myObject->qtFunctionInvoked(), 5); |
|
1082 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1083 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toString(), QString()); |
|
1084 QVERIFY(m_myObject->qtFunctionActuals().at(0).toString().isEmpty()); |
|
1085 |
|
1086 m_myObject->resetQtFunctionInvoked(); |
|
1087 QCOMPARE(evalJS("typeof myObject.myInvokableWithStringArg(undefined)"), sUndefined); |
|
1088 QCOMPARE(m_myObject->qtFunctionInvoked(), 5); |
|
1089 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1090 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toString(), QString()); |
|
1091 QVERIFY(m_myObject->qtFunctionActuals().at(0).toString().isEmpty()); |
|
1092 |
|
1093 m_myObject->resetQtFunctionInvoked(); |
|
1094 QCOMPARE(evalJS("typeof myObject.myInvokableWithIntArgs(123, 456)"), sUndefined); |
|
1095 QCOMPARE(m_myObject->qtFunctionInvoked(), 6); |
|
1096 QCOMPARE(m_myObject->qtFunctionActuals().size(), 2); |
|
1097 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), 123); |
|
1098 QCOMPARE(m_myObject->qtFunctionActuals().at(1).toInt(), 456); |
|
1099 |
|
1100 m_myObject->resetQtFunctionInvoked(); |
|
1101 QCOMPARE(evalJS("myObject.myInvokableReturningInt()"), QLatin1String("123")); |
|
1102 QCOMPARE(m_myObject->qtFunctionInvoked(), 7); |
|
1103 QCOMPARE(m_myObject->qtFunctionActuals(), QVariantList()); |
|
1104 |
|
1105 m_myObject->resetQtFunctionInvoked(); |
|
1106 QCOMPARE(evalJS("myObject.myInvokableReturningLongLong()"), QLatin1String("456")); |
|
1107 QCOMPARE(m_myObject->qtFunctionInvoked(), 39); |
|
1108 QCOMPARE(m_myObject->qtFunctionActuals(), QVariantList()); |
|
1109 |
|
1110 m_myObject->resetQtFunctionInvoked(); |
|
1111 QCOMPARE(evalJS("myObject.myInvokableReturningString()"), QLatin1String("ciao")); |
|
1112 QCOMPARE(m_myObject->qtFunctionInvoked(), 8); |
|
1113 QCOMPARE(m_myObject->qtFunctionActuals(), QVariantList()); |
|
1114 |
|
1115 m_myObject->resetQtFunctionInvoked(); |
|
1116 QCOMPARE(evalJS("typeof myObject.myInvokableWithIntArg(123, 456)"), sUndefined); |
|
1117 QCOMPARE(m_myObject->qtFunctionInvoked(), 9); |
|
1118 QCOMPARE(m_myObject->qtFunctionActuals().size(), 2); |
|
1119 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), 123); |
|
1120 QCOMPARE(m_myObject->qtFunctionActuals().at(1).toInt(), 456); |
|
1121 |
|
1122 m_myObject->resetQtFunctionInvoked(); |
|
1123 QCOMPARE(evalJS("typeof myObject.myInvokableWithVoidStarArg(null)"), sUndefined); |
|
1124 QCOMPARE(m_myObject->qtFunctionInvoked(), 44); |
|
1125 m_myObject->resetQtFunctionInvoked(); |
|
1126 { |
|
1127 QString type; |
|
1128 QString ret = evalJS("myObject.myInvokableWithVoidStarArg(123)", type); |
|
1129 QCOMPARE(type, sError); |
|
1130 QCOMPARE(ret, QLatin1String("TypeError: incompatible type of argument(s) in call to myInvokableWithVoidStarArg(); candidates were\n myInvokableWithVoidStarArg(void*)")); |
|
1131 QCOMPARE(m_myObject->qtFunctionInvoked(), -1); |
|
1132 } |
|
1133 |
|
1134 m_myObject->resetQtFunctionInvoked(); |
|
1135 { |
|
1136 QString type; |
|
1137 QString ret = evalJS("myObject.myInvokableWithAmbiguousArg(123)", type); |
|
1138 QCOMPARE(type, sError); |
|
1139 QCOMPARE(ret, QLatin1String("TypeError: ambiguous call of overloaded function myInvokableWithAmbiguousArg(); candidates were\n myInvokableWithAmbiguousArg(int)\n myInvokableWithAmbiguousArg(uint)")); |
|
1140 } |
|
1141 |
|
1142 m_myObject->resetQtFunctionInvoked(); |
|
1143 { |
|
1144 QString type; |
|
1145 QString ret = evalJS("myObject.myInvokableWithDefaultArgs(123, 'hello')", type); |
|
1146 QCOMPARE(type, sUndefined); |
|
1147 QCOMPARE(m_myObject->qtFunctionInvoked(), 47); |
|
1148 QCOMPARE(m_myObject->qtFunctionActuals().size(), 2); |
|
1149 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), 123); |
|
1150 QCOMPARE(m_myObject->qtFunctionActuals().at(1).toString(), QLatin1String("hello")); |
|
1151 } |
|
1152 |
|
1153 m_myObject->resetQtFunctionInvoked(); |
|
1154 { |
|
1155 QString type; |
|
1156 QString ret = evalJS("myObject.myInvokableWithDefaultArgs(456)", type); |
|
1157 QCOMPARE(type, sUndefined); |
|
1158 QCOMPARE(m_myObject->qtFunctionInvoked(), 47); |
|
1159 QCOMPARE(m_myObject->qtFunctionActuals().size(), 2); |
|
1160 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), 456); |
|
1161 QCOMPARE(m_myObject->qtFunctionActuals().at(1).toString(), QString()); |
|
1162 } |
|
1163 |
|
1164 // calling function that returns (const)ref |
|
1165 m_myObject->resetQtFunctionInvoked(); |
|
1166 { |
|
1167 QString type; |
|
1168 QString ret = evalJS("typeof myObject.myInvokableReturningRef()"); |
|
1169 QCOMPARE(ret, sUndefined); |
|
1170 //QVERIFY(!m_engine->hasUncaughtException()); |
|
1171 QCOMPARE(m_myObject->qtFunctionInvoked(), 48); |
|
1172 } |
|
1173 |
|
1174 m_myObject->resetQtFunctionInvoked(); |
|
1175 { |
|
1176 QString type; |
|
1177 QString ret = evalJS("typeof myObject.myInvokableReturningConstRef()"); |
|
1178 QCOMPARE(ret, sUndefined); |
|
1179 //QVERIFY(!m_engine->hasUncaughtException()); |
|
1180 QCOMPARE(m_myObject->qtFunctionInvoked(), 49); |
|
1181 } |
|
1182 |
|
1183 m_myObject->resetQtFunctionInvoked(); |
|
1184 { |
|
1185 QString type; |
|
1186 QVariant ret = evalJSV("myObject.myInvokableReturningQObjectStar()", type); |
|
1187 QCOMPARE(m_myObject->qtFunctionInvoked(), 13); |
|
1188 QCOMPARE(m_myObject->qtFunctionActuals().size(), 0); |
|
1189 QCOMPARE(type, sObject); |
|
1190 QCOMPARE(ret.userType(), int(QMetaType::QObjectStar)); |
|
1191 } |
|
1192 |
|
1193 m_myObject->resetQtFunctionInvoked(); |
|
1194 { |
|
1195 QString type; |
|
1196 QVariant ret = evalJSV("myObject.myInvokableWithQObjectListArg([myObject])", type); |
|
1197 QCOMPARE(m_myObject->qtFunctionInvoked(), 14); |
|
1198 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1199 QCOMPARE(type, sArray); |
|
1200 QCOMPARE(ret.userType(), int(QVariant::List)); // All lists get downgraded to QVariantList |
|
1201 QVariantList vl = qvariant_cast<QVariantList>(ret); |
|
1202 QCOMPARE(vl.count(), 1); |
|
1203 } |
|
1204 |
|
1205 m_myObject->resetQtFunctionInvoked(); |
|
1206 { |
|
1207 QString type; |
|
1208 m_myObject->setVariantProperty(QVariant(123)); |
|
1209 QVariant ret = evalJSV("myObject.myInvokableWithVariantArg(myObject.variantProperty)", type); |
|
1210 QCOMPARE(type, sNumber); |
|
1211 QCOMPARE(m_myObject->qtFunctionInvoked(), 15); |
|
1212 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1213 QCOMPARE(m_myObject->qtFunctionActuals().at(0), m_myObject->variantProperty()); |
|
1214 QCOMPARE(ret.userType(), int(QMetaType::Double)); // all JS numbers are doubles, even though this started as an int |
|
1215 QCOMPARE(ret.toInt(),123); |
|
1216 } |
|
1217 |
|
1218 m_myObject->resetQtFunctionInvoked(); |
|
1219 { |
|
1220 QString type; |
|
1221 QVariant ret = evalJSV("myObject.myInvokableWithVariantArg(null)", type); |
|
1222 QCOMPARE(type, sObject); |
|
1223 QCOMPARE(m_myObject->qtFunctionInvoked(), 15); |
|
1224 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1225 QCOMPARE(m_myObject->qtFunctionActuals().at(0), QVariant()); |
|
1226 QVERIFY(!m_myObject->qtFunctionActuals().at(0).isValid()); |
|
1227 } |
|
1228 |
|
1229 m_myObject->resetQtFunctionInvoked(); |
|
1230 { |
|
1231 QString type; |
|
1232 QVariant ret = evalJSV("myObject.myInvokableWithVariantArg(undefined)", type); |
|
1233 QCOMPARE(type, sObject); |
|
1234 QCOMPARE(m_myObject->qtFunctionInvoked(), 15); |
|
1235 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1236 QCOMPARE(m_myObject->qtFunctionActuals().at(0), QVariant()); |
|
1237 QVERIFY(!m_myObject->qtFunctionActuals().at(0).isValid()); |
|
1238 } |
|
1239 |
|
1240 /* XFAIL - variant support |
|
1241 m_myObject->resetQtFunctionInvoked(); |
|
1242 { |
|
1243 m_myObject->setVariantProperty(qVariantFromValue(QBrush())); |
|
1244 QVariant ret = evalJS("myObject.myInvokableWithVariantArg(myObject.variantProperty)"); |
|
1245 QVERIFY(ret.isVariant()); |
|
1246 QCOMPARE(m_myObject->qtFunctionInvoked(), 15); |
|
1247 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1248 QCOMPARE(ret.toVariant(), m_myObject->qtFunctionActuals().at(0)); |
|
1249 QCOMPARE(ret.toVariant(), m_myObject->variantProperty()); |
|
1250 } |
|
1251 */ |
|
1252 |
|
1253 m_myObject->resetQtFunctionInvoked(); |
|
1254 { |
|
1255 QString type; |
|
1256 QVariant ret = evalJSV("myObject.myInvokableWithVariantArg(123)", type); |
|
1257 QCOMPARE(type, sNumber); |
|
1258 QCOMPARE(m_myObject->qtFunctionInvoked(), 15); |
|
1259 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1260 QCOMPARE(m_myObject->qtFunctionActuals().at(0), QVariant(123)); |
|
1261 QCOMPARE(ret.userType(), int(QMetaType::Double)); |
|
1262 QCOMPARE(ret.toInt(),123); |
|
1263 } |
|
1264 |
|
1265 m_myObject->resetQtFunctionInvoked(); |
|
1266 { |
|
1267 QString type; |
|
1268 QVariant ret = evalJSV("myObject.myInvokableWithVariantMapArg({ a:123, b:'ciao' })", type); |
|
1269 QCOMPARE(m_myObject->qtFunctionInvoked(), 16); |
|
1270 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1271 |
|
1272 QVariant v = m_myObject->qtFunctionActuals().at(0); |
|
1273 QCOMPARE(v.userType(), int(QMetaType::QVariantMap)); |
|
1274 |
|
1275 QVariantMap vmap = qvariant_cast<QVariantMap>(v); |
|
1276 QCOMPARE(vmap.keys().size(), 2); |
|
1277 QCOMPARE(vmap.keys().at(0), QLatin1String("a")); |
|
1278 QCOMPARE(vmap.value("a"), QVariant(123)); |
|
1279 QCOMPARE(vmap.keys().at(1), QLatin1String("b")); |
|
1280 QCOMPARE(vmap.value("b"), QVariant("ciao")); |
|
1281 |
|
1282 QCOMPARE(type, sObject); |
|
1283 |
|
1284 QCOMPARE(ret.userType(), int(QMetaType::QVariantMap)); |
|
1285 vmap = qvariant_cast<QVariantMap>(ret); |
|
1286 QCOMPARE(vmap.keys().size(), 2); |
|
1287 QCOMPARE(vmap.keys().at(0), QLatin1String("a")); |
|
1288 QCOMPARE(vmap.value("a"), QVariant(123)); |
|
1289 QCOMPARE(vmap.keys().at(1), QLatin1String("b")); |
|
1290 QCOMPARE(vmap.value("b"), QVariant("ciao")); |
|
1291 } |
|
1292 |
|
1293 m_myObject->resetQtFunctionInvoked(); |
|
1294 { |
|
1295 QString type; |
|
1296 QVariant ret = evalJSV("myObject.myInvokableWithListOfIntArg([1, 5])", type); |
|
1297 QCOMPARE(m_myObject->qtFunctionInvoked(), 17); |
|
1298 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1299 QVariant v = m_myObject->qtFunctionActuals().at(0); |
|
1300 QCOMPARE(v.userType(), qMetaTypeId<QList<int> >()); |
|
1301 QList<int> ilst = qvariant_cast<QList<int> >(v); |
|
1302 QCOMPARE(ilst.size(), 2); |
|
1303 QCOMPARE(ilst.at(0), 1); |
|
1304 QCOMPARE(ilst.at(1), 5); |
|
1305 |
|
1306 QCOMPARE(type, sArray); |
|
1307 QCOMPARE(ret.userType(), int(QMetaType::QVariantList)); // ints get converted to doubles, so this is a qvariantlist |
|
1308 QVariantList vlst = qvariant_cast<QVariantList>(ret); |
|
1309 QCOMPARE(vlst.size(), 2); |
|
1310 QCOMPARE(vlst.at(0).toInt(), 1); |
|
1311 QCOMPARE(vlst.at(1).toInt(), 5); |
|
1312 } |
|
1313 |
|
1314 m_myObject->resetQtFunctionInvoked(); |
|
1315 { |
|
1316 QString type; |
|
1317 QVariant ret = evalJSV("myObject.myInvokableWithQObjectStarArg(myObject)", type); |
|
1318 QCOMPARE(m_myObject->qtFunctionInvoked(), 18); |
|
1319 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1320 QVariant v = m_myObject->qtFunctionActuals().at(0); |
|
1321 QCOMPARE(v.userType(), int(QMetaType::QObjectStar)); |
|
1322 QCOMPARE(qvariant_cast<QObject*>(v), (QObject*)m_myObject); |
|
1323 |
|
1324 QCOMPARE(ret.userType(), int(QMetaType::QObjectStar)); |
|
1325 QCOMPARE(qvariant_cast<QObject*>(ret), (QObject*)m_myObject); |
|
1326 |
|
1327 QCOMPARE(type, sObject); |
|
1328 } |
|
1329 |
|
1330 m_myObject->resetQtFunctionInvoked(); |
|
1331 { |
|
1332 // no implicit conversion from integer to QObject* |
|
1333 QString type; |
|
1334 evalJS("myObject.myInvokableWithQObjectStarArg(123)", type); |
|
1335 QCOMPARE(type, sError); |
|
1336 } |
|
1337 |
|
1338 /* |
|
1339 m_myObject->resetQtFunctionInvoked(); |
|
1340 { |
|
1341 QString fun = evalJS("myObject.myInvokableWithQBrushArg"); |
|
1342 Q_ASSERT(fun.isFunction()); |
|
1343 QColor color(10, 20, 30, 40); |
|
1344 // QColor should be converted to a QBrush |
|
1345 QVariant ret = fun.call(QString(), QStringList() |
|
1346 << qScriptValueFromValue(m_engine, color)); |
|
1347 QCOMPARE(m_myObject->qtFunctionInvoked(), 19); |
|
1348 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1349 QVariant v = m_myObject->qtFunctionActuals().at(0); |
|
1350 QCOMPARE(v.userType(), int(QMetaType::QBrush)); |
|
1351 QCOMPARE(qvariant_cast<QColor>(v), color); |
|
1352 |
|
1353 QCOMPARE(qscriptvalue_cast<QColor>(ret), color); |
|
1354 } |
|
1355 */ |
|
1356 |
|
1357 // private slots should not be part of the QObject binding |
|
1358 QCOMPARE(evalJS("typeof myObject.myPrivateSlot"), sUndefined); |
|
1359 |
|
1360 // protected slots should be fine |
|
1361 m_myObject->resetQtFunctionInvoked(); |
|
1362 evalJS("myObject.myProtectedSlot()"); |
|
1363 QCOMPARE(m_myObject->qtFunctionInvoked(), 36); |
|
1364 |
|
1365 // call with too few arguments |
|
1366 { |
|
1367 QString type; |
|
1368 QString ret = evalJS("myObject.myInvokableWithIntArg()", type); |
|
1369 QCOMPARE(type, sError); |
|
1370 QCOMPARE(ret, QLatin1String("SyntaxError: too few arguments in call to myInvokableWithIntArg(); candidates are\n myInvokableWithIntArg(int,int)\n myInvokableWithIntArg(int)")); |
|
1371 } |
|
1372 |
|
1373 // call function where not all types have been registered |
|
1374 m_myObject->resetQtFunctionInvoked(); |
|
1375 { |
|
1376 QString type; |
|
1377 QString ret = evalJS("myObject.myInvokableWithBrushStyleArg(0)", type); |
|
1378 QCOMPARE(type, sError); |
|
1379 QCOMPARE(ret, QLatin1String("TypeError: cannot call myInvokableWithBrushStyleArg(): unknown type `Qt::BrushStyle'")); |
|
1380 QCOMPARE(m_myObject->qtFunctionInvoked(), -1); |
|
1381 } |
|
1382 |
|
1383 // call function with incompatible argument type |
|
1384 m_myObject->resetQtFunctionInvoked(); |
|
1385 { |
|
1386 QString type; |
|
1387 QString ret = evalJS("myObject.myInvokableWithQBrushArg(null)", type); |
|
1388 QCOMPARE(type, sError); |
|
1389 QCOMPARE(ret, QLatin1String("TypeError: incompatible type of argument(s) in call to myInvokableWithQBrushArg(); candidates were\n myInvokableWithQBrushArg(QBrush)")); |
|
1390 QCOMPARE(m_myObject->qtFunctionInvoked(), -1); |
|
1391 } |
|
1392 } |
|
1393 |
|
1394 void tst_QWebFrame::connectAndDisconnect() |
|
1395 { |
|
1396 // connect(function) |
|
1397 QCOMPARE(evalJS("typeof myObject.mySignal"), sFunction); |
|
1398 QCOMPARE(evalJS("typeof myObject.mySignal.connect"), sFunction); |
|
1399 QCOMPARE(evalJS("typeof myObject.mySignal.disconnect"), sFunction); |
|
1400 |
|
1401 { |
|
1402 QString type; |
|
1403 evalJS("myObject.mySignal.connect(123)", type); |
|
1404 QCOMPARE(type, sError); |
|
1405 } |
|
1406 |
|
1407 evalJS("myHandler = function() { window.gotSignal = true; window.signalArgs = arguments; window.slotThisObject = this; window.signalSender = __qt_sender__; }"); |
|
1408 |
|
1409 QCOMPARE(evalJS("myObject.mySignal.connect(myHandler)"), sUndefined); |
|
1410 |
|
1411 evalJS("gotSignal = false"); |
|
1412 evalJS("myObject.mySignal()"); |
|
1413 QCOMPARE(evalJS("gotSignal"), sTrue); |
|
1414 QCOMPARE(evalJS("signalArgs.length == 0"), sTrue); |
|
1415 QCOMPARE(evalJS("signalSender"),evalJS("myObject")); |
|
1416 QCOMPARE(evalJS("slotThisObject == window"), sTrue); |
|
1417 |
|
1418 evalJS("gotSignal = false"); |
|
1419 m_myObject->emitMySignal(); |
|
1420 QCOMPARE(evalJS("gotSignal"), sTrue); |
|
1421 QCOMPARE(evalJS("signalArgs.length == 0"), sTrue); |
|
1422 |
|
1423 QCOMPARE(evalJS("myObject.mySignalWithIntArg.connect(myHandler)"), sUndefined); |
|
1424 |
|
1425 evalJS("gotSignal = false"); |
|
1426 m_myObject->emitMySignalWithIntArg(123); |
|
1427 QCOMPARE(evalJS("gotSignal"), sTrue); |
|
1428 QCOMPARE(evalJS("signalArgs.length == 1"), sTrue); |
|
1429 QCOMPARE(evalJS("signalArgs[0] == 123.0"), sTrue); |
|
1430 |
|
1431 QCOMPARE(evalJS("myObject.mySignal.disconnect(myHandler)"), sUndefined); |
|
1432 { |
|
1433 QString type; |
|
1434 evalJS("myObject.mySignal.disconnect(myHandler)", type); |
|
1435 QCOMPARE(type, sError); |
|
1436 } |
|
1437 |
|
1438 evalJS("gotSignal = false"); |
|
1439 QCOMPARE(evalJS("myObject.mySignal2.connect(myHandler)"), sUndefined); |
|
1440 m_myObject->emitMySignal2(true); |
|
1441 QCOMPARE(evalJS("gotSignal"), sTrue); |
|
1442 QCOMPARE(evalJS("signalArgs.length == 1"), sTrue); |
|
1443 QCOMPARE(evalJS("signalArgs[0]"), sTrue); |
|
1444 |
|
1445 QCOMPARE(evalJS("myObject.mySignal2.disconnect(myHandler)"), sUndefined); |
|
1446 |
|
1447 QCOMPARE(evalJS("typeof myObject['mySignal2()']"), sFunction); |
|
1448 QCOMPARE(evalJS("typeof myObject['mySignal2()'].connect"), sFunction); |
|
1449 QCOMPARE(evalJS("typeof myObject['mySignal2()'].disconnect"), sFunction); |
|
1450 |
|
1451 QCOMPARE(evalJS("myObject['mySignal2()'].connect(myHandler)"), sUndefined); |
|
1452 |
|
1453 evalJS("gotSignal = false"); |
|
1454 m_myObject->emitMySignal2(); |
|
1455 QCOMPARE(evalJS("gotSignal"), sTrue); |
|
1456 |
|
1457 QCOMPARE(evalJS("myObject['mySignal2()'].disconnect(myHandler)"), sUndefined); |
|
1458 |
|
1459 // connect(object, function) |
|
1460 evalJS("otherObject = { name:'foo' }"); |
|
1461 QCOMPARE(evalJS("myObject.mySignal.connect(otherObject, myHandler)"), sUndefined); |
|
1462 QCOMPARE(evalJS("myObject.mySignal.disconnect(otherObject, myHandler)"), sUndefined); |
|
1463 evalJS("gotSignal = false"); |
|
1464 m_myObject->emitMySignal(); |
|
1465 QCOMPARE(evalJS("gotSignal"), sFalse); |
|
1466 |
|
1467 { |
|
1468 QString type; |
|
1469 evalJS("myObject.mySignal.disconnect(otherObject, myHandler)", type); |
|
1470 QCOMPARE(type, sError); |
|
1471 } |
|
1472 |
|
1473 QCOMPARE(evalJS("myObject.mySignal.connect(otherObject, myHandler)"), sUndefined); |
|
1474 evalJS("gotSignal = false"); |
|
1475 m_myObject->emitMySignal(); |
|
1476 QCOMPARE(evalJS("gotSignal"), sTrue); |
|
1477 QCOMPARE(evalJS("signalArgs.length == 0"), sTrue); |
|
1478 QCOMPARE(evalJS("slotThisObject"),evalJS("otherObject")); |
|
1479 QCOMPARE(evalJS("signalSender"),evalJS("myObject")); |
|
1480 QCOMPARE(evalJS("slotThisObject.name"), QLatin1String("foo")); |
|
1481 QCOMPARE(evalJS("myObject.mySignal.disconnect(otherObject, myHandler)"), sUndefined); |
|
1482 |
|
1483 evalJS("yetAnotherObject = { name:'bar', func : function() { } }"); |
|
1484 QCOMPARE(evalJS("myObject.mySignal2.connect(yetAnotherObject, myHandler)"), sUndefined); |
|
1485 evalJS("gotSignal = false"); |
|
1486 m_myObject->emitMySignal2(true); |
|
1487 QCOMPARE(evalJS("gotSignal"), sTrue); |
|
1488 QCOMPARE(evalJS("signalArgs.length == 1"), sTrue); |
|
1489 QCOMPARE(evalJS("slotThisObject == yetAnotherObject"), sTrue); |
|
1490 QCOMPARE(evalJS("signalSender == myObject"), sTrue); |
|
1491 QCOMPARE(evalJS("slotThisObject.name"), QLatin1String("bar")); |
|
1492 QCOMPARE(evalJS("myObject.mySignal2.disconnect(yetAnotherObject, myHandler)"), sUndefined); |
|
1493 |
|
1494 QCOMPARE(evalJS("myObject.mySignal2.connect(myObject, myHandler)"), sUndefined); |
|
1495 evalJS("gotSignal = false"); |
|
1496 m_myObject->emitMySignal2(true); |
|
1497 QCOMPARE(evalJS("gotSignal"), sTrue); |
|
1498 QCOMPARE(evalJS("signalArgs.length == 1"), sTrue); |
|
1499 QCOMPARE(evalJS("slotThisObject == myObject"), sTrue); |
|
1500 QCOMPARE(evalJS("signalSender == myObject"), sTrue); |
|
1501 QCOMPARE(evalJS("myObject.mySignal2.disconnect(myObject, myHandler)"), sUndefined); |
|
1502 |
|
1503 // connect(obj, string) |
|
1504 QCOMPARE(evalJS("myObject.mySignal.connect(yetAnotherObject, 'func')"), sUndefined); |
|
1505 QCOMPARE(evalJS("myObject.mySignal.connect(myObject, 'mySlot')"), sUndefined); |
|
1506 QCOMPARE(evalJS("myObject.mySignal.disconnect(yetAnotherObject, 'func')"), sUndefined); |
|
1507 QCOMPARE(evalJS("myObject.mySignal.disconnect(myObject, 'mySlot')"), sUndefined); |
|
1508 |
|
1509 // check that emitting signals from script works |
|
1510 |
|
1511 // no arguments |
|
1512 QCOMPARE(evalJS("myObject.mySignal.connect(myObject.mySlot)"), sUndefined); |
|
1513 m_myObject->resetQtFunctionInvoked(); |
|
1514 QCOMPARE(evalJS("myObject.mySignal()"), sUndefined); |
|
1515 QCOMPARE(m_myObject->qtFunctionInvoked(), 20); |
|
1516 QCOMPARE(evalJS("myObject.mySignal.disconnect(myObject.mySlot)"), sUndefined); |
|
1517 |
|
1518 // one argument |
|
1519 QCOMPARE(evalJS("myObject.mySignalWithIntArg.connect(myObject.mySlotWithIntArg)"), sUndefined); |
|
1520 m_myObject->resetQtFunctionInvoked(); |
|
1521 QCOMPARE(evalJS("myObject.mySignalWithIntArg(123)"), sUndefined); |
|
1522 QCOMPARE(m_myObject->qtFunctionInvoked(), 21); |
|
1523 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1524 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), 123); |
|
1525 QCOMPARE(evalJS("myObject.mySignalWithIntArg.disconnect(myObject.mySlotWithIntArg)"), sUndefined); |
|
1526 |
|
1527 QCOMPARE(evalJS("myObject.mySignalWithIntArg.connect(myObject.mySlotWithDoubleArg)"), sUndefined); |
|
1528 m_myObject->resetQtFunctionInvoked(); |
|
1529 QCOMPARE(evalJS("myObject.mySignalWithIntArg(123)"), sUndefined); |
|
1530 QCOMPARE(m_myObject->qtFunctionInvoked(), 22); |
|
1531 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1532 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toDouble(), 123.0); |
|
1533 QCOMPARE(evalJS("myObject.mySignalWithIntArg.disconnect(myObject.mySlotWithDoubleArg)"), sUndefined); |
|
1534 |
|
1535 QCOMPARE(evalJS("myObject.mySignalWithIntArg.connect(myObject.mySlotWithStringArg)"), sUndefined); |
|
1536 m_myObject->resetQtFunctionInvoked(); |
|
1537 QCOMPARE(evalJS("myObject.mySignalWithIntArg(123)"), sUndefined); |
|
1538 QCOMPARE(m_myObject->qtFunctionInvoked(), 23); |
|
1539 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1540 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toString(), QLatin1String("123")); |
|
1541 QCOMPARE(evalJS("myObject.mySignalWithIntArg.disconnect(myObject.mySlotWithStringArg)"), sUndefined); |
|
1542 |
|
1543 // connecting to overloaded slot |
|
1544 QCOMPARE(evalJS("myObject.mySignalWithIntArg.connect(myObject.myOverloadedSlot)"), sUndefined); |
|
1545 m_myObject->resetQtFunctionInvoked(); |
|
1546 QCOMPARE(evalJS("myObject.mySignalWithIntArg(123)"), sUndefined); |
|
1547 QCOMPARE(m_myObject->qtFunctionInvoked(), 26); // double overload |
|
1548 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1549 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), 123); |
|
1550 QCOMPARE(evalJS("myObject.mySignalWithIntArg.disconnect(myObject.myOverloadedSlot)"), sUndefined); |
|
1551 |
|
1552 QCOMPARE(evalJS("myObject.mySignalWithIntArg.connect(myObject['myOverloadedSlot(int)'])"), sUndefined); |
|
1553 m_myObject->resetQtFunctionInvoked(); |
|
1554 QCOMPARE(evalJS("myObject.mySignalWithIntArg(456)"), sUndefined); |
|
1555 QCOMPARE(m_myObject->qtFunctionInvoked(), 28); // int overload |
|
1556 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1557 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), 456); |
|
1558 QCOMPARE(evalJS("myObject.mySignalWithIntArg.disconnect(myObject['myOverloadedSlot(int)'])"), sUndefined); |
|
1559 |
|
1560 // erroneous input |
|
1561 { |
|
1562 // ### QtScript adds .connect to all functions, WebKit does only to signals/slots |
|
1563 QString type; |
|
1564 QString ret = evalJS("(function() { }).connect()", type); |
|
1565 QCOMPARE(type, sError); |
|
1566 QCOMPARE(ret, QLatin1String("TypeError: Result of expression '(function() { }).connect' [undefined] is not a function.")); |
|
1567 } |
|
1568 { |
|
1569 QString type; |
|
1570 QString ret = evalJS("var o = { }; o.connect = Function.prototype.connect; o.connect()", type); |
|
1571 QCOMPARE(type, sError); |
|
1572 QCOMPARE(ret, QLatin1String("TypeError: Result of expression 'o.connect' [undefined] is not a function.")); |
|
1573 } |
|
1574 |
|
1575 { |
|
1576 QString type; |
|
1577 QString ret = evalJS("(function() { }).connect(123)", type); |
|
1578 QCOMPARE(type, sError); |
|
1579 QCOMPARE(ret, QLatin1String("TypeError: Result of expression '(function() { }).connect' [undefined] is not a function.")); |
|
1580 } |
|
1581 { |
|
1582 QString type; |
|
1583 QString ret = evalJS("var o = { }; o.connect = Function.prototype.connect; o.connect(123)", type); |
|
1584 QCOMPARE(type, sError); |
|
1585 QCOMPARE(ret, QLatin1String("TypeError: Result of expression 'o.connect' [undefined] is not a function.")); |
|
1586 } |
|
1587 |
|
1588 { |
|
1589 QString type; |
|
1590 QString ret = evalJS("myObject.myInvokable.connect(123)", type); |
|
1591 QCOMPARE(type, sError); |
|
1592 QCOMPARE(ret, QLatin1String("TypeError: QtMetaMethod.connect: MyQObject::myInvokable() is not a signal")); |
|
1593 } |
|
1594 { |
|
1595 QString type; |
|
1596 QString ret = evalJS("myObject.myInvokable.connect(function() { })", type); |
|
1597 QCOMPARE(type, sError); |
|
1598 QCOMPARE(ret, QLatin1String("TypeError: QtMetaMethod.connect: MyQObject::myInvokable() is not a signal")); |
|
1599 } |
|
1600 |
|
1601 { |
|
1602 QString type; |
|
1603 QString ret = evalJS("myObject.mySignal.connect(123)", type); |
|
1604 QCOMPARE(type, sError); |
|
1605 QCOMPARE(ret, QLatin1String("TypeError: QtMetaMethod.connect: target is not a function")); |
|
1606 } |
|
1607 |
|
1608 { |
|
1609 QString type; |
|
1610 QString ret = evalJS("myObject.mySignal.disconnect()", type); |
|
1611 QCOMPARE(type, sError); |
|
1612 QCOMPARE(ret, QLatin1String("Error: QtMetaMethod.disconnect: no arguments given")); |
|
1613 } |
|
1614 { |
|
1615 QString type; |
|
1616 QString ret = evalJS("var o = { }; o.disconnect = myObject.mySignal.disconnect; o.disconnect()", type); |
|
1617 QCOMPARE(type, sError); |
|
1618 QCOMPARE(ret, QLatin1String("Error: QtMetaMethod.disconnect: no arguments given")); |
|
1619 } |
|
1620 |
|
1621 /* XFAIL - Function.prototype doesn't get connect/disconnect, just signals/slots |
|
1622 { |
|
1623 QString type; |
|
1624 QString ret = evalJS("(function() { }).disconnect(123)", type); |
|
1625 QCOMPARE(type, sError); |
|
1626 QCOMPARE(ret, QLatin1String("TypeError: QtMetaMethod.disconnect: this object is not a signal")); |
|
1627 } |
|
1628 */ |
|
1629 |
|
1630 { |
|
1631 QString type; |
|
1632 QString ret = evalJS("var o = { }; o.disconnect = myObject.myInvokable.disconnect; o.disconnect(123)", type); |
|
1633 QCOMPARE(type, sError); |
|
1634 QCOMPARE(ret, QLatin1String("TypeError: QtMetaMethod.disconnect: MyQObject::myInvokable() is not a signal")); |
|
1635 } |
|
1636 |
|
1637 { |
|
1638 QString type; |
|
1639 QString ret = evalJS("myObject.myInvokable.disconnect(123)", type); |
|
1640 QCOMPARE(type, sError); |
|
1641 QCOMPARE(ret, QLatin1String("TypeError: QtMetaMethod.disconnect: MyQObject::myInvokable() is not a signal")); |
|
1642 } |
|
1643 { |
|
1644 QString type; |
|
1645 QString ret = evalJS("myObject.myInvokable.disconnect(function() { })", type); |
|
1646 QCOMPARE(type, sError); |
|
1647 QCOMPARE(ret, QLatin1String("TypeError: QtMetaMethod.disconnect: MyQObject::myInvokable() is not a signal")); |
|
1648 } |
|
1649 |
|
1650 { |
|
1651 QString type; |
|
1652 QString ret = evalJS("myObject.mySignal.disconnect(123)", type); |
|
1653 QCOMPARE(type, sError); |
|
1654 QCOMPARE(ret, QLatin1String("TypeError: QtMetaMethod.disconnect: target is not a function")); |
|
1655 } |
|
1656 |
|
1657 { |
|
1658 QString type; |
|
1659 QString ret = evalJS("myObject.mySignal.disconnect(function() { })", type); |
|
1660 QCOMPARE(type, sError); |
|
1661 QCOMPARE(ret, QLatin1String("Error: QtMetaMethod.disconnect: failed to disconnect from MyQObject::mySignal()")); |
|
1662 } |
|
1663 |
|
1664 // when the wrapper dies, the connection stays alive |
|
1665 QCOMPARE(evalJS("myObject.mySignal.connect(myObject.mySlot)"), sUndefined); |
|
1666 m_myObject->resetQtFunctionInvoked(); |
|
1667 m_myObject->emitMySignal(); |
|
1668 QCOMPARE(m_myObject->qtFunctionInvoked(), 20); |
|
1669 evalJS("myObject = null"); |
|
1670 evalJS("gc()"); |
|
1671 m_myObject->resetQtFunctionInvoked(); |
|
1672 m_myObject->emitMySignal(); |
|
1673 QCOMPARE(m_myObject->qtFunctionInvoked(), 20); |
|
1674 } |
|
1675 |
|
1676 void tst_QWebFrame::classEnums() |
|
1677 { |
|
1678 // We don't do the meta thing currently, unfortunately!!! |
|
1679 /* |
|
1680 QString myClass = m_engine->newQMetaObject(m_myObject->metaObject(), m_engine->undefinedValue()); |
|
1681 m_engine->globalObject().setProperty("MyQObject", myClass); |
|
1682 |
|
1683 QCOMPARE(static_cast<MyQObject::Policy>(evalJS("MyQObject.FooPolicy").toInt()), |
|
1684 MyQObject::FooPolicy); |
|
1685 QCOMPARE(static_cast<MyQObject::Policy>(evalJS("MyQObject.BarPolicy").toInt()), |
|
1686 MyQObject::BarPolicy); |
|
1687 QCOMPARE(static_cast<MyQObject::Policy>(evalJS("MyQObject.BazPolicy").toInt()), |
|
1688 MyQObject::BazPolicy); |
|
1689 |
|
1690 QCOMPARE(static_cast<MyQObject::Strategy>(evalJS("MyQObject.FooStrategy").toInt()), |
|
1691 MyQObject::FooStrategy); |
|
1692 QCOMPARE(static_cast<MyQObject::Strategy>(evalJS("MyQObject.BarStrategy").toInt()), |
|
1693 MyQObject::BarStrategy); |
|
1694 QCOMPARE(static_cast<MyQObject::Strategy>(evalJS("MyQObject.BazStrategy").toInt()), |
|
1695 MyQObject::BazStrategy); |
|
1696 |
|
1697 QCOMPARE(MyQObject::Ability(evalJS("MyQObject.NoAbility").toInt()), |
|
1698 MyQObject::NoAbility); |
|
1699 QCOMPARE(MyQObject::Ability(evalJS("MyQObject.FooAbility").toInt()), |
|
1700 MyQObject::FooAbility); |
|
1701 QCOMPARE(MyQObject::Ability(evalJS("MyQObject.BarAbility").toInt()), |
|
1702 MyQObject::BarAbility); |
|
1703 QCOMPARE(MyQObject::Ability(evalJS("MyQObject.BazAbility").toInt()), |
|
1704 MyQObject::BazAbility); |
|
1705 QCOMPARE(MyQObject::Ability(evalJS("MyQObject.AllAbility").toInt()), |
|
1706 MyQObject::AllAbility); |
|
1707 |
|
1708 // enums from Qt are inherited through prototype |
|
1709 QCOMPARE(static_cast<Qt::FocusPolicy>(evalJS("MyQObject.StrongFocus").toInt()), |
|
1710 Qt::StrongFocus); |
|
1711 QCOMPARE(static_cast<Qt::Key>(evalJS("MyQObject.Key_Left").toInt()), |
|
1712 Qt::Key_Left); |
|
1713 |
|
1714 QCOMPARE(evalJS("MyQObject.className()"), QLatin1String("MyQObject")); |
|
1715 |
|
1716 qRegisterMetaType<MyQObject::Policy>("Policy"); |
|
1717 |
|
1718 m_myObject->resetQtFunctionInvoked(); |
|
1719 QCOMPARE(evalJS("myObject.myInvokableWithEnumArg(MyQObject.BazPolicy)"), sUndefined); |
|
1720 QCOMPARE(m_myObject->qtFunctionInvoked(), 10); |
|
1721 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1722 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), int(MyQObject::BazPolicy)); |
|
1723 |
|
1724 m_myObject->resetQtFunctionInvoked(); |
|
1725 QCOMPARE(evalJS("myObject.myInvokableWithQualifiedEnumArg(MyQObject.BazPolicy)"), sUndefined); |
|
1726 QCOMPARE(m_myObject->qtFunctionInvoked(), 36); |
|
1727 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
1728 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), int(MyQObject::BazPolicy)); |
|
1729 |
|
1730 m_myObject->resetQtFunctionInvoked(); |
|
1731 { |
|
1732 QVariant ret = evalJS("myObject.myInvokableReturningEnum()"); |
|
1733 QCOMPARE(m_myObject->qtFunctionInvoked(), 37); |
|
1734 QCOMPARE(m_myObject->qtFunctionActuals().size(), 0); |
|
1735 QCOMPARE(ret.isVariant()); |
|
1736 } |
|
1737 m_myObject->resetQtFunctionInvoked(); |
|
1738 { |
|
1739 QVariant ret = evalJS("myObject.myInvokableReturningQualifiedEnum()"); |
|
1740 QCOMPARE(m_myObject->qtFunctionInvoked(), 38); |
|
1741 QCOMPARE(m_myObject->qtFunctionActuals().size(), 0); |
|
1742 QCOMPARE(ret.isNumber()); |
|
1743 } |
|
1744 */ |
|
1745 } |
|
1746 |
|
1747 void tst_QWebFrame::classConstructor() |
|
1748 { |
|
1749 /* |
|
1750 QString myClass = qScriptValueFromQMetaObject<MyQObject>(m_engine); |
|
1751 m_engine->globalObject().setProperty("MyQObject", myClass); |
|
1752 |
|
1753 QString myObj = evalJS("myObj = MyQObject()"); |
|
1754 QObject* qobj = myObj.toQObject(); |
|
1755 QVERIFY(qobj != 0); |
|
1756 QCOMPARE(qobj->metaObject()->className(), "MyQObject"); |
|
1757 QCOMPARE(qobj->parent(), (QObject*)0); |
|
1758 |
|
1759 QString qobjectClass = qScriptValueFromQMetaObject<QObject>(m_engine); |
|
1760 m_engine->globalObject().setProperty("QObject", qobjectClass); |
|
1761 |
|
1762 QString otherObj = evalJS("otherObj = QObject(myObj)"); |
|
1763 QObject* qqobj = otherObj.toQObject(); |
|
1764 QVERIFY(qqobj != 0); |
|
1765 QCOMPARE(qqobj->metaObject()->className(), "QObject"); |
|
1766 QCOMPARE(qqobj->parent(), qobj); |
|
1767 |
|
1768 delete qobj; |
|
1769 */ |
|
1770 } |
|
1771 |
|
1772 void tst_QWebFrame::overrideInvokable() |
|
1773 { |
|
1774 m_myObject->resetQtFunctionInvoked(); |
|
1775 QCOMPARE(evalJS("myObject.myInvokable()"), sUndefined); |
|
1776 QCOMPARE(m_myObject->qtFunctionInvoked(), 0); |
|
1777 |
|
1778 /* XFAIL - can't write to functions with RuntimeObject |
|
1779 m_myObject->resetQtFunctionInvoked(); |
|
1780 evalJS("myObject.myInvokable = function() { window.a = 123; }"); |
|
1781 evalJS("myObject.myInvokable()"); |
|
1782 QCOMPARE(m_myObject->qtFunctionInvoked(), -1); |
|
1783 QCOMPARE(evalJS("window.a").toDouble(), 123.0); |
|
1784 |
|
1785 evalJS("myObject.myInvokable = function() { window.a = 456; }"); |
|
1786 evalJS("myObject.myInvokable()"); |
|
1787 QCOMPARE(m_myObject->qtFunctionInvoked(), -1); |
|
1788 QCOMPARE(evalJS("window.a").toDouble(), 456.0); |
|
1789 */ |
|
1790 |
|
1791 evalJS("delete myObject.myInvokable"); |
|
1792 evalJS("myObject.myInvokable()"); |
|
1793 QCOMPARE(m_myObject->qtFunctionInvoked(), 0); |
|
1794 |
|
1795 /* XFAIL - ditto |
|
1796 m_myObject->resetQtFunctionInvoked(); |
|
1797 evalJS("myObject.myInvokable = myObject.myInvokableWithIntArg"); |
|
1798 evalJS("myObject.myInvokable(123)"); |
|
1799 QCOMPARE(m_myObject->qtFunctionInvoked(), 1); |
|
1800 */ |
|
1801 |
|
1802 evalJS("delete myObject.myInvokable"); |
|
1803 m_myObject->resetQtFunctionInvoked(); |
|
1804 // this form (with the '()') is read-only |
|
1805 evalJS("myObject['myInvokable()'] = function() { window.a = 123; }"); |
|
1806 evalJS("myObject.myInvokable()"); |
|
1807 QCOMPARE(m_myObject->qtFunctionInvoked(), 0); |
|
1808 } |
|
1809 |
|
1810 void tst_QWebFrame::transferInvokable() |
|
1811 { |
|
1812 /* XFAIL - can't put to functions with RuntimeObject |
|
1813 m_myObject->resetQtFunctionInvoked(); |
|
1814 evalJS("myObject.foozball = myObject.myInvokable"); |
|
1815 evalJS("myObject.foozball()"); |
|
1816 QCOMPARE(m_myObject->qtFunctionInvoked(), 0); |
|
1817 m_myObject->resetQtFunctionInvoked(); |
|
1818 evalJS("myObject.foozball = myObject.myInvokableWithIntArg"); |
|
1819 evalJS("myObject.foozball(123)"); |
|
1820 QCOMPARE(m_myObject->qtFunctionInvoked(), 1); |
|
1821 m_myObject->resetQtFunctionInvoked(); |
|
1822 evalJS("myObject.myInvokable = myObject.myInvokableWithIntArg"); |
|
1823 evalJS("myObject.myInvokable(123)"); |
|
1824 QCOMPARE(m_myObject->qtFunctionInvoked(), 1); |
|
1825 |
|
1826 MyOtherQObject other; |
|
1827 m_page->mainFrame()->addToJSWindowObject("myOtherObject", &other); |
|
1828 evalJS("myOtherObject.foo = myObject.foozball"); |
|
1829 other.resetQtFunctionInvoked(); |
|
1830 evalJS("myOtherObject.foo(456)"); |
|
1831 QCOMPARE(other.qtFunctionInvoked(), 1); |
|
1832 */ |
|
1833 } |
|
1834 |
|
1835 void tst_QWebFrame::findChild() |
|
1836 { |
|
1837 /* |
|
1838 QObject* child = new QObject(m_myObject); |
|
1839 child->setObjectName(QLatin1String("myChildObject")); |
|
1840 |
|
1841 { |
|
1842 QString result = evalJS("myObject.findChild('noSuchChild')"); |
|
1843 QCOMPARE(result.isNull()); |
|
1844 } |
|
1845 |
|
1846 { |
|
1847 QString result = evalJS("myObject.findChild('myChildObject')"); |
|
1848 QCOMPARE(result.isQObject()); |
|
1849 QCOMPARE(result.toQObject(), child); |
|
1850 } |
|
1851 |
|
1852 delete child; |
|
1853 */ |
|
1854 } |
|
1855 |
|
1856 void tst_QWebFrame::findChildren() |
|
1857 { |
|
1858 /* |
|
1859 QObject* child = new QObject(m_myObject); |
|
1860 child->setObjectName(QLatin1String("myChildObject")); |
|
1861 |
|
1862 { |
|
1863 QString result = evalJS("myObject.findChildren('noSuchChild')"); |
|
1864 QCOMPARE(result.isArray()); |
|
1865 QCOMPARE(result.property(QLatin1String("length")).toDouble(), 0.0); |
|
1866 } |
|
1867 |
|
1868 { |
|
1869 QString result = evalJS("myObject.findChildren('myChildObject')"); |
|
1870 QCOMPARE(result.isArray()); |
|
1871 QCOMPARE(result.property(QLatin1String("length")).toDouble(), 1.0); |
|
1872 QCOMPARE(result.property(QLatin1String("0")).toQObject(), child); |
|
1873 } |
|
1874 |
|
1875 QObject* namelessChild = new QObject(m_myObject); |
|
1876 |
|
1877 { |
|
1878 QString result = evalJS("myObject.findChildren('myChildObject')"); |
|
1879 QCOMPARE(result.isArray()); |
|
1880 QCOMPARE(result.property(QLatin1String("length")).toDouble(), 1.0); |
|
1881 QCOMPARE(result.property(QLatin1String("0")).toQObject(), child); |
|
1882 } |
|
1883 |
|
1884 QObject* anotherChild = new QObject(m_myObject); |
|
1885 anotherChild->setObjectName(QLatin1String("anotherChildObject")); |
|
1886 |
|
1887 { |
|
1888 QString result = evalJS("myObject.findChildren('anotherChildObject')"); |
|
1889 QCOMPARE(result.isArray()); |
|
1890 QCOMPARE(result.property(QLatin1String("length")).toDouble(), 1.0); |
|
1891 QCOMPARE(result.property(QLatin1String("0")).toQObject(), anotherChild); |
|
1892 } |
|
1893 |
|
1894 anotherChild->setObjectName(QLatin1String("myChildObject")); |
|
1895 { |
|
1896 QString result = evalJS("myObject.findChildren('myChildObject')"); |
|
1897 QCOMPARE(result.isArray()); |
|
1898 QCOMPARE(result.property(QLatin1String("length")).toDouble(), 2.0); |
|
1899 QObject* o1 = result.property(QLatin1String("0")).toQObject(); |
|
1900 QObject* o2 = result.property(QLatin1String("1")).toQObject(); |
|
1901 if (o1 != child) { |
|
1902 QCOMPARE(o1, anotherChild); |
|
1903 QCOMPARE(o2, child); |
|
1904 } else { |
|
1905 QCOMPARE(o1, child); |
|
1906 QCOMPARE(o2, anotherChild); |
|
1907 } |
|
1908 } |
|
1909 |
|
1910 // find all |
|
1911 { |
|
1912 QString result = evalJS("myObject.findChildren()"); |
|
1913 QVERIFY(result.isArray()); |
|
1914 int count = 3; |
|
1915 QCOMPARE(result.property("length"), QLatin1String(count); |
|
1916 for (int i = 0; i < 3; ++i) { |
|
1917 QObject* o = result.property(i).toQObject(); |
|
1918 if (o == namelessChild || o == child || o == anotherChild) |
|
1919 --count; |
|
1920 } |
|
1921 QVERIFY(count == 0); |
|
1922 } |
|
1923 |
|
1924 delete anotherChild; |
|
1925 delete namelessChild; |
|
1926 delete child; |
|
1927 */ |
|
1928 } |
|
1929 |
|
1930 void tst_QWebFrame::overloadedSlots() |
|
1931 { |
|
1932 // should pick myOverloadedSlot(double) |
|
1933 m_myObject->resetQtFunctionInvoked(); |
|
1934 evalJS("myObject.myOverloadedSlot(10)"); |
|
1935 QCOMPARE(m_myObject->qtFunctionInvoked(), 26); |
|
1936 |
|
1937 // should pick myOverloadedSlot(double) |
|
1938 m_myObject->resetQtFunctionInvoked(); |
|
1939 evalJS("myObject.myOverloadedSlot(10.0)"); |
|
1940 QCOMPARE(m_myObject->qtFunctionInvoked(), 26); |
|
1941 |
|
1942 // should pick myOverloadedSlot(QString) |
|
1943 m_myObject->resetQtFunctionInvoked(); |
|
1944 evalJS("myObject.myOverloadedSlot('10')"); |
|
1945 QCOMPARE(m_myObject->qtFunctionInvoked(), 29); |
|
1946 |
|
1947 // should pick myOverloadedSlot(bool) |
|
1948 m_myObject->resetQtFunctionInvoked(); |
|
1949 evalJS("myObject.myOverloadedSlot(true)"); |
|
1950 QCOMPARE(m_myObject->qtFunctionInvoked(), 25); |
|
1951 |
|
1952 // should pick myOverloadedSlot(QDateTime) |
|
1953 m_myObject->resetQtFunctionInvoked(); |
|
1954 evalJS("myObject.myOverloadedSlot(new Date())"); |
|
1955 QCOMPARE(m_myObject->qtFunctionInvoked(), 32); |
|
1956 |
|
1957 // should pick myOverloadedSlot(QRegExp) |
|
1958 m_myObject->resetQtFunctionInvoked(); |
|
1959 evalJS("myObject.myOverloadedSlot(new RegExp())"); |
|
1960 QCOMPARE(m_myObject->qtFunctionInvoked(), 34); |
|
1961 |
|
1962 // should pick myOverloadedSlot(QVariant) |
|
1963 /* XFAIL |
|
1964 m_myObject->resetQtFunctionInvoked(); |
|
1965 QString f = evalJS("myObject.myOverloadedSlot"); |
|
1966 f.call(QString(), QStringList() << m_engine->newVariant(QVariant("ciao"))); |
|
1967 QCOMPARE(m_myObject->qtFunctionInvoked(), 35); |
|
1968 */ |
|
1969 |
|
1970 // should pick myOverloadedSlot(QRegExp) |
|
1971 m_myObject->resetQtFunctionInvoked(); |
|
1972 evalJS("myObject.myOverloadedSlot(document.body)"); |
|
1973 QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=37319", Continue); |
|
1974 QCOMPARE(m_myObject->qtFunctionInvoked(), 36); |
|
1975 |
|
1976 // should pick myOverloadedSlot(QObject*) |
|
1977 m_myObject->resetQtFunctionInvoked(); |
|
1978 evalJS("myObject.myOverloadedSlot(myObject)"); |
|
1979 QCOMPARE(m_myObject->qtFunctionInvoked(), 41); |
|
1980 |
|
1981 // should pick myOverloadedSlot(QObject*) |
|
1982 m_myObject->resetQtFunctionInvoked(); |
|
1983 evalJS("myObject.myOverloadedSlot(null)"); |
|
1984 QCOMPARE(m_myObject->qtFunctionInvoked(), 41); |
|
1985 |
|
1986 // should pick myOverloadedSlot(QStringList) |
|
1987 m_myObject->resetQtFunctionInvoked(); |
|
1988 evalJS("myObject.myOverloadedSlot(['hello'])"); |
|
1989 QCOMPARE(m_myObject->qtFunctionInvoked(), 42); |
|
1990 } |
|
1991 |
|
1992 void tst_QWebFrame::enumerate_data() |
|
1993 { |
|
1994 QTest::addColumn<QStringList>("expectedNames"); |
|
1995 |
|
1996 QTest::newRow("enumerate all") |
|
1997 << (QStringList() |
|
1998 // meta-object-defined properties: |
|
1999 // inherited |
|
2000 << "objectName" |
|
2001 // non-inherited |
|
2002 << "p1" << "p2" << "p4" << "p6" |
|
2003 // dynamic properties |
|
2004 << "dp1" << "dp2" << "dp3" |
|
2005 // inherited slots |
|
2006 << "destroyed(QObject*)" << "destroyed()" |
|
2007 << "deleteLater()" |
|
2008 // not included because it's private: |
|
2009 // << "_q_reregisterTimers(void*)" |
|
2010 // signals |
|
2011 << "mySignal()" |
|
2012 // slots |
|
2013 << "mySlot()" << "myOtherSlot()"); |
|
2014 } |
|
2015 |
|
2016 void tst_QWebFrame::enumerate() |
|
2017 { |
|
2018 QFETCH(QStringList, expectedNames); |
|
2019 |
|
2020 MyEnumTestQObject enumQObject; |
|
2021 // give it some dynamic properties |
|
2022 enumQObject.setProperty("dp1", "dp1"); |
|
2023 enumQObject.setProperty("dp2", "dp2"); |
|
2024 enumQObject.setProperty("dp3", "dp3"); |
|
2025 m_page->mainFrame()->addToJavaScriptWindowObject("myEnumObject", &enumQObject); |
|
2026 |
|
2027 // enumerate in script |
|
2028 { |
|
2029 evalJS("var enumeratedProperties = []"); |
|
2030 evalJS("for (var p in myEnumObject) { enumeratedProperties.push(p); }"); |
|
2031 QStringList result = evalJSV("enumeratedProperties").toStringList(); |
|
2032 QCOMPARE(result.size(), expectedNames.size()); |
|
2033 for (int i = 0; i < expectedNames.size(); ++i) |
|
2034 QCOMPARE(result.at(i), expectedNames.at(i)); |
|
2035 } |
|
2036 } |
|
2037 |
|
2038 void tst_QWebFrame::objectDeleted() |
|
2039 { |
|
2040 MyQObject* qobj = new MyQObject(); |
|
2041 m_page->mainFrame()->addToJavaScriptWindowObject("bar", qobj); |
|
2042 evalJS("bar.objectName = 'foo';"); |
|
2043 QCOMPARE(qobj->objectName(), QLatin1String("foo")); |
|
2044 evalJS("bar.intProperty = 123;"); |
|
2045 QCOMPARE(qobj->intProperty(), 123); |
|
2046 qobj->resetQtFunctionInvoked(); |
|
2047 evalJS("bar.myInvokable.call(bar);"); |
|
2048 QCOMPARE(qobj->qtFunctionInvoked(), 0); |
|
2049 |
|
2050 // do this, to ensure that we cache that it implements call |
|
2051 evalJS("bar()"); |
|
2052 |
|
2053 // now delete the object |
|
2054 delete qobj; |
|
2055 |
|
2056 QCOMPARE(evalJS("typeof bar"), sObject); |
|
2057 |
|
2058 // any attempt to access properties of the object should result in an exception |
|
2059 { |
|
2060 QString type; |
|
2061 QString ret = evalJS("bar.objectName", type); |
|
2062 QCOMPARE(type, sError); |
|
2063 QCOMPARE(ret, QLatin1String("Error: cannot access member `objectName' of deleted QObject")); |
|
2064 } |
|
2065 { |
|
2066 QString type; |
|
2067 QString ret = evalJS("bar.objectName = 'foo'", type); |
|
2068 QCOMPARE(type, sError); |
|
2069 QCOMPARE(ret, QLatin1String("Error: cannot access member `objectName' of deleted QObject")); |
|
2070 } |
|
2071 |
|
2072 // myInvokable is stored in member table (since we've accessed it before deletion) |
|
2073 { |
|
2074 QString type; |
|
2075 evalJS("bar.myInvokable", type); |
|
2076 QCOMPARE(type, sFunction); |
|
2077 } |
|
2078 |
|
2079 { |
|
2080 QString type; |
|
2081 QString ret = evalJS("bar.myInvokable.call(bar);", type); |
|
2082 ret = evalJS("bar.myInvokable(bar)", type); |
|
2083 QCOMPARE(type, sError); |
|
2084 QCOMPARE(ret, QLatin1String("Error: cannot call function of deleted QObject")); |
|
2085 } |
|
2086 // myInvokableWithIntArg is not stored in member table (since we've not accessed it) |
|
2087 { |
|
2088 QString type; |
|
2089 QString ret = evalJS("bar.myInvokableWithIntArg", type); |
|
2090 QCOMPARE(type, sError); |
|
2091 QCOMPARE(ret, QLatin1String("Error: cannot access member `myInvokableWithIntArg' of deleted QObject")); |
|
2092 } |
|
2093 |
|
2094 // access from script |
|
2095 evalJS("window.o = bar;"); |
|
2096 { |
|
2097 QString type; |
|
2098 QString ret = evalJS("o.objectName", type); |
|
2099 QCOMPARE(type, sError); |
|
2100 QCOMPARE(ret, QLatin1String("Error: cannot access member `objectName' of deleted QObject")); |
|
2101 } |
|
2102 { |
|
2103 QString type; |
|
2104 QString ret = evalJS("o.myInvokable()", type); |
|
2105 QCOMPARE(type, sError); |
|
2106 QCOMPARE(ret, QLatin1String("Error: cannot call function of deleted QObject")); |
|
2107 } |
|
2108 { |
|
2109 QString type; |
|
2110 QString ret = evalJS("o.myInvokableWithIntArg(10)", type); |
|
2111 QCOMPARE(type, sError); |
|
2112 QCOMPARE(ret, QLatin1String("Error: cannot access member `myInvokableWithIntArg' of deleted QObject")); |
|
2113 } |
|
2114 } |
|
2115 |
|
2116 void tst_QWebFrame::typeConversion() |
|
2117 { |
|
2118 m_myObject->resetQtFunctionInvoked(); |
|
2119 |
|
2120 QDateTime localdt(QDate(2008,1,18), QTime(12,31,0)); |
|
2121 QDateTime utclocaldt = localdt.toUTC(); |
|
2122 QDateTime utcdt(QDate(2008,1,18), QTime(12,31,0), Qt::UTC); |
|
2123 |
|
2124 // Dates in JS (default to local) |
|
2125 evalJS("myObject.myOverloadedSlot(new Date(2008,0,18,12,31,0))"); |
|
2126 QCOMPARE(m_myObject->qtFunctionInvoked(), 32); |
|
2127 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
2128 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toDateTime().toUTC(), utclocaldt); |
|
2129 |
|
2130 m_myObject->resetQtFunctionInvoked(); |
|
2131 evalJS("myObject.myOverloadedSlot(new Date(Date.UTC(2008,0,18,12,31,0)))"); |
|
2132 QCOMPARE(m_myObject->qtFunctionInvoked(), 32); |
|
2133 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); |
|
2134 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toDateTime().toUTC(), utcdt); |
|
2135 |
|
2136 // Pushing QDateTimes into JS |
|
2137 // Local |
|
2138 evalJS("function checkDate(d) {window.__date_equals = (d.toString() == new Date(2008,0,18,12,31,0))?true:false;}"); |
|
2139 evalJS("myObject.mySignalWithDateTimeArg.connect(checkDate)"); |
|
2140 m_myObject->emitMySignalWithDateTimeArg(localdt); |
|
2141 QCOMPARE(evalJS("window.__date_equals"), sTrue); |
|
2142 evalJS("delete window.__date_equals"); |
|
2143 m_myObject->emitMySignalWithDateTimeArg(utclocaldt); |
|
2144 QCOMPARE(evalJS("window.__date_equals"), sTrue); |
|
2145 evalJS("delete window.__date_equals"); |
|
2146 evalJS("myObject.mySignalWithDateTimeArg.disconnect(checkDate); delete checkDate;"); |
|
2147 |
|
2148 // UTC |
|
2149 evalJS("function checkDate(d) {window.__date_equals = (d.toString() == new Date(Date.UTC(2008,0,18,12,31,0)))?true:false; }"); |
|
2150 evalJS("myObject.mySignalWithDateTimeArg.connect(checkDate)"); |
|
2151 m_myObject->emitMySignalWithDateTimeArg(utcdt); |
|
2152 QCOMPARE(evalJS("window.__date_equals"), sTrue); |
|
2153 evalJS("delete window.__date_equals"); |
|
2154 evalJS("myObject.mySignalWithDateTimeArg.disconnect(checkDate); delete checkDate;"); |
|
2155 |
|
2156 // ### RegExps |
|
2157 } |
|
2158 |
|
2159 class StringListTestObject : public QObject { |
|
2160 Q_OBJECT |
|
2161 public Q_SLOTS: |
|
2162 QVariant stringList() |
|
2163 { |
|
2164 return QStringList() << "Q" << "t"; |
|
2165 }; |
|
2166 }; |
|
2167 |
|
2168 void tst_QWebFrame::arrayObjectEnumerable() |
|
2169 { |
|
2170 QWebPage page; |
|
2171 QWebFrame* frame = page.mainFrame(); |
|
2172 QObject* qobject = new StringListTestObject(); |
|
2173 frame->addToJavaScriptWindowObject("test", qobject, QScriptEngine::ScriptOwnership); |
|
2174 |
|
2175 const QString script("var stringArray = test.stringList();" |
|
2176 "var result = '';" |
|
2177 "for (var i in stringArray) {" |
|
2178 " result += stringArray[i];" |
|
2179 "}" |
|
2180 "result;"); |
|
2181 QCOMPARE(frame->evaluateJavaScript(script).toString(), QString::fromLatin1("Qt")); |
|
2182 } |
|
2183 |
|
2184 void tst_QWebFrame::symmetricUrl() |
|
2185 { |
|
2186 QVERIFY(m_view->url().isEmpty()); |
|
2187 |
|
2188 QCOMPARE(m_view->history()->count(), 0); |
|
2189 |
|
2190 QUrl dataUrl("data:text/html,<h1>Test"); |
|
2191 |
|
2192 m_view->setUrl(dataUrl); |
|
2193 QCOMPARE(m_view->url(), dataUrl); |
|
2194 QCOMPARE(m_view->history()->count(), 0); |
|
2195 |
|
2196 // loading is _not_ immediate, so the text isn't set just yet. |
|
2197 QVERIFY(m_view->page()->mainFrame()->toPlainText().isEmpty()); |
|
2198 |
|
2199 ::waitForSignal(m_view, SIGNAL(loadFinished(bool))); |
|
2200 |
|
2201 QCOMPARE(m_view->history()->count(), 1); |
|
2202 QCOMPARE(m_view->page()->mainFrame()->toPlainText(), QString("Test")); |
|
2203 |
|
2204 QUrl dataUrl2("data:text/html,<h1>Test2"); |
|
2205 QUrl dataUrl3("data:text/html,<h1>Test3"); |
|
2206 |
|
2207 m_view->setUrl(dataUrl2); |
|
2208 m_view->setUrl(dataUrl3); |
|
2209 |
|
2210 QCOMPARE(m_view->url(), dataUrl3); |
|
2211 |
|
2212 ::waitForSignal(m_view, SIGNAL(loadFinished(bool))); |
|
2213 |
|
2214 QCOMPARE(m_view->history()->count(), 2); |
|
2215 |
|
2216 QCOMPARE(m_view->page()->mainFrame()->toPlainText(), QString("Test3")); |
|
2217 } |
|
2218 |
|
2219 void tst_QWebFrame::progressSignal() |
|
2220 { |
|
2221 QSignalSpy progressSpy(m_view, SIGNAL(loadProgress(int))); |
|
2222 |
|
2223 QUrl dataUrl("data:text/html,<h1>Test"); |
|
2224 m_view->setUrl(dataUrl); |
|
2225 |
|
2226 ::waitForSignal(m_view, SIGNAL(loadFinished(bool))); |
|
2227 |
|
2228 QVERIFY(progressSpy.size() >= 2); |
|
2229 |
|
2230 // WebKit defines initialProgressValue as 10%, not 0% |
|
2231 QCOMPARE(progressSpy.first().first().toInt(), 10); |
|
2232 |
|
2233 // But we always end at 100% |
|
2234 QCOMPARE(progressSpy.last().first().toInt(), 100); |
|
2235 } |
|
2236 |
|
2237 void tst_QWebFrame::urlChange() |
|
2238 { |
|
2239 QSignalSpy urlSpy(m_page->mainFrame(), SIGNAL(urlChanged(QUrl))); |
|
2240 |
|
2241 QUrl dataUrl("data:text/html,<h1>Test"); |
|
2242 m_view->setUrl(dataUrl); |
|
2243 |
|
2244 ::waitForSignal(m_page->mainFrame(), SIGNAL(urlChanged(QUrl))); |
|
2245 |
|
2246 QCOMPARE(urlSpy.size(), 1); |
|
2247 |
|
2248 QUrl dataUrl2("data:text/html,<html><head><title>title</title></head><body><h1>Test</body></html>"); |
|
2249 m_view->setUrl(dataUrl2); |
|
2250 |
|
2251 ::waitForSignal(m_page->mainFrame(), SIGNAL(urlChanged(QUrl))); |
|
2252 |
|
2253 QCOMPARE(urlSpy.size(), 2); |
|
2254 } |
|
2255 |
|
2256 |
|
2257 void tst_QWebFrame::domCycles() |
|
2258 { |
|
2259 m_view->setHtml("<html><body>"); |
|
2260 QVariant v = m_page->mainFrame()->evaluateJavaScript("document"); |
|
2261 QVERIFY(v.type() == QVariant::Map); |
|
2262 } |
|
2263 |
|
2264 class FakeReply : public QNetworkReply { |
|
2265 Q_OBJECT |
|
2266 |
|
2267 public: |
|
2268 FakeReply(const QNetworkRequest& request, QObject* parent = 0) |
|
2269 : QNetworkReply(parent) |
|
2270 { |
|
2271 setOperation(QNetworkAccessManager::GetOperation); |
|
2272 setRequest(request); |
|
2273 if (request.url() == QUrl("qrc:/test1.html")) { |
|
2274 setHeader(QNetworkRequest::LocationHeader, QString("qrc:/test2.html")); |
|
2275 setAttribute(QNetworkRequest::RedirectionTargetAttribute, QUrl("qrc:/test2.html")); |
|
2276 } |
|
2277 #ifndef QT_NO_OPENSSL |
|
2278 else if (request.url() == QUrl("qrc:/fake-ssl-error.html")) |
|
2279 setError(QNetworkReply::SslHandshakeFailedError, tr("Fake error !")); // force a ssl error |
|
2280 #endif |
|
2281 else if (request.url() == QUrl("http://abcdef.abcdef/")) |
|
2282 setError(QNetworkReply::HostNotFoundError, tr("Invalid URL")); |
|
2283 |
|
2284 open(QIODevice::ReadOnly); |
|
2285 QTimer::singleShot(0, this, SLOT(timeout())); |
|
2286 } |
|
2287 ~FakeReply() |
|
2288 { |
|
2289 close(); |
|
2290 } |
|
2291 virtual void abort() {} |
|
2292 virtual void close() {} |
|
2293 |
|
2294 protected: |
|
2295 qint64 readData(char*, qint64) |
|
2296 { |
|
2297 return 0; |
|
2298 } |
|
2299 |
|
2300 private slots: |
|
2301 void timeout() |
|
2302 { |
|
2303 if (request().url() == QUrl("qrc://test1.html")) |
|
2304 emit error(this->error()); |
|
2305 else if (request().url() == QUrl("http://abcdef.abcdef/")) |
|
2306 emit metaDataChanged(); |
|
2307 #ifndef QT_NO_OPENSSL |
|
2308 else if (request().url() == QUrl("qrc:/fake-ssl-error.html")) |
|
2309 return; |
|
2310 #endif |
|
2311 |
|
2312 emit readyRead(); |
|
2313 emit finished(); |
|
2314 } |
|
2315 }; |
|
2316 |
|
2317 class FakeNetworkManager : public QNetworkAccessManager { |
|
2318 Q_OBJECT |
|
2319 |
|
2320 public: |
|
2321 FakeNetworkManager(QObject* parent) : QNetworkAccessManager(parent) { } |
|
2322 |
|
2323 protected: |
|
2324 virtual QNetworkReply* createRequest(Operation op, const QNetworkRequest& request, QIODevice* outgoingData) |
|
2325 { |
|
2326 QString url = request.url().toString(); |
|
2327 if (op == QNetworkAccessManager::GetOperation) { |
|
2328 if (url == "qrc:/test1.html" || url == "http://abcdef.abcdef/") |
|
2329 return new FakeReply(request, this); |
|
2330 #ifndef QT_NO_OPENSSL |
|
2331 else if (url == "qrc:/fake-ssl-error.html") { |
|
2332 FakeReply* reply = new FakeReply(request, this); |
|
2333 QList<QSslError> errors; |
|
2334 emit sslErrors(reply, errors << QSslError(QSslError::UnspecifiedError)); |
|
2335 return reply; |
|
2336 } |
|
2337 #endif |
|
2338 } |
|
2339 |
|
2340 return QNetworkAccessManager::createRequest(op, request, outgoingData); |
|
2341 } |
|
2342 }; |
|
2343 |
|
2344 void tst_QWebFrame::requestedUrl() |
|
2345 { |
|
2346 QWebPage page; |
|
2347 QWebFrame* frame = page.mainFrame(); |
|
2348 |
|
2349 // in few seconds, the image should be completely loaded |
|
2350 QSignalSpy spy(&page, SIGNAL(loadFinished(bool))); |
|
2351 FakeNetworkManager* networkManager = new FakeNetworkManager(&page); |
|
2352 page.setNetworkAccessManager(networkManager); |
|
2353 |
|
2354 frame->setUrl(QUrl("qrc:/test1.html")); |
|
2355 waitForSignal(frame, SIGNAL(loadFinished(bool)), 200); |
|
2356 QCOMPARE(spy.count(), 1); |
|
2357 QCOMPARE(frame->requestedUrl(), QUrl("qrc:/test1.html")); |
|
2358 QCOMPARE(frame->url(), QUrl("qrc:/test2.html")); |
|
2359 |
|
2360 frame->setUrl(QUrl("qrc:/non-existent.html")); |
|
2361 waitForSignal(frame, SIGNAL(loadFinished(bool)), 200); |
|
2362 QCOMPARE(spy.count(), 2); |
|
2363 QCOMPARE(frame->requestedUrl(), QUrl("qrc:/non-existent.html")); |
|
2364 QCOMPARE(frame->url(), QUrl("qrc:/non-existent.html")); |
|
2365 |
|
2366 frame->setUrl(QUrl("http://abcdef.abcdef")); |
|
2367 waitForSignal(frame, SIGNAL(loadFinished(bool)), 200); |
|
2368 QCOMPARE(spy.count(), 3); |
|
2369 QCOMPARE(frame->requestedUrl(), QUrl("http://abcdef.abcdef/")); |
|
2370 QCOMPARE(frame->url(), QUrl("http://abcdef.abcdef/")); |
|
2371 |
|
2372 #ifndef QT_NO_OPENSSL |
|
2373 qRegisterMetaType<QList<QSslError> >("QList<QSslError>"); |
|
2374 qRegisterMetaType<QNetworkReply* >("QNetworkReply*"); |
|
2375 |
|
2376 QSignalSpy spy2(page.networkAccessManager(), SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>))); |
|
2377 frame->setUrl(QUrl("qrc:/fake-ssl-error.html")); |
|
2378 waitForSignal(frame, SIGNAL(loadFinished(bool)), 200); |
|
2379 QCOMPARE(spy2.count(), 1); |
|
2380 QCOMPARE(frame->requestedUrl(), QUrl("qrc:/fake-ssl-error.html")); |
|
2381 QCOMPARE(frame->url(), QUrl("qrc:/fake-ssl-error.html")); |
|
2382 #endif |
|
2383 } |
|
2384 |
|
2385 void tst_QWebFrame::javaScriptWindowObjectCleared_data() |
|
2386 { |
|
2387 QTest::addColumn<QString>("html"); |
|
2388 QTest::addColumn<int>("signalCount"); |
|
2389 QTest::newRow("with <script>") << "<html><body><script></script><p>hello world</p></body></html>" << 1; |
|
2390 QTest::newRow("without <script>") << "<html><body><p>hello world</p></body></html>" << 0; |
|
2391 } |
|
2392 |
|
2393 void tst_QWebFrame::javaScriptWindowObjectCleared() |
|
2394 { |
|
2395 QWebPage page; |
|
2396 QWebFrame* frame = page.mainFrame(); |
|
2397 QSignalSpy spy(frame, SIGNAL(javaScriptWindowObjectCleared())); |
|
2398 QFETCH(QString, html); |
|
2399 frame->setHtml(html); |
|
2400 |
|
2401 QFETCH(int, signalCount); |
|
2402 QCOMPARE(spy.count(), signalCount); |
|
2403 } |
|
2404 |
|
2405 void tst_QWebFrame::javaScriptWindowObjectClearedOnEvaluate() |
|
2406 { |
|
2407 QWebPage page; |
|
2408 QWebFrame* frame = page.mainFrame(); |
|
2409 QSignalSpy spy(frame, SIGNAL(javaScriptWindowObjectCleared())); |
|
2410 frame->setHtml("<html></html>"); |
|
2411 QCOMPARE(spy.count(), 0); |
|
2412 frame->evaluateJavaScript("var a = 'a';"); |
|
2413 QCOMPARE(spy.count(), 1); |
|
2414 // no new clear for a new script: |
|
2415 frame->evaluateJavaScript("var a = 1;"); |
|
2416 QCOMPARE(spy.count(), 1); |
|
2417 } |
|
2418 |
|
2419 void tst_QWebFrame::setHtml() |
|
2420 { |
|
2421 QString html("<html><head></head><body><p>hello world</p></body></html>"); |
|
2422 m_view->page()->mainFrame()->setHtml(html); |
|
2423 QCOMPARE(m_view->page()->mainFrame()->toHtml(), html); |
|
2424 } |
|
2425 |
|
2426 void tst_QWebFrame::setHtmlWithResource() |
|
2427 { |
|
2428 QString html("<html><body><p>hello world</p><img src='qrc:/image.png'/></body></html>"); |
|
2429 |
|
2430 QWebPage page; |
|
2431 QWebFrame* frame = page.mainFrame(); |
|
2432 |
|
2433 // in few seconds, the image should be completey loaded |
|
2434 QSignalSpy spy(&page, SIGNAL(loadFinished(bool))); |
|
2435 frame->setHtml(html); |
|
2436 waitForSignal(frame, SIGNAL(loadFinished(bool)), 200); |
|
2437 QCOMPARE(spy.count(), 1); |
|
2438 |
|
2439 QCOMPARE(frame->evaluateJavaScript("document.images.length").toInt(), 1); |
|
2440 QCOMPARE(frame->evaluateJavaScript("document.images[0].width").toInt(), 128); |
|
2441 QCOMPARE(frame->evaluateJavaScript("document.images[0].height").toInt(), 128); |
|
2442 |
|
2443 QString html2 = |
|
2444 "<html>" |
|
2445 "<head>" |
|
2446 "<link rel='stylesheet' href='qrc:/style.css' type='text/css' />" |
|
2447 "</head>" |
|
2448 "<body>" |
|
2449 "<p id='idP'>some text</p>" |
|
2450 "</body>" |
|
2451 "</html>"; |
|
2452 |
|
2453 // in few seconds, the CSS should be completey loaded |
|
2454 frame->setHtml(html2); |
|
2455 waitForSignal(frame, SIGNAL(loadFinished(bool)), 200); |
|
2456 QCOMPARE(spy.size(), 2); |
|
2457 |
|
2458 QWebElement p = frame->documentElement().findAll("p").at(0); |
|
2459 QCOMPARE(p.styleProperty("color", QWebElement::CascadedStyle), QLatin1String("red")); |
|
2460 } |
|
2461 |
|
2462 void tst_QWebFrame::setHtmlWithBaseURL() |
|
2463 { |
|
2464 if (!QDir(TESTS_SOURCE_DIR).exists()) |
|
2465 QSKIP(QString("This test requires access to resources found in '%1'").arg(TESTS_SOURCE_DIR).toLatin1().constData(), SkipAll); |
|
2466 |
|
2467 QDir::setCurrent(TESTS_SOURCE_DIR); |
|
2468 |
|
2469 QString html("<html><body><p>hello world</p><img src='resources/image2.png'/></body></html>"); |
|
2470 |
|
2471 QWebPage page; |
|
2472 QWebFrame* frame = page.mainFrame(); |
|
2473 |
|
2474 // in few seconds, the image should be completey loaded |
|
2475 QSignalSpy spy(&page, SIGNAL(loadFinished(bool))); |
|
2476 |
|
2477 frame->setHtml(html, QUrl::fromLocalFile(TESTS_SOURCE_DIR)); |
|
2478 waitForSignal(frame, SIGNAL(loadFinished(bool)), 200); |
|
2479 QCOMPARE(spy.count(), 1); |
|
2480 |
|
2481 QCOMPARE(frame->evaluateJavaScript("document.images.length").toInt(), 1); |
|
2482 QCOMPARE(frame->evaluateJavaScript("document.images[0].width").toInt(), 128); |
|
2483 QCOMPARE(frame->evaluateJavaScript("document.images[0].height").toInt(), 128); |
|
2484 |
|
2485 // no history item has to be added. |
|
2486 QCOMPARE(m_view->page()->history()->count(), 0); |
|
2487 } |
|
2488 |
|
2489 class MyPage : public QWebPage |
|
2490 { |
|
2491 public: |
|
2492 MyPage() : QWebPage(), alerts(0) {} |
|
2493 int alerts; |
|
2494 |
|
2495 protected: |
|
2496 virtual void javaScriptAlert(QWebFrame*, const QString& msg) |
|
2497 { |
|
2498 alerts++; |
|
2499 QCOMPARE(msg, QString("foo")); |
|
2500 // Should not be enough to trigger deferred loading, since we've upped the HTML |
|
2501 // tokenizer delay in the Qt frameloader. See HTMLTokenizer::continueProcessing() |
|
2502 QTest::qWait(1000); |
|
2503 } |
|
2504 }; |
|
2505 |
|
2506 void tst_QWebFrame::setHtmlWithJSAlert() |
|
2507 { |
|
2508 QString html("<html><head></head><body><script>alert('foo');</script><p>hello world</p></body></html>"); |
|
2509 MyPage page; |
|
2510 m_view->setPage(&page); |
|
2511 page.mainFrame()->setHtml(html); |
|
2512 QCOMPARE(page.alerts, 1); |
|
2513 QCOMPARE(m_view->page()->mainFrame()->toHtml(), html); |
|
2514 } |
|
2515 |
|
2516 class TestNetworkManager : public QNetworkAccessManager |
|
2517 { |
|
2518 public: |
|
2519 TestNetworkManager(QObject* parent) : QNetworkAccessManager(parent) {} |
|
2520 |
|
2521 QList<QUrl> requestedUrls; |
|
2522 |
|
2523 protected: |
|
2524 virtual QNetworkReply* createRequest(Operation op, const QNetworkRequest &request, QIODevice* outgoingData) { |
|
2525 requestedUrls.append(request.url()); |
|
2526 QNetworkRequest redirectedRequest = request; |
|
2527 redirectedRequest.setUrl(QUrl("data:text/html,<p>hello")); |
|
2528 return QNetworkAccessManager::createRequest(op, redirectedRequest, outgoingData); |
|
2529 } |
|
2530 }; |
|
2531 |
|
2532 void tst_QWebFrame::ipv6HostEncoding() |
|
2533 { |
|
2534 TestNetworkManager* networkManager = new TestNetworkManager(m_page); |
|
2535 m_page->setNetworkAccessManager(networkManager); |
|
2536 networkManager->requestedUrls.clear(); |
|
2537 |
|
2538 QUrl baseUrl = QUrl::fromEncoded("http://[::1]/index.html"); |
|
2539 m_view->setHtml("<p>Hi", baseUrl); |
|
2540 m_view->page()->mainFrame()->evaluateJavaScript("var r = new XMLHttpRequest();" |
|
2541 "r.open('GET', 'http://[::1]/test.xml', false);" |
|
2542 "r.send(null);" |
|
2543 ); |
|
2544 QCOMPARE(networkManager->requestedUrls.count(), 1); |
|
2545 QCOMPARE(networkManager->requestedUrls.at(0), QUrl::fromEncoded("http://[::1]/test.xml")); |
|
2546 } |
|
2547 |
|
2548 void tst_QWebFrame::metaData() |
|
2549 { |
|
2550 m_view->setHtml("<html>" |
|
2551 " <head>" |
|
2552 " <meta name=\"description\" content=\"Test description\">" |
|
2553 " <meta name=\"keywords\" content=\"HTML, JavaScript, Css\">" |
|
2554 " </head>" |
|
2555 "</html>"); |
|
2556 |
|
2557 QMultiMap<QString, QString> metaData = m_view->page()->mainFrame()->metaData(); |
|
2558 |
|
2559 QCOMPARE(metaData.count(), 2); |
|
2560 |
|
2561 QCOMPARE(metaData.value("description"), QString("Test description")); |
|
2562 QCOMPARE(metaData.value("keywords"), QString("HTML, JavaScript, Css")); |
|
2563 QCOMPARE(metaData.value("nonexistant"), QString()); |
|
2564 |
|
2565 m_view->setHtml("<html>" |
|
2566 " <head>" |
|
2567 " <meta name=\"samekey\" content=\"FirstValue\">" |
|
2568 " <meta name=\"samekey\" content=\"SecondValue\">" |
|
2569 " </head>" |
|
2570 "</html>"); |
|
2571 |
|
2572 metaData = m_view->page()->mainFrame()->metaData(); |
|
2573 |
|
2574 QCOMPARE(metaData.count(), 2); |
|
2575 |
|
2576 QStringList values = metaData.values("samekey"); |
|
2577 QCOMPARE(values.count(), 2); |
|
2578 |
|
2579 QVERIFY(values.contains("FirstValue")); |
|
2580 QVERIFY(values.contains("SecondValue")); |
|
2581 |
|
2582 QCOMPARE(metaData.value("nonexistant"), QString()); |
|
2583 } |
|
2584 |
|
2585 #if !defined(Q_WS_MAEMO_5) |
|
2586 void tst_QWebFrame::popupFocus() |
|
2587 { |
|
2588 QWebView view; |
|
2589 view.setHtml("<html>" |
|
2590 " <body>" |
|
2591 " <select name=\"select\">" |
|
2592 " <option>1</option>" |
|
2593 " <option>2</option>" |
|
2594 " </select>" |
|
2595 " <input type=\"text\"> </input>" |
|
2596 " <textarea name=\"text_area\" rows=\"3\" cols=\"40\">" |
|
2597 "This test checks whether showing and hiding a popup" |
|
2598 "takes the focus away from the webpage." |
|
2599 " </textarea>" |
|
2600 " </body>" |
|
2601 "</html>"); |
|
2602 view.resize(400, 100); |
|
2603 view.show(); |
|
2604 view.setFocus(); |
|
2605 QTRY_VERIFY(view.hasFocus()); |
|
2606 |
|
2607 // open the popup by clicking. check if focus is on the popup |
|
2608 QTest::mouseClick(&view, Qt::LeftButton, 0, QPoint(25, 25)); |
|
2609 QObject* webpopup = firstChildByClassName(&view, "QComboBox"); |
|
2610 QComboBox* combo = qobject_cast<QComboBox*>(webpopup); |
|
2611 QVERIFY(combo != 0); |
|
2612 QTRY_VERIFY(!view.hasFocus() && combo->view()->hasFocus()); // Focus should be on the popup |
|
2613 |
|
2614 // hide the popup and check if focus is on the page |
|
2615 combo->hidePopup(); |
|
2616 QTRY_VERIFY(view.hasFocus() && !combo->view()->hasFocus()); // Focus should be back on the WebView |
|
2617 } |
|
2618 #endif |
|
2619 |
|
2620 void tst_QWebFrame::inputFieldFocus() |
|
2621 { |
|
2622 QWebView view; |
|
2623 view.setHtml("<html><body><input type=\"text\"></input></body></html>"); |
|
2624 view.resize(400, 100); |
|
2625 view.show(); |
|
2626 view.setFocus(); |
|
2627 QTRY_VERIFY(view.hasFocus()); |
|
2628 |
|
2629 // double the flashing time, should at least blink once already |
|
2630 int delay = qApp->cursorFlashTime() * 2; |
|
2631 |
|
2632 // focus the lineedit and check if it blinks |
|
2633 QTest::mouseClick(&view, Qt::LeftButton, 0, QPoint(25, 25)); |
|
2634 m_inputFieldsTestView = &view; |
|
2635 view.installEventFilter( this ); |
|
2636 QTest::qWait(delay); |
|
2637 QVERIFY2(m_inputFieldTestPaintCount >= 3, |
|
2638 "The input field should have a blinking caret"); |
|
2639 } |
|
2640 |
|
2641 void tst_QWebFrame::hitTestContent() |
|
2642 { |
|
2643 QString html("<html><body><p>A paragraph</p><br/><br/><br/><a href=\"about:blank\" target=\"_foo\">link text</a></body></html>"); |
|
2644 |
|
2645 QWebPage page; |
|
2646 QWebFrame* frame = page.mainFrame(); |
|
2647 frame->setHtml(html); |
|
2648 page.setViewportSize(QSize(200, 0)); //no height so link is not visible |
|
2649 QWebHitTestResult result = frame->hitTestContent(QPoint(10, 100)); |
|
2650 QCOMPARE(result.linkText(), QString("link text")); |
|
2651 QWebElement link = result.linkElement(); |
|
2652 QCOMPARE(link.attribute("target"), QString("_foo")); |
|
2653 } |
|
2654 |
|
2655 void tst_QWebFrame::jsByteArray() |
|
2656 { |
|
2657 QByteArray ba("hello world"); |
|
2658 m_myObject->setByteArrayProperty(ba); |
|
2659 |
|
2660 // read-only property |
|
2661 QCOMPARE(m_myObject->byteArrayProperty(), ba); |
|
2662 QString type; |
|
2663 QVariant v = evalJSV("myObject.byteArrayProperty"); |
|
2664 QCOMPARE(int(v.type()), int(QVariant::ByteArray)); |
|
2665 |
|
2666 QCOMPARE(v.toByteArray(), ba); |
|
2667 } |
|
2668 |
|
2669 void tst_QWebFrame::ownership() |
|
2670 { |
|
2671 // test ownership |
|
2672 { |
|
2673 QPointer<QObject> ptr = new QObject(); |
|
2674 QVERIFY(ptr != 0); |
|
2675 { |
|
2676 QWebPage page; |
|
2677 QWebFrame* frame = page.mainFrame(); |
|
2678 frame->addToJavaScriptWindowObject("test", ptr, QScriptEngine::ScriptOwnership); |
|
2679 } |
|
2680 QVERIFY(ptr == 0); |
|
2681 } |
|
2682 { |
|
2683 QPointer<QObject> ptr = new QObject(); |
|
2684 QVERIFY(ptr != 0); |
|
2685 QObject* before = ptr; |
|
2686 { |
|
2687 QWebPage page; |
|
2688 QWebFrame* frame = page.mainFrame(); |
|
2689 frame->addToJavaScriptWindowObject("test", ptr, QScriptEngine::QtOwnership); |
|
2690 } |
|
2691 QVERIFY(ptr == before); |
|
2692 delete ptr; |
|
2693 } |
|
2694 { |
|
2695 QObject* parent = new QObject(); |
|
2696 QObject* child = new QObject(parent); |
|
2697 QWebPage page; |
|
2698 QWebFrame* frame = page.mainFrame(); |
|
2699 frame->addToJavaScriptWindowObject("test", child, QScriptEngine::QtOwnership); |
|
2700 QVariant v = frame->evaluateJavaScript("test"); |
|
2701 QCOMPARE(qvariant_cast<QObject*>(v), child); |
|
2702 delete parent; |
|
2703 v = frame->evaluateJavaScript("test"); |
|
2704 QCOMPARE(qvariant_cast<QObject*>(v), (QObject *)0); |
|
2705 } |
|
2706 { |
|
2707 QPointer<QObject> ptr = new QObject(); |
|
2708 QVERIFY(ptr != 0); |
|
2709 { |
|
2710 QWebPage page; |
|
2711 QWebFrame* frame = page.mainFrame(); |
|
2712 frame->addToJavaScriptWindowObject("test", ptr, QScriptEngine::AutoOwnership); |
|
2713 } |
|
2714 // no parent, so it should be like ScriptOwnership |
|
2715 QVERIFY(ptr == 0); |
|
2716 } |
|
2717 { |
|
2718 QObject* parent = new QObject(); |
|
2719 QPointer<QObject> child = new QObject(parent); |
|
2720 QVERIFY(child != 0); |
|
2721 { |
|
2722 QWebPage page; |
|
2723 QWebFrame* frame = page.mainFrame(); |
|
2724 frame->addToJavaScriptWindowObject("test", child, QScriptEngine::AutoOwnership); |
|
2725 } |
|
2726 // has parent, so it should be like QtOwnership |
|
2727 QVERIFY(child != 0); |
|
2728 delete parent; |
|
2729 } |
|
2730 } |
|
2731 |
|
2732 void tst_QWebFrame::nullValue() |
|
2733 { |
|
2734 QVariant v = m_view->page()->mainFrame()->evaluateJavaScript("null"); |
|
2735 QVERIFY(v.isNull()); |
|
2736 } |
|
2737 |
|
2738 void tst_QWebFrame::baseUrl_data() |
|
2739 { |
|
2740 QTest::addColumn<QString>("html"); |
|
2741 QTest::addColumn<QUrl>("loadUrl"); |
|
2742 QTest::addColumn<QUrl>("url"); |
|
2743 QTest::addColumn<QUrl>("baseUrl"); |
|
2744 |
|
2745 QTest::newRow("null") << QString() << QUrl() |
|
2746 << QUrl("about:blank") << QUrl("about:blank"); |
|
2747 |
|
2748 QTest::newRow("foo") << QString() << QUrl("http://foobar.baz/") |
|
2749 << QUrl("http://foobar.baz/") << QUrl("http://foobar.baz/"); |
|
2750 |
|
2751 QString html = "<html>" |
|
2752 "<head>" |
|
2753 "<base href=\"http://foobaz.bar/\" />" |
|
2754 "</head>" |
|
2755 "</html>"; |
|
2756 QTest::newRow("customBaseUrl") << html << QUrl("http://foobar.baz/") |
|
2757 << QUrl("http://foobar.baz/") << QUrl("http://foobaz.bar/"); |
|
2758 } |
|
2759 |
|
2760 void tst_QWebFrame::baseUrl() |
|
2761 { |
|
2762 QFETCH(QString, html); |
|
2763 QFETCH(QUrl, loadUrl); |
|
2764 QFETCH(QUrl, url); |
|
2765 QFETCH(QUrl, baseUrl); |
|
2766 |
|
2767 m_page->mainFrame()->setHtml(html, loadUrl); |
|
2768 QCOMPARE(m_page->mainFrame()->url(), url); |
|
2769 QCOMPARE(m_page->mainFrame()->baseUrl(), baseUrl); |
|
2770 } |
|
2771 |
|
2772 void tst_QWebFrame::hasSetFocus() |
|
2773 { |
|
2774 QString html("<html><body><p>top</p>" \ |
|
2775 "<iframe width='80%' height='30%'/>" \ |
|
2776 "</body></html>"); |
|
2777 |
|
2778 QSignalSpy loadSpy(m_page, SIGNAL(loadFinished(bool))); |
|
2779 m_page->mainFrame()->setHtml(html); |
|
2780 |
|
2781 waitForSignal(m_page->mainFrame(), SIGNAL(loadFinished(bool)), 200); |
|
2782 QCOMPARE(loadSpy.size(), 1); |
|
2783 |
|
2784 QList<QWebFrame*> children = m_page->mainFrame()->childFrames(); |
|
2785 QWebFrame* frame = children.at(0); |
|
2786 QString innerHtml("<html><body><p>another iframe</p>" \ |
|
2787 "<iframe width='80%' height='30%'/>" \ |
|
2788 "</body></html>"); |
|
2789 frame->setHtml(innerHtml); |
|
2790 |
|
2791 waitForSignal(frame, SIGNAL(loadFinished(bool)), 200); |
|
2792 QCOMPARE(loadSpy.size(), 2); |
|
2793 |
|
2794 m_page->mainFrame()->setFocus(); |
|
2795 QTRY_VERIFY(m_page->mainFrame()->hasFocus()); |
|
2796 |
|
2797 for (int i = 0; i < children.size(); ++i) { |
|
2798 children.at(i)->setFocus(); |
|
2799 QTRY_VERIFY(children.at(i)->hasFocus()); |
|
2800 QVERIFY(!m_page->mainFrame()->hasFocus()); |
|
2801 } |
|
2802 |
|
2803 m_page->mainFrame()->setFocus(); |
|
2804 QTRY_VERIFY(m_page->mainFrame()->hasFocus()); |
|
2805 } |
|
2806 |
|
2807 void tst_QWebFrame::render() |
|
2808 { |
|
2809 QString html("<html>" \ |
|
2810 "<head><style>" \ |
|
2811 "body, iframe { margin: 0px; border: none; }" \ |
|
2812 "</style></head>" \ |
|
2813 "<body><iframe width='100px' height='100px'/></body>" \ |
|
2814 "</html>"); |
|
2815 |
|
2816 QWebPage page; |
|
2817 page.mainFrame()->setHtml(html); |
|
2818 |
|
2819 QList<QWebFrame*> frames = page.mainFrame()->childFrames(); |
|
2820 QWebFrame *frame = frames.at(0); |
|
2821 QString innerHtml("<body style='margin: 0px;'><img src='qrc:/image.png'/></body>"); |
|
2822 frame->setHtml(innerHtml); |
|
2823 |
|
2824 QPicture picture; |
|
2825 |
|
2826 QSize size = page.mainFrame()->contentsSize(); |
|
2827 page.setViewportSize(size); |
|
2828 |
|
2829 // render contents layer only (the iframe is smaller than the image, so it will have scrollbars) |
|
2830 QPainter painter1(&picture); |
|
2831 frame->render(&painter1, QWebFrame::ContentsLayer); |
|
2832 painter1.end(); |
|
2833 |
|
2834 QCOMPARE(size.width(), picture.boundingRect().width() + frame->scrollBarGeometry(Qt::Vertical).width()); |
|
2835 QCOMPARE(size.height(), picture.boundingRect().height() + frame->scrollBarGeometry(Qt::Horizontal).height()); |
|
2836 |
|
2837 // render everything, should be the size of the iframe |
|
2838 QPainter painter2(&picture); |
|
2839 frame->render(&painter2, QWebFrame::AllLayers); |
|
2840 painter2.end(); |
|
2841 |
|
2842 QCOMPARE(size.width(), picture.boundingRect().width()); // width: 100px |
|
2843 QCOMPARE(size.height(), picture.boundingRect().height()); // height: 100px |
|
2844 } |
|
2845 |
|
2846 void tst_QWebFrame::scrollPosition() |
|
2847 { |
|
2848 // enlarged image in a small viewport, to provoke the scrollbars to appear |
|
2849 QString html("<html><body><img src='qrc:/image.png' height=500 width=500/></body></html>"); |
|
2850 |
|
2851 QWebPage page; |
|
2852 page.setViewportSize(QSize(200, 200)); |
|
2853 |
|
2854 QWebFrame* frame = page.mainFrame(); |
|
2855 frame->setHtml(html); |
|
2856 frame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); |
|
2857 frame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); |
|
2858 |
|
2859 // try to set the scroll offset programmatically |
|
2860 frame->setScrollPosition(QPoint(23, 29)); |
|
2861 QCOMPARE(frame->scrollPosition().x(), 23); |
|
2862 QCOMPARE(frame->scrollPosition().y(), 29); |
|
2863 |
|
2864 int x = frame->evaluateJavaScript("window.scrollX").toInt(); |
|
2865 int y = frame->evaluateJavaScript("window.scrollY").toInt(); |
|
2866 QCOMPARE(x, 23); |
|
2867 QCOMPARE(y, 29); |
|
2868 } |
|
2869 |
|
2870 void tst_QWebFrame::scrollToAnchor() |
|
2871 { |
|
2872 QWebPage page; |
|
2873 page.setViewportSize(QSize(480, 800)); |
|
2874 QWebFrame* frame = page.mainFrame(); |
|
2875 |
|
2876 QString html("<html><body><p style=\"margin-bottom: 1500px;\">Hello.</p>" |
|
2877 "<p><a id=\"foo\">This</a> is an anchor</p>" |
|
2878 "<p style=\"margin-bottom: 1500px;\"><a id=\"bar\">This</a> is another anchor</p>" |
|
2879 "</body></html>"); |
|
2880 frame->setHtml(html); |
|
2881 frame->setScrollPosition(QPoint(0, 0)); |
|
2882 QCOMPARE(frame->scrollPosition().x(), 0); |
|
2883 QCOMPARE(frame->scrollPosition().y(), 0); |
|
2884 |
|
2885 QWebElement fooAnchor = frame->findFirstElement("a[id=foo]"); |
|
2886 |
|
2887 frame->scrollToAnchor("foo"); |
|
2888 QCOMPARE(frame->scrollPosition().y(), fooAnchor.geometry().top()); |
|
2889 |
|
2890 frame->scrollToAnchor("bar"); |
|
2891 frame->scrollToAnchor("foo"); |
|
2892 QCOMPARE(frame->scrollPosition().y(), fooAnchor.geometry().top()); |
|
2893 |
|
2894 frame->scrollToAnchor("top"); |
|
2895 QCOMPARE(frame->scrollPosition().y(), 0); |
|
2896 |
|
2897 frame->scrollToAnchor("bar"); |
|
2898 frame->scrollToAnchor("notexist"); |
|
2899 QVERIFY(frame->scrollPosition().y() != 0); |
|
2900 } |
|
2901 |
|
2902 |
|
2903 void tst_QWebFrame::scrollbarsOff() |
|
2904 { |
|
2905 QWebView view; |
|
2906 QWebFrame* mainFrame = view.page()->mainFrame(); |
|
2907 |
|
2908 mainFrame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); |
|
2909 mainFrame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); |
|
2910 |
|
2911 QString html("<script>" \ |
|
2912 " function checkScrollbar() {" \ |
|
2913 " if (innerWidth === document.documentElement.offsetWidth)" \ |
|
2914 " document.getElementById('span1').innerText = 'SUCCESS';" \ |
|
2915 " else" \ |
|
2916 " document.getElementById('span1').innerText = 'FAIL';" \ |
|
2917 " }" \ |
|
2918 "</script>" \ |
|
2919 "<body>" \ |
|
2920 " <div style='margin-top:1000px ; margin-left:1000px'>" \ |
|
2921 " <a id='offscreen' href='a'>End</a>" \ |
|
2922 " </div>" \ |
|
2923 "<span id='span1'></span>" \ |
|
2924 "</body>"); |
|
2925 |
|
2926 |
|
2927 view.setHtml(html); |
|
2928 ::waitForSignal(&view, SIGNAL(loadFinished(bool))); |
|
2929 |
|
2930 mainFrame->evaluateJavaScript("checkScrollbar();"); |
|
2931 QCOMPARE(mainFrame->documentElement().findAll("span").at(0).toPlainText(), QString("SUCCESS")); |
|
2932 } |
|
2933 |
|
2934 void tst_QWebFrame::evaluateWillCauseRepaint() |
|
2935 { |
|
2936 QWebView view; |
|
2937 QString html("<html><body>top<div id=\"junk\" style=\"display: block;\">" |
|
2938 "junk</div>bottom</body></html>"); |
|
2939 view.setHtml(html); |
|
2940 view.show(); |
|
2941 |
|
2942 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) |
|
2943 QTest::qWaitForWindowShown(&view); |
|
2944 #else |
|
2945 QTest::qWait(2000); |
|
2946 #endif |
|
2947 |
|
2948 view.page()->mainFrame()->evaluateJavaScript( |
|
2949 "document.getElementById('junk').style.display = 'none';"); |
|
2950 |
|
2951 ::waitForSignal(view.page(), SIGNAL(repaintRequested(QRect))); |
|
2952 } |
|
2953 |
|
2954 class TestFactory : public QObject |
|
2955 { |
|
2956 Q_OBJECT |
|
2957 public: |
|
2958 TestFactory() |
|
2959 : obj(0), counter(0) |
|
2960 {} |
|
2961 |
|
2962 Q_INVOKABLE QObject* getNewObject() |
|
2963 { |
|
2964 delete obj; |
|
2965 obj = new QObject(this); |
|
2966 obj->setObjectName(QLatin1String("test") + QString::number(++counter)); |
|
2967 return obj; |
|
2968 |
|
2969 } |
|
2970 |
|
2971 QObject* obj; |
|
2972 int counter; |
|
2973 }; |
|
2974 |
|
2975 void tst_QWebFrame::qObjectWrapperWithSameIdentity() |
|
2976 { |
|
2977 m_view->setHtml("<script>function triggerBug() { document.getElementById('span1').innerText = test.getNewObject().objectName; }</script>" |
|
2978 "<body><span id='span1'>test</span></body>"); |
|
2979 |
|
2980 QWebFrame* mainFrame = m_view->page()->mainFrame(); |
|
2981 QCOMPARE(mainFrame->toPlainText(), QString("test")); |
|
2982 |
|
2983 mainFrame->addToJavaScriptWindowObject("test", new TestFactory, QScriptEngine::ScriptOwnership); |
|
2984 |
|
2985 mainFrame->evaluateJavaScript("triggerBug();"); |
|
2986 QCOMPARE(mainFrame->toPlainText(), QString("test1")); |
|
2987 |
|
2988 mainFrame->evaluateJavaScript("triggerBug();"); |
|
2989 QCOMPARE(mainFrame->toPlainText(), QString("test2")); |
|
2990 } |
|
2991 |
|
2992 void tst_QWebFrame::introspectQtMethods_data() |
|
2993 { |
|
2994 QTest::addColumn<QString>("objectExpression"); |
|
2995 QTest::addColumn<QString>("methodName"); |
|
2996 QTest::addColumn<QStringList>("expectedPropertyNames"); |
|
2997 |
|
2998 QTest::newRow("myObject.mySignal") |
|
2999 << "myObject" << "mySignal" << (QStringList() << "connect" << "disconnect" << "length" << "name"); |
|
3000 QTest::newRow("myObject.mySlot") |
|
3001 << "myObject" << "mySlot" << (QStringList() << "connect" << "disconnect" << "length" << "name"); |
|
3002 QTest::newRow("myObject.myInvokable") |
|
3003 << "myObject" << "myInvokable" << (QStringList() << "connect" << "disconnect" << "length" << "name"); |
|
3004 QTest::newRow("myObject.mySignal.connect") |
|
3005 << "myObject.mySignal" << "connect" << (QStringList() << "length" << "name"); |
|
3006 QTest::newRow("myObject.mySignal.disconnect") |
|
3007 << "myObject.mySignal" << "disconnect" << (QStringList() << "length" << "name"); |
|
3008 } |
|
3009 |
|
3010 void tst_QWebFrame::introspectQtMethods() |
|
3011 { |
|
3012 QFETCH(QString, objectExpression); |
|
3013 QFETCH(QString, methodName); |
|
3014 QFETCH(QStringList, expectedPropertyNames); |
|
3015 |
|
3016 QString methodLookup = QString::fromLatin1("%0['%1']").arg(objectExpression).arg(methodName); |
|
3017 QCOMPARE(evalJSV(QString::fromLatin1("Object.getOwnPropertyNames(%0).sort()").arg(methodLookup)).toStringList(), expectedPropertyNames); |
|
3018 |
|
3019 for (int i = 0; i < expectedPropertyNames.size(); ++i) { |
|
3020 QString name = expectedPropertyNames.at(i); |
|
3021 QCOMPARE(evalJS(QString::fromLatin1("%0.hasOwnProperty('%1')").arg(methodLookup).arg(name)), sTrue); |
|
3022 evalJS(QString::fromLatin1("var descriptor = Object.getOwnPropertyDescriptor(%0, '%1')").arg(methodLookup).arg(name)); |
|
3023 QCOMPARE(evalJS("typeof descriptor"), QString::fromLatin1("object")); |
|
3024 QCOMPARE(evalJS("descriptor.get"), sUndefined); |
|
3025 QCOMPARE(evalJS("descriptor.set"), sUndefined); |
|
3026 QCOMPARE(evalJS(QString::fromLatin1("descriptor.value === %0['%1']").arg(methodLookup).arg(name)), sTrue); |
|
3027 QCOMPARE(evalJS(QString::fromLatin1("descriptor.enumerable")), sFalse); |
|
3028 QCOMPARE(evalJS(QString::fromLatin1("descriptor.configurable")), sFalse); |
|
3029 } |
|
3030 |
|
3031 QVERIFY(evalJSV("var props=[]; for (var p in myObject.deleteLater) {props.push(p);}; props.sort()").toStringList().isEmpty()); |
|
3032 } |
|
3033 |
|
3034 QTEST_MAIN(tst_QWebFrame) |
|
3035 #include "tst_qwebframe.moc" |
|