Thanks for giving SeleniumPlus a try!
Select any of the links above ("Project Assets", "Sample Project" etc.) to go directly to an area of interest.
We welcome any feedback (both good and bad) that can help us make the test automation experience better!
When meeting any problem, please
The SAFS/SeleniumPlus Development Team
SeleniumPlus Projects, like the SAMPLE project, are intended to be portable for other users and machines with SeleniumPlus installed. The entire Project should be saved--whether to CVS, GIT, or some othe storage medium. Although the "bin" subdirectory for the Project is generally not stored since these are compiled assets.
For example, to Import a Project that has been copied or saved to the local file system:
Note: Eclipse will NOT let you have/import two projects with the same name.
Importing older SeleniumPlus projects may require you to "fix" some of the paths in that Project's Java Build Path configuration and in each test configuration INI file (Test.INI) used for testing.
Newer SeleniumPlus projects have been created with the information that follows so they are already portable to different machines. For these newer projects you should not have to "fix" anything.
The latest versions of SeleniumPlus now support 2 features to maximize (or fix) Project portability:
For more detailed information on each:
The setting can be found in the Eclipse main menu under:
New Projects created with the latest PlugIn will now automatically use this SELENIUMPLUS_HOME Classpath Variable for the Project's Java Build Paths. You can see the Project's Java Build Paths by:
Currently, you should see settings using SELENIUMPLUS_HOME like:
SELENIUMPLUS_HOME/libs/JSTAFEmbedded.jar
SELENIUMPLUS_HOME/libs/selenium-server-standalone-2.44.0.jar
SELENIUMPLUS_HOME/libs/seleniumplus.jar
To fix such a portability issue, you can replace the explicit hardcoded library paths with new ones referencing and extending the SELENIUMPLUS_HOME Classpath Variable. You can do this by:
NOTE: This setting will only work on SAFS or SeleniumPlus with installed or updated JARs dating Nov 18, 2014 or later.
The JAR files in question are:
| SAFS: | /lib/safsselenium.jar |
| SeleniumPlus: | /libs/seleniumplus.jar |
The portability setting can be found in the Test.INI as:
To fix such a portability issue, you can replace the explicit hardcoded DriverRoot path in the Test.INI with the same setting as shown above.
Right click on Maps folder of the project, click "Selenium+->Create Map" to create new App Map file.
A new App Map will be created with .map extension. User can create multiple map files to separate language-specific component recognition strings and/or test configuration data.
Examples:
In general, there is a "primary" ProjectApp.map file which holds the bulk of all recognition strings and Application Constants. Then, there can be one or more App Map files containing language-specific values used by or overriding the primary App Map values.
The AppMap.order file is a means to chain multiple App Maps to be loaded in a specific order.
Example:
; ; Order App Maps Last In First Out (LIFO) for "chaining" ; App.map App_fr.map
Normally, an App Map contains multiple "sections". One of these is [ApplicationConstants] and the remaining user-defined sections are used to define "windows" or "containers" of components.
ApplicationConstants stores all test constants and data.
; ; Constants and other data. ; [ApplicationConstants] nlsSearch="Search" url="http://www.google.com" username="anonymous" password="newpassword"
Window or Container sections hold recognition strings used to identify child components within those containers.
In a container section, the item with the same name as the container is optional.
Example:
Google="id=viewport" is optional,
See the [Login] section? There is no "Login" item in that section. The default will be assumed (See the Note below.)
;
; Component recognition:
;
; Google main page window/component recognition
;
[Google]
Google="id=viewport"
Apps="title=Apps"
Search="text={^nlsSearch}"
;
; Google's Login window/component recognition
;
[Login]
UserName="name=Email"
Password="name=Passwd"
SignIn="id=signIn"
Note:
The item with the same name as the container (ex. "Google" and "Login"), if present, MUST contain a recognition string that *will* find the parent container of the contained children. When searching for a child, the parent is sought first.
If the parent is not found, then the search for the child will NOT occur.
If the item with the same name as the container is NOT provided, the default container to search is assumed to be the topmost document of the webpage, or the topmost document in any frame or iframe that was last searched.
If there is no frame-expression in a child RS, the last visited frame will be used to find child components; the last visited frame is normally the frame defined by the parent component. If a frame expression is sepcified in a child RS, then that frame will be used to find this specific child ONLY. It will not affect other children.[TopFrameWin] TopFrameWin="FRAMEID=top_iframe" button1="id=__item23" button2="FRAMEID=other_iframe;\;id=__item23" button3="id=__item25"button1 is expected to be found in frame 'top_iframe'. button2 is expected to be found in frame 'other_iframe'. button3 is still expected to be found in frame 'top_iframe'. The DOM tree looks like below <iframe id="top_iframe"> <button id="__item23"/><-- button1 --> <button id="__item25"/><-- button3 --> </iframe id="top_iframe"> <iframe id="other_iframe"><-- a sibling frame --> <button id="__item23"/><-- button2 --> </iframe id="other_iframe">
If there are multiple levels of frame, we must define all of them in parent/child hierarchy format separated by ";\;"[ChildFrameWin] ChildFrameWin="FRAMEID=top_iframe;\;FRAMEID=child_iframe" button1="id=__item23"button1 is expected to be found in frame 'child_iframe', which is a child of frame 'top_iframe'. The DOM tree looks like below <iframe id="top_iframe"> <iframe id="child_iframe"><-- a child frame --> <button id="__item23"/> </iframe id="child_iframe"> </iframe id="top_iframe">
For child components, use supported type, property and attribute qualifiers, as necessary:
(note: these ways can ALSO be used in parent component.)
:PASM: (Property Attribute Search Mode -- Must be first, if present. See Notes.)
TYPE="DOJO"|"SAP"; (See Notes.)
ID=id;
CLASS=class;
NAME=name;
TEXT=text;
TITLE=title;
LINK=linkInfo;
PARTIALLINK=partialLinkInfo;
TAG=tagname;
INDEX=n; (1-based, NOT used alone, indicates the Nth matching item.)
ITEMINDEX=n; (1-based, NOT used alone, indicates the Nth matching list item.)
PATH=parent->child->grandchild; (NOT used alone. Path to a subitem in a List, ComboBox, Menu, Tree)
PROPERTY=propname:propvalue; (can be used with others to provide more uniqueness)
PROPERTYCONTAINS=propname:partialValue; (can be used with others to provide more uniqueness)
Notes:
Multiple qualifiers should be separated by semi-colons (";").
TYPE= is experimental and only supports "DOJO" and "SAP" at this time. Do not use.
:PASM: if used, means everything that follows is explicitly property=value pairs.
No PASM: Example 1:
MyObject="Text=Some Text;enabled=true;ItemIndex=2;"
"TEXT" and "ITEMINDEX" are known qualifiers--not property names,
while "enabled"--which is NOT a known qualifier--will be treated
as a native object property/attribute to match.
PASM: Example 2:
MyObject=":PASM:text=Some Text;enabled=true;itemindex=2;"
With ":PASM:" leading; "text", "enabled", and "itemindex" are all sought as native object
property/attribute values that must be matched.
Identify child elements by multiple native properties or attributes:
MyObject="aproperty=xxx;someattribute=yyy;anotherone=zzz"You don't need :PASM: if none of the properties or attributes have the same names as our qualifiers above.
Identify child objects using explicit XPATH or CSS:
To learn about XPATH and CSS, please refer to Xpath_Css_Groups
and Xpath_Css_Table.
MyObject="XPATH=.//div[contains(text(),'foo')]" MyObject="CSS=div:contains('foo')"
Generally, the 3 major browsers seem to support the same or similar mechanism for inspecting web page elements.
FireFox:
Chrome:
IExplore:
A Primary App Map hypothetically for Google (App.map):
;
; Constants and other data.
;
[ApplicationConstants]
nlsSearch="Search"
;
; Main Google window/component recognition
;
[Google]
Google="id=viewport"
Apps="title=Apps"
Search="text={^nlsSearch}"
;
; Google's Login window/compoent recognition
;
[Login]
Login="id=viewport"
UserName="name=Email"
Password="name=Passwd"
SignIn="id=signIn"
A French App Map to override the "Search" text in the Primary App Map (App_fr.map):
; ; Constants and other data. ; [ApplicationConstants] nlsSearch="Recherche"
There is a SeleniumPlus ProcessContainer tool that can be used to interactively capture, modify, and test recognition strings natively using the SAFS/Selenium engine with the Selenium WebDriver. This can be used instead of--or in addition to--the Browser Tools mentioned above.
Review the SeleniumPlus ProcessContainer doc for more complete usage notes.
In particular, note that Selenium and SeleniumPlus only seek components ("Find Element") in the currently identified Frame or iFrame, if frames exist. If you get "No Such Element" or "...not found." for a particular Recognition: string you believe is good, it may be we are looking in the wrong Frame.
So, when attempting "Find Element" with ProcessContainer, you must do one of the following:
Example:
Recognition: XPATH=.//*[@id='aChildComponent_id']
or
Example:
Recognition: FRAMEID=myApps_iframe;\;XPATH=.//*[@id='aChildComponent_id']
Test Design Guidelines
App Map Format Info
Historic App Map Info
Specific "Categories" and "Qualifiers" in the above docs may not (yet) be supported by SeleniumPlus.
A fundamental overview of SAFS Expression Processing.
Historically, expression processing happens on every "field" for every action or command in a SAFS "inputrecord". The JSAFS Java code that SeleniumPlus is based upon retained that functionality.
Expression processing is "ON" by default.
That is, for any String argument or parameter passed to a SeleniumPlus class "action" or "command" there will be an attempt to process that String argument for possible expressions. (Note, that calls to other libaries that are NOT in the SeleniumPlus class--like WDLibrary, SearchObject, or WebDriver--do NOT have arguments processed for expressions.)
Operators that trigger String changes in action/command arguments:
^ '(Caret) Variable Prefix
= 'Assignment operator
" 'A single Double-Quote mark
& 'String concatenate operator
+ 'Addition operator
- 'Subtraction operator
* 'Multiplication operator
/ 'Division operator
% 'Modulus/Remainder operator
( 'Open Group operator
) 'Close Group operator
We have found that most SeleniumPlus users DO NOT need or want Expression processing enabled for the majority of their "action" or "comand" calls. Until an easy "fix" is available that does not break tests for existing JSAFS and SeleniumPlus users there are two options for controlling this:
There is a (somewhat) convenient quote() method available in your TestCase or TestRun for doing this.
Example:
Because the (-) subtraction operator exists in the string we have to quote() it to avoid expression processing.
This should make enclosing these String arguments with quote() unnecessary.
Example:
Because Expressions are OFF, the (-) subtraction operator should not trigger expression processing and the argument should not need to be quoted.
; ; Constants and other data. ; [ApplicationConstants] GoogleURL="http://www.google.com"
(Note: Once you are familiar with the commands and subclasses, you don't have to type the "SeleniumPlus." prefix.
You can just type the command name or subclass name directly.)
Classes in your "current" project should automatically receive RuntimeDataAware-ness at Runtime--i.e. when the test is run. In the developer world this is called Dependency Injection. These classes will receive required object instances at runtime for doing things like retrieving values out of the runtime App Maps.
You normally don't have to think or worry about this because it happens for you behind the scenes every time you run a test. If you only use classes in your current Project, and don't reference Maps or Utility classes from other SeleniumPlus projects, then you can stop reading this and explore other sections of the Intro.
There are a few cases where you might have to provide more information for SeleniumPlus to effectively perform this dependency injection. Examples or scenarios where this is likely needed:
Classes in those "other" projects that are not the "current" project will NOT receive their normal RuntimeDataAware-ness at runtime. This can present a problem if your try to use another project's testcases, or if you try to use those other projects' Map classes:
String val = helper.Map.SomeConstant();
The call will work normally when that project is the "current" project, but it may not work correctly if it is the "other" project. You can verify this by reviewing the Debug Log after a run. The Debug Log will show which packages and classes were checked for automatic injection of RuntimeDataAware-ness. The classes in the "other" project will NOT be listed in the log.
To fix the runtime issues mentioned above:
The above example tells SeleniumPlus to check all classes in:
Recompile and Run and the issues encountered in the "other" project(s) should be resolved.
You can review the Debug Log after the Run and you should see where injecting the RuntimeDataAware classes in the "other" project(s) was attempted.
There are cases where SeleniumPlus is being asked to run in an unconventional environment. For example:
In these cases, the running Java VM may need to be seeded with System Properties giving SeleniumPlus the package or classnames it needs to correctly perform the dependency injection. These can be provided in 2 ways:
The System properties of greatest interest in these cases would be (with example values):
"safs.project.config" "C:/MyAutomation/Project/test.ini" -- test config file
"safs.test.data.aware.classes" "ev.Map;helper.Map" -- specific classes and associated packages and subpackages
"safs.test.data.aware.packages" "ev.testcases;helper.utils" -- specific packages and associated subpackages
"safs.test.data.aware.exclusions" "otherPackage;notRelatedPackage" -- packages to exclude and not inject
How many of those properties need to be provided depends on your test requirements and the Java VM Class Loader's ability to find the required classes at runtime. The SAFS/Se+ Debug Log will show if the classes and packages needing dependency injection were properly found and handled at runtime.
example:
cd c:\SeleniumPlus\SAMPLE runAutomation.bat
Note: See runAutomation.bat file for how to override App Map variables and App Map order.
SAFS and SeleniumPlus normally log a significant amount of information into the test log. This normally includes generic info as well as pass and fail information for test records.
The test INI file can be configured to change the LOGLEVEL for information sent to the logs.
The valid values for LOGLEVEL are:
; ; Test Info ; [SAFS_TEST] ... LOGLEVEL="INFO" ...
Note that "Counters" are still counting all records--including PASS and FAIL counts regardless of how the log is being filtered. However, if the LOGLEVEL is set to WARN or ERROR then the traditional test count summary that normally appears in the log will NOT be logged since they are not WARNings or ERRORs. This is a good thing for those that don't like the summary. It is a bad thing for those that do.
In SeleniumPlus we have provded some new Logging commands that allow the tester/developer to change the LOGLEVEL dynamically at runtime:
If you have reduced the logging by setting the LOGLEVEL in the INI file, or by one of the SeleniumPlus.Logging functions, you can return it to "normal" by calling:
This will enable that end-of-log test summary to make it into the log.
Only failed Asserts appear in the log. However, just like all other tests, the PASS/FAIL information increments in the test record Counters--which can be queried--will print to the log if the LOGLEVEL is set to the default "INFO".
[SAFS_DRIVER] DriverRoot="c:\seleniumplus\extra\automation"

