From 6464adec54de19356d8bea40468cea8a1ca8a83a Mon Sep 17 00:00:00 2001
From: florian <f.spreckelsen@inidscale.com>
Date: Wed, 14 Jun 2023 11:02:40 +0200
Subject: [PATCH] TST: Add tests for removing a value from a property

---
 unittests/test_property.py | 80 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 76 insertions(+), 4 deletions(-)

diff --git a/unittests/test_property.py b/unittests/test_property.py
index 7c756117..d3c0fa4b 100644
--- a/unittests/test_property.py
+++ b/unittests/test_property.py
@@ -1,11 +1,11 @@
 # -*- encoding: utf-8 -*-
 #
-# ** header v3.0
 # This file is a part of the CaosDB Project.
 #
 # Copyright (C) 2018 Research Group Biomedical Physics,
 # Max-Planck-Institute for Dynamics and Self-Organization Göttingen
-# Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
+# Copyright (C) 2020 - 2023 IndiScale GmbH <info@indiscale.com>
+# Copyright (C) 2023 Florian Spreckelsen <f.spreckelsen@indiscale.com>
 # Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
 #
 # This program is free software: you can redistribute it and/or modify
@@ -21,8 +21,6 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program. If not, see <https://www.gnu.org/licenses/>.
 #
-# ** end header
-#
 """Tests for the Property class."""
 import os
 
@@ -138,3 +136,77 @@ def test_is_reference():
 
     # restore retrieve function with original
     Entity.retrieve = real_retrieve
+
+
+def test_remove_value_from_property():
+
+    rec = Record()
+    names_values_dtypes = [
+        ("testListProp1", [1, 2, 3], db.LIST(db.INTEGER)),
+        ("testListProp2", ["a", "b", "a"], db.LIST(db.TEXT)),
+        ("testScalarProp1", "bla", db.TEXT),
+        ("testScalarProp2", False, db.BOOLEAN),
+        ("testEmptyProp", None, db.REFERENCE)
+    ]
+    for name, value, dtype in names_values_dtypes:
+        rec.add_property(name=name, value=value, datatype=dtype)
+
+    # property doesn't exist, so do nothing
+    rec.remove_value_from_property("nonexisting", "some_value")
+    for name, value, dtype in names_values_dtypes:
+        assert rec.get_property(name).value == value
+        assert rec.get_property(name).datatype == dtype
+
+    # value doesn't exist so nothing changes either
+    rec.remove_value_from_property("testListProp1", 0)
+    assert rec.get_property("testListProp1").value == [1, 2, 3]
+    assert rec.get_property("testListProp1").datatype == db.LIST(db.INTEGER)
+
+    rec.remove_value_from_property("testScalarProp2", True)
+    assert rec.get_property("testScalarProp2").value == False
+    assert rec.get_property("testScalarProp2").datatype == db.BOOLEAN
+
+    # Simple removals from lists without emptying them
+    rec.remove_value_from_property("testListProp1", 1)
+    assert rec.get_property("testListProp1").value == [2, 3]
+
+    rec.remove_value_from_property("testListProp1", 2)
+    assert rec.get_property("testListProp1").value == [3]
+
+    # similarly to Python's `list.remove()`, only remove first occurrance
+    rec.remove_value_from_property("testListProp2", "a")
+    assert rec.get_property("testListProp2").value == ["b", "a"]
+
+    # default is to remove an empty property:
+    rec.remove_value_from_property("testListProp1", 3)
+    assert rec.get_property("testListProp1") is None
+
+    rec.remove_value_from_property("testScalarProp1", "bla")
+    assert rec.get_property("testScalarProp1") is None
+
+    # don't remove if `remove_if_empty_afterwards=False`
+    rec.remove_value_from_property("testListProp2", "b")
+    rec.remove_value_from_property("testListProp2", "a", remove_if_empty_afterwards=False)
+    assert rec.get_property("testListProp2") is not None
+    assert rec.get_property("testListProp2").value is None
+    assert rec.get_property("testListProp2").datatype == db.LIST(db.TEXT)
+
+    rec.remove_value_from_property("testScalarProp2", False, remove_if_empty_afterwards=False)
+    assert rec.get_property("testScalarProp2") is not None
+    assert rec.get_property("testScalarProp2").value is None
+    assert rec.get_property("testScalarProp2").datatype == db.BOOLEAN
+
+    # Special case of an already empty property: It is not empty because a value
+    # was removed by `remove_value_from_property` but never had a value in the
+    # first place. So even `remove_if_empty_afterwards=True` should not lead to
+    # its removal.
+    rec.remove_value_from_property("testEmptyProp", 1234, remove_if_empty_afterwards=True)
+    assert rec.get_property("testEmptyProp") is not None
+    assert rec.get_property("testEmptyProp").value is None
+    assert rec.get_property("testEmptyProp").datatype == db.REFERENCE
+
+    # Corner case of corner case: remove with `value=None` explicitly and
+    # `remove_if_empty_afterwards=True` leads to the removal of an empty
+    # property.
+    rec.remove_value_from_property("testEmptyProp", None, remove_if_empty_afterwards=True)
+    assert rec.get_property("testEmptyProp") is None
-- 
GitLab