def test_delete_tree_from_both_urls(self): """ tests that features/%s/trees/%s/ and features/%s/ have the same delete tree UI behavior this test was created after discovering this bug on staging. """ # make a plot and tree tree1 = Tree(instance=self.instance, plot=self.plot) tree1.save_with_user(self.user) # delete the tree from plot detail page self.go_to_feature_detail(self.plot.pk) self._execute_delete_workflow((1, 1), (1, 0)) self.wait_until_invisible(self.delete_confirm) self.assertTrue( self.driver.current_url.endswith( '/%s/features/%s/' % (self.instance.url_name, self.plot.pk))) # make another tree to reestablish test case tree2 = Tree(instance=self.instance, plot=self.plot) tree2.save_with_user(self.user) self.go_to_tree_detail(self.plot.pk, tree2.pk) self._execute_delete_workflow((1, 1), (1, 0)) self.assertTrue( self.driver.current_url.endswith( '/%s/features/%s/' % (self.instance.url_name, self.plot.pk))) # finally, delete the plot too self._execute_delete_workflow((1, 0), (0, 0)) self.assertTrue( self.driver.current_url.endswith('/%s/map/' % self.instance.url_name))
def _commit_tree_data(self, data, plot, tree, tree_edited): for tree_attr, field_name in TreeImportRow.TREE_MAP.iteritems(): value = data.get(field_name, None) if value: tree_edited = True if tree is None: tree = Tree(instance=plot.instance) setattr(tree, tree_attr, value) ie = self.import_event tree_udf_defs = udf_defs(ie.instance, 'Tree') for udf_def in tree_udf_defs: udf_column_name = ie.get_udf_column_name(udf_def) value = data.get(udf_column_name, None) # Legitimate values could be falsey if value is not None: tree_edited = True if tree is None: tree = Tree(instance=plot.instance) tree.udfs[udf_def.name] = \ self._import_value_to_udf_value(udf_def, value) if tree_edited: tree.plot = plot tree.save_with_system_user_bypass_auth() tree.plot.update_updated_fields(ie.owner)
def test_plot_history_shows_all_trees(self): p = Plot(instance=self.instance, geom=self.p) p.save_with_user(self.user) self.assertEqual(len(p.get_tree_history()), 0) t = Tree(plot=p, instance=self.instance) t.save_with_user(self.user) tpk = t.pk self.assertEqual(list(p.get_tree_history()), [tpk]) t.delete_with_user(self.user) self.assertEqual(list(p.get_tree_history()), [tpk]) t2 = Tree(plot=p, instance=self.instance) t2.save_with_user(self.user) self.assertEqual(list(p.get_tree_history()), [t2.pk, tpk]) t3 = Tree(plot=p, instance=self.instance) t3.save_with_user(self.user) self.assertEqual(list(p.get_tree_history()), [t3.pk, t2.pk, tpk])
def test_within_radius_integration(self): test_point = Point(0, 0) near_point = Point(1, 1) far_point = Point(250, 250) near_plot = Plot(geom=near_point, instance=self.instance) near_plot.save_with_user(self.commander) near_tree = Tree(plot=near_plot, instance=self.instance) near_tree.save_with_user(self.commander) # just to make sure that the geospatial # query actually filters by distance far_plot = Plot(geom=far_point, instance=self.instance) far_plot.save_with_user(self.commander) far_tree = Tree(plot=far_plot, instance=self.instance) far_tree.save_with_user(self.commander) radius_filter = json.dumps({ 'plot.geom': { 'WITHIN_RADIUS': { 'POINT': { 'x': test_point.x, 'y': test_point.y }, 'RADIUS': 10 } } }) plots = search.Filter(radius_filter, '', self.instance)\ .get_objects(Plot) ids = {p.pk for p in plots} self.assertEqual(ids, {near_plot.pk})
def test_merges(self): p1 = mkPlot(self.instance, self.user) p2 = mkPlot(self.instance, self.user) t1 = Tree(plot=p1, species=self.s1, instance=self.instance) t2 = Tree(plot=p2, species=self.s2, instance=self.instance) for tree in (t1, t2): tree.save_with_system_user_bypass_auth() r = HttpRequest() r.REQUEST = { 'species_to_delete': self.s1.pk, 'species_to_replace_with': self.s2.pk } r.user = self.user r.user.is_staff = True merge_species(r, self.instance) self.assertRaises(Species.DoesNotExist, Species.objects.get, pk=self.s1.pk) # Requery the Trees to assert that species has changed t1r = Tree.objects.get(pk=t1.pk) t2r = Tree.objects.get(pk=t2.pk) self.assertEqual(t1r.species.pk, self.s2.pk) self.assertEqual(t2r.species.pk, self.s2.pk)
def test_delete_tree_from_both_urls(self): """ tests that features/%s/trees/%s/ and features/%s/ have the same delete tree UI behavior this test was created after discovering this bug on staging. """ # make a plot and tree tree1 = Tree(instance=self.instance, plot=self.plot) tree1.save_with_user(self.user) # delete the tree from plot detail page self.go_to_feature_detail(self.plot.pk) self._select_buttons() self.delete_begin.click() self.delete_confirm.click() self.wait_until_invisible(self.delete_confirm) # Expect tree to be deleted and redirect # to detail page for the plot self._assert_plot_and_tree_counts(1, 0) self.assertTrue( self.driver.current_url.endswith( '/autotest-instance/features/%s/' % self.plot.pk)) # make another tree to reestablish test case tree2 = Tree(instance=self.instance, plot=self.plot) tree2.save_with_user(self.user) self._assert_plot_and_tree_counts(1, 1) # delete the tree from the tree detail page self.go_to_tree_detail(self.plot.pk, tree2.pk) self._click_delete() # Expect tree to be deleted and redirect # to detail page for the plot (again) self._assert_plot_and_tree_counts(1, 0) self.assertTrue( self.driver.current_url.endswith( '/autotest-instance/features/%s/' % self.plot.pk)) # finally, delete the plot and expect to be # on the map page self._click_delete() self._assert_plot_and_tree_counts(0, 0) self.assertTrue( self.driver.current_url.endswith('/autotest-instance/map/'))
def test_reputations_increase_for_direct_writes(self): self.assertEqual(self.privileged_user.get_reputation(self.instance), 0) t = Tree(plot=self.plot, instance=self.instance, readonly=True) t.save_with_user(self.privileged_user) user = User.objects.get(pk=self.privileged_user.id) reputation = user.get_reputation(self.instance) self.assertGreater(reputation, 0)
def test_approve_insert_without_required_raises_integrity_error(self): new_plot = Plot(geom=self.p1, instance=self.instance) new_plot.save_with_user(self.pending_user) new_tree = Tree(plot=new_plot, instance=self.instance, diameter=10, height=10, readonly=False) new_tree.save_with_user(self.pending_user) approve_or_reject_audits_and_apply(new_plot.audits(), self.commander_user, True) diameter_audit = Audit.objects.get(model='Tree', field='diameter', model_id=new_tree.pk) insert_audit = Audit.objects.get(model='Tree', model_id=new_tree.pk, field='id') approve_or_reject_audit_and_apply(diameter_audit, self.commander_user, approved=True) self.assertRaises(IntegrityError, approve_or_reject_audit_and_apply, insert_audit, self.commander_user, True)
def make_tree(self, user=None): user = user or make_commander_user(self.instance) plot = Plot(geom=self.instance.center, instance=self.instance) plot.save_with_user(user) tree = Tree(instance=self.instance, plot=plot) tree.save_with_user(user) return tree
def _setup_tree_and_collection_udf(self): instance = make_instance() self.plotstew = make_collection_udf(instance, model='Plot', datatype=COLLECTION_UDF_DATATYPE) self.treestew = make_collection_udf(instance, model='Tree', datatype=COLLECTION_UDF_DATATYPE) commander = make_commander_user(instance) set_write_permissions(instance, commander, 'Plot', ['udf:Stewardship']) set_write_permissions(instance, commander, 'Tree', ['udf:Stewardship']) d1 = {'action': 'prune', 'date': "2014-05-3 00:00:00"} d2 = {'action': 'water', 'date': "2014-04-29 00:00:00"} p1 = Point(-7615441.0, 5953519.0) self.plot = Plot(instance=instance, geom=p1) self.plot.udfs[self.plotstew.name] = [d1] self.plot.save_with_user(commander) self.tree = Tree(instance=instance, plot=self.plot) self.tree.udfs[self.treestew.name] = [d2] self.tree.save_with_user(commander)
def test_treephoto_overrides_tree_and_plot(self): tree = Tree(diameter=10, plot=self.plot, instance=self.instance) tree.save_with_user(self.user) tree.add_photo(self.image, self.other) self.clear_and_set_and_reload() self.assertEqual(self.plot.updated_by_id, self.other.pk)
def _plot_audits(user, instance, plot): fake_tree = Tree(instance=instance) tree_visible_fields = fake_tree.visible_fields(user) # Get a history of trees that were on this plot tree_history = plot.get_tree_history() tree_filter = Q(model='Tree', field__in=tree_visible_fields, model_id__in=tree_history) tree_delete_filter = Q(model='Tree', action=Audit.Type.Delete, model_id__in=tree_history) tree_collection_udfs_audit_names =\ fake_tree.visible_collection_udfs_audit_names(user) tree_collection_udfs_filter = Q( model__in=tree_collection_udfs_audit_names, model_id__in=Tree.static_collection_udfs_audit_ids( (instance, ), tree_history, tree_collection_udfs_audit_names)) filters = [tree_filter, tree_delete_filter] cudf_filters = [tree_collection_udfs_filter] audits = _map_feature_audits(user, instance, plot, filters, cudf_filters) return audits
def test_treephoto_dict_to_model(self): plot = Plot(geom=self.instance.center, instance=self.instance) plot.save_with_user(self.commander) tree = Tree(plot=plot, instance=self.instance) tree.save_with_user(self.commander) ipath = self.resource_path('tree1.gif') tp_dict = json.loads(self.treephoto_blob % ipath) self.assertEqual(TreePhoto.objects.count(), 0) save_treephoto_blank = self.default_partial(save_treephoto, '') save_objects(MIGRATION_RULES, "treephoto", [tp_dict], { 'tree': { 1: tree.pk }, 'user': { 1: self.commander.pk } }, save_treephoto_blank, self.instance) self.assertEqual(TreePhoto.objects.count(), 1) photo = TreePhoto.objects.all()[0] self.assertIsNotNone(photo.image) self.assertIsNotNone(photo.thumbnail)
def test_record_is_created_when_nullables_are_still_pending(self): new_plot = Plot(geom=self.p1, instance=self.instance) new_plot.save_with_user(self.pending_user) new_tree = Tree(plot=new_plot, instance=self.instance, diameter=10, height=10, readonly=False) new_tree.save_with_user(self.pending_user) approve_or_reject_audits_and_apply( new_plot.audits(), self.commander_user, True) insert_audit = Audit.objects.filter(model='Tree')\ .get(field='id') field_audits = Audit.objects.filter(model='Tree')\ .filter(field__in=['readonly', 'diameter', 'plot']) for audit in field_audits: approve_or_reject_audit_and_apply( audit, self.commander_user, approved=True) approve_or_reject_audit_and_apply(insert_audit, self.commander_user, True) real_tree = Tree.objects.get(pk=new_tree.pk) self.assertEqual(real_tree.plot_id, new_plot.pk) self.assertEqual(real_tree.diameter, 10) self.assertEqual(real_tree.height, None) self.assertNotEqual(real_tree.readonly, True)
def setUp(self): super(ExportTreeTaskTest, self).setUp() set_write_permissions(self.instance, self.user, 'Plot', ['udf:Test choice']) set_write_permissions(self.instance, self.user, 'Tree', ['udf:Test int']) UserDefinedFieldDefinition.objects.create( instance=self.instance, model_type='Plot', datatype=json.dumps({'type': 'choice', 'choices': ['a', 'b', 'c']}), iscollection=False, name='Test choice') UserDefinedFieldDefinition.objects.create( instance=self.instance, model_type='Tree', datatype=json.dumps({'type': 'int'}), iscollection=False, name='Test int') p = Plot(geom=self.instance.center, instance=self.instance, address_street="123 Main Street") p.udfs['Test choice'] = 'a' p.save_with_user(self.user) t = Tree(plot=p, instance=self.instance, diameter=2) t.udfs['Test int'] = 4 t.save_with_user(self.user)
def setUp(self): self.instance = make_instance() self.user = make_commander_user(self.instance) self.plot = Plot(instance=self.instance, geom=Point(-7615441, 5953519)) self.plot.save_with_user(self.user) self.tree = Tree(instance=self.instance, plot=self.plot) self.tree.save_with_user(self.user)
def test_cant_use_regular_methods(self): plot = Plot(geom=self.instance.center, instance=self.instance) self.assertRaises(UserTrackingException, plot.save) self.assertRaises(UserTrackingException, plot.delete) tree = Tree() self.assertRaises(UserTrackingException, tree.save) self.assertRaises(UserTrackingException, tree.delete)
def test_delete_tree_sets_updated(self): tree = Tree(diameter=10, plot=self.plot, instance=self.instance) tree.save_with_user(self.user) self.plot = Plot.objects.get(pk=self.plot.pk) self.inital_updated = self.plot.updated_at tree.delete_with_user(self.user) self.assertGreater(self.plot.updated_at, self.initial_updated)
def setUp(self): super(UserRoleModelPermissionTest, self).setUp() self.plot = Plot(geom=self.p1, instance=self.instance) self.plot.save_with_user(self.direct_user) self.tree = Tree(plot=self.plot, instance=self.instance) self.tree.save_with_user(self.direct_user)
def test_update_species(self): with self._assert_updates_eco_rev(True): tree = Tree(instance=self.instance, plot=self.plot) tree.save_with_user(self.user) species = Species(common_name='foo', instance=self.instance) species.save_with_user(self.user) request_dict = {'tree.species': species.pk} update_map_feature(request_dict, self.user, self.plot)
def setUp(self): self.p = Point(-7615441.0, 5953519.0) self.instance = make_instance(point=self.p) self.user = make_commander_user(self.instance) self.plot = Plot(geom=self.instance.center, instance=self.instance) self.plot.save_with_user(self.user) self.tree = Tree(plot=self.plot, instance=self.instance)
def _test_hash_setup(self): self.initial_plot_hash = self.plot_obj.hash self.initial_map_feature_hash = self.map_feature_obj.hash # adding a tree should change the plot hash tree = Tree(diameter=10, plot=self.plot_obj, instance=self.instance) tree.save_with_user(self.user) self.final_plot_hash = self.plot_obj.hash self.final_map_feature_hash = self.map_feature_obj.hash
def test_save_new_object_authorized(self): '''Save two new objects with authorized user, nothing should happen''' plot = Plot(geom=self.p1, instance=self.instance) plot.save_with_user(self.officer) tree = Tree(plot=plot, instance=self.instance) tree.save_with_user(self.officer)
def test_save_new_object_unauthorized(self): plot = Plot(geom=self.p1, instance=self.instance) self.assertRaises(AuthorizeException, plot.save_with_user, self.outlaw) plot.save_base() tree = Tree(plot=plot, instance=self.instance) self.assertRaises(AuthorizeException, tree.save_with_user, self.outlaw)
def test_cant_use_regular_methods(self): p = Point(-8515222.0, 4953200.0) plot = Plot(geom=p, instance=self.instance) self.assertRaises(UserTrackingException, plot.save) self.assertRaises(UserTrackingException, plot.delete) tree = Tree() self.assertRaises(UserTrackingException, tree.save) self.assertRaises(UserTrackingException, tree.delete)
def test_lots_of_trees_and_plots(self): """ Make 3 plots: 2 pending and 1 approved Make 4 trees: 1 on each pending plot, 2 on approved plot Approve one pending plot. Approve all trees. The one on the (Still) pending plot should fail. all else should pass. """ plot1 = Plot(geom=self.instance.center, instance=self.instance) plot2 = Plot(geom=self.instance.center, instance=self.instance) plot3 = Plot(geom=self.instance.center, instance=self.instance) plot1.save_with_user(self.commander_user) plot2.save_with_user(self.pending_user) plot3.save_with_user(self.pending_user) tree1 = Tree(plot=plot1, instance=self.instance) tree1.save_with_user(self.pending_user) tree2 = Tree(plot=plot1, instance=self.instance) tree2.save_with_user(self.pending_user) tree3 = Tree(plot=plot2, instance=self.instance) tree3.save_with_user(self.pending_user) tree4 = Tree(plot=plot3, instance=self.instance) tree4.save_with_user(self.pending_user) approve_or_reject_audits_and_apply( plot2.audits(), self.commander_user, True) approve_or_reject_audits_and_apply( tree1.audits(), self.commander_user, True) approve_or_reject_audits_and_apply( tree2.audits(), self.commander_user, True) approve_or_reject_audits_and_apply( tree3.audits(), self.commander_user, True) self.assertRaises(ObjectDoesNotExist, Plot.objects.get, pk=plot3.pk) self.assertRaises(ObjectDoesNotExist, approve_or_reject_audits_and_apply, tree4.audits(), self.commander_user, True)
def commit_row(self): is_valid = self.validate_row() if not is_valid: return # not ready to commit if self.status == TreeImportRow.SUCCESS: return # nothing changed so no need to commit # Get our data data = self.cleaned self.convert_units( data, { fields.trees.PLOT_WIDTH: self.import_event.plot_width_conversion_factor, fields.trees.PLOT_LENGTH: self.import_event.plot_length_conversion_factor, fields.trees.DIAMETER: self.import_event.diameter_conversion_factor, fields.trees.TREE_HEIGHT: self.import_event.tree_height_conversion_factor, fields.trees.CANOPY_HEIGHT: self.import_event.canopy_height_conversion_factor }) plot_id = data.get(self.model_fields.OPENTREEMAP_PLOT_ID, None) # Check for an existing plot, use it if we're not already: if plot_id and (self.plot is None or self.plot.pk != plot_id): plot = Plot.objects.get(pk=plot_id) elif self.plot is not None: plot = self.plot else: plot = Plot(instance=self.import_event.instance) self._commit_plot_data(data, plot) # TREE_PRESENT handling: # If True, create a tree # If False, don't create a tree # If empty or missing, create a tree if a tree field is specified tree = plot.current_tree() tree_edited = False tree_present = data.get(self.model_fields.TREE_PRESENT, None) if tree_present: tree_edited = True if tree is None: tree = Tree(instance=plot.instance) if tree_present or tree_present is None: self._commit_tree_data(data, plot, tree, tree_edited) self.plot = plot self.status = TreeImportRow.SUCCESS self.save()
def handle(self, *args, **options): """ Create some seed data """ instance, user = self.setup_env(*args, **options) species_qs = instance.scope_model(Species) n = options['n'] self.stdout.write("Will create %s plots" % n) get_prob = lambda option: float(min(100, max(0, option))) / 100.0 tree_prob = get_prob(options['ptree']) species_prob = get_prob(options['pspecies']) diameter_prob = get_prob(options['pdiameter']) max_radius = options['radius'] center_x = instance.center.x center_y = instance.center.y ct = 0 cp = 0 for i in xrange(0, n): mktree = random.random() < tree_prob radius = random.gauss(0.0, max_radius) theta = random.random() * 2.0 * math.pi x = math.cos(theta) * radius + center_x y = math.sin(theta) * radius + center_y plot = Plot(instance=instance, geom=Point(x, y)) plot.save_with_user(user) cp += 1 if mktree: add_species = random.random() < species_prob if add_species: species = random.choice(species_qs) else: species = None add_diameter = random.random() < diameter_prob if add_diameter: diameter = 2 + random.random() * 18 else: diameter = None tree = Tree(plot=plot, species=species, diameter=diameter, instance=instance) tree.save_with_user(user) ct += 1 instance.update_geo_rev() self.stdout.write("Created %s trees and %s plots" % (ct, cp))
def test_delete_tree_sets_updated(self): tree = Tree(diameter=10, plot=self.plot, instance=self.instance) tree.save_with_user(self.user) self.plot.refresh_from_db() self.inital_updated = self.plot.updated_at tree.delete_with_user(self.fellow) self.plot.refresh_from_db() self.assertGreater(self.plot.updated_at, self.initial_updated) self.assertEqual(self.plot.updated_by, self.fellow)
def setUp(self): # Example url for # CEAT, 1630 dbh, NoEastXXX # eco.json?otmcode=CEAT&diameter=1630®ion=NoEastXXX def mockbenefits(*args, **kwargs): benefits = { "Benefits": { "aq_nox_avoided": 0.6792, "aq_nox_dep": 0.371, "aq_ozone_dep": 0.775, "aq_pm10_avoided": 0.0436, "aq_pm10_dep": 0.491, "aq_sox_avoided": 0.372, "aq_sox_dep": 0.21, "aq_voc_avoided": 0.0254, "bvoc": -0.077, "co2_avoided": 255.5, "co2_sequestered": 0, "co2_storage": 6575, "electricity": 187, "hydro_interception": 12.06, "natural_gas": 5834.1 } } return (benefits, None) region = ITreeRegion.objects.get(code='NoEastXXX') p = region.geometry.point_on_surface self.instance = make_instance(is_public=True, point=p) self.user = make_commander_user(self.instance) self.species = Species(otm_code='CEAT', genus='cedrus', species='atlantica', max_diameter=2000, max_height=100, instance=self.instance) self.species.save_with_user(self.user) self.plot = Plot(geom=p, instance=self.instance) self.plot.save_with_user(self.user) self.tree = Tree(plot=self.plot, instance=self.instance, readonly=False, species=self.species, diameter=1630) self.tree.save_with_user(self.user) self.origBenefitFn = ecobackend.json_benefits_call ecobackend.json_benefits_call = mockbenefits