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)
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)
848
cache = IJSONRequestCache(view.request)
849
all_bugtask_data = cache.objects['bugtask_data']
851
def check_bugtask_data(bugtask, can_delete):
852
self.assertIn(bugtask.id, all_bugtask_data)
853
bugtask_data = all_bugtask_data[bugtask.id]
855
'task%d' % bugtask.id, bugtask_data['form_row_id'])
857
'tasksummary%d' % bugtask.id, bugtask_data['row_id'])
858
self.assertEqual(can_delete, bugtask_data['user_can_delete'])
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)
838
cache = IJSONRequestCache(view.request)
839
all_bugtask_data = cache.objects['bugtask_data']
841
def check_bugtask_data(bugtask, can_delete):
842
self.assertIn(bugtask.id, all_bugtask_data)
843
bugtask_data = all_bugtask_data[bugtask.id]
845
'task%d' % bugtask.id, bugtask_data['form_row_id'])
847
'tasksummary%d' % bugtask.id, bugtask_data['row_id'])
848
self.assertEqual(can_delete, bugtask_data['user_can_delete'])
850
check_bugtask_data(bug.default_bugtask, False)
851
check_bugtask_data(bugtask, True)
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)
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)
899
'field.actions.delete_bugtask': 'Delete',
902
'HTTP_REFERER': bugtask_url,
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)
887
'field.actions.delete_bugtask': 'Delete',
890
'HTTP_REFERER': bugtask_url,
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)
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)
921
'field.actions.delete_bugtask': 'Delete',
923
view = create_initialized_view(
924
bug.default_bugtask, name='+delete', form=form,
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)
908
'field.actions.delete_bugtask': 'Delete',
910
view = create_initialized_view(
911
bug.default_bugtask, name='+delete', form=form,
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)
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')
952
'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
953
'HTTP_REFERER': bugtask_url,
956
'field.actions.delete_bugtask': 'Delete'
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])
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')
938
'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
939
'HTTP_REFERER': bugtask_url,
942
'field.actions.delete_bugtask': 'Delete'
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])
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)
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')
985
'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
988
'field.actions.delete_bugtask': 'Delete'
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])
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')
970
'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
973
'field.actions.delete_bugtask': 'Delete'
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])
988
view.request.response.getHeader('content-type'))
989
self.assertEqual(None, result_data)
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
1018
server_url = canonical_url(
1019
getUtility(ILaunchpadRoot), rootsite='bugs')
1021
'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
1022
'HTTP_REFERER': default_bugtask_url,
1025
'field.actions.delete_bugtask': 'Delete'
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)
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'})
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
1002
server_url = canonical_url(
1003
getUtility(ILaunchpadRoot), rootsite='bugs')
1005
'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
1006
'HTTP_REFERER': default_bugtask_url,
1009
'field.actions.delete_bugtask': 'Delete'
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)
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'})
1027
bug.default_bugtask.bugtargetdisplayname, target_link)
1046
1030
class TestBugTasksAndNominationsViewAlsoAffects(TestCaseWithFactory):