How can I automate test HTML5 elements in the UIAWebView in Instrument? - html

I am trying to automate the test of a mobile app, which is HTML5 embedded in Native app frame. I used the following code to get the elements in Instrument
UIALogger.logStart("Log elements in the landing page");
UIATarget.localTarget().logElementTree();
UIALogger.logPass("done");
And it will show the HTML5 component as UIAWebView. But for example, if there is a link in the HTML, and I want to click, I can only know it by the position. Is there any method that I can call to get the tags in HTML5?
Thanks a lot!

There is no such menthod, you will get elements with target.logElementTree(); as you used. If elements are native elements, you can use them with predefined methods like buttons() or links() else you will have to use them specifying position (xy coordinates) only. This problem always exists with Hybrid apps.

Related

When to use React 16 Portals

Lots of new functions released with React 16. One of them is the ReactDOM.createPortal(child, container) API, which is handy for visually breaking out of its container.
However, it seems like that it not only breaks out its container but also breaks the basic html rules which I learned from the first day of web development. The createPortal API let you render your component out of its parent, and break the html structure convention we expected.
In the other hand, we do retrieve more flexibility and now can render DOM in the sibling or else components.
IMO, I don't think this is a good deal to gain more flexibility by trading html convention in. Also the example supplied by official does not convince me.
What I am curious about is:
Is there anyone who face any condition that createPortal API is a must?
thanks
The examples in the docs are some of the cases where createPortal is really useful - specifically dialogs, hovercards, and tooltips.
The docs also specifically state:
Note:
It is important to remember, when working with portals, you’ll need to make sure to follow the proper accessibility guidelines.
As an example, the docs show how a modal could be built using createPortal(). You'll notice the modal is created in the #modal-root element, which is a root element alongside the #app-root element. This is a great example of how createPortal() can be used without violating any HTML rules.
<div id="app-root"></div>
<div id="modal-root"></div>
I ran into another use case a few months ago. Because React 16 portals were not available, I had to use a home-baked portal implementation.
I was creating SVG graphs. All of the lines, paths, and so forth needed to be rendered inside an <svg> element. But I wanted to use HTML to render text labels (for a number of reasons). This meant that an object on the graph and its label would necessarily be in separate parts of the DOM. But with portals, I could still keep all of a graph component's logic together. Here's a fictitious example:
const LabeledPoint = ({ x, y, r, labelText }) => [
<circle cx={x} cy={y} r={r} />,
<GraphLabel x={x + 5} y={y}>{labelText}</GraphLabel>,
];
You would use this component inside an <svg> element. The GraphLabel component would use a portal to render labelText in an HTML div element at the same coordinates as that <svg>, using absolute positioning to place it at the correct coordinates.
This way, all of the logic for a single component could be in one place even if I needed to render the actual DOM elements in different places for technical reasons.
Portals is very useful feature when you need to render your component outside the DOM hierarchy of the parent component.
You define a portal using the following syntax:
ReactDOM.createPortal(child, container)
The first argument (child) is any renderable React child, such as an
element, string, or fragment. The second argument (container) is a DOM
element.
See the following tutorial to see how and why to use portals:
https://www.youtube.com/watch?v=lOMU9BeIrO4
Before going into my answer, I'll just note that I interpret the question as "in which cases is there no alternative to using a portal, or a portal would be a demonstrably much better solution?"
There are very few cases where portals are the only solution. A lot of the time there's a way to structure your app so that you don't need to use them. There's some niche use cases, but even there it's usually not the only solution.
For example in the SVG use case, you could instead create a Labels component that takes an SVG React element as argument, and then loops recursively over the children to construct an HTML element with matching labels in the right position. That would as a bonus also make the SVG code a lot simpler. If the SVG is user editable, you'd have to store its state as a whole anyway on each change, allowing you to easily pass the state back into both SVG and label elements. That said, here the portal solution seems at least on par with the alternatives, and could be the simplest in some circumstances.
Dispatching plugin components
Portals can be useful for library/framework authors. It allows plugins to render multiple components in the same element, each of which the framework then portals to a different position in the UI (e.g. editor area, sidebar).
WordPress's block editor uses this for a few things, they call it SlotFill. For example if you're coding a new block in a plugin. You always provide an edit component for each block, which is rendered to the WYSIWYG editor. If it includes an InspectorControls component, everything inside it will go into the sidebar.
The Block Toolbar works in the same way. Content of the <BlockControls/> element is moved to the toolbar that is displayed right above the block content.
This is implemented as a portal to a registered slot.
The advantage of a portal here is that it allows a block's code to reuse the state and hooks in all components, even though they are not rendered in the same place. This makes the process of adding sidebar code very easy and with minimal repetition. If plugins instead needed to provide each of these components as a standalone React component, managing their state would be much more complex.
Example
You won't find ReactDOM.createPortal in the example itself. It's rather an example of how a plugin can benefit from a framework that uses it. See WordPress's source code if you're interested in the implementation details.
I added a simple useState hook to the mentioned InspectorControls example and removed some irrelevant parts.
edit: ( { attributes, setAttributes } ) => {
const [myColor, setMyColor] = useState('#fff');
return (
<div>
<InspectorControls key="setting">
// Simplified HTML, real world blocks use more complex HTML here.
<ColorPalette
value={myColor}
onChange={ setMyColor}
/>
</InspectorControls>
<TextControl
value={ attributes.message }
onChange={ ( val ) => setAttributes( { message: val } ) }
style={ {
backgroundColor: myColor,
color: attributes.text_color,
} }
/>
</div>
);
},

