I am trying to pass in contentDescription into a custom step definition, with little success and I am not sure I can do it, there is very little help out there, so I am a bit lost.
so I have started calabash-android console
then start_test_server_in_background
then query("TextView") which returns a list of elements in the textView, in this list are contentDescription, each has a string value, e.g "thisIsValue"
now I have written a step in my feature file as:
Then I touch contentDescription "thisIsValue" text
the syntax of my custom step method is:
Then /^I touch contentDescription text (\d+)$/ do |text, contentDescription|
tap_when_element_exists("contentDescription contentDescription:#{arg1}")
I'm starting to think passing in contentDescription just isn't possible for multiple values of the same text on a form, using ID is not possible due to the way xamarin forms are generated in our instance, another option would be on index, however that is not really good moving forward.
thanks all.
Graeme
There are few possibly wrong details about your step definition.
The (\d+) regular expression indicates, that you are looking only for elements with digits in contentDescription.
You are passing into block one value (which is mentioned above digit-only value) and then expecting two values to be passed (text and contentDescription).
You should tap element of type TextView, ImageView, * etc., but you want to tap contentDescription element.
You want to tap element with contentDescription with value of arg1, but there is none arg1 inside your block.
Do not forget about apostrophes around contentDescription's value in your query.
So, your step definition possibly should look something like that:
Then /^I touch contentDescription text: (.*?)$/ do |arg1|
tap_when_element_exists("TextView contentDescription:'#{arg1}'")
end
#kjuri - your solution has now worked, it appears that in my windows environment set up it was looking at the incorrect step def, I cleared out the folder and started again - basically turned it on and off again!! thank you very very much for your patience on this, and your help.. greatly appreciated indeed. To summize this worked:
Then /^I touch the contentDescription "(.*?)" text$/ do |text|
tap_when_element_exists("RadioButton contentDescription:'#{text}'")
end
Related
I just started using EarlGrey, and now I try to realize construction which will make screenshot if the test fails on Assert.
It is rather simple, e.g. when I check if the keyboard is visible, because GREYKeyboard.waitForKeyboardToAppear() returns Bool:
let image = GREYScreenshotUtil.takeScreenshot()
GREYScreenshotUtil.saveImage(asPNG: image, toFile: "\(testMethodName).png", inDirectory: path/to/necessary/directory)
GreyAssert(GREYKeyboard.waitForKeyboardToAppear(), "Keyboard is not active") //works correct
But if I want to check the same way if some element (for example, button or text field) I can't just use grey_sufficientlyVisible(), and most of other matchers return non-Bool.
I know that .assert(with: ) exists, but it's not so versatile.
So, is there any way to make this working?
I have an application, and it works such way: when I tap & hold some element, context menu is shown, then I can move my finger to specified element and release it on appropriate menu item. I try implement this logic with Appium, but it's failed.
At first, I tried press element, then move_to another:
Appium::TouchAction.new.press(element: my_elem).perform
Appium::TouchAction.new.move_to(element: text(...)).perform
But before second action "finger releases screen" and context menu disappeared. Then I tried another way:
Appium::TouchAction.new
.press(element: my_elem)
.move_to(element: text(...))
.perform
But it fails with Selenium::WebDriver::Error::NoSuchElementError: No element found, because element, where we move_to, didn't appeared yet.
So, tell me please, how can I implement neccessary logic?
Not sure about Ruby but in java first you release() it before perform(). Also, if this doesn't work, look if duration() method is availabe in Ruby. Then you should use somethings like:
element.longPress.duration.release.perform();
In case if you don't find duration method, then its a bug in Appium what they are working on. Look at this:
https://github.com/appium/appium/issues/4695
Try this:
driver.scrollTo("string").tap(1,2000);
First, make sure that the element you want move to is really reachable. If it is but it hasn't appeared before you called the method then you should wait till the element appears. This is a sample in java
WebDriverWait wait = new WebDriverWait(driver, 120);
wait.until(ExpectedConditions.presenceOfElementLocated(locator));
This may look a little different in your case, but the idea is the same. After it passes, then call move_to, if it fails then probably your element is not reachable.
If the problem is like you said,
But it fails with Selenium::WebDriver::Error::NoSuchElementError: No element found, because element, where we move_to, didn't appeared yet.
Then try this
wait = Selenium::WebDriver::Wait.new :timeout => 10
then you can do something like this
wait.until { moveTo(element: text(...)) } ...
You probably have to adapt this to your case, I just wanted to show you the idea, you can read more about this here
UPDATE3 - SOLVED with reservations, please see my solution below; leaving it open since the cause of the problem is unclear, and I don't know how robust the solution is.
UPDATE1: here's the short short version.
Currently, after .setEditText on a QComboBox, I get this:
so the next thing you type will overwrite 'Team '.
But the desired effect is this (unhighlighted / unselected), so that the next thing you type will be appended to 'Team ' instead of overwriting it:
Thanks for any help. The rambling details are below, which is the original post:
(this is all PyQt 5.4)
UPDATE2:
Apparently python doesn't think anything is actually selected:
self.entryForm.ui.teamField.lineEdit().setText("Team ")
print("selected text:"+self.entryForm.ui.teamField.lineEdit().selectedText())
prints "selected text:" and nothing else. To make sure that's working:
self.entryForm.ui.teamField.lineEdit().setText("Team ")
self.entryForm.ui.teamField.lineEdit().setSelection(0,4)
print("selected text:"+self.entryForm.ui.teamField.lineEdit().selectedText())
prints "selected text:Team"
So that might be why many of the methods that affect selection are not working as expected (.deselect(), .setSelection(5,5), etc, and even some of the other methods give unexpected behavior, i.e. cursorForward(False,1) or cursorBackward(False,1) and such.
Original post:
This is for a radio log GUI, so keyboard interactions must be minimal and intuitive. openNewEntryForm (below) is called as a slot from a pushbutton on the main application GUI window:
self.ui.pushButton.clicked.connect(self.openNewEntryDialog)
It can also be called using a keyPressEvent in the same class:
def keyPressEvent(self,event):
if type(event)==QKeyEvent:
print("QKeyEvent:"+str(event.key()))
if event.key()==Qt.Key_T:
self.openNewEntryDialog('t')
event.accept()
else:
event.ignore()
Here's the method in question:
def openNewEntryDialog(self,key=None):
self.entryDialog=newEntryDialog()
if key=='t':
self.entryDialog.ui.to_fromField.setCurrentIndex(1)
self.entryDialog.ui.teamField.setFocus()
self.entryDialog.ui.teamField.setEditText("Team ")
if self.entryDialog.exec_():
self.newEntry(self.entryDialog.getValues()) # adds the log entry
so, the intended key press sequence is (from the main application GUI window):
a single keyboard press of 't' will open the entryForm, set the to_fromField to index 1 (which happens to be "TO"), give focus to teamField (also a QComboBox), set its text to "Team " and set itself up so that the very next keypress will appear as the text following "Team " in teamField.
So, starting from the main app GUI again, the plan is that typing 't3' should open the new entry window, set the to_fromField to "TO", and set the teamField to "Team 3", ready for a keypress of the tab key to move on to the next field in the entryForm.
The problem is that the teamField.setEditText("Team ") call leaves all of the text highlighted/selected, so that a subsequent key press of '3' would replace "Team " with "3"; I'm looking for a way to unhighlight/unselect "Team " but leave the cursor active at the right of that string, so that the subsequent key press of '3' would make the entire string "Team 3".
Ideas? Thanks in advance.
You can access the line-edit of the combo box, and then remove the selection:
self.entryDialog.ui.teamField.setEditText("Team ")
self.entryDialog.ui.teamField.lineEdit().deselect()
UPDATE:
The above code is correct, but it seems that the dialog will then clobber it when it initialises the focus handling for its child widgets after it is shown. If a dialog is opened with exec(), it will start its own event-loop, and some events (including focus events) will only be processed after it is fully shown. This is why it may appear that some changes made to child widgets before the dialog is shown are being ignored.
One way to work around this is to use a single-shot timer to ensure the changes are only attempted after the dialog is shown.
So add a method to the entry dialog class something like this:
def resetUI(self, key):
if key == 't':
self.ui.to_fromField.setCurrentIndex(1)
self.ui.teamField.setFocus()
self.ui.teamField.setEditText('Team ')
QtCore.QTimer.singleShot(0, self.ui.teamField.lineEdit().deselect)
and then use it like this:
def openNewEntryDialog(self, key=None):
self.entryDialog = newEntryDialog()
self.entryDialog.resetUI(key)
if self.entryDialog.exec_():
self.newEntry(self.entryDialog.getValues())
SOLVED with reservations, see UPDATE3 in the original post.
So, with the initial text all highlighted, tests show that it didn't actually think anything was selected. This solution was just stumbled upon by trial and error, fiddling with setting and clearing focus, selecting text and trying deselect:
def openNewEntryDialog(self,key=None):
self.entryForm=newEntryDialog()
if key=='t':
self.entryForm.ui.to_fromField.setCurrentIndex(1)
self.entryForm.ui.teamField.lineEdit().setFocus()
self.entryForm.ui.teamField.lineEdit().setText("Team ")
self.entryForm.ui.teamField.lineEdit().setSelection(5,1)
Notice there are two spaces after 'Team' and the second one is intentionally selected. Then the very next keypress will overwrite that second space; that is basically the desired behavior.
Anyway it looks like something bizarro with the selection scheme; one way to look at this is that the highlight isn't really a selection, but, if you set a valid real selection then it will override the original highlighted 'pseudo-selection'. The original highlighting behaves like a selection in that a keypress will replace everything that's highlighted, but, not like a selection in that the selection methods reveal that there is no 'selection', see UPDATE2 in the original post.
Can anyone help explain this behavior? I'd like to build some more confidence in it before accepting this coincidental answer.
Thanks
I am learning PyQt4 (I am using version 4.4.4) and I'm pretty new to Python (Python 2.5). I have a GUI with a QListWidget and a QPushButton. I want a user to be able to click to select an entry in the list and then click the QPushButton and have the selected entry go away (be deleted from the QList). I've been banging my head against this problem for over a week and I would deeply appreciate some help.
Currently, my GUI comes up and I can select different list items (only one at a time right now), but when I click the QPushButton, nothing happens. The selection color goes from blue to grey, but the entry is not removed. No error is shown in Command Prompt (Windows 7).
I have defined a function, remove(),which I am using as the slot for the QPushButton. I believe the QPushButton.connect is defined correctly for a Qt Signal to Python Slot, based on what I've seen of answers to similar problems, but the items are not being deleted. However, the remove function is not even being triggered. I have a print statement within the function, but it is not being called when I click the QPushButton, which is how I know that the function is not being called.
Here is my most recent code: (I read a very rant-y post on meta-SO about big blocks of code, so I've cut this down to the bits I think are relevant: the list creation, the button creation and the remove function, which I'm trying to use as a slot. I've left in comments that indicate what the other sections are, so if you think I've left out something that could help, let me know and I'll add it back in)
class questionGUI(QtGui.QWidget):
#This class is the window of the gui.
def __init__(self):
super(questionGUI,self).__init__()
#Layout
grid = QtGui.QGridLayout()
grid.setSpacing(10)
#Labels Needed
...
#Question List
self.qList = QtGui.QListWidget()
#print self.qList
self.qList.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
entries = ['[Pick Image] <Default>','[Slider Question] <Default>', '[Comment Box] <Default>']
for i in entries:
item = QtGui.QListWidgetItem(i)
self.qList.addItem(item)
#Type select
...
#Text insert Needed
...
#Buttons Needed
deleteButton = QtGui.QPushButton('Delete Question')
deleteButton.connect(deleteButton,QtCore.SIGNAL('itemClicked(clicked)'),lambda: self.remove)
addQuestionButton = QtGui.QPushButton('Add Question')
...
doneButton = QtGui.QPushButton('Done')
...
#Parameters Needed
...
#Layout Placement and Window dimensions
...
def addQuestion(self):
...
def remove(self):
print 'remove triggered'
print self.qList.currentItem()
self.qList.removeItemWidget(self.qList.currentItem())
...
I tried to post an image, but I don't have enough reputation. If you think an image would be useful, let me know and I can send it to you.
You mixed the signals:
deleteButton.connect(deleteButton,QtCore.SIGNAL('itemClicked(clicked)'),lambda: self.remove)
deleteButton is a QPushButton, but itemClicked(clicked) looks like the signal from QListWidget with wrong signature. Since, QPushButton doesn't have this signal, no connection is made. Qt doesn't raise errors for failed connections, but .connect method has a bool return value indicating success/failure of the attempted connection.
Also, lambda: self.remove as a slot doesn't make sense. Slot should be a callable that is called upon signal emit. Sure, lambda creates a function, but all you do is reference the method self.remove. lambda will be called, self.remove not. Just self.remove as a slot is enough.
You should use clicked() signal (or clicked(bool), if you care about the checked value) from button:
deleteButton.connect(deleteButton, QtCore.SIGNAL('clicked()'), self.remove)
Edit
Another problem: Your remove method doesn't do what you want. removeItemWidget doesn't remove the item, it removes the widget inside the item (if you set one). It's counterpart to setItemWidget.
You should use takeItem to remove items.
def remove(self):
self.qList.takeItem(self.qList.currentRow())
newbie question: can anyone tip me to how to understand/interpret what is displayed in the debugger var pane?
Ex: I am passing an NSDictionary as a method param. I set a breakpoint so I can examine the values in the dictionary. The image below (if it comes through..) shows the expanded view of this var in the debugger. It correctly reports that it contains 3 name/value pairs but as I expand all the sections, I simply can not find where these are stored.
Do I have to create local vars of these name/value pairs in order to view them when I want to check? I know I can use NSLog or printf but sometimes I just want a quick peek.
Right click the variable, click "Edit Summary Format" and type the following:
{(NSString*)[$VAR description]}:s
This replaces the GDB formatter for NSDictionary with a call to the more expensive description method.
That is, instead "x key/value pairs", you'll see the contents of the dictionary as produced by -[NSDictionary description].
This is the same as typing po dictionary in the console window. Or right clicking the variable and choosing "Print Description". Both of them call the description method of the object.
If you are curious, you can find this formatter at /Developer/Library/Xcode/CustomDataViews/Foundation.plist under the key NSDictionary. What you type as replacement is saved in /Users/USERNAME/Library/Developer/Xcode/UserData/Debugger/CustomDataFormatters and will persist across runs until you delete that file.
A NSDictionary is really a class cluster and few people know the inside structure. At this point you ain't going to find much use for that debugger tree.
This is what you are looking for :
Click on your dict, then click on the little "i" icon :-)