convert js tests to HttpCase
bzr revid: al@openerp.com-20140428152857-h7z61vdw5crezv2u
This commit is contained in:
parent
065b3c2176
commit
d9eec7345b
|
@ -2,4 +2,3 @@
|
||||||
import test_js
|
import test_js
|
||||||
import test_menu
|
import test_menu
|
||||||
import test_serving_base
|
import test_serving_base
|
||||||
import test_ui
|
|
||||||
|
|
|
@ -1,116 +0,0 @@
|
||||||
QUnitSuite is a ``unittest.TestSuite`` able to run QUnit_ test suites
|
|
||||||
within the normal unittest process, through PhantomJS_.
|
|
||||||
|
|
||||||
QUnitSuite is built upon `Ben Alman`_'s work of for the interfacing
|
|
||||||
between PhantomJS_ and the host/reporting code: the shims and the
|
|
||||||
PhantomJS_ configuration files are those of grunt_'s ``qunit`` task.
|
|
||||||
|
|
||||||
Why
|
|
||||||
---
|
|
||||||
|
|
||||||
You're a Python shop or developer, you have tools and tests built
|
|
||||||
around unittest (or compatible with unittests) and your testing
|
|
||||||
pipeline is predicated upon that, you're doing web development of some
|
|
||||||
sort these days (as so many are) and you'd like to do some testing of
|
|
||||||
your web stuff.
|
|
||||||
|
|
||||||
But you don't really want to redo your whole testing stack just for
|
|
||||||
that.
|
|
||||||
|
|
||||||
QUnitSuite simply grafts QUnit_-based tests, run in PhantomJS_, in
|
|
||||||
your existing ``unittest``-based architecture.
|
|
||||||
|
|
||||||
What
|
|
||||||
----
|
|
||||||
|
|
||||||
QUnitSuite currently provides a single object as part of its API:
|
|
||||||
``qunitsuite.QUnitSuite(testfile[, timeout])``.
|
|
||||||
|
|
||||||
This produces a ``unittest.TestSuite`` suitable for all the usual
|
|
||||||
stuff (running it, and giving it to an other test suite which will run
|
|
||||||
it, that is).
|
|
||||||
|
|
||||||
``testfile`` is the HTML file bootstrapping your qunit tests, as would
|
|
||||||
usually be accessed via a browser. It can be either a local
|
|
||||||
(``file:``) url, or an HTTP one. As long as a regular browser can open
|
|
||||||
and execute it, PhantomJS_ will manage.
|
|
||||||
|
|
||||||
``timeout`` is a check passed to the PhantomJS_ runner: if the runner
|
|
||||||
produces no information for longer than ``timeout`` milliseconds, the
|
|
||||||
run will be cancelled and a test error will be generated. This
|
|
||||||
situation usually means either your ``testfile`` is not a qunit test
|
|
||||||
file, qunit is not running or qunit's runner was stopped (for an async
|
|
||||||
test) and never restarted.
|
|
||||||
|
|
||||||
The default value is very conservative, most tests should run
|
|
||||||
correctly with lower timeouts (especially if all tests are
|
|
||||||
synchronous).
|
|
||||||
|
|
||||||
How
|
|
||||||
---
|
|
||||||
|
|
||||||
``unittest``'s autodiscovery protocol does not directly work with test
|
|
||||||
suites (it looks for test cases). If you want autodiscovery to work
|
|
||||||
correctly, you will have to use the ``load_tests`` protocol::
|
|
||||||
|
|
||||||
# in a testing module
|
|
||||||
def load_tests(loader, tests, pattern):
|
|
||||||
tests.addTest(QUnitSuite(qunit_test_path.html))
|
|
||||||
return tests
|
|
||||||
|
|
||||||
outside of that specific case, you can use a ``QUnitSuite`` as a
|
|
||||||
standard ``TestSuite`` instance, running it, adding it to an other
|
|
||||||
suite or passing it to a ``TestRunner``
|
|
||||||
|
|
||||||
Complaints and Grievances
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
Speed
|
|
||||||
~~~~~
|
|
||||||
|
|
||||||
Starting up a phantomjs instance and running a suite turns out to have
|
|
||||||
a rather high overhead, on the order of a second on this machine
|
|
||||||
(2.4GHz, 8GB RAM and an SSD).
|
|
||||||
|
|
||||||
As each ``QUnitSuite`` currently creates its own phantomjs instance,
|
|
||||||
it's probably a good idea to create bigger suites (put many modules &
|
|
||||||
tests in the same QUnit html file, which doesn't preclude splitting
|
|
||||||
them across multiple js files).
|
|
||||||
|
|
||||||
Hacks
|
|
||||||
~~~~~
|
|
||||||
|
|
||||||
QUnitSuite contains a pretty big hack which may or may not cause
|
|
||||||
problem depending on your exact setup: in case of case failure or
|
|
||||||
error, ``unittest.TestResult`` formats the error traceback provided
|
|
||||||
alongside the test object. This goes through Python's
|
|
||||||
traceback-formatting code and there are no hooks there.
|
|
||||||
|
|
||||||
One could expect to use a custom ``TestResult``, but for test suites
|
|
||||||
the ``TestResult`` instance must be provided by the caller, so there
|
|
||||||
is no direct hook onto it.
|
|
||||||
|
|
||||||
This leaves three options:
|
|
||||||
|
|
||||||
* Create a custom ``TestResult`` class and require that it be the one
|
|
||||||
provided to the test suite. This requires altered work flows,
|
|
||||||
customization of the test runner and (as far as I know) isn't
|
|
||||||
available through Python 2.7's autodiscovery. It's the cleanest
|
|
||||||
option but completely fails on practicality.
|
|
||||||
|
|
||||||
* Create a custom ``TestResult`` which directly alters the original
|
|
||||||
result's ``errors`` and ``failures`` attributes as they're part of
|
|
||||||
the testrunner API. This would work but may put custom results in a
|
|
||||||
strange state and break e.g. unittest2's ``@failfast``.
|
|
||||||
|
|
||||||
* Lastly, monkeypatch the undocumented and implementation detail
|
|
||||||
``_exc_info_to_string`` on the provided ``result``. This is the
|
|
||||||
route taken, at least for now.
|
|
||||||
|
|
||||||
.. _QUnit: http://qunitjs.com/
|
|
||||||
|
|
||||||
.. _PhantomJS: http://phantomjs.org/
|
|
||||||
|
|
||||||
.. _Ben Alman: http://benalman.com/
|
|
||||||
|
|
||||||
.. _grunt: http://gruntjs.com/
|
|
|
@ -1,95 +0,0 @@
|
||||||
/*
|
|
||||||
* grunt
|
|
||||||
* http://gruntjs.com/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2012 "Cowboy" Ben Alman
|
|
||||||
* Licensed under the MIT license.
|
|
||||||
* http://benalman.com/about/license/
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*global phantom:true*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
// The page .html file to load.
|
|
||||||
var url = phantom.args[0];
|
|
||||||
// Extra, optionally overridable stuff.
|
|
||||||
var options = JSON.parse(phantom.args[1] || {});
|
|
||||||
|
|
||||||
// Default options.
|
|
||||||
if (!options.timeout) { options.timeout = 5000; }
|
|
||||||
|
|
||||||
// Keep track of the last time a client message was sent.
|
|
||||||
var last = new Date();
|
|
||||||
|
|
||||||
// Messages are sent to the parent by appending them to the tempfile.
|
|
||||||
var sendMessage = function(arg) {
|
|
||||||
var args = Array.isArray(arg) ? arg : [].slice.call(arguments);
|
|
||||||
last = new Date();
|
|
||||||
console.log(JSON.stringify(args));
|
|
||||||
};
|
|
||||||
|
|
||||||
// This allows grunt to abort if the PhantomJS version isn't adequate.
|
|
||||||
sendMessage('private', 'version', phantom.version);
|
|
||||||
|
|
||||||
// Abort if the page doesn't send any messages for a while.
|
|
||||||
setInterval(function() {
|
|
||||||
if (new Date() - last > options.timeout) {
|
|
||||||
sendMessage('fail.timeout');
|
|
||||||
phantom.exit();
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
// Create a new page.
|
|
||||||
var page = require('webpage').create();
|
|
||||||
|
|
||||||
// The client page must send its messages via alert(jsonstring).
|
|
||||||
page.onAlert = function(args) {
|
|
||||||
sendMessage(JSON.parse(args));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Keep track if the client-side helper script already has been injected.
|
|
||||||
var injected;
|
|
||||||
page.onUrlChanged = function(newUrl) {
|
|
||||||
injected = false;
|
|
||||||
sendMessage('onUrlChanged', newUrl);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Relay console logging messages.
|
|
||||||
page.onConsoleMessage = function(message) {
|
|
||||||
sendMessage('console', message);
|
|
||||||
};
|
|
||||||
|
|
||||||
// For debugging.
|
|
||||||
page.onResourceRequested = function(request) {
|
|
||||||
sendMessage('onResourceRequested', request.url);
|
|
||||||
};
|
|
||||||
|
|
||||||
page.onResourceReceived = function(request) {
|
|
||||||
if (request.stage === 'end') {
|
|
||||||
sendMessage('onResourceReceived', request.url);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Run when the page has finished loading.
|
|
||||||
page.onLoadFinished = function(status) {
|
|
||||||
// The window has loaded.
|
|
||||||
sendMessage('onLoadFinished', status);
|
|
||||||
if (status === 'success') {
|
|
||||||
if (options.inject && !injected) {
|
|
||||||
// Inject client-side helper script, but only if it has not yet been
|
|
||||||
// injected.
|
|
||||||
sendMessage('inject', options.inject);
|
|
||||||
page.injectJs(options.inject);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// File loading failure.
|
|
||||||
sendMessage('fail.load', url);
|
|
||||||
phantom.exit();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Actually load url.
|
|
||||||
page.open(url);
|
|
|
@ -1,22 +0,0 @@
|
||||||
Copyright (c) 2012 "Cowboy" Ben Alman
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
|
||||||
obtaining a copy of this software and associated documentation
|
|
||||||
files (the "Software"), to deal in the Software without
|
|
||||||
restriction, including without limitation the rights to use,
|
|
||||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following
|
|
||||||
conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||||
OTHER DEALINGS IN THE SOFTWARE.
|
|
|
@ -1 +0,0 @@
|
||||||
{}
|
|
|
@ -1,88 +0,0 @@
|
||||||
/*
|
|
||||||
* grunt
|
|
||||||
* http://gruntjs.com/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2012 "Cowboy" Ben Alman
|
|
||||||
* Licensed under the MIT license.
|
|
||||||
* http://benalman.com/about/license/
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*global QUnit:true, alert:true*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// Don't re-order tests.
|
|
||||||
QUnit.config.reorder = false;
|
|
||||||
// Run tests serially, not in parallel.
|
|
||||||
QUnit.config.autorun = false;
|
|
||||||
|
|
||||||
// Send messages to the parent PhantomJS process via alert! Good times!!
|
|
||||||
function sendMessage() {
|
|
||||||
var args = [].slice.call(arguments);
|
|
||||||
alert(JSON.stringify(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
// These methods connect QUnit to PhantomJS.
|
|
||||||
QUnit.log(function(obj) {
|
|
||||||
// What is this I don’t even
|
|
||||||
if (obj.message === '[object Object], undefined:undefined') { return; }
|
|
||||||
// Parse some stuff before sending it.
|
|
||||||
var actual = QUnit.jsDump.parse(obj.actual);
|
|
||||||
var expected = QUnit.jsDump.parse(obj.expected);
|
|
||||||
// Send it.
|
|
||||||
sendMessage('qunit.log', obj.result, actual, expected, obj.message, obj.source);
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.testStart(function(obj) {
|
|
||||||
sendMessage('qunit.testStart', obj.name);
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.testDone(function(obj) {
|
|
||||||
sendMessage('qunit.testDone', obj.name, obj.failed, obj.passed, obj.total);
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.moduleStart(function(obj) {
|
|
||||||
sendMessage('qunit.moduleStart', obj.name);
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.moduleDone(function(obj) {
|
|
||||||
sendMessage('qunit.moduleDone', obj.name, obj.failed, obj.passed, obj.total);
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.begin(function() {
|
|
||||||
sendMessage('qunit.begin');
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.done(function(obj) {
|
|
||||||
sendMessage('qunit.done', obj.failed, obj.passed, obj.total, obj.runtime);
|
|
||||||
});
|
|
||||||
|
|
||||||
// PhantomJS (up to and including 1.7) uses a version of webkit so old
|
|
||||||
// it does not have Function.prototype.bind:
|
|
||||||
// http://code.google.com/p/phantomjs/issues/detail?id=522
|
|
||||||
|
|
||||||
// Use moz polyfill:
|
|
||||||
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind#Compatibility
|
|
||||||
if (!Function.prototype.bind) {
|
|
||||||
Function.prototype.bind = function (oThis) {
|
|
||||||
if (typeof this !== "function") {
|
|
||||||
// closest thing possible to the ECMAScript 5 internal IsCallable function
|
|
||||||
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
|
|
||||||
}
|
|
||||||
|
|
||||||
var aArgs = Array.prototype.slice.call(arguments, 1),
|
|
||||||
fToBind = this,
|
|
||||||
fNOP = function () {},
|
|
||||||
fBound = function () {
|
|
||||||
return fToBind.apply(this instanceof fNOP && oThis
|
|
||||||
? this
|
|
||||||
: oThis,
|
|
||||||
aArgs.concat(Array.prototype.slice.call(arguments)));
|
|
||||||
};
|
|
||||||
|
|
||||||
fNOP.prototype = this.prototype;
|
|
||||||
fBound.prototype = new fNOP();
|
|
||||||
|
|
||||||
return fBound;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,136 +0,0 @@
|
||||||
import json
|
|
||||||
import subprocess
|
|
||||||
import unittest
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
|
|
||||||
ROOT = os.path.join(os.path.dirname(__file__), 'grunt')
|
|
||||||
|
|
||||||
__all__ = ['QUnitSuite']
|
|
||||||
|
|
||||||
def _exc_info_to_string(err, test):
|
|
||||||
return err
|
|
||||||
|
|
||||||
class QUnitTest(unittest.TestCase):
|
|
||||||
def __init__(self, module, name):
|
|
||||||
self.module = module
|
|
||||||
self.name = name
|
|
||||||
self.failed = False
|
|
||||||
def shortDescription(self):
|
|
||||||
return None
|
|
||||||
def __repr__(self):
|
|
||||||
return '<QUnitTest %s:%s>' % (self.module, self.name)
|
|
||||||
def __str__(self):
|
|
||||||
return '%s: %s' % (self.module, self.name)
|
|
||||||
|
|
||||||
class QUnitSuite(unittest.TestSuite):
|
|
||||||
def __init__(self, qunitfile, timeout=5000):
|
|
||||||
super(QUnitSuite, self).__init__()
|
|
||||||
self.testfile = qunitfile
|
|
||||||
self.timeout = timeout
|
|
||||||
self._module = None
|
|
||||||
self._test = None
|
|
||||||
|
|
||||||
def run(self, result):
|
|
||||||
try:
|
|
||||||
subprocess.call(['phantomjs', '-v'],
|
|
||||||
stdout=open(os.devnull, 'w'),
|
|
||||||
stderr=subprocess.STDOUT)
|
|
||||||
except OSError:
|
|
||||||
test = QUnitTest('phantomjs', 'javascript tests')
|
|
||||||
result.startTest(test)
|
|
||||||
result.startTest(test)
|
|
||||||
result.addSkip(test , "phantomjs command not found")
|
|
||||||
result.stopTest(test)
|
|
||||||
return
|
|
||||||
|
|
||||||
result._exc_info_to_string = _exc_info_to_string
|
|
||||||
try:
|
|
||||||
self._run(result)
|
|
||||||
finally:
|
|
||||||
del result._exc_info_to_string
|
|
||||||
|
|
||||||
def _run(self, result):
|
|
||||||
phantom = subprocess.Popen([
|
|
||||||
'phantomjs',
|
|
||||||
'--config=%s' % os.path.join(ROOT, 'phantomjs.json'),
|
|
||||||
os.path.join(ROOT, 'bootstrap.js'), self.testfile,
|
|
||||||
json.dumps({
|
|
||||||
'timeout': self.timeout,
|
|
||||||
'inject': os.path.join(ROOT, 'qunit-phantomjs-bridge.js')
|
|
||||||
})
|
|
||||||
], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
|
||||||
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
line = phantom.stdout.readline()
|
|
||||||
if line:
|
|
||||||
if self.process(line, result):
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
time.sleep(0.1)
|
|
||||||
finally:
|
|
||||||
# If the phantomjs process hasn't quit, kill it
|
|
||||||
if phantom.poll() is None:
|
|
||||||
phantom.terminate()
|
|
||||||
|
|
||||||
def process(self, line, result):
|
|
||||||
try:
|
|
||||||
args = json.loads(line)
|
|
||||||
except ValueError: # phantomjs stderr
|
|
||||||
if 'CoreText' not in line:
|
|
||||||
print line
|
|
||||||
return False
|
|
||||||
event_name = args[0]
|
|
||||||
|
|
||||||
if event_name == 'qunit.done':
|
|
||||||
return True
|
|
||||||
elif event_name == 'fail.load':
|
|
||||||
self.add_error(result, "PhantomJS unable to load %s" % args[1])
|
|
||||||
return True
|
|
||||||
elif event_name == 'fail.timeout':
|
|
||||||
self.add_error(result, "PhantomJS timed out, possibly due to a"
|
|
||||||
" missing QUnit start() call")
|
|
||||||
return True
|
|
||||||
|
|
||||||
elif event_name == 'qunit.moduleStart':
|
|
||||||
self._module = args[1].encode('utf-8') if args[1] else ''
|
|
||||||
elif event_name == 'qunit.moduleStop':
|
|
||||||
self._test = None
|
|
||||||
self._module = None
|
|
||||||
elif event_name == 'qunit.testStart':
|
|
||||||
self._test = QUnitTest(self._module, args[1].encode('utf-8'))
|
|
||||||
result.startTest(self._test)
|
|
||||||
elif event_name == 'qunit.testDone':
|
|
||||||
if not self._test.failed:
|
|
||||||
result.addSuccess(self._test)
|
|
||||||
result.stopTest(self._test)
|
|
||||||
self._test = None
|
|
||||||
elif event_name == 'qunit.log':
|
|
||||||
if args[1]:
|
|
||||||
return False
|
|
||||||
|
|
||||||
self._test.failed = True
|
|
||||||
result.addFailure(
|
|
||||||
self._test, self.failure_to_str(*args[2:]))
|
|
||||||
elif event_name == 'console':
|
|
||||||
print args[1]
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def add_error(self, result, s):
|
|
||||||
test = QUnitTest('phantomjs', 'startup')
|
|
||||||
result.startTest(test)
|
|
||||||
result.addError(test, s)
|
|
||||||
result.stopTest(test)
|
|
||||||
|
|
||||||
def failure_to_str(self, actual, expected, message, source):
|
|
||||||
if message or actual == expected:
|
|
||||||
formatted = str(message or '')
|
|
||||||
else:
|
|
||||||
formatted = "%s != %s" % (actual, expected)
|
|
||||||
|
|
||||||
if source:
|
|
||||||
formatted += '\n\n' + source
|
|
||||||
|
|
||||||
return formatted
|
|
|
@ -1,24 +1,6 @@
|
||||||
import urllib
|
import openerp
|
||||||
import urlparse
|
|
||||||
from openerp import sql_db, tools
|
|
||||||
from qunitsuite.suite import QUnitSuite
|
|
||||||
|
|
||||||
class WebSuite(QUnitSuite):
|
class WebSuite(openerp.tests.HttpCase):
|
||||||
def __init__(self, module):
|
def test_01_js(self):
|
||||||
url = urlparse.urlunsplit([
|
self.phantom_js('/web/tests?mod=web',"","", login='admin')
|
||||||
'http',
|
|
||||||
'localhost:{port}'.format(port=tools.config['xmlrpc_port']),
|
|
||||||
'/web/tests',
|
|
||||||
urllib.urlencode({
|
|
||||||
'mod': module,
|
|
||||||
'source': tools.config['db_name'],
|
|
||||||
'supadmin': tools.config['admin_passwd'],
|
|
||||||
'password': 'admin',
|
|
||||||
}),
|
|
||||||
''
|
|
||||||
])
|
|
||||||
super(WebSuite, self).__init__(url, 50000)
|
|
||||||
|
|
||||||
def load_tests(loader, standard_tests, _):
|
|
||||||
standard_tests.addTest(WebSuite('web'))
|
|
||||||
return standard_tests
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
'name': 'Hello',
|
|
||||||
'category': 'Hidden',
|
|
||||||
'description':"""
|
|
||||||
OpenERP Web example module.
|
|
||||||
===========================
|
|
||||||
|
|
||||||
""",
|
|
||||||
'version': '2.0',
|
|
||||||
'depends': [],
|
|
||||||
'js': ['static/*/*.js', 'static/*/js/*.js'],
|
|
||||||
'css': [],
|
|
||||||
'auto_install': False,
|
|
||||||
'web_preload': False,
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
/*---------------------------------------------------------
|
|
||||||
* OpenERP base_hello (Example module)
|
|
||||||
*---------------------------------------------------------*/
|
|
||||||
|
|
||||||
openerp.web_hello = function(instance) {
|
|
||||||
|
|
||||||
instance.web.SearchView = instance.web.SearchView.extend({
|
|
||||||
init:function() {
|
|
||||||
this._super.apply(this,arguments);
|
|
||||||
this.on('search_data', this, function(){console.log('hello');});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// vim:et fdc=0 fdl=0:
|
|
|
@ -1 +1,2 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
import tests
|
||||||
|
|
|
@ -7,7 +7,7 @@ OpenERP Web test suite.
|
||||||
|
|
||||||
""",
|
""",
|
||||||
'version': '2.0',
|
'version': '2.0',
|
||||||
'depends': [],
|
'depends': ['web', 'web_kanban'],
|
||||||
'js': ['static/src/js/*.js'],
|
'js': ['static/src/js/*.js'],
|
||||||
'css': ['static/src/css/*.css'],
|
'css': ['static/src/css/*.css'],
|
||||||
'auto_install': True,
|
'auto_install': True,
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import test_ui
|
|
@ -1,6 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from openerp.addons.web.tests.test_js import WebSuite
|
|
||||||
|
|
||||||
def load_tests(loader, standard_tests, _):
|
|
||||||
standard_tests.addTest(WebSuite('web_tests_demo'))
|
|
||||||
return standard_tests
|
|
Loading…
Reference in New Issue