Weak failure trace when using page object pattern with spock and geb - spock

When using spock+geb you can assert that you are on expected page by assertion e.g.:
assert title == 'Sign In'
and you get a nice failure trace if assertion fails:
Condition not satisfied:
title == 'Sign In'
| |
Login false
5 differences (28% similarity)
(Lo)g(i--)n
(Si)g(n I)n
But if I try to use page object pattern e.g.:
class LoginPage extends GebPage {
static at = { title == 'Sign In' }
}
Trace is not very helping what's going wrong:
Condition not satisfied:
at(LoginPage)
|
false
Is there any way how to use page object pattern and get more descriptive failure trace ?

According to geb mailing list responses the current workaround is:
static at = { assert title == 'Sign In'; true }
Thanks to David & Luke.

Offhand, I'm not sure if I have an answer to your question. I believe I had a similar question at some point, but other issues became more important after time (such as the fact that WebDriver is a POS). You won't find Stackoverflow to be much use when it comes to new & emerging libraries, such as Geb.
Your best bet is to post a message on Geb's mailing list instead. You can find it here.
Luke Daley, the creator of Geb, usually responds to messages on a daily basis & is extremely helpful. The mailing list is quite useful, even though the number of members is small at this point.

Related

Is there any way to run perticular scenario in karate more than one time if specific condition met true?

I want to run my perticular scenario or feature file more than one time.
Let's say if user enter 5 then i want my url to be hit 5 times.
is it possible in karate? Any help would be appreciated
Yes, read the docs: https://github.com/intuit/karate#loops
But also see example below using dynamic scenario outlines:
EDIT: using a Background will not work in Karate 1.3.0 onwards, please refer to this example: https://stackoverflow.com/a/75155712/143475
Background:
* def fun = function(i){ return { name: 'User ' + (i + 1) } }
* def data = karate.repeat(5, fun)
Scenario Outline:
* url 'http://httpbin.org/anything'
* request __row
* method post
Examples:
| data |
So run this, see how it works and study how it works as well.
Note that data driven features is an alternate approach where you can call a second feature file in a loop. So for example after using karate.repeat() 5 times like in the above Background, you use data as the argument to a second feature file that hits your url.

Why am I getting stackoverflow exception when calling a function twice?

I have a selenium UI test written with F# (using canopy selenium nuget package). I have a module that defines page selectors and helper functions. The page module is called by a test module. Within the test module, I am calling a function called 'handlemobimodals()', which runs four sub functions (if/else code blocks) that look for the existence of an element on a page and click on it, if it exists.
The problem I'm facing is that when the 'handlemobimodals()' function is called for a second time within the test, I get a Stack Overflow Exception (WebDriver Process is terminated due to StackOverflowException), right after its first sub function is called.
The function runs completely fine for the first time (called indirectly from another function earlier in the test), but fails the second time when called directly in the test. I'm pretty new to F# and I can't figure out how I'm causing a recursion in my test as the stackoverflow exception suggests.
Any insights would be greatly appreciated.
Snippet from Page Module:
module some_page
let isOKGotItDisplayed () =
isDisplayed <| "div.action-button.dismiss-overlay"
let clickOKGotit() =
if isOKGotItDisplayed() = true then
click "OK, GOT IT"
describe "OK, Got It clicked"
else describe "Got nothing"
let isGoToSearchDisplayed() =
isDisplayed <| "button:contains('Go to Search')"
let clickGoToSearch() =
if isGoToSearchDisplayed() = true then
click "button:contains('Go to Search')"
describe "go search button clicked"
else describe "Got nothing"
let isSkipDisplayed() =
isDisplayed <| "#uploadPhotos > div.continue.skip"
let clickSkip() =
if isSkipDisplayed() = true then
click "Skip"
describe "Skip link clicked"
else describe "Got nothing"
let mobiOkayGotItDisplayed () =
isDisplayed <| "Okay, got it"
let mobiOKGotit() =
if mobiOkayGotItDisplayed() = true then
click "Okay, got it"
describe "Okay, got it"
else describe "Got nothing"
let handleMobiModals() =
clickSkip()
clickOKGotit()
clickGoToSearch()
mobiOKGotit()
loginForPathAs user =
username << "somename"
paswword << "somepassword"
handleMobiModals()
Snippet from Test Module (note the first instance of the handleMobiModals function is called in the LoginforPathAs function, which is defined in the same page definition module):
module_sometest
open some_page
"Test 001: Log in and do something" &&& fun _ ->
newBrowser platform
loginForPathAs user1
displayed quicknoteSendButton
click quicknoteSendButton
handleMobiModals ()
displayed "Subscribe"
Note: Snippets are edited for simplicity and clarity.
It's not a direct answer, but I believe it would help to find the problem much easier. I did notice something that makes it somewhat difficult to debug this problem. You're calling multiple functions from another function, and calling this single function from a test. Splitting out these functions into separate tests and changing the tests into WIP mode should help to pinpoint your issue. There are a lot of possible points of failure within that one test.
For instance, you can use before(fun _ -> some function(s) here) or once(fun _ -> some function(s) here) within your context in Canopy to start a new browser and login, separating that part from the test.
This issue appears to have resolved itself. I believe my most recent auto-update for Chrome fixed the problem.

