293 lines
12 KiB
Python
293 lines
12 KiB
Python
from __future__ import unicode_literals
|
|
|
|
import os.path
|
|
|
|
from django.test.utils import override_settings
|
|
from django.test.testcases import TestCase
|
|
from django.contrib.auth.models import User
|
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from django.contrib.admin.models import LogEntry
|
|
from tablib import Dataset
|
|
|
|
from core.admin import BookAdmin, AuthorAdmin, BookResource
|
|
from core.models import Category, Parent, Book
|
|
|
|
|
|
class ImportExportAdminIntegrationTest(TestCase):
|
|
|
|
def setUp(self):
|
|
user = User.objects.create_user('admin', 'admin@example.com',
|
|
'password')
|
|
user.is_staff = True
|
|
user.is_superuser = True
|
|
user.save()
|
|
self.client.login(username='admin', password='password')
|
|
|
|
def test_import_export_template(self):
|
|
response = self.client.get('/admin/core/book/')
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTemplateUsed(response,
|
|
'admin/import_export/change_list_import_export.html')
|
|
self.assertContains(response, _('Import'))
|
|
self.assertContains(response, _('Export'))
|
|
|
|
@override_settings(TEMPLATE_STRING_IF_INVALID='INVALID_VARIABLE')
|
|
def test_import(self):
|
|
# GET the import form
|
|
response = self.client.get('/admin/core/book/import/')
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTemplateUsed(response, 'admin/import_export/import.html')
|
|
self.assertContains(response, 'form action=""')
|
|
|
|
# POST the import form
|
|
input_format = '0'
|
|
filename = os.path.join(
|
|
os.path.dirname(__file__),
|
|
os.path.pardir,
|
|
'exports',
|
|
'books.csv')
|
|
with open(filename, "rb") as f:
|
|
data = {
|
|
'input_format': input_format,
|
|
'import_file': f,
|
|
}
|
|
response = self.client.post('/admin/core/book/import/', data)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertIn('result', response.context)
|
|
self.assertFalse(response.context['result'].has_errors())
|
|
self.assertIn('confirm_form', response.context)
|
|
confirm_form = response.context['confirm_form']
|
|
|
|
data = confirm_form.initial
|
|
self.assertEqual(data['original_file_name'], 'books.csv')
|
|
response = self.client.post('/admin/core/book/process_import/', data,
|
|
follow=True)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response,
|
|
_('Import finished, with {} new and {} updated {}.').format(
|
|
1, 0, Book._meta.verbose_name_plural)
|
|
)
|
|
|
|
@override_settings(TEMPLATE_STRING_IF_INVALID='INVALID_VARIABLE')
|
|
def test_import_mac(self):
|
|
# GET the import form
|
|
response = self.client.get('/admin/core/book/import/')
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTemplateUsed(response, 'admin/import_export/import.html')
|
|
self.assertContains(response, 'form action=""')
|
|
|
|
# POST the import form
|
|
input_format = '0'
|
|
filename = os.path.join(
|
|
os.path.dirname(__file__),
|
|
os.path.pardir,
|
|
'exports',
|
|
'books-mac.csv')
|
|
with open(filename, "rb") as f:
|
|
data = {
|
|
'input_format': input_format,
|
|
'import_file': f,
|
|
}
|
|
response = self.client.post('/admin/core/book/import/', data)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertIn('result', response.context)
|
|
self.assertFalse(response.context['result'].has_errors())
|
|
self.assertIn('confirm_form', response.context)
|
|
confirm_form = response.context['confirm_form']
|
|
|
|
data = confirm_form.initial
|
|
self.assertEqual(data['original_file_name'], 'books-mac.csv')
|
|
response = self.client.post('/admin/core/book/process_import/', data,
|
|
follow=True)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response,
|
|
_('Import finished, with {} new and {} updated {}.').format(
|
|
1, 0, Book._meta.verbose_name_plural)
|
|
)
|
|
|
|
def test_export(self):
|
|
response = self.client.get('/admin/core/book/export/')
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
data = {
|
|
'file_format': '0',
|
|
}
|
|
response = self.client.post('/admin/core/book/export/', data)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTrue(response.has_header("Content-Disposition"))
|
|
self.assertEqual(response['Content-Type'], 'text/csv')
|
|
|
|
def test_import_export_buttons_visible_without_add_permission(self):
|
|
# issue 38 - Export button not visible when no add permission
|
|
original = BookAdmin.has_add_permission
|
|
BookAdmin.has_add_permission = lambda self, request: False
|
|
response = self.client.get('/admin/core/book/')
|
|
BookAdmin.has_add_permission = original
|
|
|
|
self.assertContains(response, _('Export'))
|
|
self.assertContains(response, _('Import'))
|
|
|
|
def test_import_buttons_visible_without_add_permission(self):
|
|
# When using ImportMixin, users should be able to see the import button
|
|
# without add permission (to be consistent with ImportExportMixin)
|
|
|
|
original = AuthorAdmin.has_add_permission
|
|
AuthorAdmin.has_add_permission = lambda self, request: False
|
|
response = self.client.get('/admin/core/author/')
|
|
AuthorAdmin.has_add_permission = original
|
|
|
|
self.assertContains(response, _('Import'))
|
|
self.assertTemplateUsed(response, 'admin/import_export/change_list.html')
|
|
|
|
def test_import_file_name_in_tempdir(self):
|
|
# 65 - import_file_name form field can be use to access the filesystem
|
|
import_file_name = os.path.join(
|
|
os.path.dirname(__file__),
|
|
os.path.pardir,
|
|
'exports',
|
|
'books.csv')
|
|
data = {
|
|
'input_format': "0",
|
|
'import_file_name': import_file_name,
|
|
'original_file_name': 'books.csv'
|
|
}
|
|
with self.assertRaises(IOError):
|
|
self.client.post('/admin/core/book/process_import/', data)
|
|
|
|
def test_csrf(self):
|
|
response = self.client.get('/admin/core/book/process_import/')
|
|
self.assertEqual(response.status_code, 405)
|
|
|
|
def test_import_log_entry(self):
|
|
input_format = '0'
|
|
filename = os.path.join(
|
|
os.path.dirname(__file__),
|
|
os.path.pardir,
|
|
'exports',
|
|
'books.csv')
|
|
with open(filename, "rb") as f:
|
|
data = {
|
|
'input_format': input_format,
|
|
'import_file': f,
|
|
}
|
|
response = self.client.post('/admin/core/book/import/', data)
|
|
self.assertEqual(response.status_code, 200)
|
|
confirm_form = response.context['confirm_form']
|
|
data = confirm_form.initial
|
|
response = self.client.post('/admin/core/book/process_import/', data,
|
|
follow=True)
|
|
self.assertEqual(response.status_code, 200)
|
|
book = LogEntry.objects.latest('id')
|
|
self.assertEqual(book.object_repr, "Some book")
|
|
self.assertEqual(book.object_id, str(1))
|
|
|
|
def test_import_log_entry_with_fk(self):
|
|
Parent.objects.create(id=1234, name='Some Parent')
|
|
input_format = '0'
|
|
filename = os.path.join(
|
|
os.path.dirname(__file__),
|
|
os.path.pardir,
|
|
'exports',
|
|
'child.csv')
|
|
with open(filename, "rb") as f:
|
|
data = {
|
|
'input_format': input_format,
|
|
'import_file': f,
|
|
}
|
|
response = self.client.post('/admin/core/child/import/', data)
|
|
self.assertEqual(response.status_code, 200)
|
|
confirm_form = response.context['confirm_form']
|
|
data = confirm_form.initial
|
|
response = self.client.post('/admin/core/child/process_import/', data,
|
|
follow=True)
|
|
self.assertEqual(response.status_code, 200)
|
|
child = LogEntry.objects.latest('id')
|
|
self.assertEqual(child.object_repr, 'Some - child of Some Parent')
|
|
self.assertEqual(child.object_id, str(1))
|
|
|
|
def test_logentry_creation_with_import_obj_exception(self):
|
|
# from https://mail.python.org/pipermail/python-dev/2008-January/076194.html
|
|
def monkeypatch_method(cls):
|
|
def decorator(func):
|
|
setattr(cls, func.__name__, func)
|
|
return func
|
|
return decorator
|
|
|
|
# Cause an exception in import_row, but only after import is confirmed,
|
|
# so a failure only occurs when ImportMixin.process_import is called.
|
|
class R(BookResource):
|
|
def import_obj(self, obj, data, dry_run):
|
|
if dry_run:
|
|
super(R, self).import_obj(obj, data, dry_run)
|
|
else:
|
|
raise Exception
|
|
|
|
@monkeypatch_method(BookAdmin)
|
|
def get_resource_class(self):
|
|
return R
|
|
|
|
# Verify that when an exception occurs in import_row, when raise_errors is False,
|
|
# the returned row result has a correct import_type value,
|
|
# so generating log entries does not fail.
|
|
@monkeypatch_method(BookAdmin)
|
|
def process_dataset(self, dataset, confirm_form, request, *args, **kwargs):
|
|
resource = self.get_import_resource_class()(**self.get_import_resource_kwargs(request, *args, **kwargs))
|
|
return resource.import_data(dataset,
|
|
dry_run=False,
|
|
raise_errors=False,
|
|
file_name=confirm_form.cleaned_data['original_file_name'],
|
|
user=request.user,
|
|
**kwargs)
|
|
|
|
dataset = Dataset(headers=["id","name","author_email"])
|
|
dataset.append([1, "Test 1", "test@example.com"])
|
|
input_format = '0'
|
|
content = dataset.csv
|
|
f = SimpleUploadedFile("data.csv", content.encode("utf-8"), content_type="text/csv")
|
|
data = {
|
|
"input_format": input_format,
|
|
"import_file": f,
|
|
}
|
|
response = self.client.post('/admin/core/book/import/', data)
|
|
self.assertEqual(response.status_code, 200)
|
|
confirm_form = response.context['confirm_form']
|
|
data = confirm_form.initial
|
|
response = self.client.post('/admin/core/book/process_import/', data,
|
|
follow=True)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
|
class ExportActionAdminIntegrationTest(TestCase):
|
|
|
|
def setUp(self):
|
|
user = User.objects.create_user('admin', 'admin@example.com',
|
|
'password')
|
|
user.is_staff = True
|
|
user.is_superuser = True
|
|
user.save()
|
|
|
|
self.cat1 = Category.objects.create(name='Cat 1')
|
|
self.cat2 = Category.objects.create(name='Cat 2')
|
|
|
|
self.client.login(username='admin', password='password')
|
|
|
|
def test_export(self):
|
|
data = {
|
|
'action': ['export_admin_action'],
|
|
'file_format': '0',
|
|
'_selected_action': [str(self.cat1.id)],
|
|
}
|
|
response = self.client.post('/admin/core/category/', data)
|
|
self.assertContains(response, self.cat1.name, status_code=200)
|
|
self.assertNotContains(response, self.cat2.name, status_code=200)
|
|
self.assertTrue(response.has_header("Content-Disposition"))
|
|
|
|
def test_export_no_format_selected(self):
|
|
data = {
|
|
'action': ['export_admin_action'],
|
|
'_selected_action': [str(self.cat1.id)],
|
|
}
|
|
response = self.client.post('/admin/core/category/', data)
|
|
self.assertEqual(response.status_code, 302)
|