~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/bugs/browser/tests/test_bugtask.py

  • Committer: William Grant
  • Date: 2011-12-22 23:28:30 UTC
  • mfrom: (14585 devel)
  • mto: This revision was merged to the branch mainline in revision 14586.
  • Revision ID: william.grant@canonical.com-20111222232830-qjyioyjc3lqnxrka
Merge devel.

Show diffs side-by-side

added added

removed removed

Lines of Context:
94
94
from lp.testing.views import create_initialized_view
95
95
 
96
96
 
97
 
DELETE_BUGTASK_ENABLED = {u"disclosure.delete_bugtask.enabled": u"on"}
98
 
 
99
 
 
100
97
class TestBugTaskView(TestCaseWithFactory):
101
98
 
102
99
    layer = LaunchpadFunctionalLayer
186
183
        self.invalidate_caches(bug.default_bugtask)
187
184
        self.getUserBrowser(url, owner)
188
185
        # At least 20 of these should be removed.
189
 
        self.assertThat(recorder, HasQueryCount(LessThan(101)))
 
186
        self.assertThat(recorder, HasQueryCount(LessThan(106)))
190
187
        count_with_no_branches = recorder.count
191
188
        for sp in sourcepackages:
192
189
            self.makeLinkedBranchMergeProposal(sp, bug, owner)
782
779
        row_view = view._getTableRowView(bug.default_bugtask, False, False)
783
780
        self.assertFalse(row_view.user_can_delete_bugtask)
784
781
        del get_property_cache(row_view).user_can_delete_bugtask
785
 
        with FeatureFixture(DELETE_BUGTASK_ENABLED):
786
 
            self.assertFalse(row_view.user_can_delete_bugtask)
 
782
        self.assertFalse(row_view.user_can_delete_bugtask)
787
783
 
788
784
    def test_can_delete_bugtask_if_authorised(self):
789
785
        # The bugtask can be deleted if the user if authorised.
794
790
            bug, name='+bugtasks-and-nominations-table',
795
791
            principal=bugtask.owner)
796
792
        row_view = view._getTableRowView(bugtask, False, False)
797
 
        self.assertFalse(row_view.user_can_delete_bugtask)
798
 
        del get_property_cache(row_view).user_can_delete_bugtask
799
 
        clear_cache()
800
 
        with FeatureFixture(DELETE_BUGTASK_ENABLED):
801
 
            self.assertTrue(row_view.user_can_delete_bugtask)
 
793
        self.assertTrue(row_view.user_can_delete_bugtask)
802
794
 
803
795
    def test_bugtask_delete_icon(self):
804
796
        # The bugtask delete icon is rendered correctly for those tasks the
806
798
        bug = self.factory.makeBug()
807
799
        bugtask_owner = self.factory.makePerson()
808
800
        bugtask = self.factory.makeBugTask(bug=bug, owner=bugtask_owner)
809
 
        with FeatureFixture(DELETE_BUGTASK_ENABLED):
810
 
            login_person(bugtask.owner)
811
 
            getUtility(ILaunchBag).add(bug.default_bugtask)
812
 
            view = create_initialized_view(
813
 
                bug, name='+bugtasks-and-nominations-table',
814
 
                principal=bugtask.owner)
815
 
            # We render the bug task table rows - there are 2 bug tasks.
816
 
            subviews = view.getBugTaskAndNominationViews()
817
 
            self.assertEqual(2, len(subviews))
818
 
            default_bugtask_contents = subviews[0]()
819
 
            bugtask_contents = subviews[1]()
820
 
            # bugtask can be deleted because the user owns it.
821
 
            delete_icon = find_tag_by_id(
822
 
                bugtask_contents, 'bugtask-delete-task%d' % bugtask.id)
823
 
            delete_url = canonical_url(
824
 
                bugtask, rootsite='bugs', view_name='+delete')
825
 
            self.assertEqual(delete_url, delete_icon['href'])
826
 
            # default_bugtask cannot be deleted.
827
 
            delete_icon = find_tag_by_id(
828
 
                default_bugtask_contents,
829
 
                'bugtask-delete-task%d' % bug.default_bugtask.id)
830
 
            self.assertIsNone(delete_icon)
 
801
        login_person(bugtask.owner)
 
802
        getUtility(ILaunchBag).add(bug.default_bugtask)
 
803
        view = create_initialized_view(
 
804
            bug, name='+bugtasks-and-nominations-table',
 
805
            principal=bugtask.owner)
 
806
        # We render the bug task table rows - there are 2 bug tasks.
 
807
        subviews = view.getBugTaskAndNominationViews()
 
808
        self.assertEqual(2, len(subviews))
 