The selenium-server will fail to start as below

User needs to remove any such read-only flags so that selenium-server can start normally.
Also, it is not recommended to push the test generated files (in folder Actuals, Logs etc.) into CVS.
The modified SeleniumPlus Eclipse IDE with the SeleniumPlus PlugIn provides many convenience features and a simplified interface for novice programmers. This includes certain levels of Eclipse interface filtering or hiding that may not be desirable for developers already comfortable with the Eclipse IDE--or even some other Java development environments.
It is possible to develop SeleniumPlus tests without these conveniences in your existing Eclipse environment or other Java IDE.
For Internet Explorer the user should make sure "Protected Mode" and the Status Bar are disabled.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BFCACHE.HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BFCACHE.FEATURE_BFCACHE subkey may or may not be present, and should be created if it is not present. Important: Inside this key, create a DWORD value named iexplore.exe with the value of 0.
1 2
String profile = "myprofile"; StartWebBrowser(URL, ID, SelectBrowser.BROWSER_NAME_FIREFOX, "30", "true", SelectBrowser.KEY_FIREFOX_PROFILE, profile);
to show a pop-up menu, and then click the item "Settings".

1 2
String datapool = "c:\\chrome_custom_data"; StartWebBrowser(URL, ID, SelectBrowser.BROWSER_NAME_CHROME, "30", "true", quote(SelectBrowser.KEY_CHROME_USER_DATA_DIR), datapool);
1 2 3
String datapool = "c:\\chrome_custom_data"; String user = "Default"; StartWebBrowser(URL, ID, SelectBrowser.BROWSER_NAME_CHROME, "30", "true", quote(SelectBrowser.KEY_CHROME_USER_DATA_DIR), datapool, quote(SelectBrowser.KEY_CHROME_PROFILE_DIR), user);
1 2 3
String datapool = "c:\\chrome_custom_data"; String user = "Profile 1"; StartWebBrowser(URL, ID, SelectBrowser.BROWSER_NAME_CHROME, "30", "true", quote(SelectBrowser.KEY_CHROME_USER_DATA_DIR), datapool, quote(SelectBrowser.KEY_CHROME_PROFILE_DIR), user);
{
#The line begins with # is considered as comment
#The preference is given as key:value, there are 3 kinds of value: string, boolean and integer.
#The string value is quoted with double-quote, while boolean and integer are not quoted.
"intl.accept_languages":"zh-cn",
"accessibility.accesskeycausesactivation":false,
"browser.download.folderList":2
}
1 2
String preferenceDataFile = "c:\\Pref.json.dat"; StartWebBrowser(URL, ID, SelectBrowser.BROWSER_NAME_FIREFOX, "30", "true", SelectBrowser.KEY_FIREFOX_PROFILE_PREFERENCE, preferenceDataFile);
{
#The line begins with # is considered as comment
#Define command-line-options as key:value
"lang":"en",
#If the command-line-options doesn't need a value, then provide an empty value as key:""
"start-maximized":"",
#"disable-smooth-scrolling":"",
#Define preferences as value of key "seplus.chrome.preference.json.key"
"seplus.chrome.preference.json.key":
{
#The preferences are given as key:value
"intl.accept_languages" :"zh-CN-pseudo",
"intl.charset_default" :"utf-8"
}
}
1 2
String preferenceDataFile = "c:\\Pref.json.dat"; StartWebBrowser(URL, ID, SelectBrowser.BROWSER_NAME_CHROME, "30", "true", quote(SelectBrowser.KEY_CHROME_PREFERENCE), preferenceDataFile);
In SeleniumPlus, We can turn on this ability when starting the browser with setting of setNetworkConditions.
Once this ability is turned on, we can manipulate (delete, set, get) the 'network condition' by the following Java APIs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
//Start the Chrome browser with an initial 'network condition'.
String networkConditions = "{ \"offline\":false, \"latency\":5, \"download_throughput\":500000 , \"upload_throughput\":500000}";
StartWebBrowser("http://www.google.com", browserId, SelectBrowser.BROWSER_NAME_CHROME, "10", "true", ChromeHttpCommandExecutor.SET_NETWORK_CONDITIONS, networkConditions);
System.out.println(WDLibrary.getNetworkConditions());
//Delete the initial 'network condition'.
System.out.println(WDLibrary.deleteNetworkConditions());
System.out.println(WDLibrary.getNetworkConditions());
//Switch to a slow connection
String networkConditionsSlow = "{ \"offline\":false, \"latency\":5, \"download_throughput\":5000 , \"upload_throughput\":5000}";
WDLibrary.setNetworkConditions(networkConditionsSlow);
System.out.println(WDLibrary.getNetworkConditions());
WDLibrary.getWebDriver().get("http://www.google.com");
SeleniumPlus Class JavaDoc
Selenium WebDriver API
SAFS Keywords Reference
SAFS Homepage on SourceForge
SAFS Test Design Guidelines
SAFS Image-Based Testing
"Update" expects that "SeleniumPlus" has already successfully installed, so the system environment %SELENUM_PLUS% has been defined correctly.
It will update the following assets to the latest level.
Before update, make sure correct Selenium+ "Update Site" preferences are enabled.
For Updating SeleniumPlus, following are the steps.

