Merge lp:~benji/launchpad/bug-809511 into lp:launchpad

Proposed by Benji York
Status: Merged
Approved by: Gary Poster
Approved revision: no longer in the source branch.
Merged at revision: 13591
Proposed branch: lp:~benji/launchpad/bug-809511
Merge into: lp:launchpad
Diff against target: 196 lines (+155/-5)
3 files modified
lib/lp/code/javascript/branch.bugspeclinks.js (+43/-5)
lib/lp/code/javascript/tests/test_bugspeclinks.html (+28/-0)
lib/lp/code/javascript/tests/test_bugspeclinks.js (+84/-0)
To merge this branch: bzr merge lp:~benji/launchpad/bug-809511
Reviewer Review Type Date Requested Status
Gary Poster (community) Approve
Review via email: mp+70219@code.launchpad.net

Commit message

[r=gary][bug=809511] use a heuristic to guess the likely bug ID from the branch name when associating

Description of the change

This branch addressed bug 809511 which is about adding a heuristic to
the "Link a bug report" functionality on branch pages. The heuristic
looks for potential bug numbers in the branch name and if found
pre-fills the bug number field with it and then selects the field
contents so the user can easily remove the number if the guess was
wrong.

Huw and I talked about this in Dublin so I guess that counts as both a
pre-implementation discussion and UI approval.

Tests are in the new test_bugspeclinks.js file and can be run by loading
lib/lp/code/javascript/tests/test_bugspeclinks.html in a browser.

QA should be to visit a branch with a bug number in the name and click
"Link a bug report" and verify that:

- the bug number is provided
- it is selected
- the field has focus
- typing something replaces the guessed ID
- not typing anything and clicking the OK button works

Also, a branch with no ID in its name should be visited and it should be
verified that:

- the field is empty
- the field has focus
- typing something works
- entering a bug ID and clicking the OK button works

After fixing some pre-existing lint the make lint report is clean.

To post a comment you must log in.
Revision history for this message
Gary Poster (gary) wrote :

This is cool, Benji! Thank you for thinking of it and doing it.

Feel free to ignore this bikeshed color, but I suggest that you make the digit limit for a bug number 5, not 6. We do have branches to fix older bugs. Launchpad has three five digit bugs that are still open (https://bugs.launchpad.net/launchpad/+bugs). Ubuntu has one (https://bugs.launchpad.net/ubuntu/+bugs). It's not a big deal, but my suggestion.

Did you consider updating "Y.DOM.byId('field.bug')" to "Y.one('#field.bug")"?

Other than that, looks good. Cool to see the JS tests gradually growing.

review: Approve
Revision history for this message
Benji York (benji) wrote :

Thanks for the review.

> I suggest that you make the digit limit for a bug number 5, not 6

Sounds good to me, done.

> Did you consider updating "Y.DOM.byId('field.bug')" to "Y.one('#field.bug")"?

