~launchpad-pqm/launchpad/devel

3691.235.2 by Francis J. Lacoste
Convert headers to moin style and comments in () to code comments.
1
= IBugLinkTarget Interface =
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
2
3691.109.31 by Francis J. Lacoste
Typos
3
Launchpad includes Malone, the powerful bug tracker. One of the best
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
4
features of Malone is the ability to track a bug in multiple products
5
and/or packages. A bug can also be linked to other non-bug tracking
3691.398.21 by Francis J. Lacoste
Rename all attributes and variables.
6
objects like questions, CVEs or specifications.
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
7
8
The IBugLinkTarget interface is used for that general purpose linking.
9
This file documents that interface and can be used to validate
10
implementation of this interface on a particular object. (This object is
11
made available through the 'target' variable which is defined outside of
12
this file, usually by a LaunchpadFunctionalTestCase. This instance
13
shouldn't have any bugs linked to it at the start of the test.)
14
3691.235.2 by Francis J. Lacoste
Convert headers to moin style and comments in () to code comments.
15
    # Some parts of the IBugLinkTarget interface are only accessible
16
    # to a registered user.
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
17
    >>> login('no-priv@canonical.com')
18
    >>> from zope.interface.verify import verifyObject
11716.1.6 by Curtis Hovey
Converted glob imports in doctests to import for the true module.
19
    >>> from lp.bugs.interfaces.bug import IBugSet
11716.1.15 by Curtis Hovey
Fixed multiline import statements in doctests.
20
    >>> from lp.bugs.interfaces.buglink import (
11716.1.12 by Curtis Hovey
Sorted imports in doctests.
21
    ...     IBugLink,
22
    ...     IBugLinkTarget,
23
    ...     )
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
24
25
    >>> verifyObject(IBugLinkTarget, target)
26
    True
27
3691.235.2 by Francis J. Lacoste
Convert headers to moin style and comments in () to code comments.
28
== linkBug() ==
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
29
30
    >>> bugset = getUtility(IBugSet)
31
    >>> bug1 = bugset.get(1)
32
33
The linkBug() method is used to link a bug to the target. It takes as
34
parameter the bug which should be linked. The method should return the
35
IBugLink that was created.
36
37
    >>> link1 = target.linkBug(bug1)
38
39
    >>> verifyObject(IBugLink, link1)
40
    True
41
    >>> link1.target == target
42
    True
43
    >>> link1.bug == bug1
44
    True
45
46
When the bug was already linked to the target, the existing link should
47
be used.
48
49
    >>> target.linkBug(bug1) == link1
50
    True
51
7876.3.6 by Francis J. Lacoste
Used ISQLObject from lazr.lifecycle
52
When a IBugLink is created, one IObjectCreatedEvent for the created
3691.109.31 by Francis J. Lacoste
Typos
53
should be fired by the method.
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
54
14606.4.7 by William Grant
canonical.lazr.testing.event -> lp.testing.event.
55
    >>> from lp.testing.event import TestEventListener
7876.3.6 by Francis J. Lacoste
Used ISQLObject from lazr.lifecycle
56
    >>> from lazr.lifecycle.interfaces import (
57
    ...     IObjectCreatedEvent, IObjectDeletedEvent)
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
58
    >>> created_events = []
59
    >>> created_event_listener = TestEventListener(
7876.3.6 by Francis J. Lacoste
Used ISQLObject from lazr.lifecycle
60
    ...     IBugLink, IObjectCreatedEvent,
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
61
    ...     lambda object, event: created_events.append(event))
62
63
    >>> bug2 = bugset.get(2)
64
    >>> link2 = target.linkBug(bugset.get(2))
65
    >>> created_events[-1].object == link2
66
    True
67
68
Of course, if no new IBugLink is created, no events should be fired:
69
70
    >>> created_events = []
71
    >>> target.linkBug(bug2) == link2
72
    True
73
    >>> created_events
74
    []
75
76
Anonymous users cannot use linkBug():
77
78
    >>> login(ANONYMOUS)
79
    >>> target.linkBug(bug2)
80
    Traceback (most recent call last):
81
      ...
82
    Unauthorized...
83
3691.109.31 by Francis J. Lacoste
Typos
84
A user can only link to a private bug if he is subscribed to the bug or
85
if he is an administrator:
3691.109.23 by Francis J. Lacoste
* Define a BugLinkTargetMixin for base implementation of linkBug and unlinkBug.
86
87
    >>> login('no-priv@canonical.com')
88
    >>> private_bug = bugset.get(6)
13147.1.9 by Graham Binns
Fixed test failures.
89
    >>> private_bug.setPrivate(True, factory.makePerson())
4813.12.15 by Gavin Panella
Change assignments to bug.private to use bug.setPrivate(), pt. 1.
90
    True
3691.109.23 by Francis J. Lacoste
* Define a BugLinkTargetMixin for base implementation of linkBug and unlinkBug.
91
    >>> target.linkBug(private_bug)
92
    Traceback (most recent call last):
93
      ...
94
    Unauthorized...
95
96
    >>> login('foo.bar@canonical.com')
97
    >>> private_link = target.linkBug(private_bug)
98
3691.235.2 by Francis J. Lacoste
Convert headers to moin style and comments in () to code comments.
99
== bugs ==
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
100
101
The list of bugs linked to the target should be available in the bugs
102
attributes:
103
104
    >>> [bug.id for bug in target.bugs]
3691.109.23 by Francis J. Lacoste
* Define a BugLinkTargetMixin for base implementation of linkBug and unlinkBug.
105
    [1, 2, 6]
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
106
3691.235.2 by Francis J. Lacoste
Convert headers to moin style and comments in () to code comments.
107
== bug_links ==
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
108
109
The IBugLink objects available on the target should be available in the
110
bug_links attribute:
111
112
    >>> [link.bug.id for link in target.bug_links]
3691.109.23 by Francis J. Lacoste
* Define a BugLinkTargetMixin for base implementation of linkBug and unlinkBug.
113
    [1, 2, 6]
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
114
3691.235.2 by Francis J. Lacoste
Convert headers to moin style and comments in () to code comments.
115
== unlinkBug() ==
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
116
117
The unlinkBug() method is used to remove a link between a bug and
118
the target.
119
120
This method is only available to registered users:
121
122
    >>> login(ANONYMOUS)
123
    >>> target.unlinkBug(bug2)
124
    Traceback (most recent call last):
125
      ...
126
    Unauthorized...
127
128
    >>> login('no-priv@canonical.com')
129
130
The method returns the linked object which was removed. It should also
7876.3.6 by Francis J. Lacoste
Used ISQLObject from lazr.lifecycle
131
send a IObjectDeletedEvent for the removed IBugLink:
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
132
133
    >>> deleted_events = []
134
    >>> deleted_event_listener = TestEventListener(
7876.3.6 by Francis J. Lacoste
Used ISQLObject from lazr.lifecycle
135
    ...     IBugLink, IObjectDeletedEvent,
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
136
    ...     lambda object, event: deleted_events.append(event))
137
138
    >>> target.unlinkBug(bug1) == link1
139
    True
140
    >>> deleted_events[-1].object == link1
141
    True
142
143
    >>> [bug.id for bug in target.bugs]
3691.109.23 by Francis J. Lacoste
* Define a BugLinkTargetMixin for base implementation of linkBug and unlinkBug.
144
    [2, 6]
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
145
146
When the bug was not linked to the target, that method should return
147
None (and not trigger any events):
148
149
    >>> deleted_events = []
150
    >>> target.unlinkBug(bug1) is None
151
    True
152
    >>> deleted_events
153
    []
154
3691.109.23 by Francis J. Lacoste
* Define a BugLinkTargetMixin for base implementation of linkBug and unlinkBug.
155
A user can only remove a link to a private bug if he is subscribed to
156
the bug or if he is an administrator.
157
158
    >>> target.unlinkBug(private_bug)
159
    Traceback (most recent call last):
160
      ...
161
    Unauthorized...
162
163
    >>> login('foo.bar@canonical.com')
164
    >>> target.unlinkBug(private_bug) == private_link
165
    True
166
3691.235.2 by Francis J. Lacoste
Convert headers to moin style and comments in () to code comments.
167
== Cleanup ==
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
168
3691.235.2 by Francis J. Lacoste
Convert headers to moin style and comments in () to code comments.
169
    # Unregister event listeners.
3691.109.2 by Francis J. Lacoste
Add interface test for IBugLinkTarget
170
    >>> created_event_listener.unregister()
171
    >>> deleted_event_listener.unregister()