Merge lp:~cjwatson/launchpad/snap-fix-js-status into lp:launchpad
- snap-fix-js-status
- Merge into devel
Proposed by
Colin Watson
Status: | Merged |
---|---|
Merged at revision: | 18501 |
Proposed branch: | lp:~cjwatson/launchpad/snap-fix-js-status |
Merge into: | lp:launchpad |
Diff against target: |
343 lines (+183/-60) 7 files modified
lib/lp/app/browser/tales.py (+2/-1) lib/lp/buildmaster/javascript/buildstatus.js (+54/-0) lib/lp/snappy/javascript/snap.update_build_statuses.js (+5/-34) lib/lp/snappy/javascript/tests/test_snap.update_build_statuses.html (+2/-0) lib/lp/snappy/javascript/tests/test_snap.update_build_statuses.js (+104/-22) lib/lp/snappy/model/snap.py (+1/-1) lib/lp/snappy/tests/test_snap.py (+15/-2) |
To merge this branch: | bzr merge lp:~cjwatson/launchpad/snap-fix-js-status |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+330015@code.launchpad.net |
Commit message
Fix AJAX update of snap builds table to handle all build statuses.
Description of the change
I suspect the original confusion was because it was cloned-and-hacked from lib/lp/
To post a comment you must log in.
Revision history for this message
William Grant (wgrant) : | # |
review:
Approve
(code)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === renamed file 'lib/canonical/launchpad/images/build-failed.gif' => 'lib/canonical/launchpad/images/build-failed.png' |
2 | === modified file 'lib/lp/app/browser/tales.py' |
3 | --- lib/lp/app/browser/tales.py 2016-12-02 12:04:11 +0000 |
4 | +++ lib/lp/app/browser/tales.py 2017-08-31 14:38:35 +0000 |
5 | @@ -1097,6 +1097,7 @@ |
6 | return '<img height="14" width="14" alt="" src="/@@/milestone" />' |
7 | |
8 | |
9 | +# Keep this in sync with lib/lp/buildmaster/javascript/build_statuses.js. |
10 | class BuildImageDisplayAPI(ObjectImageDisplayAPI): |
11 | """Adapter for IBuild objects to an image. |
12 | |
13 | @@ -1119,8 +1120,8 @@ |
14 | BuildStatus.CHROOTWAIT: {'src': "/@@/build-chrootwait"}, |
15 | BuildStatus.SUPERSEDED: {'src': "/@@/build-superseded"}, |
16 | BuildStatus.BUILDING: {'src': "/@@/processing"}, |
17 | + BuildStatus.FAILEDTOUPLOAD: {'src': "/@@/build-failedtoupload"}, |
18 | BuildStatus.UPLOADING: {'src': "/@@/processing"}, |
19 | - BuildStatus.FAILEDTOUPLOAD: {'src': "/@@/build-failedtoupload"}, |
20 | BuildStatus.CANCELLING: {'src': "/@@/processing"}, |
21 | BuildStatus.CANCELLED: {'src': "/@@/build-failed"}, |
22 | } |
23 | |
24 | === added directory 'lib/lp/buildmaster/javascript' |
25 | === added file 'lib/lp/buildmaster/javascript/buildstatus.js' |
26 | --- lib/lp/buildmaster/javascript/buildstatus.js 1970-01-01 00:00:00 +0000 |
27 | +++ lib/lp/buildmaster/javascript/buildstatus.js 2017-08-31 14:38:35 +0000 |
28 | @@ -0,0 +1,54 @@ |
29 | +/* Copyright 2017 Canonical Ltd. This software is licensed under the |
30 | + * GNU Affero General Public License version 3 (see the file LICENSE). |
31 | + * |
32 | + * Build status handling. |
33 | + * |
34 | + * @module Y.lp.buildmaster.buildstatus |
35 | + */ |
36 | +YUI.add('lp.buildmaster.buildstatus', function(Y) { |
37 | + var module = Y.namespace('lp.buildmaster.buildstatus'); |
38 | + |
39 | + // Keep this in sync with |
40 | + // lib/lp/app/browser/tales.py:BuildImageDisplayAPI. |
41 | + var icon_map = { |
42 | + NEEDSBUILD: { src: '/@@/build-needed' }, |
43 | + FULLYBUILT: { src: '/@@/build-success' }, |
44 | + FAILEDTOBUILD: { |
45 | + src: '/@@/build-failed', |
46 | + width: 16 |
47 | + }, |
48 | + MANUALDEPWAIT: { src: '/@@/build-depwait' }, |
49 | + CHROOTWAIT: { src: '/@@/build-chrootwait' }, |
50 | + SUPERSEDED: { src: '/@@/build-superseded' }, |
51 | + BUILDING: { src: '/@@/processing' }, |
52 | + FAILEDTOUPLOAD: { src: '/@@/build-failedtoupload' }, |
53 | + UPLOADING: { src: '/@@/processing' }, |
54 | + CANCELLING: { src: '/@@/processing' }, |
55 | + CANCELLED: { src: '/@@/build-failed' } |
56 | + }; |
57 | + |
58 | + module.update_build_status = function(node, build_summary) { |
59 | + var link_node = node.one('a'); |
60 | + var img_node = node.one('img'); |
61 | + |
62 | + if (link_node === null || img_node === null) { |
63 | + return false; |
64 | + } |
65 | + |
66 | + if (node.hasClass(build_summary.status)) { |
67 | + return false; |
68 | + } |
69 | + if (!(build_summary.status in icon_map)) { |
70 | + return false; |
71 | + } |
72 | + icon_props = icon_map[build_summary.status]; |
73 | + |
74 | + node.setAttribute('class', 'build_status'); |
75 | + node.addClass(build_summary.status); |
76 | + link_node.set('innerHTML', build_summary.buildstate); |
77 | + img_node.setAttribute('alt', '[' + build_summary.status + ']'); |
78 | + img_node.setAttribute('title', build_summary.buildstate); |
79 | + img_node.setAttribute('src', icon_props.src); |
80 | + img_node.setAttribute('width', icon_props.width || 14); |
81 | + }; |
82 | +}, '0.1', {'requires': []}); |
83 | |
84 | === modified file 'lib/lp/snappy/javascript/snap.update_build_statuses.js' |
85 | --- lib/lp/snappy/javascript/snap.update_build_statuses.js 2016-05-14 00:25:07 +0000 |
86 | +++ lib/lp/snappy/javascript/snap.update_build_statuses.js 2017-08-31 14:38:35 +0000 |
87 | @@ -5,7 +5,8 @@ |
88 | * LP DynamicDomUpdater plugin for updating the latest builds table of a snap. |
89 | * |
90 | * @module Y.lp.snappy.snap.update_build_statuses |
91 | - * @requires anim, node, lp.anim, lp.soyuz.dynamic_dom_updater |
92 | + * @requires anim, node, lp.anim, lp.buildmaster.buildstatus, |
93 | + * lp.soyuz.dynamic_dom_updater |
94 | */ |
95 | YUI.add('lp.snappy.snap.update_build_statuses', function(Y) { |
96 | Y.log('loading lp.snappy.snap.update_build_statuses'); |
97 | @@ -30,40 +31,9 @@ |
98 | return; |
99 | } |
100 | |
101 | - var link_node = td_build_status.one("a"); |
102 | - var img_node = td_build_status.one("img"); |
103 | - |
104 | - if (link_node === null || img_node === null) { |
105 | - return; |
106 | - } |
107 | - |
108 | - if (!td_build_status.hasClass(build_summary.status)) { |
109 | + if (Y.lp.buildmaster.buildstatus.update_build_status( |
110 | + td_build_status, build_summary)) { |
111 | ui_changed = true; |
112 | - var new_src = null; |
113 | - switch(build_summary.status) { |
114 | - case 'BUILDING': |
115 | - case 'UPLOADING': |
116 | - new_src = '/@@/processing'; |
117 | - break; |
118 | - case 'NEEDSBUILD': |
119 | - new_src = '/@@/build-needed'; |
120 | - break; |
121 | - case 'FAILEDTOBUILD': |
122 | - new_src = '/@@/build-failed'; |
123 | - break; |
124 | - case 'FULLYBUILT_PENDING': |
125 | - new_src = '/@@/build-success-publishing'; |
126 | - break; |
127 | - default: |
128 | - new_src = '/@@/build-success'; |
129 | - } |
130 | - |
131 | - td_build_status.setAttribute("class", "build_status"); |
132 | - td_build_status.addClass(build_summary.status); |
133 | - link_node.set("innerHTML", build_summary.buildstate); |
134 | - img_node.setAttribute("src", new_src); |
135 | - img_node.setAttribute("title", build_summary.buildstate); |
136 | - img_node.setAttribute("alt", "[" + build_summary.status + "]"); |
137 | } |
138 | |
139 | if (build_summary.when_complete !== null) { |
140 | @@ -137,4 +107,5 @@ |
141 | }, "0.1", {"requires":["anim", |
142 | "node", |
143 | "lp.anim", |
144 | + "lp.buildmaster.buildstatus", |
145 | "lp.soyuz.dynamic_dom_updater"]}); |
146 | |
147 | === modified file 'lib/lp/snappy/javascript/tests/test_snap.update_build_statuses.html' |
148 | --- lib/lp/snappy/javascript/tests/test_snap.update_build_statuses.html 2016-05-14 00:25:07 +0000 |
149 | +++ lib/lp/snappy/javascript/tests/test_snap.update_build_statuses.html 2017-08-31 14:38:35 +0000 |
150 | @@ -34,6 +34,8 @@ |
151 | <script type="text/javascript" |
152 | src="../../../../../build/js/lp/app/extras/extras.js"></script> |
153 | <script type="text/javascript" |
154 | + src="../../../../../build/js/lp/buildmaster/buildstatus.js"></script> |
155 | + <script type="text/javascript" |
156 | src="../../../../../build/js/lp/soyuz/lp_dynamic_dom_updater.js"></script> |
157 | <script type="text/javascript" |
158 | src="../../../../../build/js/lp/app/testing/assert.js"></script> |
159 | |
160 | === modified file 'lib/lp/snappy/javascript/tests/test_snap.update_build_statuses.js' |
161 | --- lib/lp/snappy/javascript/tests/test_snap.update_build_statuses.js 2017-07-21 17:35:14 +0000 |
162 | +++ lib/lp/snappy/javascript/tests/test_snap.update_build_statuses.js 2017-08-31 14:38:35 +0000 |
163 | @@ -63,28 +63,110 @@ |
164 | this.td_status.setAttribute("class", this.td_status_class); |
165 | }, |
166 | |
167 | - test_update_build_status_dom: function() { |
168 | - var original_a_href = this.td_status_a.get("href"); |
169 | - var data = { |
170 | - "1": { |
171 | - "status": "BUILDING", |
172 | - "build_log_url": null, |
173 | - "when_complete_estimate": true, |
174 | - "buildstate": "Currently building", |
175 | - "build_log_size": null, |
176 | - "when_complete": "in 1 minute" |
177 | - } |
178 | - }; |
179 | - module.domUpdate(this.table, data); |
180 | - Y.Assert.areEqual( |
181 | - "build_status BUILDING", this.td_status.getAttribute("class")); |
182 | - Y.Assert.areEqual( |
183 | - "Currently building", this.td_status.get("text").trim()); |
184 | - Y.Assert.areEqual("[BUILDING]", this.td_status_img.get("alt")); |
185 | - Y.Assert.areEqual( |
186 | - "Currently building", this.td_status_img.get("title")); |
187 | - Y.Assert.areEqual( |
188 | - "file:///@@/processing", this.td_status_img.get("src")); |
189 | + test_update_build_status_dom_building: function() { |
190 | + var original_a_href = this.td_status_a.get("href"); |
191 | + var data = { |
192 | + "1": { |
193 | + "status": "BUILDING", |
194 | + "build_log_url": null, |
195 | + "when_complete_estimate": true, |
196 | + "buildstate": "Currently building", |
197 | + "build_log_size": null, |
198 | + "when_complete": "in 1 minute" |
199 | + } |
200 | + }; |
201 | + module.domUpdate(this.table, data); |
202 | + Y.Assert.areEqual( |
203 | + "build_status BUILDING", this.td_status.getAttribute("class")); |
204 | + Y.Assert.areEqual( |
205 | + "Currently building", this.td_status.get("text").trim()); |
206 | + Y.Assert.areEqual("[BUILDING]", this.td_status_img.get("alt")); |
207 | + Y.Assert.areEqual( |
208 | + "Currently building", this.td_status_img.get("title")); |
209 | + Y.Assert.areEqual( |
210 | + "file:///@@/processing", this.td_status_img.get("src")); |
211 | + Y.Assert.areEqual("14", this.td_status_img.get("width")); |
212 | + Y.Assert.areEqual(original_a_href, this.td_status_a.get("href")); |
213 | + }, |
214 | + |
215 | + test_update_build_status_dom_building: function() { |
216 | + var original_a_href = this.td_status_a.get("href"); |
217 | + var data = { |
218 | + "1": { |
219 | + "status": "BUILDING", |
220 | + "build_log_url": null, |
221 | + "when_complete_estimate": true, |
222 | + "buildstate": "Currently building", |
223 | + "build_log_size": null, |
224 | + "when_complete": "in 1 minute" |
225 | + } |
226 | + }; |
227 | + module.domUpdate(this.table, data); |
228 | + Y.Assert.areEqual( |
229 | + "build_status BUILDING", this.td_status.getAttribute("class")); |
230 | + Y.Assert.areEqual( |
231 | + "Currently building", this.td_status.get("text").trim()); |
232 | + Y.Assert.areEqual("[BUILDING]", this.td_status_img.get("alt")); |
233 | + Y.Assert.areEqual( |
234 | + "Currently building", this.td_status_img.get("title")); |
235 | + Y.Assert.areEqual( |
236 | + "file:///@@/processing", this.td_status_img.get("src")); |
237 | + Y.Assert.areEqual("14", this.td_status_img.get("width")); |
238 | + Y.Assert.areEqual(original_a_href, this.td_status_a.get("href")); |
239 | + }, |
240 | + |
241 | + test_update_build_status_dom_failedtobuild: function() { |
242 | + var original_a_href = this.td_status_a.get("href"); |
243 | + var data = { |
244 | + "1": { |
245 | + "status": "FAILEDTOBUILD", |
246 | + "build_log_url": null, |
247 | + "when_complete_estimate": false, |
248 | + "buildstate": "Failed to build", |
249 | + "build_log_size": null, |
250 | + "when_complete": "1 minute ago" |
251 | + } |
252 | + }; |
253 | + module.domUpdate(this.table, data); |
254 | + Y.Assert.areEqual( |
255 | + "build_status FAILEDTOBUILD", |
256 | + this.td_status.getAttribute("class")); |
257 | + Y.Assert.areEqual( |
258 | + "Failed to build", this.td_status.get("text").trim()); |
259 | + Y.Assert.areEqual( |
260 | + "[FAILEDTOBUILD]", this.td_status_img.get("alt")); |
261 | + Y.Assert.areEqual( |
262 | + "Failed to build", this.td_status_img.get("title")); |
263 | + Y.Assert.areEqual( |
264 | + "file:///@@/build-failed", this.td_status_img.get("src")); |
265 | + Y.Assert.areEqual("16", this.td_status_img.get("width")); |
266 | + Y.Assert.areEqual(original_a_href, this.td_status_a.get("href")); |
267 | + }, |
268 | + |
269 | + test_update_build_status_dom_chrootwait: function() { |
270 | + var original_a_href = this.td_status_a.get("href"); |
271 | + var data = { |
272 | + "1": { |
273 | + "status": "CHROOTWAIT", |
274 | + "build_log_url": null, |
275 | + "when_complete_estimate": false, |
276 | + "buildstate": "Chroot problem", |
277 | + "build_log_size": null, |
278 | + "when_complete": "1 minute ago" |
279 | + } |
280 | + }; |
281 | + module.domUpdate(this.table, data); |
282 | + Y.Assert.areEqual( |
283 | + "build_status CHROOTWAIT", |
284 | + this.td_status.getAttribute("class")); |
285 | + Y.Assert.areEqual( |
286 | + "Chroot problem", this.td_status.get("text").trim()); |
287 | + Y.Assert.areEqual("[CHROOTWAIT]", this.td_status_img.get("alt")); |
288 | + Y.Assert.areEqual( |
289 | + "Chroot problem", this.td_status_img.get("title")); |
290 | + Y.Assert.areEqual( |
291 | + "file:///@@/build-chrootwait", this.td_status_img.get("src")); |
292 | + Y.Assert.areEqual("14", this.td_status_img.get("width")); |
293 | Y.Assert.areEqual(original_a_href, this.td_status_a.get("href")); |
294 | }, |
295 | |
296 | |
297 | === modified file 'lib/lp/snappy/model/snap.py' |
298 | --- lib/lp/snappy/model/snap.py 2017-06-29 12:02:11 +0000 |
299 | +++ lib/lp/snappy/model/snap.py 2017-08-31 14:38:35 +0000 |
300 | @@ -537,7 +537,7 @@ |
301 | |
302 | result[build.id] = { |
303 | "status": build.status.name, |
304 | - "buildstate": build.status, |
305 | + "buildstate": build.status.title, |
306 | "when_complete": when_complete, |
307 | "when_complete_estimate": build.estimate, |
308 | "build_log_url": build.log_url, |
309 | |
310 | === modified file 'lib/lp/snappy/tests/test_snap.py' |
311 | --- lib/lp/snappy/tests/test_snap.py 2017-04-24 13:38:04 +0000 |
312 | +++ lib/lp/snappy/tests/test_snap.py 2017-08-31 14:38:35 +0000 |
313 | @@ -23,6 +23,8 @@ |
314 | from storm.locals import Store |
315 | from testtools.matchers import ( |
316 | Equals, |
317 | + Is, |
318 | + MatchesDict, |
319 | MatchesSetwise, |
320 | MatchesStructure, |
321 | ) |
322 | @@ -420,8 +422,19 @@ |
323 | summary1 = snap1.getBuildSummariesForSnapBuildIds( |
324 | [build11.id, build12.id]) |
325 | summary2 = snap2.getBuildSummariesForSnapBuildIds([build2.id]) |
326 | - self.assertContentEqual([build11.id, build12.id], summary1.keys()) |
327 | - self.assertContentEqual([build2.id], summary2.keys()) |
328 | + summary_matcher = MatchesDict({ |
329 | + "status": Equals("NEEDSBUILD"), |
330 | + "buildstate": Equals("Needs building"), |
331 | + "when_complete": Is(None), |
332 | + "when_complete_estimate": Is(False), |
333 | + "build_log_url": Is(None), |
334 | + "build_log_size": Is(None), |
335 | + }) |
336 | + self.assertThat(summary1, MatchesDict({ |
337 | + build11.id: summary_matcher, |
338 | + build12.id: summary_matcher, |
339 | + })) |
340 | + self.assertThat(summary2, MatchesDict({build2.id: summary_matcher})) |
341 | |
342 | def test_getBuildSummariesForSnapBuildIds_empty_input(self): |
343 | snap = self.factory.makeSnap() |