809
        default_bugtask_contents = subviews[0]()
 
810
        bugtask_contents = subviews[1]()
 
811
        # bugtask can be deleted because the user owns it.
 
812
        delete_icon = find_tag_by_id(
 
813
            bugtask_contents, 'bugtask-delete-task%d' % bugtask.id)
 
814
        delete_url = canonical_url(
 
815
            bugtask, rootsite='bugs', view_name='+delete')
 
816
        self.assertEqual(delete_url, delete_icon['href'])
 
817
        # default_bugtask cannot be deleted.
 
818
        delete_icon = find_tag_by_id(
 
819
            default_bugtask_contents,
 
820
            'bugtask-delete-task%d' % bug.default_bugtask.id)
 
821
        self.assertIsNone(delete_icon)
831
822
 
832
823
    def test_client_cache_contents(self):
833
824
        """ Test that the client cache contains the expected data.
838
829
        bug = self.factory.makeBug()
839
830
        bugtask_owner = self.factory.makePerson()
840
831
        bugtask = self.factory.makeBugTask(bug=bug, owner=bugtask_owner)
841
 
        with FeatureFixture(DELETE_BUGTASK_ENABLED):
842
 
            login_person(bugtask.owner)
843
 
            getUtility(ILaunchBag).add(bug.default_bugtask)
844
 
            view = create_initialized_view(
845
 
                bug, name='+bugtasks-and-nominations-table',
846
 
                principal=bugtask.owner)
847
 
            view.render()
848
 
            cache = IJSONRequestCache(view.request)
849
 
            all_bugtask_data = cache.objects['bugtask_data']
850
 
 
851
 
            def check_bugtask_data(bugtask, can_delete):
852
 
                self.assertIn(bugtask.id, all_bugtask_data)
853
 
                bugtask_data = all_bugtask_data[bugtask.id]
854
 
                self.assertEqual(
855
 
                    'task%d' % bugtask.id, bugtask_data['form_row_id'])
856
 
                self.assertEqual(
857
 
                    'tasksummary%d' % bugtask.id, bugtask_data['row_id'])
858
 
                self.assertEqual(can_delete, bugtask_data['user_can_delete'])
859
 
 
860
 
            check_bugtask_data(bug.default_bugtask, False)
861
 
            check_bugtask_data(bugtask, True)
 
832
        login_person(bugtask.owner)
 
833
        getUtility(ILaunchBag).add(bug.default_bugtask)
 
834
        view = create_initialized_view(
 
835
            bug, name='+bugtasks-and-nominations-table',
 
836
            principal=bugtask.owner)
 
837
        view.render()
 
838
        cache = IJSONRequestCache(view.request)
 
839
        all_bugtask_data = cache.objects['bugtask_data']
 
840
 
 
841
        def check_bugtask_data(bugtask, can_delete):
 
842
            self.assertIn(bugtask.id, all_bugtask_data)
 
843
            bugtask_data = all_bugtask_data[bugtask.id]
 
844
            self.assertEqual(
 
845
                'task%d' % bugtask.id, bugtask_data['form_row_id'])
 
846
            self.assertEqual(
 
847
                'tasksummary%d' % bugtask.id, bugtask_data['row_id'])
 
848
            self.assertEqual(can_delete, bugtask_data['user_can_delete'])
 
849
 
 
850
        check_bugtask_data(bug.default_bugtask, False)
 
851
        check_bugtask_data(bugtask, True)
862
852
 
863
853
 
864
854
class TestBugTaskDeleteView(TestCaseWithFactory):
876
866
        server_url = canonical_url(
877
867
            getUtility(ILaunchpadRoot), rootsite='bugs')
878
868
        extra = {'HTTP_REFERER': bug_url}
879
 
        with FeatureFixture(DELETE_BUGTASK_ENABLED):
880
 
            login_person(bugtask.owner)
881
 
            view = create_initialized_view(
882
 
                bugtask, name='+delete', principal=bugtask.owner,
883
 
                server_url=server_url, **extra)
884
 
            contents = view.render()
885
 
            confirmation_message = find_tag_by_id(
886
 
                contents, 'confirmation-message')
887
 
            self.assertIsNotNone(confirmation_message)
888
 
            self.assertEqual(bug_url, view.cancel_url)
 
869
        login_person(bugtask.owner)
 
870
        view = create_initialized_view(
 
871
            bugtask, name='+delete', principal=bugtask.owner,
 
872
            server_url=server_url, **extra)
 
873
        contents = view.render()
 
874
        confirmation_message = find_tag_by_id(
 
875
            contents, 'confirmation-message')
 
876
        self.assertIsNotNone(confirmation_message)
 
877
        self.assertEqual(bug_url, view.cancel_url)
889
878
 
890
879
    def test_delete_action(self):
891
880
        # Test that the delete action works as expected.
893
882
        bugtask = self.factory.makeBugTask(bug=bug)
894
883
        bugtask_url = canonical_url(bugtask, rootsite='bugs')
895
884
        target_name = bugtask.bugtargetdisplayname
896
 
        with FeatureFixture(DELETE_BUGTASK_ENABLED):
897
 
            login_person(bugtask.owner)
898
 
            form = {
899
 
                'field.actions.delete_bugtask': 'Delete',
900
 
                }
901
 
            extra = {
902
 
                'HTTP_REFERER': bugtask_url,
903
 
                }
904
 
            server_url = canonical_url(
905
 
                getUtility(ILaunchpadRoot), rootsite='bugs')
906
 
            view = create_initialized_view(
907
 
                bugtask, name='+delete', form=form, server_url=server_url,
908
 
                principal=bugtask.owner, **extra)
909
 
            self.assertEqual([bug.default_bugtask], bug.bugtasks)
910
 
            notifications = view.request.response.notifications
911
 
            self.assertEqual(1, len(notifications))
912
 
            expected = 'This bug no longer affects %s.' % target_name
913
 
            self.assertEqual(expected, notifications[0].message)
 
885
        login_person(bugtask.owner)
 
886
        form = {
 
887
            'field.actions.delete_bugtask': 'Delete',
 
888
            }
 
889
        extra = {
 
890
            'HTTP_REFERER': bugtask_url,
 
891
            }
 
892
        server_url = canonical_url(
 
893
            getUtility(ILaunchpadRoot), rootsite='bugs')
 
894
        view = create_initialized_view(
 
895
            bugtask, name='+delete', form=form, server_url=server_url,
 
896
            principal=bugtask.owner, **extra)
 
897
        self.assertEqual([bug.default_bugtask], bug.bugtasks)
 
898
        notifications = view.request.response.notifications
 
899
        self.assertEqual(1, len(notifications))
 
900
        expected = 'This bug no longer affects %s.' % target_name
 
901
        self.assertEqual(expected, notifications[0].message)
914
902
 
915
903
    def test_delete_only_bugtask(self):
916
904
        # Test that the deleting the only bugtask results in an error message.
917
905
        bug = self.factory.makeBug()
918
 
        with FeatureFixture(DELETE_BUGTASK_ENABLED):
919
 
            login_person(bug.owner)
920
 
            form = {
921
 
                'field.actions.delete_bugtask': 'Delete',
922
 
                }
923
 
            view = create_initialized_view(
924
 
                bug.default_bugtask, name='+delete', form=form,
925
 
                principal=bug.owner)
926
 
            self.assertEqual([bug.default_bugtask], bug.bugtasks)
927
 
            notifications = view.request.response.notifications
928
 
            self.assertEqual(1, len(notifications))
929
 
            expected = ('Cannot delete only bugtask affecting: %s.'
930
 
                % bug.default_bugtask.target.bugtargetdisplayname)
931
 
            self.assertEqual(expected, notifications[0].message)
 
906
        login_person(bug.owner)
 
907
        form = {
 
908
            'field.actions.delete_bugtask': 'Delete',
 
909
            }
 
910
        view = create_initialized_view(
 
911
            bug.default_bugtask, name='+delete', form=form,
 
912
            principal=bug.owner)
 
913
        self.assertEqual([bug.default_bugtask], bug.bugtasks)
 
914
        notifications = view.request.response.notifications
 
915
        self.assertEqual(1, len(notifications))
 
916
        expected = ('Cannot delete only bugtask affecting: %s.'
 
917
            % bug.default_bugtask.target.bugtargetdisplayname)
 
918
        self.assertEqual(expected, notifications[0].message)
932
919
 
933
920
    def _create_bugtask_to_delete(self):
934
921
        bug = self.factory.makeBug()
942
929
        # containing the URL of the bug's default task to redirect to.
943
930
        bug, bugtask, target_name, bugtask_url = (
944
931
            self._create_bugtask_to_delete())
945
 
        with FeatureFixture(DELETE_BUGTASK_ENABLED):
946
 
            login_person(bugtask.owner)
947
 
            # Set up the request so that we correctly simulate an XHR call
948
 
            # from the URL of the bugtask we are deleting.
949
 
            server_url = canonical_url(
950
 
                getUtility(ILaunchpadRoot), rootsite='bugs')
951
 
            extra = {
952
 
                'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
953
 
                'HTTP_REFERER': bugtask_url,
954
 
                }
955
 
            form = {
956
 
                'field.actions.delete_bugtask': 'Delete'
957
 
                }
958
 
            view = create_initialized_view(
959
 
                bugtask, name='+delete', server_url=server_url, form=form,
960
 
                principal=bugtask.owner, **extra)
961
 
            result_data = simplejson.loads(view.render())
962
 
            self.assertEqual([bug.default_bugtask], bug.bugtasks)
963
 
            notifications = simplejson.loads(
964
 
                view.request.response.getHeader('X-Lazr-Notifications'))
965
 
            self.assertEqual(1, len(notifications))
966
 
            expected = 'This bug no longer affects %s.' % target_name
967
 
            self.assertEqual(expected, notifications[0][1])
968
 
            self.assertEqual(
969
 
                'application/json',
970
 
                view.request.response.getHeader('content-type'))
971
 
            expected_url = canonical_url(bug.default_bugtask, rootsite='bugs')
972
 
            self.assertEqual(dict(bugtask_url=expected_url), result_data)
 
932
        login_person(bugtask.owner)
 
933
        # Set up the request so that we correctly simulate an XHR call
 
934
        # from the URL of the bugtask we are deleting.
 
935
        server_url = canonical_url(
 
936
            getUtility(ILaunchpadRoot), rootsite='bugs')
 
937
        extra = {
 
938
            'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
 
939
            'HTTP_REFERER': bugtask_url,
 
940
            }
 
941
        form = {
 
942
            'field.actions.delete_bugtask': 'Delete'
 
943
            }
 
944
        view = create_initialized_view(
 
945
            bugtask, name='+delete', server_url=server_url, form=form,
 
946
            principal=bugtask.owner, **extra)
 
947
        result_data = simplejson.loads(view.render())
 
948
        self.assertEqual([bug.default_bugtask], bug.bugtasks)
 
949
        notifications = simplejson.loads(
 
950
            view.request.response.getHeader('X-Lazr-Notifications'))
 
951
        self.assertEqual(1, len(notifications))
 
952
        expected = 'This bug no longer affects %s.' % target_name
 
953
        self.assertEqual(expected, notifications[0][1])
 
954
        self.assertEqual(
 
955
            'application/json',
 
956
            view.request.response.getHeader('content-type'))
 
957
        expected_url = canonical_url(bug.default_bugtask, rootsite='bugs')
 
958
        self.assertEqual(dict(bugtask_url=expected_url), result_data)
973
959
 
974
960
    def test_ajax_delete_only_bugtask(self):
975
961
        # Test that deleting the only bugtask returns an empty JSON response
976
962
        # with an error notification.
977
963
        bug = self.factory.makeBug()
978
 
        with FeatureFixture(DELETE_BUGTASK_ENABLED):
979
 
            login_person(bug.owner)
980
 
            # Set up the request so that we correctly simulate an XHR call
981
 
            # from the URL of the bugtask we are deleting.
982
 
            server_url = canonical_url(
983
 
                getUtility(ILaunchpadRoot), rootsite='bugs')
984
 
            extra = {
985
 
                'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
986
 
                }
987
 
            form = {
988
 
                'field.actions.delete_bugtask': 'Delete'
989
 
                }
990
 
            view = create_initialized_view(
991
 
                bug.default_bugtask, name='+delete', server_url=server_url,
992
 
                form=form, principal=bug.owner, **extra)
993
 
            result_data = simplejson.loads(view.render())
994
 
            self.assertEqual([bug.default_bugtask], bug.bugtasks)
995
 
            notifications = simplejson.loads(
996
 
                view.request.response.getHeader('X-Lazr-Notifications'))
997
 
            self.assertEqual(1, len(notifications))
998
 
            expected = ('Cannot delete only bugtask affecting: %s.'
999
 
                % bug.default_bugtask.target.bugtargetdisplayname)
1000
 
            self.assertEqual(expected, notifications[0][1])
1001
 
            self.assertEqual(
1002
 
                'application/json',
1003
 
                view.request.response.getHeader('content-type'))
1004
 
            self.assertEqual(None, result_data)
 
964
        login_person(bug.owner)
 
965
        # Set up the request so that we correctly simulate an XHR call
 
966
        # from the URL of the bugtask we are deleting.
 
967
        server_url = canonical_url(
 
968
            getUtility(ILaunchpadRoot), rootsite='bugs')
 
969
        extra = {
 
970
            'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
 
971
            }
 
972
        form = {
 
973
            'field.actions.delete_bugtask': 'Delete'
 
974
            }
 
975
        view = create_initialized_view(
 
976
            bug.default_bugtask, name='+delete', server_url=server_url,
 
977
            form=form, principal=bug.owner, **extra)
 
978
        result_data = simplejson.loads(view.render())
 
979
        self.assertEqual([bug.default_bugtask], bug.bugtasks)
 
980
        notifications = simplejson.loads(
 
981
            view.request.response.getHeader('X-Lazr-Notifications'))
 
982
        self.assertEqual(1, len(notifications))
 
983
        expected = ('Cannot delete only bugtask affecting: %s.'
 
984
            % bug.default_bugtask.target.bugtargetdisplayname)
 
985
        self.assertEqual(expected, notifications[0][1])
 
986
        self.assertEqual(
 
987
            'application/json',
 
988
            view.request.response.getHeader('content-type'))
 
989
        self.assertEqual(None, result_data)
1005
990
 
1006
991
    def test_ajax_delete_non_current_bugtask(self):
1007
992
        # Test that deleting the non-current bugtask returns the new bugtasks
1010
995
            self._create_bugtask_to_delete())
1011
996
        default_bugtask_url = canonical_url(
1012
997
            bug.default_bugtask, rootsite='bugs')
1013
 
        with FeatureFixture(DELETE_BUGTASK_ENABLED):
1014
 
            login_person(bugtask.owner)
1015
 
            # Set up the request so that we correctly simulate an XHR call
1016
 
            # from the URL of the default bugtask, not the one we are
1017
 
            # deleting.
1018
 
            server_url = canonical_url(
1019
 
                getUtility(ILaunchpadRoot), rootsite='bugs')
1020
 
            extra = {
1021
 
                'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
1022
 
                'HTTP_REFERER': default_bugtask_url,
1023
 
                }
1024
 
            form = {
1025
 
                'field.actions.delete_bugtask': 'Delete'
1026
 
                }
1027
 
            view = create_initialized_view(
1028
 
                bugtask, name='+delete', server_url=server_url, form=form,
1029
 
                principal=bugtask.owner, **extra)
1030
 
            result_html = view.render()
1031
 
            self.assertEqual([bug.default_bugtask], bug.bugtasks)
1032
 
            notifications = view.request.response.notifications
1033
 
            self.assertEqual(1, len(notifications))
1034
 
            expected = 'This bug no longer affects %s.' % target_name
1035
 
            self.assertEqual(expected, notifications[0].message)
1036
 
            self.assertEqual(
1037
 
                view.request.response.getHeader('content-type'), 'text/html')
1038
 
            table = find_tag_by_id(result_html, 'affected-software')
1039
 
            self.assertIsNotNone(table)
1040
 
            [row] = table.tbody.findAll('tr', {'class': 'highlight'})
1041
 
            target_link = row.find('a', {'class': 'sprite product'})
1042
 
            self.assertIn(
1043
 
                bug.default_bugtask.bugtargetdisplayname, target_link)
 
998
        login_person(bugtask.owner)
 
999
        # Set up the request so that we correctly simulate an XHR call
 
1000
        # from the URL of the default bugtask, not the one we are
 
1001
        # deleting.
 
1002
        server_url = canonical_url(
 
1003
            getUtility(ILaunchpadRoot), rootsite='bugs')
 
1004
        extra = {
 
1005
            'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
 
1006
            'HTTP_REFERER': default_bugtask_url,
 
1007
            }
 
1008
        form = {
 
1009
            'field.actions.delete_bugtask': 'Delete'
 
1010
            }
 
1011
        view = create_initialized_view(
 
1012
            bugtask, name='+delete', server_url=server_url, form=form,
 
1013
            principal=bugtask.owner, **extra)
 
1014
        result_html = view.render()
 
1015
        self.assertEqual([bug.default_bugtask], bug.bugtasks)
 
1016
        notifications = view.request.response.notifications
 
1017
        self.assertEqual(1, len(notifications))
 
1018
        expected = 'This bug no longer affects %s.' % target_name
 
1019
        self.assertEqual(expected, notifications[0].message)
 
1020
        self.assertEqual(
 
1021
            view.request.response.getHeader('content-type'), 'text/html')
 
1022
        table = find_tag_by_id(result_html, 'affected-software')
 
1023
        self.assertIsNotNone(table)
 
1024
        [row] = table.tbody.findAll('tr', {'class': 'highlight'})
 
1025
        target_link = row.find('a', {'class': 'sprite product'})
 
1026
        self.assertIn(
 
1027
            bug.default_bugtask.bugtargetdisplayname, target_link)
1044
1028
 
1045
1029
 
1046
1030
class TestBugTasksAndNominationsViewAlsoAffects(TestCaseWithFactory):