Is there a way to access the DOM object from a Mobile project

StageWebView is a way to display HTML content on devices where the HTMLLoader class is not supported. Having that into account, is the htmlLoader the only possible way that of accessing DOM objects from ActionScript. Does anyone know of another way that would work on a mobile project?
If you are creating the html content, then this may be possible via loadURL and the "javascript:" protocol:
http://sean.voisen.org/blog/2010/10/making-the-most-of-stagewebview/

PhantomJS / CasperJS Canvas selector

Using PhantomJS V 1.8.1
Thanks in advance.
I am trying to run some tests on a website that I am developing which is using backbone.js.
One of my tests involve checking to see if a Canvas is present and clicking on it. My problem is that whatever selector I use to get the Canvas Element I cannot get the selector to find it. I use the same CSS selector in Google Chrome when viewing the page and all is OK. At first I thought that the issue may have been due to the element not being present on the page but other elements which are inserted with the canvas are present so I am 99% sure that this is not the problem.
The selectors I have tried to use are:
document.querySelectorAll('#idOfCanvas');
document.querySelectorAll('canvas#idOfCanvas');
Also if I use .classClassName:nth(1) to select the tyre selector, it still fails to work (works in Google Chrome though as does the other examples provided)
The canvas has a class name which is picked up by the selector by I would rather not use a class selector.
Any help would be much appreciated.
Cheers :)
Also
Like I mentioned I am almost certain that the Canvas exists as the container div for it exists. Also I have four elements on the page with the same className (two of which are canvases) and four elements are being returned when I run
return document.querySelectorAll('.className').length = 4;
Assuming you have something like this:
<canvas id="idOfCanvas"></canvas>
This should work:
canvas = document.getElementById("idOfCanvas");
// or
canvas = document.querySelector("#idOfCanvas"); // Only get the first match, ID's should be unique, any way.;
// or
canvas = document.querySelectorAll("#idOfCanvas")[0];
// or
canvas = document.getElementsByTagName("canvas")[0]; // Get the first <canvas> element.
However, you'll have to make sure your canvas element is actually loaded when the script is executed. Have a look at this onload tutorial, for example.
Try this :
canvas = document.getElementById(#IdOfCanvas:nth-child(1));

Is editing parent html page from the embedded flash file possible?

A client wants the company I work for to build an expandable flash banner, I'm a dev, so my solution is: stack 2 flash banners, small one visible, big one on top of it, with display:none, catch the click event, animate the big one into position.
The client wants it done without javascript (their banner rotation network doesn't support additional javascript).
I'm baffled, as I have no clue how a flash file can modify it's own html embed code and the css styles and as far as I'm aware, it's not possible.
Any suggestions/ideas? Is there an api in flash to talk to the html file, is there some actionscript magic that could make this happen?
Thank you for your time
You can talk to the parent HTML file via the ExternalInterface API.
You can pass the call() method entire javascript functions to do what you need. This way, you don't have to add extra javascript to the parent HTML file.
For example:
ExternalInterface.call("function() { document.getElementById(\'foo\').dosomemagichere; }");

Get Flex app's position on a web page?

Is it possible to get the x,y coordinates of a Flex app within an HTML page? I know you can use ExternalInterface.ObjecID to get the "id attribute of the object tag in Internet Explorer, or the name attribute of the embed tag in Netscape" but I can't seem to get past that step. It seems like it should be possible to get a handle on that embed object. Any suggestions?
Thanks.
I think the easiest thing to do is to include some kind of JavaScript library on the HTML page, say jQuery, and use it's functions for determining the position and size of DOM nodes. I would do it more or less like this:
var jsCode : String = "function( id ) { return $('#' + id).offset(); }";
var offset : Object = ExternalInterface.call(jsCode, ExternalObject.objectID);
trace(offset.left, offset.top);
Notice that this is ActionScript code, but it runs JavaScript code through ExternalInterface. It uses jQuery and in particular its offset method that returns the left and top offset of a DOM node.
You could do without jQuery if you looked at how the offset method is implemented and included that code in place of the call to jQuery. That way you wouldn't need to load jQuery in the HTML and the Flex app would be self-contained. The reason I suggest to use a library like jQuery is that browsers do these things differently. I'm not sure if calculating offsets is very different from browser to browser, but it doesn't hurt to be insulated from browser differences.
The JavaScript in my example is an anonymous function so that the ID of the embed/object tag can be passed in to it as a parameter to ExternalInterface.call, but you could just use string concatenation if you want:
var jsCode : String = "$('#' +" + ExternalInterface.objectID + ").offset()";
var offset : Object = ExternalInterface.call(jsCode);
That would work too, I just think the first version is more elegant.
If you are trying just to measure where it's at within a page as the external user the only thing that pops into my mind is a Firefox extension called MeasureIt I've used it occasionally for various measuring on web pages.
Are you trying to do this programmatically from within the embedded page itself and if so which langauge?