Find the focused element in end-to-end test for Stencil component - jestjs

How can I check which element has focus in a Stencil test? I can't use document.activeElement like I would normally do, as it always returns undefined...

Stencil components use Shadow DOM by default and that means that if some element in the Shadow DOM is in focus you can't get it through the normal document.activeElement property. On the other hand, the Shadow DOM host element includes an activeElement property as well (the host element is handled as a different document). You can use the host's activeElement property in your tests, which should hold the focused element inside the Shadow DOM. You can read about that property in MDN.
In some of my projects, when an element is getting focus I add a class to it which helps me to query it later and to add focus styles. This is another way to find elements which are in focus (query for the class).

I came across the same issue and agree with Gil Fink that it seems to be missing from the Stencil Puppeteer abstraction.
I've worked round it by checking that the id of the active element of my components shadow root is the same as the id of the element I expect to have focus. I retrieved the id of the active element using Puppetteers page.$eval(...), e.g.:
const activeElementId = await page.$eval('my-component', (el) => el.shadowRoot.activeElement.id);
const elementThatShouldBeActive = await page.find('my-component >>> #some-id');
expect(activeElementId).toEqual(elementThatShouldBeActive.id);
That works for my context, hopefully it's helpful for you too.

I ended up doing:
const activeElId = await page.evaluate(() => document.activeElement!.id);

Related

Using Semantic UI React with React Virtualized

I have been having difficulties getting React Virtualized working correctly with Semantic UI.
As per my example below, I am able to get correct styling applied to the items in a list by setting the className prop to 'item'.
However the issue I have been having is with props passed from Semantic's HOC components such as List to a List.Item. Props such as divided and selection. Has anyone else run into this issue and is there a solution?
https://codesandbox.io/s/31l6ol4kkm
You won't be able to pass the List properties from Semantic UI to your List.Item inside of your React-Virtualized list because the properties are not accepted by react-virtualized Lists. The nesting you are doing is preventing you from achieving the outcome you want. However, you can create a custom style sheet to pass to your List.Item. One example that worked for me would be to use the following code:
const dividedStyle = {
borderBottom:"1px solid #ccc",
margin:"5px",
padding:"5px"
}
const rowRenderer = ({ key, index, style }) => (
<List.Item key={key} style={dividedStyle}>
<List.Content>
<List.Header>
{items[index]}
</List.Header>
Is a person
<List.Description>
Description
</List.Description>
</List.Content>
</List.Item>
)
There may be other ways to do this, but this works well. You could also wrap your VList and List.Item rendering in a separate component, to which you would pass the "Divided" property. You could style it inside that component which would then encapsulate the code above, and give you a reusable VList & List.Item combo.

IE11 full screen on element

IE 11 has been out just one day as of this posting.
I cannot get an element to go full screen (div or document)
http://msdn.microsoft.com/en-us/library/ie/dn265028
msRequestFullscreen will error 'object does not support this...)
However, the above msdn example will work on passing a target - makeFullScreen(evt.target).
Can I get an div to go fullscreen as in following jquery code?:
var xxx = $('#container');
xxx.msRequestFullscreen();
Or better still: click a button then have a div or the entire document to go fullscreen?
As it stands now, when a click a button, it's the button that goes full screen.
I think this is actually a small misconception of JQuery. JQuery-ing an ID doesn't actually return the element found - it returns a "JQuery object" which allows many actions on that element (or, on a series of elements if you used a class selector)
I don't have IE11 available so I can't test for you, but try this. The [0] should retrieve the element itself.
var xxx = $('#container')[0]; xxx.msRequestFullscreen();
Your code:
var xxx = $('#container');
xxx.msRequestFullscreen();
This is wrong, because you're trying to call a DOM method on a jQuery object.
jQuery calls like $('#container') return jQuery objects. You can do lots of things with these objects, but one thing you can't do is call standard DOM methods. For that, you need an actual DOM object.
jQuery objects contain an array of matching DOM objects, which you can access via [0] for the first one, and [1], etc if there was more than one matching element. So you can do your call by changing your second line as follows:
xxx[0].msRequestFullscreen();
This will call the msRequestFullscreen() on the DOM element rather than the jQuery element, and that should work for you.
In this case, you don't even need jQuery at all, since you're not using any of the jQuery functionality. You could simply use document.getElementById('container') to get the DOM object in the first place rather than the jQuery method. Then you don't need the [0] syntax on the second line because you've already got the DOM object.
Finally, you might want to be careful of course, because this is an IE-specific method; the ms at the front of the name tells you that, which means that your code won't work in other browsers, even if they support the same feature. You need to do it in a cross-browser way. There are some tips on how to do this here: How to make the window full screen with Javascript (stretching all over the screen)

Matching elements using XPath on Coded UI Tests

