j.c.sackett has proposed merging lp:~jcsackett/launchpad/spam-button-ui-bugs 
into lp:launchpad with lp:~jcsackett/launchpad/spam-button-ui as a prerequisite.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #220535 in Launchpad itself: "Make it possible for registry admins to 
hide comments"
  https://bugs.launchpad.net/launchpad/+bug/220535

For more details, see:
https://code.launchpad.net/~jcsackett/launchpad/spam-button-ui-bugs/+merge/60437

Summary
=======
This branch completes a bunch of our spam moderation stuff, by adding UI for 
admins and registry experts to hide bug comments.

Yes, that's right. You can now hide spammy comments from within the UI. For 
bugs and questions. All, rejoice.

This branch and others before it have introduced some redundancy. Owing to the 
desire for this feature for those on Maintenance rotation, I've opted to land 
this now and have already begun work on a follow up branch (to be landed next) 
that cleans up the tech debt from previous work.

Preimplemenation
================
Spoke with Curtis Hovey.

Implementation
==============
lib/lp/answers/javascript/question_spam.js
------------------------------------------
Drive by fix.

lib/lp/bugs/browser/bugcomment.py
lib/lp/bugs/browser/bugtask.py
------------------------------
Introduced logic for determining when to show the spam controls.

lib/lp/bugs/javascript/bug_spam.js
----------------------------------
This introduces a function bound to the spam controls that sends a POST to the 
API to mark the comment as hidden, as well as updating the page so that the 
comment shows the hidden style and the controls update to marking the comment 
as not spam (or the reverse process if you're unflagging a comment).

lib/lp/bugs/templates/bugcomment-box.pt
lib/lp/bugs/templates/bugtask-index.pt
--------------------------------------
Added the link for the spam control and hooked in the javascript.

lib/lp/bugs/browser/tests/test_bugcomment.py
lib/lp/bugs/browser/tests/test_bugcomment_visibility.py
-------------------------------------------------------
Merged visibility tests into bugcomment file. Added tests for the display of 
the spam controls.

lib/lp/bugs/javascript/tests/test_bug_spam.js
lib/lp/bugs/javascript/tests/test_bug_spam.html
-----------------------------------------------
YUI tests.

Tests
=====
bin/test -vvct test_bugcomment
firefox lib/lp/bugs/browser/javascript/test_bug_spam.html

QA
==
Open a bug with comments while logged in as an admin or registry expert.
Mark a comment as spam via the control.
The comment will switch to the "hidden" display and the control will change to 
"Mark as not spam."
Reload the page; the comment will still be thusly marked.
Open the same bug as anonymous or a user without priveleges (easiest to do in 
another browser).
The comment marked as spam will not display.

Open the bug again logged in as admin or registry expert.
Mark the spam comment as not spam.
The comment will switch to the not hidden display and the control will change 
to "Mark as spam."
Reload the page; the comment will still be marked as not spam.
Open the same bug as anon or no privs user; the comment will be displayed. 

Lint
====

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/answers/javascript/question_spam.js
  lib/lp/bugs/browser/bugcomment.py
  lib/lp/bugs/browser/bugtask.py
  lib/lp/bugs/browser/tests/test_bugcomment.py
  lib/lp/bugs/javascript/bug_spam.js
  lib/lp/bugs/javascript/tests/test_bug_spam.html
  lib/lp/bugs/javascript/tests/test_bug_spam.js
  lib/lp/bugs/templates/bugcomment-box.pt
  lib/lp/bugs/templates/bugtask-index.pt

-- 
https://code.launchpad.net/~jcsackett/launchpad/spam-button-ui-bugs/+merge/60437
Your team Launchpad code reviewers is requested to review the proposed merge of 
lp:~jcsackett/launchpad/spam-button-ui-bugs into lp:launchpad.
=== modified file 'lib/lp/answers/javascript/question_spam.js'
--- lib/lp/answers/javascript/question_spam.js	2011-05-06 14:15:30 +0000
+++ lib/lp/answers/javascript/question_spam.js	2011-05-10 16:19:42 +0000
@@ -26,8 +26,8 @@
 }
 
 function set_visibility(parameters, callbacks) {
-    var question = LP.cache.context
-    var lp_client = new Y.lp.client.Launchpad()
+    var question = LP.cache.context;
+    var lp_client = new Y.lp.client.Launchpad();
     var config = {
         on: {
             success: callbacks.success,
@@ -36,7 +36,7 @@
         parameters: parameters
         }
     lp_client.named_post(
-        question.self_link, 'setCommentVisibility', config)
+        question.self_link, 'setCommentVisibility', config);
 }
 
 function toggle_spam_setting(link) {

=== modified file 'lib/lp/bugs/browser/bugcomment.py'
--- lib/lp/bugs/browser/bugcomment.py	2011-04-22 12:46:12 +0000
+++ lib/lp/bugs/browser/bugcomment.py	2011-05-10 16:19:42 +0000
@@ -51,7 +51,8 @@
 COMMENT_ACTIVITY_GROUPING_WINDOW = timedelta(minutes=5)
 
 
-def build_comments_from_chunks(bugtask, truncate=False, slice_info=None):
+def build_comments_from_chunks(
+        bugtask, truncate=False, slice_info=None, show_spam_controls=False):
     """Build BugComments from MessageChunks.
 
     :param truncate: Perform truncation of large messages.
@@ -63,8 +64,9 @@
     for bugmessage, message, chunk in chunks:
         bug_comment = comments.get(message.id)
         if bug_comment is None:
-            bug_comment = BugComment(bugmessage.index, message, bugtask,
-                visible=message.visible)
+            bug_comment = BugComment(
+                bugmessage.index, message, bugtask, visible=message.visible,
+                show_spam_controls=show_spam_controls)
             comments[message.id] = bug_comment
             # This code path is currently only used from a BugTask view which
             # has already loaded all the bug watches. If we start lazy loading
@@ -172,7 +174,10 @@
     """
     implements(IBugComment)
 
-    def __init__(self, index, message, bugtask, activity=None, visible=True):
+    def __init__(
+            self, index, message, bugtask, activity=None,
+            visible=True, show_spam_controls=False):
+
         self.index = index
         self.bugtask = bugtask
         self.bugwatch = None
@@ -194,6 +199,7 @@
 
         self.synchronized = False
         self.visible = visible
+        self.show_spam_controls = show_spam_controls
 
     @property
     def show_for_admin(self):
@@ -263,10 +269,10 @@
     @property
     def show_footer(self):
         """Return True if the footer should be shown for this comment."""
-        if len(self.activity) > 0 or self.bugwatch:
-            return True
-        else:
-            return False
+        return (
+            len(self.activity) > 0 or
+            self.bugwatch or
+            self.show_spam_controls)
 
     @property
     def rendered_cache_time(self):

=== modified file 'lib/lp/bugs/browser/bugtask.py'
--- lib/lp/bugs/browser/bugtask.py	2011-04-22 12:46:12 +0000
+++ lib/lp/bugs/browser/bugtask.py	2011-05-10 16:19:42 +0000
@@ -326,7 +326,7 @@
 
 
 def get_comments_for_bugtask(bugtask, truncate=False, for_display=False,
-    slice_info=None):
+    slice_info=None, show_spam_controls=False):
     """Return BugComments related to a bugtask.
 
     This code builds a sorted list of BugComments in one shot,
@@ -339,7 +339,7 @@
         to retrieve.
     """
     comments = build_comments_from_chunks(bugtask, truncate=truncate,
-        slice_info=slice_info)
+        slice_info=slice_info, show_spam_controls=show_spam_controls)
     # TODO: further fat can be shaved off here by limiting the attachments we
     # query to those that slice_info would include.
     for attachment in bugtask.bug.attachments_unpopulated:
