mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 02:34:06 -04:00
JS Browser: Support for AJAX form submission
This commit is contained in:
parent
70ff56c1b2
commit
f9dabe9140
@ -130,6 +130,7 @@ class NetworkAccessManager(QNetworkAccessManager): # {{{
|
|||||||
|
|
||||||
def __init__(self, log, use_disk_cache=True, parent=None):
|
def __init__(self, log, use_disk_cache=True, parent=None):
|
||||||
QNetworkAccessManager.__init__(self, parent)
|
QNetworkAccessManager.__init__(self, parent)
|
||||||
|
self.reply_count = 0
|
||||||
self.log = log
|
self.log = log
|
||||||
if use_disk_cache:
|
if use_disk_cache:
|
||||||
self.cache = QNetworkDiskCache(self)
|
self.cache = QNetworkDiskCache(self)
|
||||||
@ -170,6 +171,7 @@ class NetworkAccessManager(QNetworkAccessManager): # {{{
|
|||||||
|
|
||||||
def on_finished(self, reply):
|
def on_finished(self, reply):
|
||||||
reply_url = unicode(reply.url().toString())
|
reply_url = unicode(reply.url().toString())
|
||||||
|
self.reply_count += 1
|
||||||
|
|
||||||
if reply.error():
|
if reply.error():
|
||||||
self.log.warn("Reply error: %s - %d (%s)" %
|
self.log.warn("Reply error: %s - %d (%s)" %
|
||||||
@ -286,6 +288,17 @@ class Browser(QObject, FormsMixin):
|
|||||||
|
|
||||||
return lw.loaded_ok
|
return lw.loaded_ok
|
||||||
|
|
||||||
|
def _wait_for_replies(self, reply_count, timeout):
|
||||||
|
final_time = time.time() + timeout
|
||||||
|
loop = QEventLoop(self)
|
||||||
|
while (time.time() < final_time and self.nam.reply_count <
|
||||||
|
reply_count):
|
||||||
|
loop.processEvents()
|
||||||
|
time.sleep(0.1)
|
||||||
|
if self.nam.reply_count < reply_count:
|
||||||
|
raise Timeout('Waiting for replies took longer than %d seconds' %
|
||||||
|
timeout)
|
||||||
|
|
||||||
def visit(self, url, timeout=30.0):
|
def visit(self, url, timeout=30.0):
|
||||||
'''
|
'''
|
||||||
Open the page specified in URL and wait for it to complete loading.
|
Open the page specified in URL and wait for it to complete loading.
|
||||||
@ -310,6 +323,7 @@ class Browser(QObject, FormsMixin):
|
|||||||
:para ajax_replies: Number of replies to wait for after clicking a link
|
:para ajax_replies: Number of replies to wait for after clicking a link
|
||||||
that triggers some AJAX interaction
|
that triggers some AJAX interaction
|
||||||
'''
|
'''
|
||||||
|
initial_count = self.nam.reply_count
|
||||||
js = '''
|
js = '''
|
||||||
var e = document.createEvent('MouseEvents');
|
var e = document.createEvent('MouseEvents');
|
||||||
e.initEvent( 'click', true, true );
|
e.initEvent( 'click', true, true );
|
||||||
@ -317,7 +331,8 @@ class Browser(QObject, FormsMixin):
|
|||||||
'''
|
'''
|
||||||
qwe.evaluateJavaScript(js)
|
qwe.evaluateJavaScript(js)
|
||||||
if ajax_replies > 0:
|
if ajax_replies > 0:
|
||||||
raise NotImplementedError('AJAX clicking not implemented')
|
reply_count = initial_count + ajax_replies
|
||||||
|
self._wait_for_replies(reply_count, timeout)
|
||||||
elif wait_for_load and not self._wait_for_load(timeout):
|
elif wait_for_load and not self._wait_for_load(timeout):
|
||||||
raise LoadError('Clicking resulted in a failed load')
|
raise LoadError('Clicking resulted in a failed load')
|
||||||
|
|
||||||
|
@ -229,3 +229,15 @@ class FormsMixin(object):
|
|||||||
self.click(sc.qwe, wait_for_load=wait_for_load,
|
self.click(sc.qwe, wait_for_load=wait_for_load,
|
||||||
ajax_replies=ajax_replies, timeout=timeout)
|
ajax_replies=ajax_replies, timeout=timeout)
|
||||||
|
|
||||||
|
def ajax_submit(self, submit_control_selector=None,
|
||||||
|
num_of_replies=1, timeout=30.0):
|
||||||
|
'''
|
||||||
|
Submit the current form. This method is meant for those forms that
|
||||||
|
use AJAX rather than a plain submit. It will block until the specified
|
||||||
|
number of responses are returned from the server after the submit
|
||||||
|
button is clicked.
|
||||||
|
'''
|
||||||
|
self.submit(submit_control_selector=submit_control_selector,
|
||||||
|
wait_for_load=False, ajax_replies=num_of_replies,
|
||||||
|
timeout=timeout)
|
||||||
|
|
||||||
|
@ -23,6 +23,24 @@ class Server(object):
|
|||||||
return '''
|
return '''
|
||||||
<html>
|
<html>
|
||||||
<head><title>JS Browser test</title></head>
|
<head><title>JS Browser test</title></head>
|
||||||
|
<script type="text/javascript" src="jquery"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#ajax_test').submit(function() {
|
||||||
|
var val = $('#ajax_test input[name="text"]').val();
|
||||||
|
$.ajax({
|
||||||
|
dataType: "html",
|
||||||
|
url: "/controls_test",
|
||||||
|
data: {"text":val},
|
||||||
|
success: function(data) {
|
||||||
|
$('#ajax_test input[name="text"]').val(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<form id="controls_test" method="post" action="controls_test">
|
<form id="controls_test" method="post" action="controls_test">
|
||||||
<h3>Test controls</h3>
|
<h3>Test controls</h3>
|
||||||
@ -40,6 +58,12 @@ class Server(object):
|
|||||||
<div><label>Simple Text:</label><input type="text" name="text" value="Image Test" /></div>
|
<div><label>Simple Text:</label><input type="text" name="text" value="Image Test" /></div>
|
||||||
<input type="image" src="button_image" alt="Submit" />
|
<input type="image" src="button_image" alt="Submit" />
|
||||||
</form>
|
</form>
|
||||||
|
<form id="ajax_test" method="post" action="controls_test">
|
||||||
|
<h3>Test AJAX submit</h3>
|
||||||
|
<div><label>Simple Text:</label><input type="text" name="text" value="AJAX Test" /></div>
|
||||||
|
<input type="submit" />
|
||||||
|
</form>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
'''
|
'''
|
||||||
@ -55,6 +79,12 @@ class Server(object):
|
|||||||
cherrypy.response.headers['Content-Type'] = 'image/png'
|
cherrypy.response.headers['Content-Type'] = 'image/png'
|
||||||
return I('next.png', data=True)
|
return I('next.png', data=True)
|
||||||
|
|
||||||
|
@cherrypy.expose
|
||||||
|
def jquery(self):
|
||||||
|
cherrypy.response.headers['Content-Type'] = 'text/javascript'
|
||||||
|
return P('content_server/jquery.js', data=True)
|
||||||
|
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
class Test(unittest.TestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -121,6 +151,15 @@ class Test(unittest.TestCase):
|
|||||||
self.browser.submit()
|
self.browser.submit()
|
||||||
self.assertEqual(self.server.form_data['text'], 'Image Test')
|
self.assertEqual(self.server.form_data['text'], 'Image Test')
|
||||||
|
|
||||||
|
def test_ajax_submit(self):
|
||||||
|
'Test AJAX based form submission'
|
||||||
|
self.assertEqual(self.browser.visit('http://127.0.0.1:%d'%self.port),
|
||||||
|
True)
|
||||||
|
f = self.browser.select_form('#ajax_test')
|
||||||
|
f['text'] = 'Changed'
|
||||||
|
self.browser.ajax_submit()
|
||||||
|
self.assertEqual(self.server.form_data['text'], 'Changed')
|
||||||
|
|
||||||
def tests():
|
def tests():
|
||||||
return unittest.TestLoader().loadTestsFromTestCase(Test)
|
return unittest.TestLoader().loadTestsFromTestCase(Test)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user