Don't worry, this is a known issue during update of the embedded JRE. Next time, when we update SeleniumPlus, we can
This script should be in folder %SELENIUM_PLUS%\extra or %SAFSDIR%\extra. If it does not exist, please get its sourcecode manually and copy it to "%SELENIUM_PLUS%\extra\".
The script usage is updateRuntime.bat [ALL|SE|SAFS], with parameter "SE" it updates SeleniumPlus, with "SAFS" it updates SAFS, with "ALL" it updates both "SeleniumPlus" and "SAFS".
So call updateRuntime.bat SE to update SeleniumPlus. If the script is not latest, we might need to call updateRuntime.bat SE twice to get SE+ really updated.
In the script, we are using "github update resource".
REM External github update resource
SET SE_LIB_UPDATE=https://github.com/SAFSDEV/UpdateSite/releases/download/seleniumplus/SEPLUS.LIB.UPDATE.ZIP
SET SE_PLUGIN_UPDATE=https://github.com/SAFSDEV/UpdateSite/releases/download/seleniumplus/SEPLUS.PLUGIN.UPDATE.ZIP
SET SAFS_LIB_UPDATE=https://github.com/SAFSDEV/UpdateSite/releases/download/safs/SAFS.LIB.UPDATE.ZIP
If automated update fails then use manual steps to update SeleniumPlus environment.
SeleniumPlus library update:
SeleniumPlus eclipse plugin update:
SeleniumPlus is packaged and delivered for a small-footprint, fast execution environment when compared to a full SAFS install. It has been optimized to provide targetted test automation support for HTML applications using Selenium WebDriver. The traditional capability to interface to other test automation tools capable of testing other technologies is intentionally removed from the SeleniumPlus install.
However, individual SeleniumPlus Projects can be configured to take advantage of SAFS and other testing tools if a full SAFS installation exists on the runtime machine. For example, if you have a hybrid application that needs both HTML *and* Flex support then you might wish to enable SAFS within the project used to test that application.
[STAF]
NOSTAF=FALSE
[SAFS_DRIVER]
DriverRoot="%SAFSDIR%"
Note how the setting uses the SAFSDIR Environment variable that MUST exist at runtime.
Your test execution won't look any different, and you should get the exact same results.
By reviewing the running processes in Task Manager you would find 2 additional processes at runtime:
Other tools, scripting languages, Command(CMD) prompts, and COM-enabled applications or languages can now:
With SAFS enabled, you can now add automation support provided by other SAFS engines like:
At this time, the most recommended alternative SAFS Engine would be the SmartBear TestComplete engine. It has received the most development support in recent years along with the SAFS/Selenium Engine.
In order to use an alternative SAFS Engine, the underlying tool--like SmartBear's TestComplete--must be properly installed on the runtime system. Consult the SAFS Install/Release Notes for information concerning configuring the particular tool for SAFS integration.
Then, we simply enable the use of the engine in the TEST.INI configuration file. The SAFS/SeleniumPlus execution runtime will automatically handle the launching and shutdown of the tool during testing.
Below is an example of enabling the SmartBear TestComplete engine in the Project's TEST.INI configuration file:
[SAFS_ENGINES]
First=org.safs.tools.engines.SAFSTC
[SAFS_TC]
AUTOLAUNCH=TRUE
HOOK="%SAFSDIR%\TCAFS\TCAFS.vbs"
ConvertSAFSInputKeysSyntax=TRUE
ConvertSAFSItemPathSyntax=TRUE
And that's it. The next time a test is run the newly configured Engine will be part of the available toolset. If the tool launches any startup window or Monitor of its own you will likely see it during the course of test execution.
Note that different tools will likely require different component recognition string syntax in the App Map. So, for example, an HTML XPATH recognition string that works for Selenium WebDriver will not work for SmartBear TestComplete. You will need to consult the information available for the chosen Engine to know how to acquire and specify App Map entries for that specific Engine.
Here are the critical settings in a test.ini:
# Settings for a remote Selenium Server # SELENIUMHOST and SELENIUMPORT are used to connect Selenium Server (standalone or hub) SELENIUMHOST=remote.server.name SELENIUMPORT=4444 (setting not required if default) # SELENIUMNODE defines the selenium nodes to run. # If SELENIUMNODE is given, SELENIUMHOST will start as a selenium hub; otherwise as a stand-alone server. SELENIUMNODE=node1:port:config1;node2:port:config2
# Selenium standalone server should run on local machine at default port 4444 # [SAFS_SELENIUM] # If nothing is specified. # Selenium standalone server should run on local machine at port 6666 [SAFS_SELENIUM] SeleniumPort=6666 # Selenium standalone server should run on machine test.machine at port 4444 # test actions will actually happen in the browser opened on machine test.machine [SAFS_SELENIUM] SeleniumHost=test.machine SeleniumPort=4444 # Selenium hub should run on machine selenium.hub.machine at port 5555 # Selenium node should run on machine node.machine at port 6666 and connecting to hub server # test actions will actually happen in the browser opened on machine node.machine [SAFS_SELENIUM] SeleniumHost=selenium.hub.machine SeleniumPort=5555 SELENIUMNODE=node.machine:6666 # Selenium hub should run on local machine at port 5555 # Selenium node should run on machine node.machine at port 6666 and connecting to hub server # test actions will actually happen in the browser opened on machine node.machine [SAFS_SELENIUM] SeleniumPort=5555 SELENIUMNODE=node.machine:6666
[SAFS_SELENIUM]
# WEB_DRIVERS is used to set the specific browser
# drivers (separated by colon :) to start with selenium server.
# The following setting means 3 drivers, IE, chrome and edge will
# start with the selenium server.
WEB_DRIVERS=explorer:chrome:MicrosoftEdge
VM parameter 'safs.selenium.web.drivers' is used to
set the specific browser drivers (separated by colon :) to start with selenium server.
The following setting means 2 drivers, IE and edge will start with the selenium server,
and in the class SampleTest, the user can test with the chrome or edge browser.
java -Dsafs.selenium.web.drivers=chrome:MicrosoftEdge SampleTest
SET CLASSPATH=
<pathTo>\seleniumplus.jar;
<pathTo>\JSTAFEmbedded.jar;
<pathTo>\selenium-server-standalone-<version>.jar
SET JAVA_EXE=<pathTo>\java.exe (JRE Java 7 minimum)
%JAVA_EXE%
-Xms512m -Xmx1g
-Djava.rmi.server.hostname=machine.intranet.com
-Dwebdriver.chrome.driver=<pathTo>\chromedriver.exe
-Dwebdriver.ie.driver=<pathTo>\IEDriverServer.exe
-cp %CLASSPATH%
org.safs.selenium.util.SeleniumServerRunner
-jar <pathTo>\selenium-server-standalone-<version>.jar
-timeout=20
-browserTimeout=60
-safs.rmi.server
In order for a remote Selenium Server to provide equivalent augmented support provided by SeleniumPlus, the remote Selenium Server must be launched in a manner that allows us to inject that support into the remote Java JVM running the Selenium Server. Consult Using Selenium Server Runner to know how.