@@ -734,8 +734,10 @@
     @cachedproperty
     def comments(self):
         """Return the bugtask's comments."""
+        show_spam_controls = check_permission(
+            'launchpad.Admin', self.context.bug)
         return get_comments_for_bugtask(self.context, truncate=True,
-            for_display=True)
+            for_display=True, show_spam_controls=show_spam_controls)
 
     @cachedproperty
     def interesting_activity(self):
@@ -781,10 +783,13 @@
             # to adjust.
             oldest_count = 1 + self.visible_initial_comments
             new_count = 1 + self.total_comments-self.visible_recent_comments
+            show_spam_controls = check_permission(
+                'launchpad.Admin', self.context.bug)
             comments = get_comments_for_bugtask(
                 self.context, truncate=True, for_display=True,
                 slice_info=[
-                    slice(None, oldest_count), slice(new_count, None)])
+                    slice(None, oldest_count), slice(new_count, None)],
+                show_spam_controls=show_spam_controls)
 
         visible_comments = get_visible_comments(
             comments, user=self.user)
@@ -3150,7 +3155,7 @@
             self.milestones = list(
                 bugtask_set.getBugTaskTargetMilestones(self.bugtasks))
         else:
-            self.milestones = []    
+            self.milestones = []
         distro_packages = defaultdict(list)
         distro_series_packages = defaultdict(list)
         for bugtask in self.bugtasks:

