Can I check for multiple paragraphs in Codeception? - codeception

I'm using Codeception + Selenium.
On my website and in emails sometimes I have a text consisting of multiple paragraphs. I want to check all or most of them in my acceptance tests. I know I can do
$I->canSee($par1, $locator);
$I->canSee($par2, $locator);
however it becomes cumbersome to do this for many paragraphs.
If I try to check for more than one paragraph in canSee(), it fails.
Do you know how I can check for more than one paragraph of text?

I think the best way for you will be usage of "grabMultiple" ( PhpBrowser)
$p = $I->grabMultiple('.article-body p');
codecept_debug($p);
>> [
0 => "P1 text",
1 => "P2 Text",
2 => "P3 Text"
]
will give you back array of matched elements, so you can test how much of them you have, and check what text they have.

Related

Can t find the xpath for Following button instagram for selenium

I try to get the xpath for the following button on instagram making an automate unfollowing soft. enter image description here
I found it just like this:
driver.find_element_by_xpath('//div[#class="qF0y9 Igw0E rBNOH YBx95 ybXk5 _4EzTm soMvl "]').click()
But i want to itterate over all ,,Following" Buttons , but like this is stuck at the first one!
This is my Code:
fBody = driver.find_element_by_xpath("//div[#class='isgrP']")
for i in range(1, 1500):
driver.find_element_by_xpath('//div[#class=" qF0y9 Igw0E rBNOH YBx95 ybXk5 _4EzTm soMvl "]').click()
#driver.find_element_by_xpath("//*[text()='Following']").click()
print("Am apasat follow")
sleep(5)
driver.find_element_by_xpath('//button[#class="aOOlW -Cab_ "]').click()
sleep(5)
driver.execute_script('arguments[0].scrollTop = arguments[0].scrollTop + arguments[0].offsetHeight;', fBody)
print("Ma bag la somn 1 min")
sleep(2)
print("salut")
Selenium does Not "like" empty or white spaces in the attributes.
I suggest using a CSS selector and using *= in order to find text contains:
driver.find_element_by_CSS('//div[class*="qF0y9"][class*="Igw0E"]').click();
Avoid using white or empty spaces and, underscores (_) and hyphens (-) for the element's attributes.
I think the classes on the elements change as yours do not match with mine. Here is a more generic XPath that matches the "following" button.
//div//button[div[text()='Following']
When using this in a test I found it instantly failing unless I surrounded it with an explicit wait condition.
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//div//button[div[text()='Following']"))).click();
Ill post my example when Instagram stops giving me connectivity issues.

In Adobe Acrobat Javascript, how can I force a page to become "editable" before a certain part of a script acts upon it?

What I'm trying to do: Iterate over each page in a PDF, and extract the number of words on each page.
What is happening instead: The code below will return 0 words for any page that has not become "editable". Although I have selected for all pages to become editable at once, Adobe will not maintain the editability of a page for very long after I have left that page. Side note: It also seems to cap how many pages I can have "editable" at once. This is a problem because right now I'm working with a 10 page selection of a pdf file. This same code will have to work with a 120+ page pdf. Please click 'Edit PDF'-->'Scanned Documents'-->'Settings' to see what I mean by "editable". I have already selected the option to have all pages become editable at once.
What I've tried so far: I've tried various ways to get Acrobat to make the page being iterated upon the "active one" so that it would become editable. I've tried manually setting the page number after each iteration of the for loop, and including an artificial delay like with the h variabled for loop in the sample code. I've tried looking for some sort of method that determines which page is the "active one" but I've had no luck so far.
CurrDoc = app.activeDocs[0]
CurrDoc.title;
NumPagesInDoc = CurrDoc.numPages;
console.println("Document has "+NumPagesInDoc+" pages");
for (j=0; j<NumPagesInDoc; j++)
{
NumWordsOnPage = CurrDoc.getPageNumWords(j);
CurrDoc.pageNum = j;
for(h=0; h<10000;h++); //<--I've tried adding in delays to give time so that
//Acrobat can catch up, but this hasn't worked.
console.println("Page number: "+j+" has this number of words: "+ NumWordsOnPage);
};
Output:
Document has 10 pages
Page number: 0 has this number of words: 309
Page number: 1 has this number of words: 0
Page number: 2 has this number of words: 0
Page number: 3 has this number of words: 0
Page number: 4 has this number of words: 0
Page number: 5 has this number of words: 0
Page number: 6 has this number of words: 0
Page number: 7 has this number of words: 0
Page number: 8 has this number of words: 0
Page number: 9 has this number of words: 158
true
Note: Different pages might work on the output at different times depending on which pages I've clicked on most recently before running the script.
Any guidance or help would be greatly appreciated. Thank you for your time.
So. I'm still not entirely sure what the issue is, but I've found a way to get acrobat to function most of the time.
Before clicking the "make all pages editable" option, zoom all the way out until you can see all the pages in the document. For whatever reason, when I did this, it would seem to refresh something about the settings and once again make all the pages editable. This even seemed to work when I opened a totally different pdf and pressed "make all pages editable" even without zooming out.

