Commit 511de8a8 by Saleem Latif Committed by Matt Drayer

saleem-latif/Update Otto Theming app so that COMPREHENSIVE_THEME_DIRS is a list of directories

* mattdrayer: Refactor is_comprehensive_theming_enabled() check
parent 8e5f1d51
...@@ -103,14 +103,14 @@ It is up to you where to install the theme on the server, but a good default loc ...@@ -103,14 +103,14 @@ It is up to you where to install the theme on the server, but a good default loc
All themes must reside in the same physical directory. All themes must reside in the same physical directory.
In order for Otto to use the installed themes, you must specify the location of the theme directory in In order for Otto to use the installed themes, you must specify the location of the theme directory in
Django settings by setting COMPREHENSIVE_THEME_DIR in your settings file: Django settings by setting COMPREHENSIVE_THEME_DIRS in your settings file:
.. code-block:: python .. code-block:: python
COMPREHENSIVE_THEME_DIR = "/edx/app/ecommerce/ecommerce/themes" COMPREHENSIVE_THEME_DIRS = ["/edx/app/ecommerce/ecommerce/themes", ]
Where ``/edx/app/ecommerce/ecommerce/themes`` is the path to where you have installed the Where ``/edx/app/ecommerce/ecommerce/themes`` is the path to where you have installed the
themes on your server. themes on your server. You can list any/all theme directories through this setting.
After installing a theme, it is associated with sites by adding appropriate entries to the following tables After installing a theme, it is associated with sites by adding appropriate entries to the following tables
...@@ -195,9 +195,9 @@ Troubleshooting ...@@ -195,9 +195,9 @@ Troubleshooting
--------------- ---------------
If you have gone through the above procedure and you are not seeing theme overrides, you need to make sure If you have gone through the above procedure and you are not seeing theme overrides, you need to make sure
- ``COMPREHENSIVE_THEME_DIR`` must be path for the directory containing all themes e.g. if your theme is - ``COMPREHENSIVE_THEME_DIRS`` must contain path for the directory containing themes e.g. if your theme is
``/edx/app/ecommerce/ecommerce/themes/my-theme`` then correct value for ``COMPREHENSIVE_THEME_DIR`` is ``/edx/app/ecommerce/ecommerce/themes/my-theme`` then correct value for ``COMPREHENSIVE_THEME_DIRS`` is
``/edx/app/ecommerce/ecommerce/themes``. ``['/edx/app/ecommerce/ecommerce/themes']``.
- ``domain`` name for site is the name users will put in the browser to access the site, it also includes port number - ``domain`` name for site is the name users will put in the browser to access the site, it also includes port number
e.g. if Otto is running on ``localhost:8002`` then domain should be ``localhost:8002`` e.g. if Otto is running on ``localhost:8002`` then domain should be ``localhost:8002``
- Theme dir name is the name of the directory of you theme, for our ongoing example ``my-theme`` - Theme dir name is the name of the directory of you theme, for our ongoing example ``my-theme``
......
...@@ -18,6 +18,6 @@ class CoreContextProcessorTests(TestCase): ...@@ -18,6 +18,6 @@ class CoreContextProcessorTests(TestCase):
'lms_base_url': get_lms_url(), 'lms_base_url': get_lms_url(),
'lms_dashboard_url': get_lms_dashboard_url(), 'lms_dashboard_url': get_lms_dashboard_url(),
'platform_name': request.site.name, 'platform_name': request.site.name,
'support_url': SUPPORT_URL 'support_url': SUPPORT_URL,
} }
) )
...@@ -219,6 +219,7 @@ MIDDLEWARE_CLASSES = ( ...@@ -219,6 +219,7 @@ MIDDLEWARE_CLASSES = (
'social.apps.django_app.middleware.SocialAuthExceptionMiddleware', 'social.apps.django_app.middleware.SocialAuthExceptionMiddleware',
'simple_history.middleware.HistoryRequestMiddleware', 'simple_history.middleware.HistoryRequestMiddleware',
'threadlocals.middleware.ThreadLocalMiddleware', 'threadlocals.middleware.ThreadLocalMiddleware',
'ecommerce.theming.middleware.CurrentSiteThemeMiddleware',
) )
# END MIDDLEWARE CONFIGURATION # END MIDDLEWARE CONFIGURATION
...@@ -513,7 +514,9 @@ ENABLE_COMPREHENSIVE_THEMING = True ...@@ -513,7 +514,9 @@ ENABLE_COMPREHENSIVE_THEMING = True
DISABLE_THEMING_ON_RUNTIME_SWITCH = "disable_theming_on_runtime" DISABLE_THEMING_ON_RUNTIME_SWITCH = "disable_theming_on_runtime"
# Directory that contains all themes # Directory that contains all themes
COMPREHENSIVE_THEME_DIR = DJANGO_ROOT + "/themes" COMPREHENSIVE_THEME_DIRS = [
DJANGO_ROOT + "/themes",
]
# Theme to use when no site or site theme is defined, # Theme to use when no site or site theme is defined,
# set to None if you want to use openedx theme # set to None if you want to use openedx theme
......
from __future__ import absolute_import from __future__ import absolute_import
from path import Path
from ecommerce.settings.base import * from ecommerce.settings.base import *
from ecommerce.settings.logger import get_logger_config from ecommerce.settings.logger import get_logger_config
...@@ -128,5 +130,9 @@ COMPRESS_ENABLED = True ...@@ -128,5 +130,9 @@ COMPRESS_ENABLED = True
COMPRESS_OFFLINE = True COMPRESS_OFFLINE = True
# Comprehensive theme settings for testing environment # Comprehensive theme settings for testing environment
COMPREHENSIVE_THEME_DIR = DJANGO_ROOT + "/tests/themes" COMPREHENSIVE_THEME_DIRS = [
Path(DJANGO_ROOT + "/tests/themes"),
Path(DJANGO_ROOT + "/tests/themes-dir-2"),
]
DEFAULT_SITE_THEME = "test-theme" DEFAULT_SITE_THEME = "test-theme"
# this file is to add conf/local dir to git, currently there is no file to ignore.
@import 'ecommerce/static/sass/partials/utilities/variables';
// Theme Overrides
$body-bg: #fa6088;
$navbar-default-bg: #fa6088;
$container-bg: #fa6088;
{% extends "edx/base.html" %}
{% block title %}Test Theme 2{% endblock title %}
<!-- This template is for demonstration and testing purposes only and should not be used in production -->
{% block content %}
<div>This is third Test Theme in a separate theme directory.</div>
{% endblock %}
...@@ -4,7 +4,7 @@ Module for code that should run during application startup ...@@ -4,7 +4,7 @@ Module for code that should run during application startup
from django.apps import AppConfig from django.apps import AppConfig
from ecommerce.theming.core import enable_theming from ecommerce.theming.core import enable_theming
from ecommerce.theming.helpers import get_base_themes_dir, is_comprehensive_theming_enabled from ecommerce.theming.helpers import is_comprehensive_theming_enabled
class ThemeAppConfig(AppConfig): class ThemeAppConfig(AppConfig):
...@@ -22,6 +22,4 @@ class ThemeAppConfig(AppConfig): ...@@ -22,6 +22,4 @@ class ThemeAppConfig(AppConfig):
if is_comprehensive_theming_enabled(): if is_comprehensive_theming_enabled():
# proceed only if comprehensive theming in enabled # proceed only if comprehensive theming in enabled
enable_theming( enable_theming()
themes_dir=get_base_themes_dir(),
)
...@@ -10,10 +10,12 @@ def offline_context(): ...@@ -10,10 +10,12 @@ def offline_context():
offline context for compress management command, offline_context function iterates offline context for compress management command, offline_context function iterates
through all applied themes and returns a separate context for each theme. through all applied themes and returns a separate context for each theme.
""" """
main_css_path = "css/base/main.css"
swagger_css_path = "css/base/edx-swagger.css"
for theme in get_themes(): for theme in get_themes():
main_css = ThemeStorage(prefix=theme.theme_dir).url("css/base/main.css") main_css = ThemeStorage(prefix=theme.theme_dir_name).url(main_css_path)
swagger_css = ThemeStorage(prefix=theme.theme_dir).url("css/base/edx-swagger.css") swagger_css = ThemeStorage(prefix=theme.theme_dir_name).url(swagger_css_path)
yield { yield {
'main_css': main_css, 'main_css': main_css,
...@@ -21,6 +23,6 @@ def offline_context(): ...@@ -21,6 +23,6 @@ def offline_context():
} }
yield { yield {
'main_css': ThemeStorage().url("css/base/main.css"), 'main_css': ThemeStorage().url(main_css_path),
'swagger_css': ThemeStorage().url("css/base/edx-swagger.css"), 'swagger_css': ThemeStorage().url(swagger_css_path),
} }
...@@ -2,22 +2,15 @@ ...@@ -2,22 +2,15 @@
Core logic for Comprehensive Theming. Core logic for Comprehensive Theming.
""" """
from django.conf import settings from django.conf import settings
from path import Path
from ecommerce.theming.helpers import get_themes from ecommerce.theming.helpers import get_themes
def enable_theming(themes_dir): def enable_theming():
""" """
Add directories and relevant paths to settings for comprehensive theming. Add directories and relevant paths to settings for comprehensive theming.
Args:
themes_dir (str): path to base theme directory
""" """
if isinstance(themes_dir, basestring): for theme in get_themes():
themes_dir = Path(themes_dir) locale_dir = theme.path / "conf" / "locale"
for theme in get_themes(themes_dir):
locale_dir = themes_dir / theme.theme_dir / "conf" / "locale"
if locale_dir.isdir(): if locale_dir.isdir():
settings.LOCALE_PATHS = (locale_dir, ) + settings.LOCALE_PATHS settings.LOCALE_PATHS = (locale_dir, ) + settings.LOCALE_PATHS
...@@ -46,12 +46,12 @@ class ThemeFilesFinder(BaseFinder): ...@@ -46,12 +46,12 @@ class ThemeFilesFinder(BaseFinder):
for theme in themes: for theme in themes:
theme_storage = self.storage_class( theme_storage = self.storage_class(
os.path.join(theme.path, self.source_dir), os.path.join(theme.path, self.source_dir),
prefix=theme.theme_dir, prefix=theme.theme_dir_name,
) )
self.storages[theme.theme_dir] = theme_storage self.storages[theme.theme_dir_name] = theme_storage
if theme.theme_dir not in self.themes: if theme.theme_dir_name not in self.themes:
self.themes.append(theme.theme_dir) self.themes.append(theme.theme_dir_name)
super(ThemeFilesFinder, self).__init__(*args, **kwargs) super(ThemeFilesFinder, self).__init__(*args, **kwargs)
...@@ -71,12 +71,12 @@ class ThemeFilesFinder(BaseFinder): ...@@ -71,12 +71,12 @@ class ThemeFilesFinder(BaseFinder):
matches = [] matches = []
theme_dir = path.split("/", 1)[0] theme_dir = path.split("/", 1)[0]
themes = {t.theme_dir: t for t in get_themes()} themes = {t.theme_dir_name: t for t in get_themes()}
# if path is prefixed by theme name then search in the corresponding storage other wise search all storages. # if path is prefixed by theme name then search in the corresponding storage other wise search all storages.
if theme_dir in themes: if theme_dir in themes:
theme = themes[theme_dir] theme = themes[theme_dir]
path = "/".join(path.split("/")[1:]) path = "/".join(path.split("/")[1:])
match = self.find_in_theme(theme.theme_dir, path) match = self.find_in_theme(theme.theme_dir_name, path)
if match: if match:
if not all: if not all:
return match return match
......
...@@ -13,7 +13,7 @@ from django.core.management import call_command ...@@ -13,7 +13,7 @@ from django.core.management import call_command
import sass import sass
from path import Path from path import Path
from ecommerce.theming.helpers import get_themes, get_base_themes_dir, is_comprehensive_theming_enabled from ecommerce.theming.helpers import get_themes, get_theme_base_dirs, is_comprehensive_theming_enabled
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -107,7 +107,7 @@ class Command(BaseCommand): ...@@ -107,7 +107,7 @@ class Command(BaseCommand):
source_comments = options.get("source_comments", False) source_comments = options.get("source_comments", False)
collect = options.get("collect", True) collect = options.get("collect", True)
available_themes = {t.theme_dir: t for t in get_themes()} available_themes = {t.theme_dir_name: t for t in get_themes()}
if 'no' in given_themes or 'all' in given_themes: if 'no' in given_themes or 'all' in given_themes:
# Raise error if 'all' or 'no' is present and theme names are also given. # Raise error if 'all' or 'no' is present and theme names are also given.
...@@ -119,7 +119,7 @@ class Command(BaseCommand): ...@@ -119,7 +119,7 @@ class Command(BaseCommand):
raise CommandError( raise CommandError(
"Given themes '{invalid_themes}' do not exist inside themes directory '{themes_dir}'".format( "Given themes '{invalid_themes}' do not exist inside themes directory '{themes_dir}'".format(
invalid_themes=", ".join(set(given_themes) - set(available_themes.keys())), invalid_themes=", ".join(set(given_themes) - set(available_themes.keys())),
themes_dir=get_base_themes_dir(), themes_dir=get_theme_base_dirs(),
), ),
) )
......
"""
Middleware for theming app
Note:
This middleware depends on "django_sites_extensions.middleware.CurrentSiteWithDefaultMiddleware" middleware
So it must be added after this middleware in django settings files.
"""
from ecommerce.theming.models import SiteTheme
class CurrentSiteThemeMiddleware(object):
"""
Middleware that sets `site_theme` attribute to request object.
"""
def process_request(self, request):
request.site_theme = SiteTheme.get_theme(request.site)
...@@ -8,7 +8,7 @@ from django.conf import settings ...@@ -8,7 +8,7 @@ from django.conf import settings
from django.utils._os import safe_join from django.utils._os import safe_join
from django.contrib.staticfiles.storage import StaticFilesStorage from django.contrib.staticfiles.storage import StaticFilesStorage
from ecommerce.theming.helpers import get_current_site_theme_dir, get_base_themes_dir, is_comprehensive_theming_enabled from ecommerce.theming.helpers import get_current_theme, get_theme_base_dir, is_comprehensive_theming_enabled
class ThemeStorage(StaticFilesStorage): class ThemeStorage(StaticFilesStorage):
...@@ -45,11 +45,11 @@ class ThemeStorage(StaticFilesStorage): ...@@ -45,11 +45,11 @@ class ThemeStorage(StaticFilesStorage):
is provided by red-theme otherwise '/static/images/logo.png' is provided by red-theme otherwise '/static/images/logo.png'
""" """
prefix = '' prefix = ''
theme_dir = get_current_site_theme_dir() theme = get_current_theme()
# get theme prefix from site address if if asset is accessed via a url # get theme prefix from site address if if asset is accessed via a url
if theme_dir: if theme:
prefix = theme_dir prefix = theme.theme_dir_name
# get theme prefix from storage class, if asset is accessed during collectstatic run # get theme prefix from storage class, if asset is accessed during collectstatic run
elif self.prefix: elif self.prefix:
...@@ -76,7 +76,7 @@ class ThemeStorage(StaticFilesStorage): ...@@ -76,7 +76,7 @@ class ThemeStorage(StaticFilesStorage):
# in debug mode check static asset from within the project directory # in debug mode check static asset from within the project directory
if settings.DEBUG: if settings.DEBUG:
themes_location = get_base_themes_dir() themes_location = get_theme_base_dir(theme, suppress_error=True)
# Nothing can be themed if we don't have a theme location or required params. # Nothing can be themed if we don't have a theme location or required params.
if not all((themes_location, theme, name)): if not all((themes_location, theme, name)):
return False return False
......
...@@ -7,7 +7,7 @@ from django.template.loaders.filesystem import Loader as FilesystemLoader ...@@ -7,7 +7,7 @@ from django.template.loaders.filesystem import Loader as FilesystemLoader
from threadlocals.threadlocals import get_current_request from threadlocals.threadlocals import get_current_request
from ecommerce.theming.helpers import get_current_theme_template_dirs, get_all_theme_template_dirs from ecommerce.theming.helpers import get_current_theme, get_all_theme_template_dirs
class ThemeTemplateLoader(FilesystemLoader): class ThemeTemplateLoader(FilesystemLoader):
...@@ -45,10 +45,11 @@ class ThemeTemplateLoader(FilesystemLoader): ...@@ -45,10 +45,11 @@ class ThemeTemplateLoader(FilesystemLoader):
Return template sources for the given theme and if request object is None (this would be the case for Return template sources for the given theme and if request object is None (this would be the case for
management commands) return template sources for all themes. management commands) return template sources for all themes.
""" """
if not get_current_request(): if get_current_request():
# template is being accessed by a view, so return templates sources for current theme
theme = get_current_theme()
return theme and theme.template_dirs
else:
# if request object is not present, then this method is being called inside a management # if request object is not present, then this method is being called inside a management
# command and return all theme template sources for compression # command and return all theme template sources for compression
return get_all_theme_template_dirs() return get_all_theme_template_dirs()
else:
# template is being accessed by a view, so return templates sources for current theme
return get_current_theme_template_dirs()
...@@ -5,6 +5,7 @@ import re ...@@ -5,6 +5,7 @@ import re
from functools import wraps from functools import wraps
from mock import patch from mock import patch
from django.core.management import call_command
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from .models import SiteTheme from .models import SiteTheme
...@@ -23,10 +24,17 @@ def with_comprehensive_theme(theme_dir_name): ...@@ -23,10 +24,17 @@ def with_comprehensive_theme(theme_dir_name):
# make a domain name out of directory name # make a domain name out of directory name
domain = "{theme_dir_name}.org".format(theme_dir_name=re.sub(r"\.org$", "", theme_dir_name)) domain = "{theme_dir_name}.org".format(theme_dir_name=re.sub(r"\.org$", "", theme_dir_name))
site, __ = Site.objects.get_or_create(domain=domain, name=domain) site, __ = Site.objects.get_or_create(domain=domain, name=domain)
SiteTheme.objects.get_or_create(site=site, theme_dir_name=theme_dir_name) site_theme, __ = SiteTheme.objects.get_or_create(site=site, theme_dir_name=theme_dir_name)
with patch('ecommerce.theming.helpers.get_current_site_theme_dir', with patch('ecommerce.theming.helpers.get_current_site_theme',
return_value=theme_dir_name): return_value=site_theme):
with patch('ecommerce.theming.helpers.get_current_site', return_value=site): return func(*args, **kwargs)
return func(*args, **kwargs)
return _decorated return _decorated
return _decorator return _decorator
def compile_sass():
"""
Call update assets command to compile system and theme sass.
"""
# Compile system and theme sass files
call_command('update_assets', '--skip-collect')
...@@ -6,8 +6,6 @@ import mock ...@@ -6,8 +6,6 @@ import mock
from django.conf import settings from django.conf import settings
from django.test import TestCase, override_settings from django.test import TestCase, override_settings
from path import Path
from ecommerce.theming.apps import ThemeAppConfig from ecommerce.theming.apps import ThemeAppConfig
from ecommerce import theming from ecommerce import theming
...@@ -21,11 +19,13 @@ class TestThemeAppConfig(TestCase): ...@@ -21,11 +19,13 @@ class TestThemeAppConfig(TestCase):
""" """
Tests enable theming is called in app config's ready method. Tests enable theming is called in app config's ready method.
""" """
themes_dir = Path(settings.COMPREHENSIVE_THEME_DIR) themes_dirs = settings.COMPREHENSIVE_THEME_DIRS
# make sure locale paths were added to LOCALE_PATHS setting # make sure locale paths were added to LOCALE_PATHS setting
self.assertIn(themes_dir / "test-theme" / "conf" / "locale", settings.LOCALE_PATHS) self.assertIn(themes_dirs[0] / "test-theme" / "conf" / "locale", settings.LOCALE_PATHS)
self.assertIn(themes_dir / "test-theme-2" / "conf" / "locale", settings.LOCALE_PATHS) self.assertIn(themes_dirs[0] / "test-theme-2" / "conf" / "locale", settings.LOCALE_PATHS)
self.assertIn(themes_dirs[1] / "test-theme-3" / "conf" / "locale", settings.LOCALE_PATHS)
class TestThemeAppConfigThemingDisabled(TestCase): class TestThemeAppConfigThemingDisabled(TestCase):
...@@ -36,14 +36,11 @@ class TestThemeAppConfigThemingDisabled(TestCase): ...@@ -36,14 +36,11 @@ class TestThemeAppConfigThemingDisabled(TestCase):
""" """
Tests that method `ready` invokes `enable_theming` method Tests that method `ready` invokes `enable_theming` method
""" """
themes_dir = Path(settings.COMPREHENSIVE_THEME_DIR)
config = ThemeAppConfig('theming', theming) config = ThemeAppConfig('theming', theming)
with mock.patch('ecommerce.theming.apps.enable_theming') as mock_enable_theming: with mock.patch('ecommerce.theming.apps.enable_theming') as mock_enable_theming:
config.ready() config.ready()
self.assertTrue(mock_enable_theming.called) self.assertTrue(mock_enable_theming.called)
mock_enable_theming.assert_called_once_with(themes_dir=themes_dir)
@override_settings(ENABLE_COMPREHENSIVE_THEMING=False) @override_settings(ENABLE_COMPREHENSIVE_THEMING=False)
def test_ready_with_theming_disabled(self): def test_ready_with_theming_disabled(self):
......
...@@ -56,7 +56,7 @@ class TestUpdateAssets(TestCase): ...@@ -56,7 +56,7 @@ class TestUpdateAssets(TestCase):
# make sure update_assets picks only specified themes # make sure update_assets picks only specified themes
parsed_args = Command.parse_arguments(themes=["test-theme"]) parsed_args = Command.parse_arguments(themes=["test-theme"])
self.assertEqual(parsed_args[0], [theme for theme in get_themes() if theme.theme_dir == "test-theme"]) self.assertEqual(parsed_args[0], [theme for theme in get_themes() if theme.theme_dir_name == "test-theme"])
def test_skip_theme_sass_when_theming_is_disabled(self): def test_skip_theme_sass_when_theming_is_disabled(self):
""" """
...@@ -75,7 +75,7 @@ class TestUpdateAssets(TestCase): ...@@ -75,7 +75,7 @@ class TestUpdateAssets(TestCase):
""" """
Test that proper sass dirs are returned by get_sass_directories Test that proper sass dirs are returned by get_sass_directories
""" """
themes_dir = Path(settings.COMPREHENSIVE_THEME_DIR) themes_dirs = settings.COMPREHENSIVE_THEME_DIRS
expected_directories = [ expected_directories = [
{ {
...@@ -85,19 +85,24 @@ class TestUpdateAssets(TestCase): ...@@ -85,19 +85,24 @@ class TestUpdateAssets(TestCase):
}, },
{ {
"sass_source_dir": Path("ecommerce/static/sass/base"), "sass_source_dir": Path("ecommerce/static/sass/base"),
"css_destination_dir": themes_dir / "test-theme" / "static" / "css" / "base", "css_destination_dir": themes_dirs[0] / "test-theme" / "static" / "css" / "base",
"lookup_paths": [themes_dir / "test-theme" / "static" / "sass" / "partials"] + SYSTEM_SASS_PATHS, "lookup_paths": [themes_dirs[0] / "test-theme" / "static" / "sass" / "partials"] + SYSTEM_SASS_PATHS,
}, },
{ {
"sass_source_dir": Path("ecommerce/static/sass/base"), "sass_source_dir": Path("ecommerce/static/sass/base"),
"css_destination_dir": themes_dir / "test-theme-2" / "static" / "css" / "base", "css_destination_dir": themes_dirs[0] / "test-theme-2" / "static" / "css" / "base",
"lookup_paths": [themes_dir / "test-theme-2" / "static" / "sass" / "partials"] + SYSTEM_SASS_PATHS, "lookup_paths": [themes_dirs[0] / "test-theme-2" / "static" / "sass" / "partials"] + SYSTEM_SASS_PATHS,
}, },
{ {
"sass_source_dir": themes_dir / "test-theme-2" / "static" / "sass" / "base", "sass_source_dir": themes_dirs[0] / "test-theme-2" / "static" / "sass" / "base",
"css_destination_dir": themes_dir / "test-theme-2" / "static" / "css" / "base", "css_destination_dir": themes_dirs[0] / "test-theme-2" / "static" / "css" / "base",
"lookup_paths": [themes_dir / "test-theme-2" / "static" / "sass" / "partials"] + SYSTEM_SASS_PATHS, "lookup_paths": [themes_dirs[0] / "test-theme-2" / "static" / "sass" / "partials"] + SYSTEM_SASS_PATHS,
} },
{
"sass_source_dir": Path("ecommerce/static/sass/base"),
"css_destination_dir": themes_dirs[1] / "test-theme-3" / "static" / "css" / "base",
"lookup_paths": [themes_dirs[1] / "test-theme-3" / "static" / "sass" / "partials"] + SYSTEM_SASS_PATHS,
},
] ]
returned_dirs = get_sass_directories(themes=self.themes, system=True) returned_dirs = get_sass_directories(themes=self.themes, system=True)
...@@ -123,7 +128,7 @@ class TestUpdateAssets(TestCase): ...@@ -123,7 +128,7 @@ class TestUpdateAssets(TestCase):
""" """
Test ValueError is raised if sass directory provided to the compile_sass method does not exist. Test ValueError is raised if sass directory provided to the compile_sass method does not exist.
""" """
themes_dir = Path(settings.COMPREHENSIVE_THEME_DIR) themes_dir = settings.COMPREHENSIVE_THEME_DIRS[0]
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
compile_sass( compile_sass(
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
Comprehensive Theming tests for core functionality. Comprehensive Theming tests for core functionality.
""" """
from django.conf import settings from django.conf import settings
from django.test import override_settings
from path import Path from path import Path
from ecommerce.tests.testcases import TestCase from ecommerce.tests.testcases import TestCase
...@@ -17,14 +18,15 @@ class TestCore(TestCase): ...@@ -17,14 +18,15 @@ class TestCore(TestCase):
""" """
Tests for enable_theming method. Tests for enable_theming method.
""" """
themes_dir = Path(settings.COMPREHENSIVE_THEME_DIR) themes_dirs = settings.COMPREHENSIVE_THEME_DIRS
expected_locale_paths = ( expected_locale_paths = (
themes_dir / "test-theme" / "conf" / "locale", themes_dirs[0] / "test-theme" / "conf" / "locale",
themes_dir / "test-theme-2" / "conf" / "locale", themes_dirs[0] / "test-theme-2" / "conf" / "locale",
themes_dirs[1] / "test-theme-3" / "conf" / "locale",
) + settings.LOCALE_PATHS ) + settings.LOCALE_PATHS
enable_theming(settings.COMPREHENSIVE_THEME_DIR) enable_theming()
self.assertItemsEqual(expected_locale_paths, settings.LOCALE_PATHS) self.assertItemsEqual(expected_locale_paths, settings.LOCALE_PATHS)
...@@ -37,7 +39,8 @@ class TestCore(TestCase): ...@@ -37,7 +39,8 @@ class TestCore(TestCase):
# Note: red-theme does not contain translations dir # Note: red-theme does not contain translations dir
red_theme = Path(themes_dir + "/red-theme") red_theme = Path(themes_dir + "/red-theme")
enable_theming(red_theme.dirname()) with override_settings(COMPREHENSIVE_THEME_DIRS=[red_theme.dirname()]):
enable_theming()
# Test that locale path is added only if it exists # Test that locale path is added only if it exists
self.assertNotIn(red_theme / "conf" / "locale", settings.LOCALE_PATHS) self.assertNotIn(red_theme / "conf" / "locale", settings.LOCALE_PATHS)
...@@ -3,7 +3,6 @@ Tests for comprehensive theme static files finders. ...@@ -3,7 +3,6 @@ Tests for comprehensive theme static files finders.
""" """
from django.conf import settings from django.conf import settings
from django.test import TestCase from django.test import TestCase
from path import Path
from ecommerce.theming.finders import ThemeFilesFinder from ecommerce.theming.finders import ThemeFilesFinder
...@@ -21,7 +20,7 @@ class TestThemeFinders(TestCase): ...@@ -21,7 +20,7 @@ class TestThemeFinders(TestCase):
""" """
Verify Theme Finder returns themed assets Verify Theme Finder returns themed assets
""" """
themes_dir = Path(settings.COMPREHENSIVE_THEME_DIR) themes_dir = settings.COMPREHENSIVE_THEME_DIRS[0]
asset = "test-theme/images/default-logo.png" asset = "test-theme/images/default-logo.png"
match = self.finder.find(asset) match = self.finder.find(asset)
...@@ -31,7 +30,7 @@ class TestThemeFinders(TestCase): ...@@ -31,7 +30,7 @@ class TestThemeFinders(TestCase):
""" """
Verify Theme Finder returns themed assets Verify Theme Finder returns themed assets
""" """
themes_dir = Path(settings.COMPREHENSIVE_THEME_DIR) themes_dir = settings.COMPREHENSIVE_THEME_DIRS[0]
asset = "test-theme/images/default-logo.png" asset = "test-theme/images/default-logo.png"
matches = self.finder.find(asset, all=True) matches = self.finder.find(asset, all=True)
...@@ -45,7 +44,7 @@ class TestThemeFinders(TestCase): ...@@ -45,7 +44,7 @@ class TestThemeFinders(TestCase):
""" """
Verify find in theme method of finders returns asset from specified theme Verify find in theme method of finders returns asset from specified theme
""" """
themes_dir = Path(settings.COMPREHENSIVE_THEME_DIR) themes_dir = settings.COMPREHENSIVE_THEME_DIRS[0]
asset = "images/default-logo.png" asset = "images/default-logo.png"
match = self.finder.find_in_theme("test-theme", asset) match = self.finder.find_in_theme("test-theme", asset)
......
...@@ -5,10 +5,10 @@ from mock import patch ...@@ -5,10 +5,10 @@ from mock import patch
from django.test import override_settings from django.test import override_settings
from django.conf import settings from django.conf import settings
from path import Path
from ecommerce.tests.testcases import TestCase from ecommerce.tests.testcases import TestCase
from ecommerce.theming.storage import ThemeStorage from ecommerce.theming.storage import ThemeStorage
from ecommerce.theming.helpers import Theme, get_theme_base_dir
@override_settings(DEBUG=True) @override_settings(DEBUG=True)
...@@ -19,7 +19,7 @@ class TestThemeStorage(TestCase): ...@@ -19,7 +19,7 @@ class TestThemeStorage(TestCase):
def setUp(self): def setUp(self):
super(TestThemeStorage, self).setUp() super(TestThemeStorage, self).setUp()
self.themes_dir = Path(settings.COMPREHENSIVE_THEME_DIR) self.themes_dir = settings.COMPREHENSIVE_THEME_DIRS[0]
self.enabled_theme = "test-theme" self.enabled_theme = "test-theme"
self.storage = ThemeStorage(location=self.themes_dir / self.enabled_theme / 'static') self.storage = ThemeStorage(location=self.themes_dir / self.enabled_theme / 'static')
...@@ -60,8 +60,8 @@ class TestThemeStorage(TestCase): ...@@ -60,8 +60,8 @@ class TestThemeStorage(TestCase):
""" """
asset = "images/default-logo.png" asset = "images/default-logo.png"
with patch( with patch(
"ecommerce.theming.storage.get_current_site_theme_dir", "ecommerce.theming.storage.get_current_theme",
return_value=self.enabled_theme, return_value=Theme(self.enabled_theme, self.enabled_theme, get_theme_base_dir(self.enabled_theme)),
): ):
asset_url = self.storage.url(asset) asset_url = self.storage.url(asset)
# remove hash key from file url # remove hash key from file url
...@@ -75,8 +75,8 @@ class TestThemeStorage(TestCase): ...@@ -75,8 +75,8 @@ class TestThemeStorage(TestCase):
""" """
asset = "images/default-logo.png" asset = "images/default-logo.png"
with patch( with patch(
"ecommerce.theming.storage.get_current_site_theme_dir", "ecommerce.theming.storage.get_current_theme",
return_value=self.enabled_theme, return_value=Theme(self.enabled_theme, self.enabled_theme, get_theme_base_dir(self.enabled_theme)),
): ):
returned_path = self.storage.path(asset) returned_path = self.storage.path(asset)
expected_path = self.themes_dir / self.enabled_theme / "static" / asset expected_path = self.themes_dir / self.enabled_theme / "static" / asset
......
...@@ -5,10 +5,9 @@ from django.conf import settings ...@@ -5,10 +5,9 @@ from django.conf import settings
from django.test import override_settings from django.test import override_settings
from django.contrib import staticfiles from django.contrib import staticfiles
from django.core.management import call_command from django.core.management import call_command
from path import Path
from ecommerce.tests.testcases import TestCase from ecommerce.tests.testcases import TestCase
from ecommerce.theming.test_utils import with_comprehensive_theme from ecommerce.theming.test_utils import compile_sass
class TestComprehensiveTheme(TestCase): class TestComprehensiveTheme(TestCase):
...@@ -37,24 +36,25 @@ class TestComprehensiveTheme(TestCase): ...@@ -37,24 +36,25 @@ class TestComprehensiveTheme(TestCase):
# compile sass assets for test themes. # compile sass assets for test themes.
compile_sass() compile_sass()
# Compress test theme templates
call_command("compress")
super(TestComprehensiveTheme, cls).setUpClass() super(TestComprehensiveTheme, cls).setUpClass()
@with_comprehensive_theme("test-theme")
def test_templates(self): def test_templates(self):
""" """
Test that theme template overrides are applied. Test that theme template overrides are applied.
""" """
with override_settings(COMPRESS_OFFLINE=False, COMPRESS_ENABLED=False): resp = self.client.get('/dashboard/')
resp = self.client.get('/dashboard/') self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.status_code, 200) # This string comes from header.html of test-theme
# This string comes from header.html of test-theme self.assertContains(resp, "This is a Test Theme.")
self.assertContains(resp, "This is a Test Theme.")
def test_logo_image(self): def test_logo_image(self):
""" """
Test that theme logo is used instead of default logo. Test that theme logo is used instead of default logo.
""" """
themes_dir = Path(settings.COMPREHENSIVE_THEME_DIR) themes_dir = settings.COMPREHENSIVE_THEME_DIRS[0]
result = staticfiles.finders.find('test-theme/images/default-logo.png') result = staticfiles.finders.find('test-theme/images/default-logo.png')
self.assertEqual(result, themes_dir / "test-theme" / 'static/images/default-logo.png') self.assertEqual(result, themes_dir / "test-theme" / 'static/images/default-logo.png')
...@@ -63,7 +63,7 @@ class TestComprehensiveTheme(TestCase): ...@@ -63,7 +63,7 @@ class TestComprehensiveTheme(TestCase):
""" """
Test that theme sass files are used instead of default sass files. Test that theme sass files are used instead of default sass files.
""" """
themes_dir = Path(settings.COMPREHENSIVE_THEME_DIR) themes_dir = settings.COMPREHENSIVE_THEME_DIRS[0]
result = staticfiles.finders.find('test-theme/css/base/main.css') result = staticfiles.finders.find('test-theme/css/base/main.css')
self.assertEqual(result, themes_dir / "test-theme" / "static/css/base/main.css") self.assertEqual(result, themes_dir / "test-theme" / "static/css/base/main.css")
...@@ -74,11 +74,12 @@ class TestComprehensiveTheme(TestCase): ...@@ -74,11 +74,12 @@ class TestComprehensiveTheme(TestCase):
self.assertIn("background-color: #00fa00", main_css) self.assertIn("background-color: #00fa00", main_css)
def test_default_theme(self):
def compile_sass(): """
""" Test that theme template overrides are applied.
Call update assets command to compile system and theme sass. """
""" with override_settings(DEFAULT_SITE_THEME="test-theme-2"):
with override_settings(DEBUG=True): resp = self.client.get('/dashboard/')
# Compile system and theme sass files self.assertEqual(resp.status_code, 200)
call_command('update_assets') # This string comes from header.html of test-theme
self.assertContains(resp, "This is second Test Theme.")
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment