@@ -1,5 +1,5 @@
2− * Copyright 2013 Canonical Ltd.
2+ * Copyright 2013-2014 Canonical Ltd.
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -14,95 +14,106 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17−import QtQuick 2.0
17+import QtQuick 2.1
18+import QtQuick.Layouts 1.1
18import QtTest 1.0
19import QtTest 1.0
19import Unity.Test 0.1 as UT
20import Unity.Test 0.1 as UT
20−import Ubuntu.Components 0.1 as UC
21+import Ubuntu.Components 0.1
22+import Unity.Indicators 0.1 as Indicators
21import Ubuntu.Telephony 0.1 as Telephony
23import Ubuntu.Telephony 0.1 as Telephony
23import "../../../qml/Panel"
24import "../../../qml/Panel"
26− This tests the Panel component using a fake model to stage data in the indicators
27+ id: root
27− A view will show with indicators at the top, as does in the shell. This can be controlled
32− width: units.gu(40)
28+ width: units.gu(100)
33− height: units.gu(80)
29+ height: units.gu(71)
41− height: parent.height - row.height
42− fullscreenMode: false
44− indicators {
32+ property string indicatorProfile: "phone"
46− panelHeight: units.gu(5)
52− property real panelAndSeparatorHeight: panel.indicators.panelHeight + units.dp(2)
34+ RowLayout {
53− }
35+ anchors.fill: parent
36+ anchors.margins: units.gu(1)
40+ Layout.fillWidth: true
41+ Layout.fillHeight: true
56− Row {
43+ id: itemArea
57− id: row
44+ color: "blue"
65− UC.Button {
46+ Panel {
66− text: panel.indicators.shown ? "Hide" : "Show"
47+ id: panel
67− anchors {
48+ anchors.fill: parent
68− top: parent.top
49+ indicators {
69− bottom: parent.bottom
50+ width: parent.width > units.gu(60) ? units.gu(40) : parent.width
51+ indicatorsModel: root.indicatorsModel
54+ property real panelAndSeparatorHeight: panel.indicators.minimizedPanelHeight + units.dp(2)
71− width: parent.width/3
56+ }
59+ Layout.alignment: Qt.AlignTop
60+ Layout.fillWidth: false
63+ Layout.fillWidth: true
64+ text: panel.indicators.shown ? "Hide" : "Show"
73− onClicked: {
65+ onClicked: {
74− if (panel.indicators.shown) {
66+ if (panel.indicators.shown) {
75− panel.indicators.hide();
67+ panel.indicators.hide();
77− panel.indicators.show();
69+ panel.indicators.show();
82− UC.Button {
74+ Button {
83− text: panel.fullscreenMode ? "Maximize" : "FullScreen"
75+ text: panel.fullscreenMode ? "Maximize" : "FullScreen"
84− anchors {
76+ Layout.fillWidth: true
85− top: parent.top
77+ onClicked: panel.fullscreenMode = !panel.fullscreenMode
86− bottom: parent.bottom
88− width: parent.width/3
90− onClicked: panel.fullscreenMode = !panel.fullscreenMode
80+ Button {
81+ Layout.fillWidth: true
82+ text: callManager.hasCalls ? "Called" : "No Calls"
84+ if (callManager.foregroundCall) {
85+ callManager.foregroundCall = null;
87+ callManager.foregroundCall = phoneCall;
93− UC.Button {
92+ Rectangle {
94− text: callManager.hasCalls ? "Called" : "No Calls"
93+ Layout.preferredHeight: units.dp(1);
95− anchors {
94+ Layout.fillWidth: true;
96− top: parent.top
95+ color: "black"
97− bottom: parent.bottom
99− width: parent.width/3
101− onClicked: {
98+ Repeater {
102− if (callManager.foregroundCall) {
99+ model: root.originalModelData
103− callManager.foregroundCall = null;
100+ RowLayout {
104− } else {
101+ CheckBox {
105− callManager.foregroundCall = phoneCall;
102+ checked: true
103+ onCheckedChanged: checked ? insertIndicator(index) : removeIndicator(index);
106+ Layout.fillWidth: true
107+ text: modelData["identifier"]
112+ onCheckedChanged: setIndicatorVisible(index, checked);
@@ -118,13 +129,12 @@ Item {
118 when: windowShown
129 when: windowShown
120 function init() {
131 function init() {
121− panel.indicators.initialise();
122 panel.fullscreenMode = false;
132 panel.fullscreenMode = false;
133+ callManager.foregroundCall = null;
124 panel.indicators.hide();
135 panel.indicators.hide();
125 // Wait for animation to complete
136 // Wait for animation to complete
126 tryCompare(panel.indicators.hideAnimation, "running", false);
137 tryCompare(panel.indicators.hideAnimation, "running", false);
127− callManager.foregroundCall = null;
129 // Wait for the indicators to get into position.
139 // Wait for the indicators to get into position.
130 // (switches between normal and fullscreen modes are animated)
140 // (switches between normal and fullscreen modes are animated)
@@ -133,100 +143,21 @@ Item {
135 function get_indicator_item(index) {
145 function get_indicator_item(index) {
136− var indicatorRow = findChild(panel.indicators, "indicatorRow");
146+ var indicatorItem = findChild(panel, root.originalModelData[index]["identifier"]+"-panelItem");
137− verify(indicatorRow !== null);
139− return findChild(indicatorRow.row, "item" + index);
142− function get_indicator_item_position(index) {
143− var indicatorRow = findChild(panel.indicators, "indicatorRow");
144− verify(indicatorRow !== null);
146− var indicatorItem = get_indicator_item(index);
147 verify(indicatorItem !== null);
147 verify(indicatorItem !== null);
149− return panel.mapFromItem(indicatorItem, indicatorItem.width/2, indicatorItem.height/2);
149+ return indicatorItem;
152− // Pressing on the indicator panel should activate the indicator hints
153− // and expose a portion of the conent.
154− function test_hint() {
155− var indicatorItemCoord = get_indicator_item_position(0);
157− touchPress(panel, indicatorItemCoord.x, panel.indicators.panelHeight / 2);
159− // hint animation should be run, meaning that indicators will move downwards
160− // by hintValue pixels without any drag taking place
161− tryCompareFunction(function() { return panel.indicators.height },
162− panel.indicators.panelHeight + panel.indicators.hintValue);
163− tryCompare(panel.indicators, "partiallyOpened", true);
164− tryCompare(panel.indicators, "fullyOpened", false);
166− touchRelease(panel, indicatorItemCoord.x, panel.indicators.panelHeight/2);
169− // Pressing on the top edge of the screen should have no effect if the panel
170− // is hidden (fullscreen), which is the case when a fullscreen app is being shown
171− function test_noHintOnFullscreenMode() {
172− panel.fullscreenMode = true;
173− // Wait for the indicators to get into position.
174− // (switches between normal and fullscreen modes are animated)
175− var indicatorArea = findChild(panel, "indicatorArea");
176− tryCompare(indicatorArea, "y", -panel.panelHeight);
178− var indicatorItemCoord = get_indicator_item_position(0);
180− touchPress(panel, indicatorItemCoord.x, panel.indicators.panelHeight / 2);
182− // Give some time for a hint animation to change things, if any
185− // no hint animation when fullscreen
186− compare(panel.indicators.partiallyOpened, false,
187− "Indicator should not be partially opened when panel is pressed in" +
189− compare(panel.indicators.fullyOpened, false, "Indicator should not be partially" +
190− " opened when panel is pressed in fullscreenmode");
192− touchRelease(panel, indicatorItemCoord.x, panel.panelHeight/2);
195− // Pressing on the top edge of the indicator should have no effect if the panel
196− // has an active call
197− function test_noHintOnActiveCall() {
198− callManager.foregroundCall = phoneCall;
200− var indicatorItemCoord = get_indicator_item_position(0);
202− touchPress(panel, indicatorItemCoord.x, panel.callHint.height + panel.indicators.panelHeight / 2);
204− // Give some time for a hint animation to change things, if any
207− // no hint animation when fullscreen
208− compare(panel.indicators.partiallyOpened, false,
209− "Indicator should not be partially opened when panel is pressed in" +
211− compare(panel.indicators.fullyOpened, false, "Indicator should not be partially" +
212− " opened when panel is pressed in fullscreenmode");
214− touchRelease(panel, indicatorItemCoord.x, panel.panelHeight/2);
217 function test_drag_show_data() {
152 function test_drag_show_data() {
219− { tag: "pinned", fullscreenFlag: false, alreadyOpen: false, call: null,
154+ { tag: "pinned", fullscreen: false, call: null,
220 indicatorY: 0 },
155 indicatorY: 0 },
221− { tag: "fullscreen", fullscreenFlag: true, alreadyOpen: false, call: null,
156+ { tag: "fullscreen", fullscreen: true, call: null,
222 indicatorY: -panel.panelAndSeparatorHeight },
157 indicatorY: -panel.panelAndSeparatorHeight },
223− { tag: "pinned-alreadyOpen", fullscreenFlag: false, alreadyOpen: true, call: null,
225− { tag: "fullscreen-alreadyOpen", fullscreenFlag: true, alreadyOpen: true, call: null,
227− { tag: "pinned-callActive", fullscreenFlag: false, alreadyOpen: false, call: phoneCall,
158+ { tag: "pinned-callActive", fullscreen: false, call: phoneCall,
228 indicatorY: 0},
159 indicatorY: 0},
229− { tag: "fullscreen-callActive", fullscreenFlag: true, alreadyOpen: false, call: phoneCall,
160+ { tag: "fullscreen-callActive", fullscreen: true, call: phoneCall,
230 indicatorY: -panel.panelAndSeparatorHeight }
161 indicatorY: -panel.panelAndSeparatorHeight }
@@ -234,16 +165,12 @@ Item {
234 // Dragging from a indicator item in the panel will gradually expose the
165 // Dragging from a indicator item in the panel will gradually expose the
235 // indicators, first by running the hint animation, then after dragging down will
166 // indicators, first by running the hint animation, then after dragging down will
236 // expose more of the panel, binding it to the selected indicator and opening it's menu.
167 // expose more of the panel, binding it to the selected indicator and opening it's menu.
168+ // Tested from first Y pixel to check for swipe from offscreen.
237 function test_drag_show(data) {
169 function test_drag_show(data) {
238− panel.fullscreenMode = data.fullscreenFlag;
170+ panel.fullscreenMode = data.fullscreen;
239 callManager.foregroundCall = data.call;
171 callManager.foregroundCall = data.call;
241− if (data.alreadyOpen) {
242− panel.indicators.show();
243− tryCompare(panel.indicators, "fullyOpened", true);
246− var indicatorRow = findChild(panel.indicators, "indicatorRow");
173+ var indicatorRow = findChild(panel.indicators, "indicatorItemRow");
247 verify(indicatorRow !== null);
174 verify(indicatorRow !== null);
249 var menuContent = findChild(panel.indicators, "menuContent");
176 var menuContent = findChild(panel.indicators, "menuContent");
@@ -256,25 +183,16 @@ Item {
256 // (switches between normal and fullscreen modes are animated)
183 // (switches between normal and fullscreen modes are animated)
257 tryCompareFunction(function() { return indicatorArea.y }, data.indicatorY);
184 tryCompareFunction(function() { return indicatorArea.y }, data.indicatorY);
259− // do this for each indicator item
186+ for (var i = 0; i < root.originalModelData.length; i++) {
260− for (var i = 0; i < indicatorRow.row.count; i++) {
262 var indicatorItem = get_indicator_item(i);
187 var indicatorItem = get_indicator_item(i);
263− verify(indicatorItem !== null);
265− if (!indicatorItem.visible)
189+ var startXPosition = root.mapFromItem(indicatorItem, indicatorItem.width / 2, 0).x;
266− continue;
190+ var startYPosition = root.mapFromItem(panel, 0, 0).y;
268− var indicatorItemCoord = get_indicator_item_position(i);
271− indicatorItemCoord.x, panel.indicators.panelHeight / 2);
273− // 1) Drag the mouse down
274 touchFlick(panel,
192 touchFlick(panel,
275− indicatorItemCoord.x, panel.indicators.panelHeight / 2,
193+ startXPosition, startYPosition,
276− indicatorItemCoord.x, panel.height,
194+ startXPosition, panel.height,
277− false /* beginTouch */, false /* endTouch */);
195+ true /* beginTouch */, false /* endTouch */, units.gu(5), 15);
279 // Indicators height should follow the drag, and therefore increase accordingly.
197 // Indicators height should follow the drag, and therefore increase accordingly.
280 // They should be at least half-way through the screen
198 // They should be at least half-way through the screen
@@ -282,56 +200,109 @@ Item {
282 function() {return panel.indicators.height >= panel.height * 0.5},
200 function() {return panel.indicators.height >= panel.height * 0.5},
285− touchRelease(panel, indicatorItemCoord.x, panel.height);
203+ touchRelease(panel, startXPosition, panel.height);
287− compare(indicatorRow.currentItem, indicatorItem,
288− "Incorrect item activated at position " + i);
205+ compare(indicatorRow.currentItemIndex, i, "Indicator item should be activated at position " + i);
289− compare(menuContent.currentMenuIndex, i, "Menu conetent should be enabled for item at position " + i);
206+ compare(menuContent.currentMenuIndex, i, "Menu conetent should be activated for item at position " + i);
291 // init for next indicatorItem
208 // init for next indicatorItem
292− if (!data.alreadyOpen) {
293− panel.indicators.hide();
209+ panel.indicators.hide();
294− tryCompare(panel.indicators.hideAnimation, "running", false);
210+ tryCompare(panel.indicators.hideAnimation, "running", false);
295− tryCompare(panel.indicators, "state", "initial");
211+ tryCompare(panel.indicators, "state", "initial");
300− // Test the vertical velocity check when flicking the indicators open at an angle.
215+ function test_drag_hide_data() {
301− // If the vertical velocity is above a specific point, we shouldnt change active indicators
216+ return [
302− // if the x position changes
217+ { tag: "pinned", fullscreen: false, call: null,
303− function test_vertical_velocity_detector() {
218+ indicatorY: 0 },
219+ { tag: "fullscreen", fullscreen: true, call: null,
220+ indicatorY: -panel.panelAndSeparatorHeight },
221+ { tag: "pinned-callActive", fullscreen: false, call: phoneCall,
223+ { tag: "fullscreen-callActive", fullscreen: true, call: phoneCall,
224+ indicatorY: -panel.panelAndSeparatorHeight }
228+ // Dragging the shown indicators up from bottom of panel will hide the indicators
229+ // Tested from last Y pixel to check for swipe from offscreen.
230+ function test_drag_hide(data) {
304− panel.fullscreenMode = false;
231+ panel.fullscreenMode = data.fullscreen;
232+ callManager.foregroundCall = data.call;
306− var indicatorRow = findChild(panel.indicators, "indicatorRow");
234+ var indicatorRow = findChild(panel.indicators, "indicatorItemRow");
307 verify(indicatorRow !== null);
235 verify(indicatorRow !== null);
309− // Get the first indicator
237+ var menuContent = findChild(panel.indicators, "menuContent");
310− var indicatorItemFirst = get_indicator_item(0);
311− verify(indicatorItemFirst !== null);
238+ verify(menuContent !== null);
313− var indicatorItemCoordFirst = get_indicator_item_position(0);
240+ var indicatorArea = findChild(panel, "indicatorArea");
314− var indicatorItemCoordNext = get_indicator_item_position(indicatorRow.row.count - 1);
241+ verify(indicatorArea !== null);
316− touchPress(panel,
243+ // Wait for the indicators to get into position.
317− indicatorItemCoordFirst.x, panel.indicators.panelHeight / 2);
244+ // (switches between normal and fullscreen modes are animated)
245+ tryCompareFunction(function() { return indicatorArea.y }, data.indicatorY);
247+ var startXPosition = root.mapFromItem(panel.indicators, panel.indicators.width / 2, 0).x;
248+ var startYPosition = root.mapFromItem(panel, 0, panel.height).y;
250+ panel.indicators.show();
251+ tryCompare(panel.indicators.showAnimation, "running", false);
252+ tryCompare(panel.indicators, "unitProgress", 1);
255+ touchFlick(panel.indicators,
256+ startXPosition, startYPosition,
258+ true /* beginTouch */, false /* endTouch */, units.gu(5), 15);
319− // 1) Drag the mouse down to hint a bit
260+ // Indicators height should follow the drag, and therefore increase accordingly.
320− touchFlick(panel,
261+ // They should be at least half-way through the screen
321− indicatorItemCoordFirst.x, panel.indicators.panelHeight / 2,
262+ tryCompareFunction(
322− indicatorItemCoordFirst.x, panel.indicators.panelHeight * 2,
263+ function() {return panel.indicators.height <= panel.height * 0.5},
323− false /* beginTouch */, false /* endTouch */);
264+ true);
325− tryCompare(indicatorRow, "currentItem", indicatorItemFirst)
266+ touchRelease(panel.indicators, startXPosition, 0);
327− // 1) Flick mouse down to bottom
268+ tryCompare(panel.indicators.hideAnimation, "running", true);
328− touchFlick(panel,
269+ tryCompare(panel.indicators.hideAnimation, "running", false);
329− indicatorItemCoordFirst.x, panel.indicators.panelHeight * 2,
270+ tryCompare(panel.indicators, "state", "initial");
330− indicatorItemCoordNext.x, panel.height,
271+ }
331− false /* beginTouch */, true /* endTouch */,
272+
332− units.gu(10) /* speed */, 30 /* iterations */); // more samples needed for accurate velocity
273+ function test_hint_data() {
275+ { tag: "normal", fullscreen: false, call: null, hintExpected: true},
276+ { tag: "fullscreen", fullscreen: true, call: null, hintExpected: false},
277+ { tag: "call hint", fullscreen: false, call: phoneCall, hintExpected: false},
281+ function test_hint(data) {
282+ panel.fullscreenMode = data.fullscreen;
283+ callManager.foregroundCall = data.call;
285+ if (data.fullscreen) {
286+ // Wait for the indicators to get into position.
287+ // (switches between normal and fullscreen modes are animated)
288+ var indicatorArea = findChild(panel, "indicatorArea");
289+ tryCompare(indicatorArea, "y", -panel.panelHeight);
292+ var indicatorItem = get_indicator_item(0);
293+ var mappedPosition = root.mapFromItem(indicatorItem, indicatorItem.width / 2, indicatorItem.height / 2);
295+ touchPress(panel, mappedPosition.x, panel.indicators.minimizedPanelHeight / 2);
297+ // Give some time for a hint animation to change things, if any
300+ // no hint animation when fullscreen
301+ compare(panel.indicators.fullyClosed, !data.hintExpected, "Indicator should be fully closed");
302+ compare(panel.indicators.partiallyOpened, data.hintExpected, "Indicator should be partialy opened");
303+ compare(panel.indicators.fullyOpened, false, "Indicator should not be fully opened");
334− compare(indicatorRow.currentItem, indicatorItemFirst, "First indicator should still be the current item");
305+ touchRelease(panel, mappedPosition.x, panel.minimizedPanelHeight / 2);