|
@@ -0,0 +1,199 @@
|
|
|
+import os
|
|
|
+
|
|
|
+import pytest
|
|
|
+from django.urls import reverse
|
|
|
+
|
|
|
+from ....test import assert_contains
|
|
|
+from ...models import Theme
|
|
|
+
|
|
|
+import_link = reverse("misago:admin:appearance:themes:import")
|
|
|
+
|
|
|
+
|
|
|
+class MockThemeExport:
|
|
|
+ def __init__(self, response):
|
|
|
+ self.name = "theme-export.zip"
|
|
|
+ self.content_type = response["content-type"]
|
|
|
+ self.size = response["content-length"]
|
|
|
+ self._response = response
|
|
|
+
|
|
|
+ def read(self):
|
|
|
+ return self._response.getvalue()
|
|
|
+
|
|
|
+
|
|
|
+@pytest.fixture
|
|
|
+def reimport_theme(admin_client):
|
|
|
+ def export_import_theme(theme, extra_data=None):
|
|
|
+ export_link = reverse(
|
|
|
+ "misago:admin:appearance:themes:export", kwargs={"pk": theme.pk}
|
|
|
+ )
|
|
|
+ theme_export = MockThemeExport(admin_client.post(export_link))
|
|
|
+
|
|
|
+ data = extra_data or {}
|
|
|
+ data["upload"] = theme_export
|
|
|
+ admin_client.post(import_link, data)
|
|
|
+
|
|
|
+ return Theme.objects.filter(pk__gt=theme.pk).last()
|
|
|
+
|
|
|
+ return export_import_theme
|
|
|
+
|
|
|
+
|
|
|
+def assert_filenames_are_same(src, dst):
|
|
|
+ source_filename = os.path.split(src.path)[-1]
|
|
|
+ imported_filename = os.path.split(dst.path)[-1]
|
|
|
+ assert source_filename == imported_filename
|
|
|
+
|
|
|
+
|
|
|
+def test_import_theme_form_is_displayed(db, admin_client):
|
|
|
+ response = admin_client.get(import_link)
|
|
|
+ assert_contains(response, "Import theme")
|
|
|
+
|
|
|
+
|
|
|
+def test_theme_import_fails_if_export_was_not_uploaded(db, admin_client):
|
|
|
+ admin_client.post(import_link, {"upload": None})
|
|
|
+ assert Theme.objects.count() == 1
|
|
|
+
|
|
|
+
|
|
|
+def test_empty_theme_export_can_be_imported_back(reimport_theme, theme):
|
|
|
+ assert reimport_theme(theme)
|
|
|
+
|
|
|
+
|
|
|
+def test_theme_can_be_imported_with_custom_name(reimport_theme, theme):
|
|
|
+ imported_theme = reimport_theme(theme, {"name": "Imported theme"})
|
|
|
+ assert imported_theme.name == "Imported theme"
|
|
|
+
|
|
|
+
|
|
|
+def test_theme_can_be_imported_without_parent(reimport_theme, theme):
|
|
|
+ imported_theme = reimport_theme(theme)
|
|
|
+ assert imported_theme.parent is None
|
|
|
+
|
|
|
+
|
|
|
+def test_theme_can_be_imported_with_custom_parent(reimport_theme, theme):
|
|
|
+ imported_theme = reimport_theme(theme, {"parent": theme.pk})
|
|
|
+ assert imported_theme.parent == theme
|
|
|
+
|
|
|
+
|
|
|
+def test_theme_can_be_imported_with_default_theme_asparent(
|
|
|
+ reimport_theme, theme, default_theme
|
|
|
+):
|
|
|
+ imported_theme = reimport_theme(theme, {"parent": default_theme.pk})
|
|
|
+ assert imported_theme.parent == default_theme
|
|
|
+
|
|
|
+
|
|
|
+def test_theme_import_fails_if_parent_is_nonexisisting(
|
|
|
+ reimport_theme, theme, nonexisting_theme
|
|
|
+):
|
|
|
+ assert not reimport_theme(theme, {"parent": nonexisting_theme.pk})
|
|
|
+
|
|
|
+
|
|
|
+def test_importing_theme_under_parent_rebuilds_themes_tree(reimport_theme, theme):
|
|
|
+ imported_theme = reimport_theme(theme, {"parent": theme.pk})
|
|
|
+ theme.refresh_from_db()
|
|
|
+
|
|
|
+ assert imported_theme.tree_id == theme.tree_id
|
|
|
+ assert theme.lft == 1
|
|
|
+ assert theme.rght == 4
|
|
|
+ assert imported_theme.lft == 2
|
|
|
+ assert imported_theme.rght == 3
|
|
|
+
|
|
|
+
|
|
|
+def test_theme_details_are_exported_and_imported_back(reimport_theme, theme):
|
|
|
+ theme.name = "Exported Theme"
|
|
|
+ theme.version = "0.1.2 FINAL"
|
|
|
+ theme.author = "John Doe"
|
|
|
+ theme.url = "https://example.com"
|
|
|
+ theme.save()
|
|
|
+
|
|
|
+ imported_theme = reimport_theme(theme)
|
|
|
+
|
|
|
+ assert imported_theme.name == theme.name
|
|
|
+ assert imported_theme.version == theme.version
|
|
|
+ assert imported_theme.author == theme.author
|
|
|
+ assert imported_theme.url == theme.url
|
|
|
+
|
|
|
+
|
|
|
+def test_imported_theme_has_own_dirname(reimport_theme, theme):
|
|
|
+ imported_theme = reimport_theme(theme)
|
|
|
+ assert theme.dirname != imported_theme.dirname
|
|
|
+
|
|
|
+
|
|
|
+def test_css_file_is_exported_and_imported_back(reimport_theme, theme, css):
|
|
|
+ imported_theme = reimport_theme(theme)
|
|
|
+
|
|
|
+ imported_css = imported_theme.css.last()
|
|
|
+ assert imported_css.name == css.name
|
|
|
+ assert imported_css.source_hash == css.source_hash
|
|
|
+ assert imported_css.size == css.size
|
|
|
+
|
|
|
+ assert_filenames_are_same(css.source_file, imported_css.source_file)
|
|
|
+
|
|
|
+
|
|
|
+def test_css_link_is_exported_and_imported_back(reimport_theme, theme, css_link):
|
|
|
+ imported_theme = reimport_theme(theme)
|
|
|
+
|
|
|
+ imported_css = imported_theme.css.last()
|
|
|
+ assert imported_css.name == css_link.name
|
|
|
+ assert imported_css.url == css_link.url
|
|
|
+
|
|
|
+
|
|
|
+def test_theme_export_containing_css_file_and_link_can_be_imported_back(
|
|
|
+ reimport_theme, theme, css, css_link
|
|
|
+):
|
|
|
+ imported_theme = reimport_theme(theme)
|
|
|
+ css_names = list(imported_theme.css.values_list("name", flat=True))
|
|
|
+ assert css_names == [css.name, css_link.name]
|
|
|
+
|
|
|
+
|
|
|
+def test_theme_css_order_is_preserved_after_import(
|
|
|
+ reimport_theme, theme, css, css_link
|
|
|
+):
|
|
|
+ css_link.order = 1
|
|
|
+ css_link.save()
|
|
|
+
|
|
|
+ css.order = 2
|
|
|
+ css.save()
|
|
|
+
|
|
|
+ imported_theme = reimport_theme(theme)
|
|
|
+ css_names = list(imported_theme.css.values_list("name", flat=True))
|
|
|
+ assert css_names == [css_link.name, css.name]
|
|
|
+
|
|
|
+
|
|
|
+def test_theme_export_containing_media_file_can_be_imported_back(
|
|
|
+ reimport_theme, theme, media
|
|
|
+):
|
|
|
+ imported_theme = reimport_theme(theme)
|
|
|
+
|
|
|
+ imported_media = imported_theme.media.last()
|
|
|
+ assert imported_media.name == media.name
|
|
|
+ assert imported_media.hash == media.hash
|
|
|
+ assert imported_media.type == media.type
|
|
|
+ assert imported_media.size == media.size
|
|
|
+
|
|
|
+ assert_filenames_are_same(media.file, imported_media.file)
|
|
|
+
|
|
|
+
|
|
|
+def test_theme_export_containing_image_file_can_be_imported_back(
|
|
|
+ reimport_theme, theme, image
|
|
|
+):
|
|
|
+ imported_theme = reimport_theme(theme)
|
|
|
+
|
|
|
+ imported_image = imported_theme.media.last()
|
|
|
+ assert imported_image.name == image.name
|
|
|
+ assert imported_image.hash == image.hash
|
|
|
+ assert imported_image.type == image.type
|
|
|
+ assert imported_image.width == image.width
|
|
|
+ assert imported_image.height == image.height
|
|
|
+ assert imported_image.size == image.size
|
|
|
+
|
|
|
+ assert_filenames_are_same(image.file, imported_image.file)
|
|
|
+
|
|
|
+
|
|
|
+def test_theme_export_containing_different_files_can_be_imported_back(
|
|
|
+ reimport_theme, theme, css, css_link, media, image
|
|
|
+):
|
|
|
+ imported_theme = reimport_theme(theme)
|
|
|
+
|
|
|
+ css_names = list(imported_theme.css.values_list("name", flat=True))
|
|
|
+ assert css_names == [css.name, css_link.name]
|
|
|
+
|
|
|
+ media_names = list(imported_theme.media.values_list("name", flat=True))
|
|
|
+ assert media_names == [image.name, media.name]
|