diff options
Diffstat (limited to 'tests/auto/declarative/qdeclarativeecmascript')
127 files changed, 4808 insertions, 0 deletions
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/ConstantsOverrideBindings.qml b/tests/auto/declarative/qdeclarativeecmascript/data/ConstantsOverrideBindings.qml new file mode 100644 index 0000000..b4a702b --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/ConstantsOverrideBindings.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyQmlObject { + property int c1: 0 + property int c2: c1 +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/CustomObject.qml b/tests/auto/declarative/qdeclarativeecmascript/data/CustomObject.qml new file mode 100644 index 0000000..170d027 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/CustomObject.qml @@ -0,0 +1,5 @@ +import Qt 4.7 + +QtObject { + property string greeting: "hello world" +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/MethodsObject.qml b/tests/auto/declarative/qdeclarativeecmascript/data/MethodsObject.qml new file mode 100644 index 0000000..e9a41ed --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/MethodsObject.qml @@ -0,0 +1,6 @@ +import Qt 4.7 + +QtObject { + function testFunction() { return 19; } + function testFunction2() { return 18; } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/NestedTypeTransientErrors.qml b/tests/auto/declarative/qdeclarativeecmascript/data/NestedTypeTransientErrors.qml new file mode 100644 index 0000000..6e50b10 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/NestedTypeTransientErrors.qml @@ -0,0 +1,11 @@ +import Qt 4.7 + +QtObject { + property int b: obj.prop.a + + property variant prop; + prop: QtObject { + property int a: 10 + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/ScopeObject.qml b/tests/auto/declarative/qdeclarativeecmascript/data/ScopeObject.qml new file mode 100644 index 0000000..fe0492f --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/ScopeObject.qml @@ -0,0 +1,12 @@ +import Qt 4.7 + +Item { + property int a: 3 + property int binding: myFunction(); + property int binding2: myCompFunction(); + + function myCompFunction() { + return a; + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/SpuriousWarning.qml b/tests/auto/declarative/qdeclarativeecmascript/data/SpuriousWarning.qml new file mode 100644 index 0000000..e144de7 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/SpuriousWarning.qml @@ -0,0 +1,5 @@ +import Qt 4.7 + +Item { + property int children: root.children.length +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/TypeForDynamicCreation.qml b/tests/auto/declarative/qdeclarativeecmascript/data/TypeForDynamicCreation.qml new file mode 100644 index 0000000..56e0625 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/TypeForDynamicCreation.qml @@ -0,0 +1,2 @@ +import Qt.test 1.0 +MyQmlObject{objectName:"objectThree"} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/aliasPropertyAndBinding.qml b/tests/auto/declarative/qdeclarativeecmascript/data/aliasPropertyAndBinding.qml new file mode 100644 index 0000000..515f80f --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/aliasPropertyAndBinding.qml @@ -0,0 +1,14 @@ +import Qt 4.7 +import Qt.test 1.0 + +MyQmlObject { + property alias c1: myObject.c1 + property int c2: 3 + property int c3: c2 + objectProperty: QtObject { + id: myObject + property int c1 + } +} + + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/assignBasicTypes.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/assignBasicTypes.2.qml new file mode 100644 index 0000000..db7f2b5 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/assignBasicTypes.2.qml @@ -0,0 +1,26 @@ +import Qt.test 1.0 + +MyTypeObject { + flagProperty: if(1) "FlagVal1 | FlagVal3" + enumProperty: if(1) "EnumVal2" + stringProperty: if(1) "Hello World!" + uintProperty: if(1) 10 + intProperty: if(1) -19 + realProperty: if(1) 23.2 + doubleProperty: if(1) -19.7 + floatProperty: if(1) 8.5 + colorProperty: if(1) "red" + dateProperty: if(1) "1982-11-25" + timeProperty: if(1) "11:11:32" + dateTimeProperty: if(1) "2009-05-12T13:22:01" + pointProperty: if(1) "99,13" + pointFProperty: if(1) "-10.1,12.3" + sizeProperty: if(1) "99x13" + sizeFProperty: if(1) "0.1x0.2" + rectProperty: if(1) "9,7,100x200" + rectFProperty: if(1) "1000.1,-10.9,400x90.99" + boolProperty: if(1) true + variantProperty: if(1) "Hello World!" + vectorProperty: if(1) "10,1,2.2" + urlProperty: if(1) "main.qml" +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/assignBasicTypes.qml b/tests/auto/declarative/qdeclarativeecmascript/data/assignBasicTypes.qml new file mode 100644 index 0000000..72ae865 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/assignBasicTypes.qml @@ -0,0 +1,29 @@ +import Qt.test 1.0 +import Qt 4.7 + +MyTypeObject { + Component.onCompleted: { + flagProperty = "FlagVal1 | FlagVal3" + enumProperty = "EnumVal2" + stringProperty = "Hello World!" + uintProperty = 10 + intProperty = -19 + realProperty = 23.2 + doubleProperty = -19.7 + floatProperty = 8.5 + colorProperty = "red" + dateProperty = "1982-11-25" + timeProperty = "11:11:32" + dateTimeProperty = "2009-05-12T13:22:01" + pointProperty = "99,13" + pointFProperty = "-10.1,12.3" + sizeProperty = "99x13" + sizeFProperty = "0.1x0.2" + rectProperty = "9,7,100x200" + rectFProperty = "1000.1,-10.9,400x90.99" + boolProperty = true + variantProperty = "Hello World!" + vectorProperty = "10,1,2.2" + urlProperty = "main.qml" + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/attachedProperty.qml b/tests/auto/declarative/qdeclarativeecmascript/data/attachedProperty.qml new file mode 100644 index 0000000..061eda0 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/attachedProperty.qml @@ -0,0 +1,11 @@ +import Qt.test 1.0 +import Qt.test 1.0 as Namespace + +MyQmlObject { + id: me + property int a: MyQmlObject.value + property int b: Namespace.MyQmlObject.value + property int c: me.Namespace.MyQmlObject.value + property int d: me.Namespace.MyQmlObject.value +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/attachedPropertyScope.qml b/tests/auto/declarative/qdeclarativeecmascript/data/attachedPropertyScope.qml new file mode 100644 index 0000000..f31f142 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/attachedPropertyScope.qml @@ -0,0 +1,9 @@ +import Qt 4.7 +import Qt.test 1.0 + +QtObject { + property int value: 9 + property int value2 + + MyQmlObject.onMySignal: value2 = value +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/bindingLoop.qml b/tests/auto/declarative/qdeclarativeecmascript/data/bindingLoop.qml new file mode 100644 index 0000000..80545cf --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/bindingLoop.qml @@ -0,0 +1,14 @@ +import Qt.test 1.0 + +MyQmlContainer { + children : [ + MyQmlObject { + id: object1 + stringProperty: "hello" + object2.stringProperty + }, + MyQmlObject { + id: object2 + stringProperty: "hello" + object1.stringProperty + } + ] +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/blank.js b/tests/auto/declarative/qdeclarativeecmascript/data/blank.js new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/blank.js diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/boolPropertiesEvaluateAsBool.1.qml b/tests/auto/declarative/qdeclarativeecmascript/data/boolPropertiesEvaluateAsBool.1.qml new file mode 100644 index 0000000..3147f63 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/boolPropertiesEvaluateAsBool.1.qml @@ -0,0 +1,5 @@ +import Qt.test 1.0 + +MyQmlObject { + stringProperty: trueProperty?'pass':'fail' +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/boolPropertiesEvaluateAsBool.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/boolPropertiesEvaluateAsBool.2.qml new file mode 100644 index 0000000..c89bb49 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/boolPropertiesEvaluateAsBool.2.qml @@ -0,0 +1,5 @@ +import Qt.test 1.0 + +MyQmlObject { + stringProperty: falseProperty?'fail':'pass' +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/bug.1.qml b/tests/auto/declarative/qdeclarativeecmascript/data/bug.1.qml new file mode 100644 index 0000000..88740dc --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/bug.1.qml @@ -0,0 +1,10 @@ +import Qt 4.7 + +QtObject { + property int a: 10 + property bool b: false + + property int test + + test: ((a == 10)?(a + 1):0) + ((b == true)?9:3) +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/canAssignNullToQObject.1.qml b/tests/auto/declarative/qdeclarativeecmascript/data/canAssignNullToQObject.1.qml new file mode 100644 index 0000000..3fd9131 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/canAssignNullToQObject.1.qml @@ -0,0 +1,9 @@ +import Qt.test 1.0 + +MyQmlObject { + property bool runTest: false + + property variant a: MyQmlObject {} + + objectProperty: (runTest == false)?a:null +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/canAssignNullToQObject.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/canAssignNullToQObject.2.qml new file mode 100644 index 0000000..7530396 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/canAssignNullToQObject.2.qml @@ -0,0 +1,11 @@ +import Qt.test 1.0 +import Qt 4.7 + +MyQmlObject { + objectProperty: MyQmlObject {} + + Component.onCompleted: { + objectProperty = null; + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/compiled.qml b/tests/auto/declarative/qdeclarativeecmascript/data/compiled.qml new file mode 100644 index 0000000..1655905 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/compiled.qml @@ -0,0 +1,48 @@ +import Qt 4.7 + +QtObject { + //real + property real test1: a + b + property real test2: a - b + property bool test3: (a < b) + property bool test4: (a > b) + property bool test5: (a == b) + property bool test6: (a != b) + + //int + property int test7: c + d + property int test8: d - c + property bool test9: (c < d) + property bool test10: (c > d) + property bool test11: (c == d) + property bool test12: (c != d) + + //string + property string test13: e + f + property string test14: e + " " + f + property bool test15: (e == f) + property bool test16: (e != f) + + //type conversion + property int test17: a + property real test18: d + property int test19: g + property real test20: g + property string test21: g + property string test22: h + property bool test23: i + property color test24: j + property color test25: k + + property real a: 4.5 + property real b: 11.2 + property int c: 9 + property int d: 176 + property string e: "Hello" + property string f: "World" + property variant g: 6.7 + property variant h: "!" + property variant i: true + property string j: "#112233" + property string k: "#aa112233" +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/compositePropertyType.qml b/tests/auto/declarative/qdeclarativeecmascript/data/compositePropertyType.qml new file mode 100644 index 0000000..1dc0ada --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/compositePropertyType.qml @@ -0,0 +1,8 @@ +import Qt 4.7 + +QtObject { + property CustomObject myObject + myObject: CustomObject { } + + Component.onCompleted: console.log(myObject.greeting) +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/constantsOverrideBindings.1.qml b/tests/auto/declarative/qdeclarativeecmascript/data/constantsOverrideBindings.1.qml new file mode 100644 index 0000000..13c5ae5 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/constantsOverrideBindings.1.qml @@ -0,0 +1,8 @@ +import Qt.test 1.0 + +MyQmlObject { + property int c1: 0 + property int c2: c1 + + onBasicSignal: c2 = 13 +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/constantsOverrideBindings.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/constantsOverrideBindings.2.qml new file mode 100644 index 0000000..207a06b --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/constantsOverrideBindings.2.qml @@ -0,0 +1,11 @@ +import Qt.test 1.0 + +MyQmlObject { + property alias c1: myConstants.c1 + property alias c2: myConstants.c2 + + objectProperty: ConstantsOverrideBindings { + id: myConstants + c2: 10 + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/constantsOverrideBindings.3.qml b/tests/auto/declarative/qdeclarativeecmascript/data/constantsOverrideBindings.3.qml new file mode 100644 index 0000000..ca9d1d8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/constantsOverrideBindings.3.qml @@ -0,0 +1,7 @@ +import Qt.test 1.0 + +MyQmlObject { + property int c1: 0 + property int c2: c1 +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/declarativeToString.qml b/tests/auto/declarative/qdeclarativeecmascript/data/declarativeToString.qml new file mode 100644 index 0000000..ac296ce --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/declarativeToString.qml @@ -0,0 +1,11 @@ +import Qt.test 1.0 + +MyQmlObject{ + id: obj + objectName: "objName" + function testToString() + { + obj.stringProperty = obj.toString(); + } + +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/deferredProperties.qml b/tests/auto/declarative/qdeclarativeecmascript/data/deferredProperties.qml new file mode 100644 index 0000000..e01f708 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/deferredProperties.qml @@ -0,0 +1,10 @@ +import Qt.test 1.0 + +MyDeferredObject { + id: root + value: 10 + objectProperty: MyQmlObject { + value: root.value + } + objectProperty2: MyQmlObject { id: blah } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/deferredPropertiesErrors.qml b/tests/auto/declarative/qdeclarativeecmascript/data/deferredPropertiesErrors.qml new file mode 100644 index 0000000..9c46c3f --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/deferredPropertiesErrors.qml @@ -0,0 +1,10 @@ +import Qt.test 1.0 +import Qt 4.7 + +MyDeferredObject { + value: undefined // error is resolved before complete + objectProperty: undefined // immediate error + objectProperty2: QtObject { + Component.onCompleted: value = 10 + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/deletedEngine.qml b/tests/auto/declarative/qdeclarativeecmascript/data/deletedEngine.qml new file mode 100644 index 0000000..6fc1211 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/deletedEngine.qml @@ -0,0 +1,11 @@ +import Qt 4.7 + +QtObject { + function calculate() { + return b * 13; + } + + property int a: calculate() + property int b: 3 +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/deletedObject.qml b/tests/auto/declarative/qdeclarativeecmascript/data/deletedObject.qml new file mode 100644 index 0000000..2337e44 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/deletedObject.qml @@ -0,0 +1,25 @@ +import Qt 4.7 +import Qt.test 1.0 + +QtObject { + property variant obj + obj: MyQmlObject { + id: myObject + value: 92 + } + + property bool test1: false + property bool test2: false + property bool test3: false + property bool test4: false + + Component.onCompleted: { + test1 = myObject.value == 92; + test2 = obj.value == 92; + + myObject.deleteOnSet = 1; + + test3 = myObject == null + test4 = obj == null + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/dynamicCreation.helper.qml b/tests/auto/declarative/qdeclarativeecmascript/data/dynamicCreation.helper.qml new file mode 100644 index 0000000..d790d63 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/dynamicCreation.helper.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyQmlObject{ + objectName: "objectTwo" +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/dynamicCreation.qml b/tests/auto/declarative/qdeclarativeecmascript/data/dynamicCreation.qml new file mode 100644 index 0000000..7b132e1 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/dynamicCreation.qml @@ -0,0 +1,27 @@ +import Qt.test 1.0 + +MyQmlObject{ + id: obj + objectName: "obj" + function createOne() + { + obj.objectProperty = Qt.createQmlObject('import Qt.test 1.0; MyQmlObject{objectName:"objectOne"}', obj); + } + + function createTwo() + { + var component = Qt.createComponent('dynamicCreation.helper.qml'); + obj.objectProperty = component.createObject(obj); + } + + function createThree() + { + obj.objectProperty = Qt.createQmlObject('TypeForDynamicCreation{}', obj); + } + + function dontCrash() + { + var component = Qt.createComponent('file-doesnt-exist.qml'); + obj.objectProperty = component.createObject(obj); + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/dynamicDeletion.qml b/tests/auto/declarative/qdeclarativeecmascript/data/dynamicDeletion.qml new file mode 100644 index 0000000..f41e526 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/dynamicDeletion.qml @@ -0,0 +1,20 @@ +import Qt.test 1.0 + +MyQmlObject{ + id: obj + objectName: "obj" + function create() + { + obj.objectProperty = Qt.createQmlObject('import Qt.test 1.0; MyQmlObject{objectName:"emptyObject"}', obj); + } + + function killOther() + { + obj.objectProperty.destroy(500); + } + + function killMe() + { + obj.destroy();//Must not segfault + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/enums.1.qml b/tests/auto/declarative/qdeclarativeecmascript/data/enums.1.qml new file mode 100644 index 0000000..6351823 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/enums.1.qml @@ -0,0 +1,20 @@ +import Qt.test 1.0 +import Qt.test 1.0 as Namespace + +MyQmlObject { + // Enums from non-namespaced type + property int a: MyQmlObject.EnumValue1 + property int b: MyQmlObject.EnumValue2 + property int c: MyQmlObject.EnumValue3 + property int d: MyQmlObject.EnumValue4 + + // Enums from namespaced type + property int e: Namespace.MyQmlObject.EnumValue1 + property int f: Namespace.MyQmlObject.EnumValue2 + property int g: Namespace.MyQmlObject.EnumValue3 + property int h: Namespace.MyQmlObject.EnumValue4 + + // Test that enums don't mask attached properties + property int i: MyQmlObject.value + property int j: Namespace.MyQmlObject.value +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/enums.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/enums.2.qml new file mode 100644 index 0000000..bdc672f --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/enums.2.qml @@ -0,0 +1,8 @@ +import Qt.test 1.0 +import Qt.test 1.0 as Namespace + +MyQmlObject { + property int a: MyQmlObject.EnumValue10 + property int b: Namespace.MyQmlObject.EnumValue10 +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/eval.qml b/tests/auto/declarative/qdeclarativeecmascript/data/eval.qml new file mode 100644 index 0000000..bc2df98 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/eval.qml @@ -0,0 +1,23 @@ +import Qt 4.7 + +QtObject { + property bool test1: false; + property bool test2: false; + property bool test3: false; + property bool test4: false; + property bool test5: false; + + + property int a: 7 + property int b: 8 + + Component.onCompleted: { + var b = 9; + + test1 = (eval("a") == 7); + test2 = (eval("b") == 9); + test3 = (eval("c") == undefined); + test4 = (eval("console") == console); + test5 = (eval("Qt") == Qt); + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/exception.js b/tests/auto/declarative/qdeclarativeecmascript/data/exception.js new file mode 100644 index 0000000..160bbfa --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/exception.js @@ -0,0 +1 @@ +throw("Whoops!"); diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/exceptionClearsOnReeval.qml b/tests/auto/declarative/qdeclarativeecmascript/data/exceptionClearsOnReeval.qml new file mode 100644 index 0000000..a2f0d1a --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/exceptionClearsOnReeval.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyQmlObject { + property bool test: objectProperty.objectProperty.trueProperty +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/exceptionProducesWarning.qml b/tests/auto/declarative/qdeclarativeecmascript/data/exceptionProducesWarning.qml new file mode 100644 index 0000000..14046f0 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/exceptionProducesWarning.qml @@ -0,0 +1,8 @@ +import Qt 4.7 +import Qt.test 1.0 + +MyQmlObject { + Component.onCompleted: + { throw(new Error("JS exception")) } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/exceptionProducesWarning2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/exceptionProducesWarning2.qml new file mode 100644 index 0000000..146f6f1 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/exceptionProducesWarning2.qml @@ -0,0 +1,7 @@ +import Qt 4.7 +import Qt.test 1.0 + +MyQmlObject { + value: { throw(new Error("JS exception")) } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/extendedObjectPropertyLookup.qml b/tests/auto/declarative/qdeclarativeecmascript/data/extendedObjectPropertyLookup.qml new file mode 100644 index 0000000..dc78cd8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/extendedObjectPropertyLookup.qml @@ -0,0 +1,8 @@ +import Qt.test 1.0 +import Qt 4.7 + +QtObject { + property MyExtendedObject a; + a: MyExtendedObject { id: root } + property int b: Math.max(root.extendedProperty, 0) +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/extensionObjects.qml b/tests/auto/declarative/qdeclarativeecmascript/data/extensionObjects.qml new file mode 100644 index 0000000..c57e5f8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/extensionObjects.qml @@ -0,0 +1,19 @@ +import Qt.test 1.0 +import Qt 4.7 + +MyExtendedObject +{ + baseProperty: baseExtendedProperty + baseExtendedProperty: 13 + + coreProperty: extendedProperty + extendedProperty: 9 + + property QtObject nested: MyExtendedObject { + baseProperty: baseExtendedProperty + baseExtendedProperty: 13 + + coreProperty: extendedProperty + extendedProperty: 9 + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/extensionObjectsPropertyOverride.qml b/tests/auto/declarative/qdeclarativeecmascript/data/extensionObjectsPropertyOverride.qml new file mode 100644 index 0000000..3c443cb --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/extensionObjectsPropertyOverride.qml @@ -0,0 +1,7 @@ +import Qt.test 1.0 + +OverrideDefaultPropertyObject +{ + MyBaseExtendedObject { + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/function.qml b/tests/auto/declarative/qdeclarativeecmascript/data/function.qml new file mode 100644 index 0000000..b435f58 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/function.qml @@ -0,0 +1,19 @@ +import Qt 4.7 + +QtObject { + property bool test1: false; + property bool test2: false; + property bool test3: false; + + Component.onCompleted: { + var a = 10; + + var func1 = new Function("a", "return a + 7"); + var func2 = new Function("a", "return Qt.atob(a)"); + var func3 = new Function("return a"); + + test1 = (func1(4) == 11); + test2 = (func2("Hello World!") == Qt.atob("Hello World!")); + test3 = (func3() == undefined); + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.1.qml b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.1.qml new file mode 100644 index 0000000..09540f1 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.1.qml @@ -0,0 +1,5 @@ +import Qt.test 1.0 + +MyQmlObject { + property variant a: function myFunction() { return 2; } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml new file mode 100644 index 0000000..948b39c --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml @@ -0,0 +1,13 @@ +import Qt.test 1.0 + +MyQmlObject { + property variant a + property bool runTest: false + onRunTestChanged: { + function myFunction() { + console.log("hello world"); + } + a = myFunction; + } + +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/functionErrors.qml b/tests/auto/declarative/qdeclarativeecmascript/data/functionErrors.qml new file mode 100644 index 0000000..a893fb0 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/functionErrors.qml @@ -0,0 +1,10 @@ +import Qt 4.7 + +QtObject { + function myFunction() { + a = 10; + } + + Component.onCompleted: myFunction(); +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/idShortcutInvalidates.1.qml b/tests/auto/declarative/qdeclarativeecmascript/data/idShortcutInvalidates.1.qml new file mode 100644 index 0000000..e3b29ae --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/idShortcutInvalidates.1.qml @@ -0,0 +1,13 @@ +import Qt.test 1.0 +import Qt 4.7 + +MyQmlObject { + objectProperty: if(1) otherObject + + property variant obj + + obj: QtObject { + id: otherObject + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/idShortcutInvalidates.qml b/tests/auto/declarative/qdeclarativeecmascript/data/idShortcutInvalidates.qml new file mode 100644 index 0000000..4746f3f --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/idShortcutInvalidates.qml @@ -0,0 +1,12 @@ +import Qt.test 1.0 +import Qt 4.7 + +MyQmlObject { + objectProperty: otherObject + + property variant obj + + obj: QtObject { + id: otherObject + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/include.js b/tests/auto/declarative/qdeclarativeecmascript/data/include.js new file mode 100644 index 0000000..232fd80 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/include.js @@ -0,0 +1,8 @@ +var test1 = true +var test2 = false +var test3 = false + +function go() { + Qt.include("js/include2.js"); +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/include.qml b/tests/auto/declarative/qdeclarativeecmascript/data/include.qml new file mode 100644 index 0000000..18543b2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/include.qml @@ -0,0 +1,23 @@ +import Qt 4.7 +import "include.js" as IncludeTest + +QtObject { + property int test0: 0 + property bool test1: false + property bool test2: false + property bool test2_1: false + property bool test3: false + property bool test3_1: false + + property int testValue: 99 + + Component.onCompleted: { + IncludeTest.go(); + test0 = IncludeTest.value + test1 = IncludeTest.test1 + test2 = IncludeTest.test2 + test2_1 = IncludeTest.test2_1 + test3 = IncludeTest.test3 + test3_1 = IncludeTest.test3_1 + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/include_callback.js b/tests/auto/declarative/qdeclarativeecmascript/data/include_callback.js new file mode 100644 index 0000000..ea19eba --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/include_callback.js @@ -0,0 +1,11 @@ +function go() { + var a = Qt.include("missing.js", function(o) { test2 = o.status == o.NETWORK_ERROR }); + test1 = a.status == a.NETWORK_ERROR + + var b = Qt.include("blank.js", function(o) { test4 = o.status == o.OK }); + test3 = b.status == b.OK + + var c = Qt.include("exception.js", function(o) { test6 = o.status == o.EXCEPTION }); + test5 = c.status == c.EXCEPTION +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/include_callback.qml b/tests/auto/declarative/qdeclarativeecmascript/data/include_callback.qml new file mode 100644 index 0000000..a39e821 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/include_callback.qml @@ -0,0 +1,15 @@ +import Qt 4.7 +import "include_callback.js" as IncludeTest + +QtObject { + property bool test1: false + property bool test2: false + property bool test3: false + property bool test4: false + property bool test5: false + property bool test6: false + + Component.onCompleted: { + IncludeTest.go(); + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/include_pragma.qml b/tests/auto/declarative/qdeclarativeecmascript/data/include_pragma.qml new file mode 100644 index 0000000..67b8cfd --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/include_pragma.qml @@ -0,0 +1,11 @@ +import Qt 4.7 +import "include_pragma_outer.js" as Script + +Item { + property int test1 + + Component.onCompleted: { + test1 = Script.callFunction() + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/include_pragma_inner.js b/tests/auto/declarative/qdeclarativeecmascript/data/include_pragma_inner.js new file mode 100644 index 0000000..a0380a2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/include_pragma_inner.js @@ -0,0 +1,5 @@ +.pragma library + +function getValue() { + return 100; +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/include_pragma_outer.js b/tests/auto/declarative/qdeclarativeecmascript/data/include_pragma_outer.js new file mode 100644 index 0000000..d87bafc --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/include_pragma_outer.js @@ -0,0 +1,6 @@ +Qt.include("include_pragma_inner.js") + +function callFunction() { + return getValue(); +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/include_remote.js b/tests/auto/declarative/qdeclarativeecmascript/data/include_remote.js new file mode 100644 index 0000000..e6a4676 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/include_remote.js @@ -0,0 +1,26 @@ +var myvar = 10; + +function go() +{ + var a = Qt.include("http://127.0.0.1:8111/remote_file.js", + function(o) { + test2 = o.status == o.OK + test3 = a.status == a.OK + test4 = myvar == 13 + + done = true; + }); + test1 = a.status == a.LOADING + + + var b = Qt.include("http://127.0.0.1:8111/exception.js", + function(o) { + test7 = o.status == o.EXCEPTION + test8 = b.status == a.EXCEPTION + test9 = b.exception.toString() == "Whoops!"; + test10 = o.exception.toString() == "Whoops!"; + + done2 = true; + }); + test6 = b.status == b.LOADING +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/include_remote.qml b/tests/auto/declarative/qdeclarativeecmascript/data/include_remote.qml new file mode 100644 index 0000000..06bd174 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/include_remote.qml @@ -0,0 +1,21 @@ +import Qt 4.7 +import "include_remote.js" as IncludeTest + +QtObject { + property bool done: false + property bool done2: false + + property bool test1: false + property bool test2: false + property bool test3: false + property bool test4: false + property bool test5: false + + property bool test6: false + property bool test7: false + property bool test8: false + property bool test9: false + property bool test10: false + + Component.onCompleted: IncludeTest.go(); +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/include_remote_missing.js b/tests/auto/declarative/qdeclarativeecmascript/data/include_remote_missing.js new file mode 100644 index 0000000..cc90860 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/include_remote_missing.js @@ -0,0 +1,13 @@ +function go() +{ + var a = Qt.include("http://127.0.0.1:8111/missing.js", + function(o) { + test2 = o.status == o.NETWORK_ERROR + test3 = a.status == a.NETWORK_ERROR + + done = true; + }); + + test1 = a.status == a.LOADING +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/include_remote_missing.qml b/tests/auto/declarative/qdeclarativeecmascript/data/include_remote_missing.qml new file mode 100644 index 0000000..8e486b2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/include_remote_missing.qml @@ -0,0 +1,12 @@ +import Qt 4.7 +import "include_remote_missing.js" as IncludeTest + +QtObject { + property bool done: false + + property bool test1: false + property bool test2: false + property bool test3: false + + Component.onCompleted: IncludeTest.go(); +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/include_shared.js b/tests/auto/declarative/qdeclarativeecmascript/data/include_shared.js new file mode 100644 index 0000000..a49c07b --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/include_shared.js @@ -0,0 +1,12 @@ +.pragma library + +var test1 = true +var test2 = false +var test3 = false + +var testValue = 99; + +function go() { + Qt.include("js/include2.js"); +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/include_shared.qml b/tests/auto/declarative/qdeclarativeecmascript/data/include_shared.qml new file mode 100644 index 0000000..e957018 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/include_shared.qml @@ -0,0 +1,22 @@ +import Qt 4.7 +import "include_shared.js" as IncludeTest + +QtObject { + property int test0: 0 + property bool test1: false + property bool test2: false + property bool test2_1: false + property bool test3: false + property bool test3_1: false + + Component.onCompleted: { + IncludeTest.go(); + test0 = IncludeTest.value + test1 = IncludeTest.test1 + test2 = IncludeTest.test2 + test2_1 = IncludeTest.test2_1 + test3 = IncludeTest.test3 + test3_1 = IncludeTest.test3_1 + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/js/include2.js b/tests/auto/declarative/qdeclarativeecmascript/data/js/include2.js new file mode 100644 index 0000000..2a0c039 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/js/include2.js @@ -0,0 +1,4 @@ +test2 = true +var test2_1 = true + +Qt.include("include3.js"); diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/js/include3.js b/tests/auto/declarative/qdeclarativeecmascript/data/js/include3.js new file mode 100644 index 0000000..84b2770 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/js/include3.js @@ -0,0 +1,3 @@ +test3 = true +var test3_1 = true +var value = testValue diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/jsObject.qml b/tests/auto/declarative/qdeclarativeecmascript/data/jsObject.qml new file mode 100644 index 0000000..fb4fa4d --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/jsObject.qml @@ -0,0 +1,12 @@ +import Qt 4.7 + +QtObject { + property int test + + Component.onCompleted: { + var o = new Object; + o.test = 92; + test = o.test; + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/libraryScriptAssert.js b/tests/auto/declarative/qdeclarativeecmascript/data/libraryScriptAssert.js new file mode 100644 index 0000000..3ffdb33 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/libraryScriptAssert.js @@ -0,0 +1,6 @@ +.pragma library + +function test(target) +{ + var a = target.a; +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/libraryScriptAssert.qml b/tests/auto/declarative/qdeclarativeecmascript/data/libraryScriptAssert.qml new file mode 100644 index 0000000..a945a16 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/libraryScriptAssert.qml @@ -0,0 +1,7 @@ +import Qt 4.7 +import "libraryScriptAssert.js" as Test + +QtObject { + id: root + Component.onCompleted: Test.test(root); +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/listProperties.qml b/tests/auto/declarative/qdeclarativeecmascript/data/listProperties.qml new file mode 100644 index 0000000..3ba4183 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/listProperties.qml @@ -0,0 +1,24 @@ +import Qt.test 1.0 +import Qt 4.7 + +MyQmlObject { + id: root + + objectListProperty: [ + QtObject { property int a: 10 }, + QtObject { property int a: 11 } + ] + + function calcTest1() { + var rv = 0; + for (var ii = 0; ii < root.objectListProperty.length; ++ii) { + rv += root.objectListProperty[ii].a; + } + return rv; + } + + property int test1: calcTest1(); + property int test2: root.objectListProperty.length + property bool test3: root.objectListProperty[1] != undefined + property bool test4: root.objectListProperty[100] == undefined +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/listToVariant.qml b/tests/auto/declarative/qdeclarativeecmascript/data/listToVariant.qml new file mode 100644 index 0000000..697530f --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/listToVariant.qml @@ -0,0 +1,5 @@ +import Qt 4.7 + +QtObject { + property variant test: children +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/methods.1.qml b/tests/auto/declarative/qdeclarativeecmascript/data/methods.1.qml new file mode 100644 index 0000000..0bbee16 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/methods.1.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyQmlObject { + id: myObject + onBasicSignal: myObject.methodNoArgs() +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/methods.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/methods.2.qml new file mode 100644 index 0000000..9f0c6b1 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/methods.2.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyQmlObject { + id: myObject + onBasicSignal: myObject.method(163) +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/methods.3.qml b/tests/auto/declarative/qdeclarativeecmascript/data/methods.3.qml new file mode 100644 index 0000000..269bd83 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/methods.3.qml @@ -0,0 +1,7 @@ +import Qt 4.7 + +QtObject { + function testFunction() { return 19; } + + property int test: testFunction() +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/methods.4.qml b/tests/auto/declarative/qdeclarativeecmascript/data/methods.4.qml new file mode 100644 index 0000000..2ea9cdb --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/methods.4.qml @@ -0,0 +1,11 @@ +import Qt 4.7 + +MethodsObject { + function testFunction2() { return 17; } + function testFunction3() { return 16; } + + property int test: testFunction() + property int test2: testFunction2() + property int test3: testFunction3() +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/methods.5.qml b/tests/auto/declarative/qdeclarativeecmascript/data/methods.5.qml new file mode 100644 index 0000000..0065add --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/methods.5.qml @@ -0,0 +1,9 @@ +import Qt 4.7 + +Item { + property alias blah: item.x + Item { id: item } + + function testFunction() { return 9; } + property int test: testFunction(); +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/multiEngineObject.qml b/tests/auto/declarative/qdeclarativeecmascript/data/multiEngineObject.qml new file mode 100644 index 0000000..a8cb50e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/multiEngineObject.qml @@ -0,0 +1,5 @@ +import Qt 4.7 + +QtObject { + property string test: thing.stringProperty +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/noSpuriousWarningsAtShutdown.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/noSpuriousWarningsAtShutdown.2.qml new file mode 100644 index 0000000..8be2d5b --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/noSpuriousWarningsAtShutdown.2.qml @@ -0,0 +1,10 @@ +import Qt 4.7 + +Item { + id: root + + Item {} + + SpuriousWarning {} +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/noSpuriousWarningsAtShutdown.qml b/tests/auto/declarative/qdeclarativeecmascript/data/noSpuriousWarningsAtShutdown.qml new file mode 100644 index 0000000..daa9b0b --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/noSpuriousWarningsAtShutdown.qml @@ -0,0 +1,9 @@ +import Qt 4.7 + +Item { + id: root + + property int childrenCount: root.children.length + + Item {} +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/nonExistantAttachedObject.qml b/tests/auto/declarative/qdeclarativeecmascript/data/nonExistantAttachedObject.qml new file mode 100644 index 0000000..f9585db --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/nonExistantAttachedObject.qml @@ -0,0 +1,5 @@ +import Qt.test 1.0 + +MyQmlObject { + stringProperty: MyQmlContainer.prop +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/nullObjectBinding.qml b/tests/auto/declarative/qdeclarativeecmascript/data/nullObjectBinding.qml new file mode 100644 index 0000000..11472a0 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/nullObjectBinding.qml @@ -0,0 +1,8 @@ +import Qt 4.7 + +QtObject { + property QtObject test + test: if (1) model + property ListModel model +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/numberAssignment.qml b/tests/auto/declarative/qdeclarativeecmascript/data/numberAssignment.qml new file mode 100644 index 0000000..30a77e8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/numberAssignment.qml @@ -0,0 +1,18 @@ +import Qt.test 1.0 + +NumberAssignment { + test1: if (1) 6.7 + test2: if (1) "6.7" + test3: if (1) 6 + test4: if (1) "6" + + test5: if (1) 6.7 + test6: if (1) "6.7" + test7: if (1) 6 + test8: if (1) "6" + + test9: if (1) 6.7 + test10: if (1) "6.7" + test11: if (1) 6 + test12: if (1) "6" +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/objectsCompareAsEqual.qml b/tests/auto/declarative/qdeclarativeecmascript/data/objectsCompareAsEqual.qml new file mode 100644 index 0000000..4b51109 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/objectsCompareAsEqual.qml @@ -0,0 +1,15 @@ +import Qt 4.7 + +Item { + id: root + + property variant item: child + Item { id: child } + + property bool test1: child == child + property bool test2: child.parent == root + property bool test3: root != child + property bool test4: item == child + property bool test5: item != root +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/outerBindingOverridesInnerBinding.qml b/tests/auto/declarative/qdeclarativeecmascript/data/outerBindingOverridesInnerBinding.qml new file mode 100644 index 0000000..0a933e8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/outerBindingOverridesInnerBinding.qml @@ -0,0 +1,14 @@ +import Qt.test 1.0 + +MyQmlObject { + property alias c1: myConstants.c1 + property alias c2: myConstants.c2 + property int c3: 0 + + objectProperty: ConstantsOverrideBindings { + id: myConstants + c2: c3 + } + +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/ownership.qml b/tests/auto/declarative/qdeclarativeecmascript/data/ownership.qml new file mode 100644 index 0000000..231c9e5 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/ownership.qml @@ -0,0 +1,5 @@ +import Qt 4.7 + +QtObject { + Component.onCompleted: { var a = getObject(); a = null; } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/propertyAssignmentErrors.qml b/tests/auto/declarative/qdeclarativeecmascript/data/propertyAssignmentErrors.qml new file mode 100644 index 0000000..bef40fd --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/propertyAssignmentErrors.qml @@ -0,0 +1,22 @@ +import Qt 4.7 + +QtObject { + id: root + + property int a + property variant b + + Component.onCompleted: { + try { + root.a = undefined; + } catch(e) { + console.log (e.fileName + ":" + e.lineNumber + ":" + e); + } + + try { + root.a = "Hello"; + } catch(e) { + console.log (e.fileName + ":" + e.lineNumber + ":" + e); + } + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/qlistqobjectMethods.qml b/tests/auto/declarative/qdeclarativeecmascript/data/qlistqobjectMethods.qml new file mode 100644 index 0000000..22c4f0b --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/qlistqobjectMethods.qml @@ -0,0 +1,6 @@ +import Qt 4.7 + +QtObject { + property int test: getObjects().length + property bool test2: getObjects()[0].trueProperty +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_10696.qml b/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_10696.qml new file mode 100644 index 0000000..cb5c4c9 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_10696.qml @@ -0,0 +1,26 @@ +import Qt 4.7 + +QtObject { + property string test: "aaaa" + + "bbbb" + + "cccc" + + "cccc" + + "cccc" + + "cccc" + + "cccc" + + "cccc" + + "cccc" + + "cccc" + + "cccc" + + "cccc" + + "cccc" + + "cccc" + + "cccc" + + "cccc" + + "cccc" + + "cccc" + + "cccc" + + "cccc" + + "cccc" + + "cccc"; +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_9792.qml b/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_9792.qml new file mode 100644 index 0000000..9ac4430 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_9792.qml @@ -0,0 +1,5 @@ +import Qt.test 1.0 + +MyQmlObject { + onBasicSignal: print("Hello world!"); +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/qtcreatorbug_1289.qml b/tests/auto/declarative/qdeclarativeecmascript/data/qtcreatorbug_1289.qml new file mode 100644 index 0000000..b6d31d5 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/qtcreatorbug_1289.qml @@ -0,0 +1,13 @@ +import Qt 4.7 + +QtObject { + id: root + property QtObject object: QtObject { + id: nested + property QtObject nestedObject + } + + Component.onCompleted: { + nested.nestedObject = root; + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/regExp.qml b/tests/auto/declarative/qdeclarativeecmascript/data/regExp.qml new file mode 100644 index 0000000..0dc404b --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/regExp.qml @@ -0,0 +1,7 @@ +import Qt.test 1.0 + +MyQmlObject{ + id: obj + objectName: "obj" + regExp: /[a-zA-z]/ +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/remote_file.js b/tests/auto/declarative/qdeclarativeecmascript/data/remote_file.js new file mode 100644 index 0000000..1b123ae --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/remote_file.js @@ -0,0 +1,2 @@ +myvar = 13; +test5 = true; diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scope.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scope.2.qml new file mode 100644 index 0000000..d4d7eb2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scope.2.qml @@ -0,0 +1,40 @@ +import Qt 4.7 + +Item { + property int a: 0 + property int b: 0 + + function b() { return 11; } + function c() { return 33; } + + QtObject { + id: a + property int value: 19 + } + + QtObject { + id: c + property int value: 24 + } + + QtObject { + id: nested + property int a: 1 + property int test: a.value + property int test2: b() + property int test3: c.value + } + + + // id takes precedence over local, and root properties + property int test1: a.value + property alias test2: nested.test + + // methods takes precedence over local, and root properties + property int test3: b() + property alias test4: nested.test2 + + // id takes precedence over methods + property int test5: c.value + property alias test6: nested.test3 +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scope.3.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scope.3.qml new file mode 100644 index 0000000..4395ba3 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scope.3.qml @@ -0,0 +1,13 @@ +import Qt 4.7 + +Item { + id: root + + property int foo: 12 + property int console: 11 + + property bool test1: foo == 12 + property bool test2: console != 11 + property bool test3: root.console == 11 +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scope.4.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scope.4.qml new file mode 100644 index 0000000..d65b6e7 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scope.4.qml @@ -0,0 +1,12 @@ +import Qt.test 1.0 + +MyQmlObject { + id: a + property int b: 9 + + property int test + property string test2 + + // Should resolve to signal arguments, not to other elements in the file + onArgumentSignal: { test = a; test2 = b; } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scope.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scope.qml new file mode 100644 index 0000000..7f895ff --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scope.qml @@ -0,0 +1,44 @@ +import Qt 4.7 + +Item { + id: root + + property int a: 1 + property int binding: a + property string binding2: a + "Test" + property int binding3: myFunction() + property int binding4: nestedObject.myNestedFunction() + + function myFunction() { + return a; + } + + Item { + id: nestedObject + + function myNestedFunction() { + return a; + } + + property int a: 2 + property int binding: a + property string binding2: a + "Test" + property int binding3: myFunction() + property int binding4: myNestedFunction() + } + + ScopeObject { + id: compObject + } + + property alias test1: root.binding + property alias test2: nestedObject.binding + property alias test3: root.binding2 + property alias test4: nestedObject.binding2 + property alias test5: root.binding3 + property alias test6: nestedObject.binding3 + property alias test7: root.binding4 + property alias test8: nestedObject.binding4 + property alias test9: compObject.binding + property alias test10: compObject.binding2 +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.1.js b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.1.js new file mode 100644 index 0000000..54284fe --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.1.js @@ -0,0 +1,4 @@ +function testFunction() { + test = true; +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.1.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.1.qml new file mode 100644 index 0000000..5d8e29e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.1.qml @@ -0,0 +1,10 @@ +import Qt.test 1.0 +import Qt 4.7 +import "scriptConnect.1.js" as Script +MyQmlObject { + property bool test: false + + id: root + + Component.onCompleted: root.argumentSignal.connect(Script.testFunction); +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.2.js b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.2.js new file mode 100644 index 0000000..595c778 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.2.js @@ -0,0 +1,5 @@ +function testFunction() { + if (this.b == 12) + test = true; +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.2.qml new file mode 100644 index 0000000..5681907 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.2.qml @@ -0,0 +1,16 @@ +import Qt.test 1.0 +import Qt 4.7 +import "scriptConnect.2.js" as Script + +MyQmlObject { + property bool test: false + + id: root + + Component.onCompleted: { + var a = new Object; + a.b = 12; + root.argumentSignal.connect(a, Script.testFunction); + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.3.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.3.qml new file mode 100644 index 0000000..40d8079 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.3.qml @@ -0,0 +1,15 @@ +import Qt.test 1.0 +import Qt 4.7 + +MyQmlObject { + property bool test: false + + id: root + + function testFunction() { + test = true; + } + + Component.onCompleted: root.argumentSignal.connect(testFunction); +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.4.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.4.qml new file mode 100644 index 0000000..0356650 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.4.qml @@ -0,0 +1,12 @@ +import Qt.test 1.0 +import Qt 4.7 + +MyQmlObject { + property bool test: false + + id: root + + Component.onCompleted: root.argumentSignal.connect(methodNoArgs); +} + + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.5.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.5.qml new file mode 100644 index 0000000..661f28e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.5.qml @@ -0,0 +1,11 @@ +import Qt.test 1.0 +import Qt 4.7 + +MyQmlObject { + property bool test: false + + id: root + + Component.onCompleted: root.argumentSignal.connect(root, methodNoArgs); +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.6.js b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.6.js new file mode 100644 index 0000000..71bdd08 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.6.js @@ -0,0 +1,3 @@ +function testFunction() { + test++; +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.6.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.6.qml new file mode 100644 index 0000000..36655ee --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scriptConnect.6.qml @@ -0,0 +1,15 @@ +import Qt.test 1.0 +import Qt 4.7 +import "scriptConnect.6.js" as Script + +MyQmlObject { + property int test: 0 + + id: root + + Component.onCompleted: { + root.argumentSignal.connect(Script.testFunction); + root.argumentSignal.connect(Script.testFunction); + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scriptDisconnect.1.js b/tests/auto/declarative/qdeclarativeecmascript/data/scriptDisconnect.1.js new file mode 100644 index 0000000..407426f --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scriptDisconnect.1.js @@ -0,0 +1,6 @@ +function testFunction() { + test++; +} + +function otherFunction() { +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scriptDisconnect.1.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scriptDisconnect.1.qml new file mode 100644 index 0000000..0cb4d79 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scriptDisconnect.1.qml @@ -0,0 +1,13 @@ +import Qt.test 1.0 +import Qt 4.7 +import "scriptDisconnect.1.js" as Script + +MyQmlObject { + property int test: 0 + + id: root + + Component.onCompleted: root.argumentSignal.connect(Script.testFunction); + + onBasicSignal: root.argumentSignal.disconnect(Script.testFunction); +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scriptDisconnect.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scriptDisconnect.2.qml new file mode 100644 index 0000000..05ca7a4 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scriptDisconnect.2.qml @@ -0,0 +1,14 @@ +import Qt.test 1.0 +import Qt 4.7 +import "scriptDisconnect.1.js" as Script + +MyQmlObject { + property int test: 0 + + id: root + + Component.onCompleted: root.argumentSignal.connect(root, Script.testFunction); + + onBasicSignal: root.argumentSignal.disconnect(root, Script.testFunction); +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scriptDisconnect.3.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scriptDisconnect.3.qml new file mode 100644 index 0000000..2a66bed --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scriptDisconnect.3.qml @@ -0,0 +1,14 @@ +import Qt.test 1.0 +import Qt 4.7 +import "scriptDisconnect.1.js" as Script + +MyQmlObject { + property int test: 0 + + id: root + + Component.onCompleted: root.argumentSignal.connect(root, Script.testFunction); + + onBasicSignal: root.argumentSignal.disconnect(Script.testFunction); +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scriptDisconnect.4.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scriptDisconnect.4.qml new file mode 100644 index 0000000..7beb84e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scriptDisconnect.4.qml @@ -0,0 +1,13 @@ +import Qt.test 1.0 +import Qt 4.7 +import "scriptDisconnect.1.js" as Script + +MyQmlObject { + property int test: 0 + + id: root + + Component.onCompleted: root.argumentSignal.connect(Script.testFunction); + + onBasicSignal: root.argumentSignal.disconnect(Script.otherFunction); +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scriptErrors.js b/tests/auto/declarative/qdeclarativeecmascript/data/scriptErrors.js new file mode 100644 index 0000000..d22f623 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scriptErrors.js @@ -0,0 +1,4 @@ +// Comment +a = 10 + +function getValue() { a = 10; return 0; } diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scriptErrors.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scriptErrors.qml new file mode 100644 index 0000000..e8f7b62 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/scriptErrors.qml @@ -0,0 +1,15 @@ +import Qt.test 1.0 +import "scriptErrors.js" as Script + +MyQmlObject { + property int t: a.value + property int w: Script.getValue(); + property int x: undefinedObject + property int y: (a.value, undefinedObject) + + onBasicSignal: { console.log(a.value); } + id: myObj + onAnotherBasicSignal: myObj.trueProperty = false; + onThirdBasicSignal: myObj.fakeProperty = ""; +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/selfDeletingBinding.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/selfDeletingBinding.2.qml new file mode 100644 index 0000000..58cf805 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/selfDeletingBinding.2.qml @@ -0,0 +1,17 @@ +import Qt.test 1.0 + +MyQmlContainer { + property bool triggerDelete: false + + children: [ + MyQmlObject { + // Will trigger deletion on binding assignment + deleteOnSet: Math.max(0, 1) + }, + + MyQmlObject { + // Will trigger deletion on binding assignment, but after component creation + deleteOnSet: if (triggerDelete) 1; else 0; + } + ] +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/selfDeletingBinding.qml b/tests/auto/declarative/qdeclarativeecmascript/data/selfDeletingBinding.qml new file mode 100644 index 0000000..074851a --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/selfDeletingBinding.qml @@ -0,0 +1,18 @@ +import Qt.test 1.0 + +MyQmlContainer { + property bool triggerDelete: false + + children: [ + MyQmlObject { + // Will trigger deletion during binding evaluation + stringProperty: {deleteMe(), "Hello"} + }, + + MyQmlObject { + // Will trigger deletion during binding evaluation, but after component creation + stringProperty: if (triggerDelete) { deleteMe(), "Hello" } else { "World" } + } + + ] +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/shutdownErrors.qml b/tests/auto/declarative/qdeclarativeecmascript/data/shutdownErrors.qml new file mode 100644 index 0000000..823096b --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/shutdownErrors.qml @@ -0,0 +1,13 @@ +import Qt 4.7 + +Item { + property int test: myObject.object.a + + Item { + id: myObject + property QtObject object; + object: QtObject { + property int a: 10 + } + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/signalAssignment.1.qml b/tests/auto/declarative/qdeclarativeecmascript/data/signalAssignment.1.qml new file mode 100644 index 0000000..fbd0914 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/signalAssignment.1.qml @@ -0,0 +1,5 @@ +import Qt.test 1.0 + +MyQmlObject { + onBasicSignal: setString('pass') +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/signalAssignment.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/signalAssignment.2.qml new file mode 100644 index 0000000..8addcb9 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/signalAssignment.2.qml @@ -0,0 +1,5 @@ +import Qt.test 1.0 + +MyQmlObject { + onArgumentSignal: setString('pass ' + a + ' ' + b + ' ' + c) +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/signalParameterTypes.qml b/tests/auto/declarative/qdeclarativeecmascript/data/signalParameterTypes.qml new file mode 100644 index 0000000..ffbe317 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/signalParameterTypes.qml @@ -0,0 +1,16 @@ +import Qt.test 1.0 + +MyQmlObject +{ + id: root + property int intProperty + property real realProperty + property color colorProperty + property variant variantProperty + + signal mySignal(int a, real b, color c, variant d) + + onMySignal: { intProperty = a; realProperty = b; colorProperty = c; variantProperty = d; } + + onBasicSignal: root.mySignal(10, 19.2, Qt.rgba(1, 1, 0, 1), Qt.rgba(1, 0, 1, 1)) +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/signalTriggeredBindings.qml b/tests/auto/declarative/qdeclarativeecmascript/data/signalTriggeredBindings.qml new file mode 100644 index 0000000..a2fb4d0 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/signalTriggeredBindings.qml @@ -0,0 +1,20 @@ +import Qt.test 1.0 +import Qt 4.7 + +MyQmlObject { + property real base: 50 + property alias test1: myObject.test1 + property alias test2: myObject.test2 + + objectProperty: QtObject { + id: myObject + property real test1: base + property real test2: Math.max(0, base) + } + + // Signal with no args + onBasicSignal: base = 200 + // Signal with args + onArgumentSignal: base = 400 +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/strictlyEquals.qml b/tests/auto/declarative/qdeclarativeecmascript/data/strictlyEquals.qml new file mode 100644 index 0000000..ec49a95 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/strictlyEquals.qml @@ -0,0 +1,17 @@ +import Qt 4.7 + +QtObject { + property bool test1: (a === true) + property bool test2: !(a === false) + property bool test3: (b === 11.2) + property bool test4: !(b === 9) + property bool test5: (c === 9) + property bool test6: !(c === 13) + property bool test7: (d === "Hello world") + property bool test8: !(d === "Hi") + + property bool a: true + property real b: 11.2 + property int c: 9 + property string d: "Hello world" +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/transientErrors.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/transientErrors.2.qml new file mode 100644 index 0000000..a36b4c0 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/transientErrors.2.qml @@ -0,0 +1,14 @@ +import Qt 4.7 + +QtObject { + id: root + + property variant a: 10 + property int x: 10 + property int test: a.x + + Component.onCompleted: { + a = 11; + a = root; + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/transientErrors.qml b/tests/auto/declarative/qdeclarativeecmascript/data/transientErrors.qml new file mode 100644 index 0000000..26d9596 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/transientErrors.qml @@ -0,0 +1,10 @@ +import Qt 4.7 + +QtObject { + property variant obj: nested + + property variant obj2 + obj2: NestedTypeTransientErrors { + id: nested + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/undefinedResetsProperty.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/undefinedResetsProperty.2.qml new file mode 100644 index 0000000..e73d38e2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/undefinedResetsProperty.2.qml @@ -0,0 +1,10 @@ +import Qt.test 1.0 + +MyQmlObject { + resettableProperty: 19 + + function doReset() { + resettableProperty = undefined; + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/undefinedResetsProperty.qml b/tests/auto/declarative/qdeclarativeecmascript/data/undefinedResetsProperty.qml new file mode 100644 index 0000000..eceff60 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/undefinedResetsProperty.qml @@ -0,0 +1,7 @@ +import Qt.test 1.0 + +MyQmlObject { + property bool setUndefined: false + + resettableProperty: setUndefined?undefined:92 +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/valueTypeFunctions.qml b/tests/auto/declarative/qdeclarativeecmascript/data/valueTypeFunctions.qml new file mode 100644 index 0000000..33b4a68 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/valueTypeFunctions.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyTypeObject { + rectProperty: Qt.rect(0,0,100,100) + rectFProperty: Qt.rect(0,0.5,100,99.5) +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/variantsAssignedUndefined.qml b/tests/auto/declarative/qdeclarativeecmascript/data/variantsAssignedUndefined.qml new file mode 100644 index 0000000..46e18e5 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/variantsAssignedUndefined.qml @@ -0,0 +1,9 @@ +import Qt 4.7 + +QtObject { + property bool runTest: false + onRunTestChanged: test1 = undefined + + property variant test1: 10 + property variant test2: (runTest == false)?11:undefined +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro b/tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro new file mode 100644 index 0000000..58cad34 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro @@ -0,0 +1,24 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += declarative script network +macx:CONFIG -= app_bundle + +SOURCES += tst_qdeclarativeecmascript.cpp \ + testtypes.cpp \ + ../shared/testhttpserver.cpp +HEADERS += testtypes.h \ + ../shared/testhttpserver.h +INCLUDEPATH += ../shared + +# QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage +# LIBS += -lgcov + +symbian: { + importFiles.sources = data + importFiles.path = . + DEPLOYMENT = importFiles +} else { + DEFINES += SRCDIR=\\\"$$PWD\\\" +} + +CONFIG += parallel_test + diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp new file mode 100644 index 0000000..8a4605a --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "testtypes.h" +#include <QWidget> +#include <QPlainTextEdit> + +class BaseExtensionObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(int baseExtendedProperty READ extendedProperty WRITE setExtendedProperty NOTIFY extendedPropertyChanged) +public: + BaseExtensionObject(QObject *parent) : QObject(parent), m_value(0) {} + + int extendedProperty() const { return m_value; } + void setExtendedProperty(int v) { m_value = v; emit extendedPropertyChanged(); } + +signals: + void extendedPropertyChanged(); +private: + int m_value; +}; + +class ExtensionObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(int extendedProperty READ extendedProperty WRITE setExtendedProperty NOTIFY extendedPropertyChanged) +public: + ExtensionObject(QObject *parent) : QObject(parent), m_value(0) {} + + int extendedProperty() const { return m_value; } + void setExtendedProperty(int v) { m_value = v; emit extendedPropertyChanged(); } + +signals: + void extendedPropertyChanged(); +private: + int m_value; +}; + +class DefaultPropertyExtensionObject : public QObject +{ + Q_OBJECT + Q_CLASSINFO("DefaultProperty", "firstProperty") +public: + DefaultPropertyExtensionObject(QObject *parent) : QObject(parent) {} +}; + +class QWidgetDeclarativeUI : public QObject +{ + Q_OBJECT + + Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged) + +signals: + void widthChanged(); + +public: + QWidgetDeclarativeUI(QObject *other) : QObject(other) { } + +public: + int width() const { return 0; } + void setWidth(int) { } +}; + + +void registerTypes() +{ + qmlRegisterType<MyQmlObject>("Qt.test", 1,0, "MyQmlObject"); + qmlRegisterType<MyDeferredObject>("Qt.test", 1,0, "MyDeferredObject"); + qmlRegisterType<MyQmlContainer>("Qt.test", 1,0, "MyQmlContainer"); + qmlRegisterExtendedType<MyBaseExtendedObject, BaseExtensionObject>("Qt.test", 1,0, "MyBaseExtendedObject"); + qmlRegisterExtendedType<MyExtendedObject, ExtensionObject>("Qt.test", 1,0, "MyExtendedObject"); + qmlRegisterType<MyTypeObject>("Qt.test", 1,0, "MyTypeObject"); + qmlRegisterType<NumberAssignment>("Qt.test", 1,0, "NumberAssignment"); + qmlRegisterExtendedType<DefaultPropertyExtendedObject, DefaultPropertyExtensionObject>("Qt.test", 1,0, "DefaultPropertyExtendedObject"); + qmlRegisterType<OverrideDefaultPropertyObject>("Qt.test", 1,0, "OverrideDefaultPropertyObject"); + + qmlRegisterExtendedType<QWidget,QWidgetDeclarativeUI>("Qt.test",1,0,"QWidget"); + qmlRegisterType<QPlainTextEdit>("Qt.test",1,0,"QPlainTextEdit"); +} + +#include "testtypes.moc" diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h new file mode 100644 index 0000000..7bb8a8e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h @@ -0,0 +1,690 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef TESTTYPES_H +#define TESTTYPES_H + +#include <QtCore/qobject.h> +#include <QtDeclarative/qdeclarative.h> +#include <QtDeclarative/qdeclarativeexpression.h> +#include <QtCore/qpoint.h> +#include <QtCore/qsize.h> +#include <QtDeclarative/qdeclarativelist.h> +#include <QtCore/qrect.h> +#include <QtGui/qmatrix.h> +#include <QtGui/qcolor.h> +#include <QtGui/qvector3d.h> +#include <QtCore/qdatetime.h> +#include <QtScript/qscriptvalue.h> +#include <QtDeclarative/qdeclarativescriptstring.h> +#include <QtDeclarative/qdeclarativecomponent.h> + +class MyQmlAttachedObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(int value READ value CONSTANT) + Q_PROPERTY(int value2 READ value2 WRITE setValue2) +public: + MyQmlAttachedObject(QObject *parent) : QObject(parent), m_value2(0) {} + + int value() const { return 19; } + int value2() const { return m_value2; } + void setValue2(int v) { m_value2 = v; } + + void emitMySignal() { emit mySignal(); } + +signals: + void mySignal(); + +private: + int m_value2; +}; + +class MyQmlObject : public QObject +{ + Q_OBJECT + Q_ENUMS(MyEnum) + Q_ENUMS(MyEnum2) + Q_PROPERTY(int deleteOnSet READ deleteOnSet WRITE setDeleteOnSet) + Q_PROPERTY(bool trueProperty READ trueProperty CONSTANT) + Q_PROPERTY(bool falseProperty READ falseProperty CONSTANT) + Q_PROPERTY(int value READ value WRITE setValue) + Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty NOTIFY stringChanged) + Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty NOTIFY objectChanged) + Q_PROPERTY(QDeclarativeListProperty<QObject> objectListProperty READ objectListProperty CONSTANT) + Q_PROPERTY(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty) + Q_PROPERTY(QRegExp regExp READ regExp WRITE setRegExp) + +public: + MyQmlObject(): m_methodCalled(false), m_methodIntCalled(false), m_object(0), m_value(0), m_resetProperty(13) {} + + enum MyEnum { EnumValue1 = 0, EnumValue2 = 1 }; + enum MyEnum2 { EnumValue3 = 2, EnumValue4 = 3 }; + + bool trueProperty() const { return true; } + bool falseProperty() const { return false; } + + QString stringProperty() const { return m_string; } + void setStringProperty(const QString &s) + { + if (s == m_string) + return; + m_string = s; + emit stringChanged(); + } + + QObject *objectProperty() const { return m_object; } + void setObjectProperty(QObject *obj) { + if (obj == m_object) + return; + m_object = obj; + emit objectChanged(); + } + + QDeclarativeListProperty<QObject> objectListProperty() { return QDeclarativeListProperty<QObject>(this, m_objectQList); } + + bool methodCalled() const { return m_methodCalled; } + bool methodIntCalled() const { return m_methodIntCalled; } + + QString string() const { return m_string; } + + static MyQmlAttachedObject *qmlAttachedProperties(QObject *o) { + return new MyQmlAttachedObject(o); + } + + int deleteOnSet() const { return 1; } + void setDeleteOnSet(int v) { if(v) delete this; } + + int value() const { return m_value; } + void setValue(int v) { m_value = v; } + + int resettableProperty() const { return m_resetProperty; } + void setResettableProperty(int v) { m_resetProperty = v; } + void resetProperty() { m_resetProperty = 13; } + + QRegExp regExp() { return m_regExp; } + void setRegExp(const QRegExp ®Exp) { m_regExp = regExp; } + +signals: + void basicSignal(); + void argumentSignal(int a, QString b, qreal c); + void stringChanged(); + void objectChanged(); + void anotherBasicSignal(); + void thirdBasicSignal(); + +public slots: + void deleteMe() { delete this; } + void methodNoArgs() { m_methodCalled = true; } + void method(int a) { if(a == 163) m_methodIntCalled = true; } + void setString(const QString &s) { m_string = s; } + +private: + friend class tst_qdeclarativeecmascript; + bool m_methodCalled; + bool m_methodIntCalled; + + QObject *m_object; + QString m_string; + QList<QObject *> m_objectQList; + int m_value; + int m_resetProperty; + QRegExp m_regExp; +}; + +QML_DECLARE_TYPEINFO(MyQmlObject, QML_HAS_ATTACHED_PROPERTIES) + +class MyQmlContainer : public QObject +{ + Q_OBJECT + Q_PROPERTY(QDeclarativeListProperty<MyQmlObject> children READ children CONSTANT) +public: + MyQmlContainer() {} + + QDeclarativeListProperty<MyQmlObject> children() { return QDeclarativeListProperty<MyQmlObject>(this, m_children); } + +private: + QList<MyQmlObject*> m_children; +}; + + +class MyExpression : public QDeclarativeExpression +{ + Q_OBJECT +public: + MyExpression(QDeclarativeContext *ctxt, const QString &expr) + : QDeclarativeExpression(ctxt, 0, expr), changed(false) + { + QObject::connect(this, SIGNAL(valueChanged()), this, SLOT(expressionValueChanged())); + setNotifyOnValueChanged(true); + } + + bool changed; + +public slots: + void expressionValueChanged() { + changed = true; + } +}; + + +class MyDefaultObject1 : public QObject +{ + Q_OBJECT + Q_PROPERTY(int horseLegs READ horseLegs CONSTANT) + Q_PROPERTY(int antLegs READ antLegs CONSTANT) + Q_PROPERTY(int emuLegs READ emuLegs CONSTANT) +public: + int horseLegs() const { return 4; } + int antLegs() const { return 6; } + int emuLegs() const { return 2; } +}; + +class MyDefaultObject3 : public QObject +{ + Q_OBJECT + Q_PROPERTY(int antLegs READ antLegs CONSTANT) + Q_PROPERTY(int humanLegs READ humanLegs CONSTANT) +public: + int antLegs() const { return 7; } // Mutant + int humanLegs() const { return 2; } + int millipedeLegs() const { return 1000; } +}; + +class MyDeferredObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged) + Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty) + Q_PROPERTY(QObject *objectProperty2 READ objectProperty2 WRITE setObjectProperty2) + Q_CLASSINFO("DeferredPropertyNames", "value,objectProperty,objectProperty2") + +public: + MyDeferredObject() : m_value(0), m_object(0), m_object2(0) {} + + int value() const { return m_value; } + void setValue(int v) { m_value = v; emit valueChanged(); } + + QObject *objectProperty() const { return m_object; } + void setObjectProperty(QObject *obj) { m_object = obj; } + + QObject *objectProperty2() const { return m_object2; } + void setObjectProperty2(QObject *obj) { m_object2 = obj; } + +signals: + void valueChanged(); + +private: + int m_value; + QObject *m_object; + QObject *m_object2; +}; + +class MyBaseExtendedObject : public QObject +{ +Q_OBJECT +Q_PROPERTY(int baseProperty READ baseProperty WRITE setBaseProperty) +public: + MyBaseExtendedObject() : m_value(0) {} + + int baseProperty() const { return m_value; } + void setBaseProperty(int v) { m_value = v; } + +private: + int m_value; +}; + +class MyExtendedObject : public MyBaseExtendedObject +{ +Q_OBJECT +Q_PROPERTY(int coreProperty READ coreProperty WRITE setCoreProperty) +public: + MyExtendedObject() : m_value(0) {} + + int coreProperty() const { return m_value; } + void setCoreProperty(int v) { m_value = v; } + +private: + int m_value; +}; + +class MyTypeObject : public QObject +{ + Q_OBJECT + Q_ENUMS(MyEnum) + Q_FLAGS(MyFlags) + + Q_PROPERTY(QString id READ id WRITE setId) + Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty) + Q_PROPERTY(QDeclarativeComponent *componentProperty READ componentProperty WRITE setComponentProperty) + Q_PROPERTY(MyFlags flagProperty READ flagProperty WRITE setFlagProperty) + Q_PROPERTY(MyEnum enumProperty READ enumProperty WRITE setEnumProperty) + Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty) + Q_PROPERTY(uint uintProperty READ uintProperty WRITE setUintProperty) + Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty) + Q_PROPERTY(qreal realProperty READ realProperty WRITE setRealProperty) + Q_PROPERTY(double doubleProperty READ doubleProperty WRITE setDoubleProperty) + Q_PROPERTY(float floatProperty READ floatProperty WRITE setFloatProperty) + Q_PROPERTY(QColor colorProperty READ colorProperty WRITE setColorProperty) + Q_PROPERTY(QDate dateProperty READ dateProperty WRITE setDateProperty) + Q_PROPERTY(QTime timeProperty READ timeProperty WRITE setTimeProperty) + Q_PROPERTY(QDateTime dateTimeProperty READ dateTimeProperty WRITE setDateTimeProperty) + Q_PROPERTY(QPoint pointProperty READ pointProperty WRITE setPointProperty) + Q_PROPERTY(QPointF pointFProperty READ pointFProperty WRITE setPointFProperty) + Q_PROPERTY(QSize sizeProperty READ sizeProperty WRITE setSizeProperty) + Q_PROPERTY(QSizeF sizeFProperty READ sizeFProperty WRITE setSizeFProperty) + Q_PROPERTY(QRect rectProperty READ rectProperty WRITE setRectProperty NOTIFY rectPropertyChanged) + Q_PROPERTY(QRect rectProperty2 READ rectProperty2 WRITE setRectProperty2) + Q_PROPERTY(QRectF rectFProperty READ rectFProperty WRITE setRectFProperty) + Q_PROPERTY(bool boolProperty READ boolProperty WRITE setBoolProperty) + Q_PROPERTY(QVariant variantProperty READ variantProperty WRITE setVariantProperty) + Q_PROPERTY(QVector3D vectorProperty READ vectorProperty WRITE setVectorProperty) + Q_PROPERTY(QUrl urlProperty READ urlProperty WRITE setUrlProperty) + + Q_PROPERTY(QDeclarativeScriptString scriptProperty READ scriptProperty WRITE setScriptProperty) + +public: + MyTypeObject() + : objectPropertyValue(0), componentPropertyValue(0) {} + + QString idValue; + QString id() const { + return idValue; + } + void setId(const QString &v) { + idValue = v; + } + + QObject *objectPropertyValue; + QObject *objectProperty() const { + return objectPropertyValue; + } + void setObjectProperty(QObject *v) { + objectPropertyValue = v; + } + + QDeclarativeComponent *componentPropertyValue; + QDeclarativeComponent *componentProperty() const { + return componentPropertyValue; + } + void setComponentProperty(QDeclarativeComponent *v) { + componentPropertyValue = v; + } + + enum MyFlag { FlagVal1 = 0x01, FlagVal2 = 0x02, FlagVal3 = 0x04 }; + Q_DECLARE_FLAGS(MyFlags, MyFlag) + MyFlags flagPropertyValue; + MyFlags flagProperty() const { + return flagPropertyValue; + } + void setFlagProperty(MyFlags v) { + flagPropertyValue = v; + } + + enum MyEnum { EnumVal1, EnumVal2 }; + MyEnum enumPropertyValue; + MyEnum enumProperty() const { + return enumPropertyValue; + } + void setEnumProperty(MyEnum v) { + enumPropertyValue = v; + } + + QString stringPropertyValue; + QString stringProperty() const { + return stringPropertyValue; + } + void setStringProperty(const QString &v) { + stringPropertyValue = v; + } + + uint uintPropertyValue; + uint uintProperty() const { + return uintPropertyValue; + } + void setUintProperty(const uint &v) { + uintPropertyValue = v; + } + + int intPropertyValue; + int intProperty() const { + return intPropertyValue; + } + void setIntProperty(const int &v) { + intPropertyValue = v; + } + + qreal realPropertyValue; + qreal realProperty() const { + return realPropertyValue; + } + void setRealProperty(const qreal &v) { + realPropertyValue = v; + } + + double doublePropertyValue; + double doubleProperty() const { + return doublePropertyValue; + } + void setDoubleProperty(const double &v) { + doublePropertyValue = v; + } + + float floatPropertyValue; + float floatProperty() const { + return floatPropertyValue; + } + void setFloatProperty(const float &v) { + floatPropertyValue = v; + } + + QColor colorPropertyValue; + QColor colorProperty() const { + return colorPropertyValue; + } + void setColorProperty(const QColor &v) { + colorPropertyValue = v; + } + + QDate datePropertyValue; + QDate dateProperty() const { + return datePropertyValue; + } + void setDateProperty(const QDate &v) { + datePropertyValue = v; + } + + QTime timePropertyValue; + QTime timeProperty() const { + return timePropertyValue; + } + void setTimeProperty(const QTime &v) { + timePropertyValue = v; + } + + QDateTime dateTimePropertyValue; + QDateTime dateTimeProperty() const { + return dateTimePropertyValue; + } + void setDateTimeProperty(const QDateTime &v) { + dateTimePropertyValue = v; + } + + QPoint pointPropertyValue; + QPoint pointProperty() const { + return pointPropertyValue; + } + void setPointProperty(const QPoint &v) { + pointPropertyValue = v; + } + + QPointF pointFPropertyValue; + QPointF pointFProperty() const { + return pointFPropertyValue; + } + void setPointFProperty(const QPointF &v) { + pointFPropertyValue = v; + } + + QSize sizePropertyValue; + QSize sizeProperty() const { + return sizePropertyValue; + } + void setSizeProperty(const QSize &v) { + sizePropertyValue = v; + } + + QSizeF sizeFPropertyValue; + QSizeF sizeFProperty() const { + return sizeFPropertyValue; + } + void setSizeFProperty(const QSizeF &v) { + sizeFPropertyValue = v; + } + + QRect rectPropertyValue; + QRect rectProperty() const { + return rectPropertyValue; + } + void setRectProperty(const QRect &v) { + rectPropertyValue = v; + emit rectPropertyChanged(); + } + + QRect rectPropertyValue2; + QRect rectProperty2() const { + return rectPropertyValue2; + } + void setRectProperty2(const QRect &v) { + rectPropertyValue2 = v; + } + + QRectF rectFPropertyValue; + QRectF rectFProperty() const { + return rectFPropertyValue; + } + void setRectFProperty(const QRectF &v) { + rectFPropertyValue = v; + } + + bool boolPropertyValue; + bool boolProperty() const { + return boolPropertyValue; + } + void setBoolProperty(const bool &v) { + boolPropertyValue = v; + } + + QVariant variantPropertyValue; + QVariant variantProperty() const { + return variantPropertyValue; + } + void setVariantProperty(const QVariant &v) { + variantPropertyValue = v; + } + + QVector3D vectorPropertyValue; + QVector3D vectorProperty() const { + return vectorPropertyValue; + } + void setVectorProperty(const QVector3D &v) { + vectorPropertyValue = v; + } + + QUrl urlPropertyValue; + QUrl urlProperty() const { + return urlPropertyValue; + } + void setUrlProperty(const QUrl &v) { + urlPropertyValue = v; + } + + QDeclarativeScriptString scriptPropertyValue; + QDeclarativeScriptString scriptProperty() const { + return scriptPropertyValue; + } + void setScriptProperty(const QDeclarativeScriptString &v) { + scriptPropertyValue = v; + } + + void doAction() { emit action(); } +signals: + void action(); + void rectPropertyChanged(); +}; +Q_DECLARE_OPERATORS_FOR_FLAGS(MyTypeObject::MyFlags) + +Q_DECLARE_METATYPE(QScriptValue); +class MyInvokableObject : public QObject +{ + Q_OBJECT +public: + MyInvokableObject() { reset(); } + + int invoked() const { return m_invoked; } + bool error() const { return m_invokedError; } + const QVariantList &actuals() const { return m_actuals; } + void reset() { m_invoked = -1; m_invokedError = false; m_actuals.clear(); } + + Q_INVOKABLE QPointF method_get_QPointF() { return QPointF(99.3, -10.2); } + Q_INVOKABLE QPoint method_get_QPoint() { return QPoint(9, 12); } + + Q_INVOKABLE void method_NoArgs() { invoke(0); } + Q_INVOKABLE int method_NoArgs_int() { invoke(1); return 6; } + Q_INVOKABLE qreal method_NoArgs_real() { invoke(2); return 19.7; } + Q_INVOKABLE QPointF method_NoArgs_QPointF() { invoke(3); return QPointF(123, 4.5); } + Q_INVOKABLE QObject *method_NoArgs_QObject() { invoke(4); return this; } + Q_INVOKABLE MyInvokableObject *method_NoArgs_unknown() { invoke(5); return this; } + Q_INVOKABLE QScriptValue method_NoArgs_QScriptValue() { invoke(6); return QScriptValue("Hello world"); } + Q_INVOKABLE QVariant method_NoArgs_QVariant() { invoke(7); return QVariant("QML rocks"); } + + Q_INVOKABLE void method_int(int a) { invoke(8); m_actuals << a; } + Q_INVOKABLE void method_intint(int a, int b) { invoke(9); m_actuals << a << b; } + Q_INVOKABLE void method_real(qreal a) { invoke(10); m_actuals << a; } + Q_INVOKABLE void method_QString(QString a) { invoke(11); m_actuals << a; } + Q_INVOKABLE void method_QPointF(QPointF a) { invoke(12); m_actuals << a; } + Q_INVOKABLE void method_QObject(QObject *a) { invoke(13); m_actuals << qVariantFromValue(a); } + Q_INVOKABLE void method_QScriptValue(QScriptValue a) { invoke(14); m_actuals << qVariantFromValue(a); } + Q_INVOKABLE void method_intQScriptValue(int a, QScriptValue b) { invoke(15); m_actuals << a << qVariantFromValue(b); } + + Q_INVOKABLE void method_overload(int a) { invoke(16); m_actuals << a; } + Q_INVOKABLE void method_overload(int a, int b) { invoke(17); m_actuals << a << b; } + +private: + void invoke(int idx) { if (m_invoked != -1) m_invokedError = true; m_invoked = idx;} + int m_invoked; + bool m_invokedError; + QVariantList m_actuals; +}; + +class NumberAssignment : public QObject +{ + Q_OBJECT +public: + Q_PROPERTY(qreal test1 READ test1 WRITE setTest1); + qreal _test1; + qreal test1() const { return _test1; } + void setTest1(qreal v) { _test1 = v; } + + Q_PROPERTY(qreal test2 READ test2 WRITE setTest2); + qreal _test2; + qreal test2() const { return _test2; } + void setTest2(qreal v) { _test2 = v; } + + Q_PROPERTY(qreal test3 READ test3 WRITE setTest3); + qreal _test3; + qreal test3() const { return _test3; } + void setTest3(qreal v) { _test3 = v; } + + Q_PROPERTY(qreal test4 READ test4 WRITE setTest4); + qreal _test4; + qreal test4() const { return _test4; } + void setTest4(qreal v) { _test4 = v; } + + Q_PROPERTY(int test5 READ test5 WRITE setTest5); + int _test5; + int test5() const { return _test5; } + void setTest5(int v) { _test5 = v; } + + Q_PROPERTY(int test6 READ test6 WRITE setTest6); + int _test6; + int test6() const { return _test6; } + void setTest6(int v) { _test6 = v; } + + Q_PROPERTY(int test7 READ test7 WRITE setTest7); + int _test7; + int test7() const { return _test7; } + void setTest7(int v) { _test7 = v; } + + Q_PROPERTY(int test8 READ test8 WRITE setTest8); + int _test8; + int test8() const { return _test8; } + void setTest8(int v) { _test8 = v; } + + Q_PROPERTY(unsigned int test9 READ test9 WRITE setTest9); + unsigned int _test9; + unsigned int test9() const { return _test9; } + void setTest9(unsigned int v) { _test9 = v; } + + Q_PROPERTY(unsigned int test10 READ test10 WRITE setTest10); + unsigned int _test10; + unsigned int test10() const { return _test10; } + void setTest10(unsigned int v) { _test10 = v; } + + Q_PROPERTY(unsigned int test11 READ test11 WRITE setTest11); + unsigned int _test11; + unsigned int test11() const { return _test11; } + void setTest11(unsigned int v) { _test11 = v; } + + Q_PROPERTY(unsigned int test12 READ test12 WRITE setTest12); + unsigned int _test12; + unsigned int test12() const { return _test12; } + void setTest12(unsigned int v) { _test12 = v; } +}; + +class DefaultPropertyExtendedObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(QObject *firstProperty READ firstProperty WRITE setFirstProperty) + Q_PROPERTY(QObject *secondProperty READ secondProperty WRITE setSecondProperty) +public: + DefaultPropertyExtendedObject(QObject *parent = 0) : QObject(parent), m_firstProperty(0), m_secondProperty(0) {} + + QObject *firstProperty() const { return m_firstProperty; } + QObject *secondProperty() const { return m_secondProperty; } + void setFirstProperty(QObject *property) { m_firstProperty = property; } + void setSecondProperty(QObject *property) { m_secondProperty = property; } +private: + QObject* m_firstProperty; + QObject* m_secondProperty; +}; + +class OverrideDefaultPropertyObject : public DefaultPropertyExtendedObject +{ + Q_OBJECT + Q_CLASSINFO("DefaultProperty", "secondProperty") +public: + OverrideDefaultPropertyObject() {} +}; + +void registerTypes(); + +#endif // TESTTYPES_H + diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp new file mode 100644 index 0000000..16e7ec5 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -0,0 +1,2503 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <qtest.h> +#include <QtDeclarative/qdeclarativecomponent.h> +#include <QtDeclarative/qdeclarativeengine.h> +#include <QtDeclarative/qdeclarativeexpression.h> +#include <QtDeclarative/qdeclarativecontext.h> +#include <QtCore/qfileinfo.h> +#include <QtCore/qdebug.h> +#include <QtDeclarative/private/qdeclarativeguard_p.h> +#include <QtCore/qdir.h> +#include <QtCore/qnumeric.h> +#include <private/qdeclarativeengine_p.h> +#include <private/qdeclarativeglobalscriptclass_p.h> +#include "testtypes.h" +#include "testhttpserver.h" + +#ifdef Q_OS_SYMBIAN +// In Symbian OS test data is located in applications private dir +#define SRCDIR "." +#endif + +/* +This test covers evaluation of ECMAScript expressions and bindings from within +QML. This does not include static QML language issues. + +Static QML language issues are covered in qmllanguage +*/ +inline QUrl TEST_FILE(const QString &filename) +{ + QFileInfo fileInfo(__FILE__); + return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath("data/" + filename)); +} + +inline QUrl TEST_FILE(const char *filename) +{ + return TEST_FILE(QLatin1String(filename)); +} + +class tst_qdeclarativeecmascript : public QObject +{ + Q_OBJECT +public: + tst_qdeclarativeecmascript() {} + +private slots: + void initTestCase(); + void assignBasicTypes(); + void idShortcutInvalidates(); + void boolPropertiesEvaluateAsBool(); + void methods(); + void signalAssignment(); + void bindingLoop(); + void basicExpressions(); + void basicExpressions_data(); + void arrayExpressions(); + void contextPropertiesTriggerReeval(); + void objectPropertiesTriggerReeval(); + void deferredProperties(); + void deferredPropertiesErrors(); + void extensionObjects(); + void overrideExtensionProperties(); + void attachedProperties(); + void enums(); + void valueTypeFunctions(); + void constantsOverrideBindings(); + void outerBindingOverridesInnerBinding(); + void aliasPropertyAndBinding(); + void nonExistantAttachedObject(); + void scope(); + void signalParameterTypes(); + void objectsCompareAsEqual(); + void dynamicCreation_data(); + void dynamicCreation(); + void dynamicDestruction(); + void objectToString(); + void selfDeletingBinding(); + void extendedObjectPropertyLookup(); + void scriptErrors(); + void functionErrors(); + void propertyAssignmentErrors(); + void signalTriggeredBindings(); + void listProperties(); + void exceptionClearsOnReeval(); + void exceptionSlotProducesWarning(); + void exceptionBindingProducesWarning(); + void transientErrors(); + void shutdownErrors(); + void compositePropertyType(); + void jsObject(); + void undefinedResetsProperty(); + void listToVariant(); + void multiEngineObject(); + void deletedObject(); + void attachedPropertyScope(); + void scriptConnect(); + void scriptDisconnect(); + void ownership(); + void qlistqobjectMethods(); + void strictlyEquals(); + void compiled(); + void numberAssignment(); + + void bug1(); + void bug2(); + void dynamicCreationCrash(); + void regExpBug(); + void nullObjectBinding(); + void deletedEngine(); + void libraryScriptAssert(); + void variantsAssignedUndefined(); + void qtbug_9792(); + void qtcreatorbug_1289(); + void noSpuriousWarningsAtShutdown(); + void canAssignNullToQObject(); + void functionAssignment(); + void eval(); + void function(); + void qtbug_10696(); + + void include(); + + void callQtInvokables(); +private: + QDeclarativeEngine engine; +}; + +void tst_qdeclarativeecmascript::initTestCase() { registerTypes(); } + +void tst_qdeclarativeecmascript::assignBasicTypes() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml")); + MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3); + QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2); + QCOMPARE(object->stringProperty(), QString("Hello World!")); + QCOMPARE(object->uintProperty(), uint(10)); + QCOMPARE(object->intProperty(), -19); + QCOMPARE((float)object->realProperty(), float(23.2)); + QCOMPARE((float)object->doubleProperty(), float(-19.7)); + QCOMPARE((float)object->floatProperty(), float(8.5)); + QCOMPARE(object->colorProperty(), QColor("red")); + QCOMPARE(object->dateProperty(), QDate(1982, 11, 25)); + QCOMPARE(object->timeProperty(), QTime(11, 11, 32)); + QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1))); + QCOMPARE(object->pointProperty(), QPoint(99,13)); + QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3)); + QCOMPARE(object->sizeProperty(), QSize(99, 13)); + QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2)); + QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200)); + QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99)); + QCOMPARE(object->boolProperty(), true); + QCOMPARE(object->variantProperty(), QVariant("Hello World!")); + QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2)); + QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml"))); + delete object; + } + { + QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml")); + MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3); + QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2); + QCOMPARE(object->stringProperty(), QString("Hello World!")); + QCOMPARE(object->uintProperty(), uint(10)); + QCOMPARE(object->intProperty(), -19); + QCOMPARE((float)object->realProperty(), float(23.2)); + QCOMPARE((float)object->doubleProperty(), float(-19.7)); + QCOMPARE((float)object->floatProperty(), float(8.5)); + QCOMPARE(object->colorProperty(), QColor("red")); + QCOMPARE(object->dateProperty(), QDate(1982, 11, 25)); + QCOMPARE(object->timeProperty(), QTime(11, 11, 32)); + QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1))); + QCOMPARE(object->pointProperty(), QPoint(99,13)); + QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3)); + QCOMPARE(object->sizeProperty(), QSize(99, 13)); + QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2)); + QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200)); + QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99)); + QCOMPARE(object->boolProperty(), true); + QCOMPARE(object->variantProperty(), QVariant("Hello World!")); + QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2)); + QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml"))); + delete object; + } +} + +void tst_qdeclarativeecmascript::idShortcutInvalidates() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + QVERIFY(object->objectProperty() != 0); + delete object->objectProperty(); + QVERIFY(object->objectProperty() == 0); + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + QVERIFY(object->objectProperty() != 0); + delete object->objectProperty(); + QVERIFY(object->objectProperty() == 0); + } +} + +void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->stringProperty(), QLatin1String("pass")); + } + { + QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->stringProperty(), QLatin1String("pass")); + } +} + +void tst_qdeclarativeecmascript::signalAssignment() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.1.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->string(), QString()); + emit object->basicSignal(); + QCOMPARE(object->string(), QString("pass")); + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.2.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->string(), QString()); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->string(), QString("pass 19 Hello world! 10.3")); + } +} + +void tst_qdeclarativeecmascript::methods() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("methods.1.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->methodCalled(), false); + QCOMPARE(object->methodIntCalled(), false); + emit object->basicSignal(); + QCOMPARE(object->methodCalled(), true); + QCOMPARE(object->methodIntCalled(), false); + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("methods.2.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->methodCalled(), false); + QCOMPARE(object->methodIntCalled(), false); + emit object->basicSignal(); + QCOMPARE(object->methodCalled(), false); + QCOMPARE(object->methodIntCalled(), true); + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("methods.3.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("test").toInt(), 19); + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("methods.4.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("test").toInt(), 19); + QCOMPARE(object->property("test2").toInt(), 17); + QCOMPARE(object->property("test3").toInt(), 16); + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("methods.5.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("test").toInt(), 9); + } +} + +void tst_qdeclarativeecmascript::bindingLoop() +{ + QDeclarativeComponent component(&engine, TEST_FILE("bindingLoop.qml")); + QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\""; + QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); + QObject *object = component.create(); + QVERIFY(object != 0); +} + +void tst_qdeclarativeecmascript::basicExpressions_data() +{ + QTest::addColumn<QString>("expression"); + QTest::addColumn<QVariant>("result"); + QTest::addColumn<bool>("nest"); + + QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false; + QTest::newRow("Context property") << "a" << QVariant(1944) << false; + QTest::newRow("Context property") << "a" << QVariant(1944) << true; + QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false; + QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true; + QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false; + QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true; + QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false; + QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true; + QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false; + QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true; + QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false; + QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false; + QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false; + QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true; + QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true; + QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true; + QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true; + QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true; +} + +void tst_qdeclarativeecmascript::basicExpressions() +{ + QFETCH(QString, expression); + QFETCH(QVariant, result); + QFETCH(bool, nest); + + MyQmlObject object1; + MyQmlObject object2; + MyQmlObject object3; + MyDefaultObject1 default1; + MyDefaultObject3 default3; + object1.setStringProperty("Object1"); + object2.setStringProperty("Object2"); + object3.setStringProperty("Object3"); + + QDeclarativeContext context(engine.rootContext()); + QDeclarativeContext nestedContext(&context); + + context.setContextObject(&default1); + context.setContextProperty("a", QVariant(1944)); + context.setContextProperty("b", QVariant("Milk")); + context.setContextProperty("object", &object1); + context.setContextProperty("objectOverride", &object2); + nestedContext.setContextObject(&default3); + nestedContext.setContextProperty("b", QVariant("Cow")); + nestedContext.setContextProperty("objectOverride", &object3); + nestedContext.setContextProperty("millipedeLegs", QVariant(100)); + + MyExpression expr(nest?&nestedContext:&context, expression); + QCOMPARE(expr.evaluate(), result); +} + +void tst_qdeclarativeecmascript::arrayExpressions() +{ + QObject obj1; + QObject obj2; + QObject obj3; + + QDeclarativeContext context(engine.rootContext()); + context.setContextProperty("a", &obj1); + context.setContextProperty("b", &obj2); + context.setContextProperty("c", &obj3); + + MyExpression expr(&context, "[a, b, c, 10]"); + QVariant result = expr.evaluate(); + QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >()); + QList<QObject *> list = qvariant_cast<QList<QObject *> >(result); + QCOMPARE(list.count(), 4); + QCOMPARE(list.at(0), &obj1); + QCOMPARE(list.at(1), &obj2); + QCOMPARE(list.at(2), &obj3); + QCOMPARE(list.at(3), (QObject *)0); +} + +// Tests that modifying a context property will reevaluate expressions +void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval() +{ + QDeclarativeContext context(engine.rootContext()); + MyQmlObject object1; + MyQmlObject object2; + MyQmlObject *object3 = new MyQmlObject; + + object1.setStringProperty("Hello"); + object2.setStringProperty("World"); + + context.setContextProperty("testProp", QVariant(1)); + context.setContextProperty("testObj", &object1); + context.setContextProperty("testObj2", object3); + + { + MyExpression expr(&context, "testProp + 1"); + QCOMPARE(expr.changed, false); + QCOMPARE(expr.evaluate(), QVariant(2)); + + context.setContextProperty("testProp", QVariant(2)); + QCOMPARE(expr.changed, true); + QCOMPARE(expr.evaluate(), QVariant(3)); + } + + { + MyExpression expr(&context, "testProp + testProp + testProp"); + QCOMPARE(expr.changed, false); + QCOMPARE(expr.evaluate(), QVariant(6)); + + context.setContextProperty("testProp", QVariant(4)); + QCOMPARE(expr.changed, true); + QCOMPARE(expr.evaluate(), QVariant(12)); + } + + { + MyExpression expr(&context, "testObj.stringProperty"); + QCOMPARE(expr.changed, false); + QCOMPARE(expr.evaluate(), QVariant("Hello")); + + context.setContextProperty("testObj", &object2); + QCOMPARE(expr.changed, true); + QCOMPARE(expr.evaluate(), QVariant("World")); + } + + { + MyExpression expr(&context, "testObj.stringProperty /**/"); + QCOMPARE(expr.changed, false); + QCOMPARE(expr.evaluate(), QVariant("World")); + + context.setContextProperty("testObj", &object1); + QCOMPARE(expr.changed, true); + QCOMPARE(expr.evaluate(), QVariant("Hello")); + } + + { + MyExpression expr(&context, "testObj2"); + QCOMPARE(expr.changed, false); + QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3)); + } + +} + +void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval() +{ + QDeclarativeContext context(engine.rootContext()); + MyQmlObject object1; + MyQmlObject object2; + MyQmlObject object3; + context.setContextProperty("testObj", &object1); + + object1.setStringProperty(QLatin1String("Hello")); + object2.setStringProperty(QLatin1String("Dog")); + object3.setStringProperty(QLatin1String("Cat")); + + { + MyExpression expr(&context, "testObj.stringProperty"); + QCOMPARE(expr.changed, false); + QCOMPARE(expr.evaluate(), QVariant("Hello")); + + object1.setStringProperty(QLatin1String("World")); + QCOMPARE(expr.changed, true); + QCOMPARE(expr.evaluate(), QVariant("World")); + } + + { + MyExpression expr(&context, "testObj.objectProperty.stringProperty"); + QCOMPARE(expr.changed, false); + QCOMPARE(expr.evaluate(), QVariant()); + + object1.setObjectProperty(&object2); + QCOMPARE(expr.changed, true); + expr.changed = false; + QCOMPARE(expr.evaluate(), QVariant("Dog")); + + object1.setObjectProperty(&object3); + QCOMPARE(expr.changed, true); + expr.changed = false; + QCOMPARE(expr.evaluate(), QVariant("Cat")); + + object1.setObjectProperty(0); + QCOMPARE(expr.changed, true); + expr.changed = false; + QCOMPARE(expr.evaluate(), QVariant()); + + object1.setObjectProperty(&object3); + QCOMPARE(expr.changed, true); + expr.changed = false; + QCOMPARE(expr.evaluate(), QVariant("Cat")); + + object3.setStringProperty("Donkey"); + QCOMPARE(expr.changed, true); + expr.changed = false; + QCOMPARE(expr.evaluate(), QVariant("Donkey")); + } +} + +void tst_qdeclarativeecmascript::deferredProperties() +{ + QDeclarativeComponent component(&engine, TEST_FILE("deferredProperties.qml")); + MyDeferredObject *object = + qobject_cast<MyDeferredObject *>(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->value(), 0); + QVERIFY(object->objectProperty() == 0); + QVERIFY(object->objectProperty2() != 0); + qmlExecuteDeferred(object); + QCOMPARE(object->value(), 10); + QVERIFY(object->objectProperty() != 0); + MyQmlObject *qmlObject = + qobject_cast<MyQmlObject *>(object->objectProperty()); + QVERIFY(qmlObject != 0); + QCOMPARE(qmlObject->value(), 10); + object->setValue(19); + QCOMPARE(qmlObject->value(), 19); +} + +// Check errors on deferred properties are correctly emitted +void tst_qdeclarativeecmascript::deferredPropertiesErrors() +{ + QDeclarativeComponent component(&engine, TEST_FILE("deferredPropertiesErrors.qml")); + MyDeferredObject *object = + qobject_cast<MyDeferredObject *>(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->value(), 0); + QVERIFY(object->objectProperty() == 0); + QVERIFY(object->objectProperty2() == 0); + + QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject* objectProperty"; + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); + + qmlExecuteDeferred(object); + + delete object; +} + +void tst_qdeclarativeecmascript::extensionObjects() +{ + QDeclarativeComponent component(&engine, TEST_FILE("extensionObjects.qml")); + MyExtendedObject *object = + qobject_cast<MyExtendedObject *>(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->baseProperty(), 13); + QCOMPARE(object->coreProperty(), 9); + object->setProperty("extendedProperty", QVariant(11)); + object->setProperty("baseExtendedProperty", QVariant(92)); + QCOMPARE(object->coreProperty(), 11); + QCOMPARE(object->baseProperty(), 92); + + MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested"))); + QVERIFY(nested); + QCOMPARE(nested->baseProperty(), 13); + QCOMPARE(nested->coreProperty(), 9); + nested->setProperty("extendedProperty", QVariant(11)); + nested->setProperty("baseExtendedProperty", QVariant(92)); + QCOMPARE(nested->coreProperty(), 11); + QCOMPARE(nested->baseProperty(), 92); + +} + +void tst_qdeclarativeecmascript::overrideExtensionProperties() +{ + QDeclarativeComponent component(&engine, TEST_FILE("extensionObjectsPropertyOverride.qml")); + OverrideDefaultPropertyObject *object = + qobject_cast<OverrideDefaultPropertyObject *>(component.create()); + QVERIFY(object != 0); + QVERIFY(object->secondProperty() != 0); + QVERIFY(object->firstProperty() == 0); +} + +void tst_qdeclarativeecmascript::attachedProperties() +{ + QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("a").toInt(), 19); + QCOMPARE(object->property("b").toInt(), 19); + QCOMPARE(object->property("c").toInt(), 19); + QCOMPARE(object->property("d").toInt(), 19); + + // ### Need to test attached property assignment +} + +void tst_qdeclarativeecmascript::enums() +{ + // Existant enums + { + QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("a").toInt(), 0); + QCOMPARE(object->property("b").toInt(), 1); + QCOMPARE(object->property("c").toInt(), 2); + QCOMPARE(object->property("d").toInt(), 3); + QCOMPARE(object->property("e").toInt(), 0); + QCOMPARE(object->property("f").toInt(), 1); + QCOMPARE(object->property("g").toInt(), 2); + QCOMPARE(object->property("h").toInt(), 3); + QCOMPARE(object->property("i").toInt(), 19); + QCOMPARE(object->property("j").toInt(), 19); + } + // Non-existent enums + { + QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml")); + + QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a"; + QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b"; + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1)); + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2)); + + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("a").toInt(), 0); + QCOMPARE(object->property("b").toInt(), 0); + } +} + +void tst_qdeclarativeecmascript::valueTypeFunctions() +{ + QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml")); + MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create()); + QVERIFY(obj != 0); + QCOMPARE(obj->rectProperty(), QRect(0,0,100,100)); + QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5)); +} + +/* +Tests that writing a constant to a property with a binding on it disables the +binding. +*/ +void tst_qdeclarativeecmascript::constantsOverrideBindings() +{ + // From ECMAScript + { + QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("c2").toInt(), 0); + object->setProperty("c1", QVariant(9)); + QCOMPARE(object->property("c2").toInt(), 9); + + emit object->basicSignal(); + + QCOMPARE(object->property("c2").toInt(), 13); + object->setProperty("c1", QVariant(8)); + QCOMPARE(object->property("c2").toInt(), 13); + } + + // During construction + { + QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("c1").toInt(), 0); + QCOMPARE(object->property("c2").toInt(), 10); + object->setProperty("c1", QVariant(9)); + QCOMPARE(object->property("c1").toInt(), 9); + QCOMPARE(object->property("c2").toInt(), 10); + } + +#if 0 + // From C++ + { + QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("c2").toInt(), 0); + object->setProperty("c1", QVariant(9)); + QCOMPARE(object->property("c2").toInt(), 9); + + object->setProperty("c2", QVariant(13)); + QCOMPARE(object->property("c2").toInt(), 13); + object->setProperty("c1", QVariant(7)); + QCOMPARE(object->property("c1").toInt(), 7); + QCOMPARE(object->property("c2").toInt(), 13); + } +#endif +} + +/* +Tests that assigning a binding to a property that already has a binding causes +the original binding to be disabled. +*/ +void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding() +{ + QDeclarativeComponent component(&engine, + TEST_FILE("outerBindingOverridesInnerBinding.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("c1").toInt(), 0); + QCOMPARE(object->property("c2").toInt(), 0); + QCOMPARE(object->property("c3").toInt(), 0); + + object->setProperty("c1", QVariant(9)); + QCOMPARE(object->property("c1").toInt(), 9); + QCOMPARE(object->property("c2").toInt(), 0); + QCOMPARE(object->property("c3").toInt(), 0); + + object->setProperty("c3", QVariant(8)); + QCOMPARE(object->property("c1").toInt(), 9); + QCOMPARE(object->property("c2").toInt(), 8); + QCOMPARE(object->property("c3").toInt(), 8); +} + +/* +Access a non-existent attached object. + +Tests for a regression where this used to crash. +*/ +void tst_qdeclarativeecmascript::nonExistantAttachedObject() +{ + QDeclarativeComponent component(&engine, TEST_FILE("nonExistantAttachedObject.qml")); + + QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty"; + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); + + QObject *object = component.create(); + QVERIFY(object != 0); +} + +void tst_qdeclarativeecmascript::scope() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("scope.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toInt(), 1); + QCOMPARE(object->property("test2").toInt(), 2); + QCOMPARE(object->property("test3").toString(), QString("1Test")); + QCOMPARE(object->property("test4").toString(), QString("2Test")); + QCOMPARE(object->property("test5").toInt(), 1); + QCOMPARE(object->property("test6").toInt(), 1); + QCOMPARE(object->property("test7").toInt(), 2); + QCOMPARE(object->property("test8").toInt(), 2); + QCOMPARE(object->property("test9").toInt(), 1); + QCOMPARE(object->property("test10").toInt(), 3); + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toInt(), 19); + QCOMPARE(object->property("test2").toInt(), 19); + QCOMPARE(object->property("test3").toInt(), 11); + QCOMPARE(object->property("test4").toInt(), 11); + QCOMPARE(object->property("test5").toInt(), 24); + QCOMPARE(object->property("test6").toInt(), 24); + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toBool(), true); + QCOMPARE(object->property("test2").toBool(), true); + QCOMPARE(object->property("test3").toBool(), true); + } + + // Signal argument scope + { + QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toInt(), 0); + QCOMPARE(object->property("test2").toString(), QString()); + + emit object->argumentSignal(13, "Argument Scope", 9); + + QCOMPARE(object->property("test").toInt(), 13); + QCOMPARE(object->property("test2").toString(), QString("Argument Scope")); + + delete object; + } +} + +/* +Tests that "any" type passes through a synthesized signal parameter. This +is essentially a test of QDeclarativeMetaType::copy() +*/ +void tst_qdeclarativeecmascript::signalParameterTypes() +{ + QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + emit object->basicSignal(); + + QCOMPARE(object->property("intProperty").toInt(), 10); + QCOMPARE(object->property("realProperty").toReal(), 19.2); + QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255)); + QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255))); +} + +/* +Test that two JS objects for the same QObject compare as equal. +*/ +void tst_qdeclarativeecmascript::objectsCompareAsEqual() +{ + QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toBool(), true); + QCOMPARE(object->property("test2").toBool(), true); + QCOMPARE(object->property("test3").toBool(), true); + QCOMPARE(object->property("test4").toBool(), true); + QCOMPARE(object->property("test5").toBool(), true); +} + +/* +Confirm bindings and alias properties can coexist. + +Tests for a regression where the binding would not reevaluate. +*/ +void tst_qdeclarativeecmascript::aliasPropertyAndBinding() +{ + QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("c2").toInt(), 3); + QCOMPARE(object->property("c3").toInt(), 3); + + object->setProperty("c2", QVariant(19)); + + QCOMPARE(object->property("c2").toInt(), 19); + QCOMPARE(object->property("c3").toInt(), 19); +} + +void tst_qdeclarativeecmascript::dynamicCreation_data() +{ + QTest::addColumn<QString>("method"); + QTest::addColumn<QString>("createdName"); + + QTest::newRow("One") << "createOne" << "objectOne"; + QTest::newRow("Two") << "createTwo" << "objectTwo"; + QTest::newRow("Three") << "createThree" << "objectThree"; +} + +/* +Test using createQmlObject to dynamically generate an item +Also using createComponent is tested. +*/ +void tst_qdeclarativeecmascript::dynamicCreation() +{ + QFETCH(QString, method); + QFETCH(QString, createdName); + + QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create()); + QVERIFY(object != 0); + + QMetaObject::invokeMethod(object, method.toUtf8()); + QObject *created = object->objectProperty(); + QVERIFY(created); + QCOMPARE(created->objectName(), createdName); +} + +/* + Tests the destroy function +*/ +void tst_qdeclarativeecmascript::dynamicDestruction() +{ + QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml")); + QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create()); + QVERIFY(object != 0); + QDeclarativeGuard<QObject> createdQmlObject = 0; + + QMetaObject::invokeMethod(object, "create"); + createdQmlObject = object->objectProperty(); + QVERIFY(createdQmlObject); + QCOMPARE(createdQmlObject->objectName(), QString("emptyObject")); + + QMetaObject::invokeMethod(object, "killOther"); + QVERIFY(createdQmlObject); + QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion); + QVERIFY(createdQmlObject); + for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up + if (createdQmlObject) { + QTest::qWait(100); + QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion); + } + } + QVERIFY(!createdQmlObject); + + QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership); + QMetaObject::invokeMethod(object, "killMe"); + QVERIFY(object); + QTest::qWait(0); + QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion); + QVERIFY(!object); +} + +/* + tests that id.toString() works +*/ +void tst_qdeclarativeecmascript::objectToString() +{ + QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create()); + QVERIFY(object != 0); + QMetaObject::invokeMethod(object, "testToString"); + QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_")); + QVERIFY(object->stringProperty().endsWith(", \"objName\")")); +} + +/* +Tests bindings that indirectly cause their own deletion work. + +This test is best run under valgrind to ensure no invalid memory access occur. +*/ +void tst_qdeclarativeecmascript::selfDeletingBinding() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + object->setProperty("triggerDelete", true); + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + object->setProperty("triggerDelete", true); + } +} + +/* +Test that extended object properties can be accessed. + +This test a regression where this used to crash. The issue was specificially +for extended objects that did not include a synthesized meta object (so non-root +and no synthesiszed properties). +*/ +void tst_qdeclarativeecmascript::extendedObjectPropertyLookup() +{ + QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); +} + +/* +Test file/lineNumbers for binding/Script errors. +*/ +void tst_qdeclarativeecmascript::scriptErrors() +{ + QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml")); + QString url = component.url().toString(); + + QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\""; + QString warning2 = url + ":5: TypeError: Result of expression 'a' [undefined] is not an object."; + QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\""; + QString warning4 = url + ":10: TypeError: Result of expression 'a' [undefined] is not an object."; + QString warning5 = url + ":8: TypeError: Result of expression 'a' [undefined] is not an object."; + QString warning6 = url + ":7: Unable to assign [undefined] to int x"; + QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\""; + QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\""; + + QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData()); + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData()); + emit object->basicSignal(); + + QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData()); + emit object->anotherBasicSignal(); + + QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData()); + emit object->thirdBasicSignal(); +} + +/* +Test file/lineNumbers for inline functions. +*/ +void tst_qdeclarativeecmascript::functionErrors() +{ + QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml")); + QString url = component.url().toString(); + + QString warning = url + ":5: Error: Invalid write to global property \"a\""; + + QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); + + QObject *object = component.create(); + QVERIFY(object != 0); + delete object; +} + +/* +Test various errors that can occur when assigning a property from script +*/ +void tst_qdeclarativeecmascript::propertyAssignmentErrors() +{ + QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml")); + + QString url = component.url().toString(); + + QString warning1 = url + ":11:Error: Cannot assign [undefined] to int"; + QString warning2 = url + ":17:Error: Cannot assign QString to int"; + + QTest::ignoreMessage(QtDebugMsg, warning1.toLatin1().constData()); + QTest::ignoreMessage(QtDebugMsg, warning2.toLatin1().constData()); + + QObject *object = component.create(); + QVERIFY(object != 0); + + delete object; +} + +/* +Test bindings still work when the reeval is triggered from within +a signal script. +*/ +void tst_qdeclarativeecmascript::signalTriggeredBindings() +{ + QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("base").toReal(), 50.); + QCOMPARE(object->property("test1").toReal(), 50.); + QCOMPARE(object->property("test2").toReal(), 50.); + + object->basicSignal(); + + QCOMPARE(object->property("base").toReal(), 200.); + QCOMPARE(object->property("test1").toReal(), 200.); + QCOMPARE(object->property("test2").toReal(), 200.); + + object->argumentSignal(10, QString(), 10); + + QCOMPARE(object->property("base").toReal(), 400.); + QCOMPARE(object->property("test1").toReal(), 400.); + QCOMPARE(object->property("test2").toReal(), 400.); +} + +/* +Test that list properties can be iterated from ECMAScript +*/ +void tst_qdeclarativeecmascript::listProperties() +{ + QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toInt(), 21); + QCOMPARE(object->property("test2").toInt(), 2); + QCOMPARE(object->property("test3").toBool(), true); + QCOMPARE(object->property("test4").toBool(), true); +} + +void tst_qdeclarativeecmascript::exceptionClearsOnReeval() +{ + QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml")); + QString url = component.url().toString(); + + QString warning = url + ":4: TypeError: Result of expression 'objectProperty' [null] is not an object."; + + QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); + MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toBool(), false); + + MyQmlObject object2; + MyQmlObject object3; + object2.setObjectProperty(&object3); + object->setObjectProperty(&object2); + + QCOMPARE(object->property("test").toBool(), true); +} + +void tst_qdeclarativeecmascript::exceptionSlotProducesWarning() +{ + QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml")); + QString url = component.url().toString(); + + QString warning = component.url().toString() + ":6: Error: JS exception"; + + QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); + MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create()); + QVERIFY(object != 0); +} + +void tst_qdeclarativeecmascript::exceptionBindingProducesWarning() +{ + QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml")); + QString url = component.url().toString(); + + QString warning = component.url().toString() + ":5: Error: JS exception"; + + QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); + MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create()); + QVERIFY(object != 0); +} + +static int transientErrorsMsgCount = 0; +static void transientErrorsMsgHandler(QtMsgType, const char *) +{ + ++transientErrorsMsgCount; +} + +// Check that transient binding errors are not displayed +void tst_qdeclarativeecmascript::transientErrors() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml")); + + transientErrorsMsgCount = 0; + QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler); + + QObject *object = component.create(); + QVERIFY(object != 0); + + qInstallMsgHandler(old); + + QCOMPARE(transientErrorsMsgCount, 0); + } + + // One binding erroring multiple times, but then resolving + { + QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml")); + + transientErrorsMsgCount = 0; + QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler); + + QObject *object = component.create(); + QVERIFY(object != 0); + + qInstallMsgHandler(old); + + QCOMPARE(transientErrorsMsgCount, 0); + } +} + +// Check that errors during shutdown are minimized +void tst_qdeclarativeecmascript::shutdownErrors() +{ + QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + transientErrorsMsgCount = 0; + QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler); + + delete object; + + qInstallMsgHandler(old); + QCOMPARE(transientErrorsMsgCount, 0); +} + +void tst_qdeclarativeecmascript::compositePropertyType() +{ + QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml")); + QTest::ignoreMessage(QtDebugMsg, "hello world"); + QObject *object = qobject_cast<QObject *>(component.create()); + delete object; +} + +// QTBUG-5759 +void tst_qdeclarativeecmascript::jsObject() +{ + QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toInt(), 92); + + delete object; +} + +void tst_qdeclarativeecmascript::undefinedResetsProperty() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("resettableProperty").toInt(), 92); + + object->setProperty("setUndefined", true); + + QCOMPARE(object->property("resettableProperty").toInt(), 13); + + object->setProperty("setUndefined", false); + + QCOMPARE(object->property("resettableProperty").toInt(), 92); + + delete object; + } + { + QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("resettableProperty").toInt(), 19); + + QMetaObject::invokeMethod(object, "doReset"); + + QCOMPARE(object->property("resettableProperty").toInt(), 13); + + delete object; + } +} + +// QTBUG-6781 +void tst_qdeclarativeecmascript::bug1() +{ + QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toInt(), 14); + + object->setProperty("a", 11); + + QCOMPARE(object->property("test").toInt(), 3); + + object->setProperty("b", true); + + QCOMPARE(object->property("test").toInt(), 9); + + delete object; +} + +void tst_qdeclarativeecmascript::bug2() +{ + QDeclarativeComponent component(&engine); + component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl()); + + QObject *object = component.create(); + QVERIFY(object != 0); + + delete object; +} + +// Don't crash in createObject when the component has errors. +void tst_qdeclarativeecmascript::dynamicCreationCrash() +{ + QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create()); + QVERIFY(object != 0); + + QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready"); + QMetaObject::invokeMethod(object, "dontCrash"); + QObject *created = object->objectProperty(); + QVERIFY(created == 0); +} + +//QTBUG-9367 +void tst_qdeclarativeecmascript::regExpBug() +{ + QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]")); +} + +void tst_qdeclarativeecmascript::callQtInvokables() +{ + MyInvokableObject o; + + QDeclarativeEngine qmlengine; + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine); + QScriptEngine *engine = &ep->scriptEngine; + ep->globalClass->explicitSetProperty("object", ep->objectClass->newQObject(&o)); + + // Non-existent methods + o.reset(); + QCOMPARE(engine->evaluate("object.method_nonexistent()").isError(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), -1); + QCOMPARE(o.actuals().count(), 0); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_nonexistent(10, 11)").isError(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), -1); + QCOMPARE(o.actuals().count(), 0); + + // Insufficient arguments + o.reset(); + QCOMPARE(engine->evaluate("object.method_int()").isError(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), -1); + QCOMPARE(o.actuals().count(), 0); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_intint(10)").isError(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), -1); + QCOMPARE(o.actuals().count(), 0); + + // Excessive arguments + o.reset(); + QCOMPARE(engine->evaluate("object.method_int(10, 11)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 8); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(10)); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_intint(10, 11, 12)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 9); + QCOMPARE(o.actuals().count(), 2); + QCOMPARE(o.actuals().at(0), QVariant(10)); + QCOMPARE(o.actuals().at(1), QVariant(11)); + + // Test return types + o.reset(); + QCOMPARE(engine->evaluate("object.method_NoArgs()").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 0); + QCOMPARE(o.actuals().count(), 0); + + o.reset(); + QVERIFY(engine->evaluate("object.method_NoArgs_int()").strictlyEquals(QScriptValue(engine, 6))); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 1); + QCOMPARE(o.actuals().count(), 0); + + o.reset(); + QVERIFY(engine->evaluate("object.method_NoArgs_real()").strictlyEquals(QScriptValue(engine, 19.7))); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 2); + QCOMPARE(o.actuals().count(), 0); + + o.reset(); + { + QScriptValue ret = engine->evaluate("object.method_NoArgs_QPointF()"); + QCOMPARE(ret.toVariant(), QVariant(QPointF(123, 4.5))); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 3); + QCOMPARE(o.actuals().count(), 0); + } + + o.reset(); + { + QScriptValue ret = engine->evaluate("object.method_NoArgs_QObject()"); + QVERIFY(ret.isQObject()); + QCOMPARE(ret.toQObject(), (QObject *)&o); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 4); + QCOMPARE(o.actuals().count(), 0); + } + + o.reset(); + QCOMPARE(engine->evaluate("object.method_NoArgs_unknown()").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 5); + QCOMPARE(o.actuals().count(), 0); + + o.reset(); + { + QScriptValue ret = engine->evaluate("object.method_NoArgs_QScriptValue()"); + QVERIFY(ret.isString()); + QCOMPARE(ret.toString(), QString("Hello world")); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 6); + QCOMPARE(o.actuals().count(), 0); + } + + o.reset(); + QVERIFY(engine->evaluate("object.method_NoArgs_QVariant()").strictlyEquals(QScriptValue(engine, "QML rocks"))); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 7); + QCOMPARE(o.actuals().count(), 0); + + // Test arg types + o.reset(); + QCOMPARE(engine->evaluate("object.method_int(94)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 8); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(94)); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_int(\"94\")").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 8); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(94)); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_int(\"not a number\")").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 8); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(0)); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_int(null)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 8); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(0)); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_int(undefined)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 8); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(0)); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_int(object)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 8); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(0)); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_intint(122, 9)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 9); + QCOMPARE(o.actuals().count(), 2); + QCOMPARE(o.actuals().at(0), QVariant(122)); + QCOMPARE(o.actuals().at(1), QVariant(9)); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_real(94.3)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 10); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(94.3)); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_real(\"94.3\")").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 10); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(94.3)); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_real(\"not a number\")").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 10); + QCOMPARE(o.actuals().count(), 1); + QVERIFY(qIsNaN(o.actuals().at(0).toDouble())); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_real(null)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 10); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(0)); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_real(undefined)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 10); + QCOMPARE(o.actuals().count(), 1); + QVERIFY(qIsNaN(o.actuals().at(0).toDouble())); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_real(object)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 10); + QCOMPARE(o.actuals().count(), 1); + QVERIFY(qIsNaN(o.actuals().at(0).toDouble())); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QString(\"Hello world\")").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 11); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant("Hello world")); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QString(19)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 11); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant("19")); + + o.reset(); + { + QString expected = "MyInvokableObject(0x" + QString::number((intptr_t)&o, 16) + ")"; + QCOMPARE(engine->evaluate("object.method_QString(object)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 11); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(expected)); + } + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QString(null)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 11); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(QString())); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QString(undefined)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 11); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(QString())); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QPointF(0)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 12); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(QPointF())); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QPointF(null)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 12); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(QPointF())); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QPointF(undefined)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 12); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(QPointF())); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QPointF(object)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 12); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(QPointF())); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPointF())").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 12); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2))); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPoint())").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 12); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12))); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QObject(0)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 13); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0)); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QObject(\"Hello world\")").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 13); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0)); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QObject(null)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 13); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0)); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QObject(undefined)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 13); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0)); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QObject(object)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 13); + QCOMPARE(o.actuals().count(), 1); + QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o)); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QScriptValue(null)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 14); + QCOMPARE(o.actuals().count(), 1); + QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isNull()); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QScriptValue(undefined)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 14); + QCOMPARE(o.actuals().count(), 1); + QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isUndefined()); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QScriptValue(19)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 14); + QCOMPARE(o.actuals().count(), 1); + QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).strictlyEquals(QScriptValue(engine, 19))); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_QScriptValue([19, 20])").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 14); + QCOMPARE(o.actuals().count(), 1); + QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isArray()); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_intQScriptValue(4, null)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 15); + QCOMPARE(o.actuals().count(), 2); + QCOMPARE(o.actuals().at(0), QVariant(4)); + QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isNull()); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_intQScriptValue(8, undefined)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 15); + QCOMPARE(o.actuals().count(), 2); + QCOMPARE(o.actuals().at(0), QVariant(8)); + QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isUndefined()); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_intQScriptValue(3, 19)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 15); + QCOMPARE(o.actuals().count(), 2); + QCOMPARE(o.actuals().at(0), QVariant(3)); + QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).strictlyEquals(QScriptValue(engine, 19))); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_intQScriptValue(44, [19, 20])").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 15); + QCOMPARE(o.actuals().count(), 2); + QCOMPARE(o.actuals().at(0), QVariant(44)); + QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isArray()); + + // Test overloads - QML will always invoke the *last* method + o.reset(); + QCOMPARE(engine->evaluate("object.method_overload()").isError(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), -1); + QCOMPARE(o.actuals().count(), 0); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_overload(10)").isError(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), -1); + QCOMPARE(o.actuals().count(), 0); + + o.reset(); + QCOMPARE(engine->evaluate("object.method_overload(10, 11)").isUndefined(), true); + QCOMPARE(o.error(), false); + QCOMPARE(o.invoked(), 17); + QCOMPARE(o.actuals().count(), 2); + QCOMPARE(o.actuals().at(0), QVariant(10)); + QCOMPARE(o.actuals().at(1), QVariant(11)); +} + +// QTBUG-5675 +void tst_qdeclarativeecmascript::listToVariant() +{ + QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml")); + + MyQmlContainer container; + + QDeclarativeContext context(engine.rootContext()); + context.setContextObject(&container); + + QObject *object = component.create(&context); + QVERIFY(object != 0); + + QVariant v = object->property("test"); + QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>()); + QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container); + + delete object; +} + +// QTBUG-7957 +void tst_qdeclarativeecmascript::multiEngineObject() +{ + MyQmlObject obj; + obj.setStringProperty("Howdy planet"); + + QDeclarativeEngine e1; + e1.rootContext()->setContextProperty("thing", &obj); + QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml")); + + QDeclarativeEngine e2; + e2.rootContext()->setContextProperty("thing", &obj); + QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml")); + + QObject *o1 = c1.create(); + QObject *o2 = c2.create(); + + QCOMPARE(o1->property("test").toString(), QString("Howdy planet")); + QCOMPARE(o2->property("test").toString(), QString("Howdy planet")); + + delete o2; + delete o1; +} + +// Test that references to QObjects are cleanup when the object is destroyed +void tst_qdeclarativeecmascript::deletedObject() +{ + QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml")); + + QObject *object = component.create(); + + QCOMPARE(object->property("test1").toBool(), true); + QCOMPARE(object->property("test2").toBool(), true); + QCOMPARE(object->property("test3").toBool(), true); + QCOMPARE(object->property("test4").toBool(), true); + + delete object; +} + +void tst_qdeclarativeecmascript::attachedPropertyScope() +{ + QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml")); + + QObject *object = component.create(); + QVERIFY(object != 0); + + MyQmlAttachedObject *attached = + qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object)); + QVERIFY(attached != 0); + + QCOMPARE(object->property("value2").toInt(), 0); + + attached->emitMySignal(); + + QCOMPARE(object->property("value2").toInt(), 9); + + delete object; +} + +void tst_qdeclarativeecmascript::scriptConnect() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml")); + + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toBool(), false); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->property("test").toBool(), true); + + delete object; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml")); + + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toBool(), false); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->property("test").toBool(), true); + + delete object; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml")); + + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toBool(), false); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->property("test").toBool(), true); + + delete object; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml")); + + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->methodCalled(), false); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->methodCalled(), true); + + delete object; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml")); + + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->methodCalled(), false); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->methodCalled(), true); + + delete object; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml")); + + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toInt(), 0); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->property("test").toInt(), 2); + + delete object; + } +} + +void tst_qdeclarativeecmascript::scriptDisconnect() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml")); + + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toInt(), 0); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->property("test").toInt(), 1); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->property("test").toInt(), 2); + emit object->basicSignal(); + QCOMPARE(object->property("test").toInt(), 2); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->property("test").toInt(), 2); + + delete object; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml")); + + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toInt(), 0); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->property("test").toInt(), 1); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->property("test").toInt(), 2); + emit object->basicSignal(); + QCOMPARE(object->property("test").toInt(), 2); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->property("test").toInt(), 2); + + delete object; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml")); + + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toInt(), 0); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->property("test").toInt(), 1); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->property("test").toInt(), 2); + emit object->basicSignal(); + QCOMPARE(object->property("test").toInt(), 2); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->property("test").toInt(), 3); + + delete object; + } + { + QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml")); + + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toInt(), 0); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->property("test").toInt(), 1); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->property("test").toInt(), 2); + emit object->basicSignal(); + QCOMPARE(object->property("test").toInt(), 2); + emit object->argumentSignal(19, "Hello world!", 10.3); + QCOMPARE(object->property("test").toInt(), 3); + + delete object; + } +} + +class OwnershipObject : public QObject +{ + Q_OBJECT +public: + OwnershipObject() { object = new QObject; } + + QPointer<QObject> object; + +public slots: + QObject *getObject() { return object; } +}; + +void tst_qdeclarativeecmascript::ownership() +{ + OwnershipObject own; + QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext()); + context->setContextObject(&own); + + { + QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml")); + + QVERIFY(own.object != 0); + + QObject *object = component.create(context); + QDeclarativeEnginePrivate::getScriptEngine(&engine)->collectGarbage(); + + QCoreApplication::processEvents(QEventLoop::DeferredDeletion); + + QVERIFY(own.object == 0); + + delete object; + } + + own.object = new QObject(&own); + + { + QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml")); + + QVERIFY(own.object != 0); + + QObject *object = component.create(context); + QDeclarativeEnginePrivate::getScriptEngine(&engine)->collectGarbage(); + + QCoreApplication::processEvents(QEventLoop::DeferredDeletion); + + QVERIFY(own.object != 0); + + delete object; + } +} + +class QListQObjectMethodsObject : public QObject +{ + Q_OBJECT +public: + QListQObjectMethodsObject() { + m_objects.append(new MyQmlObject()); + m_objects.append(new MyQmlObject()); + } + + ~QListQObjectMethodsObject() { + qDeleteAll(m_objects); + } + +public slots: + QList<QObject *> getObjects() { return m_objects; } + +private: + QList<QObject *> m_objects; +}; + +// Tests that returning a QList<QObject*> from a method works +void tst_qdeclarativeecmascript::qlistqobjectMethods() +{ + QListQObjectMethodsObject obj; + QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext()); + context->setContextObject(&obj); + + QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml")); + + QObject *object = component.create(context); + + QCOMPARE(object->property("test").toInt(), 2); + QCOMPARE(object->property("test2").toBool(), true); + + delete object; +} + +// QTBUG-9205 +void tst_qdeclarativeecmascript::strictlyEquals() +{ + QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml")); + + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toBool(), true); + QCOMPARE(object->property("test2").toBool(), true); + QCOMPARE(object->property("test3").toBool(), true); + QCOMPARE(object->property("test4").toBool(), true); + QCOMPARE(object->property("test5").toBool(), true); + QCOMPARE(object->property("test6").toBool(), true); + QCOMPARE(object->property("test7").toBool(), true); + QCOMPARE(object->property("test8").toBool(), true); + + delete object; +} + +void tst_qdeclarativeecmascript::compiled() +{ + QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml")); + + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toReal(), qreal(15.7)); + QCOMPARE(object->property("test2").toReal(), qreal(-6.7)); + QCOMPARE(object->property("test3").toBool(), true); + QCOMPARE(object->property("test4").toBool(), false); + QCOMPARE(object->property("test5").toBool(), false); + QCOMPARE(object->property("test6").toBool(), true); + + QCOMPARE(object->property("test7").toInt(), 185); + QCOMPARE(object->property("test8").toInt(), 167); + QCOMPARE(object->property("test9").toBool(), true); + QCOMPARE(object->property("test10").toBool(), false); + QCOMPARE(object->property("test11").toBool(), false); + QCOMPARE(object->property("test12").toBool(), true); + + QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld")); + QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World")); + QCOMPARE(object->property("test15").toBool(), false); + QCOMPARE(object->property("test16").toBool(), true); + + QCOMPARE(object->property("test17").toInt(), 5); + QCOMPARE(object->property("test18").toReal(), qreal(176)); + QCOMPARE(object->property("test19").toInt(), 7); + QCOMPARE(object->property("test20").toReal(), qreal(6.7)); + QCOMPARE(object->property("test21").toString(), QLatin1String("6.7")); + QCOMPARE(object->property("test22").toString(), QLatin1String("!")); + QCOMPARE(object->property("test23").toBool(), true); + QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33)); + QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA)); + + delete object; +} + +// Test that numbers assigned in bindings as strings work consistently +void tst_qdeclarativeecmascript::numberAssignment() +{ + QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml")); + + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1"), QVariant((qreal)6.7)); + QCOMPARE(object->property("test2"), QVariant((qreal)6.7)); + QCOMPARE(object->property("test2"), QVariant((qreal)6.7)); + QCOMPARE(object->property("test3"), QVariant((qreal)6)); + QCOMPARE(object->property("test4"), QVariant((qreal)6)); + + QCOMPARE(object->property("test5"), QVariant((int)7)); + QCOMPARE(object->property("test6"), QVariant((int)7)); + QCOMPARE(object->property("test7"), QVariant((int)6)); + QCOMPARE(object->property("test8"), QVariant((int)6)); + + QCOMPARE(object->property("test9"), QVariant((unsigned int)7)); + QCOMPARE(object->property("test10"), QVariant((unsigned int)7)); + QCOMPARE(object->property("test11"), QVariant((unsigned int)6)); + QCOMPARE(object->property("test12"), QVariant((unsigned int)6)); + + delete object; +} + +// Test that assigning a null object works +// Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4 +void tst_qdeclarativeecmascript::nullObjectBinding() +{ + QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml")); + + QObject *object = component.create(); + QVERIFY(object != 0); + + QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0)); + + delete object; +} + +// Test that bindings don't evaluate once the engine has been destroyed +void tst_qdeclarativeecmascript::deletedEngine() +{ + QDeclarativeEngine *engine = new QDeclarativeEngine; + QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml")); + + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("a").toInt(), 39); + object->setProperty("b", QVariant(9)); + QCOMPARE(object->property("a").toInt(), 117); + + delete engine; + + QCOMPARE(object->property("a").toInt(), 117); + object->setProperty("b", QVariant(10)); + QCOMPARE(object->property("a").toInt(), 117); + + delete object; +} + +// Test the crashing part of QTBUG-9705 +void tst_qdeclarativeecmascript::libraryScriptAssert() +{ + QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml")); + + QObject *object = component.create(); + QVERIFY(object != 0); + + delete object; +} + +void tst_qdeclarativeecmascript::variantsAssignedUndefined() +{ + QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml")); + + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toInt(), 10); + QCOMPARE(object->property("test2").toInt(), 11); + + object->setProperty("runTest", true); + + QCOMPARE(object->property("test1"), QVariant()); + QCOMPARE(object->property("test2"), QVariant()); + + + delete object; +} + +void tst_qdeclarativeecmascript::qtbug_9792() +{ + QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml")); + + QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext()); + + MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context)); + QVERIFY(object != 0); + + QTest::ignoreMessage(QtDebugMsg, "Hello world!"); + object->basicSignal(); + + delete context; + + transientErrorsMsgCount = 0; + QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler); + + object->basicSignal(); + + qInstallMsgHandler(old); + + QCOMPARE(transientErrorsMsgCount, 0); + + delete object; +} + +// Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly +void tst_qdeclarativeecmascript::qtcreatorbug_1289() +{ + QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + + QObject *nested = qvariant_cast<QObject *>(o->property("object")); + QVERIFY(nested != 0); + + QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o); + + delete nested; + nested = qvariant_cast<QObject *>(o->property("object")); + QVERIFY(nested == 0); + + // If the bug is present, the next line will crash + delete o; +} + +// Test that we shut down without stupid warnings +void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml")); + + QObject *o = component.create(); + + transientErrorsMsgCount = 0; + QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler); + + delete o; + + qInstallMsgHandler(old); + + QCOMPARE(transientErrorsMsgCount, 0); + } + + + { + QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml")); + + QObject *o = component.create(); + + transientErrorsMsgCount = 0; + QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler); + + delete o; + + qInstallMsgHandler(old); + + QCOMPARE(transientErrorsMsgCount, 0); + } +} + +void tst_qdeclarativeecmascript::canAssignNullToQObject() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml")); + + MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(o != 0); + + QVERIFY(o->objectProperty() != 0); + + o->setProperty("runTest", true); + + QVERIFY(o->objectProperty() == 0); + + delete o; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml")); + + MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(o != 0); + + QVERIFY(o->objectProperty() == 0); + + delete o; + } +} + +void tst_qdeclarativeecmascript::functionAssignment() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml")); + + QString url = component.url().toString(); + QString warning = url + ":4: Unable to assign a function to a property."; + QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); + + MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(o != 0); + + QVERIFY(!o->property("a").isValid()); + + delete o; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml")); + + MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(o != 0); + + QVERIFY(!o->property("a").isValid()); + + QString url = component.url().toString(); + QString warning = url + ":10: Error: Cannot assign a function to a property."; + QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); + + o->setProperty("runTest", true); + + QVERIFY(!o->property("a").isValid()); + + delete o; + } +} + +void tst_qdeclarativeecmascript::eval() +{ + QDeclarativeComponent component(&engine, TEST_FILE("eval.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("test1").toBool(), true); + QCOMPARE(o->property("test2").toBool(), true); + QCOMPARE(o->property("test3").toBool(), true); + QCOMPARE(o->property("test4").toBool(), true); + QCOMPARE(o->property("test5").toBool(), true); + + delete o; +} + +void tst_qdeclarativeecmascript::function() +{ + QDeclarativeComponent component(&engine, TEST_FILE("function.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("test1").toBool(), true); + QCOMPARE(o->property("test2").toBool(), true); + QCOMPARE(o->property("test3").toBool(), true); + + delete o; +} + +#define TRY_WAIT(expr) \ + do { \ + for (int ii = 0; ii < 6; ++ii) { \ + if ((expr)) break; \ + QTest::qWait(50); \ + } \ + QVERIFY((expr)); \ + } while (false) + +// Test the "Qt.include" method +void tst_qdeclarativeecmascript::include() +{ + // Non-library relative include + { + QDeclarativeComponent component(&engine, TEST_FILE("include.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("test0").toInt(), 99); + QCOMPARE(o->property("test1").toBool(), true); + QCOMPARE(o->property("test2").toBool(), true); + QCOMPARE(o->property("test2_1").toBool(), true); + QCOMPARE(o->property("test3").toBool(), true); + QCOMPARE(o->property("test3_1").toBool(), true); + + delete o; + } + + // Library relative include + { + QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("test0").toInt(), 99); + QCOMPARE(o->property("test1").toBool(), true); + QCOMPARE(o->property("test2").toBool(), true); + QCOMPARE(o->property("test2_1").toBool(), true); + QCOMPARE(o->property("test3").toBool(), true); + QCOMPARE(o->property("test3_1").toBool(), true); + + delete o; + } + + // Callback + { + QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("test1").toBool(), true); + QCOMPARE(o->property("test2").toBool(), true); + QCOMPARE(o->property("test3").toBool(), true); + QCOMPARE(o->property("test4").toBool(), true); + QCOMPARE(o->property("test5").toBool(), true); + QCOMPARE(o->property("test6").toBool(), true); + + delete o; + } + + // Including file with ".pragma library" + { + QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + QCOMPARE(o->property("test1").toInt(), 100); + + delete o; + } + + // Remote - success + { + TestHTTPServer server(8111); + QVERIFY(server.isValid()); + server.serveDirectory(SRCDIR "/data"); + + QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + + TRY_WAIT(o->property("done").toBool() == true); + TRY_WAIT(o->property("done2").toBool() == true); + + QCOMPARE(o->property("test1").toBool(), true); + QCOMPARE(o->property("test2").toBool(), true); + QCOMPARE(o->property("test3").toBool(), true); + QCOMPARE(o->property("test4").toBool(), true); + QCOMPARE(o->property("test5").toBool(), true); + + QCOMPARE(o->property("test6").toBool(), true); + QCOMPARE(o->property("test7").toBool(), true); + QCOMPARE(o->property("test8").toBool(), true); + QCOMPARE(o->property("test9").toBool(), true); + QCOMPARE(o->property("test10").toBool(), true); + + delete o; + } + + // Remote - error + { + TestHTTPServer server(8111); + QVERIFY(server.isValid()); + server.serveDirectory(SRCDIR "/data"); + + QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + + TRY_WAIT(o->property("done").toBool() == true); + + QCOMPARE(o->property("test1").toBool(), true); + QCOMPARE(o->property("test2").toBool(), true); + QCOMPARE(o->property("test3").toBool(), true); + + delete o; + } +} + +void tst_qdeclarativeecmascript::qtbug_10696() +{ + QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + delete o; +} + +QTEST_MAIN(tst_qdeclarativeecmascript) + +#include "tst_qdeclarativeecmascript.moc" |