def setup_new(self): browser = Browser(id='_chrome', slug='chrome') version = Version(version='2.0', browser='_chrome') self.new_col.add(browser) self.new_col.add(version) resources = (browser, version) return resources, CollectionChangeset(self.orig_col, self.new_col)
def test_new_browser_with_ordered_versions(self): """When order matters, creation order is sort order.""" browser = Browser(id='_b', slug='browser', versions=['u', '1.0', '2.0']) v_unknown = Version(id='u', version=None, browser='_b') v_1 = Version(id='1.0', version='1.0', browser='_b') v_2 = Version(id='2.0', version='2.0', browser='_b') self.new_col.add(browser) self.new_col.add(v_1) self.new_col.add(v_unknown) self.new_col.add(v_2) cc = CollectionChangeset(self.orig_col, self.new_col) expected_order = OrderedDict([ (('browsers', 'browser'), browser), (('versions', 'browser', ''), v_unknown), (('versions', 'browser', '1.0'), v_1), (('versions', 'browser', '2.0'), v_2), ]) expected = { 'new': expected_order, 'same': OrderedDict(), 'changed': OrderedDict(), 'deleted': OrderedDict(), } self.assertEqual(expected_order.keys(), cc.changes['new'].keys()) self.assertEqual(expected, cc.changes)
def test_new_versions_to_existing_browser(self): """When order matters, new items update the parent item.""" browser = Browser(id='_b', slug='browser', versions=['u']) v_1 = Version(id='1.0', version='1.0', browser='_b') self.orig_col.add(browser) self.orig_col.add(v_1) browser_new = Browser(id='_b', slug='browser', versions=['u', '1.0', '2.0']) v_unknown = Version(id='u', version=None, browser='_b') v_1_same = Version(id='1.0', version='1.0', browser='_b') v_2 = Version(id='2.0', version='2.0', browser='_b') self.new_col.add(browser_new) self.new_col.add(v_unknown) self.new_col.add(v_1_same) self.new_col.add(v_2) cc = CollectionChangeset(self.orig_col, self.new_col) expected_order = OrderedDict([ (('versions', 'browser', ''), v_unknown), (('versions', 'browser', '2.0'), v_2), ]) expected = { 'new': expected_order, 'same': OrderedDict([ (('versions', 'browser', '1.0'), v_1_same), ]), 'changed': OrderedDict([ (('browsers', 'browser'), browser_new), ]), 'deleted': OrderedDict(), } self.assertEqual(expected_order.keys(), cc.changes['new'].keys()) self.assertEqual(expected, cc.changes)
def test_new_reference_with_dependencies(self): feature = Feature(id='feature', slug='feature', name={'en': 'Feature'}, sections=['section']) reference = Reference(id='reference', feature='feature', section='section') section = Section(id='section', specification='spec') spec = Specification(id='spec', mdn_key='SPEC', slug='spec', maturity='maturity') maturity = Maturity(id='maturity', slug='mat') self.new_col.add(feature) self.new_col.add(reference) self.new_col.add(section) self.new_col.add(spec) self.new_col.add(maturity) cc = CollectionChangeset(self.orig_col, self.new_col) expected_order = OrderedDict([ (('maturities', 'mat'), maturity), (('specifications', 'SPEC'), spec), (('sections', 'SPEC', ''), section), (('features', 'feature'), feature), (('references', 'feature', 'SPEC', ''), reference), ]) expected = { 'new': expected_order, 'same': OrderedDict(), 'changed': OrderedDict(), 'deleted': OrderedDict(), } self.assertEqual(expected_order.keys(), cc.changes['new'].keys()) self.assertEqual(expected, cc.changes)
def setup_deleted(self, skip_deletes=False): browser = Browser(id='_chrome', slug='chrome') version = Version(id='_chrome_2', version='2.0', browser='_chrome') self.orig_col.add(browser) self.orig_col.add(version) resources = (browser, version) return resources, CollectionChangeset(self.orig_col, self.new_col, skip_deletes)
def test_empty(self): cc = CollectionChangeset(self.orig_col, self.new_col) expected = { 'new': OrderedDict(), 'same': OrderedDict(), 'changed': OrderedDict(), 'deleted': OrderedDict(), } self.assertEqual(expected, cc.changes) expected_summary = '' self.assertEqual(expected_summary, cc.summarize())
def test_empty(self): cc = CollectionChangeset(self.orig_col, self.new_col) expected = { "new": OrderedDict(), "same": OrderedDict(), "changed": OrderedDict(), "deleted": OrderedDict(), } self.assertEqual(expected, cc.changes) expected_summary = "" self.assertEqual(expected_summary, cc.summarize())
def test_features_root(self): root = Feature(id='root', slug='root', parent=None) self.new_col.add(root) cc = CollectionChangeset(self.orig_col, self.new_col) expected = { 'new': OrderedDict([ (('features', 'root'), root), ]), 'changed': OrderedDict(), 'deleted': OrderedDict(), 'same': OrderedDict(), } self.assertEqual(expected, cc.changes)
def setup_new_with_dependencies(self): parent = Feature(id='parent', slug='parent') child1 = Feature(id='child1', slug='child1', parent='parent') child2 = Feature(id='child2', slug='child2', parent='parent') child3 = Feature(id='child3', slug='child3', parent='parent') grandchild = Feature(id='gchild', slug='grandchild', parent='child2') self.new_col.add(child1) self.new_col.add(parent) self.new_col.add(child2) self.new_col.add(child3) self.new_col.add(grandchild) resources = (parent, child1, child2, child3, grandchild) return resources, CollectionChangeset(self.orig_col, self.new_col)
def setup_matched(self): browser = Browser(id='1', slug='chrome') version = Version( id='1', version='2.0', browser='1', note={'en': 'Second Version'}) self.orig_col.add(browser) self.orig_col.add(version) browser_same = Browser(id='_chrome', slug='chrome') version_diff = Version( id='_version', version='2.0', browser='_chrome', note=OrderedDict(( ('en', 'Second Version'), ('es', 'Segunda Versión')))) self.new_col.add(version_diff) self.new_col.add(browser_same) resources = (version, browser_same, version_diff) return resources, CollectionChangeset(self.orig_col, self.new_col)
def test_new_section_with_dependencies(self): section = Section(id='section', specification='spec') spec = Specification(id='spec', mdn_key='SPEC', slug='spec', maturity='maturity') maturity = Maturity(id='maturity', slug='mat') self.new_col.add(section) self.new_col.add(spec) self.new_col.add(maturity) cc = CollectionChangeset(self.orig_col, self.new_col) expected_order = OrderedDict([ (('maturities', 'mat'), maturity), (('specifications', 'SPEC'), spec), (('sections', 'SPEC', ''), section), ]) expected = { 'new': expected_order, 'same': OrderedDict(), 'changed': OrderedDict(), 'deleted': OrderedDict(), } self.assertEqual(expected_order.keys(), cc.changes['new'].keys()) self.assertEqual(expected, cc.changes)
def _process_data(self): """Load the linked data and compare to current data.""" assert not hasattr(self, 'changes'), '_process_data called twice.' assert hasattr(self, 'errors'), ('_process_data not called by is_valid().') r_by_t = Collection.resource_by_type # Create and load collection of new data new_collection = Collection() for rtype, items in self.data.items(): resource_cls = r_by_t.get(rtype) if resource_cls: for seq, json_api_item in enumerate(items): item = json_api_item.copy() links = item.pop('links', {}) item.update(links) resource = self.load_resource(resource_cls, item) resource._seq = seq new_collection.add(resource) # Create native representation of current feature data current_collection = Collection(DjangoResourceClient()) feature_serializer = ViewFeatureSerializer(context=self.context) current_feature = feature_serializer.to_representation(self.feature) current_extra = current_feature.pop('_view_extra') del current_extra['meta'] # Load feature into new and current collection current_feature_resource = self.load_resource(r_by_t['features'], current_feature) current_collection.add(current_feature_resource) current_feature.update(self.feature._in_extra) current_feature['id'] = str(current_feature['id']) resource_feature = self.load_resource(r_by_t['features'], current_feature) resource_feature._seq = None new_collection.add(resource_feature) # Populate collection of current data for rtype, items in current_extra.items(): resource_cls = r_by_t[rtype] for item in items: resource = self.load_resource(resource_cls, item) current_collection.add(resource) # Add existing items not explicit in PUT content # This avoids 'delete' changes new_items = new_collection.get_all_by_data_id() for data_id, item in current_collection.get_all_by_data_id().items(): if data_id not in new_items: rtype = item._resource_type resource = r_by_t[rtype]() json_api_rep = item.to_json_api() json_api_rep[rtype]['id'] = item.id.id resource.from_json_api(json_api_rep) resource._seq = None new_collection.add(resource) # Add existing items used in new collection to current collection # This avoids incorrect 'new' changes existing_items = current_collection.get_all_by_data_id() for data_id, item in new_collection.get_all_by_data_id().items(): if item.id: item_id = item.id.id int_id = None existing_item = existing_items.get(data_id) try: int_id = int(item_id) except ValueError: pass if int_id and (existing_item is None): rtype = item._resource_type resource_cls = r_by_t[rtype] model_cls, serializer_cls = view_cls_by_name[rtype] obj = model_cls.objects.get(id=int_id) serializer = serializer_cls() data = serializer.to_representation(obj) resource = self.load_resource(resource_cls, data) current_collection.add(resource) # Load the diff self.changeset = CollectionChangeset(current_collection, new_collection) assert not self.changeset.changes.get('deleted'), ( 'Existing items were not added, so deletions found:\n%s' % self.changes['deleted'])