from core.tests.utils.cases import UserTestCase from core.util import random_id from django.apps import apps from django.core.management import call_command from django.db import connection from django.db.migrations.loader import MigrationLoader from django.test import TestCase class MigrationTestCase(UserTestCase, TestCase): @property def app(self): return apps.get_containing_app_config(type(self).__module__).name migrate_from = None migrate_to = None def setUp(self): super(UserTestCase, self).setUp() assert self.migrate_from and self.migrate_to "TestCase '{}' must define migrate_from and migrate_to " "properties".format(type(self).__name__) # get the application state pre-migration apps_before = self._get_apps_for_migration( [(self.app, self.migrate_from)]) # Reverse to migrate_from call_command('migrate', 'accounts', '0002_activate_users_20161014_0846', '--noinput') call_command('migrate', 'organization', '0004_remove_Pb_project_roles', '--noinput') call_command('migrate', self.app, self.migrate_from, '--noinput') # setup pre-migration test data self.setUpBeforeMigration(apps_before) # Run the migration to test call_command('migrate', self.app, self.migrate_to, '--noinput') # get application state post-migration self.apps_after = self._get_apps_for_migration( [(self.app, self.migrate_to)]) def setUpBeforeMigration(self, apps): pass def _get_apps_for_migration(self, migration_states): loader = MigrationLoader(connection) full_names = [] for app_name, migration_name in migration_states: if migration_name != 'zero': migration_name = loader.get_migration_by_prefix( app_name, migration_name).name full_names.append((app_name, migration_name)) state = loader.project_state(full_names) return state.apps class TestFixImportedResourceUrls(MigrationTestCase): migrate_from = '0004_add_ordering_for_resources' migrate_to = '0005_fix_import_resource_urls' def setUpBeforeMigration(self, apps_before): Resource = apps_before.get_model('resources', 'Resource') User = apps_before.get_model('accounts', 'User') Organization = apps_before.get_model('organization', 'Organization') Project = apps_before.get_model('organization', 'Project') user = User.objects.create(username='testuser') org = Organization.objects.create(name='Test Org') project = Project.objects.create(name='Test Proj', organization=org) base_path = ( 'https://s3-us-west-2.amazonaws.com/cadasta-resources/' ) # cannot call custom save methods on models in migrations # as models are serialized from migration scripts # so custom methods are not available # docs.djangoproject.com/en/1.9/topics/migrations/#historical-models for f in range(10): file_name = base_path + 'test_' + str(f) + '.csv' resource_name = 'test-resource-' + str(f) Resource.objects.create( id=random_id(), name=resource_name, file=file_name, mime_type='text/csv', contributor=user, project=project ) Resource.objects.create( id=random_id(), file=base_path + 'test.jpg', mime_type='image/jpg', contributor=user, project=project ) def test_migration(self): Resource = self.apps_after.get_model('resources', 'Resource') resources = Resource.objects.filter(mime_type='text/csv') assert len(resources) == 10 base_path = ( 'https://s3-us-west-2.amazonaws.com/cadasta-resources/' ) resource = Resource.objects.get(name='test-resource-0') assert resource.file.url == base_path + 'resources/test_0.csv' class TestRandomizeImportedFilenames(MigrationTestCase): migrate_from = '0005_fix_import_resource_urls' migrate_to = '0006_randomize_imported_filenames' def setUpBeforeMigration(self, apps_before): Resource = apps_before.get_model('resources', 'Resource') User = apps_before.get_model('accounts', 'User') Organization = apps_before.get_model('organization', 'Organization') Project = apps_before.get_model('organization', 'Project') user = User.objects.create(username='testuser') org = Organization.objects.create(name='Test Org') project = Project.objects.create(name='Test Proj', organization=org) base_path = ( 'https://s3-us-west-2.amazonaws.com/cadasta-resources/' 'resources/' ) for f in range(10): file_name = base_path + 'test_' + str(f) + '.csv' resource_name = 'test-resource-' + str(f) Resource.objects.create( id=random_id(), name=resource_name, file=file_name, mime_type='text/csv', contributor=user, project=project ) Resource.objects.create( id=random_id(), file=base_path + 'test.jpg', mime_type='image/jpg', contributor=user, project=project ) def test_migration(self): Resource = self.apps_after.get_model('resources', 'Resource') resources = Resource.objects.filter(mime_type='text/csv') assert len(resources) == 10 resource = Resource.objects.get(name='test-resource-0') assert resource.original_file == 'test_0.csv' random_filename = resource.file.url[resource.file.url.rfind('/'):] assert random_filename.endswith('.csv') assert len(random_filename.split('.')[0].strip('/')) == 24