This repository has been archived by the owner. It is now read-only.

element.webkitMatchesSelector in phantomjs does not report ":focus" accurately #10427

Open
ryangreenberg opened this Issue Mar 14, 2012 · 63 comments

Comments

Projects
None yet
@ryangreenberg
Copy link

ryangreenberg commented Mar 14, 2012

ryangree...@gmail.com commented:

Which version of PhantomJS are you using? 1.4.1

What steps will reproduce the problem?

  1. Run the provided test script with the test HTML (below).

What is the expected output? What do you see instead?
I expect :focus to be true after triggering a focus event on an element. Instead it is false.

Which operating system are you using? OS X 10.7.3

Did you use binary PhantomJS or did you compile it from source? Compiled.

Here is the output of my test script in Chrome, Safari, and PhantomJS:

Chrome

navigator.userAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.54 Safari/535.19
$('#some-input').is(':focus'): true
$input[0].webkitMatchesSelector(':focus'): true
$input[0] == document.activeElement: true

Safari

navigator.userAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.54.16 (KHTML, like Gecko) Version/5.1.4 Safari/534.54.16
$('#some-input').is(':focus'): true
$input[0].webkitMatchesSelector(':focus'): true
$input[0] == document.activeElement: true

PhantomJS 1.4.1

navigator.userAgent: Mozilla/5.0 (Macintosh; PPC Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.4.1 Safari/534.34
$('#some-input').is(':focus'): false
$input[0].webkitMatchesSelector(':focus'): false
$input[0] == document.activeElement: true

Test HTML
<!DOCTYPE html>
<html>
<head>
<title>:focus check</title>
<script src="http://code.jquery.com/jquery.js&quot;&gt;&lt;/script>
<script>
$(function(){
console.log("navigator.userAgent: " + navigator.userAgent);

// Simple case
$input = $('#some-input');
$input.focus();
console.log(&quot;$('#some-input').is(':focus'): &quot; + $('#some-input').is(':focus'));

// Similar case
$input.focus();
console.log(&quot;$input[0].webkitMatchesSelector(':focus'): &quot; + $input[0].webkitMatchesSelector(':focus'));

// When a native matchesSelector isn't available, jQuery uses:
// 
//  focus: function( elem ) {
//     return elem === elem.ownerDocument.activeElement;
//  }
// 
// The input == document.activeElement, which suggests that the bug is in webkitMatchesSelector
console.log(&quot;$input[0] == document.activeElement: &quot; + ($input[0] == document.activeElement));

});
</script>
</head>
<body>
<form>
<input id="some-input">
</form>
</body>
</html>

Test script:
var page = require('webpage').create();
page.onConsoleMessage = function(msg) { console.log(msg); };

page.open('file:///' + phantom.libraryPath + '/focus_test.html', function (status) {
if (status !== 'success') {
console.log('Could not open URL');
}
phantom.exit();
});

Disclaimer:
This issue was migrated on 2013-03-15 from the project's former issue tracker on Google Code, Issue #427.
🌟   16 people had starred this issue at the time of migration.

@spmason

This comment has been minimized.

Copy link

spmason commented Apr 3, 2012

ste...@brandwatch.com commented:

I can confirm this is an issue in 1.4.1, also in 1.5.0 as well

I'm working around by using "elem === elem.ownerDocument.activeElement" instead, but it's not pretty.

Seems to work fine in Chrome 17 and Safari 5.1.5 - I'm not sure if these are using more recent versions of webkit though

@robotarmy

This comment has been minimized.

Copy link

robotarmy commented Apr 6, 2012

cur...@ram9.cc commented:

Please fix :D

@philfreo

This comment has been minimized.

Copy link

philfreo commented Mar 9, 2013

philfreo@gmail.com commented:

Please fix!

@philfreo

This comment has been minimized.

Copy link

philfreo commented Mar 9, 2013

philfreo@gmail.com commented:

// Patch $el.is(':focus') until PhantomJS supports it properly.
// https://code.google.com/p/phantomjs/issues/detail?id=427
var _jQuery_is = jQuery.fn.is;
jQuery.fn.is = function(s) {
if (s === ':focus') {
return this.get(0) === document.activeElement;
}
return _jQuery_is.apply(this, arguments);
};

This workaround may help some (put this in your test runner code)

@realyze

This comment has been minimized.

Copy link

realyze commented May 3, 2013

+1

4 similar comments
@caiges

This comment has been minimized.

Copy link

caiges commented May 10, 2013

+1

@tjvantoll

This comment has been minimized.

Copy link

tjvantoll commented May 10, 2013

+1

@TheCloudlessSky

This comment has been minimized.

Copy link

TheCloudlessSky commented May 13, 2013

+1

@camsong

This comment has been minimized.

Copy link

camsong commented May 13, 2013

👍

@JamesMGreene

This comment has been minimized.

Copy link
Collaborator

JamesMGreene commented May 14, 2013

Since this bug specifically mentions jQuery, I'll note that jQuery added a workaround for this WebKit bug in jQuery core 1.8.2: http://bugs.jquery.com/ticket/12492

@Mr0grog

This comment has been minimized.

Copy link

Mr0grog commented Jul 10, 2013

Though this has been fixed in jQuery, I'm using Poltergeist (a PhantomJS driver for Capybara, which is a browser testing driver for Ruby) for a lot of integration testing. I'd like to be able to test whether an element has focus and it seems like the natural way to do that would be to use the :focus selector. It would be great if this was fixed.

I'd also guess the cause of this is the same as #11432.

@ccidral

This comment has been minimized.

Copy link

ccidral commented Aug 21, 2013

+1

3 similar comments
@Flamefork

This comment has been minimized.

Copy link

Flamefork commented Aug 28, 2013

+1

@ralfthewise

This comment has been minimized.

Copy link

ralfthewise commented Sep 12, 2013

+1

@roelrz

This comment has been minimized.

Copy link

roelrz commented Oct 2, 2013

+1

@vellotis

This comment has been minimized.

Copy link

vellotis commented Oct 8, 2013

+1
If I want to get currently focused element, I have to mock implementation framework which is not a part of BDD principles. The same downside exists in HTMLUnit also.

@vincentdieltiens

This comment has been minimized.

Copy link

vincentdieltiens commented Oct 11, 2013

+1

1 similar comment
@SebiTimeWaster

This comment has been minimized.

Copy link

SebiTimeWaster commented Oct 31, 2013

+1

@lijunle

This comment has been minimized.

Copy link

lijunle commented Jan 3, 2014

Please fix it!

@coledot

This comment has been minimized.

Copy link

coledot commented Jan 13, 2014

+1

@silvinobarreiros

This comment has been minimized.

Copy link

silvinobarreiros commented Jan 29, 2014

+1

1 similar comment
@joanna1010

This comment has been minimized.

Copy link

joanna1010 commented Jan 31, 2014

+1

@rgl

This comment has been minimized.

Copy link

rgl commented Apr 14, 2014

Any progress on fixing this bug?

@barnomics

This comment has been minimized.

Copy link

barnomics commented May 7, 2014

+1

Would be nice to test accessibly features but no can do without a :focus element or document.activeElement

@lorenooliveira

This comment has been minimized.

Copy link

lorenooliveira commented Sep 7, 2014

+1

1 similar comment
@grossadamm

This comment has been minimized.

Copy link

grossadamm commented Oct 10, 2014

+1

@fliot

This comment has been minimized.

Copy link

fliot commented Dec 17, 2015

I agree with @renehamburger & @myplacedk. I don't see any workaround for testing styling.

@sgress454

This comment has been minimized.

Copy link

sgress454 commented Dec 17, 2015

I think the problem here is that in Webkit, the :focus selector only matches elements if the document itself has focus--that is, if document.hasFocus() returns true. You can test this yourself in Chrome:

setTimeout(
    function(){
        var e = document.createEvent('Event');
        e.initEvent("focus", true, true);
        document.getElementById('id-of-some-focusable-element').dispatchEvent(e);
        console.log(document.querySelectorAll(':focus'));
    },
    2000
);

If you run this from the Chrome dev tools console, you'll see an empty array returned two seconds later. However, if you run it and then click inside the document within two seconds, the log will spit out the expected element.

While researching this, I found a jQuery patch from a few years ago made when someone using Selenium ran into the same issue; unfortunately that patch doesn't work for the current jQuery version but it pointed me in this direction.

So it would seem that the only fix would be to patch the Webkit that PhantomJS is using to not expect the document to be focused when querying :focus, or to allow some way to "focus" the document in PhantomJS so that document.hasFocus() returns true.

@Jedidiah

This comment has been minimized.

Copy link

Jedidiah commented Jan 18, 2016

+1

Good investigation @sgress454 😄
It would be great to see this finally fixed!

@vickiccole

This comment has been minimized.

Copy link

vickiccole commented Jan 18, 2016

+1

3 similar comments
@albinekb

This comment has been minimized.

Copy link

albinekb commented Jan 26, 2016

+1

@tiffanywei

This comment has been minimized.

Copy link

tiffanywei commented Feb 8, 2016

+1

@emilioplatzer

This comment has been minimized.

Copy link

emilioplatzer commented Mar 9, 2016

+1

@garex

This comment has been minimized.

Copy link

garex commented Apr 25, 2016

Another possible patch (rude)

// it's for casperjs, but I think you will catch the idea
this.evaluate(function() { document.hasFocus = function() { return true } })
@workmanw

This comment has been minimized.

Copy link

workmanw commented Apr 30, 2016

+1

@sgress454

This comment has been minimized.

Copy link

sgress454 commented May 3, 2016

@garex I tried something like that at one point without much luck -- I don't think the :focus selector just relies on document.hasFocus() returning true, but rather that whatever underlying conditions cause hasFocus() to return true must be met in order for the :focus selector to work.

@Jevin23

This comment has been minimized.

Copy link

Jevin23 commented May 7, 2016

+1

@kryptan

This comment has been minimized.

Copy link

kryptan commented Jan 3, 2017

I experimented with this a bit using a 2.1 branch (master crashes for me).

First I tried to fix it in PhantomJS itself, but calling QWebFrame::setFocus() on m_currentFrame or any other frame in webpage.cpp does not have any effect.

Next I looked into WebKit sources, the :focus pseudo class is checked here. SelectorChecker::matchesFocusPseudoClass function calls SelectorChecker::isFrameFocused which in turn calls FrameSelection::isFocusedAndActive. Changing FrameSelection::isFocusedAndActive to always return true fixes this issue although it feels like a hack, I don't know what a proper solution here would be.

P.S. I suggest owner of this repo to remove all junk +1 comments and block their authors.

@Vitallium

This comment has been minimized.

Copy link
Collaborator

Vitallium commented Jan 11, 2017

Can someone check it with recently released 2.5 beta version? Thanks!

@cleforwen

This comment has been minimized.

Copy link

cleforwen commented Feb 17, 2017

+1

@jameswomack

This comment has been minimized.

Copy link

jameswomack commented Mar 3, 2017

@Vitallium Where can I download a version of 2.5 that will work with Selenium/Nightwatch.js? What I downloaded from https://bitbucket.org/ariya/phantomjs/downloads/ wasn't recognized by Selenium.

@DustinAshley

This comment has been minimized.

Copy link

DustinAshley commented Jun 16, 2017

+1

@Vishwaas

This comment has been minimized.

Copy link

Vishwaas commented Sep 25, 2017

+1

markdicksonjr added a commit to markdicksonjr/ember-paper that referenced this issue Sep 29, 2017

@srescio

This comment has been minimized.

Copy link

srescio commented Oct 29, 2017

+1

@ghost ghost removed 1.x labels Jan 10, 2018

pauln added a commit to pauln/ember-paper that referenced this issue May 28, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.