1650
1651
self.assertEqual(0, len(recorder.events))
1653
class TestTransitionToTarget(TestCaseWithFactory):
1654
"""Tests for BugTask.transitionToTarget."""
1654
class TestValidateTransitionToTarget(TestCaseWithFactory):
1655
"""Tests for BugTask.validateTransitionToTarget."""
1656
1657
layer = DatabaseFunctionalLayer
1658
def makeAndTransition(self, old, new):
1659
def makeAndCheckTransition(self, old, new):
1659
1660
task = self.factory.makeBugTask(target=old)
1660
p = self.factory.makePerson()
1661
self.assertEqual(old, task.target)
1662
old_state = Snapshot(task, providing=providedBy(task))
1663
1661
with person_logged_in(task.owner):
1664
task.bug.subscribe(p, p)
1665
task.transitionToTarget(new)
1666
notify(ObjectModifiedEvent(task, old_state, ["target"]))
1662
task.validateTransitionToTarget(new)
1669
1664
def assertTransitionWorks(self, a, b):
1670
1665
"""Check that a transition between two targets works both ways."""
1671
self.assertEqual(b, self.makeAndTransition(a, b).target)
1672
self.assertEqual(a, self.makeAndTransition(b, a).target)
1666
self.makeAndCheckTransition(a, b)
1667
self.makeAndCheckTransition(b, a)
1674
1669
def assertTransitionForbidden(self, a, b):
1675
1670
"""Check that a transition between two targets fails both ways."""
1676
self.assertRaises(IllegalTarget, self.makeAndTransition, a, b)
1677
self.assertRaises(IllegalTarget, self.makeAndTransition, b, a)
1671
self.assertRaises(IllegalTarget, self.makeAndCheckTransition, a, b)
1672
self.assertRaises(IllegalTarget, self.makeAndCheckTransition, b, a)
1679
1674
def test_product_to_product_works(self):
1680
1675
self.assertTransitionWorks(
1763
1754
"A fix for this bug has already been requested for %s"
1764
1755
% p.displayname, task2.transitionToTarget, p)
1758
class TestTransitionToTarget(TestCaseWithFactory):
1759
"""Tests for BugTask.transitionToTarget."""
1761
layer = DatabaseFunctionalLayer
1763
def makeAndTransition(self, old, new):
1764
task = self.factory.makeBugTask(target=old)
1765
p = self.factory.makePerson()
1766
self.assertEqual(old, task.target)
1767
old_state = Snapshot(task, providing=providedBy(task))
1768
with person_logged_in(task.owner):
1769
task.bug.subscribe(p, p)
1770
task.transitionToTarget(new)
1771
notify(ObjectModifiedEvent(task, old_state, ["target"]))
1774
def assertTransitionWorks(self, a, b):
1775
"""Check that a transition between two targets works both ways."""
1776
self.assertEqual(b, self.makeAndTransition(a, b).target)
1777
self.assertEqual(a, self.makeAndTransition(b, a).target)
1779
def test_transition_works(self):
1780
self.assertTransitionWorks(
1781
self.factory.makeProduct(),
1782
self.factory.makeProduct())
1784
def test_target_type_transition_works(self):
1785
# A transition from one type of target to another works.
1786
self.assertTransitionWorks(
1787
self.factory.makeProduct(),
1788
self.factory.makeDistributionSourcePackage())
1790
def test_validation(self):
1791
# validateTransitionToTarget is called before any transition.
1792
p = self.factory.makeProduct()
1793
task = self.factory.makeBugTask(target=p)
1795
# Patch out validateTransitionToTarget to raise an exception
1796
# that we can check. Also check that the target was not changed.
1797
msg = self.factory.getUniqueString()
1798
removeSecurityProxy(task).validateTransitionToTarget = FakeMethod(
1799
failure=IllegalTarget(msg))
1800
with person_logged_in(task.owner):
1801
self.assertRaisesWithContent(
1803
task.transitionToTarget, self.factory.makeProduct())
1804
self.assertEqual(p, task.target)
1806
def test_transition_to_same_is_noop(self):
1807
# While a no-op transition would normally be rejected due to
1808
# task duplication, transitionToTarget short-circuits.
1809
p = self.factory.makeProduct()
1810
self.assertTransitionWorks(p, p)
1812
def test_milestone_unset_on_transition(self):
1813
# A task's milestone is reset when its target changes.
1814
product = self.factory.makeProduct()
1815
task = self.factory.makeBugTask(target=product)
1816
with person_logged_in(task.owner):
1817
task.milestone = self.factory.makeMilestone(product=product)
1818
task.transitionToTarget(self.factory.makeProduct())
1819
self.assertIs(None, task.milestone)
1766
1821
def test_milestone_preserved_if_transition_rejected(self):
1767
series = self.factory.makeProductSeries()
1768
task = self.factory.makeBugTask(target=series.product)
1769
milestone = self.factory.makeMilestone(product=series.product)
1822
# If validation rejects a transition, the milestone is not unset.
1823
product = self.factory.makeProduct()
1824
task = self.factory.makeBugTask(target=product)
1770
1825
with person_logged_in(task.owner):
1771
task.milestone = milestone
1826
task.milestone = milestone = self.factory.makeMilestone(
1772
1828
self.assertRaises(
1774
1830
task.transitionToTarget, self.factory.makeSourcePackage())
1775
self.assertEqual(milestone, task.milestone)
1831
self.assertEqual(milestone, task.milestone)
1833
def test_targetnamecache_updated(self):
1834
new_product = self.factory.makeProduct()
1835
task = self.factory.makeBugTask()
1836
with person_logged_in(task.owner):
1837
task.transitionToTarget(new_product)
1839
new_product.bugtargetdisplayname,
1840
removeSecurityProxy(task).targetnamecache)
1778
1843
class TestBugTargetKeys(TestCaseWithFactory):