=== modified file 'lib/lp/bugs/browser/tests/test_bugcomment.py'
--- lib/lp/bugs/browser/tests/test_bugcomment.py	2011-02-16 08:46:05 +0000
+++ lib/lp/bugs/browser/tests/test_bugcomment.py	2011-05-10 16:19:42 +0000
@@ -12,9 +12,17 @@
 from itertools import count
 
 from pytz import utc
+from zope.component import getUtility
 
+from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
+from canonical.launchpad.testing.pages import find_tag_by_id
+from canonical.testing.layers import DatabaseFunctionalLayer
 from lp.bugs.browser.bugcomment import group_comments_with_activity
-from lp.testing import TestCase
+from lp.testing import (
+    BrowserTestCase,
+    person_logged_in,
+    TestCase,
+    )
 
 
 class BugActivityStub:
@@ -42,7 +50,7 @@
 
     def __repr__(self):
         return "BugCommentStub(%r, %d, %r)" % (
-            self.datecreated.strftime('%Y-%m-%d--%H%M'), 
+            self.datecreated.strftime('%Y-%m-%d--%H%M'),
             self.index, self.owner)
 
 
@@ -178,3 +186,90 @@
         self.assertEqual([comment1, comment2], grouped)
         self.assertEqual([activity1, activity2], comment1.activity)
         self.assertEqual([activity3], comment2.activity)
+
+
+class TestBugCommentVisibility(BrowserTestCase):
+
+    layer = DatabaseFunctionalLayer
+
+    def makeBugWithHiddenComment(self, bugbody=None):
+        administrator = getUtility(ILaunchpadCelebrities).admin.teamowner
+        bug = self.factory.makeBug()
+        with person_logged_in(administrator):
+            comment = self.factory.makeBugComment(bug=bug, body=bugbody)
+            comment.visible = False
+        return bug
+
+    def test_admin_can_see_comments(self):
+        comment_text = "You can't see me."
+        bug = self.makeBugWithHiddenComment(comment_text)
+        admin = self.factory.makeAdministrator()
+        view = self.getViewBrowser(
+            context=bug.default_bugtask, user=admin)
+        self.assertTrue(
+           comment_text in view.contents,
+           "Administrator cannot see the hidden comment.")
+
+    def test_registry_can_see_comments(self):
+        comment_text = "You can't see me."
+        bug = self.makeBugWithHiddenComment(comment_text)
+        registry_expert = self.factory.makeRegistryExpert()
+        view = self.getViewBrowser(
+            context=bug.default_bugtask, user=registry_expert)
+        self.assertTrue(
+           comment_text in view.contents,
+           "Registy member cannot see the hidden comment.")
+
+    def test_anon_cannot_see_comments(self):
+        comment_text = "You can't see me."
+        bug = self.makeBugWithHiddenComment(comment_text)
+        view = self.getViewBrowser(context=bug.default_bugtask, no_login=True)
+        self.assertFalse(
+           comment_text in view.contents,
+           "Anonymous person can see the hidden comment.")
+
+    def test_random_cannot_see_comments(self):
+        comment_text = "You can't see me."
+        bug = self.makeBugWithHiddenComment(comment_text)
+        view = self.getViewBrowser(context=bug.default_bugtask)
+        self.assertFalse(
+           comment_text in view.contents,
+           "Random user can see the hidden comment.")
+
+
+class TestBugSpamControls(BrowserTestCase):
+
+    layer = DatabaseFunctionalLayer
+
+    def makeBugWithComment(self, bugbody=None):
+        administrator = getUtility(ILaunchpadCelebrities).admin.teamowner
+        bug = self.factory.makeBug()
+        with person_logged_in(administrator):
+            self.factory.makeBugComment(bug=bug, body=bugbody)
+        return bug
+
+    def test_admin_sees_spam_control(self):
+        bug = self.makeBugWithComment()
+        administrator = self.factory.makeAdministrator()
+        view = self.getViewBrowser(context=bug, user=administrator)
+        spam_link = find_tag_by_id(view.contents, 'mark-spam-1')
+        self.assertIsNot(None, spam_link)
+
+    def test_registry_sees_spam_control(self):
+        bug = self.makeBugWithComment()
+        registry_expert = self.factory.makeRegistryExpert()
+        view = self.getViewBrowser(context=bug, user=registry_expert)
+        spam_link = find_tag_by_id(view.contents, 'mark-spam-1')
+        self.assertIsNot(None, spam_link)
+
+    def test_anon_doesnt_see_spam_control(self):
+        bug = self.makeBugWithComment()
+        view = self.getViewBrowser(context=bug, no_login=True)
+        spam_link = find_tag_by_id(view.contents, 'mark-spam-1')
+        self.assertIs(None, spam_link)
+
+    def test_random_doesnt_see_spam_control(self):
+        bug = self.makeBugWithComment()
+        view = self.getViewBrowser(context=bug)
+        spam_link = find_tag_by_id(view.contents, 'mark-spam-1')
+        self.assertIs(None, spam_link)