This is a noobish question but I am getting started with MS Coded UI Tests. And I was wondering if there's a way to find page elements using XPath, instead of the default matching mechanism? What I want to do, is match a parent elements and programmatically navigate down the DOM tree to get the elements I want to work with. This can be easily done with Selenium, but I am not sure how to do it with Coded UI Tests.
Thanks
You should be able to manage navigating an xpath using the UITestControlCollection. Use CodedUI's recorder to get to the top level control, then use GetChildren to navigate your way. Keep in mind that the xpath changes because all the object types are similar, CodedUI's API doesn't distinguish.
Example:
HtmlDocument doc = this.UIYourWindowName.UIYourDocumentName; // mapped control
doc.Find();
UITestControl toline = new UITestControl(doc);
toline.SearchProperties["Id"] = "to_d"; // use the id of the top most control
UITestControlCollection toline1 = toline.GetChildren(); // get the child objects
toline1 = toline1[0].GetChildren(); // xpath: \\ctrl[#id='to_d']\item[0]
toline1 = toline1[0].GetChildren(); // ctrl[]\item[0]\item[0]
// and so on...

Backbone - binding to a collection's reset event loses reference to `this`

I don't think this is an uncommon problem, but I haven't been able to make any of the solutions I've found work. Here's my [simplified] view:
class MyView extends Backbone.View
el: '#mydiv'
initialize: ->
#collection.bind 'reset', #render, #
render: ->
$(#el).html('my content')
When reset is triggered, render's this has been clobbered, and #el is undefined. My understanding was that the 3rd parameter on bind was supposed to take care of this, but that doesn't appear to be happening. I am using Backbone 0.5.3.
I also tried using the "fat arrow" on render, but that didn't work either:
render: =>
$(#el).html('my content')
Update
As Trevor Burnham pointed out below, it wasn't a scoping issue, it was that my el property wasn't available at page load (it get's created later). I'm still looking for a better way to deal with that (using the id property on the view).
I don't think the problem is that render is called in the wrong context, but rather that the view's el property is never a DOM element. Does something with the ID mydiv exist at the time that you call new MyView? If not, that's the problem.
Internally, when el is a string, Backbone makes the call
this.el = $(this.el).get(0);
from the view's constructor. If nothing matching that selector string exists, #el will be undefined, which is what you're seeing.
Use the double arrow => instead of single-arrow -> when defining your render method, and CoffeeScript makes sure that the this pointer points to the class instance. Also, you may want to try to set the id member to the id reference instead of the el member, as the documentation for backbone (http://documentcloud.github.com/backbone/#View-el) indicates that el gets created (by backbone itself) based on whatever id, tagName and className is set to.

How to register keypress event listener on non-root element?

I've been developing a text editor based on SVG, and I'm now trying to
make it so that multiple instances can be instantiated in a single SVG
document. The way I've been trying to achieve this is to wrap the DOM
representation of each text editor instance with a single parent
element (either or ), and then to attach a keypress event
listener to that parent element. The problem I'm running into, though,
is it seems that keypress events are only received by the document
root. Furthermore, for all browser SVG implementations I've tried, the
target, originalTarget, and explicitOriginalTarget event properties,
when they exist, are also set to the document root, so it doesn't
event seem like it's possible to hack a solution by attaching a single
event listener on the document root, and then manually dispatching
events by reading the event's originalTarget property.
So far, I've tested Firefox 3.6, Chromium 9, Opera 11, and Batik
Squiggle 1.7, with the following test case:
http://stuff.echo-flow.com/svg-developers/testEventListener.svg
Only Batik works as expected, with the rect element receiving the
keypress event. In Firefox, target, originalTarget, and
explicitOriginalTarget are all equal to the root element. In Chromium
and Opera, target is set to the root element, and originalTarget and
explicitOriginalTarget are undefined.
Basically, what I'm trying to do is relate a keypress event back to
the element that originally fired it. I think I could probably get
this to work if I used an HTML context and embedded iframes; or, if I
used iframes inside of a foreignObject. But I'm wondering if there's a
cleaner workaround that does not require the use of iframes.
Furthermore, I guess as a worst-case scenario, I could do my own hit
testing by inspecting the clientX/clientY properties of the keypress
event, and comparing that to the bboxes of all text editor group
elements. But once again, this seems very hacky, and I wonder if
there's a better approach.
First, it's better to specify the SVG version and baseProfile you're using in your SVG document.
So far, SVG only support (in the specifications) those events, no key press event. Browsers are a bit ahead the specs, so, lets just assume it's supported.
So, you're using the DOM 3 Event keypress since it doesn't exist in DOM 2 Events.
Looking at keypress event context infos :
Event.target: focused element processing the key event, root element if no suitable input element focused
Focus is not mouse position. In the SVG 1.1 specs, no "focusable" attribute exists, but you can find it in the SVG 2.0 draft.
So Batik use a wrong "keypress event" implementation. You could use the "mouseover event" to know what element you're hovering, or try if the "focusable" attribute is already working on some browsers.
Also, originalTarget and explicitOriginalTarget are Mozilla specific, non standard, that explain your results with other browsers.

Resources