Merge lp:~wallyworld/launchpad/reassign-reviewer-cancel-option into lp:launchpad

Proposed by Ian Booth
Status: Merged
Approved by: Tim Penhey
Approved revision: no longer in the source branch.
Merged at revision: 11649
Proposed branch: lp:~wallyworld/launchpad/reassign-reviewer-cancel-option
Merge into: lp:launchpad
Diff against target: 99 lines (+30/-13)
2 files modified
lib/lp/code/browser/codereviewvote.py (+7/-2)
lib/lp/code/browser/tests/test_codereviewvote.py (+23/-11)
To merge this branch: bzr merge lp:~wallyworld/launchpad/reassign-reviewer-cancel-option
Reviewer Review Type Date Requested Status
Tim Penhey (community) Approve
Steve Kowalik (community) code* Approve
Launchpad code reviewers code Pending
Review via email: mp+36671@code.launchpad.net

Commit message

Add Cancel URL to the merge proposal Reassign Reviewer page

Description of the change

Bug 640193 requires that a Cancel link be on the merge proposal Reassign Reviewer page.

Implementation

    Simple fix - assign cancel_url in CodeReviewVoteReassign initialize() method. Also a few drive-by lint fixes.

Tests

    test -vvt test_codereviewvote

    Add new test_view_attributes() test to test_codereviewvote.py

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/code/browser/codereviewvote.py
  lib/lp/code/browser/tests/test_codereviewvote.py

To post a comment you must log in.
Revision history for this message
Steve Kowalik (stevenk) wrote :

This change looks good to me.

review: Approve (code*)
Revision history for this message
Tim Penhey (thumper) wrote :

Steve, when reviewing browser we try to avoid overriding initialize unless it
is really necessary (I don't entirely recall why), and provide as much as we
can using properties.

Also when writing tests for views there is a very useful test method called:
    create_initialized_view

So... with these two thoughts in mind I have the following suggestions:

    @property
    def next_url(self):
        return canonical_url(self.context.branch_merge_proposal)

    cancel_url = next_url

This means that you don't have to override the initialize method.

Also in the test, you should never have any database IDs, like +merge/1.

Better to assert that the cancel_url matches the canonical_url of the merge
proposal.

    self.assertEqual(canonical_url(bmp), view.cancel_url)

Also... use create_initialized_view rather than manually creating the review.

    view = create_initialized_view(vote, '+reassign')

I also find the flow of the test a little harder to follow with the multiple
login commands. I think it would read slightly better to use
with_person_logged_in (don't forget the future import if it isn't there
already).

    def test_view_cancel_url(self):
        # Check that the cancel url exists.
        bmp = self.factory.makeBranchMergeProposal()
        reviewer = self.factory.makePerson()
        with person_logged_in(bmp.registrant):
            vote = bmp.nominateReviewer(
                reviewer=reviewer, registrant=bmp.registrant)
        with person_logged_in(reviewer):
            view = create_initialized_view(vote, '+reassign')
            self.assertEqual(canonical_url(bmp), view.cancel_url)

A side note: we often use comments instead of docstrings for the test methods
because it isn't always easy to get a single line to describe the test.

review: Needs Fixing
Revision history for this message
Ian Booth (wallyworld) wrote :

Thanks for the tips. I'll address the issues raised. The approach taken
was based on looking at what had been done previously for say
MergeProposalEditView. However, I see now that case is in the minority
and most other implementations use properties :-) Trust me to find as a
template to copy from the "wrong" one :-)

The structure of the test itself, with the multiple logins and use of
docstring etc, was based on the test case just above it, the only other
one in that test class. I thought it best to maintain implementation
consistency between the two test cases. What I'll look to do then is
refactor the existing test case as well so that they are both a)
implemented as per crrent best practice, and b) consistent.

