[IMP] filter out phantomjs warning on OSX
[odoo/odoo.git] / addons / web / tests / qunitsuite / suite.py
1 import json
2 import subprocess
3 import unittest
4 import os
5 import time
6
7 ROOT = os.path.join(os.path.dirname(__file__), 'grunt')
8
9 __all__ = ['QUnitSuite']
10
11 def _exc_info_to_string(err, test):
12     return err
13
14 class QUnitTest(unittest.TestCase):
15     def __init__(self, module, name):
16         self.module = module
17         self.name = name
18         self.failed = False
19     def shortDescription(self):
20         return None
21     def __repr__(self):
22         return '<QUnitTest %s:%s>' % (self.module, self.name)
23     def __str__(self):
24         return '%s: %s' % (self.module, self.name)
25
26 class QUnitSuite(unittest.TestSuite):
27     def __init__(self, qunitfile, timeout=5000):
28         super(QUnitSuite, self).__init__()
29         self.testfile = qunitfile
30         self.timeout = timeout
31         self._module = None
32         self._test = None
33
34     def run(self, result):
35         try:
36             subprocess.call(['phantomjs', '-v'],
37                             stdout=open(os.devnull, 'w'),
38                             stderr=subprocess.STDOUT)
39         except OSError:
40             test = QUnitTest('phantomjs', 'javascript tests')
41             result.startTest(test)
42             result.startTest(test)
43             result.addSkip(test , "phantomjs command not found")
44             result.stopTest(test)
45             return
46
47         result._exc_info_to_string = _exc_info_to_string
48         try:
49             self._run(result)
50         finally:
51             del result._exc_info_to_string
52
53     def _run(self, result):
54         phantom = subprocess.Popen([
55             'phantomjs',
56             '--config=%s' % os.path.join(ROOT, 'phantomjs.json'),
57             os.path.join(ROOT, 'bootstrap.js'), self.testfile,
58             json.dumps({
59                 'timeout': self.timeout,
60                 'inject': os.path.join(ROOT, 'qunit-phantomjs-bridge.js')
61             })
62         ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
63
64         try:
65             while True:
66                 line = phantom.stdout.readline()
67                 if line:
68                     if self.process(line, result):
69                         break
70                 else:
71                     time.sleep(0.1)
72         finally:
73             # If the phantomjs process hasn't quit, kill it
74             if phantom.poll() is None:
75                 phantom.terminate()
76
77     def process(self, line, result):
78         try:
79             args = json.loads(line)
80         except ValueError: # phantomjs stderr
81             if 'CoreText' not in line:
82                 print line
83             return False
84         event_name = args[0]
85
86         if event_name == 'qunit.done':
87             return True
88         elif event_name == 'fail.load':
89             self.add_error(result, "PhantomJS unable to load %s" % args[1])
90             return True
91         elif event_name == 'fail.timeout':
92             self.add_error(result, "PhantomJS timed out, possibly due to a"
93                                    " missing QUnit start() call")
94             return True
95
96         elif event_name == 'qunit.moduleStart':
97             self._module = args[1].encode('utf-8') if args[1] else ''
98         elif event_name == 'qunit.moduleStop':
99             self._test = None
100             self._module = None
101         elif event_name == 'qunit.testStart':
102             self._test = QUnitTest(self._module, args[1].encode('utf-8'))
103             result.startTest(self._test)
104         elif event_name == 'qunit.testDone':
105             if not self._test.failed:
106                 result.addSuccess(self._test)
107             result.stopTest(self._test)
108             self._test = None
109         elif event_name == 'qunit.log':
110             if args[1]:
111                 return False
112
113             self._test.failed = True
114             result.addFailure(
115                 self._test, self.failure_to_str(*args[2:]))
116         elif event_name == 'console':
117             print args[1]
118
119         return False
120
121     def add_error(self, result, s):
122         test = QUnitTest('phantomjs', 'startup')
123         result.startTest(test)
124         result.addError(test, s)
125         result.stopTest(test)
126
127     def failure_to_str(self, actual, expected, message, source):
128         if message or actual == expected:
129             formatted = str(message or '')
130         else:
131             formatted = "%s != %s" % (actual, expected)
132
133         if source:
134             formatted += '\n\n' + source
135
136         return formatted