~feng-kylin/unity8/fix-lp1413791

« back to all changes in this revision

Viewing changes to tests/qmltests/Stages/tst_SpreadDelegate.qml

  • Committer: Michael Zanetti
  • Date: 2015-06-17 12:14:27 UTC
  • mfrom: (1595.1.214 unity8)
  • mto: (1595.1.232 unity8)
  • mto: This revision was merged to the branch mainline in revision 1608.
  • Revision ID: michael.zanetti@canonical.com-20150617121427-lgc70azrbtsanejb
merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright 2014 Canonical Ltd.
 
2
 * Copyright 2014-2015 Canonical Ltd.
3
3
 *
4
4
 * This program is free software; you can redistribute it and/or modify
5
5
 * it under the terms of the GNU General Public License as published by
26
26
Rectangle {
27
27
    color: "red"
28
28
    id: root
29
 
    width: units.gu(70)
30
 
    height: units.gu(70)
 
29
    width: fakeShell.shortestDimension + controls.width
 
30
    height: fakeShell.longestDimension
31
31
 
32
 
    Component.onCompleted: {
33
 
        root.fakeApplication = ApplicationManager.startApplication("gallery-app");
34
 
    }
35
32
    property QtObject fakeApplication: null
36
33
 
37
 
    Component {
38
 
        id: spreadDelegateComponent
39
 
        SpreadDelegate {
40
 
            anchors.fill: parent
41
 
            swipeToCloseEnabled: swipeToCloseCheckbox.checked
42
 
            closeable: closeableCheckbox.checked
43
 
            application: fakeApplication
44
 
        }
45
 
    }
46
 
    Loader {
47
 
        id: spreadDelegateLoader
48
 
        anchors {
49
 
            top: parent.top
50
 
            bottom: parent.bottom
51
 
            left: parent.left
52
 
        }
53
 
        width: units.gu(40)
54
 
        sourceComponent: spreadDelegateComponent
 
34
    Item {
 
35
        id: fakeShell
 
36
 
 
37
        readonly property real shortestDimension: units.gu(40)
 
38
        readonly property real longestDimension: units.gu(70)
 
39
 
 
40
        width: landscape ? longestDimension : shortestDimension
 
41
        height: landscape ? shortestDimension : longestDimension
 
42
 
 
43
        x: landscape ? (height - width) / 2 : 0
 
44
        y: landscape ? (width - height) / 2 : 0
 
45
 
 
46
        property bool landscape: orientationAngle == 90 || orientationAngle == 270
 
47
        property int orientationAngle: shellOrientationAngleSelector.value
 
48
 
 
49
        rotation: orientationAngle
 
50
 
 
51
        Loader {
 
52
            id: spreadDelegateLoader
 
53
            width: parent.width
 
54
            height: parent.height
 
55
 
 
56
            active: false
 
57
            property bool itemDestroyed: false
 
58
            sourceComponent: SpreadDelegate {
 
59
                anchors.fill: parent
 
60
                swipeToCloseEnabled: swipeToCloseCheckbox.checked
 
61
                closeable: closeableCheckbox.checked
 
62
                application: fakeApplication
 
63
                shellOrientationAngle: shellOrientationAngleSelector.value
 
64
                shellOrientation: {
 
65
                    switch (shellOrientationAngleSelector.value) {
 
66
                    case 0:
 
67
                        return Qt.PortraitOrientation;
 
68
                    case 90:
 
69
                        return Qt.InvertedLandscapeOrientation;
 
70
                    case 180:
 
71
                        return Qt.InvertedPortraitOrientation;
 
72
                    default: // 270
 
73
                        return Qt.LandscapeOrientation;
 
74
                    }
 
75
                }
 
76
                shellPrimaryOrientation: Qt.PortraitOrientation
 
77
                nativeOrientation: Qt.PortraitOrientation
 
78
                maximizedAppTopMargin: units.gu(3)
 
79
                Component.onDestruction: {
 
80
                    spreadDelegateLoader.itemDestroyed = true;
 
81
                }
 
82
                Component.onCompleted: {
 
83
                    spreadDelegateLoader.itemDestroyed = false;
 
84
                }
 
85
            }
 
86
        }
55
87
    }
56
88
 
57
89
    Rectangle {
 
90
        id: controls
58
91
        color: "white"
 
92
        x: fakeShell.shortestDimension
 
93
        width: units.gu(30)
59
94
        anchors {
60
95
            top: parent.top
61
96
            bottom: parent.bottom
62
 
            left: spreadDelegateLoader.right
63
 
            right: parent.right
64
97
        }
65
98
 
66
99
        Column {
67
100
            anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
68
101
            spacing: units.gu(1)
 
102
            Button {
 
103
                id: loadWithWeatherApp
 
104
                text: "Load with ubuntu-weather-app"
 
105
                onClicked: { testCase.restartWithApp("ubuntu-weather-app"); }
 
106
            }
 
107
            Button {
 
108
                id: loadWithGalleryApp
 
109
                text: "Load with gallery-app"
 
110
                onClicked: { testCase.restartWithApp("gallery-app"); }
 
111
            }
69
112
            Row {
70
113
                anchors { left: parent.left; right: parent.right }
71
114
                CheckBox { id: swipeToCloseCheckbox; checked: false; }
76
119
                CheckBox { id: closeableCheckbox; checked: false }
77
120
                Label { text: "closeable" }
78
121
            }
 
122
            ListItem.ItemSelector {
 
123
                id: shellOrientationAngleSelector
 
124
                anchors { left: parent.left; right: parent.right }
 
125
                text: "shellOrientationAngle"
 
126
                model: ["0", "90", "180", "270"]
 
127
                property int value: selectedIndex * 90
 
128
            }
 
129
            Button {
 
130
                text: "matchShellOrientation()"
 
131
                onClicked: { spreadDelegateLoader.item.matchShellOrientation(); }
 
132
            }
 
133
            Button {
 
134
                text: "animateToShellOrientation()"
 
135
                onClicked: { spreadDelegateLoader.item.animateToShellOrientation(); }
 
136
            }
79
137
        }
80
138
    }
81
139
 
91
149
        }
92
150
 
93
151
        property var dragArea
 
152
        property Item spreadDelegate: spreadDelegateLoader.item
94
153
 
95
154
        function init() {
96
 
            dragArea = findInvisibleChild(spreadDelegateLoader.item, "dragArea");
 
155
        }
 
156
 
 
157
        function cleanup() {
 
158
            unloadSpreadDelegate();
 
159
            spyClosedSignal.clear();
 
160
            shellOrientationAngleSelector.selectedIndex = 0;
 
161
            ApplicationManager.stopApplication(root.fakeApplication.appId);
 
162
            root.fakeApplication = null;
 
163
        }
 
164
 
 
165
        function restartWithApp(appId) {
 
166
            if (spreadDelegateLoader.active) {
 
167
                unloadSpreadDelegate();
 
168
            }
 
169
            if (root.fakeApplication) {
 
170
                ApplicationManager.stopApplication(root.fakeApplication.appId);
 
171
            }
 
172
 
 
173
            root.fakeApplication = ApplicationManager.startApplication(appId);
 
174
            spreadDelegateLoader.active = true;
 
175
            tryCompare(spreadDelegateLoader, "status", Loader.Ready);
 
176
 
 
177
            dragArea = findInvisibleChild(spreadDelegate, "dragArea");
97
178
            dragArea.__dateTime = fakeDateTime;
98
179
        }
99
180
 
100
 
        function cleanup() {
101
 
            // reload our test subject to get it in a fresh state once again
 
181
        function unloadSpreadDelegate() {
102
182
            spreadDelegateLoader.active = false;
103
 
            spreadDelegateLoader.active = true;
 
183
            tryCompare(spreadDelegateLoader, "status", Loader.Null);
 
184
            tryCompare(spreadDelegateLoader, "item", null);
 
185
            // Loader.status might be Loader.Null and Loader.item might be null but the Loader
 
186
            // item might still be alive. So if we set Loader.active back to true
 
187
            // again right now we will get the very same Shell instance back. So no reload
 
188
            // actually took place. Likely because Loader waits until the next event loop
 
189
            // iteration to do its work. So to ensure the reload, we will wait until the
 
190
            // Shell instance gets destroyed.
 
191
            tryCompare(spreadDelegateLoader, "itemDestroyed", true);
104
192
 
105
 
            spyClosedSignal.clear();
106
193
        }
107
194
 
108
195
        function test_swipeToClose_data() {
119
206
        }
120
207
 
121
208
        function test_swipeToClose(data) {
122
 
            var appWindowWithShadow = findChild(spreadDelegateLoader.item, "appWindowWithShadow");
 
209
            loadWithGalleryApp.clicked();
 
210
            var displacedAppWindowWithShadow = findChild(spreadDelegateLoader.item, "displacedAppWindowWithShadow");
123
211
 
124
 
            verify(appWindowWithShadow.y === 0);
 
212
            verify(displacedAppWindowWithShadow.y === 0);
125
213
 
126
214
            swipeToCloseCheckbox.checked = data.swipeToClose;
127
215
            closeableCheckbox.checked = data.closeable;
135
223
                true /* beginTouch */, false /* endTouch */, dragArea.minSpeedToClose * 1.1 /* speed */);
136
224
 
137
225
            if (data.swipeToClose) {
138
 
                verify(appWindowWithShadow.y < 0);
 
226
                verify(displacedAppWindowWithShadow.y < 0);
139
227
                var threshold = findChild(spreadDelegateLoader.item, "dragArea").threshold
140
228
                if (data.closeable) {
141
229
                    // Verify that the delegate started moving exactly "threshold" after the finger movement
142
230
                    // and did not jump up to the finger, but lags the threshold behind
143
 
                    compare(Math.abs(Math.abs(appWindowWithShadow.y) - dragDistance), threshold);
 
231
                    compare(Math.abs(Math.abs(displacedAppWindowWithShadow.y) - dragDistance), threshold);
144
232
                } else {
145
 
                    verify(Math.abs(Math.abs(appWindowWithShadow.y) - dragDistance) > threshold);
 
233
                    verify(Math.abs(Math.abs(displacedAppWindowWithShadow.y) - dragDistance) > threshold);
146
234
                }
147
235
 
148
236
                touchRelease(spreadDelegateLoader.item, touchX, toY - units.gu(1));
153
241
                    verify(spyClosedSignal.count === 1);
154
242
                } else {
155
243
                    verify(spyClosedSignal.count === 0);
156
 
                    tryCompare(appWindowWithShadow, "y", 0);
 
244
                    tryCompare(displacedAppWindowWithShadow, "y", 0);
157
245
                }
158
246
 
159
247
            } else {
160
 
                verify(appWindowWithShadow.y === 0);
 
248
                verify(displacedAppWindowWithShadow.y === 0);
161
249
 
162
250
                touchRelease(spreadDelegateLoader.item, touchX, toY);
163
251
            }
164
252
        }
