From 81e30bd4dc809cb39b7063316c0f1466940234f6 Mon Sep 17 00:00:00 2001 From: David Read Date: Fri, 9 Aug 2019 16:56:02 +0100 Subject: [PATCH] Add lots of tests for changes.py. A few fail, to provoke improvements to changes.py --- ckan/lib/changes.py | 42 +- ckan/lib/helpers.py | 8 +- ckan/logic/action/patch.py | 1 + .../snippets/changes/resource_format.html | 14 +- ckan/tests/lib/test_changes.py | 694 ++++++++++++++++++ 5 files changed, 728 insertions(+), 31 deletions(-) create mode 100644 ckan/tests/lib/test_changes.py diff --git a/ckan/lib/changes.py b/ckan/lib/changes.py index dea71ddae12..fa4c50023ad 100644 --- a/ckan/lib/changes.py +++ b/ckan/lib/changes.py @@ -1,10 +1,10 @@ # encoding: utf-8 ''' -Functions used by the helper function compare_pkg_dicts() to analyze -the differences between two versions of a dataset. +Functions for generating a list of differences between two versions of a +dataset ''' -from helpers import url_for + import logging log = logging.getLogger(__name__) @@ -40,14 +40,14 @@ def _extras_to_dict(extras_list): return ret_dict -def _check_resource_changes(change_list, original, new, new_pkg, - old_activity_id): +def check_resource_changes(change_list, original, new, new_pkg, + old_activity_id): ''' - Checks whether a dataset's resources have changed - whether new ones have - been uploaded, existing ones have been deleted, or existing ones have - been edited. For existing resources, checks whether their names, formats, - and/or descriptions have changed, as well as whether a new file has been - uploaded for the resource. + Compares two versions of a dataset and records the changes between them + (just the resources) in change_list. e.g. resources that are added, changed + or deleted. For existing resources, checks whether their names, formats, + and/or descriptions have changed, as well as whether the url changed (e.g. + a new file has been uploaded for the resource). ''' # make a set of the resource IDs present in original and new @@ -55,7 +55,6 @@ def _check_resource_changes(change_list, original, new, new_pkg, original_resource_dict = {} new_resource_set = set() new_resource_dict = {} - s = u"" for resource in original['resources']: original_resource_set.add(resource['id']) @@ -126,7 +125,8 @@ def _check_resource_changes(change_list, original, new, new_pkg, u'resource_id': resource_id, u'resource_name': new_resource_dict[resource_id]['name'], - u'org_id': new['organization']['id'], + u'org_id': new['organization']['id'] + if new['organization'] else u'', u'format': new_metadata['format']}) # if both versions have a format but the format changed @@ -138,7 +138,8 @@ def _check_resource_changes(change_list, original, new, new_pkg, u'resource_id': resource_id, u'resource_name': new_resource_dict[resource_id]['name'], - u'org_id': new['organization']['id'], + u'org_id': new['organization']['id'] + if new['organization'] else u'', u'old_format': original_metadata['format'], u'new_format': new_metadata['format']}) @@ -177,7 +178,7 @@ def _check_resource_changes(change_list, original, new, new_pkg, u'new_desc': new_metadata['description'], u'old_desc': original_metadata['description']}) - # check if the user uploaded a new file + # check if the url changes (e.g. user uploaded a new file) # TODO: use regular expressions to determine the actual name of the # new and old files if original_metadata['url'] != new_metadata['url']: @@ -189,12 +190,10 @@ def _check_resource_changes(change_list, original, new, new_pkg, new_resource_dict[resource_id]['name']}) -def _check_metadata_changes(change_list, original, new, new_pkg): +def check_metadata_changes(change_list, original, new, new_pkg): ''' - Checks whether a dataset's metadata fields (fields in its package - dictionary not including resources) have changed between two consecutive - versions and puts a list of formatted summaries of these changes in - change_list. + Compares two versions of a dataset and records the changes between them + (excluding resources) in change_list. ''' # if the title has changed if original['title'] != new['title']: @@ -280,7 +279,9 @@ def _org_change(change_list, original, new, new_pkg): Appends a summary of a change to a dataset's organization between two versions (original and new) to change_list. ''' - change_list.append({u'type': u'org', u'pkg_id': new_pkg['pkg_id'], + change_list.append({u'type': u'org', + u'method': u'change', + u'pkg_id': new_pkg['pkg_id'], u'title': new_pkg['title'], u'original_org_id': original['organization']['id'], u'original_org_title': @@ -578,7 +579,6 @@ def _extra_fields(change_list, original, new, new_pkg): from the web interface (or API?) and appends a summary of each change to change_list. ''' - s = u"" if u'extras' in new: extra_fields_new = _extras_to_dict(new['extras']) extra_new_set = set(extra_fields_new.keys()) diff --git a/ckan/lib/helpers.py b/ckan/lib/helpers.py index 915f74aff40..1cf4e3a427c 100644 --- a/ckan/lib/helpers.py +++ b/ckan/lib/helpers.py @@ -2706,7 +2706,7 @@ def compare_pkg_dicts(original, new, old_activity_id): string indicating the type of change made as well as other data necessary to form a detailed summary of the change. ''' - from changes import _check_metadata_changes, _check_resource_changes + from changes import check_metadata_changes, check_resource_changes change_list = [] new_pkg = { @@ -2715,10 +2715,10 @@ def compare_pkg_dicts(original, new, old_activity_id): u'title': new['title'] } - _check_metadata_changes(change_list, original, new, new_pkg) + check_metadata_changes(change_list, original, new, new_pkg) - _check_resource_changes(change_list, original, new, new_pkg, - old_activity_id) + check_resource_changes(change_list, original, new, new_pkg, + old_activity_id) # if the dataset was updated but none of the fields we check were changed, # display a message stating that diff --git a/ckan/logic/action/patch.py b/ckan/logic/action/patch.py index f5150f58b7e..4a4e137893a 100644 --- a/ckan/logic/action/patch.py +++ b/ckan/logic/action/patch.py @@ -38,6 +38,7 @@ def package_patch(context, data_dict): 'session': context['session'], 'user': context['user'], 'auth_user_obj': context['auth_user_obj'], + 'ignore_auth': context.get('ignore_auth', False), } package_dict = _get_action('package_show')( diff --git a/ckan/templates/snippets/changes/resource_format.html b/ckan/templates/snippets/changes/resource_format.html index 2224dada9b2..8a242e39329 100644 --- a/ckan/templates/snippets/changes/resource_format.html +++ b/ckan/templates/snippets/changes/resource_format.html @@ -1,5 +1,10 @@
  • + {% set format_search_base_url = ( + h.url_for(controller="organization", action="read", id=ah.org_id) + if ah.org_id else + h.url_for(controller="dataset", action="search")) %} + {% if ah.method == "add" %} {{ _('Set format of resource {resource_name} to {format} in @@ -9,8 +14,7 @@ resource_url = h.url_for(controller='resource', action='read', id=ah.pkg_id, resource_id=ah.resource_id), resource_name = ah.resource_name, - format_url = h.url_for(controller="organization", action="read", - id=ah.org_id) + "?res_format=" + ah.format, + format_url = format_search_base_url + "?res_format=" + ah.format, format = ah.format )|safe }} {% elif ah.method == "change" %} @@ -23,11 +27,9 @@ resource_url = h.url_for(controller='resource', action='read', id=ah.pkg_id, resource_id=ah.resource_id), resource_name = ah.resource_name, - new_format_url = h.url_for(controller="organization", action="read", - id=ah.org_id) + "?res_format=" + ah.new_format, + new_format_url = format_search_base_url + "?res_format=" + ah.new_format, new_format = ah.new_format, - old_format_url = h.url_for(controller="organization", action="read", - id=ah.org_id) + "?res_format=" + ah.old_format, + old_format_url = format_search_base_url + "?res_format=" + ah.old_format, old_format = ah.old_format )|safe }} {% else %} diff --git a/ckan/tests/lib/test_changes.py b/ckan/tests/lib/test_changes.py new file mode 100644 index 00000000000..0c8963da39f --- /dev/null +++ b/ckan/tests/lib/test_changes.py @@ -0,0 +1,694 @@ +import copy + +from nose.tools import assert_equal as eq + +from ckan.lib.changes import check_metadata_changes, check_resource_changes +from ckan.tests import helpers +from ckan.tests.factories import Dataset, Organization, Group + + +def _new_pkg(new): + return { + u'pkg_id': new['id'], + u'name': new['name'], + u'title': new['title'] + } + + +class TestCheckMetadataChanges(object): + + def setup(self): + helpers.reset_db() + + def test_title(self): + changes = [] + original = Dataset() + new = helpers.call_action(u'package_patch', id=original['id'], + title=u'New title') + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'title') + eq(changes[0]['original_title'], u'Test Dataset') + eq(changes[0]['new_title'], u'New title') + + def test_name(self): + changes = [] + original = Dataset() + new = helpers.call_action(u'package_patch', id=original['id'], + name=u'new-name') + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'name') + eq(changes[0]['old_name'], original['name']) + eq(changes[0]['new_name'], u'new-name') + + def test_add_extra(self): + changes = [] + original = Dataset() + new = helpers.call_action( + u'package_patch', id=original['id'], + extras=[{u'key': u'subject', u'value': u'science'}]) + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'custom_fields') + eq(changes[0]['method'], u'add1') + eq(changes[0]['field_name'], u'subject') + eq(changes[0]['field_val'], u'science') + + # TODO how to test 'add2'? + + def test_add_multiple_extras(self): + changes = [] + original = Dataset() + new = helpers.call_action( + u'package_patch', id=original['id'], + extras=[{u'key': u'subject', u'value': u'science'}, + {u'key': u'topic', u'value': u'wind'}]) + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'custom_fields') + eq(changes[0]['method'], u'add3') + eq(set(changes[0]['fields']), set([u'subject', u'topic'])) + + def test_change_extra(self): + changes = [] + original = Dataset( + extras=[{u'key': u'subject', u'value': u'science'}, + {u'key': u'topic', u'value': u'wind'}]) + new = helpers.call_action( + u'package_patch', id=original['id'], + extras=[{u'key': u'subject', u'value': u'scientific'}, + {u'key': u'topic', u'value': u'wind'}]) + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'custom_fields') + eq(changes[0]['method'], u'change1') + eq(changes[0]['field_name'], u'subject') + eq(changes[0]['field_val_old'], u'science') + eq(changes[0]['field_val_new'], u'scientific') + + def test_change_multiple_extras(self): + changes = [] + original = Dataset( + extras=[{u'key': u'subject', u'value': u'science'}, + {u'key': u'topic', u'value': u'wind'}]) + new = helpers.call_action( + u'package_patch', id=original['id'], + extras=[{u'key': u'subject', u'value': u'scientific'}, + {u'key': u'topic', u'value': u'rain'}]) + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + assert len(changes) == 2, changes + for change in changes: + eq(change['type'], u'custom_fields') + eq(change['method'], u'change1') + if change['field_name'] == u'subject': + eq(change['field_val_new'], u'scientific') + else: + eq(changes[0]['field_name'], u'topic') + eq(change['field_val_new'], u'rain') + + # TODO how to test change2? + + def test_delete_extra(self): + changes = [] + original = Dataset( + extras=[{u'key': u'subject', u'value': u'science'}, + {u'key': u'topic', u'value': u'wind'}]) + new = helpers.call_action( + u'package_patch', id=original['id'], + extras=[{u'key': u'topic', u'value': u'wind'}]) + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'custom_fields') + eq(changes[0]['method'], u'remove1') + eq(changes[0]['field_name'], u'subject') + + def test_delete_multiple_extras(self): + changes = [] + original = Dataset( + extras=[{u'key': u'subject', u'value': u'science'}, + {u'key': u'topic', u'value': u'wind'}, + {u'key': u'geography', u'value': u'global'}]) + new = helpers.call_action( + u'package_patch', id=original['id'], + extras=[{u'key': u'topic', u'value': u'wind'}]) + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'custom_fields') + eq(changes[0]['method'], u'remove2') + eq(set(changes[0]['fields']), set((u'subject', u'geography'))) + + def test_add_maintainer(self): + changes = [] + original = Dataset() + new = helpers.call_action( + u'package_patch', id=original['id'], + maintainer=u'new maintainer') + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + eq(changes[0]['type'], u'maintainer') + eq(changes[0]['method'], u'add') + eq(changes[0]['new_maintainer'], u'new maintainer') + + def test_change_maintainer(self): + changes = [] + original = Dataset(maintainer=u'first maintainer') + new = helpers.call_action( + u'package_patch', id=original['id'], + maintainer=u'new maintainer') + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + eq(changes[0]['type'], u'maintainer') + eq(changes[0]['method'], u'change') + eq(changes[0]['old_maintainer'], u'first maintainer') + eq(changes[0]['new_maintainer'], u'new maintainer') + + def test_remove_maintainer(self): + changes = [] + original = Dataset(maintainer=u'first maintainer') + new = helpers.call_action( + u'package_patch', id=original['id'], + maintainer=u'') + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + eq(changes[0]['type'], u'maintainer') + eq(changes[0]['method'], u'remove') + + def test_add_notes(self): + changes = [] + original = Dataset(notes=u'') + new = helpers.call_action( + u'package_patch', id=original['id'], + notes=u'new notes') + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + eq(changes[0]['type'], u'description') + eq(changes[0]['method'], u'add') + eq(changes[0]['new_desc'], u'new notes') + + def test_change_notes(self): + changes = [] + original = Dataset(notes=u'first notes') + new = helpers.call_action( + u'package_patch', id=original['id'], + notes=u'new notes') + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + eq(changes[0]['type'], u'description') + eq(changes[0]['method'], u'change') + eq(changes[0]['old_desc'], u'first notes') + eq(changes[0]['new_desc'], u'new notes') + + def test_remove_notes(self): + changes = [] + original = Dataset(notes=u'first notes') + new = helpers.call_action( + u'package_patch', id=original['id'], + notes=u'') + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + eq(changes[0]['type'], u'description') + eq(changes[0]['method'], u'remove') + + @helpers.change_config(u'ckan.auth.create_unowned_dataset', True) + def test_add_org(self): + changes = [] + original = Dataset(owner_org=None) + new_org = Organization() + new = helpers.call_action( + u'package_patch', id=original['id'], + owner_org=new_org['id']) + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + eq(changes[0]['type'], u'org') + eq(changes[0]['method'], u'add') + eq(changes[0]['new_org_id'], new_org['id']) + + def test_change_org(self): + changes = [] + old_org = Organization() + original = Dataset(owner_org=old_org['id']) + new_org = Organization() + new = helpers.call_action( + u'package_patch', id=original['id'], + owner_org=new_org['id']) + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + eq(changes[0]['type'], u'org') + eq(changes[0]['method'], u'change') + eq(changes[0]['original_org_id'], original['organization']['id']) + eq(changes[0]['new_org_id'], new_org['id']) + + @helpers.change_config(u'ckan.auth.create_unowned_dataset', True) + def test_remove_org(self): + changes = [] + old_org = Organization() + original = Dataset(owner_org=old_org['id']) + new = helpers.call_action( + u'package_patch', id=original['id'], + owner_org=None) + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + eq(changes[0]['type'], u'org') + eq(changes[0]['method'], u'remove') + + def test_make_private(self): + changes = [] + old_org = Organization() + original = Dataset(owner_org=old_org['id'], private=False) + new = helpers.call_action(u'package_patch', id=original['id'], + private=True) + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'private') + eq(changes[0]['new'], u'Private') + + def test_make_public(self): + changes = [] + old_org = Organization() + original = Dataset(owner_org=old_org['id'], private=True) + new = helpers.call_action(u'package_patch', id=original['id'], + private=False) + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'private') + eq(changes[0]['new'], u'Public') + + def test_add_tag(self): + changes = [] + original = Dataset(tags=[{u'name': u'rivers'}]) + new = helpers.call_action(u'package_patch', id=original['id'], + tags=[{u'name': u'rivers'}, + {u'name': u'oceans'}]) + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'tags') + eq(changes[0]['method'], u'add1') + eq(changes[0]['tag'], u'oceans') + + def test_add_multiple_tags(self): + changes = [] + original = Dataset(tags=[{u'name': u'rivers'}]) + new = helpers.call_action(u'package_patch', id=original['id'], + tags=[{u'name': u'rivers'}, + {u'name': u'oceans'}, + {u'name': u'streams'}]) + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'tags') + eq(changes[0]['method'], u'add2') + eq(set(changes[0]['tags']), set((u'oceans', u'streams'))) + + def test_delete_tag(self): + changes = [] + original = Dataset(tags=[{u'name': u'rivers'}, + {u'name': u'oceans'}]) + new = helpers.call_action(u'package_patch', id=original['id'], + tags=[{u'name': u'rivers'}]) + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'tags') + eq(changes[0]['method'], u'remove1') + eq(changes[0]['tag'], u'oceans') + + def test_remove_multiple_tags(self): + changes = [] + original = Dataset(tags=[{u'name': u'rivers'}, + {u'name': u'oceans'}, + {u'name': u'streams'}]) + new = helpers.call_action(u'package_patch', id=original['id'], + tags=[{u'name': u'rivers'}]) + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'tags') + eq(changes[0]['method'], u'remove2') + eq(set(changes[0]['tags']), set((u'oceans', u'streams'))) + + def test_add_url(self): + changes = [] + original = Dataset() + new = helpers.call_action( + u'package_patch', id=original['id'], + url=u'new url') + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + eq(changes[0]['type'], u'source_url') + eq(changes[0]['method'], u'add') + eq(changes[0]['new_url'], u'new url') + + def test_change_url(self): + changes = [] + original = Dataset(url=u'first url') + new = helpers.call_action( + u'package_patch', id=original['id'], + url=u'new url') + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + eq(changes[0]['type'], u'source_url') + eq(changes[0]['method'], u'change') + eq(changes[0]['old_url'], u'first url') + eq(changes[0]['new_url'], u'new url') + + def test_remove_url(self): + changes = [] + original = Dataset(url=u'first url') + new = helpers.call_action( + u'package_patch', id=original['id'], + url=u'') + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + eq(changes[0]['type'], u'source_url') + eq(changes[0]['method'], u'remove') + + def test_add_version(self): + changes = [] + original = Dataset() + new = helpers.call_action( + u'package_patch', id=original['id'], + version=u'new version') + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + eq(changes[0]['type'], u'version') + eq(changes[0]['method'], u'add') + eq(changes[0]['new_version'], u'new version') + + def test_change_version(self): + changes = [] + original = Dataset(version=u'first version') + new = helpers.call_action( + u'package_patch', id=original['id'], + version=u'new version') + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + eq(changes[0]['type'], u'version') + eq(changes[0]['method'], u'change') + eq(changes[0]['old_version'], u'first version') + eq(changes[0]['new_version'], u'new version') + + def test_remove_version(self): + changes = [] + original = Dataset(version=u'first version') + new = helpers.call_action( + u'package_patch', id=original['id'], + version=u'') + + check_metadata_changes(changes, original, new, _new_pkg(new)) + + eq(changes[0]['type'], u'version') + eq(changes[0]['method'], u'remove') + + +class TestCheckResourceChanges(object): + + def setup(self): + helpers.reset_db() + + def test_add_resource(self): + changes = [] + original = Dataset() + new = helpers.call_action( + u'package_patch', id=original['id'], + resources=[{u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 1'}]) + + check_resource_changes(changes, original, new, _new_pkg(new), u'fake') + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'new_resource') + eq(changes[0]['resource_name'], u'Image 1') + + def test_add_multiple_resources(self): + changes = [] + original = Dataset() + new = helpers.call_action( + u'package_patch', id=original['id'], + resources=[{u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 1'}, + {u'url': u'http://example.com/image2.png', + u'format': u'png', + u'name': u'Image 2'}]) + + check_resource_changes(changes, original, new, _new_pkg(new), u'fake') + + assert len(changes) == 2, changes + eq(changes[0]['type'], u'new_resource') + eq(changes[1]['type'], u'new_resource') + if changes[0]['resource_name'] == u'Image 1': + eq(changes[1]['resource_name'], u'Image 2') + else: + eq(changes[1]['resource_name'], u'Image 1') + eq(changes[0]['resource_name'], u'Image 2') + + def test_change_resource_url(self): + changes = [] + original = Dataset( + resources=[{u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 1'}, + {u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 2'}]) + new = copy.deepcopy(original) + new['resources'][1][u'url'] = u'http://example.com/image_changed.png' + new = helpers.call_action(u'package_update', **new) + + check_resource_changes(changes, original, new, _new_pkg(new), u'fake') + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'new_file') + eq(changes[0]['resource_name'], u'Image 2') + + def test_change_resource_format(self): + changes = [] + original = Dataset( + resources=[{u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 1'}, + {u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 2'}]) + new = copy.deepcopy(original) + new['resources'][1]['format'] = u'jpg' + new = helpers.call_action(u'package_update', **new) + + check_resource_changes(changes, original, new, _new_pkg(new), u'fake') + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'resource_format') + eq(changes[0]['resource_name'], u'Image 2') + + def test_change_resource_name(self): + changes = [] + original = Dataset( + resources=[{u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 1'}, + {u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 2'}]) + new = copy.deepcopy(original) + new['resources'][1]['name'] = u'Image changed' + new = helpers.call_action(u'package_update', **new) + + check_resource_changes(changes, original, new, _new_pkg(new), u'fake') + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'resource_name') + eq(changes[0]['old_resource_name'], u'Image 2') + eq(changes[0]['new_resource_name'], u'Image changed') + + def test_change_resource_description(self): + changes = [] + original = Dataset( + resources=[{u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 1', + u'description': u'First image'}, + {u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 2', + u'description': u'Second image'}]) + new = copy.deepcopy(original) + new['resources'][1]['description'] = u'changed' + new = helpers.call_action(u'package_update', **new) + + check_resource_changes(changes, original, new, _new_pkg(new), u'fake') + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'resource_desc') + eq(changes[0]['method'], u'change') + eq(changes[0]['resource_name'], u'Image 2') + + def test_add_resource_extra(self): + changes = [] + original = Dataset( + resources=[{u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 1'}]) + new = copy.deepcopy(original) + new['resources'][0]['new key'] = u'new value' + new = helpers.call_action(u'package_update', **new) + + check_resource_changes(changes, original, new, _new_pkg(new), u'fake') + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'resource_extra') + eq(changes[0]['method'], u'add') + eq(changes[0]['key'], u'new key') + eq(changes[0]['value'], u'new value') + + def test_change_resource_extra(self): + changes = [] + original = Dataset( + resources=[{u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 1', + u'key1': u'value1'}]) + new = copy.deepcopy(original) + new['resources'][0]['key1'] = u'new value' + new = helpers.call_action(u'package_update', **new) + + check_resource_changes(changes, original, new, _new_pkg(new), u'fake') + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'resource_extra') + eq(changes[0]['method'], u'change') + eq(changes[0]['key'], u'key1') + eq(changes[0]['value_old'], u'value1') + eq(changes[0]['value_new'], u'new value') + + def test_remove_resource_extra(self): + changes = [] + original = Dataset( + resources=[{u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 1', + u'key1': u'value1'}]) + new = copy.deepcopy(original) + del new['resources'][0]['key1'] + new = helpers.call_action(u'package_update', **new) + + check_resource_changes(changes, original, new, _new_pkg(new), u'fake') + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'resource_extra') + eq(changes[0]['method'], u'remove') + eq(changes[0]['key'], u'key1') + + def test_change_multiple_resources(self): + changes = [] + original = Dataset( + resources=[{u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 1'}, + {u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 2'}, + {u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 3'}]) + new = copy.deepcopy(original) + new['resources'][0]['name'] = u'changed-1' + new['resources'][1]['name'] = u'changed-2' + new = helpers.call_action(u'package_update', **new) + + check_resource_changes(changes, original, new, _new_pkg(new), u'fake') + + assert len(changes) == 2, changes + eq(changes[0]['type'], u'resource_name') + eq(changes[1]['type'], u'resource_name') + if changes[0]['old_resource_name'] == u'Image 1': + eq(changes[0]['new_resource_name'], u'changed-1') + else: + eq(changes[0]['old_resource_name'], u'Image 2') + eq(changes[0]['new_resource_name'], u'changed-2') + + def test_delete_resource(self): + changes = [] + original = Dataset( + resources=[{u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 1'}, + {u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 2'}]) + new = copy.deepcopy(original) + del new['resources'][0] + new = helpers.call_action(u'package_update', **new) + + check_resource_changes(changes, original, new, _new_pkg(new), u'fake') + + assert len(changes) == 1, changes + eq(changes[0]['type'], u'delete_resource') + eq(changes[0]['resource_name'], u'Image 1') + + def test_delete_multiple_resources(self): + changes = [] + original = Dataset( + resources=[{u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 1'}, + {u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 2'}, + {u'url': u'http://example.com/image.png', + u'format': u'png', + u'name': u'Image 3'}]) + new = copy.deepcopy(original) + del new['resources'][1] + del new['resources'][0] + new = helpers.call_action(u'package_update', **new) + + check_resource_changes(changes, original, new, _new_pkg(new), u'fake') + + assert len(changes) == 2, changes + eq(changes[0]['type'], u'delete_resource') + if changes[0]['resource_name'] == u'Image 1': + eq(changes[1]['resource_name'], u'Image 2') + else: + eq(changes[0]['resource_name'], u'Image 2') + eq(changes[1]['resource_name'], u'Image 1')