=== removed file 'lib/lp/bugs/browser/tests/test_bugcomment_visibility.py'
--- lib/lp/bugs/browser/tests/test_bugcomment_visibility.py	2011-04-22 12:46:12 +0000
+++ lib/lp/bugs/browser/tests/test_bugcomment_visibility.py	1970-01-01 00:00:00 +0000
@@ -1,73 +0,0 @@
-# Copyright 2011 Canonical Ltd.  This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Tests for the various rules around bug comment visibility."""
-
-__metaclass__ = type
-
-from zope.component import getUtility
-
-from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
-from canonical.testing.layers import DatabaseFunctionalLayer
-from lp.testing import (
-    BrowserTestCase,
-    person_logged_in,
-    )
-
-
-class TestBugCommentVisibility(BrowserTestCase):
-
-    layer = DatabaseFunctionalLayer
-
-    def _makeBugWithHiddenComment(self, bugbody=None):
-        administrator = getUtility(ILaunchpadCelebrities).admin.teamowner
-        bug = self.factory.makeBug()
-        with person_logged_in(administrator):
-            comment = self.factory.makeBugComment(bug=bug, body=bugbody)
-            comment.visible = False
-        return bug
-
-    def _getUserForTest(self, team=None):
-        person = self.factory.makePerson()
-        if team is not None:
-            with person_logged_in(team.teamowner):
-                team.addMember(person, team.teamowner)
-        return person
-
-    def test_admin_can_see_comments(self):
-        comment_text = "You can't see me."
-        bug = self._makeBugWithHiddenComment(comment_text)
-        admin_team = getUtility(ILaunchpadCelebrities).admin
-        administrator = self._getUserForTest(admin_team)
-        view = self.getViewBrowser(
-            context=bug.default_bugtask, user=administrator)
-        self.assertTrue(
-           comment_text in view.contents,
-           "Administrator cannot see the hidden comment.")
-
-    def test_registry_can_see_comments(self):
-        comment_text = "You can't see me."
-        bug = self._makeBugWithHiddenComment(comment_text)
-        registry_team = getUtility(ILaunchpadCelebrities).registry_experts
-        registry_expert = self._getUserForTest(registry_team)
-        view = self.getViewBrowser(
-            context=bug.default_bugtask, user=registry_expert)
-        self.assertTrue(
-           comment_text in view.contents,
-           "Registy member cannot see the hidden comment.")
-
-    def test_anon_cannot_see_comments(self):
-        comment_text = "You can't see me."
-        bug = self._makeBugWithHiddenComment(comment_text)
-        view = self.getViewBrowser(context=bug.default_bugtask, no_login=True)
-        self.assertFalse(
-           comment_text in view.contents,
-           "Anonymous person can see the hidden comment.")
-
-    def test_random_cannot_see_comments(self):
-        comment_text = "You can't see me."
-        bug = self._makeBugWithHiddenComment(comment_text)
-        view = self.getViewBrowser(context=bug.default_bugtask)
-        self.assertFalse(
-           comment_text in view.contents,
-           "Random user can see the hidden comment.")