Selenium hub Server.
The first line tells us that a selenium hub server is being started.
Selenium node Server with injected RMI server into the Selenium Server JVM.
The first 3 lines of the output tell us that RMI-server has been injected into the Selenium Server JVM;
while the 4th line tells us that a selenium node server is being started;
and the last 2th line tells us that the node has registered on hub server.

During the test, sometimes users need to manipulate the object within the browser directly, which can be
achieved by Javascript. This section explains how to execute Javascript through SeleniumPlus.
There are something we should understand. Such as the parameters of these APIs and how these Java-parameters are passed to Javascript as parameters, it is important! We don't need to understand all of them :) , the items below are listed by necessity priority:
try{
//do some javascript actions
}catch(err){
throw_error(err);
}
WebElement webelement = null;//User must assign it with a valid value. String event = "mousedown"; int timeout = 1000;//milliseconds DefaultJSEventListener listener = new DefaultJSEventListener(event); //add listener for event String listenerID = WDLibrary.addJavaScriptEventListener(webelement, event, listener); //do some mousedown related work, for example 'click' webelement.click(); //wait for event happen if(listener.waitEventFired(timeout)){ //ok, event has been fired.} //remove the listener WDLibrary.removeJavaScriptEventListener(webelement, event, listenerID);
There are something we should understand. Such as the parameters of these APIs and how these Java-parameters are passed to Javascript as parameters, it is important! We don't need to understand all of them :) , the items below are listed by necessity priority:
//set "your text" to innerHTML of Component Map.Google.SignIn WebElement we = SeleniumPlus.getObject(Map.Google.SignIn); String script = "arguments[0].innerHTML=arguments[1];"; List<Object> params = new ArrayList<Object>(); params.add(we);//arguments[0] params.add("your text");//arguments[1] SeleniumPlus.executeScript(script, params.toArray(new Object[0]));
//get innerHTML of component Map.Google.SignIn script = "return arguments[0].innerHTML;"; params.clear(); params.add(we);//arguments[0] Object result = SeleniumPlus.executeScript(script, params.toArray(new Object[0]));
//Example #1: Performing a sleep in the browser under test.
long start = System.currentTimeMillis();
String script = "var callback = arguments[arguments.length - 1];"+
"window.setTimeout(callback, 500);";
SeleniumPlus.executeAsyncScript(script);
System.out.println("Elapsed time: " + System.currentTimeMillis() - start);
//Example #2, call REST service to get a result.
try{
WDTimeOut.setScriptTimeout(1, TimeUnit.SECONDS);
JavaScriptFunctions.DEBUG_OUTPUT_JAVASCRIPT_FUNCTIONS = true;
JavaScriptFunctions.setJsDebugLogEnable(true);
String script = "try{ "
+ " var callback = arguments[arguments.length - 1];"
+ " debug('try to get registration service.');"
+ " var service = registry.getRegistrationService();"
+ " if(service==undefined){"
+ " debug('Failed to get service');"
+ " }else{"
+ " debug('we got registration service.'); "
+ " }"
+ " service.get({'user-id': 'administrator'}).done(callback).fail(callback);"
+ "}catch(error){"
+ " debug('we met exception');"
+ " throw_error(error);"
+ "}";
Object results = SeleniumPlus.executeAsyncScript(script);
System.out.println(results);
}catch(Exception e){
System.out.println(e.getMessage());
}finally{
WDTimeOut.resetScriptTimeout(0, TimeUnit.MILLISECONDS);
}
//Example #3: Injecting a XMLHttpRequest and waiting for the result: String script = "var callback = arguments[arguments.length - 1];" + "var xhr = new XMLHttpRequest();" + "xhr.open('GET', '/resource/data.json', true);" + "xhr.onreadystatechange = function() {" + " if (xhr.readyState == 4) {" + " callback(xhr.responseText);" + " }" + "};" + "xhr.send();"; //Wait result for at the most 5 seconds WDTimeOut.setScriptTimeout(5, TimeUnit.SECONDS); Object result = SeleniumPlus.executeAsyncScript(script); JsonObject json = new JsonParser().parse((String) result);
//Example #4: Synchronizing a test with an AJAX application:
Click(Map.Mail.ComposeButton);
String script = "var callback = arguments[arguments.length - 1];" +
"mailClient.getComposeWindowWidget().onload(callback);";
Object result = SeleniumPlus.executeAsyncScript(script);
Component.InputCharacters(Map.Mail.To, "bog@example.com");
SeleniumPlus.ExecuteScript(
Map.Google.SignIn, // The WebElement passed as 'arguments[0]' to the script.
"arguments[0].innerHTML=arguments[1];", // Script to set the WebElements innerHTML value.
"my text value"); // The value passed as 'arguments[1]' to set to innerHTML.
SeleniumPlus.ExecuteScript(
Map.Google.SignIn, // The WebElement passed as 'arguments[0]' to the script.
"return arguments[0].innerHTML;"); // A script to return the WebElemenbts innerHTML.
//scriptResult should get the innerHTML value returned.
String scriptResult = SeleniumPlus.prevResults.getStatusInfo();
There are some tools can record "selenium test" and store it into a file.
Selenium Builder will store it in JSON format.
Selenium IDE or SelRunner can store it in HTML format.
This kind of file contains the "selenium test" and we call these files as "Selenium Scripts".
This section explains how to execute "Selenium Scripts" through SeleniumPlus API CallScript.
JSON Script file name: C:\Automation\SharedStorage\Selenium\testGooglePage.json { "type": "script", "seleniumVersion": "2", "formatVersion": 2, "steps": [ { "type": "get", "url": "${GoogleURL}" }, { "type": "waitForElementPresent", "locator": { "type": "id", "value": "lst-ib" }, }, { "type": "waitForElementNotPresent", "locator": { "type": "id", "value": "bogus-id" }, }, { "type": "setElementText", "locator": { "type": "id", "value": "lst-ib" }, "text": "amazon official website" }, { "type": "sendKeysToElement", "locator": { "type": "id", "value": "lst-ib" }, "text": "hello" } ], "data": { "configs": {}, "source": "none" }, "inputs": [], "timeoutSeconds": 60 }
HTML Script file name: C:\Automation\SharedStorage\Selenium\testFormPage.htm <tbody> <tr> <td>open</td> <td>${baseurl}</td> <td>${FormsBrowser}</td> </tr> <tr> <td>pause</td> <td>2000</td> <td> </td> </tr> <tr> <td>captureEntirePageScreenshot</td> <td>Actuals/FormsSRTest/formsSRTest-1.png</td> <td></td> </tr> <tr> <td>click</td> <td>${Map:FormsMain:CheckBox2}</td> <td></td> </tr> <tr> <td>close</td> <td>${FormsBrowser}</td> <td> </td> </tr> </tbody>
[ApplicationConstant] GoogleURL="http://www.google.com"
[ApplicationConstant] baseurl="http://www.examples.com/forms.html" FormsBrowser="ID_FormsBrowser001" [FormsMain] CheckBox2="id=check-box-02"
[WindowName] CompName="xpath=/html/body/button"
[SAFS_DATA_SERVICE] protocol=http host=localhost port=8080 base.name=safsdata # server.url will override the 'protocol', 'host', 'port' and 'base.name' settings. #server.url=http://localhost:8080/safsdata
VM parameter 'safs.data.protocol', 'safs.data.host', 'safs.data.port', 'safs.data.base.name'. java -Dsafs.data.protocol=http -Dsafs.data.host=localhost -Dsafs.data.port=8080 -Dsafs.data.base.name=safsdata VM parameter 'safs.data.server.url', it will override the 'safs.data.protocol', 'safs.data.host', 'safs.data.port' and 'safs.data.base.name' settings. java -Dsafs.data.server.url=http://localhost:8080/safsdata
[SAFS_TEST] # ProductName, Platform, Track and Branch are used for product being tested. ProductName=Product to test Platform=OS platform Track=track name Branch=branch name
VM parameter 'safs.test.product.name', 'safs.test.product.platform', 'safs.test.product.track', 'safs.test.product.branch'.
java -Dsafs.test.product.name=productName -Dsafs.test.product.platform=OSplatform -Dsafs.test.product.track=trackName -Dsafs.test.product.branch=branchName

