2 # Copyright 2014 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.
10 from jsc_view
import GetEventByNameFromEvents
11 from api_schema_graph
import APISchemaGraph
12 from availability_finder
import AvailabilityFinder
, AvailabilityInfo
13 from branch_utility
import BranchUtility
, ChannelInfo
14 from compiled_file_system
import CompiledFileSystem
15 from extensions_paths
import CHROME_EXTENSIONS
16 from fake_host_file_system_provider
import FakeHostFileSystemProvider
17 from fake_url_fetcher
import FakeUrlFetcher
18 from features_bundle
import FeaturesBundle
19 from future
import Future
20 from host_file_system_iterator
import HostFileSystemIterator
21 from jsc_view
import CreateJSCView
, _JSCViewBuilder
, _FormatValue
22 from object_store_creator
import ObjectStoreCreator
23 from schema_processor
import SchemaProcessorFactoryForTest
24 from servlet
import Request
25 from server_instance
import ServerInstance
26 from test_data
.api_data_source
.canned_master_fs
import CANNED_MASTER_FS_DATA
27 from test_data
.canned_data
import CANNED_API_FILE_SYSTEM_DATA
28 from test_data
.object_level_availability
.tabs
import TABS_SCHEMA_BRANCHES
29 from test_file_system
import TestFileSystem
30 from test_util
import Server2Path
33 class _FakeTemplateCache(object):
35 def GetFromFile(self
, key
):
36 return Future(value
='motemplate %s' % key
)
39 class _FakeFeaturesBundle(object):
40 def GetAPIFeatures(self
):
42 'bluetooth': {'value': True},
43 'contextMenus': {'value': True},
44 'jsonStableAPI': {'value': True},
45 'idle': {'value': True},
46 'input.ime': {'value': True},
47 'tabs': {'value': True}
51 class _FakeAvailabilityFinder(object):
52 def __init__(self
, fake_availability
):
53 self
._fake
_availability
= fake_availability
55 def GetAPIAvailability(self
, api_name
):
56 return self
._fake
_availability
58 def GetAPINodeAvailability(self
, api_name
):
59 schema_graph
= APISchemaGraph()
60 api_graph
= APISchemaGraph(json
.loads(
61 CANNED_MASTER_FS_DATA
['api'][api_name
+ '.json']))
62 # Give the graph fake ChannelInfo; it's not used in tests.
63 channel_info
= ChannelInfo('stable', '28', 28)
64 schema_graph
.Update(api_graph
, lambda _
: channel_info
)
68 class JSCViewTest(unittest
.TestCase
):
70 self
._base
_path
= Server2Path('test_data', 'test_json')
72 server_instance
= ServerInstance
.ForTest(
73 TestFileSystem(CANNED_MASTER_FS_DATA
, relative_to
=CHROME_EXTENSIONS
))
74 file_system
= server_instance
.host_file_system_provider
.GetMaster()
75 self
._json
_cache
= server_instance
.compiled_fs_factory
.ForJson(file_system
)
76 self
._features
_bundle
= FeaturesBundle(file_system
,
77 server_instance
.compiled_fs_factory
,
78 server_instance
.object_store_creator
,
80 self
._api
_models
= server_instance
.platform_bundle
.GetAPIModels(
82 self
._fake
_availability
= AvailabilityInfo(ChannelInfo('stable', '396', 5))
84 def _ReadLocalFile(self
, filename
):
85 with
open(os
.path
.join(self
._base
_path
, filename
), 'r') as f
:
88 def _LoadJSON(self
, filename
):
89 return json
.loads(self
._ReadLocalFile
(filename
))
91 def _FakeLoadAddRulesSchema(self
):
92 events
= self
._LoadJSON
('add_rules_def_test.json')
93 return Future(value
=GetEventByNameFromEvents(events
))
95 def testFormatValue(self
):
96 self
.assertEquals('1,234,567', _FormatValue(1234567))
97 self
.assertEquals('67', _FormatValue(67))
98 self
.assertEquals('234,567', _FormatValue(234567))
100 def testGetEventByNameFromEvents(self
):
102 # Missing 'types' completely.
103 self
.assertRaises(AssertionError, GetEventByNameFromEvents
, events
)
106 # No type 'Event' defined.
107 self
.assertRaises(AssertionError, GetEventByNameFromEvents
, events
)
109 events
['types'].append({ 'name': 'Event',
111 add_rules
= { "name": "addRules" }
112 events
['types'][0]['functions'].append(add_rules
)
113 self
.assertEqual(add_rules
,
114 GetEventByNameFromEvents(events
)['addRules'])
116 events
['types'][0]['functions'].append(add_rules
)
117 # Duplicates are an error.
118 self
.assertRaises(AssertionError, GetEventByNameFromEvents
, events
)
120 def testCreateId(self
):
121 fake_avail_finder
= _FakeAvailabilityFinder(self
._fake
_availability
)
122 dict_
= CreateJSCView(
123 self
._api
_models
.GetContentScriptAPIs().Get(),
124 self
._api
_models
.GetModel('tester').Get(),
127 _FakeTemplateCache(),
128 self
._features
_bundle
,
133 self
.assertEquals('type-TypeA', dict_
['types'][0]['id'])
134 self
.assertEquals('property-TypeA-b',
135 dict_
['types'][0]['properties'][0]['id'])
136 self
.assertEquals('method-get', dict_
['functions'][0]['id'])
137 self
.assertEquals('event-EventA', dict_
['events'][0]['id'])
139 # TODO(kalman): re-enable this when we have a rebase option.
140 def DISABLED_testToDict(self
):
141 fake_avail_finder
= _FakeAvailabilityFinder(self
._fake
_availability
)
142 expected_json
= self
._LoadJSON
('expected_tester.json')
143 dict_
= CreateJSCView(
144 self
._api
_models
.GetContentScriptAPIs().Get(),
145 self
._api
_models
.GetModel('tester').Get(),
148 _FakeTemplateCache(),
149 self
._features
_bundle
,
154 self
.assertEquals(expected_json
, dict_
)
156 def testAddRules(self
):
157 fake_avail_finder
= _FakeAvailabilityFinder(self
._fake
_availability
)
158 dict_
= CreateJSCView(
159 self
._api
_models
.GetContentScriptAPIs().Get(),
160 self
._api
_models
.GetModel('add_rules_tester').Get(),
163 _FakeTemplateCache(),
164 self
._features
_bundle
,
165 self
._FakeLoadAddRulesSchema
(),
170 # Check that the first event has the addRulesFunction defined.
171 self
.assertEquals('add_rules_tester', dict_
['name'])
172 self
.assertEquals('rules', dict_
['events'][0]['name'])
173 self
.assertEquals('notable_name_to_check_for',
174 dict_
['events'][0]['byName']['addRules'][
175 'parameters'][0]['name'])
177 # Check that the second event has addListener defined.
178 self
.assertEquals('noRules', dict_
['events'][1]['name'])
179 self
.assertEquals('add_rules_tester', dict_
['name'])
180 self
.assertEquals('noRules', dict_
['events'][1]['name'])
181 self
.assertEquals('callback',
182 dict_
['events'][0]['byName']['addListener'][
183 'parameters'][0]['name'])
185 def testGetIntroList(self
):
186 fake_avail_finder
= _FakeAvailabilityFinder(self
._fake
_availability
)
187 model
= _JSCViewBuilder(
188 self
._api
_models
.GetContentScriptAPIs().Get(),
189 self
._api
_models
.GetModel('tester').Get(),
192 _FakeTemplateCache(),
193 self
._features
_bundle
,
198 { 'title': 'Description',
200 { 'text': 'a test api' }
203 { 'title': 'Availability',
205 { 'partial': 'motemplate chrome/common/extensions/docs/' +
206 'templates/private/intro_tables/stable_message.html',
212 { 'title': 'Permissions',
214 { 'class': 'override',
217 { 'text': 'is an API for testing things.' }
220 { 'title': 'Manifest',
223 'text': '"tester": {...}'
227 { 'title': 'Content Scripts',
230 'partial': 'motemplate chrome/common/extensions/docs' +
231 '/templates/private/intro_tables/content_scripts.html',
232 'contentScriptSupport': {
239 { 'title': 'Learn More',
241 { 'link': 'https://tester.test.com/welcome.html',
247 self
.assertEquals(model
._GetIntroTableList
(), expected_list
)
249 # Tests the same data with a scheduled availability.
250 fake_avail_finder
= _FakeAvailabilityFinder(
251 AvailabilityInfo(ChannelInfo('beta', '1453', 27), scheduled
=28))
252 model
= _JSCViewBuilder(
253 self
._api
_models
.GetContentScriptAPIs().Get(),
254 self
._api
_models
.GetModel('tester').Get(),
257 _FakeTemplateCache(),
258 self
._features
_bundle
,
263 'title': 'Availability',
265 { 'partial': 'motemplate chrome/common/extensions/docs/' +
266 'templates/private/intro_tables/beta_message.html',
272 self
.assertEquals(model
._GetIntroTableList
(), expected_list
)
275 class JSCViewWithoutNodeAvailabilityTest(unittest
.TestCase
):
277 server_instance
= ServerInstance
.ForTest(
278 file_system_provider
=FakeHostFileSystemProvider(
279 CANNED_API_FILE_SYSTEM_DATA
))
280 self
._api
_models
= server_instance
.platform_bundle
.GetAPIModels(
282 self
._json
_cache
= server_instance
.compiled_fs_factory
.ForJson(
283 server_instance
.host_file_system_provider
.GetMaster())
284 self
._avail
_finder
= server_instance
.platform_bundle
.GetAvailabilityFinder(
288 def testGetAPIAvailability(self
):
289 api_availabilities
= {
291 'contextMenus': 'master',
297 for api_name
, availability
in api_availabilities
.iteritems():
298 model_dict
= CreateJSCView(
299 self
._api
_models
.GetContentScriptAPIs().Get(),
300 self
._api
_models
.GetModel(api_name
).Get(),
303 _FakeTemplateCache(),
304 _FakeFeaturesBundle(),
309 self
.assertEquals(availability
,
310 model_dict
['introList'][1]['content'][0]['version'])
313 class JSCViewWithNodeAvailabilityTest(unittest
.TestCase
):
315 tabs_unmodified_versions
= (16, 20, 23, 24)
316 self
._branch
_utility
= BranchUtility(
317 os
.path
.join('branch_utility', 'first.json'),
318 os
.path
.join('branch_utility', 'second.json'),
319 FakeUrlFetcher(Server2Path('test_data')),
320 ObjectStoreCreator
.ForTest())
321 self
._node
_fs
_creator
= FakeHostFileSystemProvider(TABS_SCHEMA_BRANCHES
)
322 self
._node
_fs
_iterator
= HostFileSystemIterator(self
._node
_fs
_creator
,
323 self
._branch
_utility
)
324 test_object_store
= ObjectStoreCreator
.ForTest()
325 self
._avail
_finder
= AvailabilityFinder(
326 self
._branch
_utility
,
327 CompiledFileSystem
.Factory(test_object_store
),
328 self
._node
_fs
_iterator
,
329 self
._node
_fs
_creator
.GetMaster(),
332 SchemaProcessorFactoryForTest())
334 server_instance
= ServerInstance
.ForTest(
335 file_system_provider
=FakeHostFileSystemProvider(
336 TABS_SCHEMA_BRANCHES
))
337 self
._api
_models
= server_instance
.platform_bundle
.GetAPIModels(
339 self
._json
_cache
= server_instance
.compiled_fs_factory
.ForJson(
340 server_instance
.host_file_system_provider
.GetMaster())
342 # Imitate the actual SVN file system by incrementing the stats for paths
343 # where an API schema has changed.
344 last_stat
= type('last_stat', (object,), {'val': 0})
346 def stat_paths(file_system
, channel_info
):
347 if channel_info
.version
not in tabs_unmodified_versions
:
349 # HACK: |file_system| is a MockFileSystem backed by a TestFileSystem.
350 # Increment the TestFileSystem stat count.
351 file_system
._file
_system
.IncrementStat(by
=last_stat
.val
)
352 # Continue looping. The iterator will stop after 'master' automatically.
355 # Use the HostFileSystemIterator created above to change global stat values
356 # for the TestFileSystems that it creates.
357 self
._node
_fs
_iterator
.Ascending(
358 # The earliest version represented with the tabs' test data is 13.
359 self
._branch
_utility
.GetStableChannelInfo(13),
362 def testGetAPINodeAvailability(self
):
363 def assertEquals(node
, actual
):
364 node_availabilities
= {
366 'tabs.fakeTabsProperty1': None,
368 'tabs.onUpdated': None,
369 'tabs.InjectDetails': 25,
370 'tabs.fakeTabsProperty2': 15,
371 'tabs.getCurrent': 19,
372 'tabs.onActivated': 30
374 self
.assertEquals(node_availabilities
[node
], actual
)
376 model_dict
= CreateJSCView(
377 self
._api
_models
.GetContentScriptAPIs().Get(),
378 self
._api
_models
.GetModel('tabs').Get(),
381 _FakeTemplateCache(),
382 _FakeFeaturesBundle(),
388 # Test nodes that have the same availability as their parent.
391 assertEquals('tabs.Tab', model_dict
['types'][0]['availability'])
393 assertEquals('tabs.fakeTabsProperty1',
394 model_dict
['properties'][0]['availability'])
396 assertEquals('tabs.get', model_dict
['functions'][1]['availability'])
398 assertEquals('tabs.onUpdated', model_dict
['events'][1]['availability'])
400 # Test nodes with varying availabilities.
403 assertEquals('tabs.InjectDetails',
404 model_dict
['types'][1]['availability']['version'])
406 assertEquals('tabs.fakeTabsProperty2',
407 model_dict
['properties'][2]['availability']['version'])
409 assertEquals('tabs.getCurrent',
410 model_dict
['functions'][0]['availability']['version'])
412 assertEquals('tabs.onActivated',
413 model_dict
['events'][0]['availability']['version'])
415 # Test a node that became deprecated.
419 'partial': 'motemplate chrome/common/extensions/docs/templates/' +
420 'private/intro_tables/deprecated_message.html'
421 }, model_dict
['types'][2]['availability'])
423 if __name__
== '__main__':