cubicweb/web/test/unittest_views_staticcontrollers.py
changeset 11057 0b59724cb3f2
parent 10907 9ae707db5265
child 11201 4db44a475b9b
equal deleted inserted replaced
11052:058bb3dc685f 11057:0b59724cb3f2
       
     1 # -*- coding: utf-8 -*-
       
     2 # copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
       
     3 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
       
     4 #
       
     5 # This file is part of CubicWeb.
       
     6 #
       
     7 # CubicWeb is free software: you can redistribute it and/or modify it under the
       
     8 # terms of the GNU Lesser General Public License as published by the Free
       
     9 # Software Foundation, either version 2.1 of the License, or (at your option)
       
    10 # any later version.
       
    11 #
       
    12 # CubicWeb is distributed in the hope that it will be useful, but WITHOUT
       
    13 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
       
    14 # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
       
    15 # details.
       
    16 #
       
    17 # You should have received a copy of the GNU Lesser General Public License along
       
    18 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
       
    19 from contextlib import contextmanager
       
    20 
       
    21 from logilab.common import tempattr
       
    22 from logilab.common.testlib import Tags
       
    23 from cubicweb.devtools.testlib import CubicWebTC
       
    24 
       
    25 import os
       
    26 import os.path as osp
       
    27 import glob
       
    28 
       
    29 from cubicweb.utils import HTMLHead
       
    30 from cubicweb.web.views.staticcontrollers import ConcatFilesHandler
       
    31 
       
    32 class staticfilespublishermixin(object):
       
    33 
       
    34     @contextmanager
       
    35     def _publish_static_files(self, url, header={}):
       
    36         with self.admin_access.web_request(headers=header) as req:
       
    37             req._url = url
       
    38             self.app_handle_request(req, url)
       
    39             yield req
       
    40 
       
    41 class StaticControllerCacheTC(staticfilespublishermixin, CubicWebTC):
       
    42     tags = CubicWebTC.tags | Tags('static_controller', 'cache', 'http')
       
    43 
       
    44     def test_static_file_are_cached(self):
       
    45         with self._publish_static_files('data/cubicweb.css') as req:
       
    46             self.assertEqual(200, req.status_out)
       
    47             self.assertIn('last-modified', req.headers_out)
       
    48         next_headers = {
       
    49             'if-modified-since': req.get_response_header('last-modified', raw=True),
       
    50         }
       
    51         with self._publish_static_files('data/cubicweb.css', next_headers) as req:
       
    52             self.assertEqual(304, req.status_out)
       
    53 
       
    54 class StaticDirectoryControllerTC(staticfilespublishermixin, CubicWebTC):
       
    55 
       
    56     def test_check_static_dir_access(self):
       
    57         """write a file in the static directory and test the access"""
       
    58         staticdir = osp.join(self.session.vreg.config.static_directory)
       
    59         if not os.path.exists(staticdir):
       
    60             os.makedirs(staticdir)
       
    61         filename = osp.join(staticdir, 'test')
       
    62         with open(filename, 'a') as f:
       
    63             with self._publish_static_files('static/test') as req:
       
    64                 self.assertEqual(200, req.status_out)
       
    65 
       
    66 class DataControllerTC(staticfilespublishermixin, CubicWebTC):
       
    67     tags = CubicWebTC.tags | Tags('static_controller', 'data', 'http')
       
    68 
       
    69     def _check_datafile_ok(self, fname):
       
    70         with self._publish_static_files(fname) as req:
       
    71             self.assertEqual(200, req.status_out)
       
    72             self.assertIn('last-modified', req.headers_out)
       
    73             self.assertIn('expires', req.headers_out)
       
    74             self.assertEqual(req.get_response_header('cache-control'),
       
    75                              {'max-age': 604800})
       
    76         next_headers = {
       
    77             'if-modified-since': req.get_response_header('last-modified', raw=True),
       
    78         }
       
    79         with self._publish_static_files(fname, next_headers) as req:
       
    80             self.assertEqual(304, req.status_out)
       
    81 
       
    82     def _check_datafile_redirect(self, fname, expected):
       
    83         with self._publish_static_files(fname) as req:
       
    84             self.assertEqual(302, req.status_out)
       
    85             self.assertEqual(req.get_response_header('location'),
       
    86                              req.base_url() + expected)
       
    87 
       
    88     def _check_no_datafile(self, fname):
       
    89         with self._publish_static_files(fname) as req:
       
    90             self.assertEqual(404, req.status_out)
       
    91 
       
    92     def test_static_data_mode(self):
       
    93         hash = self.vreg.config.instance_md5_version()
       
    94         self.assertEqual(32, len(hash))
       
    95 
       
    96         with tempattr(self.vreg.config, 'mode', 'test'):
       
    97             self._check_datafile_ok('data/cubicweb.css')
       
    98             self._check_no_datafile('data/does/not/exist')
       
    99             self._check_no_datafile('data/%s/cubicweb.css' % ('0'*len(hash)))
       
   100 
       
   101         with tempattr(self.vreg.config, 'mode', 'notest'):
       
   102             self.config._init_base_url()  # reset config.datadir_url
       
   103             self._check_datafile_redirect('data/cubicweb.css', 'data/%s/cubicweb.css' % hash)
       
   104             self._check_datafile_ok('data/%s/cubicweb.css' % hash)
       
   105             self._check_no_datafile('data/%s/does/not/exist' % hash)
       
   106             self._check_datafile_redirect('data/%s/does/not/exist' % ('0'*len(hash)),
       
   107                                           'data/%s/%s/does/not/exist' % (hash, '0'*len(hash)))
       
   108 
       
   109 
       
   110 class ConcatFilesTC(CubicWebTC):
       
   111 
       
   112     tags = CubicWebTC.tags | Tags('static_controller', 'concat')
       
   113 
       
   114     def tearDown(self):
       
   115         super(ConcatFilesTC, self).tearDown()
       
   116         self._cleanup_concat_cache()
       
   117 
       
   118     def _cleanup_concat_cache(self):
       
   119         uicachedir = osp.join(self.config.apphome, 'uicache')
       
   120         for fname in glob.glob(osp.join(uicachedir, 'cache_concat_*')):
       
   121             os.unlink(osp.join(uicachedir, fname))
       
   122 
       
   123     @contextmanager
       
   124     def _publish_js_files(self, js_files):
       
   125         with self.admin_access.web_request() as req:
       
   126             head = HTMLHead(req)
       
   127             url = head.concat_urls([req.data_url(js_file)
       
   128                                     for js_file in js_files])[len(req.base_url()):]
       
   129             req._url = url
       
   130             res = self.app_handle_request(req, url)
       
   131             yield res, req
       
   132 
       
   133     def expected_content(self, js_files):
       
   134         content = b''
       
   135         for js_file in js_files:
       
   136             dirpath, rid = self.config.locate_resource(js_file)
       
   137             if dirpath is not None: # ignore resources not found
       
   138                 with open(osp.join(dirpath, rid), 'rb') as f:
       
   139                     content += f.read() + b'\n'
       
   140         return content
       
   141 
       
   142     def test_cache(self):
       
   143         js_files = ('cubicweb.ajax.js', 'jquery.js')
       
   144         with self._publish_js_files(js_files) as (result, req):
       
   145             self.assertNotEqual(404, req.status_out)
       
   146             # check result content
       
   147             self.assertEqual(result, self.expected_content(js_files))
       
   148             # make sure we kept a cached version on filesystem
       
   149             concat_hander = ConcatFilesHandler(self.config)
       
   150             filepath = concat_hander.build_filepath(js_files)
       
   151             self.assertTrue(osp.isfile(filepath))
       
   152 
       
   153 
       
   154     def test_invalid_file_in_debug_mode(self):
       
   155         js_files = ('cubicweb.ajax.js', 'dummy.js')
       
   156         # in debug mode, an error is raised
       
   157         self.config.debugmode = True
       
   158         try:
       
   159             with self._publish_js_files(js_files) as (result, req):
       
   160                 #print result
       
   161                 self.assertEqual(404, req.status_out)
       
   162         finally:
       
   163             self.config.debugmode = False
       
   164 
       
   165     def test_invalid_file_in_production_mode(self):
       
   166         js_files = ('cubicweb.ajax.js', 'dummy.js')
       
   167         with self._publish_js_files(js_files) as (result, req):
       
   168             self.assertNotEqual(404, req.status_out)
       
   169             # check result content
       
   170             self.assertEqual(result, self.expected_content(js_files))
       
   171 
       
   172 
       
   173 if __name__ == '__main__':
       
   174     from logilab.common.testlib import unittest_main
       
   175     unittest_main()