AUTOCOUNTABLETEST + Tests + autocountabletest + autocountabletest.testcycle + Cycle.java + autocountabletest.testsuite + Suite.java + autocountabletest.testcase + Case1.java customerSpringConfig.xmlThe test classes are listed below:
@Component
public class Cycle extends SeleniumPlus {
@Autowired
Suite suite;
@TestCycle
public void runTest() throws Throwable {
suite.runTest();
}
public static void main(String[] args) {
SeleniumPlus.main(args);
}
}
@Component
public class Suite extends SeleniumPlus {
@Autowired
Case1 case1;
@TestSuite
public void runTest() throws Throwable {
case1.runTest();
}
public static void main(String[] args) {
SeleniumPlus.main(args);
}
}
//Cases1 contains multiple 'test cases'.
@Component
public class Cases1 extends SeleniumPlus{
//We MUST use @Autowired to annotate this class itself, it will be used to call test method annotated by @TestCase
@Autowired
private Cases1 self;
@TestCase
public void case1(){
//test codes ...
}
@TestCase(skipped=true)//This test case will be skipped
public void case2() throws Throwable {
//test codes ...
}
@TestCase
public void case3(){
//test codes ...
}
//In TestCase class, other methods are annotated by '@TestCase', then we DO NOT annotate runTest() by '@TestCase'
public void runTest() throws Throwable {
//We MUST use the field 'self' annotated by @Autowired to call test method annotated by '@TestCase'
self.case1();
self.case2();
self.case3();
}
public static void main(String[] args) {
SeleniumPlus.main(args);
}
}


