diff --git a/masonite/view.py b/masonite/view.py index a60b7d412..e5cdeea29 100644 --- a/masonite/view.py +++ b/masonite/view.py @@ -69,17 +69,40 @@ def render(self, template, dictionary={}): if self.container.has('Cache') and self.__cached_template_exists() and not self.__is_expired_cache(): return self.__get_cached_template() - if template in self.composers: - self.dictionary.update(self.composers[template]) - - if '*' in self.composers: - self.dictionary.update(self.composers['*']) + # Check if composers are even set for a speed improvement + if self.composers: + self._update_from_composers() self.rendered_template = self.env.get_template(filename).render( self.dictionary) return self + def _update_from_composers(self): + + # Check if the template is directly specified in the composer + if self.template in self.composers: + self.dictionary.update(self.composers[self.template]) + + # Check if there is just an astericks in the composer + if '*' in self.composers: + self.dictionary.update(self.composers['*']) + + # We will append onto this string for an easier way to search through wildcard routes + compiled_string = '' + + # Check for wildcard view composers + for template in self.template.split('/'): + # Append the template onto the compiled_string + compiled_string += template + if '{}*'.format(compiled_string) in self.composers: + self.dictionary.update(self.composers['{}*'.format(compiled_string)]) + else: + # Add a slash to symbolize going into a deeper directory structure + compiled_string += '/' + + + def composer(self, composer_name, dictionary): """ Updates composer dictionary diff --git a/resources/templates/mail/welcome.html b/resources/templates/mail/welcome.html index 730085422..10cef83bd 100644 --- a/resources/templates/mail/welcome.html +++ b/resources/templates/mail/welcome.html @@ -1,6 +1,7 @@ + to: {{ to }} diff --git a/tests/test_view.py b/tests/test_view.py index c1b870557..5dc00497a 100644 --- a/tests/test_view.py +++ b/tests/test_view.py @@ -10,197 +10,153 @@ import pytest -def test_view_compiles_jinja(): - assert view('test', {'test': 'test'}) == 'test' +class TestView: + def setup_method(self): + self.container = App() + view = View(self.container) -def test_view_extends_dictionary(): - container = App() + self.container.bind('View', view.render) + self.container.bind('ViewClass', view) - view = View(container) + def test_view_compiles_jinja(self): + assert view('test', {'test': 'test'}) == 'test' - container.bind('View', view.render) + def test_view_extends_dictionary(self): + view = self.container.make('View') - view = container.make('View') + assert view('test', {'test': 'test'}).rendered_template == 'test' - assert view('test', {'test': 'test'}).rendered_template == 'test' + def test_view_gets_global_template(self): + view = self.container.make('View') + assert view('/storage/test', {'test': 'test'}).rendered_template == 'test' + assert view('/storage/static/test', {'test': 'test'}).rendered_template == 'test' -def test_view_gets_global_template(): - container = App() + def test_view_extends_without_dictionary_parameters(self): + view = self.container.make('ViewClass') + view.share({'test': 'test'}) + view = self.container.make('View') - view = View(container) + assert view('test').rendered_template == 'test' - container.bind('View', view.render) + def test_render_from_container_as_view_class(self): + self.container.make('ViewClass').share({'test': 'test'}) - view = container.make('View') + view = self.container.make('View') + assert view('test').rendered_template == 'test' - assert view('/storage/test', {'test': 'test'}).rendered_template == 'test' - assert view('/storage/static/test', {'test': 'test'}).rendered_template == 'test' + def test_composers(self): + self.container.make('ViewClass').composer('test', {'test': 'test'}) + view = self.container.make('View') + assert self.container.make('ViewClass').composers == {'test': {'test': 'test'}} + assert view('test').rendered_template == 'test' -def test_view_extends_without_dictionary_parameters(): - container = App() + def test_composers_load_all_views_with_astericks(self): - view = View(container) - view.share({'test': 'test'}) + self.container.make('ViewClass').composer('*', {'test': 'test'}) - container.bind('View', view.render) + assert self.container.make('ViewClass').composers == {'*': {'test': 'test'}} - view = container.make('View') + view = self.container.make('View') + assert view('test').rendered_template == 'test' - assert view('test').rendered_template == 'test' + def test_composers_with_wildcard_base_view(self): + self.container.make('ViewClass').composer('mail*', {'to': 'test_user'}) + assert self.container.make('ViewClass').composers == {'mail*': {'to': 'test_user'}} -def test_render_from_container_as_view_class(): - container = App() + view = self.container.make('View') + assert 'test_user' in view('mail/welcome').rendered_template - ViewClass = View(container) + def test_composers_with_wildcard_lower_directory_view(self): + self.container.make('ViewClass').composer('mail/welcome*', {'to': 'test_user'}) - container.bind('ViewClass', ViewClass) - container.bind('View', ViewClass.render) + assert self.container.make('ViewClass').composers == {'mail/welcome*': {'to': 'test_user'}} - container.make('ViewClass').share({'test': 'test'}) + view = self.container.make('View') + assert 'test_user' in view('mail/welcome').rendered_template + + def test_composers_with_wildcard_lower_directory_view_and_incorrect_shortend_wildcard(self): + self.container.make('ViewClass').composer('mail/wel*', {'to': 'test_user'}) - view = container.make('View') - assert view('test').rendered_template == 'test' + assert self.container.make('ViewClass').composers == {'mail/wel*': {'to': 'test_user'}} + view = self.container.make('View') + assert 'test_user' not in view('mail/welcome').rendered_template -def test_composers(): - container = App() + def test_composers_load_all_views_with_list(self): + self.container.make('ViewClass').composer(['home', 'test'], {'test': 'test'}) - ViewClass = View(container) + assert self.container.make('ViewClass').composers == { + 'home': {'test': 'test'}, 'test': {'test': 'test'}} - container.bind('ViewClass', ViewClass) - container.bind('View', ViewClass.render) + view = self.container.make('View') + assert view('test').rendered_template == 'test' - container.make('ViewClass').composer('test', {'test': 'test'}) + def test_view_share_updates_dictionary_not_overwrite(self): + viewclass = self.container.make('ViewClass') - assert container.make('ViewClass').composers == {'test': {'test': 'test'}} + viewclass.share({'test1': 'test1'}) + viewclass.share({'test2': 'test2'}) - view = container.make('View') - assert view('test').rendered_template == 'test' + assert viewclass.dictionary == {'test1': 'test1', 'test2': 'test2'} + def test_view_throws_exception_without_cache_binding(self): + view = self.container.make('View') -def test_composers_load_all_views_with_astericks(): - container = App() + with pytest.raises(RequiredContainerBindingNotFound): + view('test_cache').cache_for('5', 'seconds') - ViewClass = View(container) + def test_view_cache_caches_files(self): - container.bind('ViewClass', ViewClass) - container.bind('View', ViewClass.render) + self.container.bind('CacheConfig', cache) + self.container.bind('CacheDiskDriver', CacheDiskDriver) + self.container.bind('CacheManager', CacheManager(self.container)) + self.container.bind('Application', self.container) + self.container.bind('Cache', self.container.make('CacheManager').driver('disk')) - container.make('ViewClass').composer('*', {'test': 'test'}) + view = self.container.make('View') - assert container.make('ViewClass').composers == {'*': {'test': 'test'}} + assert view( + 'test_cache', {'test': 'test'} + ).cache_for(1, 'second').rendered_template == 'test' - view = container.make('View') - assert view('test').rendered_template == 'test' + assert open(glob.glob('bootstrap/cache/test_cache:*')[0]).read() == 'test' + time.sleep(2) -def test_composers_load_all_views_with_list(): - container = App() + assert view( + 'test_cache', {'test': 'macho'} + ).cache_for(5, 'seconds').rendered_template == 'macho' - ViewClass = View(container) + time.sleep(2) - container.bind('ViewClass', ViewClass) - container.bind('View', ViewClass.render) + assert open(glob.glob('bootstrap/cache/test_cache:*')[0]).read() == 'macho' - container.make('ViewClass').composer(['home', 'test'], {'test': 'test'}) + assert view( + 'test_cache', {'test': 'macho'} + ).cache_for(1, 'second').rendered_template == 'macho' - assert container.make('ViewClass').composers == { - 'home': {'test': 'test'}, 'test': {'test': 'test'}} + time.sleep(1) - view = container.make('View') - assert view('test').rendered_template == 'test' + assert open(glob.glob('bootstrap/cache/test_cache:*')[0]).read() == 'macho' + assert view( + 'test_cache', {'test': 'macho'} + ).cache_for('1', 'second').rendered_template == 'macho' -def test_view_share_updates_dictionary_not_overwrite(): - container = App() + def test_cache_throws_exception_with_incorrect_cache_type(self): + self.container.bind('CacheConfig', cache) + self.container.bind('CacheDiskDriver', CacheDiskDriver) + self.container.bind('CacheManager', CacheManager(self.container)) + self.container.bind('Application', self.container) + self.container.bind('Cache', self.container.make('CacheManager').driver('disk')) - ViewClass = View(container) + view = self.container.make('View') - container.bind('ViewClass', ViewClass) - - viewclass = container.make('ViewClass') - - viewclass.share({'test1': 'test1'}) - viewclass.share({'test2': 'test2'}) - - assert viewclass.dictionary == {'test1': 'test1', 'test2': 'test2'} - - -def test_view_throws_exception_without_cache_binding(): - container = App() - - ViewClass = View(container) - - container.bind('ViewClass', ViewClass) - container.bind('View', ViewClass.render) - - view = container.make('View') - - with pytest.raises(RequiredContainerBindingNotFound): - view('test_cache').cache_for('5', 'seconds') - - -def test_view_cache_caches_files(): - container = App() - - view = View(container) - - container.bind('CacheConfig', cache) - container.bind('CacheDiskDriver', CacheDiskDriver) - container.bind('CacheManager', CacheManager(container)) - container.bind('Application', container) - container.bind('Cache', container.make('CacheManager').driver('disk')) - container.bind('View', view.render) - - view = container.make('View') - - assert view( - 'test_cache', {'test': 'test'} - ).cache_for(1, 'second').rendered_template == 'test' - - assert open(glob.glob('bootstrap/cache/test_cache:*')[0]).read() == 'test' - - time.sleep(2) - - assert view( - 'test_cache', {'test': 'macho'} - ).cache_for(5, 'seconds').rendered_template == 'macho' - - time.sleep(2) - - assert open(glob.glob('bootstrap/cache/test_cache:*')[0]).read() == 'macho' - - assert view( - 'test_cache', {'test': 'macho'} - ).cache_for(1, 'second').rendered_template == 'macho' - - time.sleep(1) - - assert open(glob.glob('bootstrap/cache/test_cache:*')[0]).read() == 'macho' - - assert view( - 'test_cache', {'test': 'macho'} - ).cache_for('1', 'second').rendered_template == 'macho' - -def test_cache_throws_exception_with_incorrect_cache_type(): - container = App() - - view = View(container) - - container.bind('CacheConfig', cache) - container.bind('CacheDiskDriver', CacheDiskDriver) - container.bind('CacheManager', CacheManager(container)) - container.bind('Application', container) - container.bind('Cache', container.make('CacheManager').driver('disk')) - container.bind('View', view.render) - - view = container.make('View') - - with pytest.raises(ValueError): - view( - 'test_exception', {'test': 'test'} - ).cache_for(1, 'monthss') + with pytest.raises(ValueError): + view( + 'test_exception', {'test': 'test'} + ).cache_for(1, 'monthss')