165
253
 
 
254
        function test_loadingLandscapeOnlyAppWhenShellInPortrait() {
 
255
            loadWithWeatherApp.clicked();
 
256
 
 
257
            var appWindow = findChild(spreadDelegate, "appWindow_ubuntu-weather-app");
 
258
            verify(appWindow);
 
259
 
 
260
            // It must have landscape dimensions as it does not support portrait
 
261
            tryCompare(appWindow, "width", fakeShell.height);
 
262
            tryCompare(appWindow, "height", fakeShell.width - spreadDelegate.maximizedAppTopMargin);
 
263
        }
 
264
 
 
265
        function test_keepsSceneTransformationWhenShellRotates_data() {
 
266
            return [
 
267
                {tag: "0", selectedIndex: 0},
 
268
                {tag: "90", selectedIndex: 1},
 
269
                {tag: "180", selectedIndex: 2},
 
270
                {tag: "270", selectedIndex: 3}
 
271
            ];
 
272
        }
 
273
        function test_keepsSceneTransformationWhenShellRotates(data) {
 
274
            loadWithGalleryApp.clicked();
 
275
 
 
276
            var appWindowWithShadow = findChild(spreadDelegate, "appWindowWithShadow");
 
277
            verify(appWindowWithShadow);
 
278
 
 
279
            // Wait until it reaches the state we are interested on.
 
280
            // It begins with "startingUp"
 
281
            tryCompare(appWindowWithShadow, "state", "keepSceneRotation");
 
282
 
 
283
            shellOrientationAngleSelector.selectedIndex = data.selectedIndex;
 
284
 
 
285
            // must keep same aspect ratio
 
286
            compare(appWindowWithShadow.width, fakeShell.shortestDimension);
 
287
            compare(appWindowWithShadow.height, fakeShell.longestDimension);
 
288
 
 
289
 
 
290
            // and scene transformation must be the identity (ie, no rotation or translation)
 
291
            var pointInDelegateCoords = appWindowWithShadow.mapToItem(root, 0, 0);
 
292
            compare(pointInDelegateCoords.x, 0);
 
293
            compare(pointInDelegateCoords.y, 0);
 
294
 
 
295
            pointInDelegateCoords = appWindowWithShadow.mapToItem(root,
 
296
                    fakeShell.shortestDimension, fakeShell.longestDimension);
 
297
            compare(pointInDelegateCoords.x, fakeShell.shortestDimension);
 
298
            compare(pointInDelegateCoords.y, fakeShell.longestDimension);
 
299
        }
 
300
 
166
301
        function waitForCloseAnimationToFinish() {
167
302
            var closeAnimation = findInvisibleChild(spreadDelegateLoader.item, "closeAnimation");
168
303
            wait(closeAnimation.duration * 1.5);