@Component
public class Cases1 extends SeleniumPlus{
@Autowired
private Cases1 self;
//This test case will be skipped
@TestCase(skipped=true, skippedMessage="why test case is skipped")
public void case1() throws Throwable {
//test codes ...
}
@TestCase
public void case2(){
//Throw SAFSTestLevelFailure with one failure message
if(!SeleniumPlus.VerifyFileToFile("benchFile.txt", "actualFile.txt")){
throw new SAFSTestLevelFailure("benchFile.txt doesn't match actualFile.txt.","detailed failure message.", "DIFF");
}
}
@TestCase
public void case3(){
//Throw SAFSTestLevelFailure with multiple failure messages
SAFSTestLevelFailure testLevelFailure = new SAFSTestLevelFailure();
org.safs.model.Component nonExistGui = new org.safs.model.Component("FANTACY_GUI");
if(!Misc.IsComponentExists(nonExistGui)){
testLevelFailure.addFailure("IsComponentExists failed.", nonExistGui.getName()+" doesn't exist!", "NON_EXIST");
}
if(!SeleniumPlus.WaitForGUI(nonExistGui, 3)){
testLevelFailure.addFailure("WaitForGUI failed.", nonExistGui.getName()+" doesn't exist!", "TIMEOUT");
}
throw testLevelFailure;
}
@TestCase
public void case4(){
String name = null;
try{
name.length();
}catch(NullPointerException e){
throw new SAFSTestLevelError(e.getMessage(), null, e.getClass().getSimpleName());
}
}
public void runTest() throws Throwable {
self.case1();
self.case2();
self.case3();
self.case4();
}
public static void main(String[] args) {
SeleniumPlus.main(args);
}
}
How to set test count unit?
In some testing environment, Internet access is not direct, but through a Proxy server.
This section is talking about HTTP proxy settings in SeleniumPlus.
There are 2 ways:
[SAFS_SELENIUM] ;define the HTTP PROXY host name to connect Internet GATEWAYHOST=yourGateway.net ;define the HTTP PROXY port number to connect Internet GATEWAYPORT=80 ;define the HTTP PROXY "bypass address" when connecting INTRANET PROXY_BYPASS_ADDRESS=localhost,127.0.0.1,host.not.thru.gateway[go back]
The HTTP proxy can also be set by the optional parameters of StartWebBrowser API. The optional parameters are given as pair (key, value). The keys related to "HTTP proxy" are:
//Start the firefox web browser with proxy server as "proxy.server" and proxy server port as "8080" StartWebBrowser("http://www.google.com", "GoogleMain", new String[]{ SelectBrowser.BROWSER_NAME_FIREFOX, "10", "true", quote(SelectBrowser.KEY_PROXY_SETTING), quote("proxy.server:8080") }); //Start the firefox web browser with proxy server as "proxy.server" and proxy server port as "8080" //local.site1, local.site2 will not be routed through "proxy.server" StartWebBrowser("http://www.google.com", "GoogleMain", new String[]{ SelectBrowser.BROWSER_NAME_FIREFOX, "10", "true", quote(SelectBrowser.KEY_PROXY_SETTING), quote("proxy.server:8080"), quote(SelectBrowser.KEY_PROXY_BYPASS_ADDRESS), quote("local.site1, local.site2") });
This section is talking about how to run SeleniumPlus Test on docker container.