=== added file 'lib/lp/bugs/javascript/bug_spam.js'
--- lib/lp/bugs/javascript/bug_spam.js	1970-01-01 00:00:00 +0000
+++ lib/lp/bugs/javascript/bug_spam.js	2011-05-10 16:19:42 +0000
@@ -0,0 +1,72 @@
+/* Copyright 2011 Canonical Ltd.  This software is licensed under the
+ * GNU Affero General Public License version 3 (see the file LICENSE).
+ *
+ * Animation for IBugTask:+subscribe LaunchpadForm.
+ * Also used in "Edit subscription" advanced overlay.
+ *
+ * @namespace Y.lp.answers.question_spam
+ * @requires  dom, node, lazr.effects
+ */
+YUI.add('lp.bugs.bug_spam', function(Y) {
+var namespace = Y.namespace('lp.bugs.bug_spam');
+
+var hidden_class = "adminHiddenComment";
+var spam_text = "Mark as spam";
+var not_spam_text = "Mark as not spam";
+
+function update_comment(link, comment) {
+    var text = link.get('text').trim();
+    if (text == spam_text) {
+        comment.removeClass(hidden_class);
+        link.set('text', not_spam_text);
+    } else {
+        comment.addClass(hidden_class);
+        link.set('text', spam_text);
+    }
+}
+
+function set_visibility(parameters, callbacks) {
+    var bug = LP.cache.bug;
+    var lp_client = new Y.lp.client.Launchpad();
+    var config = {
+        on: {
+            success: callbacks.success,
+            failure: callbacks.failure
+            },
+        parameters: parameters
+        }
+    lp_client.named_post(
+        bug.self_link, 'setCommentVisibility', config);
+}
+
+function toggle_spam_setting(link) {
+    var comment = link.get('parentNode').get('parentNode');
+    var visible = comment.hasClass('adminHiddenComment');
+    var comment_number = parseInt(link.get('id').replace('mark-spam-', ''));
+    parameters = {
+        visible: visible,
+        comment_number: comment_number
+        };
+    set_visibility(parameters, {
+        // We use red flash on failure so admins no it didn't work.
+        // There's no green flash on success, b/c the change in bg
+        // color provides an immediate visual cue.
+        success: function () { 
+            update_comment(link, comment);
+            comment.toggleClass(hidden_class);
+            },
+        failure: function () {
+            Y.lazr.anim.red_flash({node:comment});
+            }
+        });
+}
+namespace.toggle_spam_setting = toggle_spam_setting;
+
+function setup_spam_links() {
+  Y.on('click', function(e) {
+      e.halt();
+      namespace.toggle_spam_setting(this);
+  }, '.mark-spam');
+}
+namespace.setup_spam_links = setup_spam_links
+}, "0.1", {"requires": ["dom", "node", "lazr.anim", "lp.client"]});

