diff --git a/CHANGELOG.md b/CHANGELOG.md index 88b397da..c17ea77b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ * Support reading text from SVG elements (Oliver Searle-Barnes) * Whitespace character in `current_url` remained unencoded [Issue #418] +* Fix event.target for change events on SELECT elements. (Jonathan Baudanza) [Issue #204] + ### 1.6.0 ### #### Features #### diff --git a/lib/capybara/poltergeist/client/agent.coffee b/lib/capybara/poltergeist/client/agent.coffee index afd58e7e..314fe8ca 100644 --- a/lib/capybara/poltergeist/client/agent.coffee +++ b/lib/capybara/poltergeist/client/agent.coffee @@ -115,7 +115,15 @@ class PoltergeistAgent.Node changed: -> event = document.createEvent('HTMLEvents') event.initEvent('change', true, false) - @element.dispatchEvent(event) + + # In the case of an OPTION tag, the change event should come + # from the parent SELECT + if @element.nodeName == 'OPTION' + element = @element.parentNode + else + element = @element + + element.dispatchEvent(event) input: -> event = document.createEvent('HTMLEvents') diff --git a/lib/capybara/poltergeist/client/compiled/agent.js b/lib/capybara/poltergeist/client/compiled/agent.js index 2d915fce..a3249c16 100644 --- a/lib/capybara/poltergeist/client/compiled/agent.js +++ b/lib/capybara/poltergeist/client/compiled/agent.js @@ -153,9 +153,9 @@ PoltergeistAgent.Node = (function() { FORM: ['submit'] }; - function Node(agent, element) { - this.agent = agent; - this.element = element; + function Node(_at_agent, _at_element) { + this.agent = _at_agent; + this.element = _at_element; } Node.prototype.parentId = function() { @@ -178,27 +178,33 @@ PoltergeistAgent.Node = (function() { }; Node.prototype.isObsolete = function() { - var obsolete, - _this = this; - obsolete = function(element) { - if (element.parentNode != null) { - if (element.parentNode === document) { - return false; + var obsolete; + obsolete = (function(_this) { + return function(element) { + if (element.parentNode != null) { + if (element.parentNode === document) { + return false; + } else { + return obsolete(element.parentNode); + } } else { - return obsolete(element.parentNode); + return true; } - } else { - return true; - } - }; + }; + })(this); return obsolete(this.element); }; Node.prototype.changed = function() { - var event; + var element, event; event = document.createEvent('HTMLEvents'); event.initEvent('change', true, false); - return this.element.dispatchEvent(event); + if (this.element.nodeName === 'OPTION') { + element = this.element.parentNode; + } else { + element = this.element; + } + return element.dispatchEvent(event); }; Node.prototype.input = function() { diff --git a/lib/capybara/poltergeist/client/compiled/browser.js b/lib/capybara/poltergeist/client/compiled/browser.js index 4b193fac..0525dfe9 100644 --- a/lib/capybara/poltergeist/client/compiled/browser.js +++ b/lib/capybara/poltergeist/client/compiled/browser.js @@ -1,8 +1,8 @@ var __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; Poltergeist.Browser = (function() { - function Browser(owner, width, height) { - this.owner = owner; + function Browser(_at_owner, width, height) { + this.owner = _at_owner; this.width = width || 1024; this.height = height || 768; this.pages = []; @@ -13,8 +13,7 @@ Poltergeist.Browser = (function() { } Browser.prototype.resetPage = function() { - var _ref, - _this = this; + var _ref; _ref = [0, []], this._counter = _ref[0], this.pages = _ref[1]; if (this.page != null) { if (!this.page.closed) { @@ -32,12 +31,14 @@ Poltergeist.Browser = (function() { }); this.page.handle = "" + (this._counter++); this.pages.push(this.page); - return this.page.onPageCreated = function(newPage) { - var page; - page = new Poltergeist.WebPage(newPage); - page.handle = "" + (_this._counter++); - return _this.pages.push(page); - }; + return this.page.onPageCreated = (function(_this) { + return function(newPage) { + var page; + page = new Poltergeist.WebPage(newPage); + page.handle = "" + (_this._counter++); + return _this.pages.push(page); + }; + })(this); }; Browser.prototype.getPageByHandle = function(handle) { @@ -82,8 +83,7 @@ Poltergeist.Browser = (function() { }; Browser.prototype.visit = function(url) { - var prevUrl, - _this = this; + var prevUrl; this.currentPage.state = 'loading'; prevUrl = this.currentPage.source === null ? 'about:blank' : this.currentPage.currentUrl(); this.currentPage.open(url); @@ -93,15 +93,17 @@ Poltergeist.Browser = (function() { status: 'success' }); } else { - return this.currentPage.waitState('default', function() { - if (_this.currentPage.statusCode === null && _this.currentPage.status === 'fail') { - return _this.owner.sendError(new Poltergeist.StatusFailError); - } else { - return _this.sendResponse({ - status: _this.currentPage.status - }); - } - }); + return this.currentPage.waitState('default', (function(_this) { + return function() { + if (_this.currentPage.statusCode === null && _this.currentPage.status === 'fail') { + return _this.owner.sendError(new Poltergeist.StatusFailError); + } else { + return _this.sendResponse({ + status: _this.currentPage.status + }); + } + }; + })(this)); } }; @@ -208,8 +210,7 @@ Poltergeist.Browser = (function() { }; Browser.prototype.push_frame = function(name, timeout) { - var _ref, - _this = this; + var _ref; if (timeout == null) { timeout = new Date().getTime() + 2000; } @@ -218,17 +219,21 @@ Poltergeist.Browser = (function() { } else if (this.currentPage.pushFrame(name)) { if (this.currentPage.currentUrl() === 'about:blank') { this.currentPage.state = 'awaiting_frame_load'; - return this.currentPage.waitState('default', function() { - return _this.sendResponse(true); - }); + return this.currentPage.waitState('default', (function(_this) { + return function() { + return _this.sendResponse(true); + }; + })(this)); } else { return this.sendResponse(true); } } else { if (new Date().getTime() < timeout) { - return setTimeout((function() { - return _this.push_frame(name, timeout); - }), 50); + return setTimeout(((function(_this) { + return function() { + return _this.push_frame(name, timeout); + }; + })(this)), 50); } else { return this.owner.sendError(new Poltergeist.FrameNotFound(name)); } @@ -261,15 +266,16 @@ Poltergeist.Browser = (function() { }; Browser.prototype.switch_to_window = function(handle) { - var page, - _this = this; + var page; page = this.getPageByHandle(handle); if (page) { if (page !== this.currentPage) { - return page.waitState('default', function() { - _this.currentPage = page; - return _this.sendResponse(true); - }); + return page.waitState('default', (function(_this) { + return function() { + _this.currentPage = page; + return _this.sendResponse(true); + }; + })(this)); } else { return this.sendResponse(true); } @@ -295,25 +301,26 @@ Poltergeist.Browser = (function() { }; Browser.prototype.mouse_event = function(page_id, id, name) { - var node, - _this = this; + var node; node = this.node(page_id, id); this.currentPage.state = 'mouse_event'; this.last_mouse_event = node.mouseEvent(name); - return setTimeout(function() { - if (_this.currentPage.state === 'mouse_event') { - _this.currentPage.state = 'default'; - return _this.sendResponse({ - position: _this.last_mouse_event - }); - } else { - return _this.currentPage.waitState('default', function() { + return setTimeout((function(_this) { + return function() { + if (_this.currentPage.state === 'mouse_event') { + _this.currentPage.state = 'default'; return _this.sendResponse({ position: _this.last_mouse_event }); - }); - } - }, 5); + } else { + return _this.currentPage.waitState('default', function() { + return _this.sendResponse({ + position: _this.last_mouse_event + }); + }); + } + }; + })(this), 5); }; Browser.prototype.click = function(page_id, id) { @@ -550,26 +557,28 @@ Poltergeist.Browser = (function() { }; Browser.prototype.go_back = function() { - var _this = this; if (this.currentPage.canGoBack) { this.currentPage.state = 'loading'; this.currentPage.goBack(); - return this.currentPage.waitState('default', function() { - return _this.sendResponse(true); - }); + return this.currentPage.waitState('default', (function(_this) { + return function() { + return _this.sendResponse(true); + }; + })(this)); } else { return this.sendResponse(false); } }; Browser.prototype.go_forward = function() { - var _this = this; if (this.currentPage.canGoForward) { this.currentPage.state = 'loading'; this.currentPage.goForward(); - return this.currentPage.waitState('default', function() { - return _this.sendResponse(true); - }); + return this.currentPage.waitState('default', (function(_this) { + return function() { + return _this.sendResponse(true); + }; + })(this)); } else { return this.sendResponse(false); } diff --git a/lib/capybara/poltergeist/client/compiled/connection.js b/lib/capybara/poltergeist/client/compiled/connection.js index 75133032..34ca9efd 100644 --- a/lib/capybara/poltergeist/client/compiled/connection.js +++ b/lib/capybara/poltergeist/client/compiled/connection.js @@ -1,9 +1,9 @@ var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; Poltergeist.Connection = (function() { - function Connection(owner, port) { - this.owner = owner; - this.port = port; + function Connection(_at_owner, _at_port) { + this.owner = _at_owner; + this.port = _at_port; this.commandReceived = __bind(this.commandReceived, this); this.socket = new WebSocket("ws://127.0.0.1:" + this.port + "/"); this.socket.onmessage = this.commandReceived; diff --git a/lib/capybara/poltergeist/client/compiled/main.js b/lib/capybara/poltergeist/client/compiled/main.js index 005816f9..f80ab89d 100644 --- a/lib/capybara/poltergeist/client/compiled/main.js +++ b/lib/capybara/poltergeist/client/compiled/main.js @@ -1,6 +1,6 @@ -var Poltergeist, system, _ref, _ref1, _ref2, - __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; +var Poltergeist, system, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + __hasProp = {}.hasOwnProperty; Poltergeist = (function() { function Poltergeist(port, width, height) { @@ -68,8 +68,7 @@ Poltergeist.ObsoleteNode = (function(_super) { __extends(ObsoleteNode, _super); function ObsoleteNode() { - _ref = ObsoleteNode.__super__.constructor.apply(this, arguments); - return _ref; + return ObsoleteNode.__super__.constructor.apply(this, arguments); } ObsoleteNode.prototype.name = "Poltergeist.ObsoleteNode"; @@ -89,9 +88,9 @@ Poltergeist.ObsoleteNode = (function(_super) { Poltergeist.InvalidSelector = (function(_super) { __extends(InvalidSelector, _super); - function InvalidSelector(method, selector) { - this.method = method; - this.selector = selector; + function InvalidSelector(_at_method, _at_selector) { + this.method = _at_method; + this.selector = _at_selector; } InvalidSelector.prototype.name = "Poltergeist.InvalidSelector"; @@ -107,8 +106,8 @@ Poltergeist.InvalidSelector = (function(_super) { Poltergeist.FrameNotFound = (function(_super) { __extends(FrameNotFound, _super); - function FrameNotFound(frameName) { - this.frameName = frameName; + function FrameNotFound(_at_frameName) { + this.frameName = _at_frameName; } FrameNotFound.prototype.name = "Poltergeist.FrameNotFound"; @@ -124,10 +123,10 @@ Poltergeist.FrameNotFound = (function(_super) { Poltergeist.MouseEventFailed = (function(_super) { __extends(MouseEventFailed, _super); - function MouseEventFailed(eventName, selector, position) { - this.eventName = eventName; - this.selector = selector; - this.position = position; + function MouseEventFailed(_at_eventName, _at_selector, _at_position) { + this.eventName = _at_eventName; + this.selector = _at_selector; + this.position = _at_position; } MouseEventFailed.prototype.name = "Poltergeist.MouseEventFailed"; @@ -143,8 +142,8 @@ Poltergeist.MouseEventFailed = (function(_super) { Poltergeist.JavascriptError = (function(_super) { __extends(JavascriptError, _super); - function JavascriptError(errors) { - this.errors = errors; + function JavascriptError(_at_errors) { + this.errors = _at_errors; } JavascriptError.prototype.name = "Poltergeist.JavascriptError"; @@ -160,9 +159,9 @@ Poltergeist.JavascriptError = (function(_super) { Poltergeist.BrowserError = (function(_super) { __extends(BrowserError, _super); - function BrowserError(message, stack) { - this.message = message; - this.stack = stack; + function BrowserError(_at_message, _at_stack) { + this.message = _at_message; + this.stack = _at_stack; } BrowserError.prototype.name = "Poltergeist.BrowserError"; @@ -179,8 +178,7 @@ Poltergeist.StatusFailError = (function(_super) { __extends(StatusFailError, _super); function StatusFailError() { - _ref1 = StatusFailError.__super__.constructor.apply(this, arguments); - return _ref1; + return StatusFailError.__super__.constructor.apply(this, arguments); } StatusFailError.prototype.name = "Poltergeist.StatusFailError"; @@ -197,8 +195,7 @@ Poltergeist.NoSuchWindowError = (function(_super) { __extends(NoSuchWindowError, _super); function NoSuchWindowError() { - _ref2 = NoSuchWindowError.__super__.constructor.apply(this, arguments); - return _ref2; + return NoSuchWindowError.__super__.constructor.apply(this, arguments); } NoSuchWindowError.prototype.name = "Poltergeist.NoSuchWindowError"; @@ -211,13 +208,13 @@ Poltergeist.NoSuchWindowError = (function(_super) { })(Poltergeist.Error); -phantom.injectJs("" + phantom.libraryPath + "/web_page.js"); +phantom.injectJs(phantom.libraryPath + "/web_page.js"); -phantom.injectJs("" + phantom.libraryPath + "/node.js"); +phantom.injectJs(phantom.libraryPath + "/node.js"); -phantom.injectJs("" + phantom.libraryPath + "/connection.js"); +phantom.injectJs(phantom.libraryPath + "/connection.js"); -phantom.injectJs("" + phantom.libraryPath + "/browser.js"); +phantom.injectJs(phantom.libraryPath + "/browser.js"); system = require('system'); diff --git a/lib/capybara/poltergeist/client/compiled/node.js b/lib/capybara/poltergeist/client/compiled/node.js index b34715b3..88297a6d 100644 --- a/lib/capybara/poltergeist/client/compiled/node.js +++ b/lib/capybara/poltergeist/client/compiled/node.js @@ -1,14 +1,13 @@ var __slice = [].slice; Poltergeist.Node = (function() { - var name, _fn, _i, _len, _ref, - _this = this; + var name, _fn, _i, _len, _ref; Node.DELEGATES = ['allText', 'visibleText', 'getAttribute', 'value', 'set', 'setAttribute', 'isObsolete', 'removeAttribute', 'isMultiple', 'select', 'tagName', 'find', 'getAttributes', 'isVisible', 'position', 'trigger', 'parentId', 'parentIds', 'mouseEventTest', 'scrollIntoView', 'isDOMEqual', 'isDisabled', 'deleteText', 'containsSelection']; - function Node(page, id) { - this.page = page; - this.id = id; + function Node(_at_page, _at_id) { + this.page = _at_page; + this.id = _at_id; } Node.prototype.parent = function() { @@ -82,4 +81,4 @@ Poltergeist.Node = (function() { return Node; -}).call(this); +})(); diff --git a/lib/capybara/poltergeist/client/compiled/web_page.js b/lib/capybara/poltergeist/client/compiled/web_page.js index 54045d51..099e7c11 100644 --- a/lib/capybara/poltergeist/client/compiled/web_page.js +++ b/lib/capybara/poltergeist/client/compiled/web_page.js @@ -2,8 +2,7 @@ var __slice = [].slice, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; Poltergeist.WebPage = (function() { - var command, delegate, _fn, _fn1, _i, _j, _len, _len1, _ref, _ref1, - _this = this; + var command, delegate, _fn, _fn1, _i, _j, _len, _len1, _ref, _ref1; WebPage.CALLBACKS = ['onAlert', 'onConsoleMessage', 'onLoadFinished', 'onInitialized', 'onLoadStarted', 'onResourceRequested', 'onResourceReceived', 'onError', 'onNavigationRequested', 'onUrlChanged', 'onPageCreated', 'onClosing']; @@ -13,9 +12,9 @@ Poltergeist.WebPage = (function() { WebPage.EXTENSIONS = []; - function WebPage(_native) { + function WebPage(_at__native) { var callback, _i, _len, _ref; - this._native = _native; + this._native = _at__native; this._native || (this._native = require('webpage').create()); this.id = 0; this.source = null; @@ -88,8 +87,8 @@ Poltergeist.WebPage = (function() { return this.requestId = this.lastRequestId; }; - WebPage.prototype.onLoadFinishedNative = function(status) { - this.status = status; + WebPage.prototype.onLoadFinishedNative = function(_at_status) { + this.status = _at_status; this.state = 'default'; return this.source || (this.source = this._native.content); }; @@ -153,7 +152,7 @@ Poltergeist.WebPage = (function() { if (this["native"]().evaluate(function() { return typeof __poltergeist; }) === "undefined") { - this["native"]().injectJs("" + phantom.libraryPath + "/agent.js"); + this["native"]().injectJs(phantom.libraryPath + "/agent.js"); _ref2 = WebPage.EXTENSIONS; _results = []; for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { @@ -195,13 +194,14 @@ Poltergeist.WebPage = (function() { }; WebPage.prototype.waitState = function(state, callback) { - var _this = this; if (this.state === state) { return callback.call(); } else { - return setTimeout((function() { - return _this.waitState(state, callback); - }), 100); + return setTimeout(((function(_this) { + return function() { + return _this.waitState(state, callback); + }; + })(this)), 100); } }; @@ -471,4 +471,4 @@ Poltergeist.WebPage = (function() { return WebPage; -}).call(this); +})(); diff --git a/spec/integration/session_spec.rb b/spec/integration/session_spec.rb index 69150e35..29aafc8f 100644 --- a/spec/integration/session_spec.rb +++ b/spec/integration/session_spec.rb @@ -121,6 +121,10 @@ it 'fires the blur event' do expect(@session.find(:css, '#changes_on_blur').text).to eq('Safari') end + + it 'fires the change event with the correct target' do + expect(@session.find(:css, '#target_on_select').text).to eq('SELECT') + end end describe 'Node#set' do diff --git a/spec/support/public/test.js b/spec/support/public/test.js index 12ee4555..356193db 100644 --- a/spec/support/public/test.js +++ b/spec/support/public/test.js @@ -35,8 +35,9 @@ $(function() { }) $('#browser') - .change(function() { + .change(function(event) { $('#changes').text($(this).val()) + $('#target_on_select').text(event.target.nodeName) }) .focus(function() { $('#changes_on_focus').text($(this).val()) diff --git a/spec/support/views/with_js.erb b/spec/support/views/with_js.erb index d37898ac..7f1730d5 100644 --- a/spec/support/views/with_js.erb +++ b/spec/support/views/with_js.erb @@ -45,6 +45,7 @@

+

O hai