How to prevent rollbar from reporting SEO crawlers activities?

I have setup rollbar in my rails application. It keeps reporting recordnotfound which is as a result of SEO scrawlers (i.e Google bot, Baidu, findxbot etc..) searching for deleted post.
How to prevent rollbar from reporting SEO scrawler activities.
TL;DR:
# ./initializers/rollbar.rb
#
# https://stackoverflow.com/questions/36588449/how-to-prevent-rollbar-from-reporting-seo-crawlers-activities
#
# frozen_string_literal: true
crawlers = %w[Facebot Twitterbot YandexBot bingbot AhrefsBot crawler MJ12bot Yahoo GoogleBot Mail.RU_Bot SemrushBot YandexMobileBot DotBot AppleMail SeznamBot Baiduspider]
regexp = Regexp.new(Regexp.union(*crawlers).source, Regexp::IGNORECASE)
Rollbar.configure do |config|
ignore_bots = lambda do |options|
agent = options.fetch(:scope).fetch(:request).call.fetch(:headers)['User-Agent']
raise Rollbar::Ignore if agent.match?(regexp)
end
config.before_process << ignore_bots
...
end
======================
Be careful with magic comment frozen_string_literal and use =~ instead of match? if you have Ruby version less than 2.3.
Here I use an array that will be transformed into regexp. I did this because I wanted to prevent syntax and escaping related errors of developers in future and add ignorecase thing for same reason.
So in regexp you will see a Mail\.RU_Bot, instead of anything wrong.
Also in your case you can use simply word bot instead of many crawlers, but be careful with unusual user-agents. In my case, I want to know all crawlers on my site, so I came up with this solution. Yet another example of working part: there are crawler and crawler4j on my production site. I use just crawler in array to prevent notifing for both of them.
Last thing I want to say — my solution is not very optimal, but it just works. I hope someone will share an optimized version of my code. That's also the main reason I recommend to send data asynchronously, i.e. use sidekiq, delayed_job or whatever you want, don't forget to check related wikis.
My answer is based on #AndrewSouthpaw's solution (?), that wasn't working for me. Hoping that approved wiki-copy-pasted #Jesse Gibbs will be moderated some way.
=======
EDIT1: it's nice idea to check the https://github.com/ZLevine/rollbar-ignore-crawler-errors repo if you need to prevent rollbar to notify on js.
Looks like you are using rollbar-gem, so you'd want to use Rollbar::Ignore to tell Rollbar to ignore errors that were caused by a spider
handler = proc do |options|
raise Rollbar::Ignore if is_crawler_error(options)
end
Rollbar.configure do |config|
config.before_process << handler
end
where is_crawler_error detects if the request that led to the error was from a crawler.
If you are using rollbar.js to detect errors in client-side Javascript, then you can use the checkIgnore option to filter out client-side errors caused by bots:
_rollbarConfig = {
// current config...
checkIgnore: function(isUncaught, args, payload) {
if (window.navigator.userAgent && window.navigator.userAgent.indexOf('Baiduspider') !== -1) {
// ignore baidu spider
return true;
}
// no other ignores
return false;
}
}
Here's what I did:
is_crawler_error = Proc.new do |options|
return true if options[:scope][:request]['From'] == 'bingbot(at)microsoft.com'
return true if options[:scope][:request]['From'] == 'googlebot(at)googlebot.com'
return true if options[:scope][:request]['User-Agent'] =~ /Facebot Twitterbot/
end
handler = proc do |options|
raise Rollbar::Ignore if is_crawler_error.call(options)
end
config.before_process << handler
Based on these docs.