rebol parsing html: get error "title has no value"

I'm trying to parse an html page:
url: https://dzone.com/articles/2-entity-framework-alternatives-or-give-me-data
html: read url
parse html [
to {<h1 class="article-title" itemprop="headline">}
thru {<h1 class="article-title" itemprop="headli
ne">}copy title to {</h1>}
]
probe title
Can't see why it doesn't work since I get error "title has no value"
I assume that you're using Rebol/view since the free versions don't do https though rebol3 does.
If you want to see if something is working you should look at the return value of the parse, and you'll see it's false which means that there's a problem with your parse rule. Anyway, this works for me though the quotes around the tags are not necessary as < and > are both string delimiters.
>> parse html [
thru <h1 class="article-title" itemprop="headline">
thru <h1 class="article-title" itemprop="headline">
copy title to </h1> to end
]
== true
>> trim/head/tail title
== "2 Entity Framework Alternatives (or Give Me Data!)"
It does not work most probably because the first to stops before the matched string, so that thru starts at the beginning of the first occurence of <h1 ...>, not at the second as you might have expected. You need to skip the first occurrence, before trying to search for the second one. You can achieve that using two thru rules as shown in another answer, or just repeat the rule twice to avoid duplicating it:
parse html [
2 thru <h1 class="article-title" itemprop="headline">
copy title to </h1> to end
]
Notice the final to end rule, which will make parse return true if your rules succeed in reaching the end. The to end rule is a placeholder rule, as you do not care about what is following </h1>, but want to reach the end of the input anyway.
EDIT: Testing the code you submitted works fine from here unchanged. The editing of your question has actually fixed the cause of the error. I can reproduce your issue with your original code.

Is there a way to click plain text in Codeception acceptance tests without using XPath?

Using Codeception acceptance test (with WebDriver), I would like to know if there is a way to click an element that contains a specific text, without that element being a link or a button. I know it can be done using XPath, but I'm looking for a more readable solution that uses CSS-selectors for example.
Without specific examples, probably the best you could do is to look for a group of elements using a CSS selector then loop through that collection looking for contained text. Here's a contrived example where I'm looking for a TD that contains the text "Click here".
List<WebElement> cells = driver.findElements(By.cssSelector("td.someclass"));
for (WebElement cell : cells)
{
if (cell.getText().contains("Click here"))
{
cell.click();
break; // found it, don't need to keep looping
}
}
If you want your search to look for the text, then XPath is your only option.

Deleting content from text field with Capybara

I'm writing a script that fills out text fields with Capybara, but prior to filling out the fields, I want to ensure that the fields are empty and that text is not autofilled. Basically, I'm looking for the opposite of
(Object) fill_in(locator, options = {}) #empty_content_of? delete?
found here: http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Actions. Advice?
For me only this solution worked:
fill_in('Foo', with: 'bar', fill_options: { clear: :backspace })
I have Vue.js on frontend.
After struggling with this, I asked a coworker and the solution was to use the following:
fill_in(locator, with: "")
So, for example:
fill_in "Name", with: ""
This makes perfect sense and is probably intuitive to many, but I was stumped and couldn't find an answer on SO so I thought I would post about it in case it helps anyone.
you can use the native selenium bindings to clear an input field without filling in an empty string
element = find('locator')
element.native.clear
I prefer this option rather than fill_in.
Also if you think about it fill in is limited to find your locator by label or name so if it doesn't have a label or name you still have to use find
A solution that works for me and has always been reliable:
field = find('locator')
field.value.length.times { field.send_keys [:backspace] }
In Capybara terms of mimicking a user's behaviour, this also seems a correct way to me of doing that.
For React you've got to do more than that. fill_in field, with: '' does native.clear. Which doesn't play nicely with React. As doesn't fill_in field, with: 'some text'. Since it does arguments[0].value = '' before typing text.
I've run into the issues with react-datetime. What I've settled with is:
def fill_in_react_datetime n, options
with = options[:with] == '' ? '' : format_date(options[:with])
fill_in n, with: with, fill_options: {clear: [[:control, 'a'], :delete]}
end
Building on the accepted answers, you can optionally pass with: nil:
e.g.
fill_in("search-input", with: nil, fill_options: { clear: :backspace })
I prefernil over an empty string ("") simply for explicitness. I am explicitly not setting the value and clearing with backspace. Makes for an understandable test.