In the UI, i click on button it displays the some details in new window. In this data appears in grid/table format. I'm using Selenium IDE to record & export the testcase in perl. But i'm unable to read/store those grid/table contents. How can i do it ? Can you please let me know ?
Is it possible to do it with the help of IDE commands (like getting the total number of rows & columns) ? I could only retrieve the value of the particular cell. But xpath changes for every cell, so even i can't iterate it too. Any possible ways ?
The IDE doesn't produce very maintainable tests, when I last used it there was an 'export as perl' option - use that instead of trying to convert the grid/table yourself.
If you can I'd suggest looking at using Test::WWW::Selenium::More instead, you can write very clean and modular test code like this:
use Test::Most;
use Test::WWW::Selenium::More;
my $s = Test::WWW::Selenium::More->new(
host => "localhost", # selenium server host
port => 4444, # selenium server port
browser => "*firefox",
browser_url => "http://www.google.com",
);
$s->open_ok("http://www.google.com", undef, "fetched G's site alright");
$s->type_ok( "q", "hello world");
$s->click_ok("btnG");
$s->wait_for_page_to_load_ok(5000);
$s->title_like(qr/Google Search/);
done_testing;
Have a read of the Manual and Test::WWW::Selenium which this is an extension of (anything you can to in Test::WWW::Selenium you can do in ::More).
Related
Below are the additional bullets :
I can get my "button" with following code :
$elem = $driver->find_element('//*[#id="file_uploader"]/div/div/div/div[1]/div[1]/div/span');
$driver->mouse_move_to_location(element => $elem); # xoffset => x, yoffset => y
$driver->click_ok('LEFT');
$driver->pause(3000);
But after that, I can't get anything in Opened Window which appears . How is it possible to upload a file?
PS: Here screenshot of my Developper Tools.
In Blue
Thanks in advance !
Selenium can not deal with OS dialogs. Therefore there is no way to deal with this dialog. This means you need to upload a file without opening it.
Luckily Selenium allows the user to send the filepath to the file input. This will upload the file.
In order to make it work you first need to find the input element instead of the button. It'll look something like:
<input type='file'>
Once you've found this element you can send the filepath to it like you would send any text to a textfield. I'm not sure how to do this in perl, but in Python you can achieve it like this:
element.send_keys('path/to/file')
You'll probably know yourself what the perl equivalent is.
In fact, it's more specifical. I have two ways to upload a file in my web application :
First user can use a button 'select file'.
Second you can drop directly file .
By second way, and using "upload_file" method in Selenium::Remote::Driver package as it was proposed here, it's possible. I do that :
my $fname = "D:/dev/tests/selenium/phantomjs-2.1.1-windows.zip";
my $remote_fname = $driver->upload_file( $fname );
my $element = $driver->find_element( '//*[#id="file_uploader"]/div/div/div/div[1]/div[2]/input[#class="dx-fileuploader-input"]' );
$element->send_keys( $remote_fname );
But not with my "button".
How is it possible ? I'm forwarding you additional screenshots here :
In red 'button' and blue 'drop file'
I'm developing a simple bpel process that takes data from an external file (txt or xml).
In detail, i'm trying to develop a process that takes in input 2 strings (user and pass) and checks if they are in my "Account" file. If so, output return 'true', if not 'false'.
I'm using eclipse and i can't find anything that could help me. I read something about 'file adapter', but, in eclipse, palette view doesn't show this option. Any idea ?
There are two possibilities:
If your BPEL engine supports XPath 2.0, you can use the doc() function to load an XML document and look for certain entries.
doc("users.xml")/users/user[#id = $uid and #password = $password]
should return the user node where id and password attributes match the values stored in the BPEL variables $id and $password. You can place that expression in an if activity.
If your engine does not support XPath 2.0 and you need to stick to standard BPEL, you should write a simple Web service that performs the lookup. Use an invoke activity to call this Web service.
I'm currently writing some perl scripts to test one of our GUI applications. I'm using perl's Win32::GuiTest as a foundation, and it's pretty functional for the most part. However, I am now stuck trying to get data out of a grid control (not sure what the actual name of the widget is since this is supposed to be black-box testing). Using WinSpy++, I can see that it's class is "AfxWnd42s", whatever that means. I can get the window handle with this code:
#
# check that listed ports match the spec for this model
#
my #portgrids = FindWindowLike($win,undef,"AfxWnd42s");
if(not #portgrids){ die "can't find port grid"; }
for(#portgrids){
my $styles = GetWindowLong($_,Win32::GuiTest::GWL_STYLE());
my $text = WMGetText($_);
$wintext = GetWindowText($_);
printf("static w=%x, s=$wintext, style=%x text=<<$text>>\n",$_,$styles);
}
Neither text, nor wintext contain any value, even though there is data in the grid control. I've tried a number of different options to GetWindowLong, but nothing seems to return anything about the contents of the grid. Also, The windows I'm scanning have no children. I'm stuck.
Unfortunately I don't have access to the code or the dev environment to build the application. I can only go by what WinSpy++ tells me about the window components.
I have a run mode in my CGI::Application web-app that I would like to be able to trigger from the command line so i can automate it. From the web-app's perspective it does some processing then sends the results in an email.
When called from the web interface it passes in a set of parameters (email address, which query to run, date, etc) so these need to be passed in.
How can I construct a call to the CGI::Application app that will be the same as if I ran it from the web?
The original CGI specification makes it easy to run things from the command line and was fully intended not as a specific HTTP-only interface but something that could handle FTP and gopher as well as new top-level URL schemes. I know what I wanted when I helped specify it.
The spec I referenced should give you all you need, but for the most part it is just a collection of environment variables. If you see a request for:
http://some.server.com/some/path?a=b&c=d
The environment variables come out looking like this:
SERVER_PROTOCOL=http
REQUEST_METHOD=GET
HTTP_HOST=some.server.com
SERVER_PORT=80
PATH_INFO=/some/path
QUERY_INFO=a=b&c=d
To reverse the polarity of that in Perl would go something like this:
$ENV{'SERVER_PROTOCOL'} = 'http';
$ENV{'REQUEST_METHOD'} = 'GET';
$ENV{'SERVER_PORT'} = 80;
$ENV{'PATH_INFO'} = '/some/path';
$ENV{'QUERY_INFO'} = 'a=b&c=d';
system("perl your-CGI-script.pl");
Things get a bit more complicated in handling POST queries and there are more possible environment variables that may be required. Worst case you can enumerate them all with a quick CGI script something like:
print "Content-Type: text/plain\r\n\r\n";
foreach (keys(%ENV))
{
print "$_=$ENV{$_}\r\n";
}
Now put that on the web server in place of your CGI script and you'll see all the environment that gets passed in (and the original environment so you'll need to make a few judgement calls).
Upon further digging through the CGI::App and the CGI documentation, it appeared to be more straightforward than I thought. The simplest case (no real argument handling or dealing with the output from the webapp run call) is:
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use WebApp;
my $cgi = new CGI( \%{#ARGV} );
my $webapp = WebApp->new( QUERY => $cgi );
$webapp->run();
It just takes a series of space separated name value pairs to create the CGI. You need to pass in the run mode and all the arguments.
I'm the maintainer of CGI::Application, and I do this all the time-- I have dozen of cron scripts built with CGI::Application because it's convenient to share the infrastructure with the application.
The simplest approach is this:
# There is no browser to return results to.
$ENV{CGI_APP_RETURN_ONLY} = 1;
my $app = WebApp->new;
$app->direct_run_mode_method;
In that example, you bypass the normal flow and call a method directly. Be sure you don't need any of the "setup" or "teardown" actions to happen in that case.
If you just have one run mode you are calling, you can also just set the "start_mode", and call run(), so then the default run mode is called by default.
Another idea: you can use a module like Getopt::Long and pass in values through the PARAM hash to new(), or completely replace the run-mode selection process. Here's an example where command line flags are used to determine the run mode:
sub setup {
my $self = shift;
$self->start_mode('send_error_digests');
$self->run_modes([qw/
send_error_digests
help
/]);
my ($dry_run, $help);
GetOptions(
'dry-run' => \$dry_run,
'help' => \$help
);
$self->param('dry_run' => $dry_run);
$self->mode_param(sub {
return 'help' if $help;
return $self->start_mode();
});
}
Thusly:
$ perl yourscript.pl field1=value1 field2=value2
Perl's CGI library takes care of the magic for you, and it appears that CGI::Application relies on CGI (judging from their example code).
Instead of having to go through CGI::Application every time you want to get something done, enforce a proper separation of concerns, perhaps using an MVC setup. All of the functionality should exist outside of the CGI::Application stuff since that should only work as a controller. Once you separate out those bits, you can easily write other controllers for other input methods.
Don't write a web application; write an an application that happens to have a web interface. When you have that, you can easily give your application other sorts of interfaces.
You could automate by calling the web app using curl, wget, or an LWP GET-script with the appropriate parameters. I've used a similar system for cron-driven tasks with a Catalyst application.
That deals with all the environment variables for you..
How can a I guarantee that no pop-up dialogs will appear when I automate Microsoft Excel through OLE? I'm using a Perl module (Win32::OLE). I can avoid most dialog pop-ups using the following code:
use Win32::OLE;
use Win32::OLE::Variant;
use Win32::OLE::Const;
my $excel_symbols = Win32::OLE::Const->Load('Microsoft Excel');
my $excel = Win32::OLE->new('Excel.Application', sub { $_[0]->Quit();} );
$excel->{'Visible'} = 0;
$excel->{'DisplayAlerts'} = 0;
$excel->Workbooks->Open('c:\some_excel_file.xls',
{ 'UpdateLinks' => $excel_symbols->{'xlUpdateLinksNever'},
'ReadOnly' => 1,
'IgnoreReadOnlyRecommended' => 1
});
However for some files, I continue to get a dialog with the following text:
This file is not a recognizable
format.
If you know the file is from another program which is incompatible with
Microsoft Excel, click Cancel, then
open this file in its original
application. If you want to open the
file later in Microsoft Excel, save it
in a format that is compatible, such
as text format.
If you suspect the file is damaged, click Help for more information about
solving the problem.
If you still want to see what text is contained in the file, Click OK.
Then click Finish in the Text Import
Wizard.
OK Cancel
Sometimes a similar dialog appears that contains 'OK', 'Cancel' and 'Help' buttons.
I cannot control the quality of files that are provided to the scripts.
You could consider using Spreadsheet::ParseExcel (albeit it may lack features you need) or Apache POI (albeit it will need some wrapping to use in a Perl script) instead of calling the Excel engine over OLE. That way you won't get any Excel-generated dialogs.
I revisited this issue and found a solution.
Copy the file before processing to a temporary location. Then save the file before closing it in Excel:
File::Copy::copy('c:\some_excel_file.xls', 'c:\temp\SFO3jfd.xls');
my $book = $excel->Workbooks->Open('c:\temp\SFO3jfd.xls',
{ 'UpdateLinks' => $excel_symbols->{'xlUpdateLinksNever'},
'ReadOnly' => 1,
'IgnoreReadOnlyRecommended' => 1
});
$book->Save();
$book->Close();
Why this works:
Excel 2003 automatically recalculates the formulas in documents that were created in an older version of Excel. Furthermore, macros could be invoked when the document is opened. All of this means that there could be changes made on a document, even though your script doesn't perform any such operations.
By saving the document before closing, you avoid the dialog requesting that you save the file. Using a temporary file ensures that the original file does not get changed during the validation operation. If you aren't concerned about this, you might consider validating in-place.
Here is full documentation for Open method. I wonder if CorruptLoad parameter is what you need.
If you are trying of process all xl files in the tree, some of them may be open by other users and have the ~ prefix.