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 json
7import unittest
8import copy
9
10from extensions_paths import JSON_TEMPLATES
11from mock_file_system import MockFileSystem
12from server_instance import ServerInstance
13from servlet import Request
14from sidenav_data_source import SidenavDataSource, _AddLevels, _AddAnnotations
15from test_file_system import TestFileSystem
16from test_util import CaptureLogging
17
18
19class SamplesDataSourceTest(unittest.TestCase):
20  def testAddLevels(self):
21    sidenav_json = [{
22      'title': 'H2',
23      'items': [{
24        'title': 'H3',
25        'items': [{ 'title': 'X1' }]
26      }]
27    }]
28
29    expected = [{
30      'level': 1,
31      'title': 'H2',
32      'items': [{
33        'level': 2,
34        'title': 'H3',
35        'items': [{ 'level': 3, 'title': 'X1' }]
36      }]
37    }]
38
39    _AddLevels(sidenav_json, 1)
40    self.assertEqual(expected, sidenav_json)
41
42  def testAddAnnotations(self):
43    item1 = { 'href': '/H1.html' }
44    item2_1 = { 'href': '/H2_1.html' }
45    item2_2 = { 'href': '/H2_2.html' }
46    item2 = { 'href': '/H2.html', 'items': [item2_1, item2_2] }
47
48    expected = [ item1, item2 ]
49
50    sidenav_json = copy.deepcopy(expected)
51
52    item2['child_selected'] = True
53    item2_1['selected'] = True
54    item2_1['related'] = True
55    item2_1['parent'] = { 'title': item2.get('title', None),
56                          'href': item2.get('href', None) }
57
58    item2_2['related'] = True
59
60    self.assertTrue(_AddAnnotations(sidenav_json, item2_1['href']))
61    self.assertEqual(expected, sidenav_json)
62
63  def testWithDifferentBasePath(self):
64    file_system = TestFileSystem({
65      'chrome_sidenav.json': json.dumps([
66        { 'href': '/H1.html' },
67        { 'href': '/H2.html' },
68        { 'href': '/base/path/H2.html' },
69        { 'href': 'https://qualified/X1.html' },
70        {
71          'href': 'H3.html',
72          'items': [{
73            'href': 'H4.html'
74          }]
75        },
76      ])
77    }, relative_to=JSON_TEMPLATES)
78
79    expected = [
80      {'href': '/base/path/H1.html', 'level': 2, 'related': True},
81      {'href': '/base/path/H2.html', 'level': 2, 'selected': True, 'related': True},
82      {'href': '/base/path/base/path/H2.html', 'level': 2, 'related': True},
83      {'href': 'https://qualified/X1.html', 'level': 2, 'related': True},
84      {'items': [
85        {'href': '/base/path/H4.html', 'level': 3}
86      ],
87      'href': '/base/path/H3.html', 'level': 2, 'related': True}
88    ]
89
90    server_instance = ServerInstance.ForTest(file_system,
91                                             base_path='/base/path/')
92    sidenav_data_source = SidenavDataSource(server_instance,
93                                            Request.ForTest('/H2.html'))
94
95    log_output = CaptureLogging(
96        lambda: self.assertEqual(expected, sidenav_data_source.get('chrome')))
97    self.assertEqual(2, len(log_output))
98
99  def testSidenavDataSource(self):
100    file_system = MockFileSystem(TestFileSystem({
101      'chrome_sidenav.json': json.dumps([{
102        'title': 'H1',
103        'href': 'H1.html',
104        'items': [{
105          'title': 'H2',
106          'href': '/H2.html'
107        }]
108      }])
109    }, relative_to=JSON_TEMPLATES))
110
111    expected = [{
112      'level': 2,
113      'child_selected': True,
114      'title': 'H1',
115      'href': '/H1.html',
116      'items': [{
117        'level': 3,
118        'selected': True,
119        'related': True,
120        'title': 'H2',
121        'href': '/H2.html',
122        'parent': { 'href': '/H1.html', 'title': 'H1'}
123      }]
124    }]
125
126    sidenav_data_source = SidenavDataSource(
127        ServerInstance.ForTest(file_system), Request.ForTest('/H2.html'))
128    self.assertTrue(*file_system.CheckAndReset())
129
130    log_output = CaptureLogging(
131        lambda: self.assertEqual(expected, sidenav_data_source.get('chrome')))
132
133    self.assertEqual(1, len(log_output))
134    self.assertTrue(
135        log_output[0].msg.startswith('Paths in sidenav must be qualified.'))
136
137    # Test that only a single file is read when creating the sidenav, so that
138    # we can be confident in the compiled_file_system.SingleFile annotation.
139    self.assertTrue(*file_system.CheckAndReset(
140        read_count=1, stat_count=1, read_resolve_count=1))
141
142  def testRefresh(self):
143    file_system = TestFileSystem({
144      'chrome_sidenav.json': '[{ "title": "H1" }]'
145    }, relative_to=JSON_TEMPLATES)
146
147    # Ensure Refresh doesn't rely on request.
148    sidenav_data_source = SidenavDataSource(
149        ServerInstance.ForTest(file_system), request=None)
150    sidenav_data_source.Refresh().Get()
151
152    # If Refresh fails, chrome_sidenav.json will not be cached, and the
153    # cache_data access will fail.
154    # TODO(jshumway): Make a non hack version of this check.
155    sidenav_data_source._cache._file_object_store.Get(
156        '%schrome_sidenav.json' % JSON_TEMPLATES).Get().cache_data
157
158
159if __name__ == '__main__':
160  unittest.main()
161