=== added file 'lib/lp/bugs/javascript/tests/test_bug_spam.html'
--- lib/lp/bugs/javascript/tests/test_bug_spam.html	1970-01-01 00:00:00 +0000
+++ lib/lp/bugs/javascript/tests/test_bug_spam.html	2011-05-10 16:19:42 +0000
@@ -0,0 +1,94 @@
+<html>
+  <head>
+    <title>Launchpad Question Spam Controls</title>
+    <!-- YUI 3.0 Setup -->
+    <script type="text/javascript" src="../../../../canonical/launchpad/icing/yui/yui/yui.js"></script>
+    <script type="text/javascript"
+      src="../../../../canonical/launchpad/icing/lazr/build/lazr.js"></script>
+    <link rel="stylesheet"
+      href="../../../../canonical/launchpad/icing/yui/cssreset/reset.css"/>
+    <link rel="stylesheet"
+      href="../../../../canonical/launchpad/icing/yui/cssfonts/fonts.css"/>
+    <link rel="stylesheet"
+      href="../../../../canonical/launchpad/icing/yui/cssbase/base.css"/>
+    <link rel="stylesheet"
+      href="../../../../canonical/launchpad/javascript/test.css" />
+    <script type="text/javascript" src="../../../app/javascript/client.js"></script>
+    <script type="text/javascript" src="../../../app/javascript/lp.js"></script>
+
+    <!-- The module under test -->
+    <script type="text/javascript" src="../bug_spam.js"></script>
+
+    <!-- The test suite -->
+    <script type="text/javascript" src="test_bug_spam.js"></script>
+  </head>
+  <body class="yui-skin-sam">
+
+    <!-- The example markup required by the script to run -->
+<div class="boardComment">
+  <div class="boardCommentDetails">
+    <table>
+      <tbody>
+        <tr>
+          <td>
+              <a href="https://launchpad.dev/~name12"; class="sprite person">
+                  Sample Person
+              </a>
+            wrote
+            <span title="2004-09-24 23:24:03 SAST">on 2004-09-24</span>:
+          </td>
+          <td class="bug-comment-index">
+            <a href="/firefox/+bug/1/comments/1"> #1</a>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+  </div>
+
+  <div class="boardCommentBody">
+    <div class="bug-comment"><p>Good comment.</p></div>
+  </div>
+
+  <div class="boardCommentFooter">
+    <a class="js-action sprite edit mark-spam" href="#"
+       id="mark-spam-1">
+         Mark as spam
+    </a>
+  </div>
+</div>
+
+<div id="hidden-comment" class="boardComment adminHiddenComment">
+  <div class="boardCommentDetails">
+    <table>
+      <tbody>
+        <tr>
+          <td>
+              <a href="https://launchpad.dev/~name12"; class="sprite person">
+                  Sample Person
+              </a>
+            wrote
+            <span title="2004-09-24 23:24:03 SAST">on 2004-09-24</span>:
+          </td>
+          <td class="bug-comment-index">
+            <a href="/firefox/+bug/1/comments/1"> #1</a>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+  </div>
+
+  <div class="boardCommentBody">
+    <div class="bug-comment"><p>Bad comment.</p></div>
+  </div>
+
+  <div class="boardCommentFooter">
+    <a class="js-action sprite edit mark-spam" href="#"
+       id="mark-spam-2">
+         Mark as not spam
+    </a>
+  </div>
+</div>
+    <!-- The test output -->
+    <div id="log"></div>
+  </body>
+</html>

