I am trying to tap on a link within a link label. Using the recorder I have this code for the tap event
let link = XCUIApplication().scrollViews.otherElements.links["link here"]
link.tap() does not tap on the link correctly. The link is at the end of the text, how would I be able to tap that part of the label? It seems like XCUITest taps the start of the text which doesnt have the link
Seems like it may be an accessibility container issue. However one work around is to compute the coordinate relative to the UI element you can access with XCUIApplication.
let coordinate = CGVector(dx: 0.1, dy: 0.1) //Enter your values for x / y
someElement.coordinate(withNormalizedOffset: coordinate).tap()
I usually just use trial and error to compute the coordinates. However, you can use the accessibility inspector and debug prints if you need an extra precise press.
Related
I tried and understood what could be the purpose of the accessibilityActivationPoint but in vain.
When a focused accessible element is activated, that property should indicate VoiceOver the specific area it's going to activate when a user double-taps the element (Apple reference) : for me, it's always the selected element itself.
I understood the selected element is considered as a block by VoiceOver, whatever the other elements inside. Once a double tap occurs to activate this block, VoiceOver calls accessibilityActivate to know what to perform (Apple reference).
1/. I've written many tests by creating a custom view including a switch control. Whatever the value of accessibilityActivationPoint inside (or outside on another switch control), the value of the switch control never changes. Is it a proper use case or am I totally wrong ?
2/. When we gather many elements inside one accessible element, how is VoiceOver able to activate one of them while they aren't accessible by definition ? Pointing one of them thanks to the accessibilityActivationPoint should work ?
Personally, I couldn't make it work and think that I'm really confusing accessibilityActivationPoint and accessibilityActivate.
Any help would be appreciated, thanks in advance.
Yes, you have the right idea with accessibilityActivate and accessibilityActivationPoint. Note that, in order for it to work, the accessibilityActivationPoint needs to be a point within the Control that you are trying to activate in on-screen coordinates (use the convert function!).
I think the short answer is "yes" to answer your second question, but, just to clear up confusion about when Accessibility Activation Point is useful, I'll go into more detail about it.
By default (aka, the default behavior for AcessibilityActivate()), when any view is activated by VoiceOver, VoiceOver will send a "tap gesture" to the center of the view. The position of this "tap gesture" can be changed by updating the accessibilityActivationPoint attribute on a view. Below, I have an example for how this property can be used.
Let's say you have a blank button (in the image below, the button is the gray box) next to some text:
For the purpose of accessibility, you may want to make the entire view that holds the button and text an Accessibility Element (so that VoiceOver users can easily understand that the button is associated with the text "Worldspace Attest"). In the image below, I am using Accessibility Inspector to show that the view holding both of these elements is an Accessibility Element.
Notice in these images that the button is not in the center of the view, but rather, it is to the right. When you activate this view using VoiceOver, the view will not select the button; instead, it will send a "tap" to the center of the view (which is the same as tapping the text, which does not do anything). In order to select the button, you have to set the view's accessibilityActivationPoint to be the on-screen coordinates of the button:
view.accessibilityActivationPoint = self.convert(button.center, to: UIApplication.shared.windows.first)
This should make it so that this button is usable by a VoiceOver user.
I hope this information clears up any confusion about the Accessibility Activation Point property. The example I used above can be found in this repository in the "Active Control Name" demo.
Watching a tutorial and it looks like the guy is holding down a button to show the distance between his selected view and what's around it.
I've tried command, option, control, and every other button I can think might work. What button needs to be held to get these lines?
By pressing option key only on your keyboard.
Select an element, and move the mouse while pressing the option key, it will show the red lines with the distances.
Hovering over another element will show you the distance between the selected element and that element.
I am trying to tap an x, y location, while using Xcode and UI Testing. Here is my code:
XCUIApplication().coordinateWithNormalizedOffset(CGVector(dx: 50, dy: 50)).tap()
The middle of the button is definitely at that location and cannot be identified as an individual object (hence using the x, y coordinates).
However, this is not pressing the button. Anyone know if there is a correct way of tapping an x y coordinate?
The dx and dy are not pixel offsets but normalized vectors. For example, 0.5 is actually the middle of the element. Your code is trying to tap an element outside of the screens bounds (by ~50x!).
I suggest trying to solve the problem with a different approach. First off, why can't the button be identified? What have you tried? Are you using a custom UIButton subclass?
I ask because you can (usually) expose any control or UI element to UI testing with the right accessibility attributes. For example, you can set accessibilityLabel and accessibilityIdentifier to the button's text. Then you can use that value to access the button under test.
// Production Code
let button = UIButton()
button.setTitle("Save", forState: .Normal)
button.accessibilityIdentifier = "Save"
// UI Test Code
```
let app = XCUIApplication()
app.buttons["Save"].tap()
You can use dx: 1.5 to click 50% to the right of an element. I used this on an app that has a a webView that I don't control.
I have a map where a user can choose some object/feature on the map and draw a line to another object/feature. When the user selects the feature i would like do add a draw interaction and already set the first point to the selected feature without the user having to click again on the map.
Here is a fiddle: Sample
The commented code below should be executed programmatically without user interaction, after pressing the draw button
geometryFunction: function (c, g) {
if (goog.isDef(g)) {
g.setCoordinates(c);
} else {
// DO THIS AUTOMATICALLY ON PRESSING DRAW
// TO INITIALIZE AND START THE DRAWING PROCESS
c[0][0] = 1174072.754460305;
c[0][1] = 332653.94709708635;
g = new ol.geom.LineString(c);
}
...
}
The current behaviour is that you click on the Draw button and can click on the map to start drawing (but i overwrite the first node with my desired starting location -- in this example near central africa)
Is it possible to click on Draw and the first node is already programmatically set, without having to click on map first?
It is not currently possible to do manually append points to the OpenLayers 3 ol.interaction.Draw, but it would make sense to be able to support it (in my mind). It would be "as-if" the user had clicked.
You should ask the OL3-dev mailing this about adding such a feature to see what they think about it. If they agree and you're willing to work on this, you could provide a pull request. See: https://groups.google.com/forum/#!forum/ol3-dev
If you don't mind using a private method in OL you can do this to achieve what you want.
var event = $.Event('click'); //create a click event in your draw method using JQuery
event.coordinate = [1174072.754460305,332653.94709708635];// set your starting coordinate
draw_interaction.startDrawing_(event);// tell your interaction to start drawing
I am trying to make an image picker component in LibreOffice.
I have a dialog that is dynamically filled with images. When the user clicks on one images, it should be selected and the dialog should be closed.
The problem is that the number of images is variable. So I need to enable scrolling in the dialog (so that the user can navigate through all images).
There seems to be some properties on the dialog object (Scrollbars, Scroll width, Scroll height, etc)
However, I cannot find a way to use them anywhere.
Any ideas?
The scrollbar is one of the Controls available through the dialog box editor. That is the easier way to put a ScrollBar on a dialog box. Just insert it like any other control. There is a harder way via DialogModel.addControl but that seems non-essential to answering this question.
If you add a scrollbar to the dialog box and run the dialog box, you will find it does nothing by default. The functionality (apparently) must be written into a macro. The appropriate triggering event is the While Adjusting event on the ScrollBar object, although it does not trigger the macro simply with the "Test Mode" function in the dialog editor. Running the dialog box through a macro triggers the While Adjusting event when the scroll arrows are triggered, when the slider area is clicked to move the slider, and when the slider itself is dragged. The Object variable returned by the scrollbar event contains a property .Value which is an absolute value between 0 and the EventObject.Model.ScrollValueMax, which allows you to manipulate the other objects on the page manually based on the position of the slider.
Yes, that's right, manipulate objects manually. The sole example I found, from the LibreOffice 4.5 SDK, does precisely this. Of course, it is not as bad as it sounds, because one can iterate through all of the objects on the page by reading the array Dialog.getControls(). In any event, the secret sauce of the example provided in the SDK is to define Static variables to save the initial positions of all of the objects you manipulate with the scrollbar and then simply index those initial positions based on a ratio derived from the scrollbar Value divided by the ScrollValueMax.
Here is a very simple working example of how to scroll. This requires a saved Dialog1 in the Standard library of your document, which contains an object ScrollBar1 (a vertical scrollbar) and Label1 anywhere in the dialog. The ScrollBar1 must be configured to execute the macro ScrBar subroutine (below) on the While Adjusting event. Open the dialog by executing the OpenDialog macro and the scrollbar will move the Label1 control up and down in proportion to the page.
Sub OpenDialog
DialogLibraries.LoadLibrary("Standard")
oVariable = DialogLibraries.Standard.Dialog1
oDialog1 = CreateUnoDialog( oVariable )
oDialog1.Execute()
End Sub
Sub ScrBar (oEventObj As Object)
Static bInit As Boolean
Static PositionLbl1Y0 As Long
oSrc = oEventObj.Source
oSrcModel = oSrc.Model
scrollRatio = oEventObj.Value / oSrcModel.ScrollValueMax
oContx = oSrc.Context
oContxModl = oContx.Model
oLbl1 = oContx.getControl("Label1")
oLbl1Model = oLbl1.Model
REM on initialization remember the position of the label
If bInit = False Then
bInit = True
PositionLbl1Y0 = oLbl1Model.PositionY
End If
oLbl1Model.PositionY = PositionLbl1Y0 - (scrollRatio * oContx.Size.Height)
End Sub
The example provided by the SDK does not run on my setup, but the principles are sound.
There appears to be a second improvised method closer to the functionality one might expect. This method uses the DialogModel.scrollTop property. The property appears to iterate the entire box up or down as a scroll based on the user input. There are two problems using this methodology, however. First, unless you put the scrollbar somewhere else, the scroll bar will scroll away along with the rest of the page. You will need to adjust the location of the scrollbar precisely to compensate for/negate the scrolling of the entire page. In the example below I tried but did not perfect this. Second, the property seems to miss inputs with frequency and easily goes out of alignment/ enters a maladjusted state. Perhaps you can overcome these limitations. Here is the example, relying on the same setup described above.
Sub ScrBar (oEventObj As Object)
Static scrollPos
oSrc = oEventObj.Source
oSrcModel = oSrc.Model
scrollRatio = oEventObj.Value / oSrcModel.ScrollValueMax
If IsEmpty(scrollPos) = False Then
scrollDiff = oEventObj.Value - scrollPos
Else
scrollDiff = oEventObj.Value
End If
scrollPos = oEventObj.Value
oContx = oSrc.Context
oContxModl = oContx.Model
oContxModl.scrollTop = scrollDiff * -1
oSrcModel.PositionY=(scrollRatio * oContx.Size.Height/5) * -1
End Sub
This (sort of) will scroll the contents of the entire dialog box, within limits and with the caveats noted above.