diff --git a/stats/dashboard.py b/stats/dashboard.py
index 8e16cf917b2..6cc2019201d 100644
--- a/stats/dashboard.py
+++ b/stats/dashboard.py
@@ -1242,8 +1242,17 @@ def humanitarian(self):
return {
'is_humanitarian': is_humanitarian,
'is_humanitarian_by_attrib': is_humanitarian_by_attrib,
- 'contains_humanitarian_scope': 1 if (self._version() in ['2.02', '2.03']) and self.element.xpath('humanitarian-scope/@type') and self.element.xpath('humanitarian-scope/@code') else 0,
- 'uses_humanitarian_clusters_vocab': 1 if (self._version() in ['2.02', '2.03']) and self.element.xpath('sector/@vocabulary="10"') else 0
+ 'contains_humanitarian_scope': 1 if (
+ is_humanitarian and
+ self._version() in ['2.02', '2.03'] and
+ all_true_and_not_empty(self.element.xpath('humanitarian-scope/@type')) and
+ all_true_and_not_empty(self.element.xpath('humanitarian-scope/@code'))
+ ) else 0,
+ 'uses_humanitarian_clusters_vocab': 1 if (
+ is_humanitarian and
+ self._version() in ['2.02', '2.03'] and
+ self.element.xpath('sector/@vocabulary="10"')
+ ) else 0
}
def _transaction_type_code(self, transaction):
diff --git a/stats/tests/test_humanitarian.py b/stats/tests/test_humanitarian.py
index ceb3936b08c..fbb0c33b26e 100644
--- a/stats/tests/test_humanitarian.py
+++ b/stats/tests/test_humanitarian.py
@@ -569,14 +569,14 @@ def test_humanitarian_attrib_false_sector_false(version, hum_attrib_val_true, hu
@pytest.mark.parametrize('hum_attrib_val', ['1', 'true'])
def test_humanitarian_elements_valid_version(version, hum_attrib_val):
"""
- Tests that humanitarian elements are detected at supported versions.
+ Detect that an activity containing a humanitarian-scope element (with required non-empty attributes) counts as humanitarian.
"""
activity_stats = MockActivityStats(version)
activity_stats.element = etree.fromstring('''
-
+
'''.format(hum_attrib_val))
@@ -597,7 +597,7 @@ def test_humanitarian_elements_invalid_version(version, hum_attrib_val):
activity_stats.element = etree.fromstring('''
-
+
'''.format(version, hum_attrib_val))
@@ -608,77 +608,160 @@ def test_humanitarian_elements_invalid_version(version, hum_attrib_val):
@pytest.mark.parametrize('version', ['2.02', '2.03'])
-def test_humanitarian_scope_valid(version):
+@pytest.mark.parametrize('hum_attrib_val', ['1', 'true'])
+def test_humanitarian_scope_invalid(version, hum_attrib_val):
"""
- Detect that an activity contains a humanitarian-scope element and required attributes.
+ Detect that even if an activity (at an expected version) contains a humanitarian-scope element, it must include the required attributes to count as humanitarian.
"""
activity_stats = MockActivityStats(version)
activity_stats.element = etree.fromstring('''
-
-
+
+
- ''')
- assert activity_stats.humanitarian()['contains_humanitarian_scope'] == 1
+ '''.format(hum_attrib_val))
+ assert activity_stats.humanitarian()['is_humanitarian'] == 1
+ assert activity_stats.humanitarian()['contains_humanitarian_scope'] == 0
@pytest.mark.parametrize('version', ['2.02', '2.03'])
-def test_humanitarian_scope_invalid(version):
+@pytest.mark.parametrize('hum_attrib_val', ['1', 'true'])
+def test_humanitarian_scope_invalid_empty_values(version, hum_attrib_val):
"""
- Detect that an activity contains a humanitarian-scope element without required attributes.
+ Detect that even if the humanitarian-scope (at an expected version) element is present (with required attributes), there must be non-empty data within the @type and @code attributes for it to count as humanitarian.
"""
activity_stats = MockActivityStats(version)
activity_stats.element = etree.fromstring('''
-
-
+
+
+ '''.format(hum_attrib_val))
+ assert activity_stats.humanitarian()['is_humanitarian'] == 1
+ assert activity_stats.humanitarian()['contains_humanitarian_scope'] == 0
+
+
+@pytest.mark.parametrize('version', ['1.01', '1.02', '1.03', '1.04', '1.05', '2.01', '2.02', '2.03', 'unknown version'])
+def test_humanitarian_scope_but_not_humanitarian_no_attrib(version):
+ """
+ Detect that even if an activity (of any version) contains the humanitarian-scope element, the humanitarian attribute must be present and marked as true to count.
+ """
+
+ activity_stats = MockActivityStats(version)
+
+ activity_stats.element = etree.fromstring('''
+
+
+
''')
+
+ assert activity_stats.humanitarian()['is_humanitarian'] == 0
+ assert activity_stats.humanitarian()['is_humanitarian_by_attrib'] == 0
+ assert activity_stats.humanitarian()['contains_humanitarian_scope'] == 0
+ assert activity_stats.humanitarian()['uses_humanitarian_clusters_vocab'] == 0
+
+
+@pytest.mark.parametrize('version', ['1.01', '1.02', '1.03', '1.04', '1.05', '2.01', '2.02', '2.03', 'unknown version'])
+@pytest.mark.parametrize('hum_attrib_val_false', ['0', 'false', 'True', 'False', ''])
+def test_humanitarian_scope_but_humanitarian_is_false(version, hum_attrib_val_false):
+ """
+ Detect that even if an activity (at any version) contains a humanitarian-scope element, the humanitarian attribute must be present and marked as true to count.
+ """
+
+ activity_stats = MockActivityStats(version)
+
+ activity_stats.element = etree.fromstring('''
+
+
+
+ '''.format(hum_attrib_val_false))
+
+ assert activity_stats.humanitarian()['is_humanitarian'] == 0
+ assert activity_stats.humanitarian()['is_humanitarian_by_attrib'] == 0
assert activity_stats.humanitarian()['contains_humanitarian_scope'] == 0
+ assert activity_stats.humanitarian()['uses_humanitarian_clusters_vocab'] == 0
@pytest.mark.parametrize('version', ['2.02', '2.03'])
-def test_humanitarian_clusters_valid(version):
+@pytest.mark.parametrize('hum_attrib_val', ['1', 'true'])
+def test_humanitarian_clusters_valid(version, hum_attrib_val):
"""
Detect that an activity contains a sector defined by the 'Humanitarian Global Clusters' sector vocabulary.
"""
activity_stats = MockActivityStats(version)
+ activity_stats.element = etree.fromstring('''
+
+
+
+ '''.format(hum_attrib_val))
+ assert activity_stats.humanitarian()['is_humanitarian'] == 1
+ assert activity_stats.humanitarian()['uses_humanitarian_clusters_vocab'] == 1
+
+
+@pytest.mark.parametrize('version', ['2.02', '2.03'])
+def test_humanitarian_clusters_invalid_no_attrib(version):
+ """
+ Detect that even if an activity contains a sector defined by the 'Humanitarian Global Clusters' sector vocabulary, the humanitarian attribute must be present and marked as true to count.
+ """
+ activity_stats = MockActivityStats(version)
+
activity_stats.element = etree.fromstring('''
''')
- assert activity_stats.humanitarian()['uses_humanitarian_clusters_vocab'] == 1
+ assert activity_stats.humanitarian()['is_humanitarian'] == 0
+ assert activity_stats.humanitarian()['uses_humanitarian_clusters_vocab'] == 0
+
+
+@pytest.mark.parametrize('version', ['2.02', '2.03'])
+@pytest.mark.parametrize('hum_attrib_val_false', ['0', 'false', 'True', 'False', ''])
+def test_humanitarian_clusters_invalid_humanitarian_is_false(version, hum_attrib_val_false):
+ """
+ Detect that even if an activity contains a sector defined by the 'Humanitarian Global Clusters' sector vocabulary, the humanitarian attribute must be present and marked as true to count.
+ """
+ activity_stats = MockActivityStats(version)
+
+ activity_stats.element = etree.fromstring('''
+
+
+
+ '''.format(hum_attrib_val_false))
+ assert activity_stats.humanitarian()['is_humanitarian'] == 0
+ assert activity_stats.humanitarian()['uses_humanitarian_clusters_vocab'] == 0
@pytest.mark.parametrize('version', ['1.01', '1.02', '1.03', '1.04', '1.05', '2.01', 'unknown version'])
-def test_humanitarian_clusters_version_1(version):
+@pytest.mark.parametrize('hum_attrib_val', ['1', 'true'])
+def test_humanitarian_clusters_version_1(version, hum_attrib_val):
"""
Detect that a pre-2.02 activity containing a sector defined by the 'Humanitarian Global Clusters' sector vocabulary is not detected.
"""
activity_stats = MockActivityStats(version)
activity_stats.element = etree.fromstring('''
-
+
- ''')
+ '''.format(hum_attrib_val))
+ assert activity_stats.humanitarian()['is_humanitarian'] == 0
assert activity_stats.humanitarian()['uses_humanitarian_clusters_vocab'] == 0
@pytest.mark.parametrize('version', ['1.01', '1.02', '1.03', '1.04', '1.05', '2.01', '2.02', '2.03', 'unknown version'])
+@pytest.mark.parametrize('hum_attrib_val', ['1', 'true'])
@pytest.mark.parametrize('sector_vocabulary_code', ['', '1', 'internal vocabulary'])
-def test_humanitarian_clusters_invalid(version, sector_vocabulary_code):
+def test_humanitarian_clusters_invalid(version, hum_attrib_val,
+ sector_vocabulary_code):
"""
Detect that an activity does not contain a sector defined by the 'Humanitarian Global Clusters' sector vocabulary.
"""
activity_stats = MockActivityStats(version)
activity_stats.element = etree.fromstring('''
-
-
+
+
- '''.format(sector_vocabulary_code))
+ '''.format(hum_attrib_val, sector_vocabulary_code))
assert activity_stats.humanitarian()['uses_humanitarian_clusters_vocab'] == 0
-