Skip to content

Commit

Permalink
Add Document_Query.input(..) to allow keyboard input.
Browse files Browse the repository at this point in the history
The method can only input text at this time and cannot simulate a keypress
due to a bug in WebKit. This may be a serious issue in the future if we
want to be able to simulate full keyboard interactions, such as individual
keys with modifiers.
  • Loading branch information
StanAngeloff committed Nov 2, 2011
1 parent 62f525d commit 7ee969d
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 6 deletions.
30 changes: 27 additions & 3 deletions lib/inject/document_query.js
Expand Up @@ -152,14 +152,14 @@ DocumentQuery.prototype.event = function DocumentQuery_event(options, index, mes
if ( ! _elements.length) {\n\
return "expected at least one element: " + _query;\n\
}\n\
var _index = ' + this._wrap(index) + ';\n\
if ( ! _elements[_index]) {\n\
var _element = _elements[' + this._wrap(index) + '];\n\
if ( ! _element) {\n\
return "no element at index ' + JSON.stringify(index) + ': " + _query;\n\
}\n\
' + (options.event.setUp || '') + '\n\
var _event = document.createEvent(' + JSON.stringify(options.event.type) + ');\n\
_event.' + options.event.initialize + '(' + values.join(', ') + ');\n\
_elements[_index].dispatchEvent(_event);\n\
_element.dispatchEvent(_event);\n\
' + (options.event.tearDown || '') + '\n\
return true;\n\
');
Expand All @@ -169,6 +169,30 @@ DocumentQuery.prototype.first = function DocumentQuery_first(message, block) {
return this.nth.apply(this, [0].concat(Array.prototype.slice.call(arguments)));
};

DocumentQuery.prototype.input = function DocumentQuery_input(value, index, message) {
// NOTE: Due to a [bug] in WebKit, we cannot use 'KeyboardEvent' to emit 'keypress' events.
//
// [bug]: https://bugs.webkit.org/show_bug.cgi?id=16735
return this.event.apply(this, [index, message, {
event: {
type: 'TextEvent',
initialize: 'initTextEvent',
options: [
{ key: 'type', default: 'textInput' },
{ key: 'canBubble', default: true },
{ key: 'cancelable', default: true },
'window',
{ key: 'value', default: value },
{ key: 'inputMethod', default: INPUT_METHOD_SCRIPT },
{ key: 'locale', default: 'en-US' }
],
setUp: '\n\
try { _element.select(); } catch (e) {}\n\
',
}
}]);
};

DocumentQuery.prototype.last = function DocumentQuery_last(message, block) {
return this.nth.apply(this, [-1].concat(Array.prototype.slice.call(arguments)));
};
Expand Down
17 changes: 14 additions & 3 deletions lib/inject/main.js
@@ -1,11 +1,22 @@
const PADDING = ' ';

const STATUS_SUCCESS = 'success';
const STATUS_FAIL = 'fail';
const STATUS_EXCEPTION = 'exception';
const STATUS_SKIPED = 'skipped';

const BREAK_CASE = '__breakCase__';
const INPUT_METHOD_UNKNOWN = 0x00;
const INPUT_METHOD_KEYBOARD = 0x01;
const INPUT_METHOD_CLIPBOARD = 0x02;
const INPUT_METHOD_DRAG_AND_DROP = 0x03;
const INPUT_METHOD_IME = 0x04;
const INPUT_METHOD_FORM = 0x05;
const INPUT_METHOD_PEN = 0x06;
const INPUT_METHOD_OCR = 0x07;
const INPUT_METHOD_MULTIPLE = 0x08;
const INPUT_METHOD_SCRIPT = 0x09;

const BREAK_CASE = '__breakCase__';

const PADDING = ' ';

var _webpage = require('webpage'),
_ansi = require('./ansi'),
Expand Down
14 changes: 14 additions & 0 deletions test/public/input.html
@@ -0,0 +1,14 @@
<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<title>Lotte</title>
</head>
<body>

<input type=text id=box1 value=World>
<textarea id=box2>Hello
World!</textarea>

</body>
</html>
24 changes: 24 additions & 0 deletions test/test_input.coffee
@@ -0,0 +1,24 @@
@base 'http://' + phantom.args[0] + ':' + phantom.args[1]
@title 'localhost.localdomain'

@open '/input.html', 'input(..) evaluates correctly', ->
@describe 'should access default values', ->
@assert.equal @$('#box1').value, 'World', 'expects default value in first box'
@assert.equal @$('#box2').value, 'Hello\nWorld!', 'expects default value in second box'
@success()
@describe 'should throw when attempting to set value directly', ->
@assert.throws ( => @$('#box1').value = 'knock, knock!'), /^TypeError.*getter$/, "expects .value to be read-only"
@success()
@describe 'should input text', ->
@$('#box1').input value = 'Who are you?'
@assert.equal @$('#box1').value, value, 'expects value in first box to update'
@$('#box2').input value = "I am\n'John Doe'."
@assert.equal @$('#box2').value, value, 'expects value in second box to update'
@success()
@describe 'should read and input text', ->
previous = @$('#box1').value
@$('#box1')
.input(value = "#{previous} I am John Doe.")
.contains('expects previous value in first box to persist', previous)
@assert.equal @$('#box1').value, value, 'expects value in first box to update'
@success()

0 comments on commit 7ee969d

Please sign in to comment.