Monday, April 26, 2010

How keyPressNative works on Selenium

Lately I had been facing an issue to simulate a functionality with Selenium. The functionality was of Auto Complete feature. [Yes, just like you see when typing something in Google search box].

I tried to use type command, but it just placed the value into the text field and Auto Complete feature was not showing up.

After banging my head with code and different functions I was finally able to find something that I would like to share with all. [Guys, my understanding can be wrong as well, so please correct me If I am wrong, and leave a comment regarding the same].

There are two types of code:

a. char code
b. key code

Consider we have two char 'a' and 'A'. Now, simplest way to differentiate between char code and key code is that, both 'a' and 'A' have same key code but different char code.

Does it make any sense to you? If not read it again. This time one word at a time, and slowly.

"char code for 'a' and 'A' are different, but keycode for both of them is same. "

Selenium key_press_native accepts the ascii code for the char that you want to type in. But internally it matches it with the keycode of the char and therefore when you try to type in 'A' or 'a' [with their ascii values], you will see different results as selenium will not be able to find the key code for 'a'.

Similar issue is faced while typing in the value for keys that require us to press SHIFT key. e.g. To type in #, we have to do first press 'SHIFT' and then press numeric '3'. Similarly fr & we need to press first 'SHIFT' and then '7'.

so the solution that I used finally for this was as follows:

Algo:

1. Prepare a hash map for special symbols, that require us to press SHIFT before using them. The key here would be the symbol and value would be the ascii code for the key that is to be pressed after pressing shift.

2. For UPPERCASE char also, we need to press first of all the 'SHIFT' key and then the key that is to be pressed.

so let us write down a small function doing this trick for us.

I am Perl guy, so do not mind me writing the code with Perl reference here.


sub type_some_text {
my ($class, $locator, $text) = @_;

#Key press native function do not need a locator. So to make selenium type in the correct inbox field, we need to focus on that field first.

$selenium->focus($locator);

my $ascii_map = (
SHIFT => 16,
':' => 59,
'<' => 44,
'>' => 46,
'?' => 47,
'"' => 222,
'_' => 45,
'+' => 61,
'{' => 91,
'}' => 93,
'(' => 57,
')' => 48,
'&'=> 55,
'%'=> 53,
'*'=> 56,
'$'=> 52,
'!' => 49,
'@' => 50,
);
my $upper_case = 0;
my $special_char = 0;
my @char_arr = split(//, $text);
foreach my $char (@char_arr) {
if($char ne lc($char) {
$upper_case = 1;
}
if($ascii_map{$char}) {
$special_char = 1;
}
if($upper_case || $special_char) {
$selenium->key_down_native($ascii_map{'SHIFT'});
}
if($ascii_map{$char}) {
$selenium->key_press_native($ascii_map{$char});
}else {
$selenium->key_press_native(ord(uc($char)));
}
if($upper_case || $special_char) {
$selenium->key_up_native($ascii_map{'SHIFT'});
}
}
}

Now with the above stated function, we can simulate the key strokes,and therefore the Auto Complete feature.

Hope it was of some help.

Thanks,
Rajat Jindal
http://quicksilver1183-tech.blogspot.com
http://quicksilver1183.com

Tuesday, April 6, 2010

Configuring ActiveMQ with Perl

By default ActiveMQ is configured to start the browser for C++, Java, C# etc by using Messaging protocol as Openwire. But to make it work with Perl we need couple of things to do as below:

1. First of all we need a client to handle the requests [Both pushing and retrieving]. We can download Net::Stomp library from CPAN. This is a very simple implementation to send and receive messages using STOMP Protocol.

2. We need to configure transport Connectors in file activemq.xml to use STOMP instead of openwire which is used by default as follows:

<transportConnectors>
<transportConnector name="openwire" uri="tcp://localhost:61616"/>
</transportConnectors>

to

<transportConnectors>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61616"/>
</transportConnectors>

3. If you are using activeMQ version 5.3.1 and above, there is a strong probability that your webconsole for admin [http://localhost:8161/admin] may not work as explained at following link [http://activemq.apache.org/web-console.html], so you need to modify the file [apache-activemq-5.3.1\webapps\camel\WEB-INF\applicationContext.xml] as follows :

<!-- configure the camel activemq component to use the current broker -->
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent" >
<property name="brokerURL" value="vm://localhost?create=false&waitForStart=10000" />
<property name="userName" value="${activemq.username}"/>
<property name="password" value="${activemq.password}"/>
</bean>

Now you are ready to start the activeMQ, just double click on the activeMQ app file at bin location, and at console you can notice that activeMQ has started.

Lets write a simple Perl script to push messages in the queue:

use Net::Stomp;
my $stomp = Net::Stomp->new( { hostname => 'QuickSilver-PC', port => '61616' } );
$stomp->connect( { login => 'system', passcode => 'manager' } );
$stomp->send(
{ destination => '/queue/example.A/', body => 'This is my first Stomp Message' } );
$stomp->disconnect;

# subscribe to messages from the queue 'example.A'
use Net::Stomp;
my $stomp = Net::Stomp->new( { hostname => 'localhost', port => '61616' } );
$stomp->connect( { login => 'system', passcode => 'manager' } );
$stomp->subscribe(
{ destination => '/queue/example.A',
'ack' => 'client',
'activemq.prefetchSize' => 1
}
);
while (1) {
my $frame = $stomp->receive_frame;
warn $frame->body; # do something here
$stomp->ack( { frame => $frame } );
}
$stomp->disconnect;

# write your own frame
my $frame = Net::Stomp::Frame->new(
{ command => $command, headers => $conf, body => $body } );
$stomp->send_frame($frame);

You can notice in your webconsole that message "This is my first stomp Message" is pushed to the queue example.A

Hope it helps.

Thanks,
QuickSilver1183
QuickSilver1183@gmail.com