1#!/usr/bin/env python
2# Copyright 2013 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import unittest
7
8from extensions_paths import EXAMPLES, PUBLIC_TEMPLATES, STATIC_DOCS
9from local_file_system import LocalFileSystem
10from render_servlet import RenderServlet
11from server_instance import ServerInstance
12from servlet import Request, Response
13from test_util import ReadFile
14
15
16class _RenderServletDelegate(RenderServlet.Delegate):
17  def CreateServerInstance(self):
18    return ServerInstance.ForTest(LocalFileSystem.Create())
19
20
21class RenderServletTest(unittest.TestCase):
22  def _Render(self, path, headers=None, host=None):
23    return RenderServlet(Request.ForTest(path, headers=headers, host=host),
24                         _RenderServletDelegate()).Get()
25
26  def testExtensionAppRedirect(self):
27    self.assertEqual(
28        Response.Redirect('/apps/storage', permanent=False),
29        self._Render('storage'))
30
31  def testChannelRedirect(self):
32    for channel in ('stable', 'beta', 'dev', 'master'):
33      self.assertEqual(
34          Response.Redirect('/extensions/storage', permanent=True),
35          self._Render('%s/extensions/storage' % channel))
36
37  def testOldHostsRedirect(self):
38    self.assertEqual(
39        Response.Redirect('https://developer.chrome.com/extensions',
40            permanent=False),
41        self._Render('/chrome/extensions', host='http://code.google.com'))
42    self.assertEqual(
43        Response.Redirect('https://developer.chrome.com/extensions',
44            permanent=False),
45        self._Render('/chrome/extensions', host='https://code.google.com'))
46
47  def testNotFound(self):
48    def create_404_response(real_path):
49      real_404 = self._Render(real_path)
50      self.assertEqual(200, real_404.status)
51      real_404.status = 404
52      return real_404
53
54    root_404 = create_404_response('404')
55    extensions_404 = create_404_response('extensions/404')
56    apps_404 = create_404_response('apps/404')
57
58    self.assertEqual(root_404, self._Render('not_found'))
59    self.assertEqual(root_404, self._Render('not_found/not_found'))
60
61    self.assertEqual(extensions_404, self._Render('extensions/not_found'))
62    self.assertEqual(
63        extensions_404, self._Render('extensions/manifest/not_found'))
64    self.assertEqual(
65        extensions_404,
66        self._Render('extensions/manifest/not_found/not_found'))
67
68    self.assertEqual(apps_404, self._Render('apps/not_found'))
69    self.assertEqual(apps_404, self._Render('apps/manifest/not_found'))
70    self.assertEqual(
71        apps_404, self._Render('apps/manifest/not_found/not_found'))
72
73  def testSampleFile(self):
74    sample_file = 'extensions/talking_alarm_clock/background.js'
75    response = self._Render('extensions/examples/%s' % sample_file)
76    self.assertEqual(200, response.status)
77    self.assertTrue(response.headers['Content-Type'] in (
78        'application/javascript; charset=utf-8',
79        'application/x-javascript; charset=utf-8'))
80    self.assertEqual(ReadFile('%s%s' % (EXAMPLES, sample_file)),
81                     response.content.ToString())
82
83  def testSampleZip(self):
84    sample_dir = 'extensions/talking_alarm_clock'
85    response = self._Render('extensions/examples/%s.zip' % sample_dir)
86    self.assertEqual(200, response.status)
87    self.assertEqual('application/zip', response.headers['Content-Type'])
88
89  def testStaticFile(self):
90    static_file = 'css/out/site.css'
91    response = self._Render('static/%s' % static_file)
92    self.assertEqual(200, response.status)
93    self.assertEqual('text/css; charset=utf-8',
94                     response.headers['Content-Type'])
95    self.assertEqual(ReadFile('%s%s' % (STATIC_DOCS, static_file)),
96                     response.content.ToString())
97
98  def testHtmlTemplate(self):
99    html_file = 'extensions/storage'
100    response = self._Render(html_file)
101    self.assertEqual(200, response.status)
102    self.assertEqual('text/html; charset=utf-8',
103                     response.headers.get('Content-Type'))
104    # Can't really test rendering all that well.
105    self.assertTrue(len(response.content) >
106                    len(ReadFile('%s%s.html' % (PUBLIC_TEMPLATES, html_file))))
107
108  def testIndexRender(self):
109    response = self._Render('extensions')
110    self.assertEqual(200, response.status)
111    self.assertEqual(self._Render('extensions/index').content.ToString(),
112                     response.content.ToString())
113
114  def testOtherRedirectsJsonRedirect(self):
115    response = self._Render('apps/webview_tag')
116    self.assertEqual(('/apps/tags/webview', False),
117                     response.GetRedirect())
118
119  def testDirectories(self):
120    # Directories should be redirected to a URL that doesn't end in a '/'
121    # whether or not that exists.
122    self.assertEqual(('/dir', False), self._Render('dir/').GetRedirect())
123
124  def testEtags(self):
125    def test_path(path, content_type):
126      # Render without etag.
127      response = self._Render(path)
128      self.assertEqual(200, response.status)
129      etag = response.headers.get('ETag')
130      self.assertTrue(etag is not None)
131
132      # Render with an If-None-Match which doesn't match.
133      response = self._Render(path, headers={
134        'If-None-Match': '"fake etag"',
135      })
136      self.assertEqual(200, response.status)
137      self.assertEqual(content_type, response.headers.get('Content-Type'))
138      self.assertEqual(etag, response.headers.get('ETag'))
139
140      # Render with the correct matching If-None-Match.
141      response = self._Render(path, headers={
142        'If-None-Match': etag,
143      })
144      self.assertEqual(304, response.status)
145      self.assertEqual('Not Modified', response.content.ToString())
146      self.assertEqual(content_type, response.headers.get('Content-Type'))
147      self.assertEqual(etag, response.headers.get('ETag'))
148
149    # Test with a static path and a dynamic path.
150    test_path('static/css/out/site.css', 'text/css; charset=utf-8')
151    test_path('extensions/storage', 'text/html; charset=utf-8')
152
153
154if __name__ == '__main__':
155  unittest.main()
156