Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Helper method for debugging purposes

    Does SC have a built-in library that I can call which will give me a list of all elements on a page?

    #2
    If you mean DOM elements, no. That's actually built-in to all modern browsers (getElementsByTagName), although we'd recommend using a wrapper library such as JQuery for anything you might do with the elements along the lines of detecting sizes or retrieving various attributes.

    Comment


      #3
      Thanks for the quick response - it is actually more for mimicking what scLocator does

      Comment


        #4
        Not sure what the use case, but you can't faithfully mimic scLocator via direct-to-DOM coding. There are lots of distinct scLocators that don't actually correspond to distinct DOM elements (drag & drop zones are one example), and lots of DOM elements that don't have unique scLocators.

        Comment


          #5
          Currently the scLocators are based from the Smartclient object's ID field that we've set. And the ID field we currently set are formed from their hierarchical path. For example, if there is a layout with name="myLayout" and it contains another layout with name="myLowerLayout" and in turn "myLowerLayout" contains a text field with name="myTextField" then the ID for the text field is something like myLayout$myLowerLayout$myTextField. As a result, myLayout$myLowerLayout$myTextField is also the generated scLocator for that field.

          We currently have an issue when we move the "myTextField" directly under "myLayout" since then its ID becomes "myLayout$myTextField" and the Selenium test will fail. We want to implement a smart lookup where the locator is simply "myTextField". Then the Selenium locator search should find any element with id that ends with "$myTextField". Can you recommend a way we can accomplish this?

          I'm don't know how the Selenium extension code you guys provide work exactly. Is it taking the scLocator as well as the user action, such as a "click" into your internal code to find the element and perform the click, or, is it returning the DOM element to Selenium and allowing Selenium to generate the click event on the DOM element, and your sc object merely listen to the click event to perform the click?

          Comment


            #6
            We currently have an issue when we move the "myTextField" directly under "myLayout" since then its ID becomes "myLayout$myTextField" and the Selenium test will fail. We want to implement a smart lookup where the locator is simply "myTextField". Then the Selenium locator search should find any element with id that ends with "$myTextField". Can you recommend a way we can accomplish this?
            If you simply didn't embed the entire object hierarchy in every component's ID, it would still have the same ID wherever it was. That's the right fix; searching by suffix isn't something that can be done efficiently, and could match the wrong widget (it invites a whole new class of accidental ID collisions). Trying to do this moves you yet further away from best practices as well - the recommended approach is to use IDs on just certain parent components.

            I'm don't know how the Selenium extension code you guys provide work exactly. Is it taking the scLocator as well as the user action, such as a "click" into your internal code to find the element and perform the click, or, is it returning the DOM element to Selenium and allowing Selenium to generate the click event on the DOM element, and your sc object merely listen to the click event to perform the click?
            To a first approximation, it returns the DOM Element to Selenium and Selenium performs the click. But there are a *lot* of details, the tip of the iceberg being that Selenium will not normally perform a full mouseDown, mouseUp, click cycle, so we modify it to do so.

            Comment


              #7
              We understand your point of not embedding object hierarchy in the component's ID. But for our case, we actually have to generate our UI dynamically so we use this method to guarantee uniqueness of the ids. For Selenium play back, we do not worry too much about the efficiency or the matching of the wrong widget. If we find more than one object that matches the locator, we can always say we expect the 2nd or 4th one. We also think about adding additional attribute to the objects specifically for Selenium other than using the ID attribute. Then we can add our own Selenium extension and do the matching ourselves. Two things prevent us from doing this: first we need a way to obtain all SmartClient objects so we can iterate through them. Secondly, when we find the right SmartClient object, we need a way to obtain its associated DOM object to return to Selenium. Also, as you mentioned that you have to do "special" things in order for Selenium to perform actions correctly. We need to do the same thing in our extension. Would you be able to provide a solution to the problems we have?

              Comment


                #8
                You need to articulate an actual, real-world testing scenario that you are trying to solve before we can suggest a solution.

                You mentioned the ability to match components by a suffix of an ID instead of an ID - but this capability appears be redundant with, and entirely worse than, the approaches and capabilities our product already provides.

                As far as writing your own Selenium extensions - this is extremely complicated and we would advise you, in the strongest possible terms, not to go down this path - this will lead to total failure after a huge amount of effort. Not to mention, you'd be getting into the internal DOM of SmartClient components, which by necessity is undocumented and subject to change at any time.

                Comment


                  #9
                  The driver for the questions we have posed to you is that currently our Selenium test cases are extremely brittle and prone to breaking with every new release of SmartClient we upgrade to. Unlike traditional web application UI, our UI is generated at runtime. This means that we cannot assign unique IDs to every element on a particular screen because I do not know what can potentially be on screen. I have to generate the unique IDs and I have to generate them in a way that it's the same with every run of the application. What we have is an hierarchy of objects in the UI, and we know the name of each object in the hierarchy. We have a restriction that name of each object under the same parent have to be unique. Naturally, the path of each element in the hierarchy is unique and we use that as the ID. The downside is the the IDs are potentially very long and any changes in the hierarchy breaks the test due to inability to find the object. We want the ability to search for an element through Selenium using both the ID we generate, and the name of the element. Using only the name of the element can cause the problem that multiple element with the same name can be located, but we are fine with that since in those cases we can specify the n-th element in the list. The problem is that your code only deals with IDs as the locator, there is no way for us to say: don't use IDs as the scLocator, use this "myLocator" attribute as the scLocator. Or, here is this partial scLocator, do a pattern matching on it and return all elements whose ID matches the pattern. Either of these would help us achieve what we need.

                  Comment


                    #10
                    So again, our advice, which is right there in the Using Selenium docs, is:

                    Use setID() selectively to avoid this problem. Generally, it makes sense to use setID() on all top-level (parentless) widgets - at this point, locators for children that do not have a unique ID will be based on the parent's ID plus a relative path. This relative path will not incorporate auto-generated IDs and will generally continue to work even if the interior layout of the parent is significantly rearranged (such as adding a new intervening container widget).
                    We are not insisting upon a unique ID for every widget. The Selenium support we provide does not require this, and providing unique IDs everywhere is a practice we specifically advise against.

                    If you would just follow our best practices, your scripts would not break.

                    Comment

                    Working...
                    X