Fix bug where syncing an object removed from the collection tree breaks.

This commit is contained in:
Dion Moult
2022-01-30 14:42:26 +11:00
parent bf9d46b506
commit c7428dd160
8 changed files with 71 additions and 43 deletions
@@ -27,7 +27,7 @@ class BIM_PT_spatial(Panel):
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "object"
bl_parent_id = "BIM_PT_geometry_object"
bl_parent_id = "BIM_PT_object_metadata"
@classmethod
def poll(cls, context):
@@ -32,6 +32,9 @@ class Collector(blenderbim.core.tool.Collector):
if element.is_a("IfcProject") or element.is_a("IfcGridAxis"):
return
if not obj.users_collection:
return
object_collection = None
collection_collection = None
+40 -37
View File
@@ -5,41 +5,44 @@
# ############################################################################ #
# This allows us to write full integration tests that test how all systems work
# as a whole. Whilst other tests focus on portions of the software, these tests
# simulate what happens when a user opens Blender, presses buttons, and does
# things.
# Note: these tests are commented out as they are for learning purposes only. If
# you want to run these tests, uncomment it :)
# These tests read like english. You can see all the possible sentences defined
# in test_feature.py. Most of the time, there is already a sentence defined for
# what you want to test.
@demo
Feature: Demo
# Every operator has at least one scenario associated with it to test it.
Scenario: Demonstrate hello world
Given an empty IFC project
When I press "bim.demonstrate_hello_world"
# Blender doesn't have a way of testing that things are visible in the
# interface and layout. We can check properties, and whats in the 3D
# scenegraph, but not layout. There is no "DOM" like in web applications.
# Too bad, we can't check the results, but we still write the test, that way
# we can still check for errors like crashes or Python errors, like a "smoke
# test".
Then nothing happens
# This operator has two scenarios because there are two possibilities of a user
# interacting with it.
Scenario: Demonstrate rename project - with a name provided
Given an empty IFC project
When I set "scene.BIMDemoProperties.name" to "Foobar"
And I press "bim.demonstrate_rename_project"
Then the object "IfcProject/Foobar" is an "IfcProject"
# This is the other possible scenario for the rename project operator.
Scenario: Demonstrate rename project - with no name
Given an empty IFC project
When I set "scene.BIMDemoProperties.name" to ""
And I press "bim.demonstrate_rename_project"
Then the object "IfcProject/My Project" is an "IfcProject"
#|# This allows us to write full integration tests that test how all systems work
#|# as a whole. Whilst other tests focus on portions of the software, these tests
#|# simulate what happens when a user opens Blender, presses buttons, and does
#|# things.
#|
#|# These tests read like english. You can see all the possible sentences defined
#|# in test_feature.py. Most of the time, there is already a sentence defined for
#|# what you want to test.
#|
#|@demo
#|Feature: Demo
#|
#|# Every operator has at least one scenario associated with it to test it.
#|Scenario: Demonstrate hello world
#| Given an empty IFC project
#| When I press "bim.demonstrate_hello_world"
#| # Blender doesn't have a way of testing that things are visible in the
#| # interface and layout. We can check properties, and whats in the 3D
#| # scenegraph, but not layout. There is no "DOM" like in web applications.
#| # Too bad, we can't check the results, but we still write the test, that way
#| # we can still check for errors like crashes or Python errors, like a "smoke
#| # test".
#| Then nothing happens
#|
#|# This operator has two scenarios because there are two possibilities of a user
#|# interacting with it.
#|Scenario: Demonstrate rename project - with a name provided
#| Given an empty IFC project
#| When I set "scene.BIMDemoProperties.name" to "Foobar"
#| And I press "bim.demonstrate_rename_project"
#| Then the object "IfcProject/Foobar" is an "IfcProject"
#|
#|# This is the other possible scenario for the rename project operator.
#|Scenario: Demonstrate rename project - with no name
#| Given an empty IFC project
#| When I set "scene.BIMDemoProperties.name" to ""
#| And I press "bim.demonstrate_rename_project"
#| Then the object "IfcProject/My Project" is an "IfcProject"
+1 -1
View File
@@ -184,7 +184,7 @@ def the_object_name_is_placed_in_the_collection_collection(name, collection):
def additionally_the_object_name_is_selected(name):
obj = bpy.context.scene.objects.get(name)
if not obj:
assert False, 'The object "{name}" could not be selected'
assert False, f'The object "{name}" could not be selected'
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
+7
View File
@@ -23,6 +23,11 @@
# ############################################################################ #
# Note: these tests are commented out as they are for learning purposes only. If
# you want to run these tests, uncomment it :)
"""
# Testing the core might seem strange if you haven't written this type of
# abstract test before. You essentially want to test that things are called in
# the right sequence. This seems almost like writing the code twice, like in
@@ -82,3 +87,5 @@ class TestDemonstrateRenameProject:
def test_showing_a_hint_if_no_name_provided(self, ifc, demo):
demo.show_user_hints().should_be_called()
subject.demonstrate_rename_project(ifc, demo, name=None)
"""
+4 -4
View File
@@ -37,8 +37,8 @@ class TestImplementsTool(NewFile):
class TestAddBrick(NewFile):
def test_run(self):
BrickStore.graph = brickschema.Graph()
result = subject.add_brick("http://example.org/digitaltwin#", "https://brickschema.org/schema/Brick#Equipment")
assert "http://example.org/digitaltwin#" in result
result = subject.add_brick("https://example.org/digitaltwin#", "https://brickschema.org/schema/Brick#Equipment")
assert "https://example.org/digitaltwin#" in result
assert list(
BrickStore.graph.triples(
(URIRef(result), RDF.type, URIRef("https://brickschema.org/schema/Brick#Equipment"))
@@ -250,7 +250,7 @@ class TestGetConvertableBrickElements(NewFile):
class TestGetItemClass(NewFile):
def test_run(self):
TestLoadBrickFile().test_run()
assert subject.get_item_class("http://example.org/digitaltwin#floor") == "Floor"
assert subject.get_item_class("https://example.org/digitaltwin#floor") == "Floor"
class TestGetLibraryBrickReference(NewFile):
@@ -300,7 +300,7 @@ class TestImportBrickItems(NewFile):
brick = bpy.context.scene.BIMBrickProperties.bricks[0]
assert brick.name == "bldg"
assert brick.label == "My Building"
assert brick.uri == "http://example.org/digitaltwin#bldg"
assert brick.uri == "https://example.org/digitaltwin#bldg"
assert brick.total_items == 0
@@ -249,6 +249,14 @@ class TestAssign(NewFile):
class TestSync(NewFile):
def test_doing_nothing_if_the_object_has_no_collection(self):
bpy.ops.bim.create_project()
wall_obj = bpy.data.objects.new("Object", None)
wall_element = tool.Ifc.get().createIfcWall()
tool.Ifc.link(wall_element, wall_obj)
subject.sync(wall_obj)
assert not wall_obj.users_collection
def test_in_decomposition_mode_elements_can_be_in_spatial_containers(self):
bpy.ops.bim.create_project()
wall_obj = bpy.data.objects.new("Object", None)
+7
View File
@@ -23,6 +23,11 @@
# ############################################################################ #
# Note: these tests are commented out as they are for learning purposes only. If
# you want to run these tests, uncomment it :)
"""
# Because our tools have well defined, isolated functions, it means we can test
# them very easily in isolation. Tests are fun, fast, and easy to setup!
@@ -85,3 +90,5 @@ class TestShowUserHints(NewFile):
bpy.context.scene.BIMDemoProperties.show_hints = False
subject.show_user_hints()
assert bpy.context.scene.BIMDemoProperties.show_hints == True
"""