SQLite format 3 @ $
QM2 -
q {tabletextstextsCREATE TABLE texts(id INTEGER PRIMARY KEY REFERENCES items(id) ON DELETE CASCADE ON UPDATE CASCADE,date BLOB,text TEXT)wtableitemsitemsCREATE TABLE items(id INTEGER PRIMARY KEY,pid INT,ord BLOB,flags INT,name TEXT,[trigger] TEXT,icon TEXT,td,guid BLOB) # " $ !
elected C# WebDriver.
You can find the Selenium API reference in the Selenium website or in the help file downloaded with C# language bindings.
Selenium setup:
Create folder for Selenium files. It should be QM folder's subfolder Selenium ($qm$\Selenium); if not, will need to specify it with SetOptions().
Selenium consists of multiple components without a common installer. Download what you need.
From Selenium website you need:
Selenium IDE. Need it only to record web actions, don't need to run Selenium scripts.
Selenium WebDriver bindings for C#. Create folder C# in the Selenium folder ($qm$\Selenium\C#) and add there all files from downloaded folder net35 (WinXP/7) or net40 (Win8/10).
If you'll use IE, download Internet Explorer Driver Server. Add IEDriverServer.exe to the Selenium folder.
If you'll use Chrome, download Chrome browser driver. Add chromedriver.exe to the Selenium folder.
Also you need:
Windows XP SP2 or later.
.NET framework 3.5 or 4.x. Windows 7 and 8 have it. If your Windows is older and the .NET framework is not installed, download .NET 3.5 from Microsoft.
Firefox. Only for Selenium IDE, because it is a Firefox plugin.
Also you may need:
NUnit. Only if you'll use Assert.IsTrue etc in C#. Don't need for ISelenium functions. Install NUnit eg in Program Files, and copy nunit.framework.dll to the Selenium folder.
Selenium problems:
There are no ways to automate an existing browser instance.
You can reuse only the browser instance started by StartChrome() etc without flag 1 in same QM process.
Also it means that if QM is running as admin, browser processes also run as admin. It is not good for security.
Manually closing a Selenium-started browser does not close its driver process and does not delete temporary files (eg a Firefox profile may be 30 MB).
The correct way to close browser - call Quit in the macro. Or use flag 1 with StartChrome() etc, then Quit is called automatically.
Without flag 1, StartChrome() etc correctly clo ses the browser that was previously started by the same function (StartChrome() etc) without flag 1 in same QM process.
Another correct way - use flag 2 with StartChrome() etc. It shows a driver console window if the browser is Chrome or IE. Let the user close the console after closing its controlled browser.
If using IE, may need to change Protected Mode in IE Options -> Security. Must be the same in all zones.
The IE driver process may crash when an ISelenium function does not find an element.
Selenium-started IE does not respond to user clicks.
On one of my computers did not work correctly with IE if Java is not installed. You can download Java 32-bit from Oracle. Look in Control Panel, maybe you already have it.
Does not support high DPI. Clicks in wrong place. Tested only with IE.
Does not give the browser window handle. If you need it, use win() after StartChrome() etc.
WebDriver 2.42 did not work with Firefox 32 and later. Version 2.44 works.
EXAMPLES
Example with ISeleniu m functions called from QM macro
#region Selenium, recorded 2014.09.13 08:21
#compile "__WebDriver"
WebDriver x.Init("")
str baseURL="http://www.quickmacros.com"
ISelenium selenium=x.StartChrome(baseURL) ;;StartChrome, StartFirefox or StartIE
selenium.Open("/index.html")
selenium.Click("id=m_forum"); selenium.WaitForPageToLoad("30000")
selenium.Click("link=QM Extensions"); selenium.WaitForPageToLoad("30000")
if(mes("Close browser?" "" "YN?2")='Y') x.Quit
#endregion
Example with IWebDriver functions called from C# code
#region Selenium, recorded 2014.09.13 08:21
#compile "__WebDriver"
WebDriver x2.Init(__FUNCTION__)
str baseURL2="http://www.quickmacros.com"
x2.StartChrome(baseURL2) ;;StartChrome, StartFirefox or StartIE
x2.x.Run
if(mes("Close browser?" "" "YN?2")='Y') x2.Quit
#endregion
#ret
public void Run(){
driver.Navigate().GoToUrl(baseURL + "/index.html");
driver.FindElement(By.Id("m_forum")).Click();
driver.FindElement(By.LinkText("QM Extensions")).Click();
}
able.
Call before StartChrome etc.
myCode - C# code to compile. When using IWebDriver, it must contain Selenium script code. If using ISelenium, it can be omitted or "".
Can be:
C# code in a variable.
Name of macro where the code is. This function gets code after #ret line. Error if the macro does not exist or does not contain #ret or is encrypted.
Can contain any C# functions, variables and 'using' lines in the code. The functions and variables will be added to class User.Script.
To call the functions from QM macro, you'll use code like this: WebDriver x.Init(myCode) ... x.x.MyFunction().
REMARKS
Creates and compiles C# code that contains class User.Script that will call Selenium functions. Creates object of the class.
Then you can start browser with StartChrome etc. You can call functions of the class through member variable x, like x.x.Func().
opt noerrorshere 1
#opt nowarnings 1
str userCode
int iid nEmpty
if !empty(myCode)
if findc(myCode 10)<0 ;;ass
ume macro
iid=qmitem(myCode); if(!iid) end F"{ERR_MACRO}: {myCode}"
lpstr s=_s.getmacro(iid)
if(!_s.len) end F"macro {myCode} text is empty or failed to get it. If using in exe, add macro text to exe with #exe addtextof ''{myCode}''. If encrypted, store C# code in a variable."
rep
s=strchr(s 10)+1; if(s=1) end F"macro {myCode} does not contain #ret or is encrypted"
if(!StrCompareN(s "#ret" 4)) s=strchr(s 10); break
nEmpty+1
userCode=s
else userCode=myCode
#region default C# code and options
if(!___wdGlobal.seleniumDir.len) ___wdGlobal.seleniumDir.expandpath("$qm$\Selenium")
str csDir.from(___wdGlobal.seleniumDir "\C#")
if(empty(___wdGlobal.csOptions)) ___wdGlobal.csOptions=F"references=WebDriver;WebDriver.Support;ThoughtWorks.Selenium.Core;Selenium.WebDriverBackedSelenium[]searchDirs={csDir}"
str sUsing=
using System;using System.Runtime.InteropServices;using System.Text;using System.Text.RegularExpressions;using System.Threading;
using Selenium;using OpenQA.Sel enium;using OpenQA.Selenium.Firefox;using OpenQA.Selenium.Chrome;using OpenQA.Selenium.IE;using OpenQA.Selenium.Support.UI;
if(FileExists(F"{csDir}\nunit.framework.dll")) sUsing+"using NUnit.Framework;"
sUsing.findreplace("[]")
if(userCode.len) REPLACERX rr.frepl=&sub.RxCallback; rr.paramr=&sUsing; userCode.replacerx("(?m)^([ \t]*using +[\w\.]+ *;)+" rr) ;;extract 'using' lines
str sClassDef=
namespace User{
[Guid("0AF98784-13FF-41A4-88AA-58182B4D5738")]
public interface _ISScript{ ISelenium _ISelenium(); }
public class Script :_ISScript { IWebDriver driver; ISelenium selenium; string baseURL; StringBuilder verificationErrors;
sClassDef.findreplace("[]") ;;make sClassDef 1 line and add sFunctions at the end because then easier to manage errors in user functions.
lpstr sFunctions=
public ISelenium _ISelenium(){ return selenium; }
public void _Init(IWebDriver _driver, string _baseURL){ driver=_driver; baseURL=_baseURL; verificationErrors=new StringBuilder(); selenium=new WebDriverBacke dSelenium(driver, baseURL); selenium.Start(); }
public void _Quit(){ try { selenium.Stop(); } catch(Exception) { Console.Write("Warning: Quit() failed."); } }
public String VerificationErrors(){ String R=verificationErrors.ToString(); verificationErrors.Length=0; return R; }
}}
#endregion
str cs.format("%s%s[]%.*m%s[]%s" sUsing sClassDef nEmpty 10 userCode sFunctions)
if flags&0x100 ;;show C# code
_s=cs; _s.replacerx("(?:\r?\n){2,}")
out F"<>C# code[]{_s}
[]C# options[]{___wdGlobal.csOptions}[]"
m_cs.SetOptions(___wdGlobal.csOptions)
m_cs.x.AddCode(cs)
err
if(iid) _error.description.replacerx("\bC#\((\d+),\d+\)" F"$0")
end _error
x=m_cs.CreateObject("User.Script")
#sub RxCallback
function# REPLACERXCB&x
str& sUsing=+x.rrx.paramr
sUsing+x.match
x.match.set(' ')
0 SC8 This class allows to automate Internet Explorer, Firefox and Chrome using Selenium WebDriver.
Selenium is a web recorder and API for web page automation, eg for automated testing. Free, open-source.
Selenium downloads: http://docs.seleniumhq.org/download/
Selenium scripts can be recorded/edited with the Selenium IDE or created manually in QM.
To export current script (Test Case) from Selenium IDE to QM, use the small toolbar with QM icon that QM adds to the IDE.
In QM macros the scripts can be executed in 2 ways:
1. Call ISelenium interface functions directly. The QM Selenium toolbar button creates such code if in Selenium IDE menu Options -> Clipboard Format is selected C# Remote Control.
2. Call a user-defined C# function that uses functions of IWebDriver and other Selenium classes/interfaces available in C#. The QM Selenium toolbar button creates such code if in Selenium IDE menu Options -> Clipboard Format is s
nU
| kЭ$Efunction'ISelenium $baseURL [flags] ;;flags: 1 always start new browser instance and auto-close, 2 show driver console
Starts Selenium session and Internet Explorer browser.
opt noerrorshere 1
ret _StartBrowser(3 baseURL flags)
[ )Эq
function'ISelenium $baseURL [flags] ;;flags: 1 always start new browser instance and auto-close
Starts Selenium session and Firefox browser.
opt noerrorshere 1
ret _StartBrowser(1 baseURL flags)
q UЭufunction'ISelenium $baseURL [flags] ;;flags: 1 always start new browser instance and auto-close, 2 show driver console
Starts Selenium session and Chrome browser.
opt noerrorshere 1
ret _StartBrowser(2 baseURL flags)
\ +вkfunction [$myCode] [flags] ;;flags: 0x100 show C# code
Initializes this WebDriver vari
V V ' Aж:
Closes browser started by StartChrome() etc.
REMARKS
The user should not close Selenium-started browsers manually. It would not delete temporary files and driver processes. To close correctly, call this function. Or use StartChrome() etc with flag 1 to call this function automatically.
if(!m_started) ret
x._Quit; err
if(m_started>0) ___wdGlobal.cs.Call("OnQuit" m_started); err
m_started=0
x x
y
w aP function [$SeleniumFolder] [$CsScriptOptions]
Sets some global options for WebDriver class.
SeleniumFolder - folder containing Selenium files - chromedriver.exe, IEDriverServer.exe and subfolder C#.
If not set, WebDriver.Init sets it to "$qm$\Selenium".
Once set, cannot be changed until restarting QM.
CsScriptOptions - CsScript.SetOptions optionsList.
If not set, WebDriver.Init uses F"references=WebDriver;WebDriver.Support;ThoughtWorks.Selenium.Core;Selenium.WebDriverBackedSelenium[]searchDirs={SeleniumFolder}\C#".
REMARKS
Call this function at startup or before WebDriver.Init.
If an argument is omitted or "", does not change that option.
if(!empty(SeleniumFolder) and !___wdGlobal.seleniumDir.len) ___wdGlobal.seleniumDir.expandpath(SeleniumFolder)
if(!empty(CsScriptOptions)) ___wdGlobal.csOptions=CsScriptOptions
RightAt(BSTR'locator BSTR'coordString)
MouseUp(BSTR'locator)
MouseUpRight(BSTR'locator)
MouseUpAt(BSTR'locator BSTR'coordString)
MouseUpRightAt(BSTR'locator BSTR'coordString)
MouseMove(BSTR'locator)
MouseMoveAt(BSTR'locator BSTR'coordString)
Type(BSTR'locator BSTR'value)
TypeKeys(BSTR'locator BSTR'value)
SetSpeed(BSTR'value)
BSTR'GetSpeed()
Check(BSTR'locator)
Uncheck(BSTR'locator)
Select(BSTR'selectLocator BSTR'optionLocator)
AddSelection(BSTR'locator BSTR'optionLocator)
RemoveSelection(BSTR'locator BSTR'optionLocator)
RemoveAllSelections(BSTR'locator)
Submit(BSTR'formLocator)
Open(BSTR'url)
OpenWindow(BSTR'url BSTR'windowID)
SelectWindow(BSTR'windowID)
SelectPopUp(BSTR'windowID)
DeselectPopUp()
SelectFrame(BSTR'locator)
@GetWhetherThisFrameMatchFrameExpression(BSTR'currentFrameString BSTR'target)
@GetWhetherThisWindowMatchWindowExpression(BSTR'currentWindowString BSTR'target)
WaitForPopUp(BSTR'windowID BSTR'timeout)
ChooseCancelOnNextConfirmation()
ChooseOkOnNextConfirmation()
AnswerOnNextPrompt(BSTR'answer)
GoBack()
Refresh()
Close()
@IsAlertPresent()
@IsPromptPresent()
@IsConfirmationPresent()
BSTR'GetAlert()
BSTR'GetConfirmation()
BSTR'GetPrompt()
BSTR'GetLocation()
BSTR'GetTitle()
BSTR'GetBodyText()
BSTR'GetValue(BSTR'locator)
BSTR'GetText(BSTR'locator)
Highlight(BSTR'locator)
BSTR'GetEval(BSTR'script)
@IsChecked(BSTR'locator)
BSTR'GetTable(BSTR'tableCellAddress)
ARRAY(BSTR)GetSelectedLabels(BSTR'selectLocator)
BSTR'GetSelectedLabel(BSTR'selectLocator)
ARRAY(BSTR)GetSelectedValues(BSTR'selectLocator)
BSTR'GetSelectedValue(BSTR'selectLocator)
ARRAY(BSTR)GetSelectedIndexes(BSTR'selectLocator)
BSTR'GetSelectedIndex(BSTR'selectLocator)
ARRAY(BSTR)GetSelectedIds(BSTR'selectLocator)
BSTR'GetSelectedId(BSTR'selectLocator)
@IsSomethingSelected(BSTR'selectLocator)
ARRAY(BSTR)GetSelectOptions(BSTR'selectLocator)
BSTR'GetAttribute(BSTR'attributeLocator)
@IsTextPresent(BSTR'pattern)
@IsElement Present(BSTR'locator)
@IsVisible(BSTR'locator)
@IsEditable(BSTR'locator)
ARRAY(BSTR)GetAllButtons()
ARRAY(BSTR)GetAllLinks()
ARRAY(BSTR)GetAllFields()
ARRAY(BSTR)GetAttributeFromAllWindows(BSTR'attributeName)
Dragdrop(BSTR'locator BSTR'movementsString)
SetMouseSpeed(BSTR'pixels)
DECIMAL'GetMouseSpeed()
DragAndDrop(BSTR'locator BSTR'movementsString)
DragAndDropToObject(BSTR'locatorOfObjectToBeDragged BSTR'locatorOfDragDestinationObject)
WindowFocus()
WindowMaximize()
ARRAY(BSTR)GetAllWindowIds()
ARRAY(BSTR)GetAllWindowNames()
ARRAY(BSTR)GetAllWindowTitles()
BSTR'GetHtmlSource()
SetCursorPosition(BSTR'locator BSTR'position)
DECIMAL'GetElementIndex(BSTR'locator)
@IsOrdered(BSTR'locator1 BSTR'locator2)
DECIMAL'GetElementPositionLeft(BSTR'locator)
DECIMAL'GetElementPositionTop(BSTR'locator)
DECIMAL'GetElementWidth(BSTR'locator)
DECIMAL'GetElementHeight(BSTR'locator)
DECIMAL'GetCursorPosition(BSTR'locator)
BSTR'GetExpression(BSTR'expression)
DECIMAL'GetXpath Count(BSTR'xpath)
DECIMAL'GetCSSCount(BSTR'cssLocator)
AssignId(BSTR'locator BSTR'identifier)
AllowNativeXpath(BSTR'allow)
IgnoreAttributesWithoutValue(BSTR'ignore)
WaitForCondition(BSTR'script BSTR'timeout)
SetTimeout(BSTR'timeout)
WaitForPageToLoad(BSTR'timeout)
WaitForFrameToLoad(BSTR'frameAddress BSTR'timeout)
BSTR'GetCookie()
BSTR'GetCookieByName(BSTR'name)
@IsCookiePresent(BSTR'name)
CreateCookie(BSTR'nameValuePair BSTR'optionsString)
DeleteCookie(BSTR'name BSTR'optionsString)
DeleteAllVisibleCookies()
SetBrowserLogLevel(BSTR'logLevel)
RunScript(BSTR'script)
AddLocationStrategy(BSTR'strategyName BSTR'functionDefinition)
CaptureEntirePageScreenshot(BSTR'filename BSTR'kwargs)
Rollup(BSTR'rollupName BSTR'kwargs)
AddScript(BSTR'scriptContent BSTR'scriptTagId)
RemoveScript(BSTR'scriptTagId)
UseXpathLibrary(BSTR'libraryName)
SetContext(BSTR'context)
AttachFile(BSTR'fieldLocator BSTR'fileLocator)
CaptureScreenshot(BSTR'filename)
BSTR'CaptureScreenshotToSt ring()
BSTR'CaptureEntirePageScreenshotToString(BSTR'kwargs)
ShutDownSeleniumServer()
BSTR'RetrieveLastRemoteControlLogs()
KeyDownNative(BSTR'keycode)
KeyUpNative(BSTR'keycode)
KeyPressNative(BSTR'keycode)
{A2FD957B-A7D4-3CAF-A3BE-10AAAD600E3A}
#endregion
To get ISelenium from the script object (x).
To get directly from x would be implicitly used the GUID (becauise x is IDispatch, to call user C# functions) which is unreliable because auto-generated (I discovered it with tlbexp/oleview).
Could get with typeof(ISelenium).GUID.ToString()/IIDFromString/QueryInterface, but better avoid it.
The GUID in the interface declaration now is not used when getting ISelenium, but useful eg to get extended error info.
interface# ___ISeleniumScript :IDispatch
ISelenium'_ISelenium()
{0AF98784-13FF-41A4-88AA-58182B4D5738}
class WebDriver -CsScript'm_cs IDispatch'x -ISelenium'm_selenium -m_started
type ___WebDriverGlobal CsScript'cs ~seleniumDir ~csOptions
___WebDriverGlobal+ ___wdGlobal
#region ...
interface# ISelenium :IDispatch
SetExtensionJs(BSTR'extensionJs)
Start()
Stop()
Click(BSTR'locator)
DoubleClick(BSTR'locator)
ContextMenu(BSTR'locator)
ClickAt(BSTR'locator BSTR'coordString)
DoubleClickAt(BSTR'locator BSTR'coordString)
ContextMenuAt(BSTR'locator BSTR'coordString)
FireEvent(BSTR'locator BSTR'eventName)
Focus(BSTR'locator)
KeyPress(BSTR'locator BSTR'keySequence)
ShiftKeyDown()
ShiftKeyUp()
MetaKeyDown()
MetaKeyUp()
AltKeyDown()
AltKeyUp()
ControlKeyDown()
ControlKeyUp()
KeyDown(BSTR'locator BSTR'keySequence)
KeyUp(BSTR'locator BSTR'keySequence)
MouseOver(BSTR'locator)
MouseOut(BSTR'locator)
MouseDown(BSTR'locator)
MouseDownRight(BSTR'locator)
MouseDownAt(BSTR'locator BSTR'coordString)
MouseDown arted) Quit
lock
if !___wdGlobal.cs.x
str so=
F
references=WebDriver;WebDriver.Support;ThoughtWorks.Selenium.Core;Selenium.WebDriverBackedSelenium
searchDirs={___wdGlobal.seleniumDir}\C#
___wdGlobal.cs.SetOptions(so)
___wdGlobal.cs.AddCode("")
___wdGlobal.cs.Call("Init" ___wdGlobal.seleniumDir)
lpstr fn; sel(browser) case 1 fn="StartFirefox"; case 2 fn="StartChrome"; case 3 fn="StartIE"
IUnknown driver=___wdGlobal.cs.Call(fn flags&3)
x._Init(driver baseURL)
selenium=x._ISelenium ;;unreliable because uses IID (to QI from IDispatch) which may change in the future
___ISeleniumScript _is=x; m_selenium=_is._ISelenium
BSTR guidISelenium
IUnknown _selenium=x._Init(driver baseURL &guidISelenium)
_s=guidISelenium; _s-"{"; _s+"}"
GUID guid; IIDFromString(@_s &guid)
if(_selenium.QueryInterface(&guid &selenium)) end ERR_FAILED
m_started=iif(flags&1 -browser browser)
ret m_selenium
SHOULDDO:
From FAQ: WebDriver is not thread-safe. If you can serialise access to the und erlying driver instance, you can share a reference in more than one thread.
Difficult. Assume the user will never run 2 macros that automate the same browser instance simultaneously.
#ret
using System;using OpenQA.Selenium;using OpenQA.Selenium.Firefox;using OpenQA.Selenium.Chrome;using OpenQA.Selenium.IE;
public class Script
{
static IWebDriver driverFirefox, driverChrome, driverIE;
static string driverPath;
public static void Init(string _driverPath)
{
driverPath=_driverPath;
}
public static IWebDriver StartFirefox(int flags)
{
bool reuse=(flags&1)==0 ? true : false;
if(reuse && driverFirefox!=null && _IsValid(ref driverFirefox)) return driverFirefox;
IWebDriver driver=new FirefoxDriver();
if(reuse) driverFirefox=driver;
return driver;
}
public static IWebDriver StartChrome(int flags)
{
bool reuse=(flags&1)==0 ? true : false;
if(reuse && driverChrome!=null && _IsValid(ref driverChrome)) return driverChrome;
ChromeDriverService ds=ChromeDriverService.CreateDefaultServic e(driverPath); ds.HideCommandPromptWindow=(flags&2)==0;
ChromeOptions options=new ChromeOptions();options.AddArgument("--test-type");
IWebDriver driver=new ChromeDriver(ds, options);
if(reuse) driverChrome=driver;
return driver;
}
public static IWebDriver StartIE(int flags)
{
bool reuse=(flags&1)==0 ? true : false;
if(reuse && driverIE!=null && _IsValid(ref driverIE)) return driverIE;
InternetExplorerDriverService ds=InternetExplorerDriverService.CreateDefaultService(driverPath); ds.HideCommandPromptWindow=(flags&2)==0;
IWebDriver driver=new InternetExplorerDriver(ds, new InternetExplorerOptions());
if(reuse) driverIE=driver;
return driver;
}
static bool _IsValid(ref IWebDriver driver)
{
try{string s=driver.Url;return true;}catch(Exception){}
try{driver.Quit();}catch(Exception){}
driver=null;
return false;
}
public static void OnQuit(int browser)
{
switch(browser){
case 1: driverFirefox=null; break;
case 2: driverChrome=null; break;
case 3: driverIE=null; break;
}
}
}
N*
O5
1}f /mov0 112 29 /siz0 48 23 /set0 0x4505 0xFCFF
Export to QM[]Puts full code in the clipboard. :WdExportToQM GetToolbarOwner(TriggerWindow) * $qm$\qm.ico
Export to QM[]Puts only Selenium script in the clipboard. :WdExportToQM GetToolbarOwner(TriggerWindow) 1 * $qm$\qm.ico
" 9` if(m_started<0) Quit
1к`yfunction'ISelenium browser $baseURL flags ;;browser: 1 FF, 2 Chrome, 3 IE. flags: 1 always start new browser instance, 2 show driver console
#if EXE
if(flags&3=0) end "In exe use flag 1 or 2. Or make sure that Quit is always called at the end. Else driver processes will not be closed and temporary files will not be deleted." 8|2
#endif
opt noerrorshere 1
#opt nowarnings 1
if(!x) end ERR_INIT
if(m_st State
if(state&STATE_SYSTEM_UNAVAILABLE) mes "The ''Table'' tab must be available." errMesTitle "x"; ret
if(state&STATE_SYSTEM_SELECTED=0) a.DoDefaultAction
focus the table
a.FindFF(w "tree" "" "id=commands" 0x3084) ;;or a.Navigate("pa n f2")
a.Select(1)
select all, and get code through clipboard
key Ca
s.getsel; if(!s.len) ret
is a C# formatter?
int i
if(s[0]='<') i=-1 ;;HTML, default
else i=findrx(s "\b(selenium|driver).[A-Z]")
if i<0
_s=
Please select this menu item in Selenium IDE, then retry:
Options -> Clipboard Format -> C# Remote Control or WebDriver.
;
If that does not work, look in Selenium Options, must be:
Formats -> C# Remote Control -> Variable: selenium.
Formats -> C# WebDriver -> Variable: driver.
Plugins -> Selenium IDE C# formatters: enabled. Or enable it in Firefox Add-ins.
mes _s errMesTitle "x"
ret
int format=iif(s[i]='s' 1 2)
#endregion
#region convert C# to QM
str q ;;QM code converted from C#
int isVerify
lpstr sel VarDecl
sel format
case 1 ;;call ISelenium functions directly from macro
selVarDecl="ISelenium selenium="
convert strings to QM. To make easier, put in as and replace to "[1]index[2]" in s.
ARRAY(str) as
REPLACERX rr.frepl=&sub.Callback_str_replacerx; rr.paramr=&as
s.replacerx("''[^''\\]*(?:\\.[^''\\]*)*''" rr)
convert multiline code - verifyX and waitForX
s.replacerx("(?m)^\s*try\s+\{\s+([^\r\n]+)\s+\}\s+catch\s*([^\r\n]+)\s+\{\s*([^\r\n]*)\s*\}" "try { $1 } catch$2 { $3 }")
s.replacerx("(?m)^\s*for ([^\r\n]+)\s+([^\r\n]+)\s+([^\r\n]+)\s+([^\r\n]+)\s+}" "for$1 $2 $3 $4 }")
remove indentation
s.replacerx("(?m)^\s+")
convert Regex.IsMatch etc
s.replacerx("\bRegex.IsMatch\b" "WdMatch")
s.replacerx("\bString.Join\b" "WdJoin")
if(s.replacerx("try \{ (Assert\..+?) } catch[^\r\n]+" "$1 err WdVerifyErr verificationErrors")) isVerify=1
ARRAY(str) ac=s
for i 0 ac.len
str& k=ac[i]
sel k.rtrim(";") 6
case "selenium.*"
sel k 2
case "selenium.Break()" k="i f(mes(''Continue?'' '''' ''YN?'')!='Y') goto somewhere"
case "selenium.SendKeys(*" k+" ;;if SendKeys is missing, try to replace to Type"
also missing GetCssCount, used with storeX, assertX etc
q.formata("%s[]" k)
if i