I did, but it didn't work for some reason, so I left it as-is.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/code/javascript/branch.bugspeclinks.js'
2--- lib/lp/code/javascript/branch.bugspeclinks.js 2011-06-30 15:20:59 +0000
3+++ lib/lp/code/javascript/branch.bugspeclinks.js 2011-08-02 21:14:44 +0000
4@@ -18,6 +18,34 @@
5 var error_handler;
6
7 /*
8+ * Extract the best candidate for a bug number from the branch name.
9+ */
10+function extract_candidate_bug_id(branch_name) {
11+ // Extract all the runs of numbers in the branch name and sort by
12+ // descending length.
13+ var chunks = branch_name.split(/\D/g).sort(function (a, b) {
14+ return b.length - a.length;
15+ });
16+ var chunk, i;
17+ for (i=0; i<chunks.length; i++) {
18+ chunk = chunks[i];
19+ // Bugs with fewer than six digits aren't being created any more (by
20+ // Canonical's LP at least), but there are lots of open five digit
21+ // bugs so ignore runs of fewer than five digits in the branch name.
22+ if (chunk.length < 5) {
23+ break;
24+ }
25+ // Bug IDs don't start with a zero.
26+ if (chunk[0] !== '0') {
27+ return chunk;
28+ }
29+ }
30+ return null;
31+}
32+// Expose in the namespace so we can test it.
33+namespace._extract_candidate_bug_id = extract_candidate_bug_id;
34+
35+/*
36 * Connect the links to the javascript events.
37 */
38 namespace.connect_branchlinks = function() {
39@@ -50,10 +78,19 @@
40 linkbug_handle.on('click', function(e) {
41 e.preventDefault();
42 link_bug_overlay.show();
43- Y.DOM.byId('field.bug').focus();
44+ var field = Y.DOM.byId('field.bug');
45+ field.focus();
46+ var guessed_bug_id = extract_candidate_bug_id(LP.cache.context.name);
47+ if (Y.Lang.isValue(guessed_bug_id)) {
48+ field.value = guessed_bug_id;
49+ // Select the pre-filled bug number (if any) so that it will be
50+ // replaced by anything the user types (getting the guessed bug
51+ // number out of the way quickly if we guessed incorrectly).
52+ field.selectionStart = 0;
53+ field.selectionEnd = 999;
54+ }
55 });
56 connect_remove_links();
57-
58 };
59
60 /*
61@@ -123,9 +160,10 @@
62 on: {
63 success: function(id, response) {
64 destroy_temporary_spinner();
65- Y.one('#linkbug').set(
66- 'innerHTML', 'Link to another bug report');
67- Y.one('#buglink-list').set('innerHTML', response.responseText);
68+ Y.one('#linkbug')
69+ .set('innerHTML', 'Link to another bug report');
70+ Y.one('#buglink-list')
71+ .set('innerHTML', response.responseText);
72 var new_buglink = Y.one('#buglink-' + bug.get('id'));
73 var anim = Y.lazr.anim.green_flash({node: new_buglink});
74 anim.on('end', connect_remove_links);
75
76=== added file 'lib/lp/code/javascript/tests/test_bugspeclinks.html'
77--- lib/lp/code/javascript/tests/test_bugspeclinks.html 1970-01-01 00:00:00 +0000
78+++ lib/lp/code/javascript/tests/test_bugspeclinks.html 2011-08-02 21:14:44 +0000
79@@ -0,0 +1,28 @@
80+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
81+
82+<html>
83+ <head>
84+ <title>Test page for bug link functionality.</title>
85+
86+ <!-- YUI and test setup -->
87+ <script type="text/javascript"
88+ src="../../../../canonical/launchpad/icing/yui/yui/yui.js">
89+ </script>
90+ <link rel="stylesheet" href="../../../app/javascript/testing/test.css" />
91+ <script type="text/javascript"
92+ src="../../../app/javascript/testing/testrunner.js"></script>
93+
94+ <script type="text/javascript" src="../../../app/javascript/client.js"></script>
95+ <script type="text/javascript"
96+ src="../../../app/javascript/overlay/overlay.js"></script>
97+
98+ <!-- The module under test -->
99+ <script type="text/javascript" src="../branch.bugspeclinks.js"></script>
100+
101+ <!-- The test suite -->
102+ <script type="text/javascript" src="test_bugspeclinks.js"></script>
103+ </head>
104+
105+<body class="yui3-skin-sam">
106+</body>
107+</html>
108
109=== added file 'lib/lp/code/javascript/tests/test_bugspeclinks.js'
110--- lib/lp/code/javascript/tests/test_bugspeclinks.js 1970-01-01 00:00:00 +0000
111+++ lib/lp/code/javascript/tests/test_bugspeclinks.js 2011-08-02 21:14:44 +0000
112@@ -0,0 +1,84 @@
113+/* Copyright 2011 Canonical Ltd. This software is licensed under the
114+ * GNU Affero General Public License version 3 (see the file LICENSE).
115+ *
116+ * Tests for lp.code.branch.bugspeclinks.
117+ *
118+ */
119+
120+YUI({
121+ base: '../../../../canonical/launchpad/icing/yui/',
122+ filter: 'raw', combine: false
123+ }).use('test', 'console', 'node-event-simulate',
124+ 'lp.code.branch.bugspeclinks', function(Y) {
125+
126+ var module = Y.lp.code.branch.bugspeclinks;
127+ var extract_candidate_bug_id = module._extract_candidate_bug_id;
128+ var suite = new Y.Test.Suite("lp.code.branch.bugspeclinks Tests");
129+
130+ suite.add(new Y.Test.Case({
131+ name: 'Test bug ID guessing',
132+
133+ test_no_bug_id_present: function() {
134+ // If nothing that looks like a bug ID is present, null is
135+ // returned.
136+ Y.Assert.isNull(extract_candidate_bug_id('no-id-here'));
137+ },
138+
139+ test_short_digit_rund_ignored: function() {
140+ Y.Assert.isNull(extract_candidate_bug_id('foo-1234-bar'));
141+ },
142+
143+ test_leading_zeros_disqualify_potential_ids: function() {
144+ // Since bug IDs can't start with zeros, any string of numbers
145+ // with a leading zero are not considered as a potential ID.
146+ Y.Assert.isNull(extract_candidate_bug_id('foo-0123456-bar'));
147+ Y.Assert.areEqual(
148+ extract_candidate_bug_id('foo-0123456-999999-bar'), '999999');
149+ },
150+
151+ test_five_digit_bug_ids_are_extracted: function() {
152+ Y.Assert.areEqual(
153+ extract_candidate_bug_id('foo-12345-bar'), '12345');
154+ },
155+
156+ test_six_digit_bug_ids_are_extracted: function() {
157+ Y.Assert.areEqual(
158+ extract_candidate_bug_id('foo-123456-bar'), '123456');
159+ },
160+
161+ test_seven_digit_bug_ids_are_extracted: function() {
162+ Y.Assert.areEqual(
163+ extract_candidate_bug_id('foo-1234567-bar'), '1234567');
164+ },
165+
166+ test_eight_digit_bug_ids_are_extracted: function() {
167+ Y.Assert.areEqual(
168+ extract_candidate_bug_id('foo-12345678-bar'), '12345678');
169+ },
170+
171+ test_longest_potential_id_is_extracted: function() {
172+ // Since there may be numbers other than a bug ID in a branch
173+ // name, we want to extract the longest string of digits.
174+ Y.Assert.areEqual(
175+ extract_candidate_bug_id('bug-123456-take-2'), '123456');
176+ Y.Assert.areEqual(
177+ extract_candidate_bug_id('123456-1234567'), '1234567');
178+ }
179+
180+ }));
181+
182+ var handle_complete = function(data) {
183+ window.status = '::::' + JSON.stringify(data);
184+ };
185+ Y.Test.Runner.on('complete', handle_complete);
186+ Y.Test.Runner.add(suite);
187+
188+ var console = new Y.Console({newestOnTop: false});
189+ console.render('#log');
190+
191+ // Start the test runner on Y.after to ensure all setup has had a
192+ // chance to complete.
193+ Y.after('domready', function() {
194+ Y.Test.Runner.run();
195+ });
196+});