root/gaphor/tags/gaphor-0.13.0/tests/test_association_undo.py

Revision 2210, 6.6 kB (checked in by arj..@yirdis.nl, 1 year ago)

Added testcase that exposes bug #95

Line 
1 """
2 This test exhibits a bug (ticket 77) that occurs when an undo action is done
3 after an association is disconnected from a class.
4
5
6 See: http://gaphor.devjavu.com/ticket/77
7 """
8
9 import unittest
10
11 from zope import component
12 from gaphor import UML
13 from gaphor import transaction
14 from gaphor.diagram import items
15 from gaphor.diagram.interfaces import IConnect
16 from gaphor.application import Application
17
18 class AssociationUndoTestCase(unittest.TestCase):
19    
20     def setUp(self):
21         Application.init(services=['adapter_loader', 'element_factory', 'undo_manager'])
22
23     def tearDown(self):
24         Application.shutdown()
25
26     def testAssociationUndo(self):
27         factory = Application.get_service('element_factory')
28         undo_manager = Application.get_service('undo_manager')
29
30         diagram = factory.create(UML.Diagram)
31         solver = diagram.canvas.solver
32        
33         class1 = factory.create(UML.Class)
34         class1.name = 'class1'
35         classItem1 = diagram.create(items.ClassItem, subject=class1)
36
37         class2 = factory.create(UML.Class)
38         class2.name = 'class2'
39         classItem2 = diagram.create(items.ClassItem, subject=class2)
40        
41         assoc = diagram.create(items.AssociationItem)
42         assert assoc.subject is None
43
44         adapter = component.queryMultiAdapter((classItem1, assoc), IConnect)
45         assert adapter
46         adapter.connect(assoc.handles()[0])
47        
48         adapter = component.queryMultiAdapter((classItem2, assoc), IConnect)
49         assert adapter
50         adapter.connect(assoc.handles()[1])
51        
52         assert assoc.subject
53         assert assoc.head_end.subject
54         assert assoc.tail_end.subject
55
56         former = (assoc.subject, assoc.head_end.subject, assoc.tail_end.subject)
57        
58         # Also check solver state:
59         x_cons = list(solver.constraints_with_variable(assoc.handles()[1].x))
60         y_cons = list(solver.constraints_with_variable(assoc.handles()[1].y))
61
62         assert len(solver._constraints) == 14, len(solver._constraints)
63         #assert len(x_cons) == 1, x_cons
64         #assert len(y_cons) == 1, y_cons
65
66         tx = transaction.Transaction()
67        
68         adapter = component.queryMultiAdapter((classItem2, assoc), IConnect)
69         assert adapter
70         adapter.disconnect(assoc.handles()[1])
71        
72         tx.commit()
73
74         assert assoc.subject is None
75         assert assoc.head_end.subject is None
76         assert assoc.tail_end.subject is None
77
78         # Also check solver state:
79         x_cons = list(solver.constraints_with_variable(assoc.handles()[1].x))
80         y_cons = list(solver.constraints_with_variable(assoc.handles()[1].y))
81
82         assert len(solver._constraints) == 13, len(solver._constraints)
83         #assert len(x_cons) == 0, x_cons
84         #assert len(y_cons) == 0, y_cons
85
86         assert undo_manager.can_undo()
87
88         undo_manager.undo_transaction()
89
90         assert not undo_manager.can_undo()
91
92         assert assoc.subject is former[0]
93         assert assoc.head_end.subject is former[1]
94         assert assoc.tail_end.subject is former[2]
95
96         # Also check solver state:
97         x_cons = list(solver.constraints_with_variable(assoc.handles()[1].x))
98         y_cons = list(solver.constraints_with_variable(assoc.handles()[1].y))
99
100         assert len(solver._constraints) == 14, len(solver._constraints)
101         assert len(x_cons) == 0, x_cons
102         assert len(y_cons) == 0, y_cons
103
104
105         # Disconnect again:
106
107         adapter = component.queryMultiAdapter((classItem2, assoc), IConnect)
108         assert adapter
109         adapter.disconnect(assoc.handles()[1])
110        
111         assert assoc.subject is None
112         assert assoc.head_end.subject is None
113         assert assoc.tail_end.subject is None
114
115         # Also check solver state:
116         x_cons = list(solver.constraints_with_variable(assoc.handles()[1].x))
117         y_cons = list(solver.constraints_with_variable(assoc.handles()[1].y))
118
119         # Ah hah! the constraint is not disconnected again!
120         # (Added to solver, not to Handle I guess)
121         assert len(solver._constraints) == 13, len(solver._constraints)
122         #assert len(x_cons) == 0, x_cons
123         #assert len(y_cons) == 0, y_cons
124
125     def testAssociationDelete(self):
126         factory = Application.get_service('element_factory')
127         undo_manager = Application.get_service('undo_manager')
128
129         diagram = factory.create(UML.Diagram)
130         solver = diagram.canvas.solver
131        
132         class1 = factory.create(UML.Class)
133         class1.name = 'class1'
134         classItem1 = diagram.create(items.ClassItem, subject=class1)
135
136         class2 = factory.create(UML.Class)
137         class2.name = 'class2'
138         classItem2 = diagram.create(items.ClassItem, subject=class2)
139        
140         assoc = diagram.create(items.AssociationItem)
141         assert assoc.subject is None
142
143         adapter = component.queryMultiAdapter((classItem1, assoc), IConnect)
144         assert adapter
145         adapter.connect(assoc.handles()[0])
146        
147         adapter = component.queryMultiAdapter((classItem2, assoc), IConnect)
148         assert adapter
149         adapter.connect(assoc.handles()[1])
150        
151         assoc_subject = assoc.subject
152         assert assoc.subject
153         assert assoc.head_end.subject
154         assert assoc.tail_end.subject
155         assert assoc.head.connected_to is classItem1
156         assert assoc.tail.connected_to is classItem2
157
158         former = (assoc.subject, assoc.head_end.subject, assoc.tail_end.subject)
159
160         assert len(solver._constraints) == 14, len(solver._constraints)
161
162         tx = transaction.Transaction()
163
164         assoc.unlink()
165        
166         tx.commit()
167
168         assert assoc.canvas is None
169         assert assoc.subject is None
170         assert assoc.head_end.subject is None
171         assert assoc.tail_end.subject is None
172         assert assoc.head.connected_to is None
173         assert assoc.tail.connected_to is None
174
175         assert undo_manager.can_undo()
176
177         print
178         print '-' * 80
179         print
180
181         undo_manager.undo_transaction()
182
183         print
184         print '-' * 80
185         print
186
187         assert not undo_manager.can_undo()
188
189         assert assoc.canvas
190         assert assoc.subject is assoc_subject
191         assert assoc.head_end.subject
192         assert assoc.tail_end.subject
193
194         assert len(solver._constraints) == 14, len(solver._constraints)
195         assert assoc.head.connected_to is classItem1, assoc.head.connected_to
196         assert assoc.tail.connected_to is classItem2, assoc.head.connected_to
197
198
199 if __name__ == '__main__':
200     unittest.main()
201
202 # vim:sw=4:et:ai
Note: See TracBrowser for help on using the browser.