Skip to content

Commit dab5b86

Browse files
committed
fix(View): ignore if trying to add the same relationship to a view twice
1 parent 7946a7d commit dab5b86

File tree

2 files changed

+94
-4
lines changed

2 files changed

+94
-4
lines changed

src/structurizr/view/view.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,14 +173,23 @@ def _add_relationship(self, relationship: Relationship) -> RelationshipView:
173173
"""Add a single relationship to this view.
174174
175175
Returns:
176-
The new view if both the source and destination for the relationship are
177-
in this view, else `None`.
176+
The new (or existing) view if both the source and destination for the
177+
relationship are in this view, else `None`.
178178
"""
179179
if self.is_element_in_view(relationship.source) and self.is_element_in_view(
180180
relationship.destination
181181
):
182-
view = RelationshipView(relationship=relationship)
183-
self.relationship_views.add(view)
182+
view = next(
183+
(
184+
rv
185+
for rv in self.relationship_views
186+
if rv.relationship is relationship
187+
),
188+
None,
189+
)
190+
if not view:
191+
view = RelationshipView(relationship=relationship)
192+
self.relationship_views.add(view)
184193
return view
185194
return None
186195

tests/unit/view/test_view.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Copyright (c) 2020
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
"""Ensure the expected behaviour of View."""
17+
18+
19+
from structurizr.model import Model, SoftwareSystem
20+
from structurizr.view.view import View
21+
22+
23+
class DerivedView(View):
24+
"""Mock class for testing."""
25+
26+
pass
27+
28+
29+
def test_add_relationship_doesnt_duplicate():
30+
"""Test that adding a relationships twice doesn't duplicate it."""
31+
model = Model()
32+
sys1 = model.add_software_system(name="System 1")
33+
sys2 = model.add_software_system(name="System 2")
34+
rel = sys1.uses(sys2)
35+
36+
view = DerivedView(software_system=sys1, description="")
37+
view._add_element(sys1, False)
38+
view._add_element(sys2, False)
39+
40+
rel_view1 = view._add_relationship(rel)
41+
assert len(view.relationship_views) == 1
42+
rel_view2 = view._add_relationship(rel)
43+
assert len(view.relationship_views) == 1
44+
assert rel_view2 is rel_view1
45+
46+
47+
def test_add_relationship_for_element_not_in_view():
48+
"""Ensures relationships for elements outside the view are ignored."""
49+
model = Model()
50+
sys1 = model.add_software_system(name="System 1")
51+
sys2 = model.add_software_system(name="System 2")
52+
rel = sys1.uses(sys2)
53+
54+
view = DerivedView(software_system=sys1, description="")
55+
view._add_element(sys1, False)
56+
57+
# This relationship should be ignored as sys2 isn't in the view
58+
rel_view1 = view._add_relationship(rel)
59+
assert rel_view1 is None
60+
assert view.relationship_views == set()
61+
62+
63+
def test_adding_all_relationships():
64+
"""Test adding all relationships for elements in the view."""
65+
model = Model()
66+
sys1 = model.add_software_system(name="System 1")
67+
sys2 = model.add_software_system(name="System 2")
68+
sys3 = model.add_software_system(name="System 3")
69+
rel1 = sys1.uses(sys2)
70+
rel2 = sys3.uses(sys1)
71+
72+
view = DerivedView(software_system=sys1, description="")
73+
view._add_element(sys1, False)
74+
view._add_element(sys2, False)
75+
view._add_element(sys3, False)
76+
assert view.relationship_views == set()
77+
78+
view._add_relationships(sys1)
79+
assert len(view.relationship_views) == 2
80+
assert rel1 in [vr.relationship for vr in view.relationship_views]
81+
assert rel2 in [vr.relationship for vr in view.relationship_views]

0 commit comments

Comments
 (0)