=== added file 'lib/lp/bugs/javascript/tests/test_bug_spam.js'
--- lib/lp/bugs/javascript/tests/test_bug_spam.js	1970-01-01 00:00:00 +0000
+++ lib/lp/bugs/javascript/tests/test_bug_spam.js	2011-05-10 16:19:42 +0000
@@ -0,0 +1,93 @@
+/* Copyright 2011 Canonical Ltd.  This software is licensed under the
+ * GNU Affero General Public License version 3 (see the file LICENSE).
+ */
+
+YUI({
+    base: '../../../../canonical/launchpad/icing/yui/',
+    filter: 'raw', combine: false,
+    fetchCSS: false,
+    }).use('test', 'console', 'node', 'node-event-simulate',
+           'lp.bugs.bug_spam', function(Y) {
+
+    var suite = new Y.Test.Suite("lp.bugs.bug_spam Tests");
+
+    suite.add(new Y.Test.Case({
+        name: 'bug_spam',
+
+        setUp: function() {
+            // Monkeypatch LP to avoid network traffic and to allow
+            // insertion of test data.
+            window.LP = {
+                links: {},
+                cache: {}
+            };
+            Y.lp.client.Launchpad = function() {};
+            Y.lp.client.Launchpad.prototype.named_post =
+                function(url, func, config) {
+                    LP.cache.call_data = {
+                        called_url: url, 
+                        called_func: func,
+                        called_config: config
+                    }
+                    // our setup assumes success, so we just do the
+                    // success callback.
+                    config.on.success();
+                };
+            LP.cache.bug = {
+                self_link: 'https://launchpad.dev/api/devel/bugs/fake'
+            };
+        },
+
+        test_mark_as_spam: function () {
+            link = Y.one('#mark-spam-1');
+            comment = Y.one('.boardComment');
+            Y.lp.bugs.bug_spam.toggle_spam_setting(link);
+            Y.Assert.isTrue(comment.hasClass('adminHiddenComment'));
+            Y.Assert.areEqual('Mark as not spam', link.get('text'),
+                'Link text should be \'Mark as not spam\'');
+            Y.Assert.areEqual(
+                'https://launchpad.dev/api/devel/bugs/fake',
+                LP.cache.call_data.called_url, 'Call with wrong url.');
+            Y.Assert.areEqual(
+                'setCommentVisibility', LP.cache.call_data.called_func,
+                'Call with wrong func.');
+            Y.Assert.isFalse(
+                LP.cache.call_data.called_config.parameters.visible);
+            Y.Assert.areEqual(
+                1, LP.cache.call_data.called_config.parameters.comment_number,
+                'Called with wrong wrong comment number.')
+            },
+        
+        test_mark_as_not_spam: function () {
+            link = Y.one('#mark-spam-2');
+            comment = Y.one('#hidden-comment');
+            Y.lp.bugs.bug_spam.toggle_spam_setting(link);
+            Y.Assert.isFalse(comment.hasClass('adminHiddenComment'));
+            Y.Assert.areEqual('Mark as spam', link.get('text'),
+                'Link text should be \'Mark as spam\'')
+            Y.Assert.areEqual(
+                'https://launchpad.dev/api/devel/bugs/fake',
+                LP.cache.call_data.called_url, 'Call with wrong url.');
+            Y.Assert.areEqual(
+                'setCommentVisibility', LP.cache.call_data.called_func,
+                'Call with wrong func.');
+            Y.Assert.isTrue(
+                LP.cache.call_data.called_config.parameters.visible);
+            Y.Assert.areEqual(
+                2, LP.cache.call_data.called_config.parameters.comment_number,
+                'Called with wrong wrong comment number.')
+            },
+
+        }));
+
+    // Lock, stock, and two smoking barrels.
+    Y.Test.Runner.add(suite);
+
+    var console = new Y.Console({newestOnTop: false});
+    console.render('#log');
+
+    Y.on('domready', function() {
+        Y.Test.Runner.run();
+        });
+});
+

=== modified file 'lib/lp/bugs/templates/bugcomment-box.pt'
--- lib/lp/bugs/templates/bugcomment-box.pt	2010-11-09 09:49:12 +0000
+++ lib/lp/bugs/templates/bugcomment-box.pt	2011-05-10 16:19:42 +0000
@@ -87,6 +87,16 @@
     </p>
   </div>
   <div class="boardCommentFooter" tal:condition="comment/show_footer">
+    <a tal:attributes="id string:mark-spam-${context/index};"
+       tal:condition="context/show_spam_controls"
+       class="js-action sprite edit mark-spam" href="#">
+         <tal:not-spam condition="not: context/visible">
+         Mark as not spam
+         </tal:not-spam>
+         <tal:spam condition="context/visible">
+         Mark as spam
+         </tal:spam>
+    </a>
     <tal:activity
         define="activity_list comment/activity"
         condition="comment/activity">

=== modified file 'lib/lp/bugs/templates/bugtask-index.pt'
--- lib/lp/bugs/templates/bugtask-index.pt	2011-04-22 12:56:09 +0000
+++ lib/lp/bugs/templates/bugtask-index.pt	2011-05-10 16:19:42 +0000
@@ -44,14 +44,18 @@
       <script type="text/javascript">
         LPS.use('base', 'node', 'oop', 'event', 'lp.bugs.bugtask_index',
                   'lp.bugs.bugtask_index.portlets',
-                  'lp.code.branchmergeproposal.diff', function(Y) {
+                  'lp.code.branchmergeproposal.diff', 'lp.bugs.bug_spam',
+                  function(Y) {
             Y.lp.bugs.bugtask_index.portlets.use_advanced_subscriptions =
                 use_advanced_subscriptions;
             Y.lp.bugs.bugtask_index.setup_bugtask_index();
             Y.on('load', function(e) {
                 Y.lp.code.branchmergeproposal.diff.connect_diff_links();
             }, window);
-        });
+            Y.on('domready', function() {
+                Y.lp.bugs.bug_spam.setup_spam_links();
+            });
+         });
       </script>
       <style type="text/css">
         /* Align the 'add comment' link to the right of the comment box. */

_______________________________________________
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to     : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp

Reply via email to