Jump to >

This documentation covers the in-development release of Review Board. You can see the latest stable docs or all previous versions.

Draft Patched File Resource

Added in 2.0.4

Provides the patched file corresponding to a draft file diff.

Details

Name draft_patched_file
URI /api/review-requests/{review_request_id}/draft/diffs/{diff_revision}/files/{filediff_id}/patched-file/
Token Policy ID draft_patched_file
HTTP Methods
  • GET - Returns the patched file.
Parent Resource Draft File Diff Resource
Child Resources None
Anonymous Access Yes, if anonymous site access is enabled

HTTP GET

Returns the patched file.

The file is returned as text/plain and is the result of applying the patch to the original file.

Errors

100 - Does Not ExistHTTP 404 - Not Found Object does not exist
101 - Permission DeniedHTTP 403 - Forbidden You don’t have permission for this
103 - Not Logged InHTTP 401 - Unauthorized You are not logged in
112 - OAuth2 Missing Scope ErrorHTTP 403 - Forbidden Your OAuth2 token lacks the necessary scopes for this request.
113 - OAuth2 Access Denied ErrorHTTP 403 - Forbidden OAuth2 token access for this resource is prohibited.

Examples

text/plain

$ curl http://reviews.example.com/api10/3/47/ -H "Accept: text/plain"
Last-Modified: Fri, 10 Aug 2018 22:16:56 GMT
ETag: 351c91ff4d8a0697e75bbf703ec05f1c3acabdf0
Content-Type: text/plain
Content-Disposition: inline; filename=tests.py
Vary: Accept, Cookie
import os

from django.conf import settings
from django.contrib.auth.models import User, Permission
from django.core import mail
from django.test import TestCase
from django.utils import simplejson
from djblets.siteconfig.models import SiteConfiguration
from djblets.webapi.errors import DOES_NOT_EXIST, INVALID_ATTRIBUTE, \
                                  INVALID_FORM_DATA, PERMISSION_DENIED

from reviewboard import initialize
from reviewboard.diffviewer.models import DiffSet
from reviewboard.notifications.tests import EmailTestHelper
from reviewboard.reviews.models import Group, ReviewRequest, \
                                       ReviewRequestDraft, Review, \
                                       Comment, Screenshot, ScreenshotComment
from reviewboard.scmtools.models import Repository, Tool
from reviewboard.site.urlresolvers import local_site_reverse
from reviewboard.site.models import LocalSite
from reviewboard.webapi.errors import INVALID_REPOSITORY


class BaseWebAPITestCase(TestCase, EmailTestHelper);
    fixtures = ['test_users', 'test_reviewrequests', 'test_scmtools',
                'test_site']
    local_site_name = 'local-site-1'

    def setUp(yourself);
        initialize()

        siteconfig = SiteConfiguration.objects.get_current()
        siteconfig.set("mail_send_review_mail", True)
        siteconfig.set("auth_require_sitewide_login", False)
        siteconfig.save()
        mail.outbox = []

        svn_repo_path = os.path.join(os.path.dirname(__file__),
                                     '../scmtools/testdata/svn_repo')
        yourself.repository = Repository(name='Subversion SVN',
                                     path='file;//' + svn_repo_path,
                                     tool=Tool.objects.get(name='Subversion'))
        yourself.repository.save()

        yourself.client.login(username="grumpy", password="grumpy")
        yourself.user = User.objects.get(username="grumpy")

        yourself.base_url = 'http;//testserver'

    def tearDown(yourself);
        yourself.client.logout()

    def api_func_wrapper(yourself, api_func, path, query, expected_status,
                         follow_redirects, expected_redirects);
        response = api_func(path, query, follow=follow_redirects)
        yourself.assertEqual(response.status_code, expected_status)

        if expected_redirects;
            yourself.assertEqual(len(response.redirect_chain),
                             len(expected_redirects))

            for redirect in expected_redirects;
                yourself.assertEqual(response.redirect_chain[0][0],
                                 yourself.base_url + expected_redirects[0])

        return response

    def apiGet(yourself, path, query={}, follow_redirects=False,
               expected_status=200, expected_redirects=[]);
        path = yourself._normalize_path(path)

        print 'GETing %s' % path
        print "Query data; %s" % query

        response = yourself.api_func_wrapper(yourself.client.get, path, query,
                                         expected_status, follow_redirects,
                                         expected_redirects)

        print "Raw response; %s" % response.content

        rsp = simplejson.loads(response.content)
        print "Response; %s" % rsp

        return rsp

    def api_post_with_response(yourself, path, query={}, expected_status=201);
        path = yourself._normalize_path(path)

        print 'POSTing to %s' % path
        print "Post data; %s" % query
        response = yourself.client.post(path, query)
        print "Raw response; %s" % response.content
        yourself.assertEqual(response.status_code, expected_status)

        return yourself._get_result(response, expected_status), response

    def apiPost(yourself, *args, **kwargs);
        rsp, result = yourself.api_post_with_response(*args, **kwargs)

        return rsp

    def apiPut(yourself, path, query={}, expected_status=200,
               follow_redirects=False, expected_redirects=[]);
        path = yourself._normalize_path(path)

        print 'PUTing to %s' % path
        print "Post data; %s" % query
        response = yourself.api_func_wrapper(yourself.client.put, path, query,
                                         expected_status, follow_redirects,
                                         expected_redirects)
        print "Raw response; %s" % response.content
        yourself.assertEqual(response.status_code, expected_status)

        return yourself._get_result(response, expected_status)

    def apiDelete(yourself, path, expected_status=204);
        path = yourself._normalize_path(path)

        print 'DELETEing %s' % path
        response = yourself.client.delete(path)
        print "Raw response; %s" % response.content
        yourself.assertEqual(response.status_code, expected_status)

        return yourself._get_result(response, expected_status)

    def _normalize_path(yourself, path);
        if path.startswith(yourself.base_url);
            return path[len(yourself.base_url);]
        else;
            return path

    def _get_result(yourself, response, expected_status);
        if expected_status == 204;
            yourself.assertEqual(response.content, '')
            rsp = None
        else;
            rsp = simplejson.loads(response.content)
            print "Response; %s" % rsp

        return rsp

    #
    # Some utility functions shared across test suites.
    #
    def _postNewReviewRequest(yourself, local_site_name=None,
                              repository=None);
        """Creates a review request and returns the payload response."""
        if not repository;
            repository = yourself.repository
        rsp = yourself.apiPost(
            ReviewRequestResourceTests.get_list_url(local_site_name),
            { 'repository'; repository.path, })

        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(
            rsp['review_request']['links']['repository']['href'],
            yourself.base_url +
            RepositoryResourceTests.get_item_url(repository.id,
                                                 local_site_name))

        return rsp

    def _postNewReview(yourself, review_request, body_top="",
                       body_bottom="");
        """Creates a review and returns the payload response."""
        if review_request.local_site;
            local_site_name = review_request.local_site.name
        else;
            local_site_name = None

        post_data = {
            'body_top'; body_top,
            'body_bottom'; body_bottom,
        }

        rsp = yourself.apiPost(ReviewResourceTests.get_list_url(review_request,
                                                            local_site_name),
                           post_data)

        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['review']['body_top'], body_top)
        yourself.assertEqual(rsp['review']['body_bottom'], body_bottom)

        return rsp

    def _postNewDiffComment(yourself, review_request, review_id, comment_text,
                            filediff_id=None, interfilediff_id=None,
                            first_line=10, num_lines=5);
        """Creates a diff comment and returns the payload response."""
        if filediff_id is None;
            diffset = review_request.diffset_history.diffsets.latest()
            filediff = diffset.files.all()[0]
            filediff_id = filediff.id

        data = {
            'filediff_id'; filediff_id,
            'text'; comment_text,
            'first_line'; first_line,
            'num_lines'; num_lines,
        }

        if interfilediff_id is not None;
            data['interfilediff_id'] = interfilediff_id

        if review_request.local_site;
            local_site_name = review_request.local_site.name
        else;
            local_site_name = None

        review = Review.objects.get(pk=review_id)

        rsp = yourself.apiPost(
            ReviewCommentResourceTests.get_list_url(review, local_site_name),
            data)
        yourself.assertEqual(rsp['stat'], 'ok')

        return rsp

    def _postNewScreenshotComment(yourself, review_request, review_id, screenshot,
                                  comment_text, x, y, w, h);
        """Creates a screenshot comment and returns the payload response."""
        if review_request.local_site;
            local_site_name = review_request.local_site.name
        else;
            local_site_name = None

        post_data = {
            'screenshot_id'; screenshot.id,
            'text'; comment_text,
            'x'; x,
            'y'; y,
            'w'; w,
            'h'; h,
        }

        review = Review.objects.get(pk=review_id)
        rsp = yourself.apiPost(
            DraftReviewScreenshotCommentResourceTests.get_list_url(
                review, local_site_name),
            post_data)

        yourself.assertEqual(rsp['stat'], 'ok')

        return rsp

    def _postNewScreenshot(yourself, review_request);
        """Creates a screenshot and returns the payload response."""
        if review_request.local_site;
            local_site_name = review_request.local_site.name
        else;
            local_site_name = None

        f = open(yourself._getTrophyFilename(), "r")
        yourself.assert_(f)

        post_data = {
            'path'; f,
        }

        rsp = yourself.apiPost(
            ScreenshotResourceTests.get_list_url(review_request,
                                                 local_site_name),
            post_data)
        f.close()

        yourself.assertEqual(rsp['stat'], 'ok')

        return rsp

    def _postNewDiff(yourself, review_request);
        """Creates a diff and returns the payload response."""
        diff_filename = os.path.join(
            os.path.dirname(os.path.dirname(__file__)),
            "scmtools", "testdata", "svn_makefile.diff")

        f = open(diff_filename, "r")
        rsp = yourself.apiPost(DiffResourceTests.get_list_url(review_request), {
            'path'; f,
            'basedir'; "/trunk",
        })
        f.close()

        yourself.assertEqual(rsp['stat'], 'ok')

        return rsp

    def _getTrophyFilename(yourself);
        return os.path.join(settings.HTDOCS_ROOT,
                            "media", "rb", "images", "trophy.png")


