Making Mozmill Hug Templetized Trees

4 views
Skip to first unread message

Clint Talbert

unread,
Feb 5, 2009, 1:27:23 PM2/5/09
to mozmi...@googlegroups.com
= The Simple Explanation =
Templetized Trees are an issue because they don't copy their content
elements into the DOM. That's pretty disastrous for a DOM based
automation tool. This means mozmill can't inspect tree children
elements and can't automate interaction with them through the UI
interfaces. However, if the tree in question implements some of the
standard tree object libraries, then we may have a solution for this.
If you're interested in the gory details, read on.

= The Details =

This means that your standard, run of the mill XUL trees we can
automate. It means that if you have subclassed a tree view
implementation from nsITreeView AND you also have attached a
nsITreeContentView to your created tree, we can automate you. However,
if you did not add those to your tree implementation then we can't
automate you. Specifically, we need the getItemAtIndex method which
resides on the nsITreeContentView to get to you. It tried QI'ing the
nsITreeView to an nsITreeContentView, but of course that didn't work (I
was out of other ideas, I must admit).

So, the net of this is that in order to be testable by mozmill, we need
your tree implementation to have both an nsITreeContentView object and a
nsITreeView object implemented for it. Unfortunately not all
custom-crafted trees implement both objects (places, I'm looking at you
-- Dietrich, please tell me I'm wrong here). But for standard XUL trees
(and trees that have these interfaces) we should be able to access the
DOMElement interfaces of the children elements via this algorthim:

<standard recursive search for elements>
if (element.tagName == "tree") {
for (i=0 i < element.view.rowCount; ++i) {
addInspectorListeners(element.contentView.getItemAtIndex(i));
}

The "addInspectorListener" is pseudocode for the listeners we attach to
elements in order to make the inspector function work so that we can
find these elements. Likely this means we'll have to either adapt the
"Lookup" elementslib search or create a new elementslib search type for
trees that we use once we have a tree.

We should also try to determine before doing this whether or not the
tree in question implements the "view" and "viewContent" objects,
because if it doesn't then our only option is to instruct the tester to
use the backend XPCOM interfaces to that content to get the information
there. Those nodes are not accessible outside of their trees (at least
not as far as I can tell).

= Note this will make NO sense unless you've looked at the Songbird DOM =
Let's take the songbird example (standard XUL trees) and use the mozmill
shell to figure out the elements:
// songbird window
s = windows[1];
// grab the anon node right above the service pane XUL tree element:
sbsvc = s.document.getElementById("sb_servicepane_treepane");
// get it's anon elements
anons = s.document.getAnonymousNodes(sbsvc);
// the first node is the XUL tree
tree = anons[0];
// use the view to get the number of rows of tree children that exist
numRows = tree.view.rowCount;
// use contentView to grab the DOMElement you want from that specific row.
e0 = tree.contentView.getItemAtIndex(0);

Mikeal, Adam, let me know what you think of this.

Cheers,
Clint

PS this is now bug 477079, but let's discuss the issue here first to
figure out a solution that will work for everyone. This list has wider
distribution than the people that watch our bz component.

Mikeal Rogers

unread,
Feb 5, 2009, 2:58:18 PM2/5/09
to mozmi...@googlegroups.com

On Feb 5, 2009, at February 5, 200910:27 AM, Clint Talbert wrote:
> <standard recursive search for elements>
> if (element.tagName == "tree") {
> for (i=0 i < element.view.rowCount; ++i) {
> addInspectorListeners(element.contentView.getItemAtIndex(i));
> }

So, I assume that getItemAtIndex returns a XULElement.

> The "addInspectorListener" is pseudocode for the listeners we attach
> to
> elements in order to make the inspector function work so that we can
> find these elements. Likely this means we'll have to either adapt the
> "Lookup" elementslib search or create a new elementslib search type
> for
> trees that we use once we have a tree.

We'll see, it depends on whether or not we can find a way to get all
tree elements for a given document. If we can then we should create a
new object, if we have to leverage all the other Lookup stuff to work
our way down the tree then we'll want to add some syntax to Lookup.
Adding to Lookup is more difficult so if at all possible I'd like to
avoid it.

> We should also try to determine before doing this whether or not the
> tree in question implements the "view" and "viewContent" objects,
> because if it doesn't then our only option is to instruct the tester
> to
> use the backend XPCOM interfaces to that content to get the
> information
> there. Those nodes are not accessible outside of their trees (at
> least
> not as far as I can tell).

Can we just check if those attributes are undefined? Or do they exist
even when they don't work?

> = Note this will make NO sense unless you've looked at the Songbird
> DOM =
> Let's take the songbird example (standard XUL trees) and use the
> mozmill
> shell to figure out the elements:
> // songbird window
> s = windows[1];
> // grab the anon node right above the service pane XUL tree element:
> sbsvc = s.document.getElementById("sb_servicepane_treepane");
> // get it's anon elements
> anons = s.document.getAnonymousNodes(sbsvc);
> // the first node is the XUL tree
> tree = anons[0];
> // use the view to get the number of rows of tree children that exist
> numRows = tree.view.rowCount;
> // use contentView to grab the DOMElement you want from that
> specific row.
> e0 = tree.contentView.getItemAtIndex(0);

This example concerns me.

Currently we add a listener to every window and all the elements, even
anonymous ones, respond to that listener.

It's easy to pull out all the tree elements if they are not anonymous
( document.getElementsByTagName('tree') ), but I can't see a way to
get all the tree elements behind anonymous nodes without parsing
through every element in the dom and iterating over all of it's
anonymous nodes recursively.

There is no way to get an anonymous node by tag name, and from what I
can tell there is no common attribute either. Iterating over every
element, then iterating over all it's anonymous nodes checking for tag
name, all recursively, sounds INCREDIBLY expensive.

Adam can comment on this more accurately.


> Mikeal, Adam, let me know what you think of this.

As long as there are real elements that we can click on we can figure
out a way to create expressions that can get at them, I'm not
concerned about the viability of that, but it's a given that writing
such expressions by hand will be close to impossible so my main
concern is how we get listeners on all of these. Another issue we'll
have is that new elements won't have listeners on them and we'll need
to add an observer that goes though all the addListener stuff again
every time a tree rebuild happens.

-Mikeal

Clint Talbert

unread,
Feb 5, 2009, 4:10:46 PM2/5/09
to mozmi...@googlegroups.com
On 2/5/09 11:58 AM, Mikeal Rogers wrote:
> On Feb 5, 2009, at February 5, 200910:27 AM, Clint Talbert wrote:
>
>> <standard recursive search for elements>
>> if (element.tagName == "tree") {
>> for (i=0 i< element.view.rowCount; ++i) {
>> addInspectorListeners(element.contentView.getItemAtIndex(i));
>> }
>>
>
> So, I assume that getItemAtIndex returns a XULElement.
>
>
yep, it does

>> The "addInspectorListener" is pseudocode for the listeners we attach
>> to
>> elements in order to make the inspector function work so that we can
>> find these elements. Likely this means we'll have to either adapt the
>> "Lookup" elementslib search or create a new elementslib search type
>> for
>> trees that we use once we have a tree.
>>
>
> We'll see, it depends on whether or not we can find a way to get all
> tree elements for a given document. If we can then we should create a
> new object, if we have to leverage all the other Lookup stuff to work
> our way down the tree then we'll want to add some syntax to Lookup.
> Adding to Lookup is more difficult so if at all possible I'd like to
> avoid it.
>
>
>> We should also try to determine before doing this whether or not the
>> tree in question implements the "view" and "viewContent" objects,
>> because if it doesn't then our only option is to instruct the tester
>> to
>> use the backend XPCOM interfaces to that content to get the
>> information
>> there. Those nodes are not accessible outside of their trees (at
>> least
>> not as far as I can tell).
>>
>
> Can we just check if those attributes are undefined? Or do they exist
> even when they don't work?
>
>
they will either be undefined or null: either way: if(tree.viewContent)
should do the right thing.
Well, this is the specific songbird case for their left hand menu. FWIW
it's the first time I've ever seen a tree generated as an anonymous XBL
node.

>
>> Mikeal, Adam, let me know what you think of this.
>>
>
> As long as there are real elements that we can click on we can figure
> out a way to create expressions that can get at them, I'm not
> concerned about the viability of that, but it's a given that writing
> such expressions by hand will be close to impossible so my main
> concern is how we get listeners on all of these. Another issue we'll
> have is that new elements won't have listeners on them and we'll need
> to add an observer that goes though all the addListener stuff again
> every time a tree rebuild happens.
>
>
>
Maybe I don't get it, but I think we already have this problem. If you
have a page and you do something to element A that causes there to be an
element B, then you'd have to reinpect (and add a listener) to element B
in order to find out how to access it. Then in your test, you'd
activate element A and do a waitForElement with the proper expression
for element B. New tree elements wouldn't be any different as long as
they are added into the same area of the tree on test run. Now if your
run adds a bunch of stuff to the tree and resorts it three times, you're
going to have a problem, but I'd argue you have that problem if you do
that with some element that's not in a tree too, like a <select> drop
down list.

- C

Mikeal Rogers

unread,
Feb 5, 2009, 4:16:05 PM2/5/09
to mozmi...@googlegroups.com
>>
>>
> Well, this is the specific songbird case for their left hand menu.
> FWIW
> it's the first time I've ever seen a tree generated as an anonymous
> XBL
> node.

I don't think this will be the last time we see this considering how
many other UIs are created by XBL.

>
>>
>>> Mikeal, Adam, let me know what you think of this.
>>>
>>
>> As long as there are real elements that we can click on we can figure
>> out a way to create expressions that can get at them, I'm not
>> concerned about the viability of that, but it's a given that writing
>> such expressions by hand will be close to impossible so my main
>> concern is how we get listeners on all of these. Another issue we'll
>> have is that new elements won't have listeners on them and we'll need
>> to add an observer that goes though all the addListener stuff again
>> every time a tree rebuild happens.
>>
>>
>>
> Maybe I don't get it, but I think we already have this problem. If you
> have a page and you do something to element A that causes there to
> be an
> element B, then you'd have to reinpect (and add a listener) to
> element B
> in order to find out how to access it. Then in your test, you'd
> activate element A and do a waitForElement with the proper expression
> for element B. New tree elements wouldn't be any different as long as
> they are added into the same area of the tree on test run. Now if
> your
> run adds a bunch of stuff to the tree and resorts it three times,
> you're
> going to have a problem, but I'd argue you have that problem if you do
> that with some element that's not in a tree too, like a <select> drop
> down list.


I'm not talking about test execution, I'm talking about during
inspection. Currently the window listener works for all new elements,
but we have to add individual listeners to every element in the tree
view in order to inspect them. When a re-draw happens we'll need to
find all the elements again and add listeners to any that don't
already have them.

-Mikeal

Clint Talbert

unread,
Feb 5, 2009, 4:37:50 PM2/5/09
to mozmi...@googlegroups.com
On 2/5/09 1:16 PM, Mikeal Rogers wrote:
>>
>
> I don't think this will be the last time we see this considering how
> many other UIs are created by XBL.
>
>
You are probably, unfortunately, right. :(
>>>> Mikeal, Adam, let me know what you think of this.
>>>>
>>>>
>
> I'm not talking about test execution, I'm talking about during
> inspection. Currently the window listener works for all new elements,
> but we have to add individual listeners to every element in the tree
> view in order to inspect them. When a re-draw happens we'll need to
> find all the elements again and add listeners to any that don't
> already have them.
>
>
>
I don't see how that's a problem during inspection. During inspection,
the trees are not changing. But, there is a listener available on
standard trees that will tell you when the tree is rebuilt.
tree.builder.addListener(). This takes a nsIXULTemplateBuilderListener
object [1]. However, the builder object may or may not be available on
all trees, as you have no doubt already guessed.

Clint
[1]:
http://mxr.mozilla.org/mozilla-central/source/content/xul/templates/public/nsIXULBuilderListener.idl#47
> >
>

Mikeal Rogers

unread,
Feb 9, 2009, 1:23:09 PM2/9/09
to mozmi...@googlegroups.com
I've created a wiki page on the google code project to help keep track
of all the research we're doing.

Most of this document has been merged in to that wiki document.

Discussion should still happen on this list, the wiki page is just for
keep track of all the different information we find as we drudge
along :)

http://code.google.com/p/mozmill/wiki/TreeElements

-Mikeal

On Feb 5, 2009, at February 5, 200910:27 AM, Clint Talbert wrote:

>
Reply all
Reply to author
Forward
0 new messages