Repository: RockefellerArchiveCenter/rac_aspace

Issue:
Review and improve coverage of unit tests
**Is your feature request related to a problem? Please describe.**
Now that we have some unit tests in place (see #60) it's probably a smart idea to look at how much of our code is and isn't covered by those tests.

**Describe the solution you'd like**
Use a tool like [coverage](https://coverage.readthedocs.io/en/coverage-5.0.4/) to evaluate how comprehensive our coverage is. 

**Describe alternatives you've considered**
Consider including this in the pre-commit configs or as part of `tox` config so we always have some visibility on our coverage.

Discussion:

Patch:
diff --git a/fixtures/archival_object_2.json b/fixtures/archival_object_2.json
new file mode 100644
index 0000000..b553ac7
--- /dev/null
+++ b/fixtures/archival_object_2.json
@@ -0,0 +1,127 @@
+{
+    "lock_version": 3,
+    "title": "kmtests",
+    "publish": true,
+    "restrictions": false,
+    "created_by": "k.martin",
+    "last_modified_by": "admin",
+    "create_time": "2020-03-09T16:25:14Z",
+    "system_mtime": "2020-03-19T13:07:13Z",
+    "user_mtime": "2020-03-19T13:07:13Z",
+    "suppressed": false,
+    "is_slug_auto": false,
+    "id_0": "1",
+    "id_1": "2",
+    "id_2": "3",
+    "language": "ang",
+    "level": "collection",
+    "jsonmodel_type": "resource",
+    "external_ids": [],
+    "subjects": [],
+    "linked_events": [],
+    "extents": [
+        {
+            "lock_version": 0,
+            "number": "1",
+            "created_by": "admin",
+            "last_modified_by": "admin",
+            "create_time": "2020-03-19T13:07:40Z",
+            "system_mtime": "2020-03-19T13:07:40Z",
+            "user_mtime": "2020-03-19T13:07:40Z",
+            "portion": "whole",
+            "extent_type": "Cubic Feet",
+            "jsonmodel_type": "extent"
+        }
+    ],
+    "dates": [
+        {
+            "lock_version": 0,
+            "begin": "1990",
+            "end": "2000",
+            "created_by": "admin",
+            "last_modified_by": "admin",
+            "create_time": "2020-03-19T13:07:40Z",
+            "system_mtime": "2020-03-19T13:07:40Z",
+            "user_mtime": "2020-03-19T13:07:40Z",
+            "date_type": "bulk",
+            "label": "creation",
+            "era": "ce",
+            "calendar": "gregorian",
+            "jsonmodel_type": "date"
+        }
+    ],
+    "external_documents": [],
+    "rights_statements": [
+        {
+            "lock_version": 0,
+            "identifier": "e5dc6d09b9fe8640c05fe3de2926868c",
+            "created_by": "admin",
+            "last_modified_by": "admin",
+            "create_time": "2020-03-19T13:07:41Z",
+            "system_mtime": "2020-03-19T13:07:41Z",
+            "user_mtime": "2020-03-19T13:07:41Z",
+            "start_date": "2020-02-01",
+            "end_date": "2090-05-06",
+            "rights_type": "copyright",
+            "status": "copyrighted",
+            "jurisdiction": "US",
+            "jsonmodel_type": "rights_statement",
+            "external_documents": [],
+            "acts": [
+                {
+                    "start_date": "2020-01-01",
+                    "end_date": "2090-12-31",
+                    "created_by": "admin",
+                    "last_modified_by": "admin",
+                    "create_time": "2020-03-19T13:07:41Z",
+                    "system_mtime": "2020-03-19T13:07:41Z",
+                    "user_mtime": "2020-03-19T13:07:41Z",
+                    "act_type": "use",
+                    "restriction": "disallow",
+                    "jsonmodel_type": "rights_statement_act",
+                    "notes": []
+                }
+            ],
+            "linked_agents": [],
+            "notes": []
+        }
+    ],
+    "linked_agents": [],
+    "revision_statements": [],
+    "instances": [
+        {
+            "lock_version": 0,
+            "created_by": "admin",
+            "last_modified_by": "admin",
+            "create_time": "2020-03-19T13:07:41Z",
+            "system_mtime": "2020-03-19T13:07:41Z",
+            "user_mtime": "2020-03-19T13:07:41Z",
+            "instance_type": "mixed materials",
+            "jsonmodel_type": "instance",
+            "is_representative": false,
+            "sub_container": {
+                "lock_version": 0,
+                "created_by": "admin",
+                "last_modified_by": "admin",
+                "create_time": "2020-03-19T13:07:41Z",
+                "system_mtime": "2020-03-19T13:07:41Z",
+                "user_mtime": "2020-03-19T13:07:41Z",
+                "jsonmodel_type": "sub_container",
+                "top_container": {
+                    "ref": "/repositories/2/top_containers/191155"
+                }
+            }
+        }
+    ],
+    "deaccessions": [],
+    "related_accessions": [],
+    "classifications": [],
+    "notes": [],
+    "uri": "/repositories/2/resources/13064",
+    "repository": {
+        "ref": "/repositories/2"
+    },
+    "tree": {
+        "ref": "/repositories/2/resources/13064/tree"
+    }
+}
diff --git a/fixtures/archival_object_3.json b/fixtures/archival_object_3.json
new file mode 100644
index 0000000..ae3b047
--- /dev/null
+++ b/fixtures/archival_object_3.json
@@ -0,0 +1,110 @@
+{
+    "lock_version": 3,
+    "title": "kmtests",
+    "publish": true,
+    "restrictions": false,
+    "created_by": "k.martin",
+    "last_modified_by": "admin",
+    "create_time": "2020-03-09T16:25:14Z",
+    "system_mtime": "2020-03-19T13:07:13Z",
+    "user_mtime": "2020-03-19T13:07:13Z",
+    "suppressed": false,
+    "is_slug_auto": false,
+    "id_0": "1",
+    "id_1": "2",
+    "id_2": "3",
+    "language": "ang",
+    "level": "collection",
+    "jsonmodel_type": "resource",
+    "external_ids": [],
+    "subjects": [],
+    "linked_events": [],
+    "extents": [
+        {
+            "lock_version": 0,
+            "number": "1",
+            "created_by": "admin",
+            "last_modified_by": "admin",
+            "create_time": "2020-03-19T13:07:40Z",
+            "system_mtime": "2020-03-19T13:07:40Z",
+            "user_mtime": "2020-03-19T13:07:40Z",
+            "portion": "whole",
+            "extent_type": "Cubic Feet",
+            "jsonmodel_type": "extent"
+        }
+    ],
+    "dates": [
+        {
+            "lock_version": 0,
+            "begin": "1990",
+            "end": "2000",
+            "created_by": "admin",
+            "last_modified_by": "admin",
+            "create_time": "2020-03-19T13:07:40Z",
+            "system_mtime": "2020-03-19T13:07:40Z",
+            "user_mtime": "2020-03-19T13:07:40Z",
+            "date_type": "bulk",
+            "label": "creation",
+            "era": "ce",
+            "calendar": "gregorian",
+            "jsonmodel_type": "date"
+        }
+    ],
+    "external_documents": [],
+    "rights_statements": [],
+    "linked_agents": [],
+    "revision_statements": [],
+    "instances": [
+        {
+            "lock_version": 0,
+            "created_by": "admin",
+            "last_modified_by": "admin",
+            "create_time": "2020-03-19T13:07:41Z",
+            "system_mtime": "2020-03-19T13:07:41Z",
+            "user_mtime": "2020-03-19T13:07:41Z",
+            "instance_type": "mixed materials",
+            "jsonmodel_type": "instance",
+            "is_representative": false,
+            "sub_container": {
+                "lock_version": 0,
+                "created_by": "admin",
+                "last_modified_by": "admin",
+                "create_time": "2020-03-19T13:07:41Z",
+                "system_mtime": "2020-03-19T13:07:41Z",
+                "user_mtime": "2020-03-19T13:07:41Z",
+                "jsonmodel_type": "sub_container",
+                "top_container": {
+                    "ref": "/repositories/2/top_containers/191155"
+                }
+            }
+        }
+    ],
+    "deaccessions": [],
+    "related_accessions": [],
+    "classifications": [],
+    "notes": [
+        {
+            "jsonmodel_type": "note_multipart",
+            "persistent_id": "7e39d839488e068c65f822e52f5ffa01",
+            "type": "accessrestrict",
+            "rights_restriction": {
+                "local_access_restriction_type": []
+            },
+            "subnotes": [
+                {
+                    "jsonmodel_type": "note_text",
+                    "content": "materials are open for research",
+                    "publish": true
+                }
+            ],
+            "publish": true
+        }
+    ],
+    "uri": "/repositories/2/resources/13064",
+    "repository": {
+        "ref": "/repositories/2"
+    },
+    "tree": {
+        "ref": "/repositories/2/resources/13064/tree"
+    }
+}
diff --git a/fixtures/date_no_expression_no_end.json b/fixtures/date_no_expression_no_end.json
new file mode 100644
index 0000000..bc8fbec
--- /dev/null
+++ b/fixtures/date_no_expression_no_end.json
@@ -0,0 +1,12 @@
+{
+  "lock_version": 0,
+  "begin": "1905",
+  "created_by": "greg",
+  "last_modified_by": "greg",
+  "create_time": "2017-08-08T21:11:46Z",
+  "system_mtime": "2017-08-08T21:11:46Z",
+  "user_mtime": "2017-08-08T21:11:46Z",
+  "date_type": "inclusive",
+  "label": "creation",
+  "jsonmodel_type": "date"
+}
diff --git a/fixtures/note_bibliography.json b/fixtures/note_bibliography.json
new file mode 100644
index 0000000..0f12752
--- /dev/null
+++ b/fixtures/note_bibliography.json
@@ -0,0 +1,12 @@
+{
+  "jsonmodel_type": "note_bibliography",
+  "content": [
+    "bibliography"
+  ],
+  "items": [
+    "item 1",
+    "item 2"
+  ],
+  "persistent_id": "e5275d70ec328dd680d701e8594601f2",
+  "publish": true
+}
diff --git a/fixtures/note_index.json b/fixtures/note_index.json
new file mode 100644
index 0000000..511a22e
--- /dev/null
+++ b/fixtures/note_index.json
@@ -0,0 +1,21 @@
+{
+  "jsonmodel_type": "note_index",
+  "label": "index note",
+  "content": [
+    "index note"
+  ],
+  "items": [
+    {
+      "jsonmodel_type": "note_index_item",
+      "value": "title1",
+      "type": "title"
+    },
+    {
+      "jsonmodel_type": "note_index_item",
+      "value": "title2",
+      "type": "title"
+    }
+  ],
+  "persistent_id": "d6ae385258de58d7d5d03d29c193c00a",
+  "publish": true
+}
diff --git a/fixtures/note_multi_chronology.json b/fixtures/note_multi_chronology.json
new file mode 100644
index 0000000..e454a56
--- /dev/null
+++ b/fixtures/note_multi_chronology.json
@@ -0,0 +1,27 @@
+{
+  "jsonmodel_type": "note_multipart",
+  "persistent_id": "c51deda8203865fb5716a78fe7fe1563",
+  "type": "odd",
+  "subnotes": [
+    {
+      "jsonmodel_type": "note_text",
+      "content": "general note with chronology",
+      "publish": true
+    },
+    {
+      "jsonmodel_type": "note_chronology",
+      "title": "chronology",
+      "publish": true,
+      "items": [
+        {
+          "event_date": "date",
+          "events": [
+            "event1",
+            "event2"
+          ]
+        }
+      ]
+    }
+  ],
+  "publish": true
+}
diff --git a/fixtures/note_multi_defined.json b/fixtures/note_multi_defined.json
new file mode 100644
index 0000000..18dbc8e
--- /dev/null
+++ b/fixtures/note_multi_defined.json
@@ -0,0 +1,28 @@
+{
+  "jsonmodel_type": "note_multipart",
+  "type": "bioghist",
+  "subnotes": [
+    {
+      "jsonmodel_type": "note_text",
+      "content": "bioghist with defined list",
+      "publish": true
+    },
+    {
+      "jsonmodel_type": "note_definedlist",
+      "title": "defined list",
+      "publish": true,
+      "items": [
+        {
+          "label": "item",
+          "value": "1"
+        },
+        {
+          "label": "item",
+          "value": "2"
+        }
+      ]
+    }
+  ],
+  "persistent_id": "0032cffa9e2fa854171a77d3f0ab7886",
+  "publish": true
+}
diff --git a/fixtures/note_multi_ordered.json b/fixtures/note_multi_ordered.json
new file mode 100644
index 0000000..e1f2ea5
--- /dev/null
+++ b/fixtures/note_multi_ordered.json
@@ -0,0 +1,22 @@
+{
+  "jsonmodel_type": "note_multipart",
+  "type": "bioghist",
+  "subnotes": [
+    {
+      "jsonmodel_type": "note_text",
+      "content": "Bioghist with ordered list",
+      "publish": true
+    },
+    {
+      "jsonmodel_type": "note_orderedlist",
+      "title": "ordered list",
+      "publish": true,
+      "items": [
+        "item1",
+        "item2"
+      ]
+    }
+  ],
+  "persistent_id": "9286c71e85ef1cb362c6064b0fb00f05",
+  "publish": true
+}
diff --git a/fixtures/rights_statement.json b/fixtures/rights_statement.json
new file mode 100644
index 0000000..6a5ccc6
--- /dev/null
+++ b/fixtures/rights_statement.json
@@ -0,0 +1,33 @@
+{
+    "lock_version": 0,
+    "identifier": "e5dc6d09b9fe8640c05fe3de2926868c",
+    "created_by": "admin",
+    "last_modified_by": "admin",
+    "create_time": "2020-03-19T13:07:41Z",
+    "system_mtime": "2020-03-19T13:07:41Z",
+    "user_mtime": "2020-03-19T13:07:41Z",
+    "start_date": "2020-02-01",
+    "end_date": "2090-05-06",
+    "rights_type": "copyright",
+    "status": "copyrighted",
+    "jurisdiction": "US",
+    "jsonmodel_type": "rights_statement",
+    "external_documents": [],
+    "acts": [
+        {
+            "start_date": "2020-01-01",
+            "end_date": "2090-12-31",
+            "created_by": "admin",
+            "last_modified_by": "admin",
+            "create_time": "2020-03-19T13:07:41Z",
+            "system_mtime": "2020-03-19T13:07:41Z",
+            "user_mtime": "2020-03-19T13:07:41Z",
+            "act_type": "use",
+            "restriction": "disallow",
+            "jsonmodel_type": "rights_statement_act",
+            "notes": []
+        }
+    ],
+    "linked_agents": [],
+    "notes": []
+}
diff --git a/fixtures/rights_statement_not_restricted.json b/fixtures/rights_statement_not_restricted.json
new file mode 100644
index 0000000..c818bc2
--- /dev/null
+++ b/fixtures/rights_statement_not_restricted.json
@@ -0,0 +1,48 @@
+{
+	"lock_version": 0,
+	"identifier": "7e3f88d5e63580aab2655ca3bb79352c",
+	"created_by": "admin",
+	"last_modified_by": "admin",
+	"create_time": "2020-03-17T19:37:24Z",
+	"system_mtime": "2020-03-17T19:37:24Z",
+	"user_mtime": "2020-03-17T19:37:24Z",
+	"start_date": "1994-12-30",
+	"end_date": "2200-03-10",
+	"determination_date": "2019-04-23",
+	"rights_type": "copyright",
+	"status": "copyrighted",
+	"jurisdiction": "US",
+	"jsonmodel_type": "rights_statement",
+	"external_documents": [],
+	"acts": [{
+		"start_date": "1994-12-30",
+		"end_date": "2200-03-10",
+		"created_by": "admin",
+		"last_modified_by": "admin",
+		"create_time": "2020-03-17T19:37:24Z",
+		"system_mtime": "2020-03-17T19:37:24Z",
+		"user_mtime": "2020-03-17T19:37:24Z",
+		"act_type": "publish",
+		"restriction": "allow",
+		"jsonmodel_type": "rights_statement_act",
+		"notes": [{
+			"jsonmodel_type": "note_rights_statement_act",
+			"type": "additional_information",
+			"content": [
+				"Records under copyright may not be republished without permission from the copyright holder."
+			],
+			"persistent_id": "69e17d2fcdcd977dec8593f738b66161",
+			"publish": false
+		}]
+	}],
+	"linked_agents": [],
+	"notes": [{
+		"jsonmodel_type": "note_rights_statement",
+		"type": "type_note",
+		"content": [
+			"Work for hire, under copyright until 40 years after creation."
+		],
+		"persistent_id": "fd5b4b78338b246e8e121d2309efd771",
+		"publish": false
+	}]
+}
diff --git a/rac_aspace/data_helpers.py b/rac_aspace/data_helpers.py
index df04cfb..6cce977 100644
--- a/rac_aspace/data_helpers.py
+++ b/rac_aspace/data_helpers.py
@@ -8,19 +8,15 @@ objects.
 """
 from datetime import datetime
 import re
-from asnake.jsonmodel import JSONModelObject
 from fuzzywuzzy import fuzz
 from string import Formatter
 
-from .decorators import check_type
 
-
-@check_type(JSONModelObject)
 def get_note_text(note):
     """Parses note content from different note types.
 
     Args:
-        note (JSONModelObject): an ArchivesSpace note object.
+        note (dict): an ArchivesSpace note object.
 
     Returns:
         list: a list containing note content.
@@ -29,20 +25,20 @@ def get_note_text(note):
         """Parses note content from subnotes.
 
         Args:
-            subnote (JSONModelObject): an ArchivesSpace subnote object.
+            subnote (dict): an ArchivesSpace subnote object.
 
         Returns:
             list: a list containing subnote content.
         """
         if subnote.jsonmodel_type in [
-                'note_orderedlist', 'note_definedlist', 'note_index',
-                'note_chronology']:
+                'note_orderedlist', 'note_index']:
             content = subnote.items
-        elif subnote.jsonmodel_type == 'note_bibliography':
-            data = []
-            data.append(subnote.content)
-            data.append(subnote.items)
-            content = data
+        elif subnote.jsonmodel_type in ['note_chronology', 'note_definedlist']:
+            content = []
+            for k in subnote.items:
+                for i in k:
+                    content += k.get(i) if isinstance(k.get(i),
+                                                      list) else [k.get(i)]
         else:
             content = subnote.content if isinstance(
                 subnote.content, list) else [subnote.content]
@@ -50,8 +46,16 @@ def get_note_text(note):
 
     if note.jsonmodel_type == "note_singlepart":
         content = note.content
+    elif note.jsonmodel_type == 'note_bibliography':
+        data = []
+        data += note.content
+        data += note.items
+        content = data
     elif note.jsonmodel_type == "note_index":
-        content = note.items
+        data = []
+        for item in note.items:
+            data.append(item.value)
+        content = data
     else:
         subnote_content_list = list(parse_subnote(sn) for sn in note.subnotes)
         content = [
@@ -59,12 +63,11 @@ def get_note_text(note):
     return content
 
 
-@check_type(JSONModelObject)
 def text_in_note(note, query_string):
     """Performs fuzzy searching against note text.
 
     Args:
-        note (JSONModelObject): an ArchivesSpace note object.
+        note (dict): an ArchivesSpace note object.
         query_string (str): a string to match against.
 
     Returns:
@@ -79,12 +82,11 @@ def text_in_note(note, query_string):
     return (True if ratio > CONFIDENCE_RATIO else False)
 
 
-@check_type(JSONModelObject)
 def object_locations(archival_object):
     """Finds locations associated with an archival object.
 
     Args:
-        archival_object (JSONModelObject): an ArchivesSpace archival_object.
+        archival_object (dict): an ArchivesSpace archival_object.
 
     Returns:
         list: Locations objects associated with the archival object.
@@ -96,12 +98,12 @@ def object_locations(archival_object):
     return locations
 
 
-@check_type(JSONModelObject)
 def format_from_obj(obj, format_string):
     """Generates a human-readable string from an object.
 
     Args:
         location (dict): an ArchivesSpace object.
+        string_template (dict): an (optional) Python string template
 
     Returns:
         str: a string in the chosen format
@@ -121,28 +123,27 @@ def format_from_obj(obj, format_string):
                     str(e)))
 
 
-@check_type(JSONModelObject)
 def format_resource_id(resource, separator=":"):
     """Concatenates the four-part ID for a resource record.
 
     Args:
-        resource (JSONModelObject): an ArchivesSpace resource object.
+        resource (dict): an ArchivesSpace resource object.
         separator (str): a separator to insert between the id parts. Defaults
             to `:`.
 
     Returns:
         str: a concatenated four-part ID for the resource record.
     """
+    resource_json = resource.json()
     resource_id = []
     for x in range(4):
         try:
-            resource_id.append(getattr(resource, "id_{0}".format(x)))
-        except AttributeError:
+            resource_id.append(resource_json["id_{0}".format(x)])
+        except KeyError:
             break
     return separator.join(resource_id)
 
 
-@check_type(JSONModelObject)
 def closest_value(archival_object, key):
     """Finds the closest value matching a key.
 
@@ -150,7 +151,7 @@ def closest_value(archival_object, key):
     until it finds a match for a key that is not empty or null.
 
     Args:
-        archival_object (JSONModelObject): an ArchivesSpace archival_object
+        archival_object (dict): an ArchivesSpace archival_object
         key (str): the key to match against.
 
     Returns:
@@ -178,14 +179,13 @@ def get_orphans(object_list, null_attribute):
             yield obj
 
 
-@check_type(JSONModelObject)
 def get_expression(date):
     """Returns a date expression for a date object.
 
     Concatenates start and end dates if no date expression exists.
 
     Args:
-        date (JSONModelObject): an ArchivesSpace date object
+        date (obj): an ArchivesSpace date object
 
     Returns:
         str: a date expression for the date object.
@@ -201,12 +201,11 @@ def get_expression(date):
     return expression
 
 
-@check_type(JSONModelObject)
 def indicates_restriction(rights_statement):
     """Parses a rights statement to determine if it indicates a restriction.
 
     Args:
-        rights_statement (JSONModelObject): an ArchivesSpace rights statement.
+        rights_statement (dict): an ArchivesSpace rights statement.
 
     Returns:
         bool: True if rights statement indicates a restriction, False if not.
@@ -227,7 +226,6 @@ def indicates_restriction(rights_statement):
     return False
 
 
-@check_type(JSONModelObject)
 def is_restricted(archival_object):
     """Parses an archival object to determine if it is restricted.
 
@@ -237,7 +235,7 @@ def is_restricted(archival_object):
     restricted.
 
     Args:
-        archival_object (JSONModelObject): an ArchivesSpace archival_object.
+        archival_object (dict): an ArchivesSpace archival_object.
 
     Returns:
         bool: True if archival object is restricted, False if not.
@@ -253,7 +251,6 @@ def is_restricted(archival_object):
     return False
 
 
-@check_type(str)
 def strip_html_tags(string):
     """Strips HTML tags from a string.
 
diff --git a/rac_aspace/decorators.py b/rac_aspace/decorators.py
deleted file mode 100644
index 26981cd..0000000
--- a/rac_aspace/decorators.py
+++ /dev/null
@@ -1,8 +0,0 @@
-def check_type(obj_type):
-    def real_decorator(func):
-        def wrapper(*args, **kwargs):
-            if not isinstance(args[0], obj_type):
-                raise TypeError("{} is not a {}".format(args[0], obj_type))
-            return func(*args, **kwargs)
-        return wrapper
-    return real_decorator
diff --git a/tox.ini b/tox.ini
index 0595d4b..7a3843e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -6,8 +6,11 @@ skipsdist = True
 deps =
 	py34,py35: -rrequirements/test-python34-35.txt
 	py36,py37: -rrequirements/test.txt
+	coverage
 skip_install = True
-commands = pytest
+commands =
+	coverage run -m --source=./rac_aspace pytest
+	coverage report -m
 
 [testenv:linting]
 basepython = python3
@@ -28,4 +31,4 @@ ignore =
 		# E203 Ignores Whitespace before ':'
 		# E266 Too many leading '#' for block comment
 		# W503 Line break occurred before a binary operator, or W504 Line break occurred after a binary operator
-		# F403 'from module import *' used; unable to detect undefined names
\ No newline at end of file
+		# F403 'from module import *' used; unable to detect undefined names


Test patch:
diff --git a/tests/test_data_helpers.py b/tests/test_data_helpers.py
index 835bb69..36842b3 100644
--- a/tests/test_data_helpers.py
+++ b/tests/test_data_helpers.py
@@ -31,10 +31,24 @@ class TestDataHelpers(unittest.TestCase):
 
     def test_get_note_text(self):
         """Checks whether the returned note text matches the selected query string."""
-        note = self.obj_from_fixture("note_multi.json")
-        result = data_helpers.get_note_text(note)
-        self.assertTrue(result, list)
-        self.assertEqual(result, ["materials are restricted"])
+        for fixture, expected in [
+                ("note_bibliography.json", [
+                    "bibliography", "item 1", "item 2"]),
+                ("note_index.json", ["title1", "title2"]),
+                ("note_multi.json", ["materials are restricted"]),
+                ("note_multi_chronology.json", [
+                    "general note with chronology", "date", "event1", "event2"]),
+                ("note_multi_defined.json", [
+                    "bioghist with defined list", "item", "1", "item", "2"]),
+                ("note_multi_ordered.json", [
+                    "Bioghist with ordered list", "item1", "item2"]),
+                ("note_single.json", ["New York Mets"])]:
+            note = self.obj_from_fixture(fixture)
+            result = data_helpers.get_note_text(note)
+            self.assertTrue(result, list)
+            self.assertEqual(
+                set(result), set(expected),
+                "{} returned {}, expecting {}".format(fixture, result, expected))
 
     def test_text_in_note(self):
         """Checks whether the query string and note content are close to a match."""
@@ -57,11 +71,16 @@ class TestDataHelpers(unittest.TestCase):
 
     def test_format_resource_id(self):
         """Checks whether the function returns a concatenated string as expected."""
-        separator = ":"
-        resource = self.obj_from_fixture("archival_object.json")
-        result = data_helpers.format_resource_id(resource, separator)
-        self.assertIsInstance(result, str)
-        self.assertEqual(result, '1:2:3:4')
+        for fixture, formatted, separator in [
+                ("archival_object.json", "1;2;3;4", ';'),
+                ("archival_object_2.json", "1:2:3", None)]:
+            resource = self.obj_from_fixture(fixture)
+            if not separator:
+                result = data_helpers.format_resource_id(resource)
+            else:
+                result = data_helpers.format_resource_id(resource, separator)
+            self.assertIsInstance(result, str)
+            self.assertEqual(result, formatted)
 
     def test_closest_value(self):
         with rac_vcr.use_cassette("test_closest_value.json"):
@@ -83,7 +102,9 @@ class TestDataHelpers(unittest.TestCase):
 
     def test_get_expression(self):
         """Tests whether the date expression function works as intended."""
-        files = ['date_expression.json', 'date_no_expression.json']
+        files = ['date_expression.json',
+                 'date_no_expression.json',
+                 'date_no_expression_no_end.json']
         for f in files:
             date = self.obj_from_fixture(f)
             result = data_helpers.get_expression(date)
@@ -94,7 +115,8 @@ class TestDataHelpers(unittest.TestCase):
         for fixture, outcome in [
                 ("rights_statement_restricted.json", True),
                 ("rights_statement_open.json", False),
-                ("rights_statement_conditional.json", True)]:
+                ("rights_statement_conditional.json", True),
+                ("rights_statement_not_restricted.json", False)]:
             statement = self.obj_from_fixture(fixture)
             status = data_helpers.indicates_restriction(statement)
             self.assertEqual(
@@ -104,12 +126,14 @@ class TestDataHelpers(unittest.TestCase):
 
     def test_is_restricted(self):
         """Tests whether the function can find restrictions in an AS archival object."""
-        archival_object = self.obj_from_fixture("archival_object.json")
-        result = data_helpers.is_restricted(archival_object)
-        self.assertEqual(result, True)
-        """
-        Cannot currently test the restrictions portion because data helper is unwritten
-        """
+        for fixture, outcome in [
+            ("archival_object.json", True),
+            ("archival_object_2.json", True),
+            ("archival_object_3.json", False)
+        ]:
+            archival_object = self.obj_from_fixture(fixture)
+            result = data_helpers.is_restricted(archival_object)
+            self.assertEqual(result, outcome)
 
     def test_strip_html_tags(self):
         """Ensures HTML tags are correctly removed from strings."""
@@ -122,14 +146,27 @@ class TestDataHelpers(unittest.TestCase):
 
     def test_format_from_obj(self):
         """Test that format strings can be passed to objects as expected."""
-        date = self.obj_from_fixture("date_expression.json")
-        formatted = data_helpers.format_from_obj(
-            date, "{begin} - {end} ({expression})")
-        self.assertEqual(formatted, "1905 - 1980 (1905-1980)")
-        with self.assertRaises(KeyError) as excpt:
-            formatted = data_helpers.format_from_obj(
-                date, "{start} - {end} ({expression})")
-        self.assertIn("was not found in this object", str(excpt.exception))
+        for fixture, format_string in [
+            ("date_expression.json", "{begin} - {end} ({expression})"),
+            ("date_expression.json", None),
+        ]:
+            date = self.obj_from_fixture(fixture)
+            if not format_string:
+                with self.assertRaises(Exception) as excpt:
+                    data_helpers.format_from_obj(date, format_string)
+                self.assertEqual(
+                    "No format string provided.", str(
+                        excpt.exception))
+            else:
+                formatted = data_helpers.format_from_obj(
+                    date, format_string)
+                self.assertEqual(formatted, "1905 - 1980 (1905-1980)")
+                with self.assertRaises(KeyError) as excpt:
+                    formatted = data_helpers.format_from_obj(
+                        date, "{start} - {end} ({expression})")
+                self.assertIn(
+                    "was not found in this object", str(
+                        excpt.exception))
 
 
 if __name__ == '__main__':