1#!/usr/bin/env python 2# Copyright (c) 2012 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 os 8import sys 9import unittest 10 11from api_data_source import (_JSCModel, 12 _FormatValue, 13 _GetEventByNameFromEvents) 14from branch_utility import ChannelInfo 15from extensions_paths import EXTENSIONS 16from file_system import FileNotFoundError 17from future import Future 18from object_store_creator import ObjectStoreCreator 19from reference_resolver import ReferenceResolver 20from server_instance import ServerInstance 21from test_data.canned_data import (CANNED_API_FILE_SYSTEM_DATA, CANNED_BRANCHES) 22from test_data.api_data_source.canned_trunk_fs import CANNED_TRUNK_FS_DATA 23from test_file_system import TestFileSystem 24from third_party.json_schema_compiler.memoize import memoize 25 26 27def _MakeLink(href, text): 28 return '<a href="%s">%s</a>' % (href, text) 29 30 31def _GetType(dict_, name): 32 for type_ in dict_['types']: 33 if type_['name'] == name: 34 return type_ 35 36 37class _FakeAvailabilityFinder(object): 38 39 def GetApiAvailability(self, version): 40 return ChannelInfo('stable', '396', 5) 41 42 43class _FakeHostFileSystemProvider(object): 44 45 def __init__(self, file_system_data): 46 self._file_system_data = file_system_data 47 48 def GetTrunk(self): 49 return self.GetBranch('trunk') 50 51 @memoize 52 def GetBranch(self, branch): 53 return TestFileSystem(self._file_system_data[str(branch)]) 54 55 56class _FakeSamplesDataSource(object): 57 58 def Create(self, request): 59 return {} 60 61 62# Sad irony :( 63class _FakeAPIDataSource(object): 64 65 def __init__(self, json_data): 66 self._json = json_data 67 68 def Create(self, *args, **kwargs): 69 return self 70 71 def get(self, key, disable_refs=False): 72 if key not in self._json: 73 raise FileNotFoundError(key) 74 return self._json[key] 75 76 77class _FakeAPIModels(object): 78 79 def __init__(self, names): 80 self._names = names 81 82 def GetNames(self): 83 return self._names 84 85 86class _FakeTemplateCache(object): 87 88 def GetFromFile(self, key): 89 return Future(value='handlebar %s' % key) 90 91 92class APIDataSourceTest(unittest.TestCase): 93 94 def setUp(self): 95 self._base_path = os.path.join(sys.path[0], 'test_data', 'test_json') 96 97 server_instance = ServerInstance.ForTest( 98 TestFileSystem(CANNED_TRUNK_FS_DATA, relative_to=EXTENSIONS)) 99 self._json_cache = server_instance.compiled_fs_factory.ForJson( 100 server_instance.host_file_system_provider.GetTrunk()) 101 self._api_models = server_instance.api_models 102 103 # Used for testGetApiAvailability() so that valid-ish data is processed. 104 server_instance = ServerInstance.ForTest( 105 file_system_provider=_FakeHostFileSystemProvider( 106 CANNED_API_FILE_SYSTEM_DATA)) 107 self._avail_api_models = server_instance.api_models 108 self._avail_json_cache = server_instance.compiled_fs_factory.ForJson( 109 server_instance.host_file_system_provider.GetTrunk()) 110 self._avail_finder = server_instance.availability_finder 111 112 def _ReadLocalFile(self, filename): 113 with open(os.path.join(self._base_path, filename), 'r') as f: 114 return f.read() 115 116 def _CreateRefResolver(self, filename): 117 test_data = self._LoadJSON(filename) 118 return ReferenceResolver.Factory(_FakeAPIDataSource(test_data), 119 _FakeAPIModels(test_data), 120 ObjectStoreCreator.ForTest()).Create() 121 122 def _LoadJSON(self, filename): 123 return json.loads(self._ReadLocalFile(filename)) 124 125 def testCreateId(self): 126 dict_ = _JSCModel('tester', 127 self._api_models, 128 self._CreateRefResolver('test_file_data_source.json'), 129 False, 130 _FakeAvailabilityFinder(), 131 self._json_cache, 132 _FakeTemplateCache(), 133 None).ToDict() 134 self.assertEquals('type-TypeA', dict_['types'][0]['id']) 135 self.assertEquals('property-TypeA-b', 136 dict_['types'][0]['properties'][0]['id']) 137 self.assertEquals('method-get', dict_['functions'][0]['id']) 138 self.assertEquals('event-EventA', dict_['events'][0]['id']) 139 140 # TODO(kalman): re-enable this when we have a rebase option. 141 def DISABLED_testToDict(self): 142 expected_json = self._LoadJSON('expected_tester.json') 143 dict_ = _JSCModel('tester', 144 self._api_models, 145 False, 146 self._CreateRefResolver('test_file_data_source.json'), 147 _FakeAvailabilityFinder(), 148 self._json_cache, 149 _FakeTemplateCache(), 150 None).ToDict() 151 self.assertEquals(expected_json, dict_) 152 153 def testFormatValue(self): 154 self.assertEquals('1,234,567', _FormatValue(1234567)) 155 self.assertEquals('67', _FormatValue(67)) 156 self.assertEquals('234,567', _FormatValue(234567)) 157 158 def testFormatDescription(self): 159 dict_ = _JSCModel('ref_test', 160 self._api_models, 161 self._CreateRefResolver('ref_test_data_source.json'), 162 False, 163 _FakeAvailabilityFinder(), 164 self._json_cache, 165 _FakeTemplateCache(), 166 None).ToDict() 167 self.assertEquals(_MakeLink('ref_test.html#type-type2', 'type2'), 168 _GetType(dict_, 'type1')['description']) 169 self.assertEquals( 170 'A %s, or %s' % (_MakeLink('ref_test.html#type-type3', 'type3'), 171 _MakeLink('ref_test.html#type-type2', 'type2')), 172 _GetType(dict_, 'type2')['description']) 173 self.assertEquals( 174 '%s != %s' % (_MakeLink('other.html#type-type2', 'other.type2'), 175 _MakeLink('ref_test.html#type-type2', 'type2')), 176 _GetType(dict_, 'type3')['description']) 177 178 179 def testGetApiAvailability(self): 180 api_availabilities = { 181 'bluetooth': ChannelInfo('dev', CANNED_BRANCHES[28], 28), 182 'contextMenus': ChannelInfo('trunk', CANNED_BRANCHES['trunk'], 'trunk'), 183 'jsonStableAPI': ChannelInfo('stable', CANNED_BRANCHES[20], 20), 184 'idle': ChannelInfo('stable', CANNED_BRANCHES[5], 5), 185 'input.ime': ChannelInfo('stable', CANNED_BRANCHES[18], 18), 186 'tabs': ChannelInfo('stable', CANNED_BRANCHES[18], 18) 187 } 188 for api_name, availability in api_availabilities.iteritems(): 189 model = _JSCModel(api_name, 190 self._avail_api_models, 191 None, 192 True, 193 self._avail_finder, 194 self._avail_json_cache, 195 _FakeTemplateCache(), 196 None) 197 self.assertEquals(availability, model._GetApiAvailability()) 198 199 def testGetIntroList(self): 200 model = _JSCModel('tester', 201 self._api_models, 202 self._CreateRefResolver('test_file_data_source.json'), 203 False, 204 _FakeAvailabilityFinder(), 205 self._json_cache, 206 _FakeTemplateCache(), 207 None) 208 expected_list = [ 209 { 'title': 'Description', 210 'content': [ 211 { 'text': 'a test api' } 212 ] 213 }, 214 { 'title': 'Availability', 215 'content': [ 216 { 'partial': 'handlebar chrome/common/extensions/docs/' + 217 'templates/private/intro_tables/stable_message.html', 218 'version': 5 219 } 220 ] 221 }, 222 { 'title': 'Permissions', 223 'content': [ 224 { 'class': 'override', 225 'text': '"tester"' 226 }, 227 { 'text': 'is an API for testing things.' } 228 ] 229 }, 230 { 'title': 'Manifest', 231 'content': [ 232 { 'class': 'code', 233 'text': '"tester": {...}' 234 } 235 ] 236 }, 237 { 'title': 'Learn More', 238 'content': [ 239 { 'link': 'https://tester.test.com/welcome.html', 240 'text': 'Welcome!' 241 } 242 ] 243 } 244 ] 245 self.assertEquals(model._GetIntroTableList(), expected_list) 246 247 def testGetEventByNameFromEvents(self): 248 events = {} 249 # Missing 'types' completely. 250 self.assertRaises(AssertionError, _GetEventByNameFromEvents, events) 251 252 events['types'] = [] 253 # No type 'Event' defined. 254 self.assertRaises(AssertionError, _GetEventByNameFromEvents, events) 255 256 events['types'].append({ 'name': 'Event', 257 'functions': []}) 258 add_rules = { "name": "addRules" } 259 events['types'][0]['functions'].append(add_rules) 260 self.assertEqual(add_rules, 261 _GetEventByNameFromEvents(events)['addRules']) 262 263 events['types'][0]['functions'].append(add_rules) 264 # Duplicates are an error. 265 self.assertRaises(AssertionError, _GetEventByNameFromEvents, events) 266 267 def _FakeLoadAddRulesSchema(self): 268 events = self._LoadJSON('add_rules_def_test.json') 269 return _GetEventByNameFromEvents(events) 270 271 def testAddRules(self): 272 dict_ = _JSCModel('add_rules_tester', 273 self._api_models, 274 self._CreateRefResolver('test_file_data_source.json'), 275 False, 276 _FakeAvailabilityFinder(), 277 self._json_cache, 278 _FakeTemplateCache(), 279 self._FakeLoadAddRulesSchema).ToDict() 280 281 # Check that the first event has the addRulesFunction defined. 282 self.assertEquals('add_rules_tester', dict_['name']) 283 self.assertEquals('rules', dict_['events'][0]['name']) 284 self.assertEquals('notable_name_to_check_for', 285 dict_['events'][0]['byName']['addRules'][ 286 'parameters'][0]['name']) 287 288 # Check that the second event has addListener defined. 289 self.assertEquals('noRules', dict_['events'][1]['name']) 290 self.assertEquals('add_rules_tester', dict_['name']) 291 self.assertEquals('noRules', dict_['events'][1]['name']) 292 self.assertEquals('callback', 293 dict_['events'][0]['byName']['addListener'][ 294 'parameters'][0]['name']) 295 296if __name__ == '__main__': 297 unittest.main() 298