@@ -0,0 +1,300 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import QtTest 1.0
19+import Ubuntu.Components 0.1
20+import Unity.Test 0.1 as UT
21+import "../../../qml/Dash"
22+import "CardHelpers.js" as Helpers
23+
24+Rectangle {
25+ id: root
26+ width: units.gu(80)
27+ height: units.gu(72)
28+ color: "#88FFFFFF"
29+
30+ property var cardsModel: [
31+ {
32+ "name": "Art, header, summary",
33+ "layout": { "components": JSON.parse(Helpers.fullMapping) }
34+ },
35+ {
36+ "name": "Header, summary",
37+ "layout": { "components": Helpers.update(JSON.parse(Helpers.fullMapping), { "art": undefined }) }
38+ },
39+ {
40+ "name": "Art, header",
41+ "layout": { "components": Helpers.update(JSON.parse(Helpers.fullMapping), { "summary": undefined }) }
42+ },
43+ {
44+ "name": "Header only",
45+ "layout": { "components": Helpers.update(JSON.parse(Helpers.fullMapping), { "art": undefined, "summary": undefined }) }
46+ },
47+ {
48+ "name": "Header title only",
49+ "layout": { "components": { "title": "title" } }
50+ },
51+ {
52+ "name": "Header title and subtitle",
53+ "layout": { "components": { "title": "title", "subtitle": "subtitle" } }
54+ },
55+ {
56+ "name": "Header title and mascot",
57+ "layout": { "components": { "title": "title", "mascot": "mascot" } }
58+ },
59+ {
60+ "name": "Art, header, summary - small",
61+ "layout": { "template": { "card-size": "small" }, "components": JSON.parse(Helpers.fullMapping) }
62+ },
63+ {
64+ "name": "Art, header, summary - large",
65+ "layout": { "template": { "card-size": "large" }, "components": JSON.parse(Helpers.fullMapping) }
66+ },
67+ {
68+ "name": "Art, header, summary - horizontal",
69+ "layout": { "template": { "card-layout": "horizontal" }, "components": JSON.parse(Helpers.fullMapping) }
70+ },
71+ {
72+ "name": "Art, header - portrait",
73+ "layout": { "components": Helpers.update(JSON.parse(Helpers.fullMapping), { "art": {"aspect-ratio": 0.5, "summary": undefined }}) }
74+ },
75+ ]
76+
77+ CardTool {
78+ id: cardTool
79+
80+ template: Helpers.update(JSON.parse(Helpers.defaultLayout), Helpers.tryParse(layoutArea.text, layoutError))['template'];
81+ components: Helpers.update(JSON.parse(Helpers.defaultLayout), Helpers.tryParse(layoutArea.text, layoutError))['components'];
82+ viewWidth: units.gu(Math.round(widthSlider.value))
83+ }
84+
85+ Column {
86+ width: units.gu(38)
87+ anchors { left: parent.left; top: parent.top; margins: units.gu(1) }
88+
89+ Repeater {
90+ model: [
91+ { label: "View width", value: cardTool.viewWidth && cardTool.viewWidth / units.gu(1) },
92+ { label: "Card width", value: cardTool.cardWidth && cardTool.cardWidth / units.gu(1) },
93+ { label: "Card height", value: cardTool.cardHeight && cardTool.cardHeight / units.gu(1) },
94+ ]
95+
96+ delegate: Row {
97+ anchors { left: parent.left; right: parent.right; margins: units.gu(3) }
98+
99+ Label {
100+ height: units.gu(5)
101+ width: units.gu(25)
102+ text: modelData.label
103+ verticalAlignment: Text.AlignVCenter
104+ }
105+
106+ Label {
107+ height: units.gu(5)
108+ text: modelData.value || "undefined"
109+ verticalAlignment: Text.AlignVCenter
110+ }
111+ }
112+ }
113+
114+ Card {
115+ id: card
116+ template: cardTool.template;
117+ components: cardTool.components;
118+ cardData: Helpers.mapData(dataArea.text, components, dataError)
119+
120+ width: cardTool.cardWidth || implicitWidth
121+ height: cardTool.cardHeight || implicitHeight
122+
123+ clip: true
124+
125+ Rectangle {
126+ anchors.fill: parent
127+ color: "transparent"
128+ border.width: 1
129+ border.color: "green"
130+ }
131+ }
132+ }
133+
134+ Rectangle {
135+ anchors { top: parent.top; bottom: parent.bottom; right: parent.right}
136+ width: units.gu(40)
137+ color: "lightgrey"
138+
139+ Column {
140+ anchors { fill: parent; margins: units.gu(1) }
141+ spacing: units.gu(1)
142+
143+ OptionSelector {
144+ id: selector
145+ model: cardsModel
146+ delegate: OptionSelectorDelegate { text: modelData.name }
147+ onSelectedIndexChanged: updateAreas()
148+ Component.onCompleted: updateAreas()
149+
150+ function updateAreas() {
151+ var element = cardsModel[selectedIndex];
152+ if (element) {
153+ layoutArea.text = JSON.stringify(element.layout, undefined, 2) || "{}";
154+ } else {
155+ layoutArea.text = "";
156+ }
157+ }
158+ }
159+
160+ OptionSelector {
161+ id: layoutSelector
162+ model: [
163+ { label: "Grid", layout: "grid" },
164+ { label: "Organic Grid", layout: "organic-grid" },
165+ { label: "Horizontal Journal", layout: "journal" },
166+ { label: "Vertical Journal", layout: "vertical-journal" },
167+ { label: "Carousel", layout: "carousel" },
168+ ]
169+ delegate: OptionSelectorDelegate { text: modelData.label }
170+ onSelectedIndexChanged: {
171+ var element = model[selectedIndex];
172+ if (element && cardTool.template["category-layout"] !== element.layout) {
173+ var current = JSON.parse(layoutArea.text);
174+ var update = { "template": { "category-layout": element.layout }}
175+ layoutArea.text = JSON.stringify(Helpers.update(current, update), undefined, 2) || "{}";
176+ }
177+ }
178+ }
179+
180+ Label {
181+ anchors { left: parent.left; right: parent.right }
182+ height: units.gu(3)
183+ verticalAlignment: Text.AlignBottom
184+ text: "View width:"
185+ }
186+
187+ Slider {
188+ id: widthSlider
189+ minimumValue: 30
190+ maximumValue: 140
191+ live: true
192+ value: 40
193+ }
194+
195+ TextArea {
196+ id: layoutArea
197+ anchors { left: parent.left; right: parent.right }
198+ height: units.gu(25)
199+ }
200+
201+ Label {
202+ id: layoutError
203+ anchors { left: parent.left; right: parent.right }
204+ height: units.gu(4)
205+ color: "orange"
206+ }
207+
208+ TextArea {
209+ id: dataArea
210+ anchors { left: parent.left; right: parent.right }
211+ height: units.gu(25)
212+ text: JSON.stringify(cardTool.priv.cardData, undefined, 2)
213+ }
214+
215+ Label {
216+ id: dataError
217+ anchors { left: parent.left; right: parent.right }
218+ height: units.gu(4)
219+ color: "orange"
220+ }
221+ }
222+
223+ Connections {
224+ target: cardTool
225+ onTemplateChanged: {
226+ switch(cardTool.template["category-layout"]) {
227+ case "organic-grid": layoutSelector.selectedIndex = 1; break;
228+ case "journal": layoutSelector.selectedIndex = 2; break;
229+ case "vertical-journal": layoutSelector.selectedIndex = 3; break;
230+ case "carousel": layoutSelector.selectedIndex = 4; break;
231+ case "grid":
232+ default: layoutSelector.selectedIndex = 0; break;
233+ }
234+ }
235+ }
236+ }
237+
238+ UT.UnityTestCase {
239+ id: testCase
240+ name: "Card"
241+
242+ when: windowShown
243+
244+ function cleanup() {
245+ selector.selectedIndex = -1;
246+ layoutSelector.selectedIndex = -1;
247+ }
248+
249+ function test_card_size_data() {
250+ return [
251+ { tag: "Medium", width: units.gu(18.5), height: function() { return card.height }, index: 0 },
252+ { tag: "No art", width: units.gu(18.5), height: function() { return card.height }, index: 1 },
253+ { tag: "No summary", width: units.gu(18.5), height: function() { return card.height }, index: 2 },
254+ { tag: "Just header", width: units.gu(18.5), height: function() { return card.height }, index: 3 },
255+ { tag: "Just title", width: units.gu(18.5), height: function() { return card.height }, index: 4 },
256+ { tag: "Title and subtitle", width: units.gu(18.5), height: function() { return card.height }, index: 5 },
257+ { tag: "Title and mascot", width: units.gu(18.5), height: function() { return card.height }, index: 6 },
258+ { tag: "Small", width: units.gu(12), height: function() { return card.height }, index: 7 },
259+ { tag: "Large", width: units.gu(38), height: function() { return card.height }, index: 8 },
260+ { tag: "Horizontal", width: units.gu(38), height: function() { return card.height }, index: 9 },
261+ { tag: "OrganicGrid", width: undefined, height: undefined, index: 0, layout_index: 1},
262+ { tag: "Journal", width: undefined, height: units.gu(20), size: 20, index: 0, layout_index: 2 },
263+ { tag: "OversizedJournal", width: undefined, height: units.gu(18.5), size: 40, index: 0, layout_index: 2 },
264+ { tag: "VerticalJournal", width: units.gu(18.5), height: undefined, index: 0, layout_index: 3 },
265+ { tag: "SmallCarousel", width: units.gu(18), height: units.gu(18), viewWidth: 30, index: 0, layout_index: 4},
266+ { tag: "MediumCarousel", width: units.gu(22), height: units.gu(22), viewWidth: 84, index: 0, layout_index: 4},
267+ { tag: "LargeCarousel", width: units.gu(26), height: units.gu(26), viewWidth: 140, index: 0, layout_index: 4},
268+ { tag: "PortraitCarousel", width: units.gu(22), height: units.gu(44), viewWidth: 84, index: 10, layout_index: 4},
269+ ]
270+ }
271+
272+ function test_card_size(data) {
273+ selector.selectedIndex = data.index;
274+ if (data.hasOwnProperty("layout_index")) {
275+ layoutSelector.selectedIndex = data.layout_index;
276+ }
277+
278+ if (data.hasOwnProperty("viewWidth")) {
279+ widthSlider.value = data.viewWidth;
280+ }
281+
282+ if (data.hasOwnProperty("size")) {
283+ cardTool.template['card-size'] = data.size;
284+ cardTool.templateChanged();
285+ }
286+
287+ if (data.hasOwnProperty("width")) {
288+ if (typeof data.width === "function") {
289+ tryCompareFunction(function() { return cardTool.cardWidth === data.width() }, true);
290+ } else tryCompare(cardTool, "cardWidth", data.width);
291+ }
292+
293+ if (data.hasOwnProperty("height")) {
294+ if (typeof data.height === "function") {
295+ tryCompareFunction(function() { return cardTool.cardHeight === data.height() }, true);
296+ } else tryCompare(cardTool, "cardHeight", data.height);
297+ }
298+ }
299+ }
300+}