304 lines
10 KiB
Python
304 lines
10 KiB
Python
import base64
|
|
import os
|
|
import re
|
|
from io import BytesIO
|
|
|
|
from django.core.files.uploadedfile import InMemoryUploadedFile
|
|
from django.urls import reverse
|
|
from PIL import Image
|
|
from wiki.core.plugins import registry as plugin_registry
|
|
from wiki.models import URLPath
|
|
from wiki.plugins.images import models
|
|
from wiki.plugins.images.wiki_plugin import ImagePlugin
|
|
|
|
from ...base import ArticleWebTestUtils
|
|
from ...base import DjangoClientTestBase
|
|
from ...base import RequireRootArticleMixin
|
|
from ...base import wiki_override_settings
|
|
|
|
|
|
class ImageTests(
|
|
RequireRootArticleMixin, ArticleWebTestUtils, DjangoClientTestBase
|
|
):
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.article = self.root_article
|
|
# A black 1x1 gif
|
|
self.test_data = "R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="
|
|
|
|
def _create_gif_filestream_from_base64(self, str_base64, **kwargs):
|
|
"""
|
|
Helper function to create filestream for upload.
|
|
|
|
Parameters :
|
|
strData : str, test string data
|
|
|
|
Optional Arguments :
|
|
filename : str, Defaults to 'test.txt'
|
|
"""
|
|
filename = kwargs.get("filename", "test.gif")
|
|
data = base64.b64decode(str_base64)
|
|
filedata = BytesIO(data)
|
|
filestream = InMemoryUploadedFile(
|
|
filedata, None, filename, "image", len(data), None
|
|
)
|
|
return filestream
|
|
|
|
def _create_test_image(self, path):
|
|
# Get the form index
|
|
plugin_index = -1
|
|
for cnt, plugin_instance in enumerate(plugin_registry.get_sidebar()):
|
|
if isinstance(plugin_instance, ImagePlugin):
|
|
plugin_index = cnt
|
|
break
|
|
self.assertGreaterEqual(
|
|
plugin_index, 0, msg="Image plugin not activated"
|
|
)
|
|
base_edit_url = reverse("wiki:edit", kwargs={"path": path})
|
|
url = base_edit_url + f"?f=form{plugin_index:d}"
|
|
filestream = self._create_gif_filestream_from_base64(self.test_data)
|
|
response = self.client.post(
|
|
url,
|
|
{
|
|
"unsaved_article_title": self.article.current_revision.title,
|
|
"unsaved_article_content": self.article.current_revision.content,
|
|
"image": filestream,
|
|
"images_save": "1",
|
|
},
|
|
)
|
|
self.assertRedirects(response, base_edit_url)
|
|
|
|
def test_index(self):
|
|
url = reverse("wiki:images_index", kwargs={"path": ""})
|
|
response = self.client.get(
|
|
url,
|
|
)
|
|
self.assertContains(response, "Images")
|
|
|
|
def test_upload(self):
|
|
"""
|
|
Tests that simple file upload uploads correctly
|
|
Uploading a file should preserve the original filename.
|
|
Uploading should not modify file in any way.
|
|
"""
|
|
self._create_test_image("")
|
|
# Check the object was created.
|
|
image = models.Image.objects.get()
|
|
image_revision = image.current_revision.imagerevision
|
|
self.assertEqual(image_revision.get_filename(), "test.gif")
|
|
self.assertEqual(
|
|
image_revision.image.file.read(), base64.b64decode(self.test_data)
|
|
)
|
|
|
|
def get_article(self, cont, image):
|
|
urlpath = URLPath.create_urlpath(
|
|
URLPath.root(), "html_image", title="TestImage", content=cont
|
|
)
|
|
if image:
|
|
self._create_test_image(urlpath.path)
|
|
return urlpath.article.render()
|
|
|
|
def test_image_missing(self):
|
|
output = self.get_article("[image:1]", False)
|
|
expected = (
|
|
'<figure class="thumbnail"><a href="">'
|
|
'<div class="caption"><em>Image not found</em></div>'
|
|
'</a><figcaption class="caption"></figcaption></figure>'
|
|
)
|
|
self.assertEqual(output, expected)
|
|
|
|
def test_image_default(self):
|
|
output = self.get_article("[image:1]", True)
|
|
image_rev = models.Image.objects.get().current_revision.imagerevision
|
|
expected = re.compile(
|
|
r'<figure class="thumbnail">'
|
|
r'<a href="' + re.escape(image_rev.image.url) + '">'
|
|
r'<img src="/?cache/.*\.jpg" alt="test\.gif">'
|
|
r'</a><figcaption class="caption"></figcaption></figure>'
|
|
)
|
|
self.assertRegex(output, expected)
|
|
|
|
def test_image_large_right(self):
|
|
output = self.get_article("[image:1 align:right size:large]", True)
|
|
image_rev = models.Image.objects.get().current_revision.imagerevision
|
|
expected = re.compile(
|
|
r'<figure class="thumbnail float-right">'
|
|
r'<a href="' + re.escape(image_rev.image.url) + '">'
|
|
r'<img src="/?cache/.*\.jpg" alt="test\.gif"></a>'
|
|
r'<figcaption class="caption"></figcaption></figure>'
|
|
)
|
|
self.assertRegex(output, expected)
|
|
|
|
def test_image_orig(self):
|
|
output = self.get_article("[image:1 size:orig]", True)
|
|
image_rev = models.Image.objects.get().current_revision.imagerevision
|
|
expected = (
|
|
'<figure class="thumbnail">'
|
|
'<a href="' + image_rev.image.url + '">'
|
|
'<img src="' + image_rev.image.url + '" alt="test.gif"></a>'
|
|
'<figcaption class="caption"></figcaption></figure>'
|
|
)
|
|
self.assertEqual(output, expected)
|
|
|
|
# https://gist.github.com/guillaumepiot/817a70706587da3bd862835c59ef584e
|
|
def generate_photo_file(self):
|
|
file = BytesIO()
|
|
image = Image.new("RGBA", size=(100, 100), color=(155, 0, 0))
|
|
image.save(file, "gif")
|
|
file.name = "test.gif"
|
|
file.seek(0)
|
|
return file
|
|
|
|
def test_add_revision(self):
|
|
self._create_test_image(path="")
|
|
image = models.Image.objects.get()
|
|
before_edit_rev = image.current_revision.revision_number
|
|
|
|
response = self.client.post(
|
|
reverse(
|
|
"wiki:images_add_revision",
|
|
kwargs={
|
|
"article_id": self.root_article,
|
|
"image_id": image.pk,
|
|
"path": "",
|
|
},
|
|
),
|
|
data={"image": self.generate_photo_file()},
|
|
)
|
|
self.assertRedirects(
|
|
response, reverse("wiki:edit", kwargs={"path": ""})
|
|
)
|
|
image = models.Image.objects.get()
|
|
self.assertEqual(models.Image.objects.count(), 1)
|
|
self.assertEqual(
|
|
image.current_revision.previous_revision.revision_number,
|
|
before_edit_rev,
|
|
)
|
|
|
|
def test_delete_restore_revision(self):
|
|
self._create_test_image(path="")
|
|
image = models.Image.objects.get()
|
|
before_edit_rev = image.current_revision.revision_number
|
|
|
|
response = self.client.get(
|
|
reverse(
|
|
"wiki:images_delete",
|
|
kwargs={
|
|
"article_id": self.root_article,
|
|
"image_id": image.pk,
|
|
"path": "",
|
|
},
|
|
),
|
|
)
|
|
self.assertRedirects(
|
|
response, reverse("wiki:images_index", kwargs={"path": ""})
|
|
)
|
|
image = models.Image.objects.get()
|
|
self.assertEqual(models.Image.objects.count(), 1)
|
|
self.assertEqual(
|
|
image.current_revision.previous_revision.revision_number,
|
|
before_edit_rev,
|
|
)
|
|
self.assertIs(image.current_revision.deleted, True)
|
|
|
|
# RESTORE
|
|
before_edit_rev = image.current_revision.revision_number
|
|
response = self.client.get(
|
|
reverse(
|
|
"wiki:images_restore",
|
|
kwargs={
|
|
"article_id": self.root_article,
|
|
"image_id": image.pk,
|
|
"path": "",
|
|
},
|
|
),
|
|
)
|
|
self.assertRedirects(
|
|
response, reverse("wiki:images_index", kwargs={"path": ""})
|
|
)
|
|
image = models.Image.objects.get()
|
|
self.assertEqual(models.Image.objects.count(), 1)
|
|
self.assertEqual(
|
|
image.current_revision.previous_revision.revision_number,
|
|
before_edit_rev,
|
|
)
|
|
self.assertFalse(image.current_revision.deleted)
|
|
|
|
def test_purge(self):
|
|
"""
|
|
Tests that an image is really purged
|
|
"""
|
|
self._create_test_image(path="")
|
|
image = models.Image.objects.get()
|
|
image_revision = image.current_revision.imagerevision
|
|
f_path = image_revision.image.file.name
|
|
|
|
self.assertIs(os.path.exists(f_path), True)
|
|
|
|
response = self.client.post(
|
|
reverse(
|
|
"wiki:images_purge",
|
|
kwargs={
|
|
"article_id": self.root_article,
|
|
"image_id": image.pk,
|
|
"path": "",
|
|
},
|
|
),
|
|
data={"confirm": True},
|
|
)
|
|
self.assertRedirects(
|
|
response, reverse("wiki:images_index", kwargs={"path": ""})
|
|
)
|
|
self.assertEqual(models.Image.objects.count(), 0)
|
|
self.assertIs(os.path.exists(f_path), False)
|
|
|
|
def test_add_revision_purge_image(self):
|
|
"""
|
|
Tests that an image with more than one revision is really purged
|
|
"""
|
|
# use another test to stage this one
|
|
self.test_add_revision()
|
|
|
|
image = models.Image.objects.get()
|
|
image_revision = image.current_revision.imagerevision
|
|
f_path = image_revision.image.file.name
|
|
|
|
self.assertIs(os.path.exists(f_path), True)
|
|
|
|
response = self.client.post(
|
|
reverse(
|
|
"wiki:images_purge",
|
|
kwargs={
|
|
"article_id": self.root_article,
|
|
"image_id": image.pk,
|
|
"path": "",
|
|
},
|
|
),
|
|
data={"confirm": True},
|
|
)
|
|
self.assertRedirects(
|
|
response, reverse("wiki:images_index", kwargs={"path": ""})
|
|
)
|
|
self.assertEqual(models.Image.objects.count(), 0)
|
|
self.assertIs(os.path.exists(f_path), False)
|
|
|
|
@wiki_override_settings(ACCOUNT_HANDLING=True)
|
|
def test_login_on_revision_add(self):
|
|
self._create_test_image(path="")
|
|
self.client.logout()
|
|
image = models.Image.objects.get()
|
|
url = reverse(
|
|
"wiki:images_add_revision",
|
|
kwargs={
|
|
"article_id": self.root_article,
|
|
"image_id": image.pk,
|
|
"path": "",
|
|
},
|
|
)
|
|
response = self.client.post(
|
|
url, data={"image": self.generate_photo_file()}
|
|
)
|
|
self.assertRedirects(
|
|
response, "{}?next={}".format(reverse("wiki:login"), url)
|
|
)
|