#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2010-2017 Étienne Loks # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # See the file COPYING for details. import datetime import json from django.conf import settings from django.contrib.auth.models import User from django.core.urlresolvers import reverse from django.test.client import Client from ishtar_common.tests import ( TestCase, COMMON_FIXTURES, create_superuser, AutocompleteTestBase, AcItem, ) from ishtar_common.models import Town, IshtarSiteProfile from archaeological_files import models from archaeological_operations.models import ( Parcel, ParcelOwner, ActType, AdministrativeAct, ) from ishtar_common.tests import FILE_TOWNS_FIXTURES from archaeological_operations.tests import OperationInitTest, FileInit def create_administrativact(user, fle): act_type, created = ActType.objects.get_or_create( txt_idx="act_type_F", intented_to="F" ) dct = { "history_modifier": user, "act_type": act_type, "associated_file": fle, "signature_date": datetime.date(2017, 7, 10), "index": 22, } adminact, created = AdministrativeAct.objects.get_or_create(**dct) return [act_type], [adminact] class FileTest(TestCase, FileInit): fixtures = COMMON_FIXTURES model = models.File def setUp(self): IshtarSiteProfile.objects.create() self.create_file() def test_external_id(self): self.assertEqual( self.item.external_id, "{}-{}".format(self.item.year, self.item.numeric_reference), ) def test_cached_label(self): self.item = models.File.objects.get(pk=self.item.pk) # localisation fix lbls = [] for town_lbl in ("No town", "Pas de commune"): lbls.append( settings.JOINT.join( [town_lbl, self.item.external_id, self.item.internal_reference] ) ) self.assertIn(self.item.cached_label, lbls) default_town = Town.objects.create(name="Paris", numero_insee="75001") self.item.towns.add(default_town) # manually done inside wizards self.item._cached_label_checked = False self.item._test = True self.item.save() self.item = models.File.objects.get(pk=self.item.pk) lbl = lbls[0].replace("No town", "Paris") self.assertEqual(self.item.cached_label, lbl) def testAddAndGetHistorized(self): """ Test correct new version and correct access to history """ item = models.File.objects.get(pk=self.item.pk) nb_hist = item.history.count() self.assertTrue(item.history.count() >= 1) base_label = item.internal_reference item.internal_reference = "Unité_Test" item.history_modifier = self.user item.save() self.assertEqual(item.history.count(), nb_hist + 1) self.assertEqual(item.history.all()[1].internal_reference, base_label) item = models.File.objects.get(pk=self.item.pk) item.internal_reference = "Unité_Testée" item.history_modifier = self.user item.skip_history_when_saving = True item.save() item.skip_history_when_saving = False self.assertEqual(item.history.count(), nb_hist + 1) def testCreatorHistorized(self): """ Test creator association """ self.assertEqual(self.item.history_creator, self.o_user) altuser, created = User.objects.get_or_create(username="altusername") item = models.File.objects.get(pk=self.item.pk) item.internal_reference = "Unité_Test" item.history_modifier = altuser item.save() self.assertEqual(item.history_creator, self.o_user) def testIntelligentHistorisation(self): """ Test that two identical version are not recorded twice in the history and that multiple saving in a short time are not considered """ item = models.File.objects.get(pk=self.item.pk) nb_hist = item.history.count() item.internal_reference = "Unité_Test" item.history_modifier = self.user item.save() self.assertEqual(item.history.count(), nb_hist + 1) nb_hist = item.history.count() item = models.File.objects.get(pk=self.item.pk) item.save() self.assertEqual(item.history.count(), nb_hist) def testRollbackFile(self): nb_hist = self.item.history.count() initial_values = self.item.values() backup_date = self.item.history.all()[0].history_date self.item.internal_reference = "Unité_Test" self.item.history_modifier = self.user self.item.save() self.item = models.File.objects.get(pk=self.item.pk) self.item.rollback(backup_date) self.assertEqual(self.item.history.count(), nb_hist) new_values = self.item.values() for k in initial_values.keys(): if k in ("last_modified", "search_vector", "qrcode"): continue elif k == "history_m2m" and not initial_values[k]: initial_values[k] = dict([(j, []) for j in models.File.HISTORICAL_M2M]) self.assertTrue(k in new_values, msg="%s not in new values" % k) self.assertEqual( new_values[k], initial_values[k], msg="for %s: %s != %s" % (k, str(new_values[k]), str(initial_values[k])), ) def testRESTGetFile(self): response = self.client.post( "/get-file/", {"numeric_reference": self.item.numeric_reference} ) self.assertEqual(response.status_code, 200) data = json.loads(response.content.decode()) # not allowed -> no data self.assertTrue(not data) self.login_as_superuser() response = self.client.post( "/get-file/", {"numeric_reference": self.item.numeric_reference} ) self.assertEqual(response.status_code, 200) data = json.loads(response.content.decode()) self.assertTrue("recordsTotal" in data) self.assertEqual(data["recordsTotal"], 1) def testRESTGetOldFile(self): initial_ref = self.item.internal_reference new_ref = "Unité_Test_old_file" new_ref = initial_ref != new_ref and new_ref or new_ref + "extra" item = models.File.objects.get(pk=self.item.pk) item.internal_reference = new_ref item.history_modifier = self.user item.save() response = self.client.post( "/get-file/", {"numeric_reference": item.numeric_reference, "old": 1} ) self.assertEqual(response.status_code, 200) data = json.loads(response.content.decode()) # not allowed -> no data self.assertTrue(not data) self.login_as_superuser() response = self.client.post( "/get-file/", {"numeric_reference": item.numeric_reference, "old": 1} ) self.assertEqual(response.status_code, 200) data = json.loads(response.content.decode()) self.assertIn("recordsTotal", data) self.assertEqual(data["recordsTotal"], 1) self.assertEqual(data["rows"][0]["internal_reference"], initial_ref) def testPostDeleteParcels(self): fle = self.item town = Town.objects.create(name="plouf", numero_insee="20000") parcel = Parcel.objects.create(town=town) parcel_nb = Parcel.objects.count() fle.parcels.add(parcel) fle.delete() # our parcel has no operation attached is... no more be deleted self.assertEqual(parcel_nb, Parcel.objects.count()) self.create_file() fle = self.item parcel = Parcel.objects.create(town=town) parcel_nb = Parcel.objects.count() fle.parcels.add(parcel) fle.parcels.clear() # no signal raised... should resave Parcel.objects.filter(pk=parcel.pk).all()[0].save() # our parcel has no operation attached and... is no more automatically # deleted self.assertEqual(parcel_nb, Parcel.objects.count()) def test_show(self): c = Client() url = "show-file" pk = self.item.pk response = self.client.get(reverse(url, kwargs={"pk": pk})) self.assertEqual(response.status_code, 200) # empty content when not allowed self.assertEqual(response.content.decode(), "") self.login_as_superuser() response = self.client.get(reverse(url, kwargs={"pk": pk})) self.assertEqual(response.status_code, 200) self.assertIn('class="card sheet"', response.content.decode()) class FileOperationTest(TestCase, OperationInitTest, FileInit): model = models.File fixtures = FILE_TOWNS_FIXTURES def setUp(self): self.create_file() self.orgas = self.create_orgas(self.user) self.operations = self.create_operation(self.user, self.orgas[0]) self.operation = self.operations[0] def testFileAssociation(self): # parcel association default_town = Town.objects.all()[0] for p in range(0, 10): parcel = Parcel.objects.create( parcel_number=str(p), section="YY", town=default_town, operation=self.operation, ) if p == 1: ParcelOwner.objects.create( owner=self.extra_models["person"], parcel=parcel, start_date=datetime.date.today(), end_date=datetime.date.today(), ) initial_nb = self.item.parcels.count() # no parcel on the file -> new parcels are copied from the # operation self.operation.associated_file = self.item self.operation.save() self.assertEqual(self.item.parcels.count(), initial_nb + 10) # parcel owner well attached q = ParcelOwner.objects.filter(parcel__associated_file=self.item) self.assertEqual(q.count(), 1) # when attaching parcel from a file to an operation, copy is done parcel = Parcel.objects.create( parcel_number="42", section="ZZ", town=default_town, associated_file=self.item, ) ParcelOwner.objects.create( owner=self.extra_models["person"], parcel=parcel, start_date=datetime.date.today(), end_date=datetime.date.today(), ) parcel.operation = self.operation parcel.save() # double reference to operation and associated_file is deleted self.assertEqual(parcel.operation, None) # now 2 objects with the same parameters q = Parcel.objects.filter(parcel_number="42", section="ZZ", town=default_town) self.assertEqual(q.count(), 2) q = q.filter(operation=self.operation, associated_file=None) self.assertEqual(q.count(), 1) # parcel owner well attached q = ParcelOwner.objects.filter( parcel__operation=self.operation, parcel__parcel_number="42" ) self.assertEqual(q.count(), 1) class DashboardTest(TestCase, FileInit): fixtures = FILE_TOWNS_FIXTURES model = models.File def setUp(self): self.username, self.password, self.user = create_superuser() IshtarSiteProfile.objects.create() self.create_file() def test_dashboard(self): url = "dashboard-file" c = Client() c.login(username=self.username, password=self.password) response = c.get(reverse(url)) self.assertEqual(response.status_code, 200) class AutocompleteTest(AutocompleteTestBase, TestCase): fixtures = FILE_TOWNS_FIXTURES models = [ AcItem(models.File, "autocomplete-file", prepare_func="create_file"), ] def create_file(self, base_name): item, __ = models.File.objects.get_or_create( name=base_name, file_type=models.FileType.objects.all()[0] ) return item, None