Prestashop all translatable-field display none for product page

Just new in Prestashop (1.6.0.6), I've a problem with my product page in admin. All translatable-field are to display:none (I inspect the code with chrome).
So when I want to create a new product I can't because the name field is required.
I thought that it was simple to find the .js whose do that but it isn't.
If somebody could help me, I would be happy.
Thank you for your help
Hi,
I make some searches and see that the function hideOtherLanguage(id) hide and show translatable-field element.
function hideOtherLanguage(id)
{
console.log(id_language);
$('.translatable-field').hide();
$('.lang-' + id).show();
var id_old_language = id_language;
id_language = id;
if (id_old_language != id)
changeEmployeeLanguage();
updateCurrentText();
}
When I set the Id to 1 (default language), it works. It seems that when I load the page, the function is called twice and the last calling, the id value is undefined. So the show() function will not work.
If somebody could help me. Thank you.
In my console, I see only one error
undefined is not a function.
under index.php / Line 1002
...
$("#product_form").validate({
...
But I find the form.tpl template and set this lines in comment but nothing change.
EDIT: According to comment on this link http://forge.prestashop.com/browse/PSCFV-2928 this can possibly be caused by corrupted installation file(s) - so when on clean install - try to re-download and reinstall...
...otherwise:
I got into a similar problem - in module admin page, when creating configuration form using PrestaShop's HelperForm. I will provide most probable cases and their possible solutions.
The solution for HelperForm was tested on PS 1.6.0.14
Generally there are 2 cases when this will happen.
First, you have to check what html you recieve.
=> Display source code - NOT in developer tools/firebug/etc...!
=> I really mean the pure recieved (JavaScript untouched) html.
Check if your translatable-fields have already the inline style "display: none":
Case 1 - fields already have inline style(s) for "display: none"
This means the template/html was already prepared this way - most probably in some TPL file I saw codes similar to these:
<div class="translatable-field lang-{$language.id_lang}"
{if $language.id_lang != $id_lang_default}style="display:none"{/if}>
Or particularly in HelperForm template:
<div class="translatable-field lang-{$language.id_lang}"
{if $language.id_lang != $defaultFormLanguage}style="display:none"{/if}>
Case 1 is the most easy to solve, you just have to find, where to set this default language.
Solutions
HelperForm
Look where you've (or someone else) prepared the HelperForm object - something like:
$formHelper = new HelperForm();
...
Somewhere there will be something like $formHelper->default_form_language = ...;
My wrong first solution was to get default form language from context - which might not be set:
$this->context->controller->default_form_language; //THIS IS WRONG!
The correct way is to get the default language from configuration - something like:
$default_lang = new Language((int)Configuration::get('PS_LANG_DEFAULT'));
$formHelper->default_form_language = $default_lang->id;
...this particularly solved my problem...
Other form-creations
If there is something else than HelperForm used for form creations, the problem is still very similar.
You have to find where in files(probably tpls) is a condition for printing display:none for your case - then find where is the check-against-variable set and set it correctly yourself.
Case 2 - fields don't have inline style(s) for "display: none"
This means it is done after loading HTML by JavaScript. There are two options:
There is a call for hideOtherLanguage(), but there is wrongly set input language - that means no language will be displayed and all hidden.Solution for this one can be often solved by solving Case 1 (see above). In addition there can be programming error in not setting the after-used language id variable at all... then you would have to set it yourself (assign in JavaScript).
Some script calls some sort of .hide() on .translatable-field - you will have to search for it the hard way and remove/comment it out.
PS: Of course you can set the language to whatever you want, it is just common to set it to default language, because it is the most easier and the most clear way how to set it.

Parse arbitary user input [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 6 years ago.
Improve this question
I have a database full of messages from a bulletin board. The board uses BB codes as formatting style. I.e.:
I'm not formatted
This is [b]bold[/b] text
Tags can also [i][b]be[/b] nested[/i]
And the [b]nesting [i]can be[/b] rather[/i] ugly
My ultimate goal is to convert these messages to some well formed XML (no discussion here ;) ). I don't want to use regular expression, which will fail at some point (in fact: it does).
First step: parse a message into some kind of internal representation (a graph, a tree, etc.). And I'm stuck at this point. The actual extraction is not that big problem, but the storage is.
How do I represent this kind of markup into some meaningful structure. My problem seems to be similar (or almost identical) to a browser building a DOM from a HTML file. So I think there are some strategies to solve it. I know the solution will not be perfect but im willing to invest a vast amount of time to do build the best possible.
Question: Do you have any tips/hint/comments? Any articles or paper you can recommend? Or a book which discusses these topic? I'm grateful for any input.
And the [b]nesting [i]can be[/b] rather[/i] ugly
I've written a parser very similar to what you are looking to do except that it would throw an error on your fourth example. Something to the effect of "Unexpected end tag [/b] within [i]".
I think that what you want to do is very doable but internally you will want to create a tree as if your original text was:
"And the [b]nesting [i]can be[/i][/b][i] rather[/i] ugly". (I don't think this would be necessary if you didn't need to convert it to XML later. If there were no need to convert to XML you could keep a linked list of text sections where each section is marked with its format combination)
Two possible approaches to this problem come to mind (of course there could be better possibilities). 1) Preprocess and insert the missing end and begin tags where necessary. 2) Build your parse tree and where there are overlapping tags imply the missing ones based on the current context. I think approach number (2) would be simpler and cleaner.
You could model your tree based on a composite pattern where you have an AbstractElement class, a TextElement class that extends AbstractElement, and a Tag class that extends AbstractElement and contains a list of sub-elements of type AbstractElement.
You would start by creating a root Tag instance. You would then call rootTag.parse(text). You would need a scanner that could return 3 types of tokens: text, start-tags, and end-tags. The scanner would allow you to push tokens onto it, which it would return before any normal scanned token. This would allow you to push new start tag tokens on after encountering and dealing with the unexpected end tag. You would also have to know when you are done with input. I'll use a 4th token type for that.
/* methods within class Tag */
public void parse(String text) {
MyScanner scanner = new MyScanner(text);
parse(scanner);
}
/* returns next token */
private Token parse(MyScanner scanner) {
Token firstToken = scanner.getNextToken();
return parse(scanner,firstToken);
}
private Token parse(MyScanner scanner) {
Token firstToken = scanner.getNextToken();
return parse(scanner,firstToken);
}
private Token parse(MyScanner scanner, Token token) {
while (!token.isDone() && !token.isEndTag()) {
if (token.isStartTag()) {
Tag subTag = new Tag(token.getValue());
token = scanner.getNextToken();
token = subTag.parse(scanner,token);
addElement(subTag);
}
else {
TextElement text = new TextElement(token.getValue());
addElement(text);
token = scanner.getNextToken();
}
}
if (token.isEndTag()) {
if (!token.getValue().equals(getName()) {
scanner.push(new Token(Token.START_TAG,token.getValue()));
}
else {
token = scanner.getNextToken();
}
}
return token;
}
So if you were to parse "And the [b]nesting [i]can be[/b] rather[/i] ugly", The following should get created.
rootTag.parse should be adding:
TextElement: "And the "
Tag: "b"
TextElement: "nesting "
Tag: "i"
TextElement: "can be"
(... at this point the odd [/b] is encountered ...)
(... push "i" start tag on the scanner ...)
(... here the [/b] is encountered (again) ...)
Tag: "i" (this was scanned because it had been pushed to the scanner)
TextElement: " rather"
TextElement: " ugly"
Note: Coding within a text area does not lend itself well to testing and debugging. Accept this answer as a hint or a possibility, not as your definate answer.

Resources