Start the selenium standalone sever with chrome in docker container, we name this container as "my-chrome",
the container's port 4444 and 5900 have been mapped to port 4444 and port 32800 on local machine where the docker is running
docker run -d -p 4444:4444 -p 32800:5900 --name my-chrome selenium/standalone-chrome-debug
2. We can use command docker container ls to show all the running containers, we should see the container "my-chrome" is listed.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
61520f90554a selenium/standalone-chrome-debug "/opt/bin/entry_poin..." 23 minutes ago Up 23 minutes 0.0.0.0:4444->4444/tcp, 0.0.0.0:32800->5900/tcp my-chrome
3. Open a "VNC Viewer" connection to the container "my-chrome".[SAFS_SELENIUM] ;bypass the robot, so that the selenium's API will do the work bypass.robot.action=true ;define the port where the selenium standalone server is running on. SELENIUMPORT=44445. Run the SeleniumPlus test as usual, we should be able to see the test gets running in the "VNC Viewer" connection with "my-chrome".
docker container stop my-chrome
docker container rm my-chrome
2. Create a docker network "my-grid"
docker network create my-grid
3. Start a selenium hub container "my-hub"
docker run -d -p 4444:4444 --net my-grid --name my-hub selenium/hub
4. Start a selenium node container "my-chrome"
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
598b873c4546 selenium/node-firefox-debug "/opt/bin/entry_poin..." 6 seconds ago Up 5 seconds 0.0.0.0:32801->5900/tcp my-firefox
18dd54892960 selenium/node-chrome-debug "/opt/bin/entry_poin..." 9 minutes ago Up 9 minutes 0.0.0.0:32800->5900/tcp my-chrome
4026567e5dc2 selenium/hub "/opt/bin/entry_poin..." 9 minutes ago Up 9 minutes 0.0.0.0:4444->4444/tcp my-hub
7. Open a "VNC Viewer" connection to the container "my-chrome" on port 32800.[SAFS_SELENIUM] ;bypass the robot, so that the selenium's API will do the work bypass.robot.action=true ;define the port where the selenium hub is running SELENIUMPORT=4444 ;define the browser to run test BROWSER=chrome10. Run the SeleniumPlus test as usual, we should be able to see the test gets running in the "VNC Viewer" connection with "my-chrome".
[SAFS_SELENIUM] ;bypass the robot, so that the selenium's API will do the work bypass.robot.action=true ;define the port where the selenium hub is running SELENIUMPORT=4444 ;define the browser to run test BROWSER=firefox12. Run the SeleniumPlus test as usual, we should be able to see the test gets running in the "VNC Viewer" connection with "my-firefox". If the first test is long enough, we should be able to see the both tests are running the same time in 2 containers.
docker container stop my-chrome my-firefox
docker container rm my-chrome my-firefox
2. Suppose that we hava a docker network "my-grid" as before.
3. Suppose that we have a selenium hub container "my-hub" as before.
4. Start a selenium node container "my-chrome" with RMI port-forwarding
Start the selenium node in docker container, we name this container as "my-chrome",
the container's port 5900 has been mapped to port 32800 on local machine where the docker is running,
the container's port 1099 has been mapped to local port 1099, this port is used by RMI Registry,
the container's port 6890 has been mapped to local port 6890, this port is used by RMI server,
this container is running in network "my-grid", this selenium node will connect to selenium hub "my-hub",
we mount the folder "c:/seleniumplus" to docker's folder "/dev/seleniumplus".
docker run -d -p 32800:5900 -p 1099:1099 -p 6890:6890 --net my-grid --name my-chrome -e HUB_HOST=my-hub -v c:/seleniumplus:/dev/seleniumplus selenium/node-chrome-debug
5. Start a selenium node container "my-firefox" with RMI port-forwarding
Start the selenium node in docker container, we name this container as "my-firefox",
the container's port 5900 has been mapped to port 32801 on local machine where the docker is running,
the container's port 1099 has been mapped to local port 1100, this port is used by RMI Registry,
the container's port 6891 has been mapped to local port 6891, this port is used by RMI server,
this container is running in network "my-grid", this selenium node will connect to selenium hub "my-hub",
we mount the folder "c:/seleniumplus" to docker's folder "/dev/seleniumplus".
docker run -d -p 32801:5900 -p 1100:1099 -p 6891:6891 --net my-grid --name my-firefox -e HUB_HOST=my-hub -v c:/seleniumplus:/dev/seleniumplus selenium/node-firefox-debug
6. We can use command docker container ls to show all the running containers, we should see the following containers.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
598b873c4546 selenium/node-firefox-debug "/opt/bin/entry_poin..." 6 seconds ago Up 5 seconds 0.0.0.0:32801->5900/tcp my-firefox
18dd54892960 selenium/node-chrome-debug "/opt/bin/entry_poin..." 9 minutes ago Up 9 minutes 0.0.0.0:32800->5900/tcp my-chrome
4026567e5dc2 selenium/hub "/opt/bin/entry_poin..." 9 minutes ago Up 9 minutes 0.0.0.0:4444->4444/tcp my-hub
7. Start "RMI server" on "my-chrome" container
Currently, the environment SELENIUM_PLUS is /dev/seleniumplus.
If you want to change it, please enter below:
When we see this message, we enter "/seleniumplus" as below:
/seleniumplus
[SAFS_SELENIUM] ;define the port where the selenium hub is running SELENIUMPORT=4444 ;turn on the rmi port forwarding rmi.port.forward=true ;define the port where the rmi registry is running on registry.port=1099 ;define the browser to run test BROWSER=chrome12. Run the SeleniumPlus test as usual, we should be able to see the test gets running in the "VNC Viewer" connection with "my-chrome".
[SAFS_SELENIUM] ;define the port where the selenium hub is running SELENIUMPORT=4444 ;turn on the rmi port forwarding rmi.port.forward=true ;define the port where the rmi registry is running registry.port=1100 ;define the browser to run test BROWSER=firefox14. Run the SeleniumPlus test as usual, we should be able to see the test gets running in the "VNC Viewer" connection with "my-firefox". If the first test is long enough, we should be able to see the both tests are running the same time in 2 containers.



