Tuesday, November 18, 2008

Write user-extensions.js working for both Selenium-IDE and Selenium-Core

Sometimes we found our user-extensions.js(like include cmd)work on Selenium-Core but error on Selenium-IDE, or vise versa.

The reason is IDE and Core used 30% different js objects.

We can write below style user-extension to support both IDE and Core.
Sample:
if(IDE_MODE){
   //IDE manner
}else{//CORE_MODE
   //Core manner
}
The key function here is how to determine current mode type by javascript?
Simple workaround code:
function isIDE(){
  var locstr = window.location.href;  
  if(locstr.indexOf("selenium-ide.xul") != -1){
      //IDE mode   
      return true;
  }else{
      return false; //Core mode
  }
}

Monday, November 17, 2008

Multiple Profiles running simultaneously synchronization in SeleniumJRunner

We must assign each SeleniumJRunner a unique profile name at one time.
Otherwise, if 2 instances use the same profile name at one time, Firefox will report "Firefox is already running..." error.

Assume we have pre-created Firefox profiles on one machine with name:
testprofile1
testprofile2
testprofile3
...
testprofile9

We can lock profile name when one SeleniumJRunner is using it and unlock it when SeleniumJRunner quit. If there is no free profile name, let new SeleniumJRunner wait.

Sample code:
public static String lockAndGetAvailableProfile(String[] allProfiles) { 
  FileLock lock = null; 
  for (int i = 0; i < allProfiles.length; i++) {
   try {
    RandomAccessFile raf = new RandomAccessFile(PROFILE_LOCK_FOLDER 
                        + "/" +i+".lck" , "rw");
    FileChannel fileChannel = raf.getChannel();
    lock = fileChannel.tryLock();
    if(lock != null && lock.isValid()
       && !lock.isShared()){ 
     return allProfiles[i];
    }else{
     lock = null;
     fileChannel.close();
     raf.close();
    }
   } catch (IOException ioe) {
    ioe.printStackTrace();
   } 
  }
  return "No available profile";
}

Sunday, November 16, 2008

Daemon AutoIt3 process to click popup and alerts for Selenium

There are always all kinds of popup and alerts during selenium running. If they are not clicked out, Selenium may be blocked and timed out.

We recommend to use a free tool AutoIt3 to write daemon scripts to click out any popup. Make sure selenium run smoothly.

Sample Autoit3 scripts:
If WinExists("Alert") Then
    WinActivate("Alert")
    ControlSend ("Alert", "", "", "{SPACE}")
    ContinueLoop
EndIf

Saturday, November 15, 2008

Customize Selenium Chrome TestRunner profile in JRunner

There is a prefs.js configuration file for each Firefox profile.
Selenium Java Runner can do some necessary customization before launch Firefox TestRunner instance.
Read prefs.js docs: http://kb.mozillazine.org/Prefs.js_file

Sample prefs.js customize code:
PrintStream out = new PrintStream(new FileOutputStream(prefsJS, true));
// Don't ask if we want to switch default browsers
out.println("user_pref('browser.shell.checkDefaultBrowser', false);"); 
// suppress authentication confirmations
out.println("user_pref('network.http.phishy-userpass-length', 255);");
// Disable pop-up blocking
out.println("user_pref('browser.allowpopups', true);");
out.println("user_pref('dom.disable_open_during_load', false);");
out.println("user_pref('startup.homepage_welcome_url', '');");
// Disable Restore your session dialog. Always start a new session
out.println("user_pref('browser.sessionstore.enabled', false);");
// Disable security warnings
out.println("user_pref('security.warn_submit_insecure', false);");
out.println("user_pref('security.warn_submit_insecure.show_once', false);");
out.println("user_pref('security.warn_entering_secure', false);");
out.println("user_pref('security.warn_entering_secure.show_once', false);");
out.println("user_pref('security.warn_entering_weak', false);");
out.println("user_pref('security.warn_entering_weak.show_once', false);");
out.println("user_pref('security.warn_leaving_secure', false);");
out.println("user_pref('security.warn_leaving_secure.show_once', false);");
out.println("user_pref('security.warn_viewing_mixed', false);");
out.println("user_pref('security.warn_viewing_mixed.show_once', false);");
// Disable cache
out.println("user_pref('browser.cache.disk.enable', false);");
out.println("user_pref('browser.cache.memory.enable', true);");
// Disable "do you want to remember this password?"
out.println("user_pref('signon.rememberSignons', false);");
// Disable any of the random self-updating crap
out.println("user_pref('app.update.auto', false);");
out.println("user_pref('app.update.enabled', false);");
out.println("user_pref('extensions.update.enabled', false);");
out.println("user_pref('browser.search.update', false);");
out.println("user_pref('browser.safebrowsing.enabled', false);"); 
//enable javascript 
out.println("user_pref('javascript.enabled', true);"); 
//Optional Tips: User-Agent hijack for http traffic debug
//out.println("user_pref('general.useragent.override', 'Here crack user-agent');");  out.close();

Friday, November 14, 2008

Include JS src file in Firefox Chrome Javascript file

To include a Javascript src file in HTML, it's very simple:
<script src="scripts/b.js" type="text/javascript"></script>
However, how to implement above logic in a Chrome js file(XUL missed including b.js).
There is a XPCOM API @mozilla.org/moz/jssubscript-loader;1
Sample:
const subScriptLoader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader);
 //file:/// path for XPCOM. http:// not support
subScriptLoader.loadSubScript('file:///c:/scripts/b.js', this);
In normal js file(non-chrome), it's also simple.
Sample:
document.write('<script src="scripts/b.js" type="text/javascript"></script>');
This tip is useful for Selenium-IDE enhancement.

Thursday, November 13, 2008

Security Alerts Interceptor for Selenium-IDE

There are 2 kinds of HTTPs Certification Security Alerts in Firefox.
1) Domain name mismatch
2) Certificate expired
Read http://kb.mozillazine.org/Security_Error:_Domain_Name_Mismatch_or_Server_Certificate_Expired
Unfortunately, Firefox 2 didn't provide a preferences entry to disable or hidden alerts.
These annoyed alerts slow down selenium speed and block selenium automation if we don't click out alerts.

There is a Firefox extension Remember Mismatch Domains(RMD.xpi) to add a "Don't warn me again about this certificate for this domain" checkbox to the Domain Mismatch and Expired Certificate warning windows. When selected the domain name and security certificate domain pair (or certificate and expiration date pair) is stored in a Firefox preference and the security error dialogue will be bypassed on subsequent visits.

The author provided a XPCOM to destroy Security Alerts Window before it displays in Firefox. We can integrate this XPCOM with Selenium-IDE and provide Security Alerts Interceptor feature.

Here are steps and code:
1) copy /platform folder from RMD.xpi to selenium-ide.xpi
2) copy rmdBadCertHandler.js and rmdIBadCertHandler.xpt to /components folder
3) edit rmdBadCertHandler.js
_isRemembered: function (handler_type, target_url, cert) {
   return true;
   //intercept and kill all security alerts
   //or add a preference entry here and return true or false
   ...
}
NOTE: it is used for Firefox 2 only. Firefox 3 has a new security exception handler.

Tuesday, November 11, 2008

Selenium close all Firefox windows in profile when finish run

There is a Chrome URL parameter &close=true in Selenium-IDE. When set to true, it will automatically close Selenium Firefox windows when finish run. However, if application window has popuped child windows like ads, selenium can't close these popup windows when quit.

This has risk to lock Firefox profile when multiple Firefox profiles running simuteniously. Please refer to "Firefox is aleady running issue"
Enhance Selenium-IDE by XPCOM API: close all Firefox windows under current profile. Add logic when Selenium quit(close=true).
Sample code:
var windowManager = Components
  .classes['@mozilla.org/appshell/window-mediator;1'].getService();
var windowManagerInterface = windowManager
  .QueryInterface( Components.interfaces.nsIWindowMediator);
var enumerator = windowManagerInterface.getEnumerator( null );
var appStartup = Components
  .classes['@mozilla.org/toolkit/app-startup;1'].
  getService(Components.interfaces.nsIAppStartup);
while ( enumerator.hasMoreElements()  )
{
  var domWindow = enumerator.getNext();
  if (("tryToClose" in domWindow) 
       && !domWindow.tryToClose())
    return false;
  domWindow.close();
};
appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit);