2 # -*- encoding: utf-8 -*-
10 from mako.template import Template
11 from openerp.modules import module
13 from .main import module_topological_sort
16 NOMODULE_TEMPLATE = Template(u"""<!DOCTYPE html>
19 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
20 <meta http-equiv="content-type" content="text/html; charset=utf-8" />
21 <title>OpenERP Testing</title>
24 <form action="/web/tests" method="GET">
25 <button name="mod" value="*">Run all tests</button>
27 % for name, module in modules:
28 <li>${name} <button name="mod" value="${module}">
29 Run Tests</button></li>
35 """, default_filters=['h'])
36 NOTFOUND = Template(u"""
37 <p>Unable to find the module [${module}], please check that the module
38 name is correct and the module is on OpenERP's path.</p>
39 <a href="/web/tests"><< Back to tests</a>
40 """, default_filters=['h'])
41 TESTING = Template(u"""<!DOCTYPE html>
42 <html style="height: 100%">
43 <%def name="to_path(module, p)">/${module}/${p}</%def>
45 <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
46 <meta http-equiv="content-type" content="text/html; charset=utf-8" />
47 <title>OpenERP Web Tests</title>
48 <link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon"/>
50 <link rel="stylesheet" href="/web/static/lib/qunit/qunit.css">
51 <script src="/web/static/lib/qunit/qunit.js"></script>
53 <script type="text/javascript">
54 var oe_db_info = ${db_info | n};
55 // List of modules, each module is preceded by its dependencies
56 var oe_all_dependencies = ${dependencies | n};
57 QUnit.config.testTimeout = 5 * 60 * 1000;
60 <body id="oe" class="openerp">
61 <div id="qunit"></div>
62 <div id="qunit-fixture"></div>
64 <!-- TODO xmo please use the regular template even for testing -->
65 % for module, jss, tests, templates in files:
67 % if not js.endswith('/apps.js'):
68 <script src="${to_path(module, js)}"></script>
71 % if tests or templates:
73 openerp.testing.current_module = "${module}";
74 % for template in templates:
75 openerp.testing.add_template("${to_path(module, template)}");
81 <script type="text/javascript" src="${to_path(module, test)}"></script>
86 """, default_filters=['h'])
88 class TestRunnerController(http.Controller):
89 _cp_path = '/web/tests'
92 def index(self, req, mod=None, **kwargs):
93 ms = module.get_modules()
96 for name, desc in zip(ms, map(self.load_manifest, ms))
97 if desc # remove not-actually-openerp-modules
101 return NOMODULE_TEMPLATE.render(modules=(
102 (manifest['name'], name)
103 for name, manifest in manifests.iteritems()
104 if any(testfile.endswith('.js')
105 for testfile in manifest['test'])
107 sorted_mods = module_topological_sort(dict(
108 (name, manifest.get('depends', []))
109 for name, manifest in manifests.iteritems()
111 # to_load and to_test should be zippable lists of the same length.
112 # A falsy value in to_test indicate nothing to test at that index (just
113 # load the corresponding part of to_load)
114 to_test = sorted_mods
116 if mod not in manifests:
117 return req.not_found(NOTFOUND.render(module=mod))
118 idx = sorted_mods.index(mod)
119 to_test = [None] * len(sorted_mods)
123 filter(lambda path: path.endswith('.js'),
124 manifests[mod]['test'] if mod else [])
126 # remove trailing test-less modules
127 tests = reversed(list(
130 reversed(tests_candicates))))
133 (mod, manifests[mod]['js'], tests, manifests[mod]['qweb'])
134 for mod, tests in itertools.izip(sorted_mods, tests)
137 # if all three db_info parameters are present, send them to the page
138 db_info = dict((k, v) for k, v in kwargs.iteritems()
139 if k in ['source', 'supadmin', 'password'])
140 if len(db_info) != 3:
143 return TESTING.render(files=files, dependencies=json.dumps(
144 [name for name in sorted_mods
145 if module.get_module_resource(name, 'static')
146 if manifests[name]['js']]), db_info=json.dumps(db_info))
148 def load_manifest(self, name):
149 manifest = module.load_information_from_description_file(name)
151 path = module.get_module_path(name)
152 manifest['js'] = list(
153 self.expand_patterns(path, manifest.get('js', [])))
154 manifest['test'] = list(
155 self.expand_patterns(path, manifest.get('test', [])))
156 manifest['qweb'] = list(
157 self.expand_patterns(path, manifest.get('qweb', [])))
160 def expand_patterns(self, root, patterns):
161 for pattern in patterns:
162 normalized_pattern = os.path.normpath(os.path.join(root, pattern))
163 for path in glob.glob(normalized_pattern):
164 # replace OS path separators (from join & normpath) by URI ones
165 yield path[len(root):].replace(os.path.sep, '/')