~launchpad-pqm/launchpad/devel

« back to all changes in this revision

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

[r=wgrant][no-qa] Better tests for BugTask.transitionToTarget.

Show diffs side-by-side

added added

removed removed

Lines of Context:
75
75
    TestCaseWithFactory,
76
76
    )
77
77
from lp.testing.factory import LaunchpadObjectFactory
 
78
from lp.testing.fakemethod import FakeMethod
78
79
from lp.testing.matchers import HasQueryCount
79
80
 
80
81
 
1650
1651
                self.assertEqual(0, len(recorder.events))
1651
1652
 
1652
1653
 
1653
 
class TestTransitionToTarget(TestCaseWithFactory):
1654
 
    """Tests for BugTask.transitionToTarget."""
 
1654
class TestValidateTransitionToTarget(TestCaseWithFactory):
 
1655
    """Tests for BugTask.validateTransitionToTarget."""
1655
1656
 
1656
1657
    layer = DatabaseFunctionalLayer
1657
1658
 
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"]))
1667
 
        return task
 
1662
            task.validateTransitionToTarget(new)
1668
1663
 
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)
1673
1668
 
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)
1678
1673
 
1679
1674
    def test_product_to_product_works(self):
1680
1675
        self.assertTransitionWorks(
1748
1743
        sp2 = self.factory.makeSourcePackage(distroseries=ds2)
1749
1744
        self.assertTransitionForbidden(sp1, sp2)
1750
1745
 
1751
 
    def test_transition_to_same_is_noop(self):
1752
 
        p = self.factory.makeProduct()
1753
 
        self.assertTransitionWorks(p, p)
1754
 
 
1755
1746
    def test_validate_target_is_called(self):
1756
1747
        p = self.factory.makeProduct()
1757
1748
        task1 = self.factory.makeBugTask(target=p)
1763
1754
                "A fix for this bug has already been requested for %s"
1764
1755
                % p.displayname, task2.transitionToTarget, p)
1765
1756
 
 
1757
 
 
1758
class TestTransitionToTarget(TestCaseWithFactory):
 
1759
    """Tests for BugTask.transitionToTarget."""
 
1760
 
 
1761
    layer = DatabaseFunctionalLayer
 
1762
 
 
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"]))
 
1772
        return task
 
1773
 
 
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)
 
1778
 
 
1779
    def test_transition_works(self):
 
1780
        self.assertTransitionWorks(
 
1781
            self.factory.makeProduct(),
 
1782
            self.factory.makeProduct())
 
1783
 
 
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())
 
1789
 
 
1790
    def test_validation(self):
 
1791
        # validateTransitionToTarget is called before any transition.
 
1792
        p = self.factory.makeProduct()
 
1793
        task = self.factory.makeBugTask(target=p)
 
1794
 
 
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(
 
1802
                IllegalTarget, msg,
 
1803
                task.transitionToTarget, self.factory.makeProduct())
 
1804
        self.assertEqual(p, task.target)
 
1805
 
 
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)
 
1811
 
 
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)
 
1820
 
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(
 
1827
                product=product)
1772
1828
            self.assertRaises(
1773
1829
                IllegalTarget,
1774
1830
                task.transitionToTarget, self.factory.makeSourcePackage())
1775
 
            self.assertEqual(milestone, task.milestone)
 
1831
        self.assertEqual(milestone, task.milestone)
 
1832
 
 
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)
 
1838
        self.assertEqual(
 
1839
            new_product.bugtargetdisplayname,
 
1840
            removeSecurityProxy(task).targetnamecache)
1776
1841
 
1777
1842
 
1778
1843
class TestBugTargetKeys(TestCaseWithFactory):