Merge lp:~cjwatson/launchpad/snap-fix-js-status into lp:launchpad

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
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/soyuz/javascript/update_archive_build_statuses.js, which is dealing with BuildSetStatus values rather than BuildStatus values.

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
=== renamed file 'lib/canonical/launchpad/images/build-failed.gif' => 'lib/canonical/launchpad/images/build-failed.png'
=== modified file 'lib/lp/app/browser/tales.py'
--- lib/lp/app/browser/tales.py 2016-12-02 12:04:11 +0000
+++ lib/lp/app/browser/tales.py 2017-08-31 14:38:35 +0000
@@ -1097,6 +1097,7 @@
1097 return '<img height="14" width="14" alt="" src="/@@/milestone" />'1097 return '<img height="14" width="14" alt="" src="/@@/milestone" />'
10981098
10991099
1100# Keep this in sync with lib/lp/buildmaster/javascript/build_statuses.js.
1100class BuildImageDisplayAPI(ObjectImageDisplayAPI):1101class BuildImageDisplayAPI(ObjectImageDisplayAPI):
1101 """Adapter for IBuild objects to an image.1102 """Adapter for IBuild objects to an image.
11021103
@@ -1119,8 +1120,8 @@
1119 BuildStatus.CHROOTWAIT: {'src': "/@@/build-chrootwait"},1120 BuildStatus.CHROOTWAIT: {'src': "/@@/build-chrootwait"},
1120 BuildStatus.SUPERSEDED: {'src': "/@@/build-superseded"},1121 BuildStatus.SUPERSEDED: {'src': "/@@/build-superseded"},
1121 BuildStatus.BUILDING: {'src': "/@@/processing"},1122 BuildStatus.BUILDING: {'src': "/@@/processing"},
1123 BuildStatus.FAILEDTOUPLOAD: {'src': "/@@/build-failedtoupload"},
1122 BuildStatus.UPLOADING: {'src': "/@@/processing"},1124 BuildStatus.UPLOADING: {'src': "/@@/processing"},
1123 BuildStatus.FAILEDTOUPLOAD: {'src': "/@@/build-failedtoupload"},
1124 BuildStatus.CANCELLING: {'src': "/@@/processing"},1125 BuildStatus.CANCELLING: {'src': "/@@/processing"},
1125 BuildStatus.CANCELLED: {'src': "/@@/build-failed"},1126 BuildStatus.CANCELLED: {'src': "/@@/build-failed"},
1126 }1127 }
11271128
=== added directory 'lib/lp/buildmaster/javascript'
=== added file 'lib/lp/buildmaster/javascript/buildstatus.js'
--- lib/lp/buildmaster/javascript/buildstatus.js 1970-01-01 00:00:00 +0000
+++ lib/lp/buildmaster/javascript/buildstatus.js 2017-08-31 14:38:35 +0000
@@ -0,0 +1,54 @@
1/* Copyright 2017 Canonical Ltd. This software is licensed under the
2 * GNU Affero General Public License version 3 (see the file LICENSE).
3 *
4 * Build status handling.
5 *
6 * @module Y.lp.buildmaster.buildstatus
7 */
8YUI.add('lp.buildmaster.buildstatus', function(Y) {
9 var module = Y.namespace('lp.buildmaster.buildstatus');
10
11 // Keep this in sync with
12 // lib/lp/app/browser/tales.py:BuildImageDisplayAPI.
13 var icon_map = {
14 NEEDSBUILD: { src: '/@@/build-needed' },
15 FULLYBUILT: { src: '/@@/build-success' },
16 FAILEDTOBUILD: {
17 src: '/@@/build-failed',
18 width: 16
19 },
20 MANUALDEPWAIT: { src: '/@@/build-depwait' },
21 CHROOTWAIT: { src: '/@@/build-chrootwait' },
22 SUPERSEDED: { src: '/@@/build-superseded' },
23 BUILDING: { src: '/@@/processing' },
24 FAILEDTOUPLOAD: { src: '/@@/build-failedtoupload' },
25 UPLOADING: { src: '/@@/processing' },
26 CANCELLING: { src: '/@@/processing' },
27 CANCELLED: { src: '/@@/build-failed' }
28 };
29
30 module.update_build_status = function(node, build_summary) {
31 var link_node = node.one('a');
32 var img_node = node.one('img');
33
34 if (link_node === null || img_node === null) {
35 return false;
36 }
37
38 if (node.hasClass(build_summary.status)) {
39 return false;
40 }
41 if (!(build_summary.status in icon_map)) {
42 return false;
43 }
44 icon_props = icon_map[build_summary.status];
45
46 node.setAttribute('class', 'build_status');
47 node.addClass(build_summary.status);
48 link_node.set('innerHTML', build_summary.buildstate);
49 img_node.setAttribute('alt', '[' + build_summary.status + ']');
50 img_node.setAttribute('title', build_summary.buildstate);
51 img_node.setAttribute('src', icon_props.src);
52 img_node.setAttribute('width', icon_props.width || 14);
53 };
54}, '0.1', {'requires': []});
055
=== modified file 'lib/lp/snappy/javascript/snap.update_build_statuses.js'
--- lib/lp/snappy/javascript/snap.update_build_statuses.js 2016-05-14 00:25:07 +0000
+++ lib/lp/snappy/javascript/snap.update_build_statuses.js 2017-08-31 14:38:35 +0000
@@ -5,7 +5,8 @@
5 * LP DynamicDomUpdater plugin for updating the latest builds table of a snap.5 * LP DynamicDomUpdater plugin for updating the latest builds table of a snap.
6 *6 *
7 * @module Y.lp.snappy.snap.update_build_statuses7 * @module Y.lp.snappy.snap.update_build_statuses
8 * @requires anim, node, lp.anim, lp.soyuz.dynamic_dom_updater8 * @requires anim, node, lp.anim, lp.buildmaster.buildstatus,
9 * lp.soyuz.dynamic_dom_updater
9 */10 */
10YUI.add('lp.snappy.snap.update_build_statuses', function(Y) {11YUI.add('lp.snappy.snap.update_build_statuses', function(Y) {
11 Y.log('loading lp.snappy.snap.update_build_statuses');12 Y.log('loading lp.snappy.snap.update_build_statuses');
@@ -30,40 +31,9 @@
30 return;31 return;
31 }32 }
3233
33 var link_node = td_build_status.one("a");34 if (Y.lp.buildmaster.buildstatus.update_build_status(
34 var img_node = td_build_status.one("img");35 td_build_status, build_summary)) {
35
36 if (link_node === null || img_node === null) {
37 return;
38 }
39
40 if (!td_build_status.hasClass(build_summary.status)) {
41 ui_changed = true;36 ui_changed = true;
42 var new_src = null;
43 switch(build_summary.status) {
44 case 'BUILDING':
45 case 'UPLOADING':
46 new_src = '/@@/processing';
47 break;
48 case 'NEEDSBUILD':
49 new_src = '/@@/build-needed';
50 break;
51 case 'FAILEDTOBUILD':
52 new_src = '/@@/build-failed';
53 break;
54 case 'FULLYBUILT_PENDING':
55 new_src = '/@@/build-success-publishing';
56 break;
57 default:
58 new_src = '/@@/build-success';
59 }
60
61 td_build_status.setAttribute("class", "build_status");
62 td_build_status.addClass(build_summary.status);
63 link_node.set("innerHTML", build_summary.buildstate);
64 img_node.setAttribute("src", new_src);
65 img_node.setAttribute("title", build_summary.buildstate);
66 img_node.setAttribute("alt", "[" + build_summary.status + "]");
67 }37 }
6838
69 if (build_summary.when_complete !== null) {39 if (build_summary.when_complete !== null) {
@@ -137,4 +107,5 @@
137}, "0.1", {"requires":["anim",107}, "0.1", {"requires":["anim",
138 "node",108 "node",
139 "lp.anim",109 "lp.anim",
110 "lp.buildmaster.buildstatus",
140 "lp.soyuz.dynamic_dom_updater"]});111 "lp.soyuz.dynamic_dom_updater"]});
141112
=== modified file 'lib/lp/snappy/javascript/tests/test_snap.update_build_statuses.html'
--- lib/lp/snappy/javascript/tests/test_snap.update_build_statuses.html 2016-05-14 00:25:07 +0000
+++ lib/lp/snappy/javascript/tests/test_snap.update_build_statuses.html 2017-08-31 14:38:35 +0000
@@ -34,6 +34,8 @@
34 <script type="text/javascript"34 <script type="text/javascript"
35 src="../../../../../build/js/lp/app/extras/extras.js"></script>35 src="../../../../../build/js/lp/app/extras/extras.js"></script>
36 <script type="text/javascript"36 <script type="text/javascript"
37 src="../../../../../build/js/lp/buildmaster/buildstatus.js"></script>
38 <script type="text/javascript"
37 src="../../../../../build/js/lp/soyuz/lp_dynamic_dom_updater.js"></script>39 src="../../../../../build/js/lp/soyuz/lp_dynamic_dom_updater.js"></script>
38 <script type="text/javascript"40 <script type="text/javascript"
39 src="../../../../../build/js/lp/app/testing/assert.js"></script>41 src="../../../../../build/js/lp/app/testing/assert.js"></script>
4042
=== modified file 'lib/lp/snappy/javascript/tests/test_snap.update_build_statuses.js'
--- lib/lp/snappy/javascript/tests/test_snap.update_build_statuses.js 2017-07-21 17:35:14 +0000
+++ lib/lp/snappy/javascript/tests/test_snap.update_build_statuses.js 2017-08-31 14:38:35 +0000
@@ -63,28 +63,110 @@
63 this.td_status.setAttribute("class", this.td_status_class);63 this.td_status.setAttribute("class", this.td_status_class);
64 },64 },
6565
66 test_update_build_status_dom: function() {66 test_update_build_status_dom_building: function() {
67 var original_a_href = this.td_status_a.get("href");67 var original_a_href = this.td_status_a.get("href");
68 var data = {68 var data = {
69 "1": {69 "1": {
70 "status": "BUILDING",70 "status": "BUILDING",
71 "build_log_url": null,71 "build_log_url": null,
72 "when_complete_estimate": true,72 "when_complete_estimate": true,
73 "buildstate": "Currently building",73 "buildstate": "Currently building",
74 "build_log_size": null,74 "build_log_size": null,
75 "when_complete": "in 1 minute"75 "when_complete": "in 1 minute"
76 }76 }
77 };77 };
78 module.domUpdate(this.table, data);78 module.domUpdate(this.table, data);
79 Y.Assert.areEqual(79 Y.Assert.areEqual(
80 "build_status BUILDING", this.td_status.getAttribute("class"));80 "build_status BUILDING", this.td_status.getAttribute("class"));
81 Y.Assert.areEqual(81 Y.Assert.areEqual(
82 "Currently building", this.td_status.get("text").trim());82 "Currently building", this.td_status.get("text").trim());
83 Y.Assert.areEqual("[BUILDING]", this.td_status_img.get("alt"));83 Y.Assert.areEqual("[BUILDING]", this.td_status_img.get("alt"));
84 Y.Assert.areEqual(84 Y.Assert.areEqual(
85 "Currently building", this.td_status_img.get("title"));85 "Currently building", this.td_status_img.get("title"));
86 Y.Assert.areEqual(86 Y.Assert.areEqual(
87 "file:///@@/processing", this.td_status_img.get("src"));87 "file:///@@/processing", this.td_status_img.get("src"));
88 Y.Assert.areEqual("14", this.td_status_img.get("width"));
89 Y.Assert.areEqual(original_a_href, this.td_status_a.get("href"));
90 },
91
92 test_update_build_status_dom_building: function() {
93 var original_a_href = this.td_status_a.get("href");
94 var data = {
95 "1": {
96 "status": "BUILDING",
97 "build_log_url": null,
98 "when_complete_estimate": true,
99 "buildstate": "Currently building",
100 "build_log_size": null,
101 "when_complete": "in 1 minute"
102 }
103 };
104 module.domUpdate(this.table, data);
105 Y.Assert.areEqual(
106 "build_status BUILDING", this.td_status.getAttribute("class"));
107 Y.Assert.areEqual(
108 "Currently building", this.td_status.get("text").trim());
109 Y.Assert.areEqual("[BUILDING]", this.td_status_img.get("alt"));
110 Y.Assert.areEqual(
111 "Currently building", this.td_status_img.get("title"));
112 Y.Assert.areEqual(
113 "file:///@@/processing", this.td_status_img.get("src"));
114 Y.Assert.areEqual("14", this.td_status_img.get("width"));
115 Y.Assert.areEqual(original_a_href, this.td_status_a.get("href"));
116 },
117
118 test_update_build_status_dom_failedtobuild: function() {
119 var original_a_href = this.td_status_a.get("href");
120 var data = {
121 "1": {
122 "status": "FAILEDTOBUILD",
123 "build_log_url": null,
124 "when_complete_estimate": false,
125 "buildstate": "Failed to build",
126 "build_log_size": null,
127 "when_complete": "1 minute ago"
128 }
129 };
130 module.domUpdate(this.table, data);
131 Y.Assert.areEqual(
132 "build_status FAILEDTOBUILD",
133 this.td_status.getAttribute("class"));
134 Y.Assert.areEqual(
135 "Failed to build", this.td_status.get("text").trim());
136 Y.Assert.areEqual(
137 "[FAILEDTOBUILD]", this.td_status_img.get("alt"));
138 Y.Assert.areEqual(
139 "Failed to build", this.td_status_img.get("title"));
140 Y.Assert.areEqual(
141 "file:///@@/build-failed", this.td_status_img.get("src"));
142 Y.Assert.areEqual("16", this.td_status_img.get("width"));
143 Y.Assert.areEqual(original_a_href, this.td_status_a.get("href"));
144 },
145
146 test_update_build_status_dom_chrootwait: function() {
147 var original_a_href = this.td_status_a.get("href");
148 var data = {
149 "1": {
150 "status": "CHROOTWAIT",
151 "build_log_url": null,
152 "when_complete_estimate": false,
153 "buildstate": "Chroot problem",
154 "build_log_size": null,
155 "when_complete": "1 minute ago"
156 }
157 };
158 module.domUpdate(this.table, data);
159 Y.Assert.areEqual(
160 "build_status CHROOTWAIT",
161 this.td_status.getAttribute("class"));
162 Y.Assert.areEqual(
163 "Chroot problem", this.td_status.get("text").trim());
164 Y.Assert.areEqual("[CHROOTWAIT]", this.td_status_img.get("alt"));
165 Y.Assert.areEqual(
166 "Chroot problem", this.td_status_img.get("title"));
167 Y.Assert.areEqual(
168 "file:///@@/build-chrootwait", this.td_status_img.get("src"));
169 Y.Assert.areEqual("14", this.td_status_img.get("width"));
88 Y.Assert.areEqual(original_a_href, this.td_status_a.get("href"));170 Y.Assert.areEqual(original_a_href, this.td_status_a.get("href"));
89 },171 },
90172
91173
=== modified file 'lib/lp/snappy/model/snap.py'
--- lib/lp/snappy/model/snap.py 2017-06-29 12:02:11 +0000
+++ lib/lp/snappy/model/snap.py 2017-08-31 14:38:35 +0000
@@ -537,7 +537,7 @@
537537
538 result[build.id] = {538 result[build.id] = {
539 "status": build.status.name,539 "status": build.status.name,
540 "buildstate": build.status,540 "buildstate": build.status.title,
541 "when_complete": when_complete,541 "when_complete": when_complete,
542 "when_complete_estimate": build.estimate,542 "when_complete_estimate": build.estimate,
543 "build_log_url": build.log_url,543 "build_log_url": build.log_url,
544544
=== modified file 'lib/lp/snappy/tests/test_snap.py'
--- lib/lp/snappy/tests/test_snap.py 2017-04-24 13:38:04 +0000
+++ lib/lp/snappy/tests/test_snap.py 2017-08-31 14:38:35 +0000
@@ -23,6 +23,8 @@
23from storm.locals import Store23from storm.locals import Store
24from testtools.matchers import (24from testtools.matchers import (
25 Equals,25 Equals,
26 Is,
27 MatchesDict,
26 MatchesSetwise,28 MatchesSetwise,
27 MatchesStructure,29 MatchesStructure,
28 )30 )
@@ -420,8 +422,19 @@
420 summary1 = snap1.getBuildSummariesForSnapBuildIds(422 summary1 = snap1.getBuildSummariesForSnapBuildIds(
421 [build11.id, build12.id])423 [build11.id, build12.id])
422 summary2 = snap2.getBuildSummariesForSnapBuildIds([build2.id])424 summary2 = snap2.getBuildSummariesForSnapBuildIds([build2.id])
423 self.assertContentEqual([build11.id, build12.id], summary1.keys())425 summary_matcher = MatchesDict({
424 self.assertContentEqual([build2.id], summary2.keys())426 "status": Equals("NEEDSBUILD"),
427 "buildstate": Equals("Needs building"),
428 "when_complete": Is(None),
429 "when_complete_estimate": Is(False),
430 "build_log_url": Is(None),
431 "build_log_size": Is(None),
432 })
433 self.assertThat(summary1, MatchesDict({
434 build11.id: summary_matcher,
435 build12.id: summary_matcher,
436 }))
437 self.assertThat(summary2, MatchesDict({build2.id: summary_matcher}))
425438
426 def test_getBuildSummariesForSnapBuildIds_empty_input(self):439 def test_getBuildSummariesForSnapBuildIds_empty_input(self):
427 snap = self.factory.makeSnap()440 snap = self.factory.makeSnap()