On 28/09/10 08:24, Tim Penhey wrote:
> Review: Needs Fixing
> Steve, when reviewing browser we try to avoid overriding initialize unless it
> is really necessary (I don't entirely recall why), and provide as much as we
> can using properties.
>
> Also when writing tests for views there is a very useful test method called:
> create_initialized_view
>
> So... with these two thoughts in mind I have the following suggestions:
>
> @property
> def next_url(self):
> return canonical_url(self.context.branch_merge_proposal)
>
> cancel_url = next_url
>
> This means that you don't have to override the initialize method.
>
> Also in the test, you should never have any database IDs, like +merge/1.
>
> Better to assert that the cancel_url matches the canonical_url of the merge
> proposal.
>
> self.assertEqual(canonical_url(bmp), view.cancel_url)
>
> Also... use create_initialized_view rather than manually creating the review.
>
> view = create_initialized_view(vote, '+reassign')
>
> I also find the flow of the test a little harder to follow with the multiple
> login commands. I think it would read slightly better to use
> with_person_logged_in (don't forget the future import if it isn't there
> already).
>
> def test_view_cancel_url(self):
> # Check that the cancel url exists.
> bmp = self.factory.makeBranchMergeProposal()
> reviewer = self.factory.makePerson()
> with person_logged_in(bmp.registrant):
> vote = bmp.nominateReviewer(
> reviewer=reviewer, registrant=bmp.registrant)
> with person_logged_in(reviewer):
> view = create_initialized_view(vote, '+reassign')
> self.assertEqual(canonical_url(bmp), view.cancel_url)
>
> A side note: we often use comments instead of docstrings for the test methods
> because it isn't always easy to get a single line to describe the test.
>

Revision history for this message
Tim Penhey (thumper) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/code/browser/codereviewvote.py'
--- lib/lp/code/browser/codereviewvote.py 2010-08-20 20:31:18 +0000
+++ lib/lp/code/browser/codereviewvote.py 2010-09-27 23:15:58 +0000
@@ -24,7 +24,7 @@
24class ReassignSchema(Interface):24class ReassignSchema(Interface):
25 """Schema to use when reassigning the reviewer for a requested review."""25 """Schema to use when reassigning the reviewer for a requested review."""
2626
27 reviewer = PublicPersonChoice( title=_('Reviewer'), required=True,27 reviewer = PublicPersonChoice(title=_('Reviewer'), required=True,
28 description=_('A person who you want to review this.'),28 description=_('A person who you want to review this.'),
29 vocabulary='ValidPersonOrTeam')29 vocabulary='ValidPersonOrTeam')
3030
@@ -36,11 +36,16 @@
3636
37 page_title = label = 'Reassign review request'37 page_title = label = 'Reassign review request'
3838
39 @property
40 def next_url(self):
41 return canonical_url(self.context.branch_merge_proposal)
42
43 cancel_url = next_url
44
39 @action('Reassign', name='reassign')45 @action('Reassign', name='reassign')
40 def reassign_action(self, action, data):46 def reassign_action(self, action, data):
41 """Use the form data to change the review request reviewer."""47 """Use the form data to change the review request reviewer."""
42 self.context.reassignReview(data['reviewer'])48 self.context.reassignReview(data['reviewer'])
43 self.next_url = canonical_url(self.context.branch_merge_proposal)
4449
45 def validate(self, data):50 def validate(self, data):
46 """Make sure that the reassignment can happen."""51 """Make sure that the reassignment can happen."""
4752
=== modified file 'lib/lp/code/browser/tests/test_codereviewvote.py'
--- lib/lp/code/browser/tests/test_codereviewvote.py 2010-08-20 20:31:18 +0000
+++ lib/lp/code/browser/tests/test_codereviewvote.py 2010-09-27 23:15:58 +0000
@@ -1,22 +1,22 @@
1# Copyright 2009 Canonical Ltd. This software is licensed under the1# Copyright 2009 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4
5"""Unit tests for CodeReviewVoteReferences."""4"""Unit tests for CodeReviewVoteReferences."""
65
6from __future__ import with_statement
77
8__metaclass__ = type8__metaclass__ = type
99
1010
11import unittest11import unittest
1212
13from canonical.launchpad.webapp.servers import LaunchpadTestRequest13from canonical.launchpad.webapp import canonical_url
14from canonical.testing import DatabaseFunctionalLayer14from canonical.testing import DatabaseFunctionalLayer
15from lp.code.browser.codereviewvote import CodeReviewVoteReassign
16from lp.testing import (15from lp.testing import (
17 login_person,16 person_logged_in,
18 TestCaseWithFactory,17 TestCaseWithFactory,
19 )18 )
19from lp.testing.views import create_initialized_view
2020
2121
22class TestReassignReviewer(TestCaseWithFactory):22class TestReassignReviewer(TestCaseWithFactory):
@@ -25,18 +25,30 @@
25 layer = DatabaseFunctionalLayer25 layer = DatabaseFunctionalLayer
2626
27 def test_reassign(self):27 def test_reassign(self):
28 """A reviewer can reassign their vote to someone else."""28 # A reviewer can reassign their vote to someone else.
29 bmp = self.factory.makeBranchMergeProposal()29 bmp = self.factory.makeBranchMergeProposal()
30 reviewer = self.factory.makePerson()30 reviewer = self.factory.makePerson()
31 login_person(bmp.registrant)31 with person_logged_in(bmp.registrant):
32 vote = bmp.nominateReviewer(32 vote = bmp.nominateReviewer(
33 reviewer=reviewer, registrant=bmp.registrant)33 reviewer=reviewer, registrant=bmp.registrant)
34 new_reviewer = self.factory.makePerson()34 new_reviewer = self.factory.makePerson()
35 login_person(reviewer)35 with person_logged_in(reviewer):
36 view = CodeReviewVoteReassign(vote, LaunchpadTestRequest())36 view = create_initialized_view(vote, '+reassign')
37 view.reassign_action.success({'reviewer': new_reviewer})37 view.reassign_action.success({'reviewer': new_reviewer})
38 self.assertEqual(vote.reviewer, new_reviewer)38 self.assertEqual(vote.reviewer, new_reviewer)
3939
40 def test_view_attributes(self):
41 # Check various urls etc on view are correct.
42 # At the moment, there's just the one: cancel_url
43 bmp = self.factory.makeBranchMergeProposal()
44 reviewer = self.factory.makePerson()
45 with person_logged_in(bmp.registrant):
46 vote = bmp.nominateReviewer(
47 reviewer=reviewer, registrant=bmp.registrant)
48 with person_logged_in(reviewer):
49 view = create_initialized_view(vote, '+reassign')
50 self.assertEqual(canonical_url(bmp), view.cancel_url)
51
4052
41def test_suite():53def test_suite():
42 return unittest.TestLoader().loadTestsFromName(__name__)54 return unittest.TestLoader().loadTestsFromName(__name__)