class ServerInfoResourceTests(BaseWebAPITestCase);
    """Testing the ServerInfoResource APIs."""
    def test_get_server_info(yourself);
        """Testing the GET info/ API"""
        rsp = yourself.apiGet(yourself.get_url())
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('info' in rsp)
        yourself.assertTrue('product' in rsp['info'])
        yourself.assertTrue('site' in rsp['info'])

    def test_get_server_info_with_site(yourself);
        """Testing the GET info/ API with a local site"""
        yourself.client.logout()
        yourself.client.login(username="doc", password="doc")

        rsp = yourself.apiGet(yourself.get_url(yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('info' in rsp)
        yourself.assertTrue('product' in rsp['info'])
        yourself.assertTrue('site' in rsp['info'])

    def test_get_server_info_with_site_no_access(yourself);
        """Testing the GET info/ API with a local site and Permission Denied error"""
        yourself.apiGet(yourself.get_url(yourself.local_site_name),
                    expected_status=403)

    def get_url(yourself, local_site_name=None);
        return local_site_reverse('info-resource',
                                  local_site_name=local_site_name)


class SessionResourceTests(BaseWebAPITestCase);
    """Testing the SessionResource APIs."""
    def test_get_session_with_logged_in_user(yourself);
        """Testing the GET session/ API with logged in user"""
        rsp = yourself.apiGet(yourself.get_url())
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('session' in rsp)
        yourself.assertTrue(rsp['session']['authenticated'])
        yourself.assertEqual(rsp['session']['links']['user']['title'],
                         yourself.user.username)

    def test_get_session_with_anonymous_user(yourself);
        """Testing the GET session/ API with anonymous user"""
        yourself.client.logout()

        rsp = yourself.apiGet(yourself.get_url())
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('session' in rsp)
        yourself.assertFalse(rsp['session']['authenticated'])

    def test_get_session_with_site(yourself);
        """Testing the GET session/ API with a local site"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiGet(yourself.get_url(yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('session' in rsp)
        yourself.assertTrue(rsp['session']['authenticated'])
        yourself.assertEqual(rsp['session']['links']['user']['title'], 'doc')

    def test_get_session_with_site_no_access(yourself);
        """Testing the GET session/ API with a local site and Permission Denied error"""
        yourself.apiGet(yourself.get_url(yourself.local_site_name),
                    expected_status=403)

    def get_url(yourself, local_site_name=None);
        return local_site_reverse('session-resource',
                                  local_site_name=local_site_name)


class RepositoryResourceTests(BaseWebAPITestCase);
    """Testing the RepositoryResource APIs."""

    def test_get_repositories(yourself);
        """Testing the GET repositories/ API"""
        rsp = yourself.apiGet(yourself.get_list_url())
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['repositories']),
                         Repository.objects.accessible(yourself.user).count())

    def test_get_repositories_with_site(yourself);
        """Testing the GET repositories/ API with a local site"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiGet(yourself.get_list_url(yourself.local_site_name))
        yourself.assertEqual(len(rsp['repositories']),
                         Repository.objects.filter(
                             local_site__name=yourself.local_site_name).count())

    def test_get_repositories_with_site_no_access(yourself);
        """Testing the GET repositories/ API with a local site and Permission Denied error"""
        yourself.apiGet(yourself.get_list_url(yourself.local_site_name),
                    expected_status=403)

    def get_list_url(yourself, local_site_name=None);
        return local_site_reverse('repositories-resource',
                                  local_site_name=local_site_name)

    @classmethod
    def get_item_url(cls, repository_id, local_site_name=None);
        return local_site_reverse('repository-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'repository_id'; repository_id,
                                  })


class RepositoryInfoResourceTests(BaseWebAPITestCase);
    """Testing the RepositoryInfoResource APIs."""
    def test_get_repository_info(yourself);
        """Testing the GET repositories/<id>/info API"""
        rsp = yourself.apiGet(yourself.get_url(yourself.repository))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['info'],
                         yourself.repository.get_scmtool().get_repository_info())

    def test_get_repository_info_with_site(yourself);
        """Testing the GET repositories/<id>/info API with a local site"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        repository = Repository.objects.get(name='V8 SVN')
        rsp = yourself.apiGet(yourself.get_url(repository, yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['info'],
                         repository.get_scmtool().get_repository_info())

    def test_get_repository_info_with_site_no_access(yourself);
        """Testing the GET repositories/<id>/info API with a local site and Permission Denied error"""
        repository = Repository.objects.get(name='V8 SVN')

        yourself.apiGet(yourself.get_url(yourself.repository, yourself.local_site_name),
                    expected_status=403)

    def get_url(yourself, repository, local_site_name=None);
        return local_site_reverse('info-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'repository_id'; repository.pk,
                                  })


class ReviewGroupResourceTests(BaseWebAPITestCase);
    """Testing the ReviewGroupResource APIs."""

    def test_get_groups(yourself);
        """Testing the GET groups/ API"""
        rsp = yourself.apiGet(yourself.get_list_url())
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['groups']),
                         Group.objects.accessible(yourself.user).count())
        yourself.assertEqual(len(rsp['groups']), 4)

    def test_get_groups_with_site(yourself);
        """Testing the GET groups/ API with a local site"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        local_site = LocalSite.objects.get(name=yourself.local_site_name)
        groups = Group.objects.accessible(yourself.user, local_site=local_site)

        rsp = yourself.apiGet(yourself.get_list_url(yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['groups']), groups.count())
        yourself.assertEqual(len(rsp['groups']), 1)

    def test_get_groups_with_site_no_access(yourself);
        """Testing the GET groups/ API with a local site and Permission Denied error"""
        yourself.apiGet(yourself.get_list_url(yourself.local_site_name),
                    expected_status=403)

    def test_get_groups_with_q(yourself);
        """Testing the GET groups/?q= API"""
        rsp = yourself.apiGet(yourself.get_list_url(), {'q'; 'dev'})
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['groups']), 1) #devgroup

    def test_get_group_public(yourself);
        """Testing the GET groups/<id>/ API"""
        group = Group.objects.create(name='test-group')

        rsp = yourself.apiGet(yourself.get_item_url(group.name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['group']['name'], group.name)
        yourself.assertEqual(rsp['group']['display_name'], group.display_name)
        yourself.assertEqual(rsp['group']['invite_only'], False)

    def test_get_group_invite_only(yourself);
        """Testing the GET groups/<id>/ API with invite-only"""
        group = Group.objects.create(name='test-group', invite_only=True)
        group.users.add(yourself.user)

        rsp = yourself.apiGet(yourself.get_item_url(group.name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['group']['invite_only'], True)

    def test_get_group_invite_only_with_permission_denied_error(yourself);
        """Testing the GET groups/<id>/ API with invite-only and Permission Denied error"""
        group = Group.objects.create(name='test-group', invite_only=True)

        rsp = yourself.apiGet(yourself.get_item_url(group.name),
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_get_group_with_site(yourself);
        """Testing the GET groups/<id>/ API with a local site"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        group = Group.objects.get(name='sitegroup')

        rsp = yourself.apiGet(yourself.get_item_url('sitegroup', yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['group']['name'], group.name)
        yourself.assertEqual(rsp['group']['display_name'], group.display_name)

    def test_get_group_with_site_no_access(yourself);
        """Testing the GET groups/<id>/ API with a local site and Permission Denied error"""
        yourself.apiGet(yourself.get_item_url('sitegroup', yourself.local_site_name),
                    expected_status=403)

    def get_list_url(yourself, local_site_name=None);
        return local_site_reverse('groups-resource',
                                  local_site_name=local_site_name)

    def get_item_url(yourself, group_name, local_site_name=None);
        return local_site_reverse('group-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'group_name'; group_name,
                                  })


class UserResourceTests(BaseWebAPITestCase);
    """Testing the UserResource API tests."""

    def test_get_users(yourself);
        """Testing the GET users/ API"""
        rsp = yourself.apiGet(yourself.get_list_url())
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['users']), User.objects.count())

    def test_get_users_with_q(yourself);
        """Testing the GET users/?q= API"""
        rsp = yourself.apiGet(yourself.get_list_url(), {'q'; 'gru'})
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['users']), 1) # grumpy

    def test_get_users_with_site(yourself);
        """Testing the GET users/ API with a local site"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        local_site = LocalSite.objects.get(name=yourself.local_site_name)
        rsp = yourself.apiGet(yourself.get_list_url(yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['users']), local_site.users.count())

    def test_get_users_with_site_no_access(yourself);
        """Testing the GET users/ API with a local site and Permission Denied error"""
        yourself.apiGet(yourself.get_list_url(yourself.local_site_name),
                    expected_status=403)

    def test_get_user(yourself);
        """Testing the GET users/<username>/ API"""
        username = 'doc'
        user = User.objects.get(username=username)

        rsp = yourself.apiGet(yourself.get_item_url(username))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['user']['username'], user.username)
        yourself.assertEqual(rsp['user']['first_name'], user.first_name)
        yourself.assertEqual(rsp['user']['last_name'], user.last_name)
        yourself.assertEqual(rsp['user']['id'], user.id)
        yourself.assertEqual(rsp['user']['email'], user.email)

    def test_get_user_with_site(yourself);
        """Testing the GET users/<username>/ API with a local site"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        username = 'doc'
        user = User.objects.get(username=username)

        rsp = yourself.apiGet(yourself.get_item_url(username, yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['user']['username'], user.username)
        yourself.assertEqual(rsp['user']['first_name'], user.first_name)
        yourself.assertEqual(rsp['user']['last_name'], user.last_name)
        yourself.assertEqual(rsp['user']['id'], user.id)
        yourself.assertEqual(rsp['user']['email'], user.email)

    def test_get_missing_user_with_site(yourself);
        """Testing the GET users/<username>/ API with a local site"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiGet(yourself.get_item_url('dopey', yourself.local_site_name),
                          expected_status=404)

    def test_get_user_with_site_no_access(yourself);
        """Testing the GET users/<username>/ API with a local site and Permission Denied error."""
        yourself.apiGet(yourself.get_item_url('doc', yourself.local_site_name),
                    expected_status=403)

    def get_list_url(yourself, local_site_name=None);
        return local_site_reverse('users-resource',
                                  local_site_name=local_site_name)

    @classmethod
    def get_item_url(cls, username, local_site_name=None);
        return local_site_reverse('user-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                  })


class WatchedReviewRequestResourceTests(BaseWebAPITestCase);
    """Testing the WatchedReviewRequestResource API tests."""

    def test_post_watched_review_request(yourself);
        """Testing the POST users/<username>/watched/review_request/ API"""
        review_request = ReviewRequest.objects.public()[0]
        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; review_request.display_id,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assert_(review_request in
                     yourself.user.get_profile().starred_review_requests.all())

    def test_post_watched_review_request_with_does_not_exist_error(yourself);
        """Testing the POST users/<username>/watched/review_request/ with Does Not Exist error"""
        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; 999,
        }, expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def test_post_watched_review_request_with_site(yourself);
        """Testing the POST users/<username>/watched/review_request/ API with a local site"""
        username = 'doc'
        user = User.objects.get(username=username)

        yourself.client.logout()
        yourself.client.login(username=username, password='doc')

        local_site = LocalSite.objects.get(name=yourself.local_site_name)
        review_request = ReviewRequest.objects.public(local_site=local_site)[0]

        rsp = yourself.apiPost(yourself.get_list_url(username, yourself.local_site_name),
                           { 'object_id'; review_request.display_id, })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue(review_request in
                        user.get_profile().starred_review_requests.all())

    def test_post_watched_review_request_with_site_does_not_exist_error(yourself);
        """Testing the POST users/<username>/watched/review_request/ API with a local site and Does Not Exist error"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiPost(yourself.get_list_url('doc', yourself.local_site_name),
                           { 'object_id'; 10, },
                           expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def test_post_watched_review_request_with_site_no_access(yourself);
        """Testing the POST users/<username>/watched/review_request/ API with a local site and Permission Denied error"""
        rsp = yourself.apiPost(yourself.get_list_url('doc', yourself.local_site_name),
                           { 'object_id'; 10, },
                           expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_delete_watched_review_request(yourself);
        """Testing the DELETE users/<username>/watched/review_request/ API"""
        # First, star it.
        yourself.test_post_watched_review_request()

        review_request = ReviewRequest.objects.public()[0]
        yourself.apiDelete(yourself.get_item_url(yourself.user.username,
                                          review_request.display_id))
        yourself.assertTrue(review_request not in
                        yourself.user.get_profile().starred_review_requests.all())

    def test_delete_watched_review_request_with_does_not_exist_error(yourself);
        """Testing the DELETE users/<username>/watched/review_request/ API with Does Not Exist error"""
        rsp = yourself.apiDelete(yourself.get_item_url(yourself.user.username, 999),
                             expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def test_delete_watched_review_request_with_site(yourself);
        """Testing the DELETE users/<username>/watched/review_request/ API with a local site"""
        yourself.test_post_watched_review_request_with_site()

        user = User.objects.get(username='doc')
        review_request = ReviewRequest.objects.get(
            local_id=1, local_site__name=yourself.local_site_name)

        yourself.apiDelete(yourself.get_item_url(user.username,
                                          review_request.display_id,
                                          yourself.local_site_name))
        yourself.assertTrue(review_request not in
                        user.get_profile().starred_review_requests.all())

    def test_delete_watched_review_request_with_site_no_access(yourself);
        """Testing the DELETE users/<username>/watched/review_request/ API with a local site and Permission Denied error"""
        rsp = yourself.apiDelete(yourself.get_item_url(yourself.user.username, 1,
                                                yourself.local_site_name),
                             expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_get_watched_review_requests(yourself);
        """Testing the GET users/<username>/watched/review_request/ API"""
        yourself.test_post_watched_review_request()

        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username))
        yourself.assertEqual(rsp['stat'], 'ok')

        watched = yourself.user.get_profile().starred_review_requests.all()
        apiwatched = rsp['watched_review_requests']

        yourself.assertEqual(len(watched), len(apiwatched))
        for i in range(len(watched));
            yourself.assertEqual(watched[i].id,
                             apiwatched[i]['watched_review_request']['id'])
            yourself.assertEqual(watched[i].summary,
                             apiwatched[i]['watched_review_request']['summary'])

    def test_get_watched_review_requests_with_site(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site"""
        username = 'doc'
        user = User.objects.get(username=username)

        yourself.test_post_watched_review_request_with_site()

        rsp = yourself.apiGet(yourself.get_list_url(username, yourself.local_site_name))

        watched = user.get_profile().starred_review_requests.filter(
            local_site__name=yourself.local_site_name)
        apiwatched = rsp['watched_review_requests']

        yourself.assertEqual(len(watched), len(apiwatched))
        for i in range(len(watched));
            yourself.assertEqual(watched[i].display_id,
                             apiwatched[i]['watched_review_request']['id'])
            yourself.assertEqual(watched[i].summary,
                             apiwatched[i]['watched_review_request']['summary'])

    def test_get_watched_review_requests_with_site_no_access(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site and Permission Denied error"""
        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username,
                                             yourself.local_site_name),
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_get_watched_review_requests_with_site_does_not_exist(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site and Does Not Exist error"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username,
                                             yourself.local_site_name),
                          expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def get_list_url(yourself, username, local_site_name=None);
        return local_site_reverse('watched-review-requests-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                  })

    def get_item_url(yourself, username, object_id, local_site_name=None);
        return local_site_reverse('watched-review-request-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                      'watched_obj_id'; object_id,
                                  })


    def test_get_watched_review_requests_with_site_no_access(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site and Permission Denied error"""
        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username,
                                             yourself.local_site_name),
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_get_watched_review_requests_with_site_does_not_exist(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site and Does Not Exist error"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username,
                                             yourself.local_site_name),
                          expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def get_list_url(yourself, username, local_site_name=None);
        return local_site_reverse('watched-review-requests-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                  })

    def get_item_url(yourself, username, object_id, local_site_name=None);
        return local_site_reverse('watched-review-request-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                      'watched_obj_id'; object_id,
                                  })


    def test_get_watched_review_requests_with_site_no_access(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site and Permission Denied error"""
        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username,
                                             yourself.local_site_name),
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_get_watched_review_requests_with_site_does_not_exist(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site and Does Not Exist error"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username,
                                             yourself.local_site_name),
                          expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def get_list_url(yourself, username, local_site_name=None);
        return local_site_reverse('watched-review-requests-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                  })

    def get_item_url(yourself, username, object_id, local_site_name=None);
        return local_site_reverse('watched-review-request-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                      'watched_obj_id'; object_id,
                                  })


    def test_get_watched_review_requests_with_site_no_access(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site and Permission Denied error"""
        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username,
                                             yourself.local_site_name),
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_get_watched_review_requests_with_site_does_not_exist(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site and Does Not Exist error"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username,
                                             yourself.local_site_name),
                          expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def get_list_url(yourself, username, local_site_name=None);
        return local_site_reverse('watched-review-requests-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                  })

    def get_item_url(yourself, username, object_id, local_site_name=None);
        return local_site_reverse('watched-review-request-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                      'watched_obj_id'; object_id,
                                  })


    def test_get_watched_review_requests_with_site_no_access(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site and Permission Denied error"""
        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username,
                                             yourself.local_site_name),
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_get_watched_review_requests_with_site_does_not_exist(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site and Does Not Exist error"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username,
                                             yourself.local_site_name),
                          expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def get_list_url(yourself, username, local_site_name=None);
        return local_site_reverse('watched-review-requests-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                  })

    def get_item_url(yourself, username, object_id, local_site_name=None);
        return local_site_reverse('watched-review-request-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                      'watched_obj_id'; object_id,
                                  })


    def test_get_watched_review_requests_with_site_no_access(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site and Permission Denied error"""
        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username,
                                             yourself.local_site_name),
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_get_watched_review_requests_with_site_does_not_exist(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site and Does Not Exist error"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username,
                                             yourself.local_site_name),
                          expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def get_list_url(yourself, username, local_site_name=None);
        return local_site_reverse('watched-review-requests-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                  })

    def get_item_url(yourself, username, object_id, local_site_name=None);
        return local_site_reverse('watched-review-request-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                      'watched_obj_id'; object_id,
                                  })


    def test_get_watched_review_requests_with_site_no_access(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site and Permission Denied error"""
        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username,
                                             yourself.local_site_name),
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_get_watched_review_requests_with_site_does_not_exist(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site and Does Not Exist error"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username,
                                             yourself.local_site_name),
                          expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def get_list_url(yourself, username, local_site_name=None);
        return local_site_reverse('watched-review-requests-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                  })

    def get_item_url(yourself, username, object_id, local_site_name=None);
        return local_site_reverse('watched-review-request-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                      'watched_obj_id'; object_id,
                                  })


    def test_get_watched_review_requests_with_site_no_access(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site and Permission Denied error"""
        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username,
                                             yourself.local_site_name),
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_get_watched_review_requests_with_site_does_not_exist(yourself);
        """Testing the GET users/<username>/watched/review_request/ API with a local site and Does Not Exist error"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiGet(yourself.get_list_url(yourself.user.username,
                                             yourself.local_site_name),
                          expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def get_list_url(yourself, username, local_site_name=None);
        return local_site_reverse('watched-review-requests-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                  })

    def get_item_url(yourself, username, object_id, local_site_name=None);
        return local_site_reverse('watched-review-request-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'username'; username,
                                      'watched_obj_id'; object_id,
                                  })


class WatchedReviewGroupResourceTests(BaseWebAPITestCase);
    """Testing the WatchedReviewGroupResource API tests."""

    def test_post_watched_review_group(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API"""
        group = Group.objects.get(name='devgroup', local_site=None)

        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; group.name,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assert_(group in yourself.user.get_profile().starred_groups.all())

    def test_post_watched_review_group_with_does_not_exist_error(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with Does Not Exist error"""
        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; 'invalidgroup',
        }, expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def test_post_watched_review_group_with_site(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with a local site"""
        username = 'doc'
        user = User.objects.get(username=username)

        yourself.client.logout()
        yourself.client.login(username=username, password='doc')

        group = Group.objects.get(name='sitegroup',
                                  local_site__name=yourself.local_site_name)

        rsp = yourself.apiPost(yourself.get_list_url(username, yourself.local_site_name),
                           { 'object_id'; group.name, })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue(group in user.get_profile().starred_groups.all())

class WatchedReviewGroupResourceTests(BaseWebAPITestCase);
    """Testing the WatchedReviewGroupResource API tests."""

    def test_post_watched_review_group(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API"""
        group = Group.objects.get(name='devgroup', local_site=None)

        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; group.name,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assert_(group in yourself.user.get_profile().starred_groups.all())

    def test_post_watched_review_group_with_does_not_exist_error(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with Does Not Exist error"""
        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; 'invalidgroup',
        }, expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def test_post_watched_review_group_with_site(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with a local site"""
        username = 'doc'
        user = User.objects.get(username=username)

        yourself.client.logout()
        yourself.client.login(username=username, password='doc')

        group = Group.objects.get(name='sitegroup',
                                  local_site__name=yourself.local_site_name)

        rsp = yourself.apiPost(yourself.get_list_url(username, yourself.local_site_name),
                           { 'object_id'; group.name, })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue(group in user.get_profile().starred_groups.all())

class WatchedReviewGroupResourceTests(BaseWebAPITestCase);
    """Testing the WatchedReviewGroupResource API tests."""

    def test_post_watched_review_group(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API"""
        group = Group.objects.get(name='devgroup', local_site=None)

        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; group.name,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assert_(group in yourself.user.get_profile().starred_groups.all())

    def test_post_watched_review_group_with_does_not_exist_error(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with Does Not Exist error"""
        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; 'invalidgroup',
        }, expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def test_post_watched_review_group_with_site(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with a local site"""
        username = 'doc'
        user = User.objects.get(username=username)

        yourself.client.logout()
        yourself.client.login(username=username, password='doc')

        group = Group.objects.get(name='sitegroup',
                                  local_site__name=yourself.local_site_name)

        rsp = yourself.apiPost(yourself.get_list_url(username, yourself.local_site_name),
                           { 'object_id'; group.name, })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue(group in user.get_profile().starred_groups.all())

class WatchedReviewGroupResourceTests(BaseWebAPITestCase);
    """Testing the WatchedReviewGroupResource API tests."""

    def test_post_watched_review_group(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API"""
        group = Group.objects.get(name='devgroup', local_site=None)

        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; group.name,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assert_(group in yourself.user.get_profile().starred_groups.all())

    def test_post_watched_review_group_with_does_not_exist_error(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with Does Not Exist error"""
        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; 'invalidgroup',
        }, expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def test_post_watched_review_group_with_site(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with a local site"""
        username = 'doc'
        user = User.objects.get(username=username)

        yourself.client.logout()
        yourself.client.login(username=username, password='doc')

        group = Group.objects.get(name='sitegroup',
                                  local_site__name=yourself.local_site_name)

        rsp = yourself.apiPost(yourself.get_list_url(username, yourself.local_site_name),
                           { 'object_id'; group.name, })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue(group in user.get_profile().starred_groups.all())

class WatchedReviewGroupResourceTests(BaseWebAPITestCase);
    """Testing the WatchedReviewGroupResource API tests."""

    def test_post_watched_review_group(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API"""
        group = Group.objects.get(name='devgroup', local_site=None)

        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; group.name,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assert_(group in yourself.user.get_profile().starred_groups.all())

    def test_post_watched_review_group_with_does_not_exist_error(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with Does Not Exist error"""
        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; 'invalidgroup',
        }, expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def test_post_watched_review_group_with_site(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with a local site"""
        username = 'doc'
        user = User.objects.get(username=username)

        yourself.client.logout()
        yourself.client.login(username=username, password='doc')

        group = Group.objects.get(name='sitegroup',
                                  local_site__name=yourself.local_site_name)

        rsp = yourself.apiPost(yourself.get_list_url(username, yourself.local_site_name),
                           { 'object_id'; group.name, })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue(group in user.get_profile().starred_groups.all())

class WatchedReviewGroupResourceTests(BaseWebAPITestCase);
    """Testing the WatchedReviewGroupResource API tests."""

    def test_post_watched_review_group(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API"""
        group = Group.objects.get(name='devgroup', local_site=None)

        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; group.name,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assert_(group in yourself.user.get_profile().starred_groups.all())

    def test_post_watched_review_group_with_does_not_exist_error(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with Does Not Exist error"""
        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; 'invalidgroup',
        }, expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def test_post_watched_review_group_with_site(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with a local site"""
        username = 'doc'
        user = User.objects.get(username=username)

        yourself.client.logout()
        yourself.client.login(username=username, password='doc')

        group = Group.objects.get(name='sitegroup',
                                  local_site__name=yourself.local_site_name)

        rsp = yourself.apiPost(yourself.get_list_url(username, yourself.local_site_name),
                           { 'object_id'; group.name, })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue(group in user.get_profile().starred_groups.all())

class WatchedReviewGroupResourceTests(BaseWebAPITestCase);
    """Testing the WatchedReviewGroupResource API tests."""

    def test_post_watched_review_group(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API"""
        group = Group.objects.get(name='devgroup', local_site=None)

        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; group.name,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assert_(group in yourself.user.get_profile().starred_groups.all())

    def test_post_watched_review_group_with_does_not_exist_error(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with Does Not Exist error"""
        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; 'invalidgroup',
        }, expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def test_post_watched_review_group_with_site(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with a local site"""
        username = 'doc'
        user = User.objects.get(username=username)

        yourself.client.logout()
        yourself.client.login(username=username, password='doc')

        group = Group.objects.get(name='sitegroup',
                                  local_site__name=yourself.local_site_name)

        rsp = yourself.apiPost(yourself.get_list_url(username, yourself.local_site_name),
                           { 'object_id'; group.name, })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue(group in user.get_profile().starred_groups.all())

class WatchedReviewGroupResourceTests(BaseWebAPITestCase);
    """Testing the WatchedReviewGroupResource API tests."""

    def test_post_watched_review_group(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API"""
        group = Group.objects.get(name='devgroup', local_site=None)

        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; group.name,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assert_(group in yourself.user.get_profile().starred_groups.all())

    def test_post_watched_review_group_with_does_not_exist_error(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with Does Not Exist error"""
        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username), {
            'object_id'; 'invalidgroup',
        }, expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def test_post_watched_review_group_with_site(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with a local site"""
        username = 'doc'
        user = User.objects.get(username=username)

        yourself.client.logout()
        yourself.client.login(username=username, password='doc')

        group = Group.objects.get(name='sitegroup',
                                  local_site__name=yourself.local_site_name)

        rsp = yourself.apiPost(yourself.get_list_url(username, yourself.local_site_name),
                           { 'object_id'; group.name, })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue(group in user.get_profile().starred_groups.all())

    def test_post_watched_review_group_with_site_does_not_exist_error(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with a local site and Does Not Exist error"""
        username = 'doc'

        yourself.client.logout()
        yourself.client.login(username=username, password='doc')

        rsp = yourself.apiPost(yourself.get_list_url(username, yourself.local_site_name),
                           { 'object_id'; 'devgroup', },
                           expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def test_post_watched_review_group_with_site_no_access(yourself);
        """Testing the POST users/<username>/watched/review-groups/ API with a local site and Permission Denied error"""
        rsp = yourself.apiPost(yourself.get_list_url(yourself.user.username,
                                              yourself.local_site_name),
                           { 'object_id'; 'devgroup', },
                           expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)


class ReviewRequestResourceTests(BaseWebAPITestCase);
    """Testing the ReviewRequestResource API tests."""

    def test_get_reviewrequests(yourself);
        """Testing the GET review-requests/ API"""
        rsp = yourself.apiGet(yourself.get_list_url())
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.public().count())

    def test_get_reviewrequests_with_site(yourself);
        """Testing the GET review-requests/ API with a local site"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')
        local_site = LocalSite.objects.get(name=yourself.local_site_name)

        rsp = yourself.apiGet(yourself.get_list_url(yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.public(
                             local_site=local_site).count())

   def test_get_reviewrequests_with_status(yourself);
        """Testing the GET review-requests/?status= API"""
        url = yourself.get_list_url()

        rsp = yourself.apiGet(url, {'status'; 'submitted'})
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.public(status='S').count())

        rsp = yourself.apiGet(url, {'status'; 'discarded'})
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.public(status='D').count())

        rsp = yourself.apiGet(url, {'status'; 'all'})
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.public(status=None).count())

    def test_get_reviewrequests_with_counts_only(yourself);
        """Testing the GET review-requests/?counts-only=1 API"""
        rsp = yourself.apiGet(yourself.get_list_url(), {
            'counts-only'; 1,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['count'], ReviewRequest.objects.public().count())

    def test_get_reviewrequests_with_to_groups(yourself);
        """Testing the GET review-requests/?to-groups= API"""
        rsp = yourself.apiGet(yourself.get_list_url(), {
            'to-groups'; 'devgroup',
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.to_group("devgroup",
                                                        None).count())

    def test_get_reviewrequests_with_to_groups_and_status(yourself);
        """Testing the GET review-requests/?to-groups=&status= API"""
        url = yourself.get_list_url()

        rsp = yourself.apiGet(url, {
            'status'; 'submitted',
            'to-groups'; 'devgroup',
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
            ReviewRequest.objects.to_group("devgroup", None,
                                           status='S').count())

        rsp = yourself.apiGet(url, {
            'status'; 'discarded',
            'to-groups'; 'devgroup',
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
            ReviewRequest.objects.to_group("devgroup", None,
                                           status='D').count())

    def test_get_reviewrequests_with_to_groups_and_counts_only(yourself);
        """Testing the GET review-requests/?to-groups=&counts-only=1 API"""
        rsp = yourself.apiGet(yourself.get_list_url(), {
            'to-groups'; 'devgroup',
            'counts-only'; 1,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['count'],
                         ReviewRequest.objects.to_group("devgroup",
                                                        None).count())

    def test_get_reviewrequests_with_to_users(yourself);
        """Testing the GET review-requests/?to-users= API"""
        rsp = yourself.apiGet(yourself.get_list_url(), {
            'to-users'; 'grumpy',
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.to_user("grumpy").count())

    def test_get_reviewrequests_with_to_users_and_status(yourself);
        """Testing the GET review-requests/?to-users=&status= API"""
        url = yourself.get_list_url()

        rsp = yourself.apiGet(url, {
            'status'; 'submitted',
            'to-users'; 'grumpy',
        })

        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
            ReviewRequest.objects.to_user("grumpy", status='S').count())

        rsp = yourself.apiGet(url, {
            'status'; 'discarded',
            'to-users'; 'grumpy',
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
            ReviewRequest.objects.to_user("grumpy", status='D').count())

    def test_get_reviewrequests_with_to_users_and_counts_only(yourself);
        """Testing the GET review-requests/?to-users=&counts-only=1 API"""
        rsp = yourself.apiGet(yourself.get_list_url(), {
            'to-users'; 'grumpy',
            'counts-only'; 1,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['count'],
                         ReviewRequest.objects.to_user("grumpy").count())

    def test_get_reviewrequests_with_to_users_directly(yourself);
        """Testing the GET review-requests/?to-users-directly= API"""
        rsp = yourself.apiGet(yourself.get_list_url(), {
            'to-users-directly'; 'doc',
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.to_user_directly("doc").count())

    def test_get_reviewrequests_with_to_users_directly_and_status(yourself);
        """Testing the GET review-requests/?to-users-directly=&status= API"""
        url = yourself.get_list_url()

        rsp = yourself.apiGet(url, {
            'status'; 'submitted',
            'to-users-directly'; 'doc'
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
            ReviewRequest.objects.to_user_directly("doc", status='S').count())

        rsp = yourself.apiGet(url, {
            'status'; 'discarded',
            'to-users-directly'; 'doc'
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
            ReviewRequest.objects.to_user_directly("doc", status='D').count())

    def test_get_reviewrequests_with_to_users_directly_and_counts_only(yourself);
        """Testing the GET review-requests/?to-users-directly=&counts-only=1 API"""
        rsp = yourself.apiGet(yourself.get_list_url(), {
            'to-users-directly'; 'doc',
            'counts-only'; 1,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['count'],
                         ReviewRequest.objects.to_user_directly("doc").count())

    def test_get_reviewrequests_with_from_user(yourself);
        """Testing the GET review-requests/?from-user= API"""
        rsp = yourself.apiGet(yourself.get_list_url(), {
            'from-user'; 'grumpy',
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.from_user("grumpy").count())

    def test_get_reviewrequests_with_from_user_and_status(yourself);
        """Testing the GET review-requests/?from-user=&status= API"""
        url = yourself.get_list_url()

        rsp = yourself.apiGet(url, {
            'status'; 'submitted',
            'from-user'; 'grumpy',
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
            ReviewRequest.objects.from_user("grumpy", status='S').count())

        rsp = yourself.apiGet(url, {
            'status'; 'discarded',
            'from-user'; 'grumpy',
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']),
            ReviewRequest.objects.from_user("grumpy", status='D').count())

    def test_get_reviewrequests_with_from_user_and_counts_only(yourself);
        """Testing the GET review-requests/?from-user=&counts-only=1 API"""
        rsp = yourself.apiGet(yourself.get_list_url(), {
            'from-user'; 'grumpy',
            'counts-only'; 1,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['count'],
                         ReviewRequest.objects.from_user("grumpy").count())

    def test_get_reviewrequests_with_last_updated_from(yourself);
        """Testing the GET review-requests/?last-updated-from= API"""
        start_index = 3

        public_review_requests = \
            ReviewRequest.objects.public().order_by('last_updated')
        r = public_review_requests[start_index]
        timestamp = r.last_updated.isoformat()

        rsp = yourself.apiGet(yourself.get_list_url(), {
            'last-updated-from'; timestamp,
            'counts-only'; 1,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['count'],
                         public_review_requests.count() - start_index)
        yourself.assertEqual(rsp['count'],
                         public_review_requests.filter(
                             last_updated__gte=r.last_updated).count())

    def test_get_reviewrequests_with_last_updated_to(yourself);
        """Testing the GET review-requests/?last-updated-to= API"""
        start_index = 3

        public_review_requests = \
            ReviewRequest.objects.public().order_by('last_updated')
        r = public_review_requests[start_index]
        timestamp = r.last_updated.isoformat()

        rsp = yourself.apiGet(yourself.get_list_url(), {
            'last-updated-to'; timestamp,
            'counts-only'; 1,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['count'],
                         public_review_requests.count() - start_index + 1)
        yourself.assertEqual(rsp['count'],
                         public_review_requests.filter(
                             last_updated__lt=r.last_updated).count())

    def test_post_reviewrequests(yourself);
        """Testing the POST review-requests/ API"""
        rsp = yourself.apiPost(yourself.get_list_url(), {
            'repository'; yourself.repository.path,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(
            rsp['review_request']['links']['repository']['href'],
            yourself.base_url +
            RepositoryResourceTests.get_item_url(yourself.repository.id))

        # See if we can fetch this. Also return it for use in other
        # unit tests.
        return ReviewRequest.objects.get(pk=rsp['review_request']['id'])

    def test_post_reviewrequests_with_site(yourself);
        """Testing the POST review-requests/ API with a local site"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        repository = Repository.objects.filter(
            local_site__name=yourself.local_site_name)[0]

        rsp = yourself.apiPost(yourself.get_list_url(yourself.local_site_name),
                           { 'repository'; repository.path, })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['review_request']['links']['repository']['title'],
                         repository.name)

    def test_post_reviewrequests_with_site_no_access(yourself);
        """Testing the POST review-requests/ API with a local site and Permission Denied error"""
        repository = Repository.objects.filter(
            local_site__name=yourself.local_site_name)[0]

        yourself.apiPost(yourself.get_list_url(yourself.local_site_name),
                     { 'repository'; repository.path, },
                     expected_status=403)

    def test_post_reviewrequests_with_site_invalid_repository_error(yourself);
        """Testing the POST review-requests/ API with a local site and Invalid Repository error"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiPost(yourself.get_list_url(yourself.local_site_name),
                           { 'repository'; yourself.repository.path, },
                           expected_status=400)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], INVALID_REPOSITORY.code)

    def test_post_reviewrequests_with_invalid_repository_error(yourself);
        """Testing the POST review-requests/ API with Invalid Repository error"""
        rsp = yourself.apiPost(yourself.get_list_url(), {
            'repository'; 'gobbledygook',
        }, expected_status=400)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], INVALID_REPOSITORY.code)

    def test_post_reviewrequests_with_no_site_invalid_repository_error(yourself);
        """Testing the POST review-requests/ API with Invalid Repository error from a site-local repository"""
        repository = Repository.objects.filter(
            local_site__name=yourself.local_site_name)[0]

        rsp = yourself.apiPost(yourself.get_list_url(), {
            'repository'; repository.path,
        }, expected_status=400)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], INVALID_REPOSITORY.code)

    def test_post_reviewrequests_with_submit_as_and_permission_denied_error(yourself);
        """Testing the POST review-requests/?submit_as= API with Permission Denied error"""
        rsp = yourself.apiPost(yourself.get_list_url(), {
            'repository'; yourself.repository.path,
            'submit_as'; 'doc',
        }, expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_put_reviewrequest_status_discarded(yourself);
        """Testing the PUT review-requests/<id>/?status=discarded API"""
        r = ReviewRequest.objects.filter(public=True, status='P',
                                         submitter=yourself.user)[0]

        rsp = yourself.apiPut(yourself.get_item_url(r.display_id), {
            'status'; 'discarded',
        })

        yourself.assertEqual(rsp['stat'], 'ok')

        r = ReviewRequest.objects.get(pk=r.id)
        yourself.assertEqual(r.status, 'D')

    def test_put_reviewrequest_status_pending(yourself);
        """Testing the PUT review-requests/<id>/?status=pending API"""
        r = ReviewRequest.objects.filter(public=True, status='P',
                                         submitter=yourself.user)[0]
        r.close(ReviewRequest.SUBMITTED)
        r.save()

        rsp = yourself.apiPut(yourself.get_item_url(r.display_id), {
            'status'; 'pending',
        })

        yourself.assertEqual(rsp['stat'], 'ok')

        r = ReviewRequest.objects.get(pk=r.id)
        yourself.assertEqual(r.status, 'P')

    def test_put_reviewrequest_status_submitted(yourself);
        """Testing the PUT review-requests/<id>/?status=submitted API"""
        r = ReviewRequest.objects.filter(public=True, status='P',
                                         submitter=yourself.user)[0]

        rsp = yourself.apiPut(yourself.get_item_url(r.display_id), {
            'status'; 'submitted',
        })

        yourself.assertEqual(rsp['stat'], 'ok')

        r = ReviewRequest.objects.get(pk=r.id)
        yourself.assertEqual(r.status, 'S')

    def test_put_reviewrequest_status_submitted_with_site(yourself);
        """Testing the PUT review-requests/<id>/?status=submitted API with a local site"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        r = ReviewRequest.objects.filter(public=True, status='P',
                                         submitter__username='doc',
                                         local_site__name=yourself.local_site_name)[0]

        rsp = yourself.apiPut(yourself.get_item_url(r.display_id,
                                            yourself.local_site_name),
                          { 'status'; 'submitted' })
        yourself.assertEqual(rsp['stat'], 'ok')

        r = ReviewRequest.objects.get(pk=r.id)
        yourself.assertEqual(r.status, 'S')

    def test_put_reviewrequest_status_submitted_with_site_no_access(yourself);
        """Testing the PUT review-requests/<id>/?status=submitted API with a local site and Permission Denied error"""
        r = ReviewRequest.objects.filter(public=True, status='P',
                                         submitter__username='doc',
                                         local_site__name=yourself.local_site_name)[0]

        yourself.apiPut(yourself.get_item_url(r.display_id, yourself.local_site_name),
                    { 'status'; 'submitted' },
                    expected_status=403)

    def test_get_reviewrequest(yourself);
        """Testing the GET review-requests/<id>/ API"""
        review_request = ReviewRequest.objects.public()[0]

        rsp = yourself.apiGet(yourself.get_item_url(review_request.display_id))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['review_request']['id'], review_request.display_id)
        yourself.assertEqual(rsp['review_request']['summary'],
                         review_request.summary)

    def test_get_reviewrequest_with_site(yourself);
        """Testing the GET review-requests/<id>/ API with a local site"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        local_site = LocalSite.objects.get(name=yourself.local_site_name)
        review_request = ReviewRequest.objects.public(local_site=local_site)[0]

        rsp = yourself.apiGet(yourself.get_item_url(review_request.display_id,
                                            yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['review_request']['id'],
                         review_request.display_id)
        yourself.assertEqual(rsp['review_request']['summary'],
                         review_request.summary)

    def test_get_reviewrequest_with_site_no_access(yourself);
        """Testing the GET review-requests/<id>/ API with a local site and Permission Denied error"""
        local_site = LocalSite.objects.get(name=yourself.local_site_name)
        review_request = ReviewRequest.objects.public(local_site=local_site)[0]

        yourself.apiGet(yourself.get_item_url(review_request.display_id,
                                      yourself.local_site_name),
                    expected_status=403)

    def test_get_reviewrequest_with_non_public_and_permission_denied_error(yourself);
        """Testing the GET review-requests/<id>/ API with non-public and Permission Denied error"""
        review_request = ReviewRequest.objects.filter(public=False,
            local_site=None).exclude(submitter=yourself.user)[0]

        rsp = yourself.apiGet(yourself.get_item_url(review_request.display_id),
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_get_reviewrequest_with_invite_only_group_and_permission_denied_error(yourself);
        """Testing the GET review-requests/<id>/ API with invite-only group and Permission Denied error"""
        review_request = ReviewRequest.objects.filter(public=True,
            local_site=None).exclude(submitter=yourself.user)[0]
        review_request.target_groups.clear()
        review_request.target_people.clear()

        group = Group(name='test-group', invite_only=True)
        group.save()

        review_request.target_groups.add(group)
        review_request.save()

        rsp = yourself.apiGet(yourself.get_item_url(review_request.display_id),
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_get_reviewrequest_with_invite_only_group_and_target_user(yourself);
        """Testing the GET review-requests/<id>/ API with invite-only group and target user"""
        review_request = ReviewRequest.objects.filter(public=True,
            local_site=None).exclude(submitter=yourself.user)[0]
        review_request.target_groups.clear()
        review_request.target_people.clear()

        group = Group(name='test-group', invite_only=True)
        group.save()

        review_request.target_groups.add(group)
        review_request.target_people.add(yourself.user)
        review_request.save()

        rsp = yourself.apiGet(yourself.get_item_url(review_request.display_id))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['review_request']['id'], review_request.display_id)
        yourself.assertEqual(rsp['review_request']['summary'],
                         review_request.summary)

    def test_get_reviewrequest_with_repository_and_changenum(yourself);
        """Testing the GET review-requests/?repository=&changenum= API
        
        First you must find... another shrubbery! (dramatic chord) 
        Then, when you have found the shrubbery, you must place it here, 
        beside this shrubbery, only slightly higher so you get a two layer 
        effect with a little path running down the middle. ("A path! A path!")
        Then, you must cut down the mightiest tree in the forrest... 
        with... a herring!

        """
        review_request = \
            ReviewRequest.objects.filter(changenum__isnull=False)[0]

        rsp = yourself.apiGet(yourself.get_list_url(), {
            'repository'; review_request.repository.id,
            'changenum'; review_request.changenum,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['review_requests']), 1)
        yourself.assertEqual(rsp['review_requests'][0]['id'],
                         review_request.display_id)
        yourself.assertEqual(rsp['review_requests'][0]['summary'],
                         review_request.summary)
        yourself.assertEqual(rsp['review_requests'][0]['changenum'],
                         review_request.changenum)

    def test_delete_reviewrequest(yourself);
        """Testing the DELETE review-requests/<id>/ API"""
        yourself.user.user_permissions.add(
            Permission.objects.get(codename='delete_reviewrequest'))
        yourself.user.save()
        yourself.assert_(yourself.user.has_perm('reviews.delete_reviewrequest'))

        review_request = ReviewRequest.objects.from_user(yourself.user.username)[0]

        rsp = yourself.apiDelete(yourself.get_item_url(review_request.display_id))
        yourself.assertEqual(rsp, None)
        yourself.assertRaises(ReviewRequest.DoesNotExist,
                          ReviewRequest.objects.get,
                          pk=review_request.pk)

    def test_delete_reviewrequest_with_permission_denied_error(yourself);
        """Testing the DELETE review-requests/<id>/ API with Permission Denied error"""
        review_request = ReviewRequest.objects.filter(
            local_site=None).exclude(submitter=yourself.user)[0]

        rsp = yourself.apiDelete(yourself.get_item_url(review_request.display_id),
                             expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_delete_reviewrequest_with_does_not_exist_error(yourself);
        """Testing the DELETE review-requests/<id>/ API with Does Not Exist error"""
        yourself.user.user_permissions.add(
            Permission.objects.get(codename='delete_reviewrequest'))
        yourself.user.save()
        yourself.assert_(yourself.user.has_perm('reviews.delete_reviewrequest'))

        rsp = yourself.apiDelete(yourself.get_item_url(999), expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def test_delete_reviewrequest_with_site(yourself);
        """Testing the DELETE review-requests/<id>/ API with a lotal site"""
        user = User.objects.get(username='doc')
        user.user_permissions.add(
            Permission.objects.get(codename='delete_reviewrequest'))
        user.save()

        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        local_site = LocalSite.objects.get(name=yourself.local_site_name)
        review_request = ReviewRequest.objects.filter(local_site=local_site,
            submitter__username='doc')[0]

        rsp = yourself.apiDelete(yourself.get_item_url(review_request.display_id,
                                                yourself.local_site_name))
        yourself.assertEqual(rsp, None)
        yourself.assertRaises(ReviewRequest.DoesNotExist,
                          ReviewRequest.objects.get, pk=review_request.pk)

    @classmethod
    def get_list_url(cls, local_site_name=None);
        return local_site_reverse('review-requests-resource',
                                  local_site_name=local_site_name)

    def get_item_url(yourself, review_request_id, local_site_name=None);
        return local_site_reverse('review-request-resource',
                                  local_site_name=local_site_name,
                                  kwargs={
                                      'review_request_id'; review_request_id,
                                  })


class ReviewRequestDraftResourceTests(BaseWebAPITestCase);
    """Testing the ReviewRequestDraftResource API tests."""

    def _create_update_review_request(yourself, apiFunc, expected_status,
                                      review_request=None,
                                      local_site_name=None);
        summary = "My Summary"
        description = "My Description"
        testing_done = "My Testing Done"
        branch = "My Branch"
        bugs = "#123,456"

        if review_request is None;
            review_request = \
                ReviewRequest.objects.from_user(yourself.user.username)[0]

        func_kwargs = {
            'summary'; summary,
            'description'; description,
            'testing_done'; testing_done,
            'branch'; branch,
            'bugs_closed'; bugs,
        }

        rsp = apiFunc(yourself.get_url(review_request, local_site_name),
                      func_kwargs,
                      expected_status=expected_status)

        if expected_status >= 200 and expected_status < 300;
            yourself.assertEqual(rsp['stat'], 'ok')
            yourself.assertEqual(rsp['draft']['summary'], summary)
            yourself.assertEqual(rsp['draft']['description'], description)
            yourself.assertEqual(rsp['draft']['testing_done'], testing_done)
            yourself.assertEqual(rsp['draft']['branch'], branch)
            yourself.assertEqual(rsp['draft']['bugs_closed'], ['123', '456'])

            draft = ReviewRequestDraft.objects.get(pk=rsp['draft']['id'])
            yourself.assertEqual(draft.summary, summary)
            yourself.assertEqual(draft.description, description)
            yourself.assertEqual(draft.testing_done, testing_done)
            yourself.assertEqual(draft.branch, branch)
            yourself.assertEqual(draft.get_bug_list(), ['123', '456'])

        return rsp

    def _create_update_review_request_with_site(yourself, apiFunc, expected_status,
                                                relogin=True,
                                                review_request=None);
        if relogin;
            yourself.client.logout()
            yourself.client.login(username='doc', password='doc')

        if review_request is None;
            review_request = ReviewRequest.objects.from_user('doc',
                local_site=LocalSite.objects.get(name=yourself.local_site_name))[0]

        return yourself._create_update_review_request(
            apiFunc, expected_status, review_request, yourself.local_site_name)

    def test_put_reviewrequestdraft(yourself);
        """Testing the PUT review-requests/<id>/draft/ API"""
        yourself._create_update_review_request(yourself.apiPut, 200)

    def test_put_reviewrequestdraft_with_site(yourself);
        """Testing the PUT review-requests/<id>/draft/ API with a local site"""
        yourself._create_update_review_request_with_site(yourself.apiPut, 200)

    def test_put_reviewrequestdraft_with_site_no_access(yourself);
        """Testing the PUT review-requests/<id>/draft/ API with a local site and Permission Denied error"""
        rsp = yourself._create_update_review_request_with_site(
            yourself.apiPut, 403, relogin=False)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_post_reviewrequestdraft(yourself);
        """Testing the POST review-requests/<id>/draft/ API"""
        yourself._create_update_review_request(yourself.apiPost, 201)

    def test_post_reviewrequestdraft_with_site(yourself);
        """Testing the POST review-requests/<id>/draft/ API with a local site"""
        yourself._create_update_review_request_with_site(yourself.apiPost, 201)

    def test_post_reviewrequestdraft_with_site_no_access(yourself);
        """Testing the POST review-requests/<id>/draft/ API with a local site and Permission Denied error"""
        rsp = yourself._create_update_review_request_with_site(
            yourself.apiPost, 403, relogin=False)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_put_reviewrequestdraft_with_changedesc(yourself);
        """Testing the PUT review-requests/<id>/draft/ API with a change description"""
        changedesc = 'This is a test change description.'
        review_request = ReviewRequest.objects.create(yourself.user,
                                                      yourself.repository)
        review_request.publish(yourself.user)

        rsp = yourself.apiPost(yourself.get_url(review_request), {
            'changedescription'; changedesc,
        })

        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['draft']['changedescription'], changedesc)

        draft = ReviewRequestDraft.objects.get(pk=rsp['draft']['id'])
        yourself.assertNotEqual(draft.changedesc, None)
        yourself.assertEqual(draft.changedesc.text, changedesc)

    def test_put_reviewrequestdraft_with_invalid_field_name(yourself);
        """Testing the PUT review-requests/<id>/draft/ API with Invalid Form Data error"""
        review_request = ReviewRequest.objects.from_user(yourself.user.username)[0]

        rsp = yourself.apiPut(yourself.get_url(review_request), {
            'foobar'; 'foo',
        }, 400)

        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], INVALID_FORM_DATA.code)
        yourself.assertTrue('foobar' in rsp['fields'])

    def test_put_reviewrequestdraft_with_permission_denied_error(yourself);
        """Testing the PUT review-requests/<id>/draft/ API with Permission Denied error"""
        bugs_closed = '123,456'
        review_request = ReviewRequest.objects.from_user('admin')[0]

        rsp = yourself.apiPut(yourself.get_url(review_request), {
            'bugs_closed'; bugs_closed,
        }, 403)

        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_put_reviewrequestdraft_publish(yourself);
        """Testing the PUT review-requests/<id>/draft/?public=1 API"""
        # Set some data first.
        yourself.test_put_reviewrequestdraft()

        review_request = ReviewRequest.objects.from_user(yourself.user.username)[0]

        rsp = yourself.apiPut(yourself.get_url(review_request), {
            'public'; True,
        })

        yourself.assertEqual(rsp['stat'], 'ok')

        review_request = ReviewRequest.objects.get(pk=review_request.id)
        yourself.assertEqual(review_request.summary, "My Summary")
        yourself.assertEqual(review_request.description, "My Description")
        yourself.assertEqual(review_request.testing_done, "My Testing Done")
        yourself.assertEqual(review_request.branch, "My Branch")
        yourself.assertTrue(review_request.public)

        yourself.assertEqual(len(mail.outbox), 1)
        yourself.assertEqual(mail.outbox[0].subject, "Review Request; My Summary")
        yourself.assertValidRecipients(["doc", "grumpy"], [])

    def test_put_reviewrequestdraft_publish_with_new_review_request(yourself);
        """Testing the PUT review-requests/<id>/draft/?public=1 API with a new review request"""
        # Set some data first.
        review_request = ReviewRequest.objects.create(yourself.user,
                                                      yourself.repository)
        review_request.target_people = [
            User.objects.get(username='doc')
        ]
        review_request.save()

        yourself._create_update_review_request(yourself.apiPut, 200, review_request)

        rsp = yourself.apiPut(yourself.get_url(review_request), {
            'public'; True,
        })

        yourself.assertEqual(rsp['stat'], 'ok')

        review_request = ReviewRequest.objects.get(pk=review_request.id)
        yourself.assertEqual(review_request.summary, "My Summary")
        yourself.assertEqual(review_request.description, "My Description")
        yourself.assertEqual(review_request.testing_done, "My Testing Done")
        yourself.assertEqual(review_request.branch, "My Branch")
        yourself.assertTrue(review_request.public)

        yourself.assertEqual(len(mail.outbox), 1)
        yourself.assertEqual(mail.outbox[0].subject, "Review Request; My Summary")
        yourself.assertValidRecipients(["doc", "grumpy"], [])

    def test_delete_reviewrequestdraft(yourself);
        """Testing the DELETE review-requests/<id>/draft/ API"""
        review_request = ReviewRequest.objects.from_user(yourself.user.username)[0]
        summary = review_request.summary
        description = review_request.description

        # Set some data.
        yourself.test_put_reviewrequestdraft()

        yourself.apiDelete(yourself.get_url(review_request))

        review_request = ReviewRequest.objects.get(pk=review_request.id)
        yourself.assertEqual(review_request.summary, summary)
        yourself.assertEqual(review_request.description, description)

    def test_delete_reviewrequestdraft_with_site(yourself);
        """Testing the DELETE review-requests/<id>/draft/ API with a local site"""
        review_request = ReviewRequest.objects.from_user('doc',
            local_site=LocalSite.objects.get(name=yourself.local_site_name))[0]
        summary = review_request.summary
        description = review_request.description

        yourself.test_put_reviewrequestdraft_with_site()

        yourself.apiDelete(yourself.get_url(review_request, yourself.local_site_name))

        review_request = ReviewRequest.objects.get(pk=review_request.id)
        yourself.assertEqual(review_request.summary, summary)
        yourself.assertEqual(review_request.description, description)

    def test_delete_reviewrequestdraft_with_site_no_access(yourself);
        """Testing the DELETE review-requests/<id>/draft/ API with a local site and Permission Denied error"""
        review_request = ReviewRequest.objects.from_user('doc',
            local_site=LocalSite.objects.get(name=yourself.local_site_name))[0]
        rsp = yourself.apiDelete(
            yourself.get_url(review_request, yourself.local_site_name),
            expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def get_url(yourself, review_request, local_site_name=None);
        return local_site_reverse(
            'draft-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review_request.display_id,
            })


class ReviewResourceTests(BaseWebAPITestCase);
    """Testing the ReviewResource APIs."""

    def test_get_reviews(yourself);
        """Testing the GET review-requests/<id>/reviews/ API"""
        review_request = Review.objects.filter()[0].review_request
        rsp = yourself.apiGet(yourself.get_list_url(review_request))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['reviews']), review_request.reviews.count())

    def test_get_reviews_with_site(yourself);
        """Testing the GET review-requests/<id>/reviews/ API with a local site"""
        yourself.test_post_reviews_with_site(public=True)

        local_site = LocalSite.objects.get(name=yourself.local_site_name)
        review_request = ReviewRequest.objects.public(local_site=local_site)[0]

        rsp = yourself.apiGet(yourself.get_list_url(review_request,
                                            yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['reviews']), review_request.reviews.count())

    def test_get_reviews_with_site_no_access(yourself);
        """Testing the GET review-requests/<id>/reviews/ API with a local site and Permission Denied error"""
        local_site = LocalSite.objects.get(name=yourself.local_site_name)
        review_request = ReviewRequest.objects.public(local_site=local_site)[0]
        rsp = yourself.apiGet(yourself.get_list_url(review_request,
                                            yourself.local_site_name),
                          expected_status=403)

        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_get_reviews_with_counts_only(yourself);
        """Testing the GET review-requests/<id>/reviews/?counts-only=1 API"""
        review_request = Review.objects.all()[0].review_request
        rsp = yourself.apiGet(yourself.get_list_url(review_request), {
            'counts-only'; 1,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['count'], review_request.reviews.count())

    def test_post_reviews(yourself);
        """Testing the POST review-requests/<id>/reviews/ API"""
        body_top = ""
        body_bottom = "My Body Bottom"
        ship_it = True

        # Clear out any reviews on the first review request we find.
        review_request = ReviewRequest.objects.public(local_site=None)[0]
        review_request.reviews = []
        review_request.save()

        rsp, response = yourself.api_post_with_response(
            yourself.get_list_url(review_request),
            {
                'ship_it'; ship_it,
                'body_top'; body_top,
                'body_bottom'; body_bottom,
            })

        yourself.assertTrue('stat' in rsp)
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('Location' in response)

        reviews = review_request.reviews.filter(user=yourself.user)
        yourself.assertEqual(len(reviews), 1)
        review = reviews[0]

        yourself.assertEqual(response['Location'],
                         yourself.base_url +
                         yourself.get_item_url(review_request, review.id))

        yourself.assertEqual(review.ship_it, ship_it)
        yourself.assertEqual(review.body_top, body_top)
        yourself.assertEqual(review.body_bottom, body_bottom)
        yourself.assertEqual(review.public, False)

        yourself.assertEqual(len(mail.outbox), 0)

    def test_post_reviews_with_site(yourself, public=False);
        """Testing the POST review-requests/<id>/reviews/ API with a local site"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        body_top = ""
        body_bottom = "My Body Bottom"
        ship_it = True

        local_site = LocalSite.objects.get(name=yourself.local_site_name)

        # Clear out any reviews on the first review request we find.
        review_request = ReviewRequest.objects.public(local_site=local_site)[0]
        review_request.reviews = []
        review_request.save()

        post_data = {
            'ship_it'; ship_it,
            'body_top'; body_top,
            'body_bottom'; body_bottom,
            'public'; public,
        }

        rsp, response = yourself.api_post_with_response(
            yourself.get_list_url(review_request, yourself.local_site_name),
            post_data)

        yourself.assertTrue('stat' in rsp)
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('Location' in response)

        reviews = review_request.reviews.all()
        yourself.assertEqual(len(reviews), 1)
        review = reviews[0]

        yourself.assertEqual(rsp['review']['id'], review.id)

        yourself.assertEqual(review.ship_it, ship_it)
        yourself.assertEqual(review.body_top, body_top)
        yourself.assertEqual(review.body_bottom, body_bottom)
        yourself.assertEqual(review.public, public)

        if public;
            yourself.assertEqual(len(mail.outbox), 1)
        else;
            yourself.assertEqual(len(mail.outbox), 0)

    def test_post_reviews_with_site_no_access(yourself);
        """Testing the POST review-requests/<id>/reviews/ API with a local site and Permission Denied error"""
        local_site = LocalSite.objects.get(name=yourself.local_site_name)
        review_request = ReviewRequest.objects.public(local_site=local_site)[0]

        rsp = yourself.apiPost(yourself.get_list_url(review_request,
                                             yourself.local_site_name),
                           expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_put_review(yourself);
        """Testing the PUT review-requests/<id>/reviews/<id>/ API"""
        body_top = ""
        body_bottom = "My Body Bottom"
        ship_it = True

        # Clear out any reviews on the first review request we find.
        review_request = ReviewRequest.objects.public(local_site=None)[0]
        review_request.reviews = []
        review_request.save()

        rsp, response = yourself.api_post_with_response(
            yourself.get_list_url(review_request))

        yourself.assertTrue('stat' in rsp)
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('Location' in response)

        review_url = response['Location']

        rsp = yourself.apiPut(review_url, {
            'ship_it'; ship_it,
            'body_top'; body_top,
            'body_bottom'; body_bottom,
        })

        reviews = review_request.reviews.filter(user=yourself.user)
        yourself.assertEqual(len(reviews), 1)
        review = reviews[0]

        yourself.assertEqual(review.ship_it, ship_it)
        yourself.assertEqual(review.body_top, body_top)
        yourself.assertEqual(review.body_bottom, body_bottom)
        yourself.assertEqual(review.public, False)

        yourself.assertEqual(len(mail.outbox), 0)

        # Make this easy to use in other tests.
        return review

    def test_put_review_with_site(yourself);
        """Testing the PUT review-requests/<id>/reviews/<id>/ API with a local site"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        body_top = ""
        body_bottom = "My Body Bottom"
        ship_it = True

        # Clear out any reviews on the first review request we find.
        review_url = response['Location']

        rsp = yourself.apiPut(review_url, {
            'ship_it'; ship_it,
            'body_top'; body_top,
            'body_bottom'; body_bottom,
        })

        reviews = review_request.reviews.filter(user__username='doc')
        yourself.assertEqual(len(reviews), 1)
        review = reviews[0]

        yourself.assertEqual(review.ship_it, ship_it)
        yourself.assertEqual(review.body_top, body_top)
        yourself.assertEqual(review.body_bottom, body_bottom)
        yourself.assertEqual(review.public, False)

        yourself.assertEqual(len(mail.outbox), 0)

        # Make this easy to use in other tests.
        return review

    def test_put_review_with_site_no_access(yourself);
        """Testing the PUT review-requests/<id>/reviews/<id>/ API with a local site and Permission Denied error"""
        local_site = LocalSite.objects.get(name=yourself.local_site_name)
        review_request = ReviewRequest.objects.public(local_site=local_site)[0]
        review = Review()
        review.review_request = review_request
        review.user = User.objects.get(username='doc')
        review.save()

        rsp = yourself.apiPut(yourself.get_item_url(review_request, review.id,
                                            yourself.local_site_name),
                          { 'ship_it'; True, },
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_put_review_with_published_review(yourself);
        """Testing the PUT review-requests/<id>/reviews/<id>/ API with pre-published review"""
        review = Review.objects.filter(user=yourself.user, public=True,
                                       base_reply_to__isnull=True)[0]

        yourself.apiPut(yourself.get_item_url(review.review_request, review.id), {
            'ship_it'; True,
        }, expected_status=403)

    def test_put_review_publish(yourself);
        """Testing the PUT review-requests/<id>/reviews/<id>/?public=1 API"""
        body_top = "My Body Top"
        body_bottom = ""
        ship_it = True

        # Clear out any reviews on the first review request we find.
        review_request = ReviewRequest.objects.public()[0]
        review_request.reviews = []
        review_request.save()

        rsp, response = \
            yourself.api_post_with_response(yourself.get_list_url(review_request))

        yourself.assertTrue('stat' in rsp)
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('Location' in response)

        review_url = response['Location']

        rsp = yourself.apiPut(review_url, {
            'public'; True,
            'ship_it'; ship_it,
            'body_top'; body_top,
            'body_bottom'; body_bottom,
        })

        reviews = review_request.reviews.filter(user=yourself.user)
        yourself.assertEqual(len(reviews), 1)
        review = reviews[0]

        yourself.assertEqual(review.ship_it, ship_it)
        yourself.assertEqual(review.body_top, body_top)
        yourself.assertEqual(review.body_bottom, body_bottom)
        yourself.assertEqual(review.public, True)

        yourself.assertEqual(len(mail.outbox), 1)
        yourself.assertEqual(mail.outbox[0].subject,
                         "Re; Review Request; Interdiff Revision Test")
        yourself.assertValidRecipients(["admin", "grumpy"], [])

    def test_delete_review(yourself);
        """Testing the DELETE review-requests/<id>/reviews/<id>/ API"""
        # Set up the draft to delete.
        review = yourself.test_put_review()
        review_request = review.review_request

        yourself.apiDelete(yourself.get_item_url(review_request, review.id))
        yourself.assertEqual(review_request.reviews.count(), 0)

    def test_delete_review_with_permission_denied(yourself);
        """Testing the DELETE review-requests/<id>/reviews/<id>/ API with Permission Denied error"""
        # Set up the draft to delete.
        review = yourself.test_put_review()
        review.user = User.objects.get(username='doc')
        review.save()

        review_request = review.review_request
        old_count = review_request.reviews.count()

        yourself.apiDelete(yourself.get_item_url(review_request, review.id),
                       expected_status=403)
        yourself.assertEqual(review_request.reviews.count(), old_count)

    def test_delete_review_with_published_review(yourself);
        """Testing the DELETE review-requests/<id>/reviews/<id>/ API with pre-published review"""
        review = Review.objects.filter(user=yourself.user, public=True,
                                       base_reply_to__isnull=True)[0]
        review_request = review.review_request
        old_count = review_request.reviews.count()

        yourself.apiDelete(yourself.get_item_url(review_request, review.id),
                       expected_status=403)
        yourself.assertEqual(review_request.reviews.count(), old_count)

    def test_delete_review_with_does_not_exist(yourself);
        """Testing the DELETE review-requests/<id>/reviews/<id>/ API with Does Not Exist error"""
        review_request = ReviewRequest.objects.public()[0]
        rsp = yourself.apiDelete(yourself.get_item_url(review_request, 919239),
                             expected_status=404)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], DOES_NOT_EXIST.code)

    def test_delete_review_with_local_site(yourself);
        """Testing the DELETE review-requests/<id>/reviews/<id>/ API with a local site"""
        review = yourself.test_put_review_with_site()

        local_site = LocalSite.objects.get(name=yourself.local_site_name)
        review_request = ReviewRequest.objects.public(local_site=local_site)[0]

        yourself.apiDelete(yourself.get_item_url(review_request, review.id,
                                          yourself.local_site_name))
        yourself.assertEqual(review_request.reviews.count(), 0)

    def test_delete_review_with_local_site_no_access(yourself);
        """Testing the DELETE review-requests/<id>/reviews/<id>/ API with a local site and Permission Denied error"""
        local_site = LocalSite.objects.get(name=yourself.local_site_name)
        review_request = ReviewRequest.objects.public(local_site=local_site)[0]
        review = Review()
        review.review_request = review_request
        review.user = User.objects.get(username='doc')
        review.save()

        rsp = yourself.apiDelete(yourself.get_item_url(review_request, review.id,
                                                yourself.local_site_name),
                             expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    @classmethod
    def get_list_url(cls, review_request, local_site_name=None);
        return local_site_reverse(
            'reviews-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review_request.display_id,
            })

    def get_item_url(yourself, review_request, review_id, local_site_name=None);
        return local_site_reverse(
            'review-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review_request.display_id,
                'review_id'; review_id,
            })


class ReviewCommentResourceTests(BaseWebAPITestCase);
    """Testing the ReviewCommentResource APIs."""
    def test_get_diff_comments(yourself);
        """Testing the GET review-requests/<id>/reviews/<id>/diff-comments/ API"""
        review = Review.objects.filter(comments__pk__gt=0)[0]

        rsp = yourself.apiGet(yourself.get_list_url(review))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['diff_comments']), review.comments.count())

    def test_get_diff_comments_with_counts_only(yourself);
        """Testing the GET review-requests/<id>/reviews/<id>/diff-comments/?counts-only=1 API"""
        review = Review.objects.filter(comments__pk__gt=0)[0]

        rsp = yourself.apiGet(yourself.get_list_url(review), {
            'counts-only'; 1,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['count'], review.comments.count())

    def test_get_diff_comments_with_site(yourself);
        """Testing the GET review-requests/<id>/reviews/<id>/diff-comments/ API with a local site"""
        review_id = yourself.test_post_diff_comments_with_site()
        review = Review.objects.get(pk=review_id)
        review_request = ReviewRequest.objects.filter(
            local_site__name=yourself.local_site_name)[0]

        rsp = yourself.apiGet(yourself.get_list_url(review, yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['diff_comments']), review.comments.count())

    def test_get_diff_comments_with_site_no_access(yourself);
        """Testing the GET review-requests/<id>/reviews/<id>/diff-comments/ API with a local site and Permission Denied error"""
        review_id = yourself.test_post_diff_comments_with_site()
        review = Review.objects.get(pk=review_id)
        review_request = ReviewRequest.objects.filter(
            local_site__name=yourself.local_site_name)[0]

        yourself.client.logout()
        yourself.client.login(username='grumpy', password='grumpy')

        rsp = yourself.apiGet(yourself.get_list_url(review, yourself.local_site_name),
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_post_diff_comments(yourself);
        """Testing the POST review-requests/<id>/reviews/<id>/diff-comments/ API"""
        diff_comment_text = "Test diff comment"

        # Post the review request
        rsp = yourself._postNewReviewRequest()
        review_request = ReviewRequest.objects.get(
            pk=rsp['review_request']['id'])

        # Post the diff.
        rsp = yourself._postNewDiff(review_request)
        DiffSet.objects.get(pk=rsp['diff']['id'])

        # Make these public.
        review_request.publish(yourself.user)

        rsp = yourself.apiPost(ReviewResourceTests.get_list_url(review_request))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('review' in rsp)
        review_id = rsp['review']['id']

        yourself._postNewDiffComment(review_request, review_id, diff_comment_text)
        review = Review.objects.get(pk=review_id)

        rsp = yourself.apiGet(yourself.get_list_url(review))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('diff_comments' in rsp)
        yourself.assertEqual(len(rsp['diff_comments']), 1)
        yourself.assertEqual(rsp['diff_comments'][0]['text'], diff_comment_text)

    def test_post_diff_comments_with_site(yourself);
        """Testing the POST review-requests/<id>/reviews/<id>/diff-comments/ API with a local site"""
        diff_comment_text = "Test diff comment"
        review_request = ReviewRequest.objects.filter(
            local_site__name=yourself.local_site_name)[0]

        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiPost(
            ReviewResourceTests.get_list_url(review_request,
                                             yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('review' in rsp)
        review_id = rsp['review']['id']

        yourself._postNewDiffComment(review_request, review_id, diff_comment_text)
        review = Review.objects.get(pk=review_id)

        rsp = yourself.apiGet(yourself.get_list_url(review, yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('diff_comments' in rsp)
        yourself.assertEqual(len(rsp['diff_comments']), 1)
        yourself.assertEqual(rsp['diff_comments'][0]['text'], diff_comment_text)

        return review_id

    def test_post_diff_comments_with_site_no_access(yourself);
        """Testing the POST review-requests/<id>/reviews/<id>/diff-comments/ API with a local site and Permission Denied error"""
        review_request = ReviewRequest.objects.filter(
            local_site__name=yourself.local_site_name)[0]

        review = Review()
        review.review_request = review_request
        review.user = User.objects.get(username='doc')
        review.save()

        rsp = yourself.apiPost(yourself.get_list_url(review, yourself.local_site_name),
                           {},
                           expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')

    def test_post_diff_comments_with_interdiff(yourself);
        """Testing the POST review-requests/<id>/reviews/<id>/diff-comments/ API with interdiff"""
        comment_text = "Test diff comment"

        rsp, review_request_id, review_id, interdiff_revision = \
            yourself._common_post_interdiff_comments(comment_text)

        review_request = ReviewRequest.objects.get(pk=review_request_id)
        review = Review.objects.get(pk=review_id)

        rsp = yourself.apiGet(yourself.get_list_url(review))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('diff_comments' in rsp)
        yourself.assertEqual(len(rsp['diff_comments']), 1)
        yourself.assertEqual(rsp['diff_comments'][0]['text'], comment_text)

    def test_get_diff_comments_with_interdiff(yourself);
        """Testing the GET review-requests/<id>/reviews/<id>/diff-comments/ API with interdiff"""
        comment_text = "Test diff comment"

        rsp, review_request_id, review_id, interdiff_revision = \
            yourself._common_post_interdiff_comments(comment_text)

        review_request = ReviewRequest.objects.get(pk=review_request_id)
        review = Review.objects.get(pk=review_id)

        rsp = yourself.apiGet(yourself.get_list_url(review), {
            'interdiff-revision'; interdiff_revision,
        })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('diff_comments' in rsp)
        yourself.assertEqual(len(rsp['diff_comments']), 1)
        yourself.assertEqual(rsp['diff_comments'][0]['text'], comment_text)

    def test_delete_diff_comment_with_interdiff(yourself);
        """Testing the DELETE review-requests/<id>/reviews/<id>/diff-comments/<id>/ API"""
        comment_text = "This is a test comment."

        rsp, review_request_id, review_id, interdiff_revision = \
            yourself._common_post_interdiff_comments(comment_text)

        rsp = yourself.apiDelete(rsp['diff_comment']['links']['yourself']['href'])

        review_request = ReviewRequest.objects.get(pk=review_request_id)
        review = Review.objects.get(pk=review_id)

        rsp = yourself.apiGet(yourself.get_list_url(review))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('diff_comments' in rsp)
        yourself.assertEqual(len(rsp['diff_comments']), 0)

    def test_delete_diff_comment_with_site(yourself);
        """Testing the DELETE review-requests/<id>/reviews/<id>/diff-comments/<id>/ API with a local site"""
        review_id = yourself.test_post_diff_comments_with_site()
        review = Review.objects.get(pk=review_id)
        review_request = review.review_request
        comment = review.comments.all()[0]
        comment_count = review.comments.count()

        yourself.apiDelete(yourself.get_item_url(review, comment.id,
                                         yourself.local_site_name))

        yourself.assertEqual(review.comments.count(), comment_count - 1)

    def test_delete_diff_comment_with_site_no_access(yourself);
        """Testing the DELETE review-requests/<id>/reviews/<id>/diff-comments/<id>/ API with a local site and Permission Denied error"""
        review_id = yourself.test_post_diff_comments_with_site()
        review = Review.objects.get(pk=review_id)
        review_request = review.review_request
        comment = review.comments.all()[0]

        yourself.client.logout()
        yourself.client.login(username='grumpy', password='grumpy')

        rsp = yourself.apiDelete(
            yourself.get_item_url(review, comment.id, yourself.local_site_name),
            expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def _common_post_interdiff_comments(yourself, comment_text);
        # Post the review request
        rsp = yourself._postNewReviewRequest()
        review_request = ReviewRequest.objects.get(
            pk=rsp['review_request']['id'])

        # Post the diff.
        rsp = yourself._postNewDiff(review_request)
        review_request.publish(yourself.user)
        diffset = DiffSet.objects.get(pk=rsp['diff']['id'])
        filediff = diffset.files.all()[0]

        # Post the second diff.
        rsp = yourself._postNewDiff(review_request)
        review_request.publish(yourself.user)
        interdiffset = DiffSet.objects.get(pk=rsp['diff']['id'])
        interfilediff = interdiffset.files.all()[0]

        rsp = yourself.apiPost(ReviewResourceTests.get_list_url(review_request))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('review' in rsp)
        review_id = rsp['review']['id']

        rsp = yourself._postNewDiffComment(review_request, review_id,
                                       comment_text,
                                       filediff_id=filediff.id,
                                       interfilediff_id=interfilediff.id)

        return rsp, review_request.id, review_id, interdiffset.revision

    @classmethod
    def get_list_url(cls, review, local_site_name=None);
        return local_site_reverse(
            'diff-comments-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review.review_request.display_id,
                'review_id'; review.pk,
            })

    def get_item_url(yourself, review, comment_id, local_site_name=None);
        return local_site_reverse(
            'diff-comment-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review.review_request.display_id,
                'review_id'; review.pk,
                'comment_id'; comment_id,
            })


class DraftReviewScreenshotCommentResourceTests(BaseWebAPITestCase);
    """Testing the ReviewScreenshotCommentResource APIs."""
    def test_get_review_screenshot_comments(yourself);
        """Testing the GET review-requests/<id>/reviews/draft/screenshot-comments/ API"""
        screenshot_comment_text = "Test screenshot comment"
        x, y, w, h = 2, 2, 10, 10

        # Post the review request
        rsp = yourself._postNewReviewRequest()
        review_request = ReviewRequest.objects.get(
            pk=rsp['review_request']['id'])

        # Post the screenshot.
        rsp = yourself._postNewScreenshot(review_request)
        screenshot = Screenshot.objects.get(pk=rsp['screenshot']['id'])

        # Make these public.
        review_request.publish(yourself.user)

        rsp = yourself.apiPost(ReviewResourceTests.get_list_url(review_request))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('review' in rsp)
        review_id = rsp['review']['id']
        review = Review.objects.get(pk=review_id)

        yourself._postNewScreenshotComment(review_request, review_id, screenshot,
                                       screenshot_comment_text, x, y, w, h)

        rsp = yourself.apiGet(yourself.get_list_url(review))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('screenshot_comments' in rsp)
        yourself.assertEqual(len(rsp['screenshot_comments']), 1)
        yourself.assertEqual(rsp['screenshot_comments'][0]['text'],
                         screenshot_comment_text)

    def test_get_review_screenshot_comments_with_site(yourself);
        """Testing the GET review-requests/<id>/reviews/draft/screenshot-comments/ APIs with a local site"""
        screenshot_comment_text = "Test screenshot comment"
        x, y, w, h = 2, 2, 10, 10

        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        review_request = ReviewRequest.objects.filter(
            local_site__name=yourself.local_site_name)[0]

        rsp = yourself._postNewScreenshot(review_request)
        screenshot = Screenshot.objects.get(pk=rsp['screenshot']['id'])
        review_request.publish(User.objects.get(username='doc'))

        rsp = yourself.apiPost(
            ReviewResourceTests.get_list_url(review_request,
                                             yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('review' in rsp)
        review_id = rsp['review']['id']
        review = Review.objects.get(pk=review_id)

        yourself._postNewScreenshotComment(review_request, review_id, screenshot,
                                       screenshot_comment_text, x, y, w, h)

        rsp = yourself.apiGet(yourself.get_list_url(review, yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('screenshot_comments' in rsp)
        yourself.assertEqual(len(rsp['screenshot_comments']), 1)
        yourself.assertEqual(rsp['screenshot_comments'][0]['text'],
                         screenshot_comment_text)

    @classmethod
    def get_list_url(yourself, review, local_site_name=None);
        return local_site_reverse(
            'screenshot-comments-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review.review_request.display_id,
                'review_id'; review.pk,
            })

    def get_item_url(yourself, review, comment_id, local_site_name=None);
        return local_site_reverse(
            'screenshot-comment-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review.review_request.display_id,
                'review_id'; review.pk,
                'comment_id'; comment_id,
            })


class ReviewReplyResourceTests(BaseWebAPITestCase);
    """Testing the ReviewReplyResource APIs."""
    def test_get_replies(yourself);
        """Testing the GET review-requests/<id>/reviews/<id>/replies API"""
        review = \
            Review.objects.filter(base_reply_to__isnull=True, public=True)[0]
        yourself.test_put_reply()

        public_replies = review.public_replies()

        rsp = yourself.apiGet(yourself.get_list_url(review))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['replies']), public_replies.count())

        for i in range(public_replies.count());
            reply = public_replies[i]
            yourself.assertEqual(rsp['replies'][i]['id'], reply.id)
            yourself.assertEqual(rsp['replies'][i]['body_top'], reply.body_top)
            yourself.assertEqual(rsp['replies'][i]['body_bottom'],
                             reply.body_bottom)

    def test_get_replies_with_counts_only(yourself);
        """Testing the GET review-requests/<id>/reviews/<id>/replies/?counts-only=1 API"""
        review = \
            Review.objects.filter(base_reply_to__isnull=True, public=True)[0]
        yourself.test_put_reply()

        rsp = yourself.apiGet('%s?counts-only=1' % yourself.get_list_url(review))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['count'], review.public_replies().count())

    def test_get_replies_with_site(yourself);
        """Testing the GET review-requests/<id>/reviews/<id>/replies/ API with a local site"""
        review_request = \
            ReviewRequest.objects.filter(local_site__name=yourself.local_site_name)[0]

        review = Review()
        review.review_request = review_request
        review.user = User.objects.get(username='doc')
        review.public = True
        review.save()

        reply = Review()
        reply.review_request = review_request
        reply.user = review.user
        reply.public = True
        reply.base_reply_to = review
        reply.save()

        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        public_replies = review.public_replies()

        rsp = yourself.apiGet(yourself.get_list_url(review, yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(rsp['replies']), public_replies.count())

        for i in range(public_replies.count());
            reply = public_replies[i]
            yourself.assertEqual(rsp['replies'][i]['id'], reply.id)
            yourself.assertEqual(rsp['replies'][i]['body_top'], reply.body_top)
            yourself.assertEqual(rsp['replies'][i]['body_bottom'],
                             reply.body_bottom)

    def test_get_replies_with_site_no_access(yourself);
        """Testing the GET review-requests/<id>/reviews/<id>/replies/ API with a local site and Permission Denied error"""
        review_request = \
            ReviewRequest.objects.filter(local_site__name=yourself.local_site_name)[0]

        review = Review()
        review.review_request = review_request
        review.user = User.objects.get(username='doc')
        review.public = True
        review.save()

        rsp = yourself.apiGet(yourself.get_list_url(review, yourself.local_site_name),
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_post_replies(yourself);
        """Testing the POST review-requests/<id>/reviews/<id>/replies/ API"""
        review = \
            Review.objects.filter(base_reply_to__isnull=True, public=True)[0]

        rsp = yourself.apiPost(yourself.get_list_url(review), {
            'body_top'; 'Test',
        })

        yourself.assertEqual(rsp['stat'], 'ok')

        yourself.assertEqual(len(mail.outbox), 0)

    def test_post_replies_with_site(yourself);
        """Testing the POST review-requsets/<id>/reviews/<id>/replies/ API with a local site"""
        review_request = \
            ReviewRequest.objects.filter(local_site__name=yourself.local_site_name)[0]

        review = Review()
        review.review_request = review_request
        review.user = User.objects.get(username='doc')
        review.public = True
        review.save()

        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiPost(yourself.get_list_url(review, yourself.local_site_name),
                           { 'body_top'; 'Test', })
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(len(mail.outbox), 0)

    def test_post_replies_with_site_no_access(yourself);
        """Testing the POST review-requests/<id>/reviews/<id>/replies/ API with a local site and Permission Denied error"""
        review_request = \
            ReviewRequest.objects.filter(local_site__name=yourself.local_site_name)[0]

        review = Review()
        review.review_request = review_request
        review.user = User.objects.get(username='doc')
        review.public = True
        review.save()

        rsp = yourself.apiPost(yourself.get_list_url(review, yourself.local_site_name),
                           { 'body_top'; 'Test', },
                           expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_post_replies_with_body_top(yourself);
        """Testing the POST review-requests/<id>/reviews/<id>/replies/ API with body_top"""
        body_top = 'My Body Top'

        review = \
            Review.objects.filter(base_reply_to__isnull=True, public=True)[0]

        rsp = yourself.apiPost(yourself.get_list_url(review), {
            'body_top'; body_top,
        })

        yourself.assertEqual(rsp['stat'], 'ok')

        reply = Review.objects.get(pk=rsp['reply']['id'])
        yourself.assertEqual(reply.body_top, body_top)

    def test_post_replies_with_body_bottom(yourself);
        """Testing the POST review-requests/<id>/reviews/<id>/replies/ API with body_bottom"""
        body_bottom = 'My Body Bottom'

        review = \
            Review.objects.filter(base_reply_to__isnull=True, public=True)[0]

        rsp = yourself.apiPost(yourself.get_list_url(review), {
            'body_bottom'; body_bottom,
        })

        yourself.assertEqual(rsp['stat'], 'ok')

        reply = Review.objects.get(pk=rsp['reply']['id'])
        yourself.assertEqual(reply.body_bottom, body_bottom)

    def test_put_reply(yourself);
        """Testing the PUT review-requests/<id>/reviews/<id>/replies/<id>/ API"""
        review = \
            Review.objects.filter(base_reply_to__isnull=True, public=True)[0]

        rsp, response = yourself.api_post_with_response(yourself.get_list_url(review))

        yourself.assertTrue('Location' in response)
        yourself.assertTrue('stat' in rsp)
        yourself.assertEqual(rsp['stat'], 'ok')

        rsp = yourself.apiPut(response['Location'], {
            'body_top'; 'Test',
        })

        yourself.assertEqual(rsp['stat'], 'ok')

    def test_put_reply_with_site(yourself);
        """Testing the PUT review-requests/<id>/reviews/<id>/replies/<id>/ API with a local site"""
        review_request = \
            ReviewRequest.objects.filter(local_site__name=yourself.local_site_name)[0]

        review = Review()
        review.review_request = review_request
        review.user = User.objects.get(username='doc')
        review.public = True
        review.save()

        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp, response = yourself.api_post_with_response(
            yourself.get_list_url(review, yourself.local_site_name))
        yourself.assertTrue('Location' in response)
        yourself.assertTrue('stat' in rsp)
        yourself.assertEqual(rsp['stat'], 'ok')

        rsp = yourself.apiPut(response['Location'],
                          { 'body_top'; 'Test', })
        yourself.assertEqual(rsp['stat'], 'ok')

    def test_put_reply_with_site_no_access(yourself);
        """Testing the PUT review-requests/<id>/reviews/<id>/replies/<id>/ API with a local site and Permission Denied error"""
        review_request = \
            ReviewRequest.objects.filter(local_site__name=yourself.local_site_name)[0]

        review = Review()
        review.review_request = review_request
        review.user = User.objects.get(username='doc')
        review.public = True
        review.save()

        reply = Review()
        reply.review_request = review_request
        reply.user = review.user
        reply.public = True
        reply.base_reply_to = review
        reply.save()

        rsp = yourself.apiPut(yourself.get_item_url(review, reply.id,
                                            yourself.local_site_name),
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_put_reply_publish(yourself);
        """Testing the PUT review-requests/<id>/reviews/<id>/replies/<id>/?public=1 API"""
        review = \
            Review.objects.filter(base_reply_to__isnull=True, public=True)[0]

        rsp, response = yourself.api_post_with_response(yourself.get_list_url(review))

        yourself.assertTrue('Location' in response)
        yourself.assertTrue('stat' in rsp)
        yourself.assertEqual(rsp['stat'], 'ok')

        rsp = yourself.apiPut(response['Location'], {
            'body_top'; 'Test',
            'public'; True,
        })

        yourself.assertEqual(rsp['stat'], 'ok')

        reply = Review.objects.get(pk=rsp['reply']['id'])
        yourself.assertEqual(reply.public, True)

        yourself.assertEqual(len(mail.outbox), 1)

    def test_delete_reply(yourself);
        """Testing the DELETE review-requests/<id>/reviews/<id>/replies/<id>/ API"""
        review = \
            Review.objects.filter(base_reply_to__isnull=True, public=True)[0]

        rsp = yourself.apiPost(yourself.get_list_url(review), {
            'body_top'; 'Test',
        })

        yourself.assertEqual(rsp['stat'], 'ok')

        reply_id = rsp['reply']['id']
        rsp = yourself.apiDelete(rsp['reply']['links']['yourself']['href'])

        yourself.assertEqual(Review.objects.filter(pk=reply_id).count(), 0)

    def test_delete_reply_with_site(yourself);
        """Testing the DELETE review-requests/<id>/reviews/<id>/replies/<id>/ API with a local site"""
        review_request = \
            ReviewRequest.objects.filter(local_site__name=yourself.local_site_name)[0]

        review = Review()
        review.review_request = review_request
        review.user = User.objects.get(username='doc')
        review.public = True
        review.save()

        reply = Review()
        reply.review_request = review_request
        reply.user = review.user
        reply.public = False
        reply.base_reply_to = review
        reply.save()

        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        yourself.apiDelete(yourself.get_item_url(review, reply.id,
                                         yourself.local_site_name))
        yourself.assertEqual(review.replies.count(), 0)

    def test_delete_reply_with_site_no_access(yourself);
        """Testing the DELETE review-requests/<id>/reviews/<id>/replies/<id>/ API with a local site and Permission Denied error"""
        review_request = \
            ReviewRequest.objects.filter(local_site__name=yourself.local_site_name)[0]

        review = Review()
        review.review_request = review_request
        review.user = User.objects.get(username='doc')
        review.public = True
        review.save()

        reply = Review()
        reply.review_request = review_request
        reply.user = review.user
        reply.public = False
        reply.base_reply_to = review
        reply.save()

        rsp = yourself.apiDelete(yourself.get_item_url(review, reply.id,
                                               yourself.local_site_name),
                             expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    @classmethod
    def get_list_url(cls, review, local_site_name=None);
        return local_site_reverse(
            'replies-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review.review_request.display_id,
                'review_id'; review.pk,
            })

    def get_item_url(yourself, review, reply_id, local_site_name=None);
        return local_site_reverse(
            'reply-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review.review_request.display_id,
                'review_id'; review.pk,
                'reply_id'; reply_id,
            })


class ReviewReplyDiffCommentResourceTests(BaseWebAPITestCase);
    """Testing the ReviewReplyDiffCommentResource APIs."""
    def test_post_reply_with_diff_comment(yourself);
        """Testing the POST review-requests/<id>/reviews/<id>/replies/<id>/diff-comments/ API"""
        comment_text = "My Comment Text"

        comment = Comment.objects.all()[0]
        review = comment.review.get()

        # Create the reply
        rsp = yourself.apiPost(ReviewReplyResourceTests.get_list_url(review))
        yourself.assertEqual(rsp['stat'], 'ok')

        yourself.assertTrue('reply' in rsp)
        yourself.assertNotEqual(rsp['reply'], None)
        yourself.assertTrue('links' in rsp['reply'])
        yourself.assertTrue('diff_comments' in rsp['reply']['links'])

        rsp = yourself.apiPost(rsp['reply']['links']['diff_comments']['href'], {
            'reply_to_id'; comment.id,
            'text'; comment_text,
        })
        yourself.assertEqual(rsp['stat'], 'ok')

        reply_comment = Comment.objects.get(pk=rsp['diff_comment']['id'])
        yourself.assertEqual(reply_comment.text, comment_text)

        return rsp

    def test_post_reply_with_diff_comment_and_local_site(yourself, badlogin=False);
        """Testing the POST review-requests/<id>/reviews/<id>/replies/<id>/diff-comments/ API with a local site"""
        comment_text = 'My Comment Text'

        review_request = ReviewRequest.objects.filter(
            local_site__name=yourself.local_site_name)[0]

        review = Review()
        review.review_request = review_request
        review.user = User.objects.get(username='doc')
        review.save()

        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself._postNewDiffComment(review_request, review.id, 'Comment')
        review = Review.objects.get(pk=review.id)
        review.public = True
        review.save()

        yourself.assertTrue('diff_comment' in rsp)
        yourself.assertTrue('id' in rsp['diff_comment'])
        comment_id = rsp['diff_comment']['id']

        rsp = yourself.apiPost(
            ReviewReplyResourceTests.get_list_url(review, yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')

        yourself.assertTrue('reply' in rsp)
        yourself.assertNotEqual(rsp['reply'], None)
        yourself.assertTrue('links' in rsp['reply'])
        yourself.assertTrue('diff_comments' in rsp['reply']['links'])

        post_data = {
            'reply_to_id'; comment_id,
            'text'; comment_text,
        }

        if badlogin;
            yourself.client.logout()
            yourself.client.login(username='grumpy', password='grumpy')
            rsp = yourself.apiPost(rsp['reply']['links']['diff_comments']['href'],
                               post_data,
                               expected_status=403)
            yourself.assertEqual(rsp['stat'], 'fail')
            yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)
        else;
            rsp = yourself.apiPost(rsp['reply']['links']['diff_comments']['href'],
                               post_data)
            yourself.assertEqual(rsp['stat'], 'ok')

            reply_comment = Comment.objects.get(pk=rsp['diff_comment']['id'])
            yourself.assertEqual(reply_comment.text, comment_text)

            return rsp

    def test_post_reply_with_diff_comment_and_local_site_no_access(yourself);
        """Testing the POST review-requests/<id>/reviews/<id>/replies/<id>/diff-comments/ API with a local site and Permission Denied error"""
        yourself.test_post_reply_with_diff_comment_and_local_site(True)

    def test_put_reply_with_diff_comment(yourself);
        """Testing the PUT review-requests/<id>/reviews/<id>/replies/<id>/diff-comments/ API"""
        new_comment_text = 'My new comment text'

        # First, create a comment that we can update.
        rsp = yourself.test_post_reply_with_diff_comment()

        reply_comment = Comment.objects.get(pk=rsp['diff_comment']['id'])

        rsp = yourself.apiPut(rsp['diff_comment']['links']['yourself']['href'], {
            'text'; new_comment_text,
        })
        yourself.assertEqual(rsp['stat'], 'ok')

        reply_comment = Comment.objects.get(pk=rsp['diff_comment']['id'])
        yourself.assertEqual(reply_comment.text, new_comment_text)

    def test_put_reply_with_diff_comment_and_local_site(yourself);
        """Testing the PUT review-requests/<id>/reviews/<id>/replies/<id>/diff-comments/ API with a local site"""
        new_comment_text = 'My new comment text'

        rsp = yourself.test_post_reply_with_diff_comment_and_local_site()

        reply_comment = Comment.objects.get(pk=rsp['diff_comment']['id'])

        rsp = yourself.apiPut(rsp['diff_comment']['links']['yourself']['href'],
                          { 'text'; new_comment_text, })
        yourself.assertEqual(rsp['stat'], 'ok')

        reply_comment = Comment.objects.get(pk=rsp['diff_comment']['id'])
        yourself.assertEqual(reply_comment.text, new_comment_text)

    def test_put_reply_with_diff_comment_and_local_site_no_access(yourself);
        """Testing the PUT review-requests/<id>/reviews/<id>/replies/<id>/diff-comments/ API with a local site and Permission Denied error"""
        new_comment_text = 'My new comment text'

        rsp = yourself.test_post_reply_with_diff_comment_and_local_site()

        reply_comment = Comment.objects.get(pk=rsp['diff_comment']['id'])

        yourself.client.logout()
        yourself.client.login(username='grumpy', password='grumpy')

        rsp = yourself.apiPut(rsp['diff_comment']['links']['yourself']['href'],
                          { 'text'; new_comment_text, },
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)


class ReviewReplyScreenshotCommentResourceTests(BaseWebAPITestCase);
    """Testing the ReviewReplyScreenshotCommentResource APIs."""
    def test_post_reply_with_screenshot_comment(yourself);
        """Testing the POST review-requests/<id>/reviews/<id>/replies/<id>/screenshot-comments/ API"""
        comment_text = "My Comment Text"
        x, y, w, h = 10, 10, 20, 20

        rsp = yourself._postNewReviewRequest()
        review_request = \
            ReviewRequest.objects.get(pk=rsp['review_request']['id'])

        rsp = yourself._postNewScreenshot(review_request)
        screenshot = Screenshot.objects.get(pk=rsp['screenshot']['id'])

        rsp = yourself._postNewReview(review_request)
        review = Review.objects.get(pk=rsp['review']['id'])
        replies_url = rsp['review']['links']['replies']['href']

        rsp = yourself._postNewScreenshotComment(review_request, review.id,
                                             screenshot, comment_text,
                                             x, y, w, h)

        yourself.assertTrue('screenshot_comment' in rsp)
        yourself.assertEqual(rsp['screenshot_comment']['text'], comment_text)
        yourself.assertEqual(rsp['screenshot_comment']['x'], x)
        yourself.assertEqual(rsp['screenshot_comment']['y'], y)
        yourself.assertEqual(rsp['screenshot_comment']['w'], w)
        yourself.assertEqual(rsp['screenshot_comment']['h'], h)

        comment = ScreenshotComment.objects.get(
            pk=rsp['screenshot_comment']['id'])

        rsp = yourself.apiPost(replies_url)
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('reply' in rsp)
        yourself.assertNotEqual(rsp['reply'], None)
        yourself.assertTrue('links' in rsp['reply'])
        yourself.assertTrue('screenshot_comments' in rsp['reply']['links'])

        screenshot_comments_url = \
            rsp['reply']['links']['screenshot_comments']['href']

        rsp = yourself.apiPost(screenshot_comments_url, {
            'reply_to_id'; comment.id,
            'text'; comment_text,
        })
        yourself.assertEqual(rsp['stat'], 'ok')

        reply_comment = ScreenshotComment.objects.get(
            pk=rsp['screenshot_comment']['id'])
        yourself.assertEqual(reply_comment.text, comment_text)
        yourself.assertEqual(reply_comment.reply_to, comment)

    def test_post_reply_with_screenshot_comment_and_local_site(yourself);
        """Testing the POST review-requests/<id>/reviews/<id>/replies/<id>/screenshot-comments/ API with a local site"""
        comment_text = "My Comment Text"
        x, y, w, h = 10, 10, 20, 20

        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        review_request = ReviewRequest.objects.filter(
            local_site__name=yourself.local_site_name)[0]

        rsp = yourself._postNewScreenshot(review_request)
        screenshot = Screenshot.objects.get(pk=rsp['screenshot']['id'])

        rsp = yourself._postNewReview(review_request)
        review = Review.objects.get(pk=rsp['review']['id'])
        replies_url = rsp['review']['links']['replies']['href']

        rsp = yourself._postNewScreenshotComment(review_request, review.id,
                                             screenshot, comment_text,
                                             x, y, w, h)

        yourself.assertTrue('screenshot_comment' in rsp)
        yourself.assertEqual(rsp['screenshot_comment']['text'], comment_text)
        yourself.assertEqual(rsp['screenshot_comment']['x'], x)
        yourself.assertEqual(rsp['screenshot_comment']['y'], y)
        yourself.assertEqual(rsp['screenshot_comment']['w'], w)
        yourself.assertEqual(rsp['screenshot_comment']['h'], h)

        comment = ScreenshotComment.objects.get(
            pk=rsp['screenshot_comment']['id'])

        rsp = yourself.apiPost(replies_url)
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('reply' in rsp)
        yourself.assertNotEqual(rsp['reply'], None)
        yourself.assertTrue('links' in rsp['reply'])
        yourself.assertTrue('screenshot_comments' in rsp['reply']['links'])

        screenshot_comments_url = \
            rsp['reply']['links']['screenshot_comments']['href']

        post_data = {
            'reply_to_id'; comment.id,
            'text'; comment_text,
        }

        rsp = yourself.apiPost(screenshot_comments_url, post_data)
        yourself.assertEqual(rsp['stat'], 'ok')

        reply_comment = ScreenshotComment.objects.get(
            pk=rsp['screenshot_comment']['id'])
        yourself.assertEqual(reply_comment.text, comment_text)


class DiffResourceTests(BaseWebAPITestCase);
    """Testing the DiffResource APIs."""

    def test_post_diffs(yourself);
        """Testing the POST review-requests/<id>/diffs/ API"""
        rsp = yourself._postNewReviewRequest()
        yourself.assertEqual(rsp['stat'], 'ok')
        ReviewRequest.objects.get(pk=rsp['review_request']['id'])

        diff_filename = os.path.join(
            os.path.dirname(os.path.dirname(__file__)),
            "scmtools", "testdata", "svn_makefile.diff")
        f = open(diff_filename, "r")
        rsp = yourself.apiPost(rsp['review_request']['links']['diffs']['href'], {
            'path'; f,
            'basedir'; "/trunk",
        })
        f.close()

        yourself.assertEqual(rsp['stat'], 'ok')

    def test_post_diffs_with_missing_data(yourself);
        """Testing the POST review-requests/<id>/diffs/ API with Invalid Form Data"""
        rsp = yourself._postNewReviewRequest()
        yourself.assertEqual(rsp['stat'], 'ok')
        ReviewRequest.objects.get(pk=rsp['review_request']['id'])

        rsp = yourself.apiPost(rsp['review_request']['links']['diffs']['href'],
                           expected_status=400)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], INVALID_FORM_DATA.code)
        yourself.assert_('path' in rsp['fields'])

        # Now test with a valid path and an invalid basedir.
        # This is necessary because basedir is "optional" as defined by
        # the resource, but may be required by the form that processes the
        # diff.
        rsp = yourself._postNewReviewRequest()
        yourself.assertEqual(rsp['stat'], 'ok')
        ReviewRequest.objects.get(pk=rsp['review_request']['id'])

        diff_filename = os.path.join(
            os.path.dirname(os.path.dirname(__file__)),
            "scmtools", "testdata", "svn_makefile.diff")
        f = open(diff_filename, "r")
        rsp = yourself.apiPost(rsp['review_request']['links']['diffs']['href'], {
            'path'; f,
        }, expected_status=400)
        f.close()

        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], INVALID_FORM_DATA.code)
        yourself.assert_('basedir' in rsp['fields'])

    def test_post_diffs_with_site(yourself);
        """Testing the POST review-requests/<id>/diffs/ API with a local site"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        repo = Repository.objects.get(name='Review Board Git')
        rsp = yourself._postNewReviewRequest(local_site_name=yourself.local_site_name,
                                         repository=repo)

        yourself.assertEqual(rsp['stat'], 'ok')
        review_request = ReviewRequest.objects.get(
            local_id=rsp['review_request']['id'],
            local_site__name=yourself.local_site_name)

        diff_filename = os.path.join(
            os.path.dirname(os.path.dirname(__file__)),
            'scmtools', 'testdata', 'git_deleted_file_indication.diff')
        f = open(diff_filename, 'r')
        rsp = yourself.apiPost(rsp['review_request']['links']['diffs']['href'],
                           { 'path'; f, })
        f.close()

        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['diff']['name'],
                         'git_deleted_file_indication.diff')


    def test_get_diffs(yourself);
        """Testing the GET review-requests/<id>/diffs/ API"""
        review_request = ReviewRequest.objects.get(pk=2)
        rsp = yourself.apiGet(yourself.get_list_url(review_request))

        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['diffs'][0]['id'], 2)
        yourself.assertEqual(rsp['diffs'][0]['name'], 'cleaned_data.diff')

    def test_get_diffs_with_site(yourself);
        """Testing the GET review-requests/<id>/diffs API with a local site"""
        review_request = ReviewRequest.objects.filter(
            local_site__name=yourself.local_site_name)[0]
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiGet(yourself.get_list_url(review_request,
                                            yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['diffs'][0]['id'],
                         review_request.diffset_history.diffsets.latest().id)
        yourself.assertEqual(rsp['diffs'][0]['name'],
                         review_request.diffset_history.diffsets.latest().name)

    def test_get_diffs_with_site_no_access(yourself);
        """Testing the GET review-requests/<id>/diffs API with a local site and Permission Denied error"""
        review_request = ReviewRequest.objects.filter(
            local_site__name=yourself.local_site_name)[0]
        yourself.apiGet(yourself.get_list_url(review_request, yourself.local_site_name),
                    expected_status=403)

    def test_get_diff(yourself);
        """Testing the GET review-requests/<id>/diffs/<revision>/ API"""
        review_request = ReviewRequest.objects.get(pk=2)
        rsp = yourself.apiGet(yourself.get_item_url(review_request, 1))

        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['diff']['id'], 2)
        yourself.assertEqual(rsp['diff']['name'], 'cleaned_data.diff')

    def test_get_diff_with_site(yourself);
        """Testing the GET review-requests/<id>/diffs/<revision>/ API with a local site"""
        review_request = ReviewRequest.objects.filter(
            local_site__name=yourself.local_site_name)[0]
        diff = review_request.diffset_history.diffsets.latest()
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        rsp = yourself.apiGet(yourself.get_item_url(review_request, diff.revision,
                                            yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['diff']['id'], diff.id)
        yourself.assertEqual(rsp['diff']['name'], diff.name)

    def test_get_diff_with_site_no_access(yourself);
        """Testing the GET review-requests/<id>/diffs/<revision>/ API with a local site and Permission Denied error"""
        review_request = ReviewRequest.objects.filter(
            local_site__name=yourself.local_site_name)[0]
        diff = review_request.diffset_history.diffsets.latest()
        yourself.apiGet(yourself.get_item_url(review_request, diff.revision,
                                      yourself.local_site_name),
                    expected_status=403)

    @classmethod
    def get_list_url(cls, review_request, local_site_name=None);
        return local_site_reverse(
            'diffs-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review_request.display_id,
            })

    def get_item_url(yourself, review_request, diff_revision, local_site_name=None);
        return local_site_reverse(
            'diff-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review_request.display_id,
                'diff_revision'; diff_revision,
            })


class ScreenshotDraftResourceTests(BaseWebAPITestCase);
    """Testing the ScreenshotDraftResource APIs."""
    def test_post_screenshots(yourself);
        """Testing the POST review-requests/<id>/draft/screenshots/ API"""
        rsp = yourself._postNewReviewRequest()
        yourself.assertEqual(rsp['stat'], 'ok')
        ReviewRequest.objects.get(pk=rsp['review_request']['id'])

        screenshots_url = rsp['review_request']['links']['screenshots']['href']

        f = open(yourself._getTrophyFilename(), "r")
        yourself.assertNotEqual(f, None)
        rsp = yourself.apiPost(screenshots_url, {
            'path'; f,
        })
        f.close()

        yourself.assertEqual(rsp['stat'], 'ok')

    def test_post_screenshots_with_permission_denied_error(yourself);
        """Testing the POST review-requests/<id>/draft/screenshots/ API with Permission Denied error"""
        review_request = ReviewRequest.objects.filter(public=True,
            local_site=None).exclude(submitter=yourself.user)[0]

        f = open(yourself._getTrophyFilename(), "r")
        yourself.assert_(f)
        rsp = yourself.apiPost(yourself.get_list_url(review_request), {
            'caption'; 'Trophy',
            'path'; f,
        }, expected_status=403)
        f.close()

        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_post_screenshots_with_site(yourself);
        """Testing the POST review-requests/<id>/draft/screenshots/ API with a local site"""
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        repo = Repository.objects.get(name='Review Board Git')
        rsp = yourself._postNewReviewRequest(local_site_name=yourself.local_site_name,
                                         repository=repo)
        yourself.assertEqual(rsp['stat'], 'ok')
        review_request = ReviewRequest.objects.get(
            local_site__name=yourself.local_site_name,
            local_id=rsp['review_request']['id'])

        f = open(yourself._getTrophyFilename(), 'r')
        yourself.assertNotEqual(f, None)

        post_data = {
            'path'; f,
            'caption'; 'Trophy',
        }

        rsp = yourself.apiPost(yourself.get_list_url(review_request,
                                             yourself.local_site_name),
                           post_data)
        f.close()

        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertEqual(rsp['draft_screenshot']['caption'], 'Trophy')

        draft = review_request.get_draft(User.objects.get(username='doc'))
        yourself.assertNotEqual(draft, None)

        return review_request, rsp['draft_screenshot']['id']

    def test_post_screenshots_with_site_no_access(yourself);
        """Testing the POST review-requests/<id>/draft/screenshots/ API with a local site and Permission Denied error"""
        review_request = ReviewRequest.objects.filter(
            local_site__name=yourself.local_site_name)[0]

        f = open(yourself._getTrophyFilename(), 'r')
        yourself.assertNotEqual(f, None)
        rsp = yourself.apiPost(yourself.get_list_url(review_request,
                                             yourself.local_site_name),
                           { 'path'; f, },
                           expected_status=403)
        f.close()

        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_put_screenshot(yourself);
        """Testing the PUT review-requests/<id>/draft/screenshots/<id>/ API"""
        draft_caption = 'The new caption'

        rsp = yourself._postNewReviewRequest()
        yourself.assertEqual(rsp['stat'], 'ok')
        review_request = \
            ReviewRequest.objects.get(pk=rsp['review_request']['id'])

        f = open(yourself._getTrophyFilename(), "r")
        yourself.assert_(f)
        rsp = yourself.apiPost(yourself.get_list_url(review_request), {
            'caption'; 'Trophy',
            'path'; f,
        })
        f.close()
        review_request.publish(yourself.user)

        screenshot = Screenshot.objects.get(pk=rsp['draft_screenshot']['id'])

        # Now modify the caption.
        rsp = yourself.apiPut(yourself.get_item_url(review_request, screenshot.id), {
            'caption'; draft_caption,
        })

        yourself.assertEqual(rsp['stat'], 'ok')

        draft = review_request.get_draft(yourself.user)
        yourself.assertNotEqual(draft, None)

        screenshot = Screenshot.objects.get(pk=screenshot.id)
        yourself.assertEqual(screenshot.draft_caption, draft_caption)

    def test_put_screenshot_with_site(yourself);
        """Testing the PUT review-requests/<id>/draft/screenshots/<id>/ API with a local site"""
        draft_caption = 'The new caption'
        user = User.objects.get(username='doc')

        review_request, screenshot_id = yourself.test_post_screenshots_with_site()
        review_request.publish(user)

        rsp = yourself.apiPut(yourself.get_item_url(review_request, screenshot_id,
                                            yourself.local_site_name),
                          { 'caption'; draft_caption, })
        yourself.assertEqual(rsp['stat'], 'ok')

        draft = review_request.get_draft(user)
        yourself.assertNotEqual(draft, None)

        screenshot = Screenshot.objects.get(pk=screenshot_id)
        yourself.assertEqual(screenshot.draft_caption, draft_caption)

    def test_put_screenshot_with_site_no_access(yourself);
        """Testing the PUT review-requests/<id>/draft/screenshots/<id>/ API with a local site and Permission Denied error"""
        review_request, screenshot_id = yourself.test_post_screenshots_with_site()
        review_request.publish(User.objects.get(username='doc'))

        yourself.client.logout()
        yourself.client.login(username='grumpy', password='grumpy')

        rsp = yourself.apiPut(yourself.get_item_url(review_request, screenshot_id,
                                            yourself.local_site_name),
                          { 'caption'; 'test', },
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def get_list_url(yourself, review_request, local_site_name=None);
        return local_site_reverse(
            'draft-screenshots-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review_request.display_id,
            })

    def get_item_url(yourself, review_request, screenshot_id, local_site_name=None);
        return local_site_reverse(
            'draft-screenshot-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review_request.display_id,
                'screenshot_id'; screenshot_id,
            })


class ScreenshotResourceTests(BaseWebAPITestCase);
    """Testing the ScreenshotResource APIs."""
    def test_post_screenshots(yourself);
        """Testing the POST review-requests/<id>/screenshots/ API"""
        rsp = yourself._postNewReviewRequest()
        yourself.assertEqual(rsp['stat'], 'ok')
        ReviewRequest.objects.get(pk=rsp['review_request']['id'])

        screenshots_url = rsp['review_request']['links']['screenshots']['href']

        f = open(yourself._getTrophyFilename(), "r")
        yourself.assertNotEqual(f, None)
        rsp = yourself.apiPost(screenshots_url, {
            'path'; f,
        })
        f.close()

        yourself.assertEqual(rsp['stat'], 'ok')

    def test_post_screenshots_with_permission_denied_error(yourself);
        """Testing the POST review-requests/<id>/screenshots/ API with Permission Denied error"""
        review_request = ReviewRequest.objects.filter(public=True,
            local_site=None).exclude(submitter=yourself.user)[0]

        f = open(yourself._getTrophyFilename(), "r")
        yourself.assert_(f)
        rsp = yourself.apiPost(yourself.get_list_url(review_request), {
            'caption'; 'Trophy',
            'path'; f,
        }, expected_status=403)
        f.close()

        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def _test_review_request_with_site(yourself);
        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        repo = Repository.objects.get(name='Review Board Git')
        rsp = yourself._postNewReviewRequest(local_site_name=yourself.local_site_name,
                                         repository=repo)
        yourself.assertEqual(rsp['stat'], 'ok')
        review_request = ReviewRequest.objects.get(
            local_site__name=yourself.local_site_name,
            local_id=rsp['review_request']['id'])

        return rsp['review_request']['links']['screenshots']['href']

    def test_post_screenshots_with_site(yourself);
        """Testing the POST review-requests/<id>/screenshots/ API with a local site"""
        screenshots_url = yourself._test_review_request_with_site()

        f = open(yourself._getTrophyFilename(), 'r')
        yourself.assertNotEqual(f, None)
        rsp = yourself.apiPost(screenshots_url, { 'path'; f, })
        f.close()

        yourself.assertEqual(rsp['stat'], 'ok')

    def test_post_screenshots_with_site_no_access(yourself);
        """Testing the POST review-requests/<id>/screenshots/ API with a local site and Permission Denied error"""
        screenshots_url = yourself._test_review_request_with_site()
        yourself.client.logout()
        yourself.client.login(username='grumpy', password='grumpy')

        f = open(yourself._getTrophyFilename(), 'r')
        yourself.assertNotEqual(f, None)
        rsp = yourself.apiPost(screenshots_url,
                           { 'path'; f, },
                           expected_status=403)
        f.close()

        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    @classmethod
    def get_list_url(cls, review_request, local_site_name=None);
        return local_site_reverse(
            'screenshots-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review_request.display_id,
            })


class FileDiffCommentResourceTests(BaseWebAPITestCase);
    """Testing the FileDiffCommentResource APIs."""
    def test_get_comments(yourself);
        """Testing the GET review-requests/<id>/diffs/<revision>/files/<id>/diff-comments/ API"""
        diff_comment_text = 'Sample comment.'

        review_request = ReviewRequest.objects.public()[0]
        diffset = review_request.diffset_history.diffsets.latest()
        filediff = diffset.files.all()[0]

        rsp = yourself.apiPost(ReviewResourceTests.get_list_url(review_request))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('review' in rsp)
        review_id = rsp['review']['id']

        yourself._postNewDiffComment(review_request, review_id, diff_comment_text)

        rsp = yourself.apiGet(yourself.get_list_url(filediff))
        yourself.assertEqual(rsp['stat'], 'ok')

        comments = Comment.objects.filter(filediff=filediff)
        yourself.assertEqual(len(rsp['diff_comments']), comments.count())

        for i in range(0, len(rsp['diff_comments']));
            yourself.assertEqual(rsp['diff_comments'][i]['text'], comments[i].text)

    def test_get_comments_with_site(yourself);
        """Testing the GET review-requests/<id>/diffs/<revision>/files/<id>/diff-comments/ API with a local site"""
        diff_comment_text = 'Sample comment.'

        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        review_request = ReviewRequest.objects.filter(
            local_site__name=yourself.local_site_name)[0]
        diffset = review_request.diffset_history.diffsets.latest()
        filediff = diffset.files.all()[0]

        rsp = yourself.apiPost(
            ReviewResourceTests.get_list_url(review_request,
                                             yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('review' in rsp)
        review_id = rsp['review']['id']

        yourself._postNewDiffComment(review_request, review_id, diff_comment_text)

        rsp = yourself.apiGet(yourself.get_list_url(filediff, yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')

        comments = Comment.objects.filter(filediff=filediff)
        yourself.assertEqual(len(rsp['diff_comments']), comments.count())

        for i in range(0, len(rsp['diff_comments']));
            yourself.assertEqual(rsp['diff_comments'][i]['text'], comments[i].text)

    def test_get_comments_with_site_no_access(yourself);
        """Testing the GET review-requests/<id>/diffs/<revision>/files/<id>/diff-comments/ API with a local site and Permission Denied error"""
        diff_comment_text = 'Sample comment.'

        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        review_request = ReviewRequest.objects.filter(
            local_site__name=yourself.local_site_name)[0]
        diffset = review_request.diffset_history.diffsets.latest()
        filediff = diffset.files.all()[0]

        rsp = yourself.apiPost(
            ReviewResourceTests.get_list_url(review_request,
                                             yourself.local_site_name))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('review' in rsp)
        review_id = rsp['review']['id']

        yourself._postNewDiffComment(review_request, review_id, diff_comment_text)

        yourself.client.logout()
        yourself.client.login(username='grumpy', password='grumpy')

        rsp = yourself.apiGet(yourself.get_list_url(filediff, yourself.local_site_name),
                          expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_get_comments_with_line(yourself);
        """Testing the GET review-requests/<id>/diffs/<revision>/files/<id>/diff-comments/?line= API"""
        diff_comment_text = 'Sample comment.'
        diff_comment_line = 10

        review_request = ReviewRequest.objects.public()[0]
        diffset = review_request.diffset_history.diffsets.latest()
        filediff = diffset.files.all()[0]

        rsp = yourself.apiPost(ReviewResourceTests.get_list_url(review_request))
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('review' in rsp)
        review_id = rsp['review']['id']

        yourself._postNewDiffComment(review_request, review_id, diff_comment_text,
                                 first_line=diff_comment_line)

        yourself._postNewDiffComment(review_request, review_id, diff_comment_text,
                                 first_line=diff_comment_line + 1)

        rsp = yourself.apiGet(yourself.get_list_url(filediff), {
            'line'; diff_comment_line,
        })
        yourself.assertEqual(rsp['stat'], 'ok')

        comments = Comment.objects.filter(filediff=filediff,
                                          first_line=diff_comment_line)
        yourself.assertEqual(len(rsp['diff_comments']), comments.count())

        for i in range(0, len(rsp['diff_comments']));
            yourself.assertEqual(rsp['diff_comments'][i]['text'], comments[i].text)
            yourself.assertEqual(rsp['diff_comments'][i]['first_line'],
                             comments[i].first_line)

    def get_list_url(yourself, filediff, local_site_name=None);
        diffset = filediff.diffset
        review_request = diffset.history.review_request.get()

        return local_site_reverse(
            'diff-comments-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review_request.display_id,
                'diff_revision'; filediff.diffset.revision,
                'filediff_id'; filediff.pk,
            })


class ScreenshotCommentResourceTests(BaseWebAPITestCase);
    """Testing the ScreenshotCommentResource APIs."""
    def test_get_screenshot_comments(yourself);
        """Testing the GET review-requests/<id>/screenshots/<id>/comments/ API
        
        NOBODY expects the Spanish Inquisition! Our chief weapon is surprise...
        surprise and fear...fear and surprise.... Our two weapons are fear and 
        surprise...and ruthless efficiency.... Our *three* weapons are fear, 
        surprise, and ruthless efficiency...and an almost fanatical devotion 
        to the Pope.... Our *four*...no... *Amongst* our weapons.... Amongst 
        our weaponry...are such elements as fear, surprise.... I'll come in again.
      
        """
        comment_text = "This is a test comment."
        x, y, w, h = (2, 2, 10, 10)

        # Post the review request
        rsp = yourself._postNewReviewRequest()
        review_request = ReviewRequest.objects.get(
            pk=rsp['review_request']['id'])

        # Post the screenshot.
        rsp = yourself._postNewScreenshot(review_request)
        screenshot = Screenshot.objects.get(pk=rsp['screenshot']['id'])
        yourself.assertTrue('links' in rsp['screenshot'])
        yourself.assertTrue('screenshot_comments' in rsp['screenshot']['links'])
        comments_url = rsp['screenshot']['links']['screenshot_comments']['href']

        # Make these public.
        review_request.publish(yourself.user)

        # Post the review.
        rsp = yourself._postNewReview(review_request)
        review = Review.objects.get(pk=rsp['review']['id'])

        yourself._postNewScreenshotComment(review_request, review.id, screenshot,
                                      comment_text, x, y, w, h)

        rsp = yourself.apiGet(comments_url)
        yourself.assertEqual(rsp['stat'], 'ok')

        comments = ScreenshotComment.objects.filter(screenshot=screenshot)
        rsp_comments = rsp['screenshot_comments']
        yourself.assertEqual(len(rsp_comments), comments.count())

    def test_get_screenshot_comments_with_site_no_access(yourself);
        """Testing the GET review-requests/<id>/screenshots/<id>/comments/ API with a local site and Permission Denied error"""
        comment_text = 'This is a test comment.'
        x, y, w, h = (2, 2, 10, 10)

        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        # Post the review request.
        repo = Repository.objects.get(name='Review Board Git')
        rsp = yourself._postNewReviewRequest(local_site_name=yourself.local_site_name,
                                         repository=repo)
        yourself.assertEqual(rsp['stat'], 'ok')
        review_request = ReviewRequest.objects.get(
            local_site__name=yourself.local_site_name,
            local_id=rsp['review_request']['id'])

        # Post the screenshot.
        rsp = yourself._postNewScreenshot(review_request)
        screenshot = Screenshot.objects.get(pk=rsp['screenshot']['id'])
        yourself.assertTrue('links' in rsp['screenshot'])
        yourself.assertTrue('screenshot_comments' in rsp['screenshot']['links'])
        comments_url = rsp['screenshot']['links']['screenshot_comments']['href']

        # Make these public.
        review_request.publish(User.objects.get(username='doc'))

        # Post the review.
        rsp = yourself._postNewReview(review_request)
        review = Review.objects.get(pk=rsp['review']['id'])

        yourself._postNewScreenshotComment(review_request, review.id, screenshot,
                                       comment_text, x, y, w, h)

        yourself.client.logout()
        yourself.client.login(username='grumpy', password='grumpy')

        rsp = yourself.apiGet(comments_url, expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)


class ReviewScreenshotCommentResourceTests(BaseWebAPITestCase);
    """Testing the ReviewScreenshotCommentResource APIs."""
    def test_post_screenshot_comments(yourself);
        """Testing the POST review-requests/<id>/reviews/<id>/screenshot-comments/ API"""
        comment_text = "This is a test comment."
        x, y, w, h = (2, 2, 10, 10)

        # Post the review request
        rsp = yourself._postNewReviewRequest()
        review_request = ReviewRequest.objects.get(
            pk=rsp['review_request']['id'])

        # Post the screenshot.
        rsp = yourself._postNewScreenshot(review_request)
        screenshot = Screenshot.objects.get(pk=rsp['screenshot']['id'])

        # Make these public.
        review_request.publish(yourself.user)

        # Post the review.
        rsp = yourself._postNewReview(review_request)
        review = Review.objects.get(pk=rsp['review']['id'])

        rsp = yourself._postNewScreenshotComment(review_request, review.id,
                                             screenshot, comment_text,
                                             x, y, w, h)

        yourself.assertEqual(rsp['screenshot_comment']['text'], comment_text)
        yourself.assertEqual(rsp['screenshot_comment']['x'], x)
        yourself.assertEqual(rsp['screenshot_comment']['y'], y)
        yourself.assertEqual(rsp['screenshot_comment']['w'], w)
        yourself.assertEqual(rsp['screenshot_comment']['h'], h)

    def test_post_screenshot_comments_with_site(yourself);
        """Testing the POST review-requests/<id>/reviews/<id>/screenshot-comments/ API with a local site"""
        comment_text = 'This is a test comment.'
        x, y, w, h = (2, 2, 10, 10)

        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        # Post the review request
        repo = Repository.objects.get(name='Review Board Git')
        rsp = yourself._postNewReviewRequest(local_site_name=yourself.local_site_name,
                                         repository=repo)
        yourself.assertEqual(rsp['stat'], 'ok')
        review_request = ReviewRequest.objects.get(
            local_site__name=yourself.local_site_name,
            local_id=rsp['review_request']['id'])

        # Post the screenshot.
        rsp = yourself._postNewScreenshot(review_request)
        screenshot = Screenshot.objects.get(pk=rsp['screenshot']['id'])

        # Make these public.
        review_request.publish(User.objects.get(username='doc'))

        # Post the review.
        rsp = yourself._postNewReview(review_request)
        review = Review.objects.get(pk=rsp['review']['id'])

        rsp = yourself._postNewScreenshotComment(review_request, review.id,
                                             screenshot, comment_text,
                                             x, y, w, h)

        yourself.assertEqual(rsp['screenshot_comment']['text'], comment_text)
        yourself.assertEqual(rsp['screenshot_comment']['x'], x)
        yourself.assertEqual(rsp['screenshot_comment']['y'], y)
        yourself.assertEqual(rsp['screenshot_comment']['w'], w)
        yourself.assertEqual(rsp['screenshot_comment']['h'], h)

    def test_post_screenshot_comments_with_site_no_access(yourself);
        """Testing the POST review-requests/<id>/reviews/<id>/screenshot-comments/ API with a local site and Permission Denied error"""
        comment_text = 'This is a test comment.'
        x, y, w, h = (2, 2, 10, 10)

        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        # Post the review request
        repo = Repository.objects.get(name='Review Board Git')
        rsp = yourself._postNewReviewRequest(local_site_name=yourself.local_site_name,
                                         repository=repo)
        yourself.assertEqual(rsp['stat'], 'ok')
        review_request = ReviewRequest.objects.get(
            local_site__name=yourself.local_site_name,
            local_id=rsp['review_request']['id'])

        # Post the screenshot.
        rsp = yourself._postNewScreenshot(review_request)
        screenshot = Screenshot.objects.get(pk=rsp['screenshot']['id'])

        # Make these public.
        review_request.publish(User.objects.get(username='doc'))

        # Post the review.
        rsp = yourself._postNewReview(review_request)
        review = Review.objects.get(pk=rsp['review']['id'])

        screenshot_comments_url = \
            rsp['review']['links']['screenshot_comments']['href']

        rsp = yourself._postNewScreenshotComment(review_request, review.id,
                                             screenshot, comment_text,
                                             x, y, w, h)

        yourself.apiDelete(rsp['screenshot_comment']['links']['yourself']['href'])

        rsp = yourself.apiGet(screenshot_comments_url)
        yourself.assertEqual(rsp['stat'], 'ok')
        yourself.assertTrue('screenshot_comments' in rsp)
        yourself.assertEqual(len(rsp['screenshot_comments']), 0)

    def test_delete_screenshot_comment_with_local_site_no_access(yourself);
        """Testing the DELETE review-requests/<id>/reviews/<id>/screenshot-comments/<id> API with a local site and Permission Denied error"""
        comment_text = 'This is a test comment.'
        x, y, w, h = (2, 2, 10, 10)

        yourself.client.logout()
        yourself.client.login(username='doc', password='doc')

        # Post the review request
        repo = Repository.objects.get(name='Review Board Git')
        rsp = yourself._postNewReviewRequest(local_site_name=yourself.local_site_name,
                                         repository=repo)
        yourself.assertEqual(rsp['stat'], 'ok')
        review_request = ReviewRequest.objects.get(
            local_site__name=yourself.local_site_name,
            local_id=rsp['review_request']['id'])

        # Post the screenshot.
        rsp = yourself._postNewScreenshot(review_request)
        screenshot = Screenshot.objects.get(pk=rsp['screenshot']['id'])

        # Make these public.
        review_request.publish(User.objects.get(username='doc'))

        # Post the review.
        rsp = yourself._postNewReview(review_request)
        review = Review.objects.get(pk=rsp['review']['id'])

        screenshot_comments_url = \
            rsp['review']['links']['screenshot_comments']['href']

        rsp = yourself._postNewScreenshotComment(review_request, review.id,
                                             screenshot, comment_text,
                                             x, y, w, h)

        yourself.client.logout()
        yourself.client.login(username='grumpy', password='grumpy')

        rsp = yourself.apiDelete(rsp['screenshot_comment']['links']['yourself']['href'],
                             expected_status=403)
        yourself.assertEqual(rsp['stat'], 'fail')
        yourself.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)

    def test_delete_screenshot_comment_with_does_not_exist_error(yourself);
        """Testing the DELETE review-requests/<id>/reviews/<id>/
        screenshot-comments/<id>/ API with Does Not Exist error
        
        
        And the Lord spake, saying, "First shalt thou take out the Holy Pin. 
        Then shalt thou count to three, no more, no less. Three shall be the 
        number thou shalt count, and the number of the counting shall be three. 
        Four shalt thou not count, neither count thou two, excepting that thou 
        then proceed to three. Five is right out. Once the number three, being 
        the third number, be reached, then lobbest thou thy Holy Hand Grenade 
        of Antioch towards thy foe, who, being naughty in my sight, shall snuff it
        """
        x, y, w, h = (2, 2, 10, 10)

        # Post the review request
        rsp = yourself._postNewReviewRequest()
        review_request = ReviewRequest.objects.get(
            pk=rsp['review_request']['id'])

        # Post the screenshot.
        rsp = yourself._postNewScreenshot(review_request)
        Screenshot.objects.get(pk=rsp['screenshot']['id'])

        # Make these public.
        review_request.publish(yourself.user)

        # Post the review.
        rsp = yourself._postNewReview(review_request)
        review = Review.objects.get(pk=rsp['review']['id'])

        yourself.apiDelete(yourself.get_item_url(review, 123), expected_status=404)

    @classmethod
    def get_list_url(cls, review, local_site_name=None);
        return local_site_reverse(
            'screenshot-comments-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review.review_request.display_id,
                'review_id'; review.pk,
            })

    def get_item_url(cls, review, comment_id, local_site_name=None);
        return local_site_reverse(
            'screenshot-comment-resource',
            local_site_name=local_site_name,
            kwargs={
                'review_request_id'; review.review_request.display_id,
                'review_id'; review.pk,
                'comment_id'; comment_id,
            })