docker run -d -p 32800:5900 --name seplus_test ghcr.io/safsdev/seplus
docker run -d -p 32801:5900 --name seplus_hub ghcr.io/safsdev/seplus
docker run -d -p 32802:5900 --name seplus_node ghcr.io/safsdev/seplus
docker exec -it seplus_hub bash
docker exec -it seplus_node bash
Then we start "selenium hub" in bash terminal against container "seplus_hub" by following command
. bin/SeleniumPlusEnv.sh
"$SELENIUM_PLUS/Java64/jre/bin/java" org.safs.selenium.webdriver.lib.RemoteDriverLauncher "-role hub" "SELENIUMSERVER_JVM_OPTIONS=-Xms512m -Xmx2g"
If you open a VNC connection, you can see the Java Console (selenium hub) start up.
docker inspect -f "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" seplus_hub
Suppose we get the seplus_hub's IP is 172.17.0.3
. bin/SeleniumPlusEnv.sh
"$SELENIUM_PLUS/Java64/jre/bin/java" org.safs.selenium.webdriver.lib.RemoteDriverLauncher -safs.rmi.server "-role node -hub http://172.17.0.3:4444/grid/register" "-port 5678" "SELENIUMSERVER_JVM_OPTIONS=-Xms256m -Xmx4g"
If you open a VNC connection, you can see the Java Console (selenium node) start up.



docker inspect -f "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" seplus_node
Suppose we get the seplus_node's IP is 172.17.0.4
# Settings for a remote Selenium Server
# SELENIUMHOST and SELENIUMPORT are used to connect Selenium Server (standalone or hub)
SELENIUMHOST=172.17.0.3
SELENIUMPORT=4444
SELENIUMNODE=172.17.0.4:5678
docker run -d -p 32800:5900 --name seplus_test ghcr.io/safsdev/seplus
docker run -d -p 32801:5900 --name seplus_hub ghcr.io/safsdev/seplus
docker run -d -p 32802:5900 --name seplus_node ghcr.io/safsdev/seplus
We need to know containers' IP by following command
docker inspect -f "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" <container's name>
Suppose we the seplus_test's IP is 172.17.0.2, seplus_hub's IP is 172.17.0.3, seplus_node's IP is 172.17.0.4
docker exec -it seplus_hub bash
docker exec -it seplus_node bash
Then we need to get "seplus_hub" and "seplus_node" to trust "seplus_test" by following command to modify STAF configuration
cat >> /usr/local/staf_64/bin/STAF.cfg
trust machine 172.17.0.2 level 5
Ctrl+D



# Settings for a remote Selenium Server
# SELENIUMHOST and SELENIUMPORT are used to connect Selenium Server (standalone or hub)
SELENIUMHOST=172.17.0.3
SELENIUMPORT=4444
SELENIUMNODE=172.17.0.4:5678







SELENIUMHOST=seplus-hub SELENIUMPORT=4444 SELENIUMNODE=seplus-node:5555
SELENIUMHOST=seplus-hub SELENIUMPORT=4444 SELENIUMNODE=seplus-node2:5678







This section is talking about how to install SeleniumPlus on Linux.
$mkdir /usr/local/seleniumplus
4. Un-compress the installation assets to folder /usr/local/seleniumplus by following command:
$tar xvzf TestDesigner.tar.gz -C /usr/local/seleniumplus
5. Then go to directory /usr/local/seleniumplus where you put
the installation assets. There, you can find a file named SetupSeleniumPlus.sh,
which is an interactive script to setup SELENIUMPLUS and STAF:
$cd /usr/local/seleniumplus
6. Grant execute-permission to installation scripts and STAF installer
$chmod a+x STAF*.bin *.sh
7. Install SeleniumPlus by following command
$SetupSeleniumPlus.sh
Then, just follow the script's steps:
The script will ask user
i. If he wants to install STAF, where he wants to install STAF (STAF is not necessary to install, user can choose No);
ii. If he wants to install SeleniumPlus, where he wants to install SeleniumPlus;
iii. If he wants to see detail informations during installation.
The simple way is to hit Enter always, script will install SAFS and STAF to the
default location:
a.For super user root:
STAF --> /usr/local/staf (for 32 bits OS)
/usr/local/staf_64 (for 64 bits OS)
SAFS --> /usr/local/seleniumplus
b.For normal user:
STAF --> $HOME/staf (for 32 bits OS)
$HOME/staf_64 (for 64 bits OS)
SAFS --> $HOME/seleniumplus
[go back]
$/usr/local/seleniumplus/bin/ModifyDotBash.sh

$env | grep SELENIUM_PLUS
We should see the response something like below:
$SELENIUM_PLUS=/usr/local/seleniumplus
If you cannot see it, that means the environment SELENIUM_PLUS is not correctly set. We can set it by following script
$. /usr/local/seleniumplus/bin/SeleniumPlusEnv.sh
NOTE:
$/usr/local/seleniumplus/extra/RemoteServer.sh &
4. Start the SeleniumPlus IDE (Eclipse) as below:
$/usr/local/seleniumplus/eclipse/eclipse &
5. Before running any test in the SeleniumPlus IDE, we need to verify the classpath variable "SELENIUMPLUS_HOME"
has been set correctly, if not, we can set it as shown in below picture:
