When program fails to find a component in a test case, a failure trace is shown. It shows attributes of components in the hierarchy. For example:
[name=null, text='Close', enabled=true, visible=true, showing=false]
I wonder what value of visible and showing tell us about the component.
This are properties from the java.awt.Component class.
The JavaDoc for these properties (https://docs.oracle.com/javase/8/docs/api/java/awt/Component.html) has the following information:
visible:
Determines whether this component should be visible when its parent is visible.
showing:
Determines whether this component is showing on screen. This means that the component must be visible, and it must be in a container that is visible and showing.
Related
I want to validate a form that consists of a parent component and a child component. The user can dynamically add another child component on click of a button. I am unable to check the invalid state of the the child components and therefore also the invalid state of the parent component.
Previously, this was not an issue since Vuelidate had $each function.
I'm runing a nightwatch test on Loadero and its failing.
I'm trying to test if an element is available, and if it is, to click on it.
I believe that below, I'm saying only try click the button if it exists.
client.elements("css selector", "div[aria-describedby='dialogWindowTooSmall button.ui-button']", function (result) {
if (result.value.length) {
client.click('div[aria-describedby="dialogWindowTooSmall"] button.ui-button)');
}
})
But I'm getting an error.
The first line seems to execute fine. I get two ELEMENT ids back
[ { ELEMENT: '0.7754195696252344-2' },
{ ELEMENT: '0.7754195696252344-3' } ] }
but the click function fails:
Error while running .clickElement() protocol action: An element command could not be completed because the element is not visible on the page. – element not interactable
Surely if the element is found, its clickable?
(i have tried to paste more of the log here but it loses all formatting and is impossible to read)
Thanks!
No, if the element is present on the page, it does not mean that the element is also interactable (or clickable). For an element to be interactable, it also needs to be "visible" on the page and not just "present" on the page. It can happen if the element is hidden or outside the viewport of the page.
When you try to perform a 'click' operation on an element, Selenium first tries to locate the element and if the element is not visible in the view, it tries to scroll to the element to bring it into the view and then click on the center-point of the element.
Now, if Selenium is unable to bring the element into the view, it throws element not interactable error. If it is able to bring the element into the view but the center-point of the element is covered by some other element, it throws element click intercepted error. Otherwise, it successfully performs the 'click' operation on the element.
For reference: https://w3c.github.io/webdriver/#element-click
I have a parent component where the view model contains a property prop1.
In its view, a custom element has a view-model.ref="prop1".
export class Parent {
public prop1;
}
<template>
<custom-element view-model.ref="prop1"></custom-element>
</template>
This works like a charm and I get a reference to the view model of my custom element in my parent.
Now, I add a child router to parent with a child component. In child's view model, I add a property prop1. and in its view, a custom element has a view-model.ref="prop1". So exactly like I did in parent...
As soon as I navigate to parent/child, the parent's container prop1 stops referencing the custom element of parent and starts referencing the one from child.
If I name the properties differently, there is no problem.
Any idea why this happens? And how could I avoid this behavior without worrying about the naming of the properties?
EDIT
I chanced upon some more information! If the properties are initialized in the view model, I seem to be able to retain the references in the view models. Note that I'm using Typescript so I think the compiled code for an unassigned class property doesn't mention the property at all until it is assigned.
I still don't really understand where the problem comes from exactly...
And I remain with the same problem if I use a view-model.ref directly in the template without mapping it to an explicit property from the view model like this:
<template>
<custom-element view-model.ref="custom"></custom-element>
<custom-element2 opened.call="custom.opened()"></custom-element2>
</template>
when you create a property in a class and don't assign anything to it, babel/typescript will remove that property as if it was not even declared.. because it's really not doing anything.
typescript is interested in your definitions in compile time only.
now that your property in the child is emitted, you have a binding in the child to an undeclared property.
in that case, aurelia creates a property for you and bind to it..
but in your case, aurelia finds this property in the parent scope (just like regular JS scoping rules), and therefor do not create a "new property" in the child scope but rather binds to the parent property.
this is why when you initialize the property in the child (even with undefined) it "works". because you have 2 properties in 2 scopes.
and when you change the name, aurelia will create a new property for you..
and here come another rule - wen aurelia create a property for you - it creates it in the lowest scope available.. in your case - the child scope. and everything works again.
you can notice this behavior a lot with repeate.for, because the repeater creates an invisible scope for each repeate loop..
if you bind anything in the repeate to a property that dont exists, you will have that property in each child, and not once in the parent.
I'm trying to understand host and target (and element) in the following context taken from the Polymer Path and Polymer Data Flow documentation.
Consider the following diagram:
Now consider the following statement (from the same documentation):
"When two elements in the local DOM are bound to the same property data appears to flow from one element to the other, but this flow is mediated by the host."
So far, so good. Then it goes on to say:
"A change made by one element propagates up to the host, then the host propagates the change down to the second element."
The first part: "A change made by one element propagates up to the host..." Does this mean that a change to the first element propagates to its own host first? And does "element" actually mean the element's data properties?
The second part "then the host propagates the change down to the second element." Are we propagating down to the second element's data properties? It's extra confusing here as there is only one element or data object that is shared between the two ehhh elements??
I'm thinking that the change made in the first element's data property goes to its own host first and then the first host propagates the change back down to the second element's data element (which so happens to be the first element's data object as well).
<parent-el>
<user-profile primary-address="{{addr}}"></user-profile>
<address-card address="{{addr}}"></address-card>
</parent-el>
If either element changes addr (the child elements can use whatever name they want), the change will be propagated to the parent and then to the other element.
If either binding used [[addr]] instead, changes would only propagate from parent to child.
Note that both child elements should have notify: true set on the relevant property (primaryAddress or address) so that the parent is notified of changes and the two-way binding is fully setup.
Also note that this listens for the object to change as a whole only. To listen for changes to sub-properties e.g. addr.street the parent should add an observer. For more info on that see complex observers.
I'd like to conditionally hide a tab in a TabNavigator. It seems that setting visible doesn't work properly (presumably because this is how the TabNavigator hides the tabs that aren't currently selected).
What's the right way to do this?
You can do this by making use of TabNavigator's getTabAt() method which returns the Button that makes up the visual tab. You can then set that Button's visible property. It's a little tricky to get this setup with a bindings, but it's doable.
You could also consider just disabling the tab instead, which you can do by setting enabled on the corresponding TabNavigator child (for which visible didn't work).
What do you mean by hide? If you actually mean remove, then just take your array that's bound to the data in the TabNavigator, and remove the applicable element from it.
If you want to just have them removed temporarily, create a component of your own that encapsulates the TabNavigator and has an array of removed tabs and an array of actual tabs. Then handle this as you see fit.
You might want to check out the flexlib project. They have a component called SuperTabNavigator that adds a lot of functionality to the base Flex TabNavigator, including hiding tabs (I think).
If you do have to create your own component, though, it's a bit more tricky. The thing to know is that "tabs" are actually specially styled buttons, contained within a TabBar component (the TabBar is then contained within the TabNavigator). What you'll have to do then, is subclass TabNavigator and have some property on your views (i.e. the canvases, etc. that are added to the TabNavigator) that is bound to the visible and includeInLayout properties of the TabBar buttons.
In essence, what you'll have is something like:
BindingUtils.bindProperty( tabButton, "visible", view, "someProperty" );
BindingUtils.bindProperty( tabButton, "includeInLayout", view, "someProperty" );
I don't know about TabNavigator, but in other containers, you can set the includeInLayout property to false and it will be ignored. You probably still need to combine it with visible.
var secondTab = tabNavigator.removeChildAt(0);