summaryrefslogtreecommitdiff
path: root/testautomation/global/tools/includes/optional
diff options
context:
space:
mode:
authorJoerg Skottke <jsk@openoffice.org>2008-06-20 06:59:34 +0000
committerJoerg Skottke <jsk@openoffice.org>2008-06-20 06:59:34 +0000
commit7ecf6630c2b195ba14743d27deb19367ac303a0e (patch)
tree33bb2bd0c5d73bbb12098272f4589f5f81180255 /testautomation/global/tools/includes/optional
parent3bb16f65ef1e228b17569210353b97f26095c7c5 (diff)
Add files that fit into the naming scheme
Diffstat (limited to 'testautomation/global/tools/includes/optional')
-rwxr-xr-xtestautomation/global/tools/includes/optional/t_accels.inc130
-rwxr-xr-xtestautomation/global/tools/includes/optional/t_basic_ide_tools.inc996
-rwxr-xr-xtestautomation/global/tools/includes/optional/t_basic_organizer_tools.inc526
-rwxr-xr-xtestautomation/global/tools/includes/optional/t_control_objects.inc608
-rwxr-xr-xtestautomation/global/tools/includes/optional/t_docfuncs.inc739
-rwxr-xr-xtestautomation/global/tools/includes/optional/t_extension_manager_tools.inc750
-rwxr-xr-xtestautomation/global/tools/includes/optional/t_filetools.inc665
-rwxr-xr-xtestautomation/global/tools/includes/optional/t_key_tools.inc569
-rwxr-xr-xtestautomation/global/tools/includes/optional/t_listfuncs.inc736
-rwxr-xr-xtestautomation/global/tools/includes/optional/t_macro_tools.inc183
-rwxr-xr-xtestautomation/global/tools/includes/optional/t_security_tools.inc670
-rwxr-xr-xtestautomation/global/tools/includes/optional/t_stringtools.inc359
-rwxr-xr-xtestautomation/global/tools/includes/optional/t_treelist_tools.inc509
13 files changed, 7440 insertions, 0 deletions
diff --git a/testautomation/global/tools/includes/optional/t_accels.inc b/testautomation/global/tools/includes/optional/t_accels.inc
new file mode 100755
index 000000000000..ccaf5d5ba9ce
--- /dev/null
+++ b/testautomation/global/tools/includes/optional/t_accels.inc
@@ -0,0 +1,130 @@
+'encoding UTF-8 Do not remove or change this line!
+'**************************************************************************
+'* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+'*
+'* Copyright 2008 by Sun Microsystems, Inc.
+'*
+'* OpenOffice.org - a multi-platform office productivity suite
+'*
+'* $RCSfile: t_accels.inc,v $
+'*
+'* $Revision: 1.1 $
+'*
+'* last change: $Author: jsk $ $Date: 2008-06-20 07:57:02 $
+'*
+'* This file is part of OpenOffice.org.
+'*
+'* OpenOffice.org is free software: you can redistribute it and/or modify
+'* it under the terms of the GNU Lesser General Public License version 3
+'* only, as published by the Free Software Foundation.
+'*
+'* OpenOffice.org is distributed in the hope that it will be useful,
+'* but WITHOUT ANY WARRANTY; without even the implied warranty of
+'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+'* GNU Lesser General Public License version 3 for more details
+'* (a copy is included in the LICENSE file that accompanied this code).
+'*
+'* You should have received a copy of the GNU Lesser General Public License
+'* version 3 along with OpenOffice.org. If not, see
+'* <http://www.openoffice.org/license.html>
+'* for a copy of the LGPLv3 License.
+'*
+'/************************************************************************
+'*
+'* owner : joerg.skottke@sun.com
+'*
+'* short description : handle accelerators
+'*
+'*******************************************************************************
+'**
+' #1 hGetAccel ' function to retrieve a language specific accelerator
+'**
+'\******************************************************************************
+
+function hGetAccel( cCommand as string ) as string
+
+ '///<h3>Retrieve a keyboard accelerator for a specific function</h3>
+ '///<i>Uses: global/input/accelerators.txt</i><br>
+ '///<i>NOTE: Accelerator is language dependent</i><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Name of the action to be executed (string). Valid options are:</li>
+ '///<ul>
+ '///+<li>&quot;FileOpen&quot;</li>
+ '///+<li>&quot;FileSave&quot;</li>
+ '///+<li>&quot;Print&quot;</li>
+ '///+<li>&quot;SelectAll&quot;</li>
+ '///+<li>&quot;Copy&quot;</li>
+ '///+<li>&quot;DocumentConverter_ShowLog&quot;</li>
+ '///+<li>&quot;IDE_SWITCH_TAB+&quot;</li>
+ '///+<li>&quot;IDE_SWITCH_TAB-&quot;</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Accelerator (string)</li>
+ '///<ul>
+ '///+<li>A string ready to use by .typeKeys(...) method</li>
+ '///+<li>&quot;Error&quot; if the requested Accelerator is unknown</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+ const CFN = "hGetAccel::"
+ const DEFAULT_LANGUAGE = "en-us"
+
+ dim cAccel as string
+ dim lsAccelerators( 1000 ) as string
+ dim cFile as string
+ cFile = gTesttoolpath & "global/input/accelerators.txt"
+ cFile = convertpath( cFile )
+
+ dim cProximityLocale as string
+
+ dim iLang as integer
+
+ printlog( CFN & "Enter with option: " & cCommand )
+ 'printlog( CFN & "Current Language.: <" & gISOLang & ">" )
+
+ '///+<li>Get the section from the accelerators file</li>
+ hGetDatafileSection( cFile , lsAccelerators() , cCommand , "" , "" )
+
+ '///+<li>Find the matching string for the current language</li>
+ cAccel = hGetValueForKeyAsString( lsAccelerators() , gISOLang )
+
+ '///+<li>In case of a miss we retry with a modified string</li>
+ '///<ul>
+ if ( instr( cAccel , "Error" ) <> 0 ) then
+
+ iLang = len( gISOLang )
+
+ select case iLang
+ case 2 :
+ '///+<li>Try xx-XX</li>
+ cProximityLocale = gISOLang & "-" & ucase( gISOLang )
+ printlog( CFN & "Trying alternative locale: " & cProximityLocale )
+ cAccel = hGetValueForKeyAsString( lsAccelerators() , cProximityLocale )
+ case 5 :
+ '///+<li>Try xx</li>
+ cProximityLocale = mid( cUpperCaseLocale , 1, 2 )
+ printlog( CFN & "Trying alternative locale: " & cProximityLocale )
+ cAccel = hGetValueForKeyAsString( lsAccelerators() , cProximityLocale )
+ case else :
+ '///+<li>Try en-US</li>
+ cProximityLocale = "en-US"
+ printlog( CFN & "Trying default locale: " & cProximityLocale )
+ cAccel = hGetValueForKeyAsString( lsAccelerators() , DEFAULT_LANGUAGE )
+ end select
+
+ endif
+ '///</ul>
+
+ '///+<li>Build the complete accelerator-string so it can be used by "TypeKeys"</li>
+ '///+<li>Print it to the log and return the string to the calling function</li>
+
+ cAccel = "<" & cAccel & ">"
+ printlog( CFN & "Requested accelerator: " & cAccel & " for language: " & gISOLang )
+ hGetAccel() = cAccel
+ '///</ul>
+
+end function
diff --git a/testautomation/global/tools/includes/optional/t_basic_ide_tools.inc b/testautomation/global/tools/includes/optional/t_basic_ide_tools.inc
new file mode 100755
index 000000000000..36a019374361
--- /dev/null
+++ b/testautomation/global/tools/includes/optional/t_basic_ide_tools.inc
@@ -0,0 +1,996 @@
+'encoding UTF-8 Do not remove or change this line!
+'**************************************************************************
+'* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+'*
+'* Copyright 2008 by Sun Microsystems, Inc.
+'*
+'* OpenOffice.org - a multi-platform office productivity suite
+'*
+'* $RCSfile: t_basic_ide_tools.inc,v $
+'*
+'* $Revision: 1.1 $
+'*
+'* last change: $Author: jsk $ $Date: 2008-06-20 07:57:11 $
+'*
+'* This file is part of OpenOffice.org.
+'*
+'* OpenOffice.org is free software: you can redistribute it and/or modify
+'* it under the terms of the GNU Lesser General Public License version 3
+'* only, as published by the Free Software Foundation.
+'*
+'* OpenOffice.org is distributed in the hope that it will be useful,
+'* but WITHOUT ANY WARRANTY; without even the implied warranty of
+'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+'* GNU Lesser General Public License version 3 for more details
+'* (a copy is included in the LICENSE file that accompanied this code).
+'*
+'* You should have received a copy of the GNU Lesser General Public License
+'* version 3 along with OpenOffice.org. If not, see
+'* <http://www.openoffice.org/license.html>
+'* for a copy of the LGPLv3 License.
+'*
+'/************************************************************************
+' **
+' ** owner : joerg.skottke@sun.com
+' **
+' ** short description : tools for the property-browser test
+' **
+'\******************************************************************************
+
+function hShowMacroControls() as boolean
+
+ '///<h3>Tear off the ToolsCollectionBar from the MacroBar</h3>
+ '///<i>Starting point: Basic dialog editor is open and has the focus</i>
+ '///<ul>
+ const CFN = "hShowMacroControls::"
+
+ printlog( CFN & "Enter" )
+
+ '///+<li>Test whether the ToolsCollectionBar is already open. If yes, exit directly</li>
+ kontext "ToolsCollectionBar"
+ if ( ToolsCollectionBar.exists( 3 ) ) then
+ printlog( CFN & "Exit: ToolsCollectionBar is already open." )
+ hShowMacroControls() = true
+ exit function
+ endif
+
+ '///+<li>Verify that the Dialog Bar is available</li>
+ Kontext "DialogBar"
+ if ( DialogBar.exists( 5 ) ) then
+
+ '///+<li>Verify that the controls-button is enabled</li>
+ try
+ '///+<li>Click on the controls-button to open the ToolsCollectionBar</li>
+ controls.click()
+
+ '///+<li>Tear off the ToolsCollectionBar from the DialogBar</li>
+ controls.tearOff()
+
+ '///+<li>Verify that the ToolsCollectionBar is visible and can be accessed</li>
+ kontext "ToolsCollectionBar"
+ if ( ToolsCollectionBar.exists( 5 ) ) then
+
+ '///+<li>Move it to the upper left corner at pos 50/50</li>
+ ToolsCollectionBar.Move ( 50 , 50 )
+ printlog( CFN & "Exit: ToolsCollectionBar is open and has been placed" )
+ hShowMacroControls() = true
+ exit function
+ else
+ printlog( CFN & "Exit: ToolsCollectionBar is not available. Aborting." )
+ hShowMacroControls() = false
+ exit function
+ endif
+ catch
+ printlog( CFN & "Exit: The Controls-Button is not enabled. Aborting." )
+ hShowMacroControls() = false
+ exit function
+ endcatch
+ else
+ printlog( CFN & "Exit: The Dialog Bar is not available. Aborting." )
+ hShowMacroControls() = false
+ exit function
+ endif
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hGetBasicWorkFile( cMajorID as string ) as string
+
+ '///<h3>Retrieve a filename, depending on gApplication and Build-ID</h3>
+ '///<i>Structure: work-directory/basic[.suffix]</i>
+ '///<ul>
+
+ const CFN = "hGetBasicWorkFile::"
+
+ dim sFile as string
+
+ '///+<li>Build a path and a filename (path from UNO, Suffix from global-module)</li>
+ sFile = hGetWorkPath() & "basic" & hGetSuffix( cMajorId )
+ sFile = ConvertPath( sFile )
+
+ printlog( CFN & sFile & " for " & gApplication & " (" & cMajorID & ")" )
+
+ '///+<li>Return the path as string</li>
+ hGetBasicWorkFile() = convertpath( sFile )
+
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hOpenBasicIDE() as boolean
+
+ '///<h3>Open the Basic IDE for the last module listed in the Macro Organizer</h3>
+ '///<i>Starting point: Basic Macro Organizer has focus</i>
+ '///<ul>
+
+ const CFN = "hOpenBasicIDE::"
+
+ '///+<li>Select the last module in the treelist, verify that it can be edited</li>
+ hSelectTheLastModule( true )
+
+ '///+<li>Click the Edit-button</li>
+ Bearbeiten.click()
+
+ '///+<li>Maximize the Basic IDE (required to ensure proper operation of mousemovements)</li>
+ sleep( 2 )
+ kontext "BasicIde"
+ BasicIde.maximize()
+
+ '///+<li>Verify that the Basic IDE is open, return TRUE on success</li>
+ if ( BasicIde.exists() ) then
+ printlog( CFN & "Open Basic-IDE for existing module: success" )
+ hOpenBasicIDE() = true
+ else
+ printlog( CFN & "Open Basic-IDE for existing module: failure" )
+ hOpenBasicIDE() = false
+ endif
+
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hCloseBasicIDE() as boolean
+
+ '///<h3>Close the BASIC-IDE with best effort verification</h3>
+ '///<i>Starting point: Basic IDE is open and has the focus</i>
+ '///<ol>
+ '///+<li>File-menu</li>
+ '///+<li>Slot FileClose</li>
+ '///+<li>hCloseDocument()/hDestroyDocument()</li>
+ '///</ol>
+ '///<ul>
+
+ use "global\tools\includes\optional\f_docfuncs.inc"
+
+ const CFN = "hCloseBasicIDE::"
+ dim brc as boolean
+
+ '///+<li>Close the macro controls float</li>
+ hCloseCollectionBar()
+
+ '///+<li>Try to close the current document</li>
+ brc = hDestroyDocument()
+ if ( brc ) then
+ hCloseBasicIDE() = true
+ else
+ hCloseBasicIDE() = false
+ qaerrorlog( "#i54135# Failed to close BASIC IDE" )
+ endif
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hReOpenBasicDialog() as boolean
+
+ '///<h3>Open BASIC-IDE after loading a workfile with documentbound macro</h3>
+ '///<i>Starting point: Focus on document containing at least one macro</i><br>
+ '///<i>IMPORTANT: Errorhandling is incomplete, test may end up in undefined state</i>
+ '///<ul>
+
+ dim brc as boolean
+
+ '///+<li>open the macro dialog, select the last module</li>
+ brc = hSelectTheLastModule( true )
+ if ( not brc ) then
+ warnlog( "Could not open the last module for editing." )
+ hReOpenBasicDialog() = false
+ exit function
+ endif
+
+ '///+<li>edit the module</li>
+ Bearbeiten.Click()
+
+ '///+<li>find the dialog window.</li>
+ kontext "BasicIDE"
+ BasicIde.maximize()
+
+ brc = hFindFirstDialog()
+ if ( not brc ) then
+ warnlog( "Could not find any dialog" )
+ hReOpenBasicDialog() = false
+ else
+ hReOpenBasicDialog() = true
+ endif
+
+ '///+<li>Return TRUE on success, FALSE on failure</li>
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hFindFirstDialog() as boolean
+
+ '///<h3>Find the first dialog in the BASIC-IDE</h3>
+ '///<i>Starting point: Basic IDE must be open and has the focus</i>
+ '///<ul>
+
+ dim iPosOverTabbar as integer
+ dim brc as boolean
+ const CFN = "hFindFirstDialog::"
+
+ '///+<li>Set focus to Basic IDE, maximize it</li>
+ kontext "BasicIde"
+ BasicIde.maximize()
+
+
+ brc = false
+
+ '///+<li>move pointer over the tabbar and click until a dialog opens (hopefully)</li>
+ for iPosOverTabbar = 1 to 20
+
+ Tabbar.MouseDown ( 5 * iPosOverTabbar , 50 )
+ Tabbar.MouseUp ( 5 * iPosOverTabbar , 50 )
+
+ if ( DialogWindow.Exists() ) then
+ brc = true
+ exit for
+ endif
+
+ next iPosOverTabbar
+
+ '///+<li>Return TRUE on success, FALSE on failure</li>
+ if ( brc ) then
+ printlog( CFN & "Found dialog" )
+ else
+ printlog( CFN & "Could not find the first dialog via tabbar" )
+ endif
+ hFindFirstDialog() = brc
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hSelectDialogPane() as boolean
+
+ '///<h3>Select the dialog pane in the Basic dialog editor</h3>
+ '///<i>Starting point: Basic dialog editor is open and has the focus</i>
+ '///<ul>
+
+ const CFN = "hSelectDialogPane::"
+ printlog( CFN & "Enter" )
+
+ '///+<li>Select background dialog by rubberband</li>
+ kontext "BasicIDE"
+
+ '///+<li>Set the mousepointer down at 90/90</li>
+ DialogWindow.mouseDown( 90 , 90 )
+
+ '///+<li>Move it to 10/10</li>
+ DialogWindow.mouseMove( 10 , 10 )
+
+ '///+<li>Release the mouse pointer at 10/10</li>
+ DialogWindow.mouseUp ( 10 , 10 )
+
+ '///+<li>Return TRUE, currently no verification is implemented</li>
+ printlog( CFN & "Exit: Selected dialog pane (not verified)" )
+ hSelectDialogPane() = true
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hCloseCollectionBar() as boolean
+
+ '///<h3>Close the ToolsCollectionBar (Macro Controls Float)</h3>
+ '///<i>Starting point: Basic Dialog editor is open, ToolsCollectionBar is open</i>
+ '///<ul>
+
+ const CFN = "hCloseCollectionBar::"
+ const RETRIES = 3
+
+ dim iTry as integer
+ iTry = 0
+
+ '///+<li>Try to close the ToolsCollectionBar max 3 times</li>
+ kontext "ToolsCollectionBar"
+ while ( ToolsCollectionBar.exists( 1 ) )
+ iTry = iTry + 1
+ printlog( CFN & "Closing ToolsCollectionBar..." )
+ ToolsCollectionBar.close()
+
+ if ( iTry = RETRIES ) then
+ printlog( CFN & "Failed to close ToolsCollectionBar" )
+ hCloseCollectionBar() = false
+ exit function
+ endif
+ wend
+
+ hCloseCollectionBar() = true
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hDeleteMacro() as boolean
+
+ '///<h3>Delete all text in the Basic IDE editor</h3>
+ '///<i>Starting point: Basic IDE is open, has focus, code can be edited</i>
+ '///<ul>
+
+ use "global\tools\includes\optional\t_accels.inc"
+
+ '///+<li>Verify all prerequisites are met (BasicIDE must be open)</li>
+ kontext "BasicIDE"
+ if ( not BasicIde.exists() ) then
+ warnlog( "hDeleteMacro::BasicIDE is not visible/active. Aborting" )
+ hDeleteMacro() = false
+ exit function
+ endif
+
+ dim brc as boolean
+
+ '///+<li>get the languagespecific accelerator for "Edit->Select All"</li>
+ dim cAccelerator as string
+ cAccelerator = hGetAccel( "SelectAll" )
+
+ printlog( "hDeleteMacro::Using Accel: " & cAccelerator )
+
+ ' Common for all actions is that we delete the existing macro before
+ ' inserting the new one. This fails if the accelerator for SelectAll
+ ' is incorrect, we try to recover by doing this manually then.
+ '///+<li>Delete the entire content of the Basic IDE editor</li>
+ EditWindow.TypeKeys( cAccelerator )
+ EditWindow.TypeKeys( "<Delete>" )
+
+ ' Verify that the EditWindow is empty, if not use a method that
+ ' should work for all languages/locales
+ '///+<li>Verify that the editor window is indeed empty</li>
+ brc = hIsEditWindowEmpty()
+ if ( not brc ) then
+ qaerrorlog( "#i52430# hDeleteMacro::Accelerator " & cAccelerator & " failed" )
+ printlog( "hDeleteMacro::Trying alternative method" )
+ EditWindow.TypeKeys( "<Mod1 Home>" )
+ EditWindow.TypeKeys( "<Mod1 Shift End>" )
+ EditWindow.TypeKeys( "<Delete>" )
+ brc = hIsEditWindowEmpty()
+ endif
+
+ '///+<li>Return TRUE on success, FALSE on failure</li>
+ hDeleteMacro() = brc
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hIsEditWindowEmpty() as boolean
+
+ '///<h3>Test if the Basic-EditWindow is empty</h3>
+ '///<i>Starting point: Basic IDE editor is open and has the focus</i>
+ '///<ul>
+
+ '///+<li>Verify that prerequisites are met: Basic IDE must be open</li>
+ kontext "BasicIDE"
+ if ( not BasicIDE.exists() ) then
+ warnlog( "hIsEditWindowEmpty::BasicIde is not open/visible" )
+ hIsEditWindowEmpty() = false
+ exit function
+ endif
+
+ '///+<li>Verify that the EditWindow is empty. EditCopy is disabled when empty</li>
+ EditWindow.TypeKeys( "<Mod1 Home>" )
+ EditWindow.TypeKeys( "<Mod1 Shift End>" )
+ try
+ EditCopy
+ printlog( "EditCopy should be enabled for empty Basic IDE editor" )
+ catch
+ setClipboard( "" )
+ endcatch
+
+ if ( getClipBoardText() <> "" ) then
+ hIsEditWindowEmpty() = false
+ printlog( "hIsEditWindowEmpty::no - content follows:" )
+ printlog( GetClipboardText )
+ else
+ hIsEditWindowEmpty() = true
+ printlog( "hIsEditWindowEmpty::yes" )
+ endif
+
+ '///+<li>Return TRUE on success, FALSE on failure</li>
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hRenameTab( cTabName as string ) as integer
+
+ '///<h3>Rename the first tab in the Basic IDE Tabbar</h3>
+ '///<i>Starting point: Basic IDE is open, at least one tab exists</i><br>
+ '///Return values are:
+ '///<ul>
+ '///+<li>0 = Tab was correctly renamed</li>
+ '///+<li>1 = Invalid name warning is displayed (handle outside of function)</li>
+ '///+<li>2 = Unknown error / failed to rename the tab</li>
+ '///+<li>3 = Unable to access context menu</li>
+ '///</ul>
+ '///Description
+ '///<ul>
+
+ const CFN = "hRenameTab::"
+
+ dim cString as string
+ dim iWait as integer
+ dim iTry as integer
+ dim brc as boolean
+ brc = false
+
+ cString = "<HOME><SHIFT END>" & cTabName & "<RETURN>"
+ kontext "basicide"
+
+ '///+<li>Open the context menu of the tabbar</li>
+ for iTry = 1 to 5
+ try
+ kontext "basicide"
+ Tabbar.OpenContextMenu
+ hMenuSelectNr( 3 )
+ sleep( 2 )
+ brc = true
+
+ catch
+ printlog( "No context menu, retrying..." )
+ endcatch
+ next iTry
+ '///+<li>Select to rename the tab</li>
+ if ( not brc ) then
+ warnlog( CFN & "Unable to access Context Menu" )
+ hRenameTab() = 3
+ exit function
+ endif
+
+ try
+ '///+<li>Overwrite the old name of the tab</li>
+ kontext "basicide"
+ Tabbar.TypeKeys( cString , true )
+ hRenameTab() = 0
+ printlog( CFN & "Tab renamed: " & cTabName )
+ catch
+ '///+<li>Handle possible errors</li>
+ hRenameTab() = 2
+ warnlog( CFN & "Failed to rename tab: " & cTabName )
+ exit function
+ endcatch
+
+ kontext "active"
+ for iWait = 1 to 3
+ sleep( 1 )
+ if ( active.exists() ) then
+ hRenameTab() = 1
+ printlog( CFN & "Invalid name for tab: Warning is displayed" )
+ exit for
+ endif
+ next iWait
+ '///+<li>Return 0, 1 or 2</li>
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hGetTabNameFromOrganizer() as string
+
+ '///<h3>Retrieve the name of a tab from the Basic Library Organizer</h3>
+ '///<i>Starting point: Basic IDE is open and has the focus</i>
+ '///<ul>
+
+ const CFN = "hGetTabNameFromOrganizer::"
+ dim cReturnString as string
+
+ '///+<li>Open the Basic Library Organizer</li>
+ '///+<li>Go to the Module-Tab</li>
+ '///+<li>Get the name of the currently selected item from the Module-list</li>
+ '///+<li>Close the Macro Library Organizer</li>
+ if ( hOpenBasicObjectOrganizer( 1 ) ) then
+ cReturnString = Modulliste.GetSelText()
+ TabModule.Close()
+ printlog( CFN & "Returning Tab-Name: " & cReturnString )
+ else
+ cReturnString = "Failure: Macro Organizer not open"
+ warnlog( CFN & cReturnString )
+
+ endif
+
+ '///+<li>Return the name from the Module-list</li>
+ hGetTabNameFromOrganizer() = cReturnString
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hNewDialog() as boolean
+
+ '///<h3>Create a new BASIC dialog</h3>
+ '///<i>Starting point: Basic IDE is open</i>
+ '///<ul>
+
+ const CFN = "hNewDialog::"
+
+ '///+<li>Open the context menu for the tabbar</li>
+ kontext "basicide"
+ Tabbar.OpenContextMenu
+
+ '///+<li>Select the first item (insert)</li>
+ hMenuSelectNr( 1 )
+ sleep( 1 )
+
+ '///+<li>Select the second item (new dialog)</li>
+ hMenuSelectNr( 2 )
+ sleep( 2 )
+
+ '///+<li>Verify that a new dialog is opened and has the focus</li>
+ if ( DialogWindow.Exists() ) then
+ printlog( CFN & "New dialog is open" )
+ hNewDialog() = true
+ else
+ warnlog( CFN & "New dialog is not open" )
+ hNewDialog() = false
+ endif
+ '///+<li>Return TRUE on success, FALSE on failure</li>
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hNewModule() as boolean
+
+ '///<h3>Create a new BASIC module</h3>
+ '///<i>Starting point: Basic IDE is open</i>
+ '///<ul>
+
+ const CFN = "hNewModule::"
+
+ '///+<li>Open the context menu for the tabbar</li>
+ kontext "basicide"
+ Tabbar.OpenContextMenu
+
+ '///+<li>Select the first item (insert)</li>
+ hMenuSelectNr( 1 )
+ sleep( 1 )
+
+ '///+<li>Select the first item (new module)</li>
+ hMenuSelectNr( 1 )
+ sleep( 2 )
+
+ '///+<li>Verify that a new module is opened and has the focus</li>
+ if ( EditWindow.Exists() ) then
+ printlog( CFN & "New module is open" )
+ hNewModule() = true
+ else
+ warnlog( CFN & "New module is not open" )
+ hNewModule() = false
+ endif
+ '///+<li>Return TRUE on success, FALSE on failure</li>
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hHideModule() as boolean
+
+ '///<h3>Hide a Basic Module from the IDE</h3>
+ '///<i>Starting point: Basic IDE is open and has the focus</i>
+ '///<ul>
+
+ const CFN = "hHideModule::"
+
+ kontext "basicide"
+
+ '///+<li>Open the context menu of the tabbar</li>
+ try
+ tabbar.openContextMenu
+
+ '///+<li>Select the fourth entry (Hide)</li>
+ hMenuSelectNr( 4 )
+ sleep( 1 )
+ hHideModule() = true
+ printlog( CFN & "Success" )
+ catch
+ hHideModule() = false
+ warnlog( CFN & "Failure" )
+ endcatch
+ '///+<li>Return TRUE on success, FALSE on any other condition (not verified)</li>
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hInitFormControls( cModule as string ) as boolean
+
+ '///<h3>Get from a new document to the Macro Controls Float in one go</h3>
+ '///<i>Starting point: Plain document</i><br>
+ '///This function performs following steps:
+ '///<ol>
+ '///+<li>Open the Basic Organizer</li>
+ '///+<li>Create a new module for the current document</li>
+ '///+<li>Open a new basic dialog</li>
+ '///+<li>Open the Macro controls float</li>
+ '///</ol>
+ '///Description:
+ '///<ul>
+
+ const CFN = "hInitFormControls::"
+ dim brc as boolean
+ '///+<li>Create and edit a new module for the current document</li>
+ brc = hInitBasicIde( cModule )
+ if ( not brc ) then
+ warnlog( "Could not create new module" )
+ hCloseBasicIde()
+ hInitFormControls() = false
+ exit function
+ endif
+
+ kontext "BasicIde"
+ BasicIde.maximize()
+
+ '///+<li>Create a new dialog.</li>
+ brc = hNewDialog()
+ if ( not brc ) then
+ warnlog( "Could not create Basic-Dialog" )
+ hCloseBasicIde()
+ hInitFormControls() = false
+ exit function
+ endif
+
+ '///+<li>Open the macro controls float.</li>
+ brc = hShowMacroControls()
+ if ( not brc ) then
+ warnlog( CFN & "Could not tear off the macro controls float" )
+ hCloseBasicIde()
+ hInitFormControls() = false
+ exit function
+ endif
+
+ '///+<li>Return TRUE if all went well, FALSE on any other error</li>
+ hInitFormControls() = true
+ '///</ul>
+ '///NOTE: The function will try to cleanup after itself in case of failure
+
+end function
+
+'*******************************************************************************
+
+function hInitBasicIde( cModule as string ) as boolean
+
+ '///<h3>Get from a new document to the Basic IDE in one go</h3>
+ '///<i>Starting point: New, plain document</i>
+ '///<ul>
+
+ use "global\tools\includes\optional\t_basic_organizer_tools.inc"
+ use "global\tools\includes\optional\t_listfuncs.inc"
+
+ const CFN = "hInitBasicIde::"
+
+ if ( cModule = "" ) then
+ warnlog( CFN & "Invalid parameter passed to function" )
+ hInitBasicIde() = false
+ exit function
+ endif
+
+ ' some multi-purpose return code
+ dim brc as boolean
+
+ '///+<li>Open the basic Organizer</li>
+ brc = hOpenBasicOrganizerFromDoc()
+ if ( not brc ) then
+ warnlog( CFN & "Could not open the Basic Organizer, aborting" )
+ hInitBasicIde() = false
+ exit function
+ endif
+
+ '///+<li>Create a new module for the current document</li>
+ brc = hCreateModuleForDoc( cModule )
+ if ( not brc ) then
+ warnlog( CFN & "The Basic-IDE is not open, aborting" )
+ hInitBasicIde() = false
+
+ kontext "Makro"
+ if ( Makro.exists() ) then
+ printlog( CFN & "Closed Macro Organizer" )
+ Makro.cancel()
+ endif
+ exit function
+ endif
+
+ '///+<li>Maximize the BasicIDE</li>
+ kontext "BasicIde"
+ BasicIde.maximize()
+
+ '///+<li>Verify that the Basic IDE is open, return TRUE on success, FASLE on failure</li>
+ hInitBasicIde() = true
+ '///</ul>
+ '///NOTE: The function will try to to clean up after itself in case of any error
+
+end function
+
+'*******************************************************************************
+
+function hInsertMacro( _id as integer ) as boolean
+
+ '///<h3>Insert a macro into the Basic-IDE edit window by Index</h3>
+ '///<i>Starting point: Basic IDE is open, has the focus</i>
+ '///<ul>
+
+ const CFN = "hInsertMacro::"
+ dim brc as boolean
+
+ if ( ( _id < 1 ) or ( _id > 3 ) ) then
+ warnlog( CFN & "Invalid parameter passed to function: " & _id )
+ hInsertMacro() = false
+ exit function
+ endif
+
+ kontext "basicide"
+
+ '///+<li>Delete the content of the edit window</li>
+ brc = hDeleteMacro()
+ if ( not brc ) then
+ warnlog( CFN & "Content of Basic-IDE was not deleted" )
+ hInsertMacro() = false
+ exit function
+ endif
+
+ '///+<li>Insert a macro by index (passed as function parameter)</li>
+ select case _id
+ case 1 :
+ ' this is a working macro that contains no errors
+ EditWindow.TypeKeys( "'# TTMacro1: This is a short testscript for automated testing!<return><return>" )
+ EditWindow.TypeKeys( "sub main<return><return>" )
+ EditWindow.TypeKeys( "print " & Chr (34) + "hallo" & Chr (34) )
+ EditWindow.TypeKeys( "<Return><Return>" )
+ EditWindow.TypeKeys( "<Home>end sub<return>" )
+ hInsertMacro() = true
+ printlog( CFN & "Inserted: " & _id )
+ case 2 :
+ EditWindow.TypeKeys( "'# TTMacro2: a second module for automated testing!" )
+ EditWindow.TypeKeys( "<Return><Return>" )
+ hInsertMacro() = true
+ printlog( CFN & "Inserted: " & _id )
+ case 3 :
+ EditWindow.TypeKeys( "'# TTMacro3: Bring up a messagebox<return><return>" )
+ EditWindow.TypeKeys( "sub main<return><return>" )
+ EditWindow.TypeKeys( " msgbox " & Chr (34) + "TTMacro3" & Chr (34) )
+ EditWindow.TypeKeys( "<Return><Return>" )
+ EditWindow.TypeKeys( "<Home>end sub<return>" )
+ hInsertMacro() = true
+ printlog( CFN & "Inserted: " & _id )
+ end select
+
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hTestMacro( _id as integer ) as integer
+
+ '///<h3>Verify that the correct macro is visible in the IDE edit Window</h3>
+ '///<i>Starting point: Basic IDE is open and has focus</i>
+ '///<ul>
+
+ const CFN = "hTestMacro::"
+
+ kontext "basicide"
+
+ '///+<li>Copy the first line in the editwindow to clipboard</li>
+ EditWindow.TypeKeys( "<Mod1 Home>" )
+ EditWindow.TypeKeys( "<Home><Shift End>" )
+ EditCopy
+
+ '///+<li>Compare the string to a unique substring for the macro</li>
+ select case _id
+ case 1 :
+ if ( Instr ( GetClipboardText, "TTMacro1" ) <> 0 ) then
+ printlog( CFN & "The correct macro is displayed in the editwindow" )
+ htestMacro() = 1
+ exit function
+ endif
+ case 2 :
+ if ( Instr ( GetClipboardText, "TTMacro2" ) <> 0 ) then
+ printlog( CFN & "The correct macro is displayed in the editwindow" )
+ htestMacro() = 2
+ exit function
+ endif
+ case 3 :
+ if ( Instr ( GetClipboardText, "TTMacro3" ) <> 0 ) then
+ printlog( CFN & "The correct macro is displayed in the editwindow" )
+ htestMacro() = 3
+ exit function
+ endif
+ end select
+
+ hTestMacro() = 0
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hCreateBasicWorkFiles() as string
+
+ '///<H3>Create a macro, attach it to a file, save the file</H3>
+ '///<i>Starting point: The first doc or any other plain document</i>
+ '///<ul>
+ const CFN = "hCreateBasicWorkFiles::"
+ const CMACRO = "TestMacro"
+
+ ' some returncodes
+ dim brc as boolean
+ dim irc as integer
+ dim crc as string
+
+ dim sFile as string
+ sFile = hGetBasicWorkFile( "CURRENT" )
+
+ '///+<li>Open a new document</li>
+ call hCreateDocument()
+
+ '///+<li>Change the document (to save it)</li>
+ crc = hChangeDoc()
+ printlog( CFN & crc )
+
+ '///+<li>Open Basic-Organizer, select the document and create a module</li>
+ brc = hInitBasicIde( CMACRO )
+ if ( not brc ) then
+ printlog( CFN & "Unable to create a module, aborting" )
+ call hDestroyDocument()
+ hCreateBasicWorkFiles() = ""
+ exit function
+ endif
+
+ '///+<li>Insert a macro that triggers a messagebox</li>
+ brc = hInsertMacro( 3 )
+ if ( not brc ) then
+ printlog( CFN & "Unable to insert macro, aborting" )
+ hCloseBasicIde()
+ call hDestroyDocument()
+ hCreateBasicWorkFiles() = ""
+ exit function
+ endif
+
+ '///+<li>Close the Basic-IDE</li>
+ brc = hCloseBasicIde()
+
+ '///+<li>Save the file without autoextension, overwrite existing</li>
+ brc = hFileSaveAsKill( sFile )
+ if ( not brc ) then
+ printlog( CFN & "Unknown error while saving the file. Resetting" )
+ call ExitRestartTheOffice
+ hCreateBasicWorkFiles() = ""
+ exit function
+ endif
+
+ '///+<li>Close the document</li>
+ call hDestroyDocument()
+
+ '///</ul>
+
+end function
+
+
+'*******************************************************************************
+
+function hIDESelectTabByIndex( iIndex as integer ) as string
+
+ use "global\tools\includes\optional\t_accels.inc"
+
+
+ '///<h3>Select a tab within the BASIC-IDE by index</h3>
+ '///<i>The BASIC-IDE has to be open and has the focus. This function
+ '///+ selects the tab by sending CTRL+PAGEUP or CTRL+PAGEDOWN to the IDE using
+ '///+ the .typeKeys method. It is assumed that - when opening the IDE - the
+ '///+ first tab is active. When the specified index has been reached we
+ '///+ retrieve the name of the current tab by opening the context menu on the
+ '///+ tab and selecting &quot;Rename&quot;. The name (which should be
+ '///+ highlighted by default) is then copied to the clipboard and returned
+ '///+ to the calling function.</i><br><br>
+
+ '///<u>Parameter(s):</u><br>
+ '///<ol>
+
+ '///+<li>Index of the requested Tab (Integer)</li>
+ '///<ul>
+ '///+<li>Index must not be negative</li>
+ '///+<li>0 does nothing (returning the name of the current tab)</li>
+ '///+<li>Index must be &le; present number of tabs</li>
+ '///+<li>If Index &gt; number of tabs, the last tab is selected</li>
+ '///</ul>
+
+ '///</ol>
+
+
+ '///<u>Returns:</u><br>
+ '///<ol>
+ '///+<li>Name of the selected tab (string)</li>
+ '///<ul>
+ '///+<li>Always evaluate the returnvalue</li>
+ '///</ul>
+ '///</ol>
+
+ const CFN = "hIDESelectTabByIndex::"
+ printlog( CFN & "Enter with option: " & iIndex )
+ dim brc as boolean 'a multi purpose boolean returnvalue
+
+ dim cTabName as string
+ dim iCurrentTab as integer
+ dim cAccel as string
+
+ '///<u>Description:</u>
+ '///<ul>
+ '///+<li>Set context to BASIC IDE</li>
+ kontext "BasicIDE"
+
+ '///+<li>Retrieve the accelerator to switch tabs</li>
+ '///+<li>Switch tabs</li>
+ select case iIndex
+ case 0 : cAccel = ""
+ case 1 : cAccel = hGetAccel( "IDE_SWITCH_TAB-" )
+ for iTab = 1 to 20
+ BasicIDE.typeKeys( cAccel )
+ next iTab
+ case else: cAccel = hGetAccel( "IDE_SWITCH_TAB+" )
+ for iTab = 1 to iIndex
+ BasicIDE.typeKeys( cAccel )
+ next iTab
+ end select
+
+ '///+<li>Select the Tabbar</li>
+ Kontext "Tabbar"
+
+ '///+<li>Open the context menu</li>
+ hUseMenu()
+
+ '///+<li>Select &quot;Rename&quot;</li>
+ hSelectMenuNr( 3 )
+
+ '///+<li>Copy the selected string to the clipboard</li>
+ EditCopy
+
+ '///+<li>Send ESC to the tabbar to deselect the tab</li>
+ Kontext "Tabbar"
+ Tabbar.typeKeys( "<ESCAPE>" )
+
+ '///+<li>Copy the string from clipboard to a local variable</li>
+ cTabName = getClipboardText
+
+ '///+<li>Print exit message, set return value</li>
+ printlog( CFN & "Exit with result: " & cTabName )
+ hIDESelectTabByIndex() = cTabName
+ '///</ul>
+
+end function
diff --git a/testautomation/global/tools/includes/optional/t_basic_organizer_tools.inc b/testautomation/global/tools/includes/optional/t_basic_organizer_tools.inc
new file mode 100755
index 000000000000..eb2b302f9199
--- /dev/null
+++ b/testautomation/global/tools/includes/optional/t_basic_organizer_tools.inc
@@ -0,0 +1,526 @@
+'encoding UTF-8 Do not remove or change this line!
+'**************************************************************************
+'* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+'*
+'* Copyright 2008 by Sun Microsystems, Inc.
+'*
+'* OpenOffice.org - a multi-platform office productivity suite
+'*
+'* $RCSfile: t_basic_organizer_tools.inc,v $
+'*
+'* $Revision: 1.1 $
+'*
+'* last change: $Author: jsk $ $Date: 2008-06-20 07:57:24 $
+'*
+'* This file is part of OpenOffice.org.
+'*
+'* OpenOffice.org is free software: you can redistribute it and/or modify
+'* it under the terms of the GNU Lesser General Public License version 3
+'* only, as published by the Free Software Foundation.
+'*
+'* OpenOffice.org is distributed in the hope that it will be useful,
+'* but WITHOUT ANY WARRANTY; without even the implied warranty of
+'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+'* GNU Lesser General Public License version 3 for more details
+'* (a copy is included in the LICENSE file that accompanied this code).
+'*
+'* You should have received a copy of the GNU Lesser General Public License
+'* version 3 along with OpenOffice.org. If not, see
+'* <http://www.openoffice.org/license.html>
+'* for a copy of the LGPLv3 License.
+'*
+'/************************************************************************
+' **
+' ** owner : joerg.skottke@sun.com
+' **
+' ** short description : tools for tools/macro test
+' **
+'\******************************************************************************
+
+function hSelectTheLastModule( bEditEnabled as Boolean ) as string
+
+ '///<h3>Select the last (editable) module in the macro seletor treelist</li>
+
+ use "global\tools\includes\optional\t_treelist_tools.inc"
+
+ const CFN = "hSelectTheLastModule()::"
+
+ dim bCloseDialog as boolean : bCloseDialog = FALSE
+ dim iNodeCount as integer
+ dim iCurrentNode as integer
+
+ hSelectTheLastModule() = ""
+
+ kontext "Makro"
+ if ( not Makro.exists() ) then ToolsMacro_uno : bCloseDialog = TRUE
+
+ kontext "Makro"
+ iNodeCount = hSelectTheLastNode( MakroAus )
+
+ if ( bEditEnabled ) then
+ for iCurrentNode = iNodeCount to 1 step -1
+ if ( Bearbeiten.isEnabled() ) then
+ printlog( CFN & "Editable module found at pos: " & iCurrentNode )
+ exit for
+ endif
+ next iCurrentNode
+ else
+ printlog( CFN & "Module selected at pos: " & iNodeCount )
+ endif
+
+ if ( iCurrentNode > 1 ) then hSelectTheLastModule = MakroAus.getSelText()
+
+end function
+
+'*******************************************************************************
+
+function hCreateModuleForDoc( optional cName as string ) as boolean
+
+ use "global\tools\includes\optional\t_treelist_tools.inc"
+ use "global\tools\includes\optional\t_stringtools.inc"
+
+ '///<h3>Create a new Basic module for the current document</h3>
+ '///<i>Starting point: Basic Macro Organizer is visible and has focus</i>
+ '///<ul>
+
+ const CFN = "hCreateModuleForDoc::"
+
+ dim iWait as integer ' how long we had to wait for the IDE to open
+ dim iPos as integer
+ dim brc as boolean ' boolean returncode, a temporary variable
+ brc = false
+ dim cMsg as string
+
+ ' make sure that we have a name for the module
+ if ( isMissing( cName ) ) Then
+ cName = "TTModule"
+ endif
+
+ '///+<li>Select the last module (it should belong to the current document)</li>
+ kontext "Makro"
+ iPos = hSelectTheLastNode( MakroAus )
+
+ '///+<li>Click the New-Button, name the module</li>
+ if ( Neu.isEnabled() ) then
+ 'printlog( CFN & "New-button is enabled" )
+ else
+ warnlog( CFN & "New-button is disabled" )
+ hCreateModuleForDoc() = false
+ exit function
+ endif
+
+ Neu.Click()
+
+ '///+<li>If the module already exists we end up on the Deletion dialog</li>
+ kontext "Active"
+ if ( Active.exists() ) then
+ cMsg = active.getText()
+ cMsg = hRemoveLineBreaks( cMsg )
+ printlog( "Module seems to exist, deleting Main: " & cMsg )
+ Active.Yes()
+ endif
+
+ Kontext "NeuesModul"
+ if ( NeuesModul.exists() ) then
+ Modulname.SetText( cName )
+ NeuesModul.OK()
+ else
+ warnlog( CFN & "Failed create a new module, aborting" )
+ hCreateModuleForDoc() = false
+ kontext "Makro"
+ Makro.cancel()
+ exit function
+ endif
+
+ '///+<li>Wait for the BASIC_IDE to open, verify</li>
+ ' BasicIDE is bad for "Kontexting", using the default toolbar instead
+ kontext "MacroBar"
+ if ( MacroBar.exists( 3 ) ) then
+ printlog( CFN & "Exit: New module: " & cName & ". IDE is open" )
+ brc = true
+ else
+ warnlog( CFN & "Exit: Failed to create the Module" )
+ brc = false
+ endif
+
+ hCreateModuleForDoc() = brc
+ '///+<li>Return TRUE on success, FALSE on failure</li>
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hOpenBasicObjectOrganizer( iTabPage as integer ) as boolean
+
+ '///<h3>Open the Basic Library/Module/Dialog Organizer</h3>
+ '///<i>Starting point: Basic IDE is open and has focus</i>
+ '///<ul>
+
+ const CFN = "hOpenBasicObjectOrganizer::"
+
+ ' This function opens a specified tab on the BASIC Organizer from the
+ ' BASIC-IDE
+ ' NOTE: This is the organizer for libraries, modules and dialogs,
+ ' not the one to run or assign macros!
+
+ dim iMenuSize as integer
+ dim brc as boolean
+
+ '///+<li>Open the context menu of the tabbar</li>
+ kontext "basicide"
+ Tabbar.OpenContextMenu
+
+ '///+<li>Select the last entry of the context menu (dynamic menu!)</li>
+ iMenuSize = hMenuItemgetCount()
+ if ( iMenuSize = 2 ) then
+ printlog( " * short context menu (no edit-window)" )
+ hMenuSelectNr( 2 )
+ else
+ printlog( " * long context menu (edit-window/dialog visible)" )
+ hMenuSelectNr( 5 )
+ endif
+
+ WaitSlot()
+
+ '///+<li>On the basic object organizer switch to the Modules tab</li>
+ brc = hSelectBasicObjectOrganizerTab( 1 )
+ if ( not brc ) then
+ warnlog( CFN & "Failed to open requested Tabpage" )
+ hOpenBasicObjectOrganizer() = false
+ else
+ printlog( CFN & "Requested page is open" )
+ hOpenBasicObjectOrganizer = true
+ endif
+ '///+<li>Return TRUE on success, FALSE on failure</li>
+ '///</ul>
+
+
+end function
+
+'*******************************************************************************
+
+function hOpenBasicOrganizerFromDoc() as boolean
+
+ '///<h3>Open the Basic Macro Organizer from a plain document</h3>
+ '///<i>Starting point: Plain document</i>
+ '///<ul>
+
+ const CFN = "hOpenBasicOrganizerFromDoc::"
+
+ '///+<li>Use the slot ToolsMacro_uno to open the Basic Macro organizer</li>
+ ToolsMacro_uno
+
+ '///+<li>Verify that the dialog is open</li>
+ kontext "Makro"
+ if ( not Makro.exists() ) then
+ warnlog( CFN & "Could not open Macro Organizer" )
+ hOpenBasicOrganizerFromDoc() = false
+ exit function
+ endif
+
+ call dialogtest( Makro )
+
+ '///+<li>Return TRUE on success, FALSE on failure</li>
+ printlog( CFN & "Basic Organizer is open" )
+ hOpenBasicOrganizerFromDoc() = true
+ kontext "Makro"
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hSelectBasicObjectOrganizerTab( iTabPage as integer ) as boolean
+
+ const CFN = "hSelectBasicObjectOrganizerTab::"
+
+ '///<h3>Switch between tab pages in the Basic Object Organizer</h3>
+ '///<i>Starting point: Masic Object Organizer is visible and has focus</i>
+ '///<ol>
+ '///+<li>1 = Modules</li>
+ '///+<li>2 = Dialogs</li>
+ '///+<li>3 = Libraries</li>
+ '///</ol>
+ '///Description:
+ '///<ul>
+
+ '///+<li>Verify function parameters</li>
+ if ( ( iTabPage < 1 ) or ( iTabPage > 3 ) ) then
+ warnlog( CFN & "Illegal argument passed to function: " & iTabPage )
+ hSelectBasicObjectOrganizerTab() = false
+ exit function
+ endif
+
+ '///+<li>Switch between tabpages 1, 2 or 3</li>
+ select case iTabPage
+ case 1 :
+ kontext
+ Active.SetPage TabModule
+ kontext "tabmodule"
+ if ( TabModule.exists() ) then
+ printlog( CFN & "Modules-Tab is open"
+ hSelectBasicObjectOrganizerTab() = true
+ exit function
+ endif
+
+ case 2 :
+ kontext
+ Active.setPage TabDialogs
+ kontext "tabdialogs"
+ if ( TabDialogs.exists() ) then
+ printlog( CFN & "Dialogs-Tab is open"
+ hSelectBasicObjectOrganizerTab() = true
+ exit function
+ endif
+ case 3 :
+ kontext
+ Active.setPage TabBibliotheken
+ kontext "tabbibliotheken"
+ if ( TabBibliotheken.exists() ) then
+ printlog( CFN & "Libraries-Tab is open"
+ hSelectBasicObjectOrganizerTab() = true
+ exit function
+ endif
+ end select
+
+ '///+<li>Return TRUE on success, FALSE on failure</li>
+ '///</ul>
+ hSelectBasicObjectOrganizerTab() = false
+
+end function
+
+'*******************************************************************************
+
+function hDeleteLibrary( iLocation as integer, cLibName as string ) as boolean
+
+ '///<h3>Delete a library by name via Macro Object Organizer</h3>
+ '///<i>Starting point: Plain document</i>
+ '///<ul>
+
+ const CFN = "hDeleteLibrary::"
+ const ITABPOS = 3
+
+ '///+<li>Verify function parameters</li>
+ if ( ( iLocation < 1 ) or ( iLocation > 3 ) ) then
+ warnlog( CFN & "Invalid parameter passed to function" )
+ hDeleteLibrary() = false
+ endif
+
+ dim iObjectCount as integer
+ dim iCurrentObject as integer
+ dim cCurrentObjectName as string
+
+ '///+<li>Open Macro Organizer</li>
+ hOpenBasicOrganizerFromDoc()
+
+ '///+<li>Click Manage-button</li>
+ Kontext "Makro"
+ Verwalten.click()
+
+ '///+<li>Go to the Libraries Tab on the Macro Object Organizer</li>
+ hSelectBasicObjectOrganizerTab( ITABPOS )
+
+ '///+<li>Select the root node in the libraries treelist</li>
+ ' Needs to be specified to avoid touching the wrong library (e.g. a protected one)
+ kontext "TabBibliotheken"
+ Bibliothek.select( iLocation )
+ iObjectCount = Bibliotheksliste.getItemCount()
+
+ '///+<li>Find the requested item in the treelist</li>
+ for iCurrentObject = 1 to iObjectCount
+
+ Bibliotheksliste.select( iCurrentObject )
+ cCurrentObjectName = Bibliotheksliste.getSelText()
+ if ( cCurrentObjectName = cLibName ) then
+
+ '///+<li>Click Delete</li>
+ Loeschen.click()
+ exit for
+ endif
+
+ next iCurrentObject
+
+ '///+<li>Confirm to delete library</li>
+ Kontext "Active"
+ if ( Active.exists() ) then
+ active.yes()
+ else
+ warnlog( CFN & "No confirmation for delete" )
+ endif
+
+ '///+<li>Verify that there is one item less in the treelist (object has been deleted)</li>
+ kontext "TabBibliotheken"
+ if ( Bibliotheksliste.getItemCount() = ( iObjectCount - 1 ) ) then
+ printlog( CFN & "Library has been deleted" )
+ hDeleteLibrary() = true
+ else
+ printlog( CFN & "Library has not been deleted" )
+ hDeleteLibrary() = false
+ endif
+
+ '///+<li>Cancel Macro Object Organizer</li>
+ TabBibliotheken.cancel()
+
+ '///+<li>Cancel Basic Macro Organizer</li>
+ Kontext "Makro"
+ Makro.cancel()
+ '///+<li>Return TRUE on success, FALSE on failure</li>
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hIsMacroEditButtonEnabled() as boolean
+
+ '///<h3>Test whether the "Edit..." button is enabled or not</h3>
+ '///<i>Starting point: Basic Macro Organizer</i>
+ '///<ul>
+
+ const CFN = "hIsMacroEditButtonEnabled::"
+ dim brc as boolean
+
+ '///+<li>Check that the macro dialog is open</li>
+ Kontext "Makro"
+ if ( not Makro.exists() ) then
+ warnlog( "Macro organizer is not open, aborting function" )
+ hIsMacroEditButtonEnabled() = false
+ exit function
+ endif
+
+ '///+<li>Verify that the Edit...-Button exists and is enabled</li>
+ if ( bearbeiten.exists() ) then
+ if ( bearbeiten.isEnabled() ) then
+ printlog( CFN & "Button exists and is enabled" )
+ brc = true
+ else
+ printlog( CFN & "Button exists but is disabled" )
+ brc = false
+ endif
+ else
+ warnlog( CFN & "Button does not exist" )
+ brc = false
+ endif
+
+ '///+<li>Return TRUE if button exists and is enabled</li>
+ '///</ul>
+ hIsMacroEditButtonEnabled() = brc
+
+end function
+
+'*******************************************************************************
+
+function hIsMacroNewButtonEnabled() as boolean
+
+ '///<h3>Find out whether the "New..." button is enabled or not</h3>
+ '///<i>Starting point: Basic Macro Organizer</i>
+ '///<ul>
+
+ const CFN = "hIsMacroNewButtonEnabled::"
+ dim brc as boolean
+
+ '///+<li>Check that the macro dialog is open</li>
+ Kontext "Makro"
+ if ( not Makro.exists() ) then
+ warnlog( "Macro organizer is not open, aborting function" )
+ hIsMacroNewButtonEnabled() = false
+ exit function
+ endif
+
+ '///+<li>Verify that the New...-Button exists and is enabled</li>
+ if ( neu.exists() ) then
+ if ( neu.isEnabled() ) then
+ printlog( CFN & "Button exists and is enabled" )
+ brc = true
+ else
+ printlog( CFN & "Button exists but is disabled" )
+ brc = false
+ endif
+ else
+ warnlog( CFN & "Button does not exist" )
+ brc = false
+ endif
+
+ '///+<li>Return TRUE if button exists and is enabled</li>
+ '///</ul>
+ hIsMacroNewButtonEnabled() = brc
+
+end function
+
+'*******************************************************************************
+
+function hNameBasicModule( cName as string ) as boolean
+
+ '///<h3>Name a Basic Module</h3>
+ '///<i>Starting point: Clicked &quot;New...&quot; button in Basic Macro organizer.<br>
+ '///+ On success the kontext will be on the Basic IDE. In case of
+ '///+ failure we remain on the naming dialog so that the function can be
+ '///+ triggered again.</i><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Name of the module (string)</li>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Errorcondition (Boolean)</li>
+ '///<ul>
+ '///+<li>TRUE if name is valid, module has been created</li>
+ '///+<li>FALSE if name is invalid or naming dialog does not exist</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+ use "global\tools\includes\optional\t_stringtools.inc"
+
+ const CFN = "hNameBasicModule::"
+ dim brc as boolean
+ brc = true
+ dim cMsg as string
+
+ '///+<li>Verify that the naming dialog is open</li>
+ kontext "NeuesModul"
+ if ( not NeuesModul.exists() ) then
+ hNameBasicModule() = false
+ exit function
+ endif
+
+ '///+<li>Insert the name into the EntryField</li>
+ Modulname.SetText( cName )
+
+ '///+<li>Accept the name with OK</li>
+ NeuesModul.OK()
+
+ '///+<li>If there is no warning, the name should be valid.</li>
+ kontext "BasicIDE"
+ if ( BasicIde.exists( 2 ) ) then
+ brc = true
+ printlog( CFN & "Name accepted, Basic-Ide is open" )
+ else
+ brc = false
+ '///+<li>Look for invalid name warning, close it</li>
+ kontext "active"
+ if ( active.exists() ) then
+ cMsg = active.getText()
+ cMsg = hRemoveLineBreaks( cMsg
+ printlog( CFN & "Msgbox: " & cMsg )
+ active.ok()
+ endif
+
+ '///+<li>If the name is invalid, get back to the naming-dialog</li>
+ kontext "NeuesModul"
+ if ( NeuesModul.exists() ) then
+ printlog( CFN & "Name not accepted, focus on naming-dialog" )
+ else
+ warnlog( CFN & "Naming failed but we are not on the naming dialog" )
+ endif
+ endif
+
+ hNameBasicModule() = brc
+ '///</ul>
+
+end function
+
+
+
diff --git a/testautomation/global/tools/includes/optional/t_control_objects.inc b/testautomation/global/tools/includes/optional/t_control_objects.inc
new file mode 100755
index 000000000000..79b28ece9214
--- /dev/null
+++ b/testautomation/global/tools/includes/optional/t_control_objects.inc
@@ -0,0 +1,608 @@
+'encoding UTF-8 Do not remove or change this line!
+'**************************************************************************
+'* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+'*
+'* Copyright 2008 by Sun Microsystems, Inc.
+'*
+'* OpenOffice.org - a multi-platform office productivity suite
+'*
+'* $RCSfile: t_control_objects.inc,v $
+'*
+'* $Revision: 1.1 $
+'*
+'* last change: $Author: jsk $ $Date: 2008-06-20 07:57:33 $
+'*
+'* This file is part of OpenOffice.org.
+'*
+'* OpenOffice.org is free software: you can redistribute it and/or modify
+'* it under the terms of the GNU Lesser General Public License version 3
+'* only, as published by the Free Software Foundation.
+'*
+'* OpenOffice.org is distributed in the hope that it will be useful,
+'* but WITHOUT ANY WARRANTY; without even the implied warranty of
+'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+'* GNU Lesser General Public License version 3 for more details
+'* (a copy is included in the LICENSE file that accompanied this code).
+'*
+'* You should have received a copy of the GNU Lesser General Public License
+'* version 3 along with OpenOffice.org. If not, see
+'* <http://www.openoffice.org/license.html>
+'* for a copy of the LGPLv3 License.
+'*
+'/************************************************************************
+'*
+'* owner : joerg.skottke@sun.com
+'*
+'* short description : Functions to manipulate controls by accessing them as objects
+'*
+'*******************************************************************************
+'**
+' #0 checkRadioButtons ' check a group of RBs where the sel. RB is given by number
+' #0 checkRadioButton ' check a singe RB where the state is specified directly
+' #0 checkCheckbox ' check a single checkbox
+' #0 setCheckBox ' sets checkbox to status provided in reference file
+' #0 checkComboBox ' compares an index to one provided in a reference-file
+' #0 setComboBox ' selects an index provided by a reference file
+' #0 checkListBox ' compares an index to one provided in a reference-file
+' #0 setListBox ' selects an index provided by a reference file
+' #0 checkListItem ' check that a listitem is correct
+' #1 hSetControlValue ' Change the value of a EntryField (failsafe)
+'**
+'\******************************************************************************
+
+function checkRadioButtons( _file as string , sKey as string , control1 as object , control2 as object , optional control3 as object , optional control4 as object ) as integer
+
+ '///<h3>EXPERIMENTAL: Get/Set function for some control types</h3>
+ '///<i>This is a function that allows to change the state/content of a
+ '///+ control via a configuration file. This function is experimental
+ '///+ and should not be used.<br>
+ '///+ This function checks if the correct radiobutton of a group is selected.
+ '///+ at least two radiobuttons must be provided, the third and fouth are optional.
+ '///+ The value for sKey in the reference file must be of type integer</i><br>
+
+ dim _sItem as string
+ dim _iItem as integer
+
+ ' lowercase sKey for comparision
+ sKey = lcase( sKey )
+
+ ' get the reference value for sKey as string
+ _sItem = hGetFileData( _file , sKey )
+
+ ' cast it to int
+ _iItem = val( _sItem )
+
+ ' check which one of the up to four radiobuttons is selected.
+ select case _iItem
+
+ case 1 :
+ if ( control1.isChecked() = true ) then
+ checkRadioButtons() = true
+ printlog( " * Radiobutton 1 selected: ok" )
+ else
+ warnlog( "The wrong radiobutton is selected" )
+ endif
+
+ case 2 :
+ if ( control2.isChecked() = true ) then
+ checkRadioButtons() = true
+ printlog( " * Radiobutton 2 selected: ok" )
+ else
+ warnlog( "The wrong radiobutton is selected" )
+ endif
+
+ case 3 :
+ if ( isMissing( control3 ) = false ) then
+ if ( control3.isChecked() = true ) then
+ checkRadioButtons() = true
+ printlog( " * Radiobutton 3 selected: ok" )
+ else
+ warnlog( "The wrong radiobutton is selected" )
+ endif
+ else
+ warnlog( "referencing to non-existing control." )
+ checkRadioButtons() = false
+ endif
+
+ case 4 :
+ if ( isMissing( control4 ) = false ) then
+ if ( control4.isChecked() = true ) then
+ checkRadioButtons() = true
+ printlog( " * Radiobutton 4 selected: ok" )
+ else
+ warnlog( "The wrong radiobutton is selected" )
+ endif
+ else
+ warnlog( "referencing to non-existing control." )
+ checkRadioButtons() = false
+ endif
+
+ case else
+ warnlog( "Maximum of four connected radiobuttons allowed." )
+ checkRadioButtons() = false
+ end select
+
+end function
+
+'*******************************************************************************
+
+function checkRadioButton( _file as string , sKey as string , control as object ) as boolean
+
+ '///<h3>EXPERIMENTAL: Get/Set function for some control types</h3>
+ '///<i>This is a function that allows to change the state/content of a
+ '///+ control via a configuration file. This function is experimental
+ '///+ and should not be used.<br>
+
+ ' a wrapper. The routine is identical to checkCheckBox.
+
+ checkRadioButton = checkCheckBox( _file , sKey , control )
+
+end function
+
+'*******************************************************************************
+
+function checkCheckBox( _file as string , sKey as string , control as object , optional cBugID as string ) as boolean
+
+ '///<h3>EXPERIMENTAL: Get/Set function for some control types</h3>
+ '///<i>This is a function that allows to change the state/content of a
+ '///+ control via a configuration file. This function is experimental
+ '///+ and should not be used.<br>
+
+ dim bIsChecked as boolean
+ dim sIsChecked as string
+ dim _sIsChecked as string
+
+ if ( ismissing( cBugID ) ) then
+ cBugID = "WriteMe!"
+ endif
+ if ( sKey = "*" ) then
+ sKey = control.name()
+ endif
+
+ sKey = lcase( sKey )
+ _sIsChecked = lcase( hGetFileData( _file , sKey ) )
+
+ if ( _sIsChecked <> "disabled" ) then
+
+ ' look if the control is present on the current dialog
+ if ( control.exists() and _
+ control.IsVisible() and _
+ control.IsEnabled() ) then
+
+ ' find out whether it is checked or not, create strings for errormessage
+ bIsChecked = control.isChecked()
+ if ( bIsChecked = true ) then
+ sIsChecked = "checked"
+ else
+ sIsChecked = "unchecked"
+ endif
+
+ ' compare
+ keycompare( sIsChecked , _sIsChecked , sKey , cBugID )
+ checkCheckBox() = control.isChecked()
+
+ else
+
+ warnlog( "Control <" & sKey & "> could not be accessed." )
+
+ endif
+
+ else
+
+ if ( control.IsEnabled() ) then
+ warnlog( "The control should be disabled but it is not: " & sKey )
+ endif
+
+ endif
+
+end function
+
+'*******************************************************************************
+
+function setCheckBox( _file as string , sKey as string , control as object , optional bverbose as boolean ) as boolean
+
+ '///<h3>EXPERIMENTAL: Get/Set function for some control types</h3>
+ '///<i>This is a function that allows to change the state/content of a
+ '///+ control via a configuration file. This function is experimental
+ '///+ and should not be used.<br>
+
+ dim sIsChecked as string
+ dim _sIsChecked as string
+
+ if ( sKey = "*" ) then
+ sKey = control.name()
+ endif
+ if ( ismissing( bverbose ) ) then
+ bverbose = true
+ endif
+
+ sKey = lcase( sKey )
+ _sIsChecked = lcase( hGetFileData( _file , sKey ) )
+
+ if ( _sIsChecked <> "disabled" ) then
+
+ if ( control.exists() and _
+ control.IsVisible() and _
+ control.IsEnabled() ) then
+
+ select case _sIsChecked
+
+ case "checked"
+ control.check()
+ setCheckBox() = true
+ case "unchecked"
+ control.uncheck()
+ setCheckBox() = false
+ case else
+ warnlog( "what?" )
+
+ end select
+
+ if ( bverbose ) then
+ printlog( " * " & sKey )
+ endif
+
+ else
+
+ ' warn if the control could not be used (only works in rare cases)
+ warnlog( "Control <" & sKey & "> is not accessible." )
+
+ endif
+
+ else
+
+ if ( control.IsEnabled() ) then
+ warnlog( "The control should be disabled but it is not: " & sKey )
+ endif
+
+ endif
+
+end function
+
+'*******************************************************************************
+
+function checkComboBox( _file as string , sKey as string , control as object ) as boolean
+
+ '///<h3>EXPERIMENTAL: Get/Set function for some control types</h3>
+ '///<i>This is a function that allows to change the state/content of a
+ '///+ control via a configuration file. This function is experimental
+ '///+ and should not be used.<br>
+
+ dim controltext as string ' current state
+ dim _controltext as string ' reference
+
+ if ( sKey = "*" ) then
+ sKey = control.name()
+ endif
+
+ sKey = lcase( sKey )
+
+ if ( control.exists() = true and control.IsVisible = true ) then
+
+ _controltext = lcase( hGetFileData( _file , skey ) )
+ controltext = control.getSelText()
+ keycompare( controltext , _controltext , sKey )
+ checkComboBox() = control.isEnabled()
+
+ else
+
+ warnlog( "Control <" & sKey & "> could not be accessed." )
+
+ endif
+
+end function
+
+'*******************************************************************************
+
+function setComboBox( _file as string , sKey as string , control as object , optional bverbose as boolean ) as integer
+
+ '///<h3>EXPERIMENTAL: Get/Set function for some control types</h3>
+ '///<i>This is a function that allows to change the state/content of a
+ '///+ control via a configuration file. This function is experimental
+ '///+ and should not be used.<br>
+
+ dim _controltext as string ' reference string retrieved from _file
+
+ if ( ismissing( bverbose ) ) then
+ bverbose = true
+ endif
+ if ( sKey = "*" ) then
+ sKey = control.name()
+ endif
+
+ sKey = lcase( sKey )
+
+ if ( control.exists() = true and control.IsVisible = true ) then
+
+ _controltext = hGetFileData( _file , sKey )
+ control.settext( _controltext )
+ setComboBox() = _controltext
+ if ( bverbose = true ) then
+ printlog( " * " & sKey )
+ endif
+
+ else
+
+ warnlog( "Control <" & sKey & "> is not accessible." )
+
+ endif
+
+end function
+
+'*******************************************************************************
+
+function checkEntryField( _file as string , sKey as string , control as object , optional cBugID as string ) as boolean
+
+ '///<h3>EXPERIMENTAL: Get/Set function for some control types</h3>
+ '///<i>This is a function that allows to change the state/content of a
+ '///+ control via a configuration file. This function is experimental
+ '///+ and should not be used.<br>
+
+ dim controltext as string ' current state
+ dim _controltext as string ' reference
+
+ if ( ismissing( cBugID ) ) then
+ cBugID = "WriteMe!"
+ endif
+ if ( sKey = "*" ) then
+ sKey = control.name()
+ endif
+
+ ' lowercase the name (or alias) of the control which will be tested
+ sKey = lcase( sKey )
+
+ ' get the expected setting for the control from the reference file
+ _controltext = lcase( hGetFileData( _file , skey ) )
+
+ ' if the reference file specifies that the control should be disabled
+ ' the routine tries to access it - expecting to fail. In this case we write
+ ' a string into the EF
+ if ( _controltext <> "disabled" ) then
+
+ if ( control.exists() and _
+ control.IsVisible() and _
+ control.IsEnabled() ) then
+
+ controltext = lcase( control.getText() )
+ keycompare( controltext , _controltext , sKey , cBugID )
+ checkEntryField() = control.isEnabled()
+
+ else
+
+ warnlog( "Control <" & sKey & "> could not be accessed." )
+
+ endif
+
+ else
+
+ if ( control.IsEnabled() ) then
+ warnlog( "The control should be disabled but it is not: " & sKey )
+ endif
+
+ endif
+
+end function
+
+'*******************************************************************************
+
+function setEntryField( _file as string , sKey as string , control as object , optional bverbose as boolean ) as string
+
+ '///<h3>EXPERIMENTAL: Get/Set function for some control types</h3>
+ '///<i>This is a function that allows to change the state/content of a
+ '///+ control via a configuration file. This function is experimental
+ '///+ and should not be used.<br>
+
+ ' this is the text that will be written into the entryfield
+ dim _controltext as string
+
+ if ( ismissing( bverbose ) ) then
+ bverbose = true
+ endif
+ if ( sKey = "*" ) then
+ sKey = lcase( control.name() )
+ endif
+
+ ' get the string from the reference file
+ _controltext = lcase( hGetFileData( _file , sKey ) )
+
+ if ( _controltext <> "disabled" ) then
+
+ ' we can only access the control if it is present + visible
+ if ( control.exists() and _
+ control.IsVisible() and _
+ control.IsEnabled() ) then
+
+ control.setText( lcase( _controltext ) )
+ setEntryField() = _controltext
+
+ if ( bverbose ) then
+ printlog( " * " & sKey )
+ endif
+
+ else
+
+ warnlog( "Control <" & sKey & "> is not accessible." )
+
+ endif
+
+ else
+
+ if ( control.IsEnabled() ) then
+ warnlog( "The control should be disabled but it is not: " & sKey )
+ endif
+
+ endif
+
+end function
+
+'*******************************************************************************
+
+function checkListBox( _file as string , sKey as string , control as object ) as boolean
+
+ '///<h3>EXPERIMENTAL: Get/Set function for some control types</h3>
+ '///<i>This is a function that allows to change the state/content of a
+ '///+ control via a configuration file. This function is experimental
+ '///+ and should not be used.<br>
+
+ dim controltext as string ' current state
+ dim _controltext as string ' reference
+
+ if ( sKey = "*" ) then
+ sKey = control.name()
+ endif
+
+ sKey = lcase( sKey )
+
+ if ( control.exists() = true and control.IsVisible = true ) then
+
+ _controltext = lcase( hGetFileData( _file , skey ) )
+ controltext = control.getSelIndex()
+ keycompare( controltext , _controltext , sKey )
+ checkListBox() = control.isEnabled()
+
+ else
+
+ warnlog( "Control <" & sKey & "> could not be accessed." )
+
+ endif
+
+end function
+
+'*******************************************************************************
+
+function setListBox( _file as string , sKey as string , control as object , optional bverbose as boolean ) as integer
+
+ '///<h3>EXPERIMENTAL: Get/Set function for some control types</h3>
+ '///<i>This is a function that allows to change the state/content of a
+ '///+ control via a configuration file. This function is experimental
+ '///+ and should not be used.<br>
+
+ dim _controltext as string ' reference
+
+ ' if name of the control is '*' get the name from the control itself
+ if ( ismissing( bverbose ) ) then
+ bverbose = true
+ endif
+ if ( sKey = "*" ) then
+ sKey = control.name()
+ endif
+
+ ' change the key to lowercase
+ sKey = lcase( sKey )
+
+ if ( control.exists() = true and control.IsVisible = true ) then
+
+ _controltext = hGetFileData( _file , sKey )
+ control.select( val( _controltext ) )
+ setListBox() = control.getselindex()
+ if ( bverbose = true ) then
+ printlog( " * " & sKey )
+ endif
+
+ else
+
+ warnlog( "Control <" & sKey & "> is not accessible." )
+
+ endif
+
+end function
+
+'*******************************************************************************
+
+function checkListItem( _file as string , _iIndex as integer , sKey as string , control as object ) as boolean
+
+ '///<h3>EXPERIMENTAL: Get/Set function for some control types</h3>
+ '///<i>This is a function that allows to change the state/content of a
+ '///+ control via a configuration file. This function is experimental
+ '///+ and should not be used.<br>
+
+ dim controltext as string ' current state
+ dim _controltext as string ' reference
+
+ sKey = lcase( sKey )
+
+
+ if ( control.exists() = true and control.IsVisible() = true ) then
+
+ control.select( _iIndex )
+ controltext = control.getSelText()
+ _controltext = hGetFileData( _file , skey )
+
+
+ keycompare( controltext , _controltext , sKey )
+
+ checkListItem() = control.isEnabled()
+
+ else
+
+ printlog( "Control <" & sKey & "> could not be found." )
+
+ endif
+
+
+end function
+
+'*******************************************************************************
+
+function hSetControlValue( oObject as object, cValue as string ) as integer
+
+ '///<h3>Enter some text into a EntryField/TextField</h3>
+ '///<i>This extends .setText() to provide a returnvalue</i><br>
+ '///<i>The function runs silent as long as no errors occur</i><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Control Object (Object)</li>
+ '///<ul>
+ '///+<li>The object must exist</li>
+ '///+<li>The object must be enabled</li>
+ '///+<li>The object must be visible</li>
+ '///</ul>
+ '///+<li>String (string)</li>
+ '///<ul>
+ '///+<li>Any string, including empty strings (=delete)</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Status of the control (integer)</li>
+ '///<ul>
+ '///+<li>0 = EntryField was updated correctly</li>
+ '///+<li>1 = Object does not exist</li>
+ '///+<li>2 = Object it not visible</li>
+ '///+<li>3 = Object is disabled</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+ dim irc as integer
+ const CFN = "hSetControlValue::"
+
+ '///+<li>Verify that the control exists</li>
+ if ( oObject.exists() ) then
+
+ '///+<li>Verify that the object is visible</li>
+ if ( oObject.isVisible() ) then
+
+ '///+<li>Verify that the control is enabled</li>
+ if ( oObject.isEnabled() ) then
+ oObject.setText( cValue )
+ irc = 0
+ else
+ irc = 3 ' control disabled
+ printlog( CFN & "Control is disabled: ID: " & oObject )
+ endif
+ else
+ irc = 2 ' control not visible
+ printlog( CFN & "Control is not visible: ID: " & oObject )
+ endif
+ else
+ irc = 1 ' control does not exist
+ printlog( CFN & "Control does not exist: ID: " & oObject )
+ endif
+
+ hSetControlValue() = irc
+ '///</ul>
+
+end function
+
+
diff --git a/testautomation/global/tools/includes/optional/t_docfuncs.inc b/testautomation/global/tools/includes/optional/t_docfuncs.inc
new file mode 100755
index 000000000000..7f3c08671b95
--- /dev/null
+++ b/testautomation/global/tools/includes/optional/t_docfuncs.inc
@@ -0,0 +1,739 @@
+'encoding UTF-8 Do not remove or change this line!
+'**************************************************************************
+'* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+'*
+'* Copyright 2008 by Sun Microsystems, Inc.
+'*
+'* OpenOffice.org - a multi-platform office productivity suite
+'*
+'* $RCSfile: t_docfuncs.inc,v $
+'*
+'* $Revision: 1.1 $
+'*
+'* last change: $Author: jsk $ $Date: 2008-06-20 07:57:47 $
+'*
+'* This file is part of OpenOffice.org.
+'*
+'* OpenOffice.org is free software: you can redistribute it and/or modify
+'* it under the terms of the GNU Lesser General Public License version 3
+'* only, as published by the Free Software Foundation.
+'*
+'* OpenOffice.org is distributed in the hope that it will be useful,
+'* but WITHOUT ANY WARRANTY; without even the implied warranty of
+'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+'* GNU Lesser General Public License version 3 for more details
+'* (a copy is included in the LICENSE file that accompanied this code).
+'*
+'* You should have received a copy of the GNU Lesser General Public License
+'* version 3 along with OpenOffice.org. If not, see
+'* <http://www.openoffice.org/license.html>
+'* for a copy of the LGPLv3 License.
+'*
+'/************************************************************************
+'*
+'* owner : joerg.skottke@sun.com
+'*
+'* short description : misc functions to handle documents
+'*
+'\******************************************************************************
+
+function hUseImpressAutopilot( bEnable as boolean ) as boolean
+
+ '///<h3>Enable/disable the Impress Autopilot in Tools/Options</h3>
+ '///<i>Starting point: Any plain document</i>
+ '///<ul>
+ const CFN = "hUseImpressAutopilot::"
+
+ printlog( CFN & "Enter" )
+
+ '///+<li>Create a new IMPRESS document</li>
+ gApplication = "IMPRESS"
+ hCreateDocument()
+
+ '///+<li>Open Tools/Options, go to Presentataion/General page</li>
+ ToolsOptions
+ hToolsOptions( "Presentation" , "General" )
+
+ '///+<li>Check or uncheck to start with autopilot</li>
+ Kontext "TabSonstigesDraw"
+ if ( mitAutopilotStarten.exists() ) then
+
+ if ( bEnable ) then
+ mitAutopilotStarten.check()
+ printlog( CFN & "Enable Impress Autopilot" )
+ else
+ mitAutopilotStarten.uncheck()
+ printlog( CFN & "Disable Impress Autopilot" )
+ endif
+
+ else
+
+ warnlog( CFN & "Cannot find Autopilot Checkbox" )
+
+ endif
+
+ '///+<li>Return Status of Checkbox (checked=TRUE)</li>
+ hUseImpressAutopilot() = mitAutopilotStarten.isChecked()
+
+ '///+<li>Close Tools/Options</li>
+ Kontext "OptionenDlg"
+ OptionenDlg.OK()
+
+ '///+<li>Close IMPRESS document</li>
+ hDestroyDocument()
+
+ '///+<li>Returncode is undefined</li>
+ printlog( CFN & "Exit" )
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hCloseNavigator() as boolean
+
+ '///<h3>Function to close the navigator</h3>
+ '///<i>Starting point: Any document</i>
+ '///<ul>
+ const CFN = "hCloseNavigator::"
+
+ printlog( CFN & "Enter" )
+
+ '///+<li>close the navigator if found</li>
+ Kontext "Navigator"
+ if ( Navigator.Exists() ) then
+ Navigator.Close()
+ printlog( CFN & "Closed Navigator" )
+ else
+ printlog( CFN & "Navigator not present" )
+ endif
+
+ '///+<li>verify that the navigator is indeed closed, return true on success</li>
+ Kontext "Navigator"
+ if ( Navigator.exists() ) then
+ hCloseNavigator() = false
+ warnlog( CFN & "Failed to close Navigator, it is still open." )
+ else
+ hCloseNavigator() = true
+ endif
+
+ printlog( CFN & "Exit" )
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hNumericDocType( doctype as integer ) as string
+
+ '///<h3>Convert a numeric expression to a gApplication</h3>
+ '///<i>BEWARE: This is a core function used by many testcases!</i><br>
+ '///<u>Using file: global/input/applications.txt as reference</u>
+ '///<ul>
+
+ const CFN = "hNumericDocType::"
+
+ dim sFile as string
+ sFile = gTesttoolPath & "global\input\applications.txt"
+ sFile = convertpath( sFile )
+
+ dim sList( 100 ) as string
+ dim iDocTypes as integer
+
+ 'printlog( CFN & "Enter" )
+
+ '///+<li>Retrieve matching list from file</li>
+ hGetDataFileSection( sFile , sList() , "application" , "" , "" )
+ iDocTypes = val( sList( 0 ) )
+
+ '///+<li>Verify that the functionparameter (documenttype) is valid</li>
+ if ( ( doctype < 0 ) or ( doctype > iDocTypes ) ) then
+ warnlog( CFN & "Undefined numeric doctype: " & doctype )
+ hNumericDocType() = ""
+ exit function
+ endif
+
+ '///+<li>Set gApplication to the requested document type</li>
+ gApplication = hGetValueForKeyAsString( sList() , doctype )
+
+ '///+<li>Set a plain text name as returnvalue for the function</li>
+ hGetDataFileSection( sFile , sList() , "application_names" , "" , "" )
+ hNumericDocType() = hGetValueForKeyAsString( sList() , gApplication )
+ 'printlog( CFN & "Exit" )
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hChangeDoc() as string
+
+ '///<h3>Function to modify all documenttypes to set the "changed" flag</h3>
+ '///<i>Starting point: Any plain document</i><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Nothing</li>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>String, ready to use in printlog</li>
+ '///<ul>
+ '///+<li>&quot;Changed &lt;Documenttype&gt;&quot;</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+ select case gApplication
+
+ '///+<li>WRITER: Type some text</li>
+ case "WRITER", "HTML", "MASTERDOC"
+ Kontext "DocumentWriter"
+ DocumentWriter.TypeKeys "<Return>This doc is changed!"
+ hChangeDoc() = "Changed WRITER/HTML/MASTERDOC"
+
+ '///+<li>CALC: Write some text into the current location (usually A1)</li>
+ case "CALC" : Kontext "DocumentCalc"
+ DocumentCalc.TypeKeys "<Down>This doc is changed!<Return>"
+ hChangeDoc() = "Changed CALC"
+
+ '///+<li>DRAW: Draw a rectangle</li>
+ case "DRAW" : Kontext "DocumentDraw"
+ hRechteckErstellen ( 20, 20, 25, 25 )
+ gMouseClick ( 1, 1 )
+ hChangeDoc() = "Changed DRAW"
+
+ '///+<li>IMPRESS: Draw a rectangle</li>
+ case "IMPRESS": Kontext "DocumentImpress"
+ hRechteckErstellen ( 20, 20, 25, 25 )
+ gMouseClick ( 1, 1 )
+ hChangeDoc() = "Changed IMPRESS"
+
+ '///+<li>MATH: Create a simple formaula</li>
+ case "MATH" : SchreibenInMathdok( "b over c" )
+ hChangeDoc() = "Changed MATH"
+
+ end select
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hIdentifyWriterDoc( cString as string, bWarn as boolean ) as boolean
+
+ '///<h3>Function to validate that the expected WRITER doc has the focus</h3>
+ '///<i>Starting point: Any WRITER document containing some text</i>
+ '///<ul>
+
+ use "global\tools\includes\optional\t_stringtools.inc"
+
+ const CFN = "hIdentifyWriterDoc::"
+ dim cIdentifier as string
+ dim irc as integer ' some temporary returnvalue
+
+ printlog( CFN & "Enter" )
+
+ '///+<li>Test the function parameter</li>
+ if ( cString = "" ) then
+ qaerrorlog( CFN & "Function parameter is empty string. Aborting" )
+ hIdentifyWriterDoc() = false
+ exit function
+ endif
+
+ '///+<li>Verify function prerequisites</li>
+ kontext "DocumentWriter"
+ if ( not DocumentWriter.exists() ) then
+ printlog( CFN & "There is no Writer document. Aborting" )
+ hIdentifyWriterDoc() = false
+ exit function
+ endif
+
+ hIdentifyWriterDoc() = true
+
+ '///+<li>Go to the very beginning of the current writer document</li>
+ kontext "DocumentWriter"
+ DocumentWriter.typeKeys( "<MOD1 HOME>" )
+
+ '///+<li>Select the entire line</li>
+ DocumentWriter.typeKeys( "<SHIFT END>" )
+
+ '///+<li>copy the string to the clipboard and store it into a variable</li>
+ try
+ editcopy
+ cIdentifier = getClipboardText()
+ catch
+ warnlog( "EditCopy failed. Probably the document is empty" )
+ cIdentifier = "**** invalid ****"
+ endcatch
+
+
+ '///+<li>compare the string to the reference (given as parameter)</li>
+ irc = hCompareSubstrings( cIdentifier, cString )
+
+ '///+<li>Write the result to the printlog if desired</li>
+ if ( irc = 0 ) then
+
+ if ( bWarn ) then
+ warnlog ( CFN & "The focus is not on the expected document" )
+ else
+ printlog( CFN & "The focus is not on the expected document" )
+ endif
+
+ printlog( CFN & "Expected: " & cString )
+ printlog( CFN & "Found...: " & cIdentifier )
+ hIdentifyWriterDoc() = false
+
+ else
+ printlog( CFN & "OK: The document contains the requested string" )
+ endif
+ '///+<li>Return TRUE only if the current document is the expected one</li>
+
+ printlog( CFN & "Exit" )
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hCreateDocument() as boolean
+
+ '///<h3>Create anew document, extends hNewDocument()</h3>
+ '///<i>Starting point: Any document</i><br>
+ '///<i>Note: When calling this function with gApplication "BACKGROUND" the
+ '///+ function will actually close one document to get to the backing window</i><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Nothing, valid gApplication must be set</li>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Errorstatus (boolean)</li>
+ '///<ul>
+ '///+<li>TRUE if a new document was created successfully</li>
+ '///+<li>FALSE if anything went wrong</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+
+ const CFN = "hCreateDocument::"
+
+ dim iDocCountBefore as integer
+ dim iDocCountAfter as integer
+
+ '///+<li>Retrieve the number of open documents</li>
+ iDocCountBefore = getDocumentCount
+ printlog( CFN & "Number of open documents before: " & iDocCountBefore )
+
+ '///+<li>Special treatment if gApplication = BACKGROUND (virtual gApplication)</li>
+ if ( ucase( gApplication ) = "BACKGROUND" ) then
+ do while( getDocumentCount > 0 )
+ hCloseDocument()
+ loop
+ hCreateDocument() = true
+ else
+
+ '///+<li>Open a new document using hNewDocument()</li>
+ call hNewDocument()
+
+ '///+<li>Retrieve the number of open documents</li>
+ iDocCountAfter = getDocumentCount()
+
+ '///+<li>Verify that there is exactly one more document than before</li>
+ if ( iDocCountAfter = ( iDocCountBefore + 1 ) ) then
+ hCreateDocument() = true
+ else
+ hCreateDocument() = false
+ endif
+ endif
+ printlog( CFN & "Number of open documents after.: " & iDocCountAfter )
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hDocumentTypeKeys( cString as string ) as boolean
+
+ '///<h3>Type a string to a document</h3>
+ '///<i>The documenttype is determined by gApplication.<br>
+ '///See hNumericDocType for details and number/gApplication matching</i><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Keystrokes to be sent to the document (string), e.g.</li>
+ '///<ul>
+ '///+<li>&quot;&lt;SHIFT HOME&gt;&quot;</li>
+ '///+<li>&quot;&lt;MOD1 A&gt;&quot;</li>
+ '///+<li>&quot;&lt;MOD2 Q&gt;&quot;</li>
+ '///+<li>&quot;Hello&quot;</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Errorstatus (boolean)</li>
+ '///<ul>
+ '///+<li>TRUE if all went well</li>
+ '///+<li>FALSE on any error</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+ const CFN = "hDocumentTypeKeys::"
+ dim brc as boolean
+ brc = true
+
+ printlog( CFN & "Enter" )
+
+ '///+<li>Set focus to the current documenttype determined by gApplication</li>
+ '///+<li>Type the string passed as function parameter</li>
+ select case gApplication
+ case "WRITER" : kontext "DocumentWriter"
+ DocumentWriter.typeKeys( cString )
+ case "CALC" : kontext "DocumentCalc"
+ DocumentCalc.typeKeys( cString )
+ case "IMPRESS" : kontext "DocumentImpress"
+ DocumentImpress.typeKeys( cString )
+ case "DRAW" : kontext "DocumentDraw"
+ DocumentDraw.typeKeys( cString )
+ case "MATH" : kontext "DocumentMath"
+ DocumentMath.typeKeys( cString )
+ case "MASTERDOC": kontext "DocumentWriter"
+ DocumentWriter.typeKeys( cString )
+ case "HTML" : kontext "DocumentWriter"
+ DocumentWriter.typeKeys( cString )
+ case else
+ warnlog( CFN & "Exit: Unknown gApplication: " & gApplication )
+ brc = false
+ end select
+
+ '///+<li>Print some message to the log on success</li>
+ if ( brc ) then
+ printlog( CFN & "Exit: Sent keystroke to " & gApplication )
+ endif
+
+ hDocumentTypeKeys() = brc
+ '///</ul>
+
+end function
+
+
+'*******************************************************************************
+
+function hDestroyDocument() as boolean
+
+
+ '///<h3>Enhanced version of hCloseDoc()</h3>
+ '///<i>Close a document and print some additional information to the log to
+ '///+ ease debugging tests which handle a lot of documents</i><br><br>
+
+ '///<u>Parameter(s):</u><br>
+ '///<ol>
+ '///+<li>No input parameters</li>
+ '///</ol>
+
+
+ '///<u>Returns:</u><br>
+ '///<ol>
+ '///+<li>Return value description</li>
+ '///<ul>
+ '///+<li>TRUE: The document was closed successfully (-1 open document)</li>
+ '///+<li>TRUE: We are on backing window, no document closed</li>
+ '///+<li>FALSE: The number of documents is unchanged, closing failed</li>
+ '///+<li>FALSE: If any error occurred during close (open dialogs etc.)</li>
+ '///</ul>
+ '///</ol>
+
+ const CFN = "hDestroyDocument::"
+ dim brc as boolean 'a multi purpose boolean returnvalue
+ dim irc as integer
+
+ dim iOpenDocsBefore as integer
+ dim iOpenDocsAfter as integer
+ dim iAttemptToClose as integer
+
+ '///<u>Description:</u>
+ '///<ul>
+ '///+<li>Get the current number of documents</li>
+ iOpenDocsBefore = getDocumentCount
+ printlog( CFN & "Open documents before close: " & iOpenDocsBefore )
+
+ '///+<li>Handle special case of 0 open documents</li>
+ '///<ul>
+ if ( iOpenDocsBefore = 0 ) then
+
+ '///+<li>If gApplication has been set to BACKGROUND explicitly we do a restart</li>
+ if ( ucase( gApplication ) = "BACKGROUND" ) then
+
+ do while ( getDocumentCount > 0 )
+ hCloseDocument()
+ loop
+
+ iOpenDocsAfter = getDocumentCount
+ printlog( CFN & "Open documents after restart: " & iOpenDocsAfter )
+
+ if ( iOpenDocsAfter = 0 ) then
+ hDestroyDocument() = true
+ exit function
+ else
+ warnlog( CFN & "There should be 0 open documents" )
+ hDestroyDocument() = false
+ exit function
+ endif
+
+ '///+<li>Otherwise just do not close the backing window - do nothing</li>
+ else
+ printlog( CFN & "On backing window, no action taken" )
+ hDestroyDocument() = true
+ exit function
+ endif
+
+ endif
+ '///</ul>
+
+ '///+<li>Handle more than one open document - handle FileOpen/FileSave dialogs</li>
+ '///<ul>
+ brc = true
+ for iAttemptToClose = 1 to 3
+
+ '///+<li>FileOpen</li>
+ kontext "OeffnenDlg"
+ if ( OeffnenDlg.exists( 1 ) ) then
+ qaerrorlog( CFN & "Closed FileOpen dialog. This was not expected." )
+ OeffnenDlg.cancel()
+ brc = false
+ endif
+
+ '///+<li>FileSave</li>
+ kontext "SpeichernDlg"
+ if ( SpeichernDlg.exists( 1 ) ) then
+ qaerrorlog( CFN & "Closed FileSave dialog. This was not expected." )
+ brc = false
+ endif
+
+ '///+<li>Check for any messagebox (some might still be floating around)</li>
+ '///<ul>
+ kontext "active"
+ if ( active.exists( 1 ) ) then
+
+ qaerrorlog( CFN & "Closed unexpected messagebox: " & active.getText() )
+
+ '///+<li>Try to close the dialog clicking on &quot;OK&quot;</li>
+ try
+ active.ok()
+ printlog( CFN & "Clicked <OK> to close the dialog" )
+ catch
+ printlog( CFN & "Failed using OK" )
+ endcatch
+
+ '///+<li>Try to close the dialog clicking on &quot;YES&quot;</li>
+ try
+ active.yes()
+ printlog( CFN & "Clicked <YES> to close the dialog" )
+ catch
+ printlog( CFN & "Failed using <YES>" )
+ endcatch
+
+ brc = false
+
+ endif
+ '///</ul>
+
+ '///+<li>Close the current document using hCloseDocument()</li>
+ call hCloseDocument()
+
+ '///+<li>Verify that the document has indeed been closed, exit function if yes</li>
+ iOpenDocsAfter = getDocumentCount
+ if ( iOpenDocsAfter = ( iOpenDocsBefore - 1 ) ) then
+ printlog( CFN & "Open documents after close.: " & iOpenDocsAfter )
+ hDestroyDocument() = brc
+ exit function
+ else
+ qaerrorlog( CFN & "Failed to close document, retrying" )
+ brc = false
+ endif
+
+ next iAttemptToClose
+ '///</ul>
+ '///</ul>
+
+ printlog( CFN & "Exit with result: " & brc )
+
+ hDestroyDocument() = brc
+
+end function
+
+'*******************************************************************************
+
+function hInitSingleDoc() as boolean
+
+ '///<h3>Make sure exactly one single writer document is open</h3>
+ '///<i>The wizards cannot be triggered correctly from the backing window.
+ '///+ As a workaround this function checks the amount of open documents and
+ '///+ creates exactly one unchanged Writer document</i><br><br>
+
+ '///<u>Parameter(s):</u><br>
+ '///<ol>
+ '///+<li>No input parameters</li>
+ '///</ol>
+
+
+ '///<u>Returns:</u><br>
+ '///<ol>
+ '///+<li>Errorcondition (Boolean)</li>
+ '///<ul>
+ '///+<li>TRUE: Exactly one Writer document is open</li>
+ '///+<li>FALSE: Any error</li>
+ '///</ul>
+ '///</ol>
+
+ const CFN = "hInitSingleDoc::"
+ dim cOldApplication as string
+
+ '///<u>Description:</u>
+ '///<ul>
+ '///+<li>Close all documents until we are on the backing window</li>
+ do while ( getDocumentCount > 0 )
+ call hCloseDocument()
+ loop
+
+ '///+<li>Save the previous gApplication</li>
+ cOldApplication = gApplication
+
+ '///+<li>Set gApplication to WRITER</li>
+ gApplication = "WRITER"
+
+ '///+<li>Open one new Writer document</li>
+ call hNewDocument()
+
+ '///+<li>Verify that exactly one document is open</li>
+ if ( getDocumentCount = 1 ) then
+ printlog( CFN & "A single unchanged writer document is open" )
+ hInitSingleDoc() = true
+ else
+ printlog( CFN & "Failed to open just one single writer document" )
+ hInitSingleDoc() = false
+ endif
+
+ '///+<li>Restore gApplication</li>
+ gApplication = cOldApplication
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hInitBackingMode() as boolean
+
+ '///<h3>Make that we are on the backing window (no open documents)</h3>
+ '///<i>Close all open documents</i><br><br>
+
+ '///<u>Parameter(s):</u><br>
+ '///<ol>
+ '///+<li>No input parameters</li>
+ '///</ol>
+
+
+ '///<u>Returns:</u><br>
+ '///<ol>
+ '///+<li>Errorcondition (Boolean)</li>
+ '///<ul>
+ '///+<li>TRUE: No open documents are present</li>
+ '///+<li>FALSE: Any error</li>
+ '///</ul>
+ '///</ol>
+
+ const CFN = "hInitBackingMode::"
+
+ '///<u>Description:</u>
+ '///<ul>
+ '///+<li>Close all documents until we are on the backing window</li>
+ do while ( getDocumentCount > 0 )
+ hCloseDocument()
+ loop
+
+ '///+<li>verify that we do not have any open documents left (redundant check)</li>
+ if ( getDocumentCount = 0 ) then
+ printlog( CFN & "Office is in backing mode." )
+ hInitBackingMode() = true
+ else
+ printlog( CFN & "Office is in undefined state." )
+ hInitBackingMode() = false
+ endif
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hInitWriteDocIdentifier( cString as string ) as boolean
+
+
+ '///<h3>Write a specific string to an open writer document</h3>
+ '///<i>This function verifies that exactly one document is open, that this is a
+ '///+ Writer document and writes the string to the document</i><br><br>
+
+ '///<u>Parameter(s):</u><br>
+ '///<ol>
+
+ '///+<li>A free form string (String) which serves as identifier for the document</li>
+ '///<ul>
+ '///+<li>The first character should be uppercase</li>
+ '///</ul>
+
+ '///</ol>
+
+
+ '///<u>Returns:</u><br>
+ '///<ol>
+ '///+<li>Errorcondition (Boolean)</li>
+ '///<ul>
+ '///+<li>TRUE: The string was written correctly</li>
+ '///+<li>FALSE: Too many open documents</li>
+ '///+<li>FALSE: Not a Writer document</li>
+ '///+<li>FALSE: Any other error</li>
+ '///</ul>
+ '///</ol>
+
+ const CFN = "hInitWriteDocIdentifier::"
+
+ '///<u>Description:</u>
+ '///<ul>
+ '///+<li>Verify number of open documents</li>
+ if ( getDocumentCount <> 1 ) then
+ printlog( CFN & "Incorrect document count" )
+ hInitWriteDocIdentifier() = false
+ exit function
+ endif
+
+ '///+<li>Verify that it is a writer document</li>
+ kontext "DocumentWriter"
+ if ( not DocumentWriter.exists() ) then
+ printlog( CFN & "Open document is not a text document" )
+ hInitWriteDocIdentifier() = false
+ exit function
+ endif
+
+ '///+<li>Write the string</li>
+ kontext "DocumentWriter"
+ DocumentWriter.typeKeys( "<MOD1 END>" )
+ DocumentWriter.typeKeys( "<MOD1 SHIFT HOME>" )
+ DocumentWriter.typeKeys( "<DELETE>" )
+ DocumentWriter.typekeys( cString )
+
+ '///+<li>Verify the string</li>
+ DocumentWriter.typeKeys( "<MOD1 END>" )
+ DocumentWriter.typeKeys( "<MOD1 SHIFT HOME>" )
+ EditCopy
+ if ( getClipboardText = cString ) then
+ printlog( CFN & "Document has been successfully modified." )
+ hInitWriteDocIdentifier() = true
+ else
+ printlog( CFN & "Could not verify document identification string" )
+ hInitWriteDocIdentifier() = false
+ endif
+ '///</ul>
+
+end function
diff --git a/testautomation/global/tools/includes/optional/t_extension_manager_tools.inc b/testautomation/global/tools/includes/optional/t_extension_manager_tools.inc
new file mode 100755
index 000000000000..83d9268fb6f5
--- /dev/null
+++ b/testautomation/global/tools/includes/optional/t_extension_manager_tools.inc
@@ -0,0 +1,750 @@
+'encoding UTF-8 Do not remove or change this line!
+'**************************************************************************
+'* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+'*
+'* Copyright 2008 by Sun Microsystems, Inc.
+'*
+'* OpenOffice.org - a multi-platform office productivity suite
+'*
+'* $RCSfile: t_extension_manager_tools.inc,v $
+'*
+'* $Revision: 1.1 $
+'*
+'* last change: $Author: jsk $ $Date: 2008-06-20 07:57:57 $
+'*
+'* This file is part of OpenOffice.org.
+'*
+'* OpenOffice.org is free software: you can redistribute it and/or modify
+'* it under the terms of the GNU Lesser General Public License version 3
+'* only, as published by the Free Software Foundation.
+'*
+'* OpenOffice.org is distributed in the hope that it will be useful,
+'* but WITHOUT ANY WARRANTY; without even the implied warranty of
+'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+'* GNU Lesser General Public License version 3 for more details
+'* (a copy is included in the LICENSE file that accompanied this code).
+'*
+'* You should have received a copy of the GNU Lesser General Public License
+'* version 3 along with OpenOffice.org. If not, see
+'* <http://www.openoffice.org/license.html>
+'* for a copy of the LGPLv3 License.
+'*
+'/******************************************************************************
+'*
+'* owner : joerg.skottke@sun.com
+'*
+'* short description : Tools to ease working with the extension manager
+'*
+'\******************************************************************************
+
+function hExtensionAddGUI( _path as string, _flags as string ) as integer
+
+ '///<h3>Install an extension using the OpenOffice.org Extension Manager UI</h3>
+ '///<p>This function is intended for use with the new Extension Manager UI
+ '///+ and replaces an older function with the same name. Please note that
+ '///+ the interface has changed significantly. <br>This has become necessary
+ '///+ because the Extension Manager can turn up with a really huge number
+ '///+ of different dialogs, warnings, errormessages etc. <br>
+ '///+ As this function is designed to handle the most common installation
+ '///+ scenarios it needs quite a number of differnt options.<br>
+ '///+ Please have a look at the usage sample:<br><br></p>
+ '///+ <p align="center"><i>hExtensionAddGUI( sMyExtension,
+ '///+ &quot;InstallForAll,BrokenDeps,DenyUpdate&quot; )</i<p><br>
+
+
+ '///<u>Input:</u><br>
+ '///<ol>
+ '///+<li>Path to extension (String)</li>
+ '///<ul>
+ '///+<li>The path has to be fully qualified</li>
+ '///+<li>The path may be platform specifix</li>
+ '///</ul>
+
+ '///+<li>Flags (String), defaults underlined</li>
+ '///<ul>
+ '///+<li>The string is non optional but may be empty. Allowed flags are:</li>
+ '///<ul>
+ '///+<li>InstallForAll | <u>InstallForUser</u><br>Used when running office with administrator rights</li>
+ '///+<li>AllowUpdate | DenyUpdate | <u>NoUpdate</u><br>Reinstall already installed extension/update</li>
+ '///+<li>AcceptLicense | DenyLicense | <u>NoLicense</u><br>How to handle possible license dialog</li>
+ '///+<li>BrokenDeps<br>Close exactly one broken dependencies warning</li>
+ '///+<li>UseSlot<br>Use the File Open slot to load the extension (faster)</li>
+ '///</ul>
+ '///+<li>It is recommended to use the comma as delimiter between flags</li>
+ '///</ul>
+ '///</ol>
+
+ '///<u>Return Value:</u><br>
+ '///<ol>
+ '///+<li>Installation status (Integer)</li>
+ '///<ul>
+ '///+<li>&gt; 0 = Installation completed with no errors, number of installed extensions</li>
+ '///+<li>-1 = The requested extension does not exist</li>
+ '///+<li>-2 = The Add-button could not be accessed</li>
+ '///+<li>-3 = The Extension Manager did not open</li>
+ '///+<li>-4 = Unknown messagebox before the file Open dialog exists</li>
+ '///+<li>-5 = Broken dependency warning displayed</li>
+ '///+<li>-6 = The File Open dialog did not pop up</li>
+ '///</ul>
+ '///</ol>
+
+ dim flags as string : flags = lcase( _flags )
+ dim path as string : path = convertpath( _path )
+ dim bLogs as boolean : bLogs = FALSE
+
+ const CFN = "hExtensionAddGUI()::"
+
+ '///<u>Description</u>
+ '///<ul>
+
+ ' set defaults if string is empty
+ if ( flags = "" ) then flags = "installforuser,noupdate,nolicense"
+ if ( instr( flags , "verbose" ) <> 0 ) then bLogs = TRUE
+
+ if ( bLogs ) then printlog( CFN & "Flags: " & flags )
+
+ '///+<li>Verify that the requested extension exists (filesystem level)</li>
+ if ( not FileExists( path ) ) then
+ printlog( CFN & "Requested extension does not exist" )
+ hExtensionAddGUI() = -1
+ exit function
+ endif
+
+
+ if ( bLogs ) then
+ printlog( "" )
+ printlog( "********** Installing extension begin **********" )
+ endif
+
+ '///+<li>Open the Extension Manager - optionally using the slot (CWS oxtsysint01)</li>
+ if ( instr( flags , "useslot" ) <> 0 ) then
+ hFileOpen( path )
+ else
+ ToolsPackageManager
+ kontext "PackageManager"
+
+ if ( PackageManager.exists( 2 ) ) then
+
+ '///+<li>Verify that the &quot;Add..&quot; button is available</li>
+ if ( add.exists() and add.isEnabled() ) then
+
+ '///+<li>Click the &quot;Add...&quot; button</li>
+ add.click()
+ else
+ printlog( CFN & "Add button is missing or disabled" )
+ hExtensionAddGUI() = -2
+ exit function
+ endif
+
+ '///+<li>Test for the dreaded &quot;The office workdirectory does not exist&quot; warning, close it</li>
+ kontext "Active"
+ if ( Active.exists( 1 ) ) then
+ if ( Active.getButtonCount() = 1 ) then
+ if ( bLogs ) then printlog( Active.getText() )
+ active.ok()
+ else
+ printlog( CFN & "Unexpected/unknown messagebox" )
+ printlog( Active.getText() )
+ hExtensionAddGUI() = -4
+ exit function
+ endif
+ endif
+
+ '///+<li>Enter the extension name into the file picker, open the file</lI>
+ kontext "OeffnenDlg"
+ if ( OeffnenDlg.exists( 2 ) ) then
+ DateiName.setText( path )
+ Oeffnen.click()
+ else
+ printlog( CFN & "The File Open dialog did not open" )
+ hExtensionAddGUI() = -6
+ exit function
+ endif
+
+ else
+ printlog( CFN & "Extension Manager is not open" )
+ hExtensionAddGUI() = -3
+ exit function
+ endif
+ endif
+
+ '///+<li>Test for the installation target dialog that comes up as soon as the
+ '///+ user has administrator rights or works on a userspace installation.
+ '///+ Handle the dialog as specified by the function flags</li>
+ if ( instr( flags, "installfor" ) <> 0 ) then
+ kontext "Active"
+ if ( Active.exists( 1 ) ) then
+ if ( Active.getButtonCount() = 3 ) then
+
+ if ( bLogs ) then
+ printlog( CFN & "Installation target dialog found" )
+ printlog( Active.getText() )
+ endif
+
+ if ( instr( flags , "installforall" ) <> 0 ) then
+ printlog( CFN & "Installing for all users" )
+ Active.no()
+ else
+ printlog( CFN & "Installing for user only" )
+ Active.yes()
+ endif
+ else
+ if ( bLogs ) then
+ printlog( CFN & "Unexpected/unknown dialog" )
+ printlog( Active.getText() )
+ endif
+ endif
+ else
+ if ( bLogs ) then printlog( CFN & "Skipping handling of installation target" )
+ endif
+ else
+ if ( bLogs ) then printlog( CFN & "Not handling userspace installations" )
+ endif
+
+ '///+<li>Test for the broken dependencies exception, close it with ok.</li>
+ if ( instr( flags , "brokendeps" ) <> 0 ) then
+ if ( bLogs ) then printlog( CFN & "Testing for dependencies messagebox" )
+ kontext "UnsatisfiedDependencies"
+ if ( UnsatisfiedDependencies.exists( 1 ) ) then
+ printlog( CFN & "Closing Unsatisfied Dependencies dialog." )
+ UnsatisfiedDependencies.ok()
+ hExtensionAddGUI() = -5
+ else
+ printlog( CFN & "No unsatisfied dependencies dialog" )
+ endif
+ else
+ if ( bLogs ) then printlog( CFN & "Skipping handling of broken dependencies dialog" )
+ endif
+
+ '///+<li>Test for the extension update dialog which pops up if an extension
+ '///+ is already installed. Handle as specified by flags</li>
+ if ( instr( flags, "update" ) ) then
+ if ( bLogs ) then printlog( CFN & "Testing for version message/update" )
+ kontext "Active"
+ if ( Active.exists( 1 ) ) then
+
+ if ( bLogs ) then
+ printlog( CFN & "Found update dialog" )
+ printlog( Active.getText() )
+ endif
+
+ if ( Active.getButtonCount() = 2 ) then
+ if ( instr( flags, "denyupdate" ) <> 0 ) then
+ printlog( CFN & "Denying update" )
+ Active.cancel()
+ else
+ printlog( CFN & "Allowing update" )
+ Active.ok()
+ endif
+ else
+ printlog( CFN & "Unexpected/unknown dialog displayed" )
+ printlog( Active.getText() )
+ endif
+ else
+ if ( instr( flags , "noupdate" ) <> 0 ) then
+ printlog( CFN & "No update dialog present. Good" )
+ else
+ printlog( CFN & "Update messagebox is missing" )
+ endif
+ endif
+ else
+ if ( bLogs ) then printlog( CFN & "Skipping handling of update dialog" )
+ endif
+
+ '///+<li>Test for the Software License Agreement dialog. Handle as specified by
+ '///+ flags</li>
+ if ( instr( flags, "license" ) <> 0 ) then
+ if ( bLogs ) then printlog( CFN & "Testing software license dialog" )
+ kontext "ExtensionSoftwareLicenseAgreement"
+ if ( ExtensionSoftwareLicenseAgreement.exists( 1 ) ) then
+ if ( bLogs ) then printlog( CFN & "Software license dialog found" )
+ if ( instr( flags , "denylicense" ) <> 0 ) then
+ printlog( CFN & "Cancelling software license dialog" )
+ ExtensionSoftwareLicenseAgreement.cancel()
+ else
+ printlog( CFN & "Accepting software license" )
+ do while ( not accept.isEnabled() )
+ ScrollDown.click()
+ WaitSlot()
+ loop
+ accept.click()
+ endif
+ else
+ if ( instr( flags , "nolicense" ) <> 0 ) then
+ printlog( CFN & "No license dialog displayed. Good." )
+ else
+ printlog( CFN & "Expected license dialog is missing" )
+ endif
+ endif
+ else
+ if ( bLogs ) then printlog( CFN & "Skipping handling of license dialog" )
+ endif
+
+ '///+<li>Retrieve the number of installed extensions</li>
+ kontext "PackageManager"
+ wait( 500 )
+ hExtensionAddGUI() = BrowsePackages.getItemCount()
+
+ '///+<li>Close the Extension Manager</li>
+ PackageManager.close()
+
+ if ( bLogs ) then
+ printlog( "********** Installing extension end **********" )
+ printlog( "" )
+ endif
+ '///</ul>
+
+end function
+
+
+'*******************************************************************************
+
+function hExtensionRemoveGUI( cExtensionName as string ) as integer
+
+
+ '///<h3>Remove an extension via Extension Manager </h3>
+
+ '///<u>Input value(s):</u><br>
+ '///<ol>
+ '///+<li>UI Name of the extension (string)</li>
+ '///</ol>
+
+
+ '///<u>Return Value:</u><br>
+
+ '///<ol>
+ '///+<li>Errorcode (integer)</li>
+ '///<ul>
+ '///+<li>0 = No errors, extension was removed</li>
+ '///+<li>1 = Failure to open Extension Manager (fatal)</li>
+ '///+<li>2 = Cannot delete found extension, remove-button is disabled (fatal)</li>
+ '///+<li>3 = The extension was not found (non-fatal)</li>
+ '///</ul>
+ '///</ol>
+
+ printlog( "Removing extension by name: " & cExtensionName )
+
+ ToolsPackageManager
+ kontext "PackageManager"
+ if ( PackageManager.exists( 2 ) ) then
+ try
+ BrowsePackages.select( cExtensionName )
+ if ( Remove.exists() ) then
+ if ( Remove.isEnabled() ) then
+ Remove.click()
+ WaitSlot( 5000 )
+ hExtensionRemoveGUI() = 0
+ else
+ hExtensionRemoveGUI() = 2
+ endif
+ else
+ hExtensionRemoveGUI() = 4
+ endif
+ catch
+ hExtensionRemoveGUI() = 3
+ endcatch
+
+ PackageManager.close()
+ else
+ hExtensionRemoveGUI() = 1
+ endif
+
+end function
+
+'*******************************************************************************
+
+function sExtensionCLI(sCommand as string, sExtensionName as string, optional sExtensionPath as string) as string
+ '/// Add/remove an extension with the command line tool 'unopkg'///'
+ '/// INPUT: sCommand: string of command from "add remove list reinstall" ///'
+ '/// INPUT: sExtensionName: name of the extension ///'
+ '/// INPUT: optional sExtensionPath: path to the extension ///'
+ '/// RETURN: currently nothing ///'
+ dim sLokalExtensionPath as string
+ dim sCommands as string
+ dim sUnoPkg as string
+ dim i, a, b as integer
+ dim args as string
+
+ if isMissing(sExtensionPath) then
+ sLokalExtensionPath = ""
+ else
+ sLokalExtensionPath = sExtensionPath
+ endif
+
+ sCommands = "add remove list reinstall"
+
+ a = len(sAppExe)
+ if a > 12 then
+ b = inStr(a-12, sAppExe, "soffice")
+ sUnoPkg = left(sAppExe, b-1) + "unopkg" + mid(sAppExe, b+len("soffice"))
+ 'printlog sUnoPkg
+ sUnoPkg = convertToUrl(sUnoPkg)
+ 'printlog sUnoPkg
+ else
+ qaErrorLog ("Need to think about another solution..." + sAppExe)
+ endif
+ args = sCommand+" "+sLokalExtensionPath + sExtensionName
+ printlog "Executing: "+sUnopkg+" "+args
+ shell(sUnoPkg,2,args)
+end function
+
+'*******************************************************************************
+
+function hExtensionGetItemList( cItemList() as string ) as integer
+
+ '///<h3>Get the list of all items in the extensions list</h3>
+ '///<i>The array contains the list of all items in the extension manager GUI,
+ '///+ including all components of the extensions. Consider this when defining
+ '///+ the size of the array to be passed to this function as problems here are
+ '///+ hard to debug.<br>
+ '///+ Starting point is any document, the function will return to the
+ '///+ calling document on completion</i><br><br>
+
+ '///<u>Input:</u>
+ '///<ol>
+ '///+<li>Array for the list items (string)</li>
+ '///</ol>
+
+
+ '///<u>Return Value:</u><br>
+ '///<ol>
+ '///+<li>Number of items (integer)</li>
+ '///<ul>
+ '///+<li>0 on any error</li>
+ '///+<li>2 if no extensions exist (My Macros/OpenOffice.org macros nodes present</li>
+ '///+<li>&gt; 2 if any changes to the default exist</li>
+ '///</ul>
+ '///</ol>
+
+ dim iItemCount as integer
+ dim iCurrentExtension as integer
+
+ printlog( "Retrieving extension list" )
+
+ ToolsPackageManager
+ kontext "PackageManager"
+ if ( PackageManager.exists( 2 ) ) then
+
+ iItemCount = BrowsePackages.getItemCount()
+
+ for iCurrentExtension = 1 to iItemCount
+ cItemList( iCurrentExtension ) = BrowsePackages.getItemText( iCurrentExtension , 1 )
+ printlog( " * " & cItemList( iCurrentExtension )
+ next iCurrentExtension
+
+ hExtensionGetItemList() = iItemCount
+ cItemList( 0 ) = iItemCount
+ PackageManager.close()
+
+ else
+
+ hExtensionGetItemList() = 0
+
+ endif
+
+end function
+
+'*******************************************************************************
+
+function hSelectExtensionID( iPos as integer ) as string
+
+ '///<h3>Select an item by index in the list of available extensions</h3>
+ '///<i>This function needs the Extension Manager to be open. It will only
+ '///+ select extensions but not their components.</i><br><br>
+
+ '///<u>Input:</u>
+ '///<ol>
+ '///+<li>Absolute position of the extension to be selected (Integer)</li>
+ '///</ol>
+
+ '///<u>Return Value:</u><br>
+ '///<ol>
+ '///+<li>Name of the selected extension (String)</li>
+ '///+<li>Empty string on index out of range or Extension Manager not open</li>
+ '///</ol>
+
+ printlog( "Selecting extension at pos. " & iPos )
+
+ ToolsPackageManager
+ kontext "PackageManager"
+ if ( PackageManager.exists( 2 ) ) then
+ try
+ BrowsePackages.select( iPos )
+ hSelectExtensionID() = BrowsePackages.getItemText( iPos , 1 )
+ catch
+ hSelectExtensionID() = ""
+ endcatch
+ PackageManager.close()
+ else
+ hSelectExtensionID() = ""
+ endif
+
+
+end function
+
+'*******************************************************************************
+
+function hSelectExtensionName( cName as string ) as integer
+
+ '///<h3>Select an item by name in the list of available extensions</h3>
+ '///<i>This function needs the Extension Manager to be open. It will only
+ '///+ select extensions but not their components.</i><br><br>
+
+ '///<u>Input:</u>
+ '///<ol>
+ '///+<li>Name of the extension (String)</li>
+ '///<ul>
+ '///+<li>Name of any item in the treelist, even those of top nodes</li>
+ '///</ul>
+ '///</ol>
+
+ '///<u>Return Value:</u><br>
+ '///<ol>
+ '///+<li>Absolute position of the selected extension (Integer)</li>
+ '///<ul>
+ '///+<li>0 = Extension was not found</li>
+ '///+<li>&gt; 0 = Absolute position of the extension/node</li>
+ '///+<li>-1 = Extension Manager did not open</li>
+ '///</ul>
+ '///</ol>
+
+ printlog( "Selecting extension by display name: " & cName )
+
+ ToolsPackageManager
+ kontext "PackageManager"
+ if ( PackageManager.exists( 2 ) ) then
+ try
+ BrowsePackages.select( cName )
+ hSelectExtensionName() = BrowsePackages.getSelIndex()
+ catch
+ hSelectExtensionName() = 0
+ endcatch
+ PackageManager.close()
+ else
+ hSelectExtensionName() = -1
+ endif
+
+
+end function
+
+
+'*******************************************************************************
+
+function hSelectOptionsItem( cName as string, iIndex as integer ) as integer
+
+ '///<h3>Select an item in Tools/Options and verify</h3>
+ '///<i>You need to open the Tools/Options dialog before using this function,
+ '///+ it will not close the dialog either. No warnlogs are printed so evaluation
+ '///+ of the return value is mandatory</i><br><br>
+
+ '///<u>Parameter(s):</u><br>
+ '///<ol>
+
+ '///+<li>Name of the extension node (string)</li>
+ '///<ul>
+ '///+<li>Name of the module</li>
+ '///+<li>Name of the leaf</li>
+ '///+<li>Node must be valid</li>
+ '///</ul>
+
+ '///+<li>Position of the node (absolute) (integer)</li>
+ '///<ul>
+ '///+<li>All nodes are expanded</li>
+ '///+<li>Position must be valid (&gt; 0 and &le; number of nodes in list)</li>
+ '///</ul>
+
+ '///</ol>
+
+
+ '///<u>Returns:</u><br>
+ '///<ol>
+ '///+<li>Errorcondition (integer)</li>
+ '///<ul>
+ '///+<li>0 = Success</li>
+ '///+<li>1 = Partial success - node is at wrong position</li>
+ '///+<li>2 = Node does not exist</li>
+ '///+<li>3 = Dialog not open</li>
+ '///+<li>4 = Index out of range (incorrect call to function)</li>
+ '///</ul>
+ '///</ol>
+
+ const CFN = "hSelectOptionsItem::"
+ printlog( CFN & "Enter with option (Name).: " & cName )
+ printlog( CFN & "Enter with option (Index): " & iIndex )
+
+ dim brc as boolean ' a multi purpose boolean returnvalue
+ dim irc as integer ' a multi purpose integer returnvalue
+ dim crc as string ' a multi purpose string returnvalue
+
+ '///<u>Description:</u>
+ '///<ul>
+ '///+<li>Make sure we are on the Tools/Options dialog</li>
+ kontext "OptionenDlg"
+ if ( not OptionenDlg.exists( 2 ) ) then
+ warnlog( CFN & "Tools/Options is not open, aborting" )
+ hSelectOptionsItem() = 3
+ exit function
+ endif
+
+ '///+<li>Expand all nodes on &quot;OptionsListe&quot;</li>
+ irc = hExpandAllNodes( OptionsListe )
+ if ( irc < iIndex ) then
+ warnlog( CFN & "Index out of range, quitting" )
+ hSelectOptionsItem() = 4
+ exit function
+ endif
+
+ '///+<li>Search for the node at the given index, handle errors, exit function</li>
+ crc = hSelectNode( OptionsListe , iIndex )
+
+ ' if the name of the node at given position is ok ...
+ if ( crc = cName ) then
+ printlog( CFN & "Exit: The node was found: " & crc )
+ hSelectOptionsItem() = 0
+ exit function
+
+ ' if the name is not ok, try to find the node by name
+ else
+ printlog( CFN & "Node not found at expected position, retrying" )
+ irc = hSelectNodeByName( OptionsListe , cName )
+
+ ' if the node is found it is just at the wrong position - bad but not deadly
+ if ( irc > 0 ) then
+ qaerrorlog( CFN & "Exit: Node <" & cName & "> found at pos: " & irc )
+ hSelectOptionsItem() = 1
+ exit function
+
+ ' if the node was not found at all this is really bad.
+ else
+ warnlog( CFN & "Exit: Node does not exist: " & cName )
+ hSelectOptionsItem() = 3
+ exit function
+ endif
+ endif
+
+ '///</ul>
+
+end function
+
+
+'*******************************************************************************
+
+function hIsExtensionAlreadyInstalled( cName as string ) as boolean
+
+ '///<h3>Check if an extension is already installed</h3>
+ '///<i>The function opents the Extension Manager, finds (or not) the extension
+ '///+ and returns an appropriate return value. The Extension Manager is
+ '///+ closed again at the end.</i><br><br>
+
+ '///<u>Input:</u>
+ '///<ol>
+ '///+<li>Name of the extension (String)</li>
+ '///</ol>
+
+ '///<u>Return Value:</u><br>
+ '///<ol>
+ '///+<li>is the extension allredy installed (boolean)</li>
+ '///<ul>
+ '///+<li>FALSE = Extension is not installed</li>
+ '///+<li>FALSE = Extension Manager did not open</li>
+ '///+<li>TRUE = Extension is installed</li>
+ '///</ul>
+ '///</ol>
+
+ printlog( "Checking if extension is already installed: " & cname )
+
+ ToolsPackageManager
+ kontext "PackageManager"
+ if ( PackageManager.exists( 2 ) ) then
+ try
+ BrowsePackages.select( cName )
+ hIsExtensionAlreadyInstalled() = TRUE
+ catch
+ hIsExtensionAlreadyInstalled() = FALSE
+ endcatch
+ PackageManager.close()
+ else
+ hIsExtensionAlreadyInstalled() = FALSE
+ endif
+
+end function
+
+
+'*******************************************************************************
+
+function hDisableUserExtensionGUI( extension_name as string ) as integer
+
+ '///<h3>Disable a userspace extension by name via GUI</h3>
+ '///<i>This function tries to disable an Extension specified by name. There
+ '///+ are several reasons why this might fail so it is required to evaluate the
+ '///+ returnvalue as the function will not print any warnings. If the function
+ '///+ fails this is most likely caused by a) the extension already being
+ '///+ disabled or b) the extension belonging to the shared layer.<br>
+ '///+ The Extension Manager needs to be open when function is called.</i><br><br>
+
+ '///<u>Parameter(s):</u><br>
+ '///<ol>
+
+ '///+<li>Name of the extension to be disabled (string)</li>
+ '///<ul>
+ '///+<li>Only extensions from the user layer can be disabled</li>
+ '///</ul>
+
+ '///</ol>
+
+
+ '///<u>Returns:</u><br>
+ '///<ol>
+ '///+<li>Errorcondition (integer)</li>
+ '///<ul>
+ '///+<li>0 = Extension was found and disabled</li>
+ '///+<li>1 = Extension does not exist</li>
+ '///+<li>2 = Extension could not be disabled</li>
+ '///+<li>3 = Extension Manager did not open</li>
+ '///</ul>
+
+ printlog( "Disabling user extension" )
+
+ ToolsPackageManager
+ kontext "PackageManager"
+ if ( PackageManager.exists( 2 ) ) then
+ try
+ BrowsePackages.select( extension_name )
+ if ( Disable.exists() and Disable.isEnabled() ) then
+ hDisableUserExtensionGUI() = 0
+ else
+ hDisableUserExtensionGUI() = 2
+ endif
+ PackageManager.close()
+ catch
+ hDisableUserExtensionGUI() = 1
+ endcatch
+ else
+ hDisableUserExtensionGUI() = 3
+ endif
+
+end function
+
+'*******************************************************************************
+
+function hGetExtensionCount() as integer
+
+ printlog( "Getting number of installed extensions." )
+
+ ToolsPackageManager
+ kontext "PackageManager"
+ if ( PackageManager.exists( 2 ) ) then
+ try
+ hGetExtensionCount() = BrowsePackages.getItemCount()
+ PackageManager.close()
+ catch
+ hGetExtensionCount() = -2
+ endcatch
+ else
+ hGetExtensionCount() = -1
+ endif
+
+
+end function
+
+
diff --git a/testautomation/global/tools/includes/optional/t_filetools.inc b/testautomation/global/tools/includes/optional/t_filetools.inc
new file mode 100755
index 000000000000..87c7ce47c0dd
--- /dev/null
+++ b/testautomation/global/tools/includes/optional/t_filetools.inc
@@ -0,0 +1,665 @@
+'encoding UTF-8 Do not remove or change this line!
+'**************************************************************************
+'* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+'*
+'* Copyright 2008 by Sun Microsystems, Inc.
+'*
+'* OpenOffice.org - a multi-platform office productivity suite
+'*
+'* $RCSfile: t_filetools.inc,v $
+'*
+'* $Revision: 1.1 $
+'*
+'* last change: $Author: jsk $ $Date: 2008-06-20 07:58:07 $
+'*
+'* This file is part of OpenOffice.org.
+'*
+'* OpenOffice.org is free software: you can redistribute it and/or modify
+'* it under the terms of the GNU Lesser General Public License version 3
+'* only, as published by the Free Software Foundation.
+'*
+'* OpenOffice.org is distributed in the hope that it will be useful,
+'* but WITHOUT ANY WARRANTY; without even the implied warranty of
+'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+'* GNU Lesser General Public License version 3 for more details
+'* (a copy is included in the LICENSE file that accompanied this code).
+'*
+'* You should have received a copy of the GNU Lesser General Public License
+'* version 3 along with OpenOffice.org. If not, see
+'* <http://www.openoffice.org/license.html>
+'* for a copy of the LGPLv3 License.
+'*
+'/************************************************************************
+'*
+'* owner : joerg.skottke@sun.com
+'*
+'* short description : Functions that work with files like deleting, loading...
+'*
+'\******************************************************************************
+
+Option Explicit
+
+private const CBUILDID = "680" ' This corresponds to the 680 codeline
+
+function hDeleteFile( cFileOrig as string ) as boolean
+
+ const CFN = "hDeleteFile::"
+ dim cHome as string
+ cHome = gOfficePath & "user"
+ cHome = convertpath( cHome )
+ dim cFile as string
+ cFile = convertpath( cFileOrig )
+
+ '///<h3>Delete a file</h3>
+ '///<i>In many cases it is a good idea to use this function outside the testcase.<br>
+ '///+ You should always evaluate the returncode</i><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Filename (string)</li>
+ '///<ul>
+ '///+<li>The function converts the path to system specific syntax (convertpath)
+ '///+ but does <b>not</b> modify the input parameter</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Errorstatus (boolean)</li>
+ '///<ul>
+ '///+<li>TRUE: File was deleted/does not exist</li>
+ '///+<li>FALSE: File could not be deleted/any other error</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+
+ ' this function tries to delete a file and does some very basic error-
+ ' handling. Returns 'true' on success, only error while deleting returns
+ ' 'false', if the file does not exist, it is considered to be successfully
+ ' deleted.
+ ' i introduced this function due to a number of cases where deleting files
+ ' actually failed because of weird code or situations where the user lacks
+ ' accessrights to files are not handled at all.
+
+ '///+<li>We may never delete a file outside gOfficePath/user/work</li>
+ if ( instr( cFile , cHome ) = 0 ) then
+ qaerrorlog( CFN & "Trying to delete file outside (default)homedir -> forbidden" )
+ qaerrorlog( CFN & "Home: " & cHome )
+ qaerrorlog( CFN & "File: " & cFile )
+ hDeleteFile() = false
+ exit function
+ endif
+
+ cFile = convertpath( cFile )
+
+ '///+<li>Check that the file exists</li>
+ if ( FileExists( cFile ) ) then
+
+ '///+<li>Use kill to delete</li>
+ try
+
+ kill( cFile )
+
+ '///+<li>Verify that the file does not exist anymore</li>
+ if ( FileExists( cFile ) ) then
+ warnlog( CFN & "File was not deleted: " & cFile )
+ hDeleteFile() = false
+ else
+ printlog( CFN & "File successfully deleted: " & cFile )
+ hDeleteFile() = true
+ endif
+
+ catch
+
+ '///+<li>in very rare cases 'kill' fails and can be handled this way</li>
+ qaerrorlog( CFN & "Deleting file failed: " & cFile )
+ hDeleteFile() = false
+
+ endcatch
+
+ else
+
+ '///+<li>write some text to the log if the file does not exist</li>
+ printlog( CFN & "Nothing to do." )
+ hDeleteFile() = true
+
+ endif
+
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hHandleActivesOnLoad( iTries as integer , iAdd as integer ) as boolean
+
+ '///<h3>Handle any dialogs that might pop up when loading a file</h3>
+ '///<i>Beware: This function gives only limited control over the dialogs closed,
+ '///+ it just closes anything it can.</i><br>
+ '///<i>Please refer to the inline documentation for further details</i><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Number of dialogs to be closed (integer)</li>
+ '///<ul>
+ '///+<li>Number of dialogs not limited though more than 3 is not useful</li>
+ '///</ul>
+ '///+<li>Additional dialogs (integer).</li>
+ '///<ul>
+ '///+<li>Number of dialogs to handle in case of unexpected behavior. If unsure set it to 2</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Errorcondition (boolean)</li>
+ '///<ul>
+ '///+<li>TRUE: The expected number of dialogs were closed</li>
+ '///+<li>FASLE: On any other condition</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+ '///+<li>OK to create a new document based on a template</li>
+ '///+<li>YES to update links</li>
+ '///+<li>YES to execute macros</li>
+ '///</ul>
+
+ use "global/tools/includes/optional/t_stringtools.inc"
+
+ const CFN = "hHandleActivesOnLoad::"
+
+ dim iTry as integer
+ dim iActives as integer
+ dim cMessage as string
+ dim bSkip as boolean
+
+ printlog( CFN & "Enter" )
+
+ ' not good but apparently required - else hDestroyDocument will handle the
+ ' dialogs and warn about them.
+
+ ' think positive: preset the returnvalue with "true"
+ hHandleActivesOnLoad() = true
+
+ for iTry = 1 to iTries + iAdd
+
+ ' handle two possible dialogs:
+ ' 1. The warning that the user should create a new document based
+ ' on this Sample/Template (the document is writeprotected)
+ ' 2. The question to update links to the internet. Note: If you
+ ' use proxies, they must be set correctly otherwise the result
+ ' is undefined.
+
+ ' Although this works quite well, there is a flaw that we will not
+ ' get information about an "active" dialog that cannot be closed by
+ ' .yes() or .ok(). If this happens, we probably run into an error
+ kontext "Active"
+ try
+ if ( active.exists( 1 ) ) then
+
+ cMessage = active.getText()
+ cMessage = hRemoveLineBreaks( cMessage )
+ printlog( "Ressource type is: " & Active.getRT() )
+ bSkip = false
+
+ wait( 100 )
+
+
+ ' ok to create a new document
+ try
+ active.ok()
+ iActives = iActives + 1
+ printlog( CFN & "MSG (" & iActives & "): " & cMessage )
+ printlog( CFN & "MSG (" & iActives & "): closed with OK" )
+ bSkip = true
+ catch
+ printlog( CFN & "Missed - this dialog has no OK button (create new document)" )
+ endcatch
+
+ if ( not bSkip ) then
+ ' no to update links
+ try
+ active.no()
+ iActives = iActives + 1
+ printlog( CFN & "MSG (" & iActives & "): " & cMessage )
+ printlog( CFN & "MSG (" & iActives & "): closed with NO" )
+ catch
+ printlog( CFN & "Missed - this dialog has no NO button (update links)" )
+ endcatch
+ endif
+
+ endif
+ catch
+ warnlog( "Serious problem while trying to handle messageboxes" )
+ hHandleActivesOnLoad() = false
+ endcatch
+
+ next iTry
+
+ ' now see how many dialogs were allowed and how many have been closed
+ ' this does not change the return value of the function
+ if ( iActives > iTries ) then
+ printlog( CFN & "Exit: The test closed more dialogs than expected" )
+ hHandleActivesOnLoad() = false
+ else
+ printlog( CFN & "Exit" )
+ endif
+
+end function
+
+'*******************************************************************************
+
+function hHandleInitialDialogs() as integer
+
+ const CFN = "hHandleInitialDialogs::"
+
+ '///<h3>Handle dialogs while opening samples/templates etc.</h3>
+ '///<i>The returnvalue is of limited use</i><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Nothing</li>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Id of the dialog (integer)</li>
+ '///<ul>
+ '///+<li>0: No dialog was found</li>
+ '///+<li>1: UseOfThisTemplate</li>
+ '///+<li>2: StarOfficeCalendar1</li>
+ '///+<li>3: NewsletterLayout</li>
+ '///+<li>4: PortfolioCurrency</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+
+ ' NOTE: The ID of the dialog will be returned but is of limited use
+ ' Function returns 0 if no dialogs have been encountered
+
+ dim incident as integer
+ incident = 0
+
+ printlog( CFN & "Enter" )
+
+ '///+<li>Test for UseOfThisTemplate-dialog</li>
+ Kontext "UseOfThisTemplate"
+ if ( UseOfThisTemplate.Exists() ) then
+ printlog( CFN & "Closing UseOfThisTemplate-dialog" )
+ incident = 1
+ CancelButton.Click()
+ endif
+
+ '///+<li>Test for StarOfficeCalendar1-dialog</li>
+ Kontext "StarOfficeCalendar1"
+ if ( StarOfficeCalendar1.Exists() ) then
+ printlog( CFN & "Closing StarOfficeCalendarl-dialog" )
+ incident = 2
+ Create.Click()
+ endif
+
+ '///+<li>Test for NewsletterLayout-dialog</li>
+ Kontext "NewsletterLayout"
+ if ( NewsletterLayout.Exists() ) then
+ printlog( CFN & "Closing NewsletterLayout-dialog" )
+ incident = 3
+ OkButton.Click()
+ endif
+
+ '///+<li>Test for PortfolioCurrency-dialog</li>
+ Kontext "PortfolioCurrency"
+ if ( PortfolioCurrency.Exists() ) then
+ printlog( CFN & "Closing PortfolioCurrency-dialog" )
+ incident = 4
+ OKButton.Click()
+ endif
+
+ hHandleInitialDialogs() = incident
+ printlog( CFN & "Exit" )
+
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hWaitWhileLoading() as boolean
+
+ '///<h3>Wait for a document to load</h3>
+ '///<i>Extends: IsItLoaded with 10 retries</i><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Nothing</li>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Errorstatus (boolean)</li>
+ '///<ul>
+ '///+<li>TRUE: Document was loaded</li>
+ '///+<li>FALSE: Document not loaded</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+ ' IsItLoaded wastes at least 5 seconds on each call which is bad
+ ' for the extras test which run at least 20 minutes longer than
+ ' necessary. The function works the same way as IsItLoaded but
+ ' eliminates a lot of sleep-cycles.
+
+ dim iNextProbe as integer
+ dim brc as boolean
+ dim iTime as integer
+
+ const CFN = "hWaitWhileLoading::"
+ const I_MAX_WAIT = 30
+ const I_PROBE_INTERVAL = 100
+
+ printlog( CFN & "Enter" )
+
+ '///+<li>Cycle for at most ten times to check the IsDocLoading-slot</li>
+ for iNextProbe = 1 to I_MAX_WAIT
+
+ brc = false
+ wait( I_PROBE_INTERVAL )
+
+ '///+<li>while the file is loaded the slot will not be dispatched -> catch</li>
+ try
+ brc = IsDocLoading
+ hWaitWhileLoading() = true
+ iTime = iNextProbe * I_PROBE_INTERVAL
+ printlog( CFN & "File loaded in less than " & iTime & " ms" )
+ catch
+ endcatch
+
+ '///+<li>"exit for" within try...catch does not always work</li>
+ if ( brc ) then
+ exit for
+ endif
+
+ next iNextProbe
+
+ '///+<li>Warn if the document did not respond in at most 10 seconds</li>
+ if ( not brc ) then
+ printlog( CFN & "Exit: Did not get feedback within 10 seconds" )
+ hWaitWhileLoading() = true
+ else
+ printlog( CFN & "Exit" )
+ endif
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hCancelFilterDialog() as boolean
+
+ '///<h3>Handle filter selection dialog</h3>
+ '///<i>This dialog might come up if the documenttype could not be determined.
+ '///+ This is most likely a bug since we should handle any type of document
+ '///+ correctly</i><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Nothing</li>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Errorstatus</li>
+ '///<ul>
+ '///+<li>TRUE: If the dialog was found and closed</li>
+ '///+<li>FALSE: If no filterdialog exists</li>
+ '///</ul>
+ '///+<li>Variable</li>
+ '///<ul>
+ '///+<li>Variable description</li>
+ '///+<li>Variable description</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+
+ const CFN = "hCancelFilterDialog::"
+
+ '///+<li>Check whether the filter dialog is open or not, close it</li>
+ kontext "FilterAuswahl"
+ if ( FilterAuswahl.exists() ) then
+ warnlog( CFN & "Found. Closing with CANCEL" )
+ hCancelFilterDialog() = true
+ FilterAuswahl.cancel()
+ else
+ printlog( CFN & "No FilterDialog." )
+ hCancelFilterDialog() = false
+ endif
+
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hGetWorkPath() as string
+
+ '///<h3>Retrieve the users work directory</h3>
+ '///<i>Uses: Call to UNO service</i><br>
+ '///<i>Errorhandling: Fixes &quot;$(user)&quot;-type path (uses fallback)</i><br>
+ '///<i>Errorhandling: Handles broken UNO connection (uses fallback)</i><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Nothing</li>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Path to local workdir (string)</li>
+ '///<ul>
+ '///+<li>Includes trailing slash/backslash</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+ dim sPath as string
+ dim sDefaultPath as string
+ sDefaultPath = convertpath( gOfficePath & "user/work" )
+ dim oOfficeConnect as object
+ dim oOfficeConfig as object
+ dim bPathIsFromAPI as boolean
+
+ const CFN = "hGetWorkPath::"
+
+ '///+<li>Create an UNO service and ask it for the location of &quot;Work&quot;</li>
+ try
+ oOfficeConnect = hGetUnoService( true )
+ oOfficeConfig = oOfficeConnect.createInstance( "com.sun.star.util.PathSettings" )
+ sPath = convertFromURL( oOfficeConfig.Work )
+ bPathIsFromAPI = true
+ catch
+ '///+<li>Handle broken UNO connection</li>
+ printlog( CFN & "Could not access service, connection broken?" )
+ sPath = ""
+ bPathIsFromAPI = false
+ endcatch
+
+ '///+<li>If the path differs from the default do a warnlog</li>
+ if ( sPath <> sDefaultPath ) then
+ printlog( CFN & "Default path is: " & sDefaultPath )
+ printlog( CFN & "Workpath is not defaultpath: " & sPath )
+ printlog( CFN & "Overriding UNO path" )
+ sPath = convertpath( gOfficePath & "user\work" )
+ bPathIsFromAPI = false
+ endif
+
+ '///+<li>Apply fallback in case of broken connection or invalid path</li>
+ if ( instr( sPath , "$(user)" ) > 0 ) then
+ printlog( CFN & "sPath has $(user)-type string, using fallback" )
+ sPath = sDefaultPath
+ bPathIsFromAPI = false
+ endif
+
+ '///+<li>Add trailing pathseparator, do convertpath</li>
+ sPath = sPath & "/"
+ sPath = convertpath( sPath )
+
+ '///+<li>Print info to the log and return the path</li>
+ if ( bPathIsFromAPI ) then
+ printlog( CFN & "(From API): " & sPath )
+ else
+ qaerrorlog( CFN & "(Junked API-Path): " & sPath )
+ endif
+ hGetWorkPath() = sPath
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hGetInputPath( byval sBasePath as string, byval sFile as string ) as string
+
+ '///<h3>Create an input path for reference files</h3>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>BasePath (string) without trailing slash/backslash</li>
+ '///<ul>
+ '///+<li>Format: gTesttoolPath &amp; &quot;[project]\input\[dir]&quot;</li>
+ '///</ul>
+ '///+<li>Filename (string)</li>
+ '///<ul>
+ '///+<li>The name of the file below BasePath to be used</li>
+ '///+<li>The filename may be an empty string</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Full path to file: BasePath + Build-Id + ProductName + sFile</li>
+ '///<ul>
+ '///+<li>Build-ID (e.g. &quot;680&quot;, from environment)</li>
+ '///+<li>ProducName (e.g &quot;OpenOffice.org&quot;, from environment)</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+ const CFN = "hGetInputPath::"
+ dim sPath as string
+ dim iAttr as integer
+ dim cLastChar as string
+ dim iLen as integer
+
+ sPath = convertpath( sBasePath )
+
+ '///+<li>None of the two parameters may be empty</li>
+ if ( sPath = "" ) then
+ warnlog( CFN & "Invalid parameter: Empty string passed to function" )
+ hGetInputPath() = ""
+ exit function
+ endif
+
+ '///+<li>Remove trailing slash or backslash</li>
+ iLen = len( sPath )
+ cLastChar = right( sPath , 1 )
+ if ( cLastChar = gPathSigne ) then
+ sPath = mid( sPath , 1 , iLen - 1 )
+ printlog( CFN & "Truncated path: Trailing Pathseparator not allowed" )
+ endif
+
+ '///+<li>At least Basepath should exist</li>
+ if ( dir ( sPath ) = "" ) then
+ warnlog( CFN & "BasePath does not exist: " & sPath )
+ hGetInputPath() = ""
+ exit function
+ endif
+
+ '///+<li>We must be certain, that basepath is a directory</li>
+ iAttr = getAttr( sPath )
+ if ( iAttr < 16 or iAttr > 17 ) then
+ warnlog( CFN & "Invalid Path: Not a directory: " & sPath )
+ hGetInputPath() = ""
+ exit function
+ endif
+
+ '///+<li>Now we concatenate all the information we have to a fully qualified path</li>
+ sPath = sPath & "\" & CBUILDID & "\" & gProductName & "\" & sFile
+ sPath = convertpath( sPath )
+
+ '///+<li>...and return it (without further verification)</li>
+ printlog( CFN & sPath )
+ hGetInputPath() = sPath
+
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hGetFileSizeAsLong( cFileName as string ) as long
+
+ '///<h3>Get the size (long) of a file</h3>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Filename (string)</li>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Size of file (long)</li>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+ const CFN = "hGetFileSizeAsLong::"
+
+ ' This function returns the size of a specified file. If it is a directory,
+ ' the size will default to -1 (A filesize can never be <0 - hopefully)
+
+ dim iAttrib as integer
+
+ '///+<li>Verify that the given file exists</li>
+ if ( app.dir( cFileName ) <> "" ) then
+
+ try
+ iAttrib = getattr( cFileName )
+
+ '///+<li>Return the size for a file or -1 for a directory</li>
+ if ( iAttrib <> 16 and iAttrib <> 17 ) then
+ hGetFileSizeAsLong() = filelen( cFileName )
+ else
+ hGetFileSizeAsLong() = -1
+ endif
+ catch
+ qaerrorlog( CFN & "File was not handled correctly: " & cFileName )
+ hGetFileSizeAsLong() = 0
+ endcatch
+
+ else
+
+ '///+<li>Return a size of 0 if the file was not found</li>
+ hGetFileSizeAsLong() = 0
+ warnlog( CFN & "File does not exist: " & cFileName )
+
+ endif
+
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hGetWorkFile( cFileName as string ) as string
+
+ '///<h3>Returns a fully qualified filename to a workfile</h3>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Filename without path (string)</li>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Filename including path to user work directory (string)</li>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+ '///+<li>Concatenate workpath and filename, convertpath</li>
+ hGetWorkFile() = convertpath( hGetWorkPath() & cFileName )
+ '///</ul>
+
+end function
+
+
diff --git a/testautomation/global/tools/includes/optional/t_key_tools.inc b/testautomation/global/tools/includes/optional/t_key_tools.inc
new file mode 100755
index 000000000000..04df2e37313e
--- /dev/null
+++ b/testautomation/global/tools/includes/optional/t_key_tools.inc
@@ -0,0 +1,569 @@
+'encoding UTF-8 Do not remove or change this line!
+'**************************************************************************
+'* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+'*
+'* Copyright 2008 by Sun Microsystems, Inc.
+'*
+'* OpenOffice.org - a multi-platform office productivity suite
+'*
+'* $RCSfile: t_key_tools.inc,v $
+'*
+'* $Revision: 1.1 $
+'*
+'* last change: $Author: jsk $ $Date: 2008-06-20 07:58:19 $
+'*
+'* This file is part of OpenOffice.org.
+'*
+'* OpenOffice.org is free software: you can redistribute it and/or modify
+'* it under the terms of the GNU Lesser General Public License version 3
+'* only, as published by the Free Software Foundation.
+'*
+'* OpenOffice.org is distributed in the hope that it will be useful,
+'* but WITHOUT ANY WARRANTY; without even the implied warranty of
+'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+'* GNU Lesser General Public License version 3 for more details
+'* (a copy is included in the LICENSE file that accompanied this code).
+'*
+'* You should have received a copy of the GNU Lesser General Public License
+'* version 3 along with OpenOffice.org. If not, see
+'* <http://www.openoffice.org/license.html>
+'* for a copy of the LGPLv3 License.
+'*
+'/************************************************************************
+'*
+'* owner : joerg.skottke@sun.com
+'*
+'* short description : tools for evaluation of key=value datalists
+'*
+'*******************************************************************************
+' **
+' #1 hGetDataPairAsString ' retrieve key=value from a list
+' #1 hGetValueForPairAsString ' retrieve value from a key=value as string
+' #1 hGetValueForPairAsLong ' retrieve value from a key=value as long integer
+' #1 hGetValueForKeyAsInt ' retrieve value for a specified key as integer
+' #1 hGetValueForKeyAsLong ' retrieve value for a specified key as long integer
+' #1 hGetKeyForPairAsString ' retrieve key from key=value as string
+' #1 hGetKeyForValueAsString ' retrieve key for a specified value as string
+' #1 hGetKeyForValueAsInt ' retrieve key for a specified value as int
+' #1 hGetIndexForKeyAsInt ' retrieve the index for a key in a list
+' #1 KeyCompare ' compare two keys
+' **
+'\******************************************************************************
+
+' Some variables explained:
+'
+' cComp is the KEY belonging to the VALUE above for reverse test
+'
+' NOTE: Other related functions can be found in global/tools/inc/t_filters.inc
+
+'*******************************************************************************
+
+function hGetDataPairAsString( sKey as string, sVal as long ) as string
+
+ '///<h3>Concatenate two strings and insert an = sign</h3>
+ '///<i>About &quot;KEY&quot;-functions: <br>
+ '///These functions are used whenever
+ '///+ data is to be processed that is stored in a key=value format.<br>
+ '///+ They handle a single string or a list of strings
+ '///+ to e.g. isolate a key, a value or to just retrieve the pair.</i><br><br>
+
+ '///<u>Input</u>:
+ '///<ol>
+
+ '///+<li>KEY (string)</li>
+ '///<ul>
+ '///+<li>Anything but should not contain # or '</li>
+ '///</ul>
+
+ '///+<li>VALUE (string)</li>
+ '///<ul>
+ '///+<li>Anything but should not contain # or '</li>
+ '///</ul>
+
+ '///</ol>
+
+ '///<u>Returns</u>:
+ '///<ol>
+
+ '///+<li>KEY=VALUE pair (string)</li>
+
+ '///</ol>
+
+ '///<u>Description</u>:
+ '///<ul>
+
+ '///+<li>Returns string1=string2</li>
+ hGetDataPairAsString() = sKey & "=" & sVal
+
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hGetValueForPairAsString( cLine as string ) as string
+
+ '///<h3>Retrieve value from a key=value string</h3>
+ '///<i>About &quot;KEY&quot;-functions: <br>
+ '///These functions are used whenever
+ '///+ data is to be processed that is stored in a key=value format.<br>
+ '///+ They handle a single string or a list of strings
+ '///+ to e.g. isolate a key, a value or to just retrieve the pair.</i><br><br>
+
+ '///<u>Input</u>:
+ '///<ol>
+
+ '///+<li>KEY=VALUE pair (string)</li>
+
+ '///</ol>
+
+ '///<u>Returns</u>:
+ '///<ol>
+
+ '///+<li>VALUE (string)</li>
+ '///<ul>
+ '///+<li>Anything after the = character</li>
+ '///</ul>
+
+ '///</ol>
+
+ '///<u>Description</u>:
+ '///<ul>
+
+ dim iCharPos as integer
+
+ '///+<li>Locate the equal sign</li>
+ iCharPos = instr( cLine , "=" )
+ iCharPos = len( cLine ) - iCharPos
+
+ '///+<li>Isolate everything to the right of the equal sign</li>
+ '///+<li>Return the value as string</li>
+ hGetValueForPairAsString() = right( cLine , iCharPos )
+
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hGetValueForPairAsLong( cLine as string ) as long
+
+ '///<h3>Retrieve the value from a key=value pair as long</h3>
+ '///<i>About &quot;KEY&quot;-functions: <br>
+ '///These functions are used whenever
+ '///+ data is to be processed that is stored in a key=value format.<br>
+ '///+ They handle a single string or a list of strings
+ '///+ to e.g. isolate a key, a value or to just retrieve the pair.</i><br><br>
+
+ '///<u>Input</u>:
+ '///<ol>
+
+ '///+<li>KEY=VALUE pair (string)</li>
+
+ '///</ol>
+
+ '///<u>Returns</u>:
+ '///<ol>
+
+ '///+<li>VALUE (long)</li>
+ '///<ul>
+ '///+<li>Anything after the = character as long integer value</li>
+ '///</ul>
+
+ '///</ol>
+
+ '///<u>Description</u>:
+ '///<ul>
+
+ dim iCharPos as integer
+
+ '///+<li>Locate the equal sign</li>
+ iCharPos = instr( cLine , "=" )
+ iCharPos = len( cLine ) - iCharPos
+
+ '///+<li>Isolate and return the Value as long datatype</li>
+ hGetValueForPairAsLong = val( right( cLine , iCharPos ))
+
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hGetValueForKeyAsInt( lsList() as string, sKey as string ) as integer
+
+ '///<h3>Retrieve the value of a key=value pair as integer</h3>
+ '///<i>About &quot;KEY&quot;-functions: <br>
+ '///These functions are used whenever
+ '///+ data is to be processed that is stored in a key=value format.<br>
+ '///+ They handle a single string or a list of strings
+ '///+ to e.g. isolate a key, a value or to just retrieve the pair.</i><br><br>
+ '///<i>Prerequisite: Array compatible to listfuncs, known, valid key</i><br><br>
+
+ '///<u>Input</u>:
+ '///<ol>
+
+ '///+<li>List of KEY=VALUE pairs (string)</li>
+ '///<ul>
+ '///+<li>List must be compatible to listfunctions (see t_listfuncs.inc)</li>
+ '///</ul>
+ '///+<li>Key to be searched for within the list (string)</li>
+ '///<ul>
+ '///+<li>Key must be valid</li>
+ '///</ul>
+
+ '///</ol>
+
+ '///<u>Returns</u>:
+ '///<ol>
+
+ '///+<li>VALUE (integer)</li>
+ '///<ul>
+ '///+<li>The value for a given key</li>
+ '///</ul>
+
+ '///</ol>
+
+ '///<u>Description</u>:
+ '///<ul>
+
+ dim iItem as integer
+ dim cString as string
+ dim cComp as string
+
+ hGetValueForKeyAsInt() = 0
+
+ ' Scan through the list and look for sKey. If found, return the Value
+ ' (everything to the right of the '=')
+ '///+<li>Search the list for the key</li>
+ for iItem = 1 to listcount( lsList() )
+ if( instr( lsList( iItem ) , sKey ) <> 0 ) then
+
+ '///+<li>Verify that this is really the correct key by reverse-checking</li>
+ cComp = hGetKeyforPairAsString( lsList( iItem ) )
+
+ '///+<li>Retrieve the value for the key as string</li>
+ if( sKey = cComp ) then
+ cString = hGetValueForPairAsString( lsList( iItem ) )
+ iItem = listcount( lsList() ) + 1
+ endif
+
+ endif
+ next iItem
+
+ '///+<li>Convert the stringvalue to integer and return it</li>
+ hGetValueForKeyAsInt() = val( cString )
+
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hGetValueForKeyAsLong( lsList() as string, sKey as string ) as long
+
+ '///<h3>Retrieve the value of a key=value pair as integer</h3>
+ '///<i>About &quot;KEY&quot;-functions: <br>
+ '///These functions are used whenever
+ '///+ data is to be processed that is stored in a key=value format.<br>
+ '///+ They handle a single string or a list of strings
+ '///+ to e.g. isolate a key, a value or to just retrieve the pair.</i><br><br>
+ '///<i>Prerequisite: Array compatible to listfuncs, known, valid key</i><br><br>
+
+ '///<u>Input</u>:
+ '///<ol>
+
+ '///+<li>List of KEY=VALUE pairs (string)</li>
+ '///<ul>
+ '///+<li>List must be compatible to listfunctions (see t_listfuncs.inc)</li>
+ '///</ul>
+ '///+<li>Key to be searched for within the list (string)</li>
+ '///<ul>
+ '///+<li>Key must be valid</li>
+ '///</ul>
+
+ '///</ol>
+
+ '///<u>Returns</u>:
+ '///<ol>
+
+ '///+<li>VALUE (long integer)</li>
+ '///<ul>
+ '///+<li>The value for a given key</li>
+ '///</ul>
+
+ '///</ol>
+
+ '///<u>Description</u>:
+ '///<ul>
+
+ dim iItem as integer
+ dim cString as string
+ dim cComp as string
+
+ hGetValueForKeyAsInt() = 0
+
+ ' Scan through the list and look for sKey. If found, return the Value
+ ' (everything to the right of the '=')
+ '///+<li>Search the list for the key</li>
+ for iItem = 1 to listcount( lsList() )
+ if( instr( lsList( iItem ) , sKey ) <> 0 ) then
+
+ '///+<li>Verify that this is really the correct key by reverse-checking</li>
+ cComp = hGetKeyforPairAsString( lsList( iItem ) )
+
+ '///+<li>Retrieve the value for the key as string</li>
+ if( sKey = cComp ) then
+ cString = hGetValueForPairAsString( lsList( iItem ) )
+ iItem = listcount( lsList() ) + 1
+ endif
+
+ endif
+ next iItem
+
+ '///+<li>Convert the stringvalue to long integer and return it</li>
+ hGetValueForKeyAsInt() = val( cString )
+
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hGetKeyForPairAsString( cLine as string ) as string
+
+ '///<h3>Retrieve the KEY from a key=value pair</h3>
+ '///<i>About &quot;KEY&quot;-functions: <br>
+ '///These functions are used whenever
+ '///+ data is to be processed that is stored in a key=value format.<br>
+ '///+ They handle a single string or a list of strings
+ '///+ to e.g. isolate a key, a value or to just retrieve the pair.</i><br><br>
+
+ '///<u>Input</u>:
+ '///<ol>
+
+ '///+<li>KEY=VALUE pair (string)</li>
+
+ '///</ol>
+
+ '///<u>Returns</u>:
+ '///<ol>
+
+ '///+<li>KEY (string)</li>
+ '///<ul>
+ '///+<li>Anything before the = character</li>
+ '///</ul>
+
+ '///</ol>
+
+ '///<u>Description</u>:
+ '///<ul>
+
+ dim iCharPos as integer
+
+ iCharPos = instr( cLine , "=" )
+
+ '///+<li>get the string to the left of the = char</li>
+ if ( iCharPos > 0 ) then
+ hGetKeyForPairAsString() = left( cLine , iCharPos -1 )
+ else
+ warnlog( "Invalid string passed to hGetKeyForPairAsString" )
+ printlog( "It was: " & cLine )
+ endif
+ '///+<li>Return the key</li>
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hGetKeyForValueAsString( lsList() as string, sVal as string ) as string
+
+ '///<h3>Retrieve the KEY for a known VALUE from a key=value pair</h3>
+ '///<i>About &quot;KEY&quot;-functions: <br>
+ '///These functions are used whenever
+ '///+ data is to be processed that is stored in a key=value format.<br>
+ '///+ They handle a single string or a list of strings
+ '///+ to e.g. isolate a key, a value or to just retrieve the pair.</i><br><br>
+ '///<i>Prerequisite: List compatible to listfuncs, known VALUE for pair</i><br><br>
+
+ '///<u>Input</u>:
+ '///<ol>
+
+ '///+<li>List of KEY=VALUE pairs (string)</li>
+ '///<ul>
+ '///+<li></li>
+ '///</ul>
+
+ '///+<li>VALUE (string)</li>
+ '///<ul>
+ '///+<li>Absolute match required.</li>
+ '///</ul>
+
+ '///</ol>
+
+ '///<u>Returns</u>:
+ '///<ol>
+
+ '///+<li>KEY (string)</li>
+
+ '///</ol>
+
+ '///<u>Description</u>:
+ '///<ul>
+
+ ' This function returns the value of a key as string.
+ ' The form of the input strings is 'key=value', the list is parsed
+ ' The key for the first occurrence of sVal is returned
+
+ dim iCurrentValue as integer
+ dim iListItems as integer
+ iListItems = listcount( lsList() )
+ dim cLine as string
+
+ ' preset a default return string
+ hGetKeyForValueAsString() = "Error: No matching KEY found for VALUE"
+
+ '///+<li>scan through a list to find an entry that matches sKey. Return the Key.</li>
+ for iCurrentValue = 1 to iListItems
+
+ cLine = lsList( iCurrentValue )
+
+ if( instr( cLine , sVal ) <> 0 ) then
+ hGetKeyForValueAsString() = hGetKeyForPairAsString( cLine )
+ iCurrentValue = iListItems + 1
+ end if
+
+ next iCurrentValue
+ '///+<li>Return the key from the first matching value</li>
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hGetKeyForValueAsInt( lsList() as string, sVal as string ) as integer
+
+ '///<h3>Retrieve the KEY for a known VALUE from a key=value pair</h3>
+ '///<i>About &quot;KEY&quot;-functions: <br>
+ '///These functions are used whenever
+ '///+ data is to be processed that is stored in a key=value format.<br>
+ '///+ They handle a single string or a list of strings
+ '///+ to e.g. isolate a key, a value or to just retrieve the pair.</i><br><br>
+ '///<i>Prerequisite: List compatible to listfuncs, known VALUE for pair</i><br><br>
+
+ '///<u>Input</u>:
+ '///<ol>
+
+ '///+<li>List of KEY=VALUE pairs (string)</li>
+
+ '///+<li>VALUE (string)</li>
+ '///<ul>
+ '///+<li>Absolute match required.</li>
+ '///</ul>
+
+ '///</ol>
+
+ '///<u>Returns</u>:
+ '///<ol>
+
+ '///+<li>KEY (integer)</li>
+
+ '///</ol>
+
+ '///<u>Description</u>:
+ '///<ul>
+
+ '///+<li>Use hgetKeyForValueAsString, convert result to integer, return it.</li>
+ hGetKeyForValueAsInt() = val( hGetKeyForValueAsString( lsList() , sVal ) )
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hGetIndexForKeyAsInt( lsList() as string, sKey as string ) as integer
+
+ '///<h3>Search a list of key=value pairs for a key and return its index</h3>
+ '///<i>About &quot;KEY&quot;-functions: <br>
+ '///These functions are used whenever
+ '///+ data is to be processed that is stored in a key=value format.<br>
+ '///+ They handle a single string or a list of strings
+ '///+ to e.g. isolate a key, a value or to just retrieve the pair.</i><br><br>
+ '///<i>Prerequisite: List compatible to listfuncs, known VALUE for pair</i><br><br>
+
+ '///<u>Input</u>:
+ '///<ol>
+
+ '///+<li>List of KEY=VALUE pairs (string)</li>
+
+ '///+<li>KEY to search for (string)</li>
+
+ '///</ol>
+
+ '///<u>Returns</u>:
+ '///<ol>
+
+ '///+<li>Index of the KEY in the list (integer)</li>
+ '///<ul>
+ '///+<li>0 if not found</li>
+ '///+<li>Any number &gt; 0 and &le; listcount( List() )</li>
+ '///</ul>
+
+ '///</ol>
+
+ '///<u>Description</u>:
+ '///<ul>
+
+ dim iItem as integer
+ dim cComp as string
+
+ hGetIndexForNamedKeyAsInt() = 0
+
+ ' Scan through the list and look for sKey. If found, return the Value
+ ' (everything to the right of the '=')
+ '///+<li>Scan through the list for the KEY</li>
+ for iItem = 1 to listcount( lsList() )
+ if( instr( lsList( iItem ) , sKey ) <> 0 ) then
+
+ '///+<li>if found, perform reverse checking</li>
+ cComp = hGetKeyforValueAsString( lsList( iItem ) )
+
+ '///+<li>get the index of the item</li>
+ if( sKey = cComp ) then
+ hGetIndexForKeyAsInt() = iItem
+ iItem = listcount( lsList() ) + 1
+ endif
+
+ endif
+ next iItem
+ '///+<li>Return the index</li>
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function keycompare( found as string, expected as string, sKey as string, optional cBugID as string) as boolean
+
+ '///<h3>Function to compare two keys with each other</h3>
+ '///<u>Deprecated, do not use</u>
+
+ if ( isMissing( cBugID ) ) then
+ cBugID = ""
+ endif
+
+ if ( lcase(found) = lcase(expected) ) then
+ printlog( " * '" & sKey & "': ok" )
+ keycompare = true
+ else
+ warnlog( "#" + cBugID + "# Control has incorrect value: '" & sKey & "'")
+ printlog( " > Found...: '" & found & "'" )
+ printlog( " > Expected: '" & expected & "'" )
+ keycompare = false
+ endif
+
+end function
+
+
+
diff --git a/testautomation/global/tools/includes/optional/t_listfuncs.inc b/testautomation/global/tools/includes/optional/t_listfuncs.inc
new file mode 100755
index 000000000000..6c7e8923fe7d
--- /dev/null
+++ b/testautomation/global/tools/includes/optional/t_listfuncs.inc
@@ -0,0 +1,736 @@
+'encoding UTF-8 Do not remove or change this line!
+'**************************************************************************
+'* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+'*
+'* Copyright 2008 by Sun Microsystems, Inc.
+'*
+'* OpenOffice.org - a multi-platform office productivity suite
+'*
+'* $RCSfile: t_listfuncs.inc,v $
+'*
+'* $Revision: 1.1 $
+'*
+'* last change: $Author: jsk $ $Date: 2008-06-20 07:58:28 $
+'*
+'* This file is part of OpenOffice.org.
+'*
+'* OpenOffice.org is free software: you can redistribute it and/or modify
+'* it under the terms of the GNU Lesser General Public License version 3
+'* only, as published by the Free Software Foundation.
+'*
+'* OpenOffice.org is distributed in the hope that it will be useful,
+'* but WITHOUT ANY WARRANTY; without even the implied warranty of
+'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+'* GNU Lesser General Public License version 3 for more details
+'* (a copy is included in the LICENSE file that accompanied this code).
+'*
+'* You should have received a copy of the GNU Lesser General Public License
+'* version 3 along with OpenOffice.org. If not, see
+'* <http://www.openoffice.org/license.html>
+'* for a copy of the LGPLv3 License.
+'*
+'/******************************************************************************
+'*
+'* owner : joerg.skottke@sun.com
+'*
+'* short description : Replacements for routines in t_lists.inc adds some
+'*
+'*******************************************************************************
+'*
+' #1 hListTestUpperBoundary ' Tests upper boundary of arrays
+' #1 hListTestLowerBoundary ' Tests lower boundary of arrays
+' #1 hListDelete ' Deletes one item from a list by index
+' #1 hListAppend ' Append an item to a list
+' #1 hManageComparisionList ' quick way to compare/create reference lists
+' #1 hListFileGetSize ' find out how big an array has to be to hold the file
+' #1 hListCompare ' compare two lists
+' #1 hListPrependString ' Insert a string infront of each item in a list
+' #1 hListAppendList ' Append one list to another
+' #1 hCountMatchesInList ' Return count of occurrences of a string within a list
+'*
+'\******************************************************************************
+
+' Note: These functions fix some minor bugs and introduce strict boundary
+' checking for the arrays we work with. The arrays must be compatible
+' to those from the "standard" list-functions.
+' Why: Two reasons:
+'
+' 1) When working with listboxes it might happen that they are empty (bug)
+' or contain more items than expected. In this case the tests would
+' usually break. This is not desired as many testcases do not rely
+' on the content of the listboxes.
+'
+' 2) This way eases the trouble of debugging huge amounts of arrays
+' like those in the installation test or anywhere else where we work
+' with reference lists. This is a coding help.
+
+'*******************************************************************************
+
+function hListTestUpperBoundary( aList() as string ) as boolean
+
+ '///<h3>Verify that ListCount does not exceed upper boundary</h3>
+ '///<i>About listfunctions: All listfunctions rely on a special type of
+ '///+ array. This can be string arrays and - in some cases - numeric
+ '///+ arrays. What makes the arrays unique is that the first item which
+ '///+ has the index 0 contains the number of items in the list to be used,
+ '///+ anything that is stored beyond this number is ignored. This has three
+ '///+ consequences: 1) all listfunctions that alter an array must update
+ '///+ the index stored in array(0) and 2) it is possible that the index
+ '///+ point beyond ubound of the array which will most likely cause a
+ '///+ runtime error. 3) Means that arrays may only have an upper boundary
+ '///+ declared, all loops must start with index array(1) and must end with
+ '///+ index array(val( array(0))</i><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>List (string)</li>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Errorstatus (boolean)</li>
+ '///<ul>
+ '///+<li>TRUE: Array is ok</li>
+ '///+<li>FALSE: Array logic has errors</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+
+ const CFN = "hListTestUpperBoundary::"
+
+ dim iUpperBoundary as integer ' size according to UBOUND
+ dim iListSize as integer ' size according to ListCount
+
+ dim brc as boolean
+ brc = true
+
+ '///+<li>Determine the size of the array</li>
+ iUpperBoundary = UBOUND( aList() )
+
+ '///+<li>Determine the <i>claimed</i> size of the array</li>
+ iListSize = ListCount( aList() )
+
+ '///+<li>Verify that val(array(0)) <= array-size</li>
+ if ( iListSize > iUpperBoundary ) then
+ warnlog ( CFN & "List points beyound upper array boundary:" )
+ printlog( CFN & "ListCount: " & iListSize )
+ printlog( CFN & "UBOUND...: " & iUpperBoundary )
+ brc = false
+ endif
+
+ hListTestUpperBoundary() = brc
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hListTestLowerBoundary( aList() as string ) as boolean
+
+ '///<h3>Verify that the lower boundaries of an array are ok</h3>
+ '///<i>Prerequisite: Array compatible with those from t_lists.inc</i>
+ '///<i>About listfunctions: All listfunctions rely on a special type of
+ '///+ array. This can be string arrays and - in some cases - numeric
+ '///+ arrays. What makes the arrays unique is that the first item which
+ '///+ has the index 0 contains the number of items in the list to be used,
+ '///+ anything that is stored beyond this number is ignored. This has three
+ '///+ consequences: 1) all listfunctions that alter an array must update
+ '///+ the index stored in array(0) and 2) it is possible that the index
+ '///+ point beyond ubound of the array which will most likely cause a
+ '///+ runtime error. 3) Means that arrays may only have an upper boundary
+ '///+ declared, all loops must start with index array(1) and must end with
+ '///+ index array(val( array(0))</i><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>List (string)</li>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Errorstatus (boolean)</li>
+ '///<ul>
+ '///+<li>TRUE: Array is ok</li>
+ '///+<li>FALSE: Array logic has errors</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+ const CFN = "hListTestLowerBoundary::"
+
+ dim iLowerBoundary as integer ' size according to LBOUND
+ dim iListSize as integer ' size according to ListCount
+
+ dim brc as boolean
+ brc = true
+
+ iLowerBoundary = LBOUND( aList() )
+ iListSize = ListCount( aList() )
+
+ '///+<li>Verify that ubound for the array returns 0 (lower boundary)</li>
+ if ( iLowerBoundary <> 0 ) then
+ warnlog ( CFN & "Boundary of the array must be 0." )
+ printlog( CFN & "Lower boundary is: " & iLowerBoundary )
+ brc = false
+ endif
+
+ '///+<li>Verify that val(array(0)) &gt; 0</li>
+ if ( iListSize < 0 ) then
+ warnlog ( CFN & "Defined Listsize (ListCount) may never be negative" )
+ printlog( CFN & "ListCount is: " & iListSize )
+ brc = false
+ endif
+
+ hListTestLowerBoundary() = brc
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hListDelete( aList() as string, iItemToDelete as integer ) as boolean
+
+ '///<h3>Delete one item from a list specified by index</h3>
+ '///<i>Prerequisite: Array compatible with those from t_lists.inc</i><br>
+ '///<i>About listfunctions: All listfunctions rely on a special type of
+ '///+ array. This can be string arrays and - in some cases - numeric
+ '///+ arrays. What makes the arrays unique is that the first item which
+ '///+ has the index 0 contains the number of items in the list to be used,
+ '///+ anything that is stored beyond this number is ignored. This has three
+ '///+ consequences: 1) all listfunctions that alter an array must update
+ '///+ the index stored in array(0) and 2) it is possible that the index
+ '///+ point beyond ubound of the array which will most likely cause a
+ '///+ runtime error. 3) Means that arrays may only have an upper boundary
+ '///+ declared, all loops must start with index array(1) and must end with
+ '///+ index array(val( array(0))</i><br>
+ '///<u>Review the code, it has many unused variables</u>
+ '///<ul>
+
+ const CFN = "hListDelete::"
+
+ dim iArraySize as integer ' The size of the array, must be large enough
+ dim iListSizeOld as integer ' The size of the list before deletion
+ dim iListSizeNew as integer ' The size of the list after deletion
+ dim iCurrentItem as integer ' Increment-Variable
+ dim iOffset as integer ' First item to be "moved down" by index
+ dim sItemToDelete as string ' The string that will be deleted
+ dim brc as boolean ' preliminary return value
+
+ '///+<li>test array integrity: upper boundary</li>
+ brc = hListTestUpperBoundary( alist() )
+ if ( not brc ) then
+ hListDelete() = brc
+ exit function
+ endif
+
+ '///+<li>test array integrity: lower boundary</li>
+ brc = hListTestLowerBoundary( alist() )
+ if ( not brc ) then
+ hListDelete() = brc
+ exit function
+ endif
+
+ '///+<li>Get some data from the arrays to work with.</li>
+ iArraySize = ubound( aList() )
+ iListSizeOld = ListCount( aList() )
+ iListSizeNew = iListSizeOld - 1
+ sItemToDelete = aList( iItemToDelete )
+ iOffset = iItemToDelete + 1
+
+ ' some output (may be removed as soon the function is thoroughly tested)
+ 'printlog( CFN & "Removing: " & sItemToDelete & " at pos " & iItemToDelete )
+
+ ' Move all items down by one in the list beginning with the item after
+ ' iItemToDelete
+ '///+<li>Move all items one up</li>
+ for iCurrentItem = iOffset to iListSizeOld
+ aList( iCurrentItem - 1 ) = aList( iCurrentItem )
+ next iCurrentItem
+
+ ' Delete the last entry, it is no longer used and it is duplicate to the item
+ ' at iListSizeOld-1 (iListSizeNew)
+ '///+<li>Delete the last item from the list</li>
+ aList( iListSizeOld ) = ""
+
+ '///+<li>Set the new listsize (one smaller than the original list)</li>
+ aList( 0 ) = iListSizeNew
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hListAppend( sNewString as string, aTargetList() as string ) as integer
+
+ '///<h3>Append an item to an existing list</h3>
+ '///<i>Prerequisite: Array compatible with those from t_lists.inc</i>
+ '///<i>About listfunctions: All listfunctions rely on a special type of
+ '///+ array. This can be string arrays and - in some cases - numeric
+ '///+ arrays. What makes the arrays unique is that the first item which
+ '///+ has the index 0 contains the number of items in the list to be used,
+ '///+ anything that is stored beyond this number is ignored. This has three
+ '///+ consequences: 1) all listfunctions that alter an array must update
+ '///+ the index stored in array(0) and 2) it is possible that the index
+ '///+ point beyond ubound of the array which will most likely cause a
+ '///+ runtime error. 3) Means that arrays may only have an upper boundary
+ '///+ declared, all loops must start with index array(1) and must end with
+ '///+ index array(val( array(0))</i><br>
+
+ const CFN = "hListAppend::"
+
+ dim iCurrentListSize as integer
+ dim iNewListSize as integer
+ dim iArraySize as integer
+ dim irc as integer
+
+ iCurrentListSize = val( aTargetList( 0 ) )
+ iNewListSize = iCurrentListSize + 1
+ iArraySize = ubound( aTargetList() )
+
+ if ( iNewListSize > iArraySize ) then
+ warnlog ( CFN & "Cannot append, array too small" )
+ printlog( CFN & "Array-Size.....: " & iArraySize )
+ printlog( CFN & "Requested index: " & iNewListSize )
+ irc = -1
+ else
+ aTargetList( iNewListSize ) = sNewString
+ aTargetList( 0 ) = iNewListSize
+ irc = iNewListSize
+ endif
+
+ hListAppend() = irc
+
+end function
+
+'*******************************************************************************
+
+function hManageComparisionList( sFileIn as string, sFileOut as string, sListOut() as string ) as integer
+
+ '///<h3>Function to create or compare a list to a reference</h3>
+ '///<i>Prerequisite: List of items to compare, input- and outputfilename</i><br>
+ '///<i>About listfunctions: All listfunctions rely on a special type of
+ '///+ array. This can be string arrays and - in some cases - numeric
+ '///+ arrays. What makes the arrays unique is that the first item which
+ '///+ has the index 0 contains the number of items in the list to be used,
+ '///+ anything that is stored beyond this number is ignored. This has three
+ '///+ consequences: 1) all listfunctions that alter an array must update
+ '///+ the index stored in array(0) and 2) it is possible that the index
+ '///+ point beyond ubound of the array which will most likely cause a
+ '///+ runtime error. 3) Means that arrays may only have an upper boundary
+ '///+ declared, all loops must start with index array(1) and must end with
+ '///+ index array(val( array(0))</i><br>
+ '///<u>BEWARE: This is a core function and used by many tests!<br>
+ '///Please read the inline documentation for further reference</u><br>
+ '///Function parameters:
+ '///<ol>
+ '///+<li>sFileIn = The file that contains the reference data</li>
+ '///+<li>sFileOut = The file new lists are written to in case of an error</li>
+ '///+<li>sListOut() = The list containing the newly retrieved data.</li>
+ '///</ol>
+ '///Description:
+ '///<ul>
+
+ const CFN = "hManageComparisionList::"
+
+ '///+<li>The name of the input file may not be empty</li>
+ if ( sFileIn = "" ) then
+ warnlog( CFN & "Invalid parameter: Input filename is empty string" )
+ hManageComparisionList() = 2
+ exit function
+ endif
+
+ '///+<li>The name of the output-file may not be empty</li>
+ if ( sFileOut = "" ) then
+ warnlog( CFN & "Invalid parameter: Output filename is empty string" )
+ hManageComparisionList() = 3
+ exit function
+ endif
+
+ '///+<li>the list should not claim to be empty / be empty</li>
+ if ( listcount( sListOut() ) = 0 ) then
+ qaerrorlog( CFN & "Invalid parameter: Array claims to be empty" )
+ hManageComparisionList() = 4
+ exit function
+ endif
+
+ ' hListFileGetSize will return -1 if the list does not exist or the number
+ ' of lines in the reference file plus additional 10 lines.
+ '///+<li>Verify that the reference file exists and is non-empty</li>
+ dim iFileSize as integer
+ iFileSize = hListFileGetSize( sFileIn )
+ dim brc as boolean
+ brc = false
+
+ '///+<li>Read the reference list and compare</li>
+ if ( iFileSize > -1 ) then
+
+ dim aReferenceList( iFileSize ) as string
+ printlog( CFN & "Reading: " & sFileIn )
+ ' disabled hGetDataFileSection because some lists contain a #
+ ' (hash) as value which is identified as comment by the function.
+ ' Fixing this for hGetDataFileSection() would break compatibility
+ ' to other functions both in framework and global module
+ 'hgetDataFileSection( sFileIn , aReferenceList() , "" , "" , "" )
+ listread( aReferenceList(), sFileIn, "utf8" )
+ brc = hListCompare( sListOut() , aReferenceList() )
+
+ endif
+
+ ' A this point there are three possible states:
+ ' a) the reference list does not exist
+ ' b) the comparision failed
+ ' c) the comparision succeeded
+ ' only if hListCompare() returns TRUE the testrun is successful.
+ ' This means that on any error, the ref-list will be written so it can be
+ ' directly reviewed/compared to the "faulty" list without having to run this
+ ' test again (after deleting the ref-file)
+ '///+<li>In case the lists are not identical, write the new one to the local work directory</li>
+ if ( brc ) then
+ printlog( CFN & "Comparision succeeded" )
+ hManageComparisionList() = 0
+ else
+ printlog( CFN & "Writing: " & sFileOut )
+ listwrite( sListOut(), sFileOut, "UTF8" )
+ qaerrorlog ( CFN & "Reference file review required:" )
+ printlog( "" )
+ printlog( CFN & "Two possible reasons:" )
+ printlog( CFN & "1) The reference file does not exist at all" )
+ printlog( CFN & "2) Reference and actual UI-Content do not match." )
+ printlog( CFN & "Location: " & sFileOut )
+ printlog( CFN & "Target..: " & sFileIn )
+ printlog( CFn & "Verify the content and copy the file to <Target>" )
+ printlog( "" )
+ printlog( CFN & "Comparision failed" )
+ hManageComparisionList() = 1
+ endif
+
+ '///+<li>Return 0 if the lists are identical, 1 if not and 2-4 on any other error</li>
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hListFileGetSize( sFileIn as string ) as integer
+
+ '///<h3>Get the number of lines from a file</h3>
+ '///<i>Prerequisites: Path to an existing plain text file</i>
+ '///<i>About listfunctions: All listfunctions rely on a special type of
+ '///+ array. This can be string arrays and - in some cases - numeric
+ '///+ arrays. What makes the arrays unique is that the first item which
+ '///+ has the index 0 contains the number of items in the list to be used,
+ '///+ anything that is stored beyond this number is ignored. This has three
+ '///+ consequences: 1) all listfunctions that alter an array must update
+ '///+ the index stored in array(0) and 2) it is possible that the index
+ '///+ point beyond ubound of the array which will most likely cause a
+ '///+ runtime error. 3) Means that arrays may only have an upper boundary
+ '///+ declared, all loops must start with index array(1) and must end with
+ '///+ index array(val( array(0))</i><br>
+ '///<ul>
+
+ const CFN = "hListFileGetSize::"
+ const I_EXTRA_SIZE = 10
+
+ '///+<li>Verify that the filename is non-empty</li>
+ if ( sFileIn = "" ) then
+ warnlog( CFN & "Invalid parameter: Filename is empty string" )
+ hListFileGetSize() = -1
+ exit function
+ endif
+
+ '///+<li>Verify that the file exists</li>
+ if ( dir( sFileIn ) = "" ) then
+ warnlog( CFN & "File not found: " & sFileIn )
+ hListFileGetSize() = -1
+ exit function
+ endif
+
+ dim iFile as integer
+ dim sLine as string
+ dim iLineCount as integer
+ iLineCount = 0
+
+ '///+<li>Open the file (standard BASIC calls)</li>
+ iFile = freefile
+ open sFileIn for input as iFile
+
+ '///+<li>Read the number of lines from the file</li>
+ while( not eof( iFile ) )
+
+ line input #iFile, sLine
+ iLineCount = iLineCount + 1
+
+ wend
+
+ '///+<li>Close the file</li>
+ close #iFile
+
+ '///+<li>Return the number of lines read or -1 on error</li>
+ hListFileGetSize() = iLineCount + I_EXTRA_SIZE
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hListCompare( aListOne() as String, aListTwo() as String ) as boolean
+
+ const CFN = "hListcompare::"
+
+ '///<h3>Compare two lists with each other, where <b>list TWO</b> is the reference</h3>
+ '///<i>Prerequisites: Two lists compatible with listfunctions</i><br>
+ '///<i>About listfunctions: All listfunctions rely on a special type of
+ '///+ array. This can be string arrays and - in some cases - numeric
+ '///+ arrays. What makes the arrays unique is that the first item which
+ '///+ has the index 0 contains the number of items in the list to be used,
+ '///+ anything that is stored beyond this number is ignored. This has three
+ '///+ consequences: 1) all listfunctions that alter an array must update
+ '///+ the index stored in array(0) and 2) it is possible that the index
+ '///+ point beyond ubound of the array which will most likely cause a
+ '///+ runtime error. 3) Means that arrays may only have an upper boundary
+ '///+ declared, all loops must start with index array(1) and must end with
+ '///+ index array(val( array(0))</i><br>
+ '///<u>Duplicates gCompare2Lists but does not print warnlogs, evaluate returncode instead</u>
+ '///<ul>
+
+ dim aOneOnlyList( ubound( aListOne() ) ) as string
+ dim aTwoOnlyList( ubound( aListTwo() ) ) as string
+
+ dim iListOneIndex as integer
+ dim iListTwoIndex as integer
+
+ dim iTwoOnlyListSize as integer
+ dim iListOneSize as integer
+
+ dim bFound as boolean
+ dim brc as boolean ' returncode: true only if lists are identical
+ brc = true
+
+ '///+<li>Create a copy of list two so we do not change the original list</li>
+ ListCopy( aListTwo() , aTwoOnlyList() )
+
+ iTwoOnlyListSize = ListCount( aTwoOnlyList() )
+ iListOneSize = ListCount( aListOne() )
+
+
+ '///+<li>Step through each item in list one</li>
+ for iListOneIndex = 1 to iListOneSize
+
+ bFound = false
+
+ '///+<li>Compare it to each item in list two</li>
+ for iListTwoIndex = 1 to iTwoOnlyListSize
+
+ '///+<li>If the entries match, delete it from the TwoOnly list</li>
+ if ( aListOne( iListOneIndex ) = aTwoOnlyList( iListTwoIndex ) ) then
+
+ bFound = true
+ aTwoOnlyList( iListTwoIndex ) = aTwoOnlyList( iTwoOnlyListSize )
+ ' this breaks compatibility to listfunctions because the actual
+ ' number of items is out of sync with listcount
+ iTwoOnlyListSize = iTwoOnlyListSize -1
+ exit for
+
+ end if
+
+ next iListTwoIndex
+
+ '///+<li>If there is no match, the item exists in list one only -> copy</li>
+ if ( not bFound ) then
+ hListAppend( aListOne( iListOneIndex ), aOneOnlyList() )
+ end if
+
+ next iListOneIndex
+
+ ' restore compatibility to listfunctions so hListPrint() will not fail
+ aTwoOnlyList( 0 ) = iTwoOnlyListSize
+
+ '///+<li>List all items that exist in List One only</li>
+ if ( ListCount( aOneOnlyList() ) > 0 ) then
+ printlog( CFN & "Objects have been added to the list" )
+ hListPrint( aOneOnlyList() , "Items found in list ONE only (NEW)" )
+ brc = false
+ end if
+
+ '///+<li>List all items that exist in List Two only</li>
+ if ( ListCount( aTwoOnlyList() ) > 0 ) then
+ printlog( CFN & "Objects have been removed from the list" )
+ hListPrint( aTwoOnlyList() , "Items found in list TWO only (MISSING)" )
+ brc = false
+ end if
+
+ hListCompare() = brc
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hListPrependString( aList() as string, cString as string ) as boolean
+
+ '///<h3>Insert a string infront of each item in a list</h3>
+ '///<i>Prerequisites: A list compatible with listfunctions</i><br>
+ '///<i>About listfunctions: All listfunctions rely on a special type of
+ '///+ array. This can be string arrays and - in some cases - numeric
+ '///+ arrays. What makes the arrays unique is that the first item which
+ '///+ has the index 0 contains the number of items in the list to be used,
+ '///+ anything that is stored beyond this number is ignored. This has three
+ '///+ consequences: 1) all listfunctions that alter an array must update
+ '///+ the index stored in array(0) and 2) it is possible that the index
+ '///+ point beyond ubound of the array which will most likely cause a
+ '///+ runtime error. 3) Means that arrays may only have an upper boundary
+ '///+ declared, all loops must start with index array(1) and must end with
+ '///+ index array(val( array(0))</i><br><br>
+ '///<i>Note that the function alters the input list. If the list contains
+ '///+ strings of the type &quot;MyString&quot; the items will be changed to
+ '///+ read &quot;Some Text : MyString&quot;</i><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>List (string)</li>
+ '///+<li>A text to be inserted infront of every item in the list</li>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Errorcondition (boolean)</li>
+ '///<ul>
+ '///+<li>The returnvalue is currently undefined</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+ const CFN = "hListPrependString::"
+ dim iCurrentItem as integer
+
+ '///+<li>Cycle through the list and insert a text infront of each item</li>
+ for iCurrentItem = 1 to listcount( aList() )
+
+ aList( iCurrentItem ) = cString & " : " & aList( iCurrentItem )
+
+ next iCurrentItem
+
+ hListPrependString() = true
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hListAppendList( aBaseList() as string, aListToAppend() as string ) as integer
+
+ '///<h3>Append one list to another</h3>
+ '///<i>Prerequisites: A list compatible with listfunctions</i><br>
+ '///<i>About listfunctions: All listfunctions rely on a special type of
+ '///+ array. This can be string arrays and - in some cases - numeric
+ '///+ arrays. What makes the arrays unique is that the first item which
+ '///+ has the index 0 contains the number of items in the list to be used,
+ '///+ anything that is stored beyond this number is ignored. This has three
+ '///+ consequences: 1) all listfunctions that alter an array must update
+ '///+ the index stored in array(0) and 2) it is possible that the index
+ '///+ point beyond ubound of the array which will most likely cause a
+ '///+ runtime error. 3) Means that arrays may only have an upper boundary
+ '///+ declared, all loops must start with index array(1) and must end with
+ '///+ index array(val( array(0))</i><br><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Target list (string)</li>
+ '///+<li>Source list (string)</li>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Listsize (integer)</li>
+ '///<ul>
+ '///+<li>The size of the sum of both lists</li>
+ '///+<li>0 in case of error</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+ const CFN = "hListAppendList::"
+
+ dim iCurrentItem as integer
+ dim iNewSize as integer
+
+ '///+<li>Do some basic boundary checking</li>
+ if ( ubound( aBaseList() ) < _
+ ( listcount( aBaseList ) + listcount( aListToAppend() ) ) ) then
+ warnlog( CFN & "Base Array too small" )
+ iNewSize = 0
+ else
+
+ '///+<li>Append the list</li>
+ for iCurrentItem = 1 to listcount( aListToAppend() )
+
+ hListAppend( aBaseList() , aListToAppend( iCurrentItem ) )
+
+ next iCurrentItem
+
+ iNewSize = listcount( aBaseList() )
+
+ endif
+ '///</ul>
+
+end function
+
+
+'*******************************************************************************
+
+function hCountMatchesInList( acItemList() as string, cSearchTerm as string ) as integer
+
+
+ '///<h3>Find out how many times a string is found in a list</h3>
+
+ '///<u>Parameter(s):</u><br>
+ '///<ol>
+
+ '///+<li>List to be searched (String)</li>
+ '///<ul>
+ '///+<li>The list may not be empty</li>
+ '///+<li>Search begins at index 1</li>
+ '///</ul>
+
+ '///+<li>Expression to search for (String)</li>
+ '///<ul>
+ '///+<li>Only exact matches are counted</li>
+ '///</ul>
+
+ '///</ol>
+
+
+ '///<u>Returns:</u><br>
+ '///<ol>
+ '///+<li>Number of hits (Integer)</li>
+ '///<ul>
+ '///+<li>0: if no matches were found</li>
+ '///+<li>-1: Any error</li>
+ '///</ul>
+ '///</ol>
+
+ const CFN = "hCountMatchesInList::"
+ printlog( CFN & "Enter" )
+ dim brc as boolean 'a multi purpose boolean returnvalue
+
+ dim iHitCount as integer
+ dim iItemCount as integer
+ dim iCurrentItem as integer
+
+ '///<u>Description:</u>
+ '///<ul>
+ '///+<li>Retrieve the number of items in the list</li>
+ iItemCount = ListCount( acItemList() )
+
+ '///+<li>Walk through the list and count the hits</li>
+ for iCurrentItem = 1 to iItemCount
+
+ if ( cSearchTerm = acItemList( iCurrentItem ) ) then
+ iHitCount = iHitCount + 1
+ endif
+
+ next iCurrentItem
+ '///</ul>
+
+ printlog( CFN & "Exit with result: " & iHitCount )
+
+ hCountMatchesInList() = iHitCount
+
+end function
diff --git a/testautomation/global/tools/includes/optional/t_macro_tools.inc b/testautomation/global/tools/includes/optional/t_macro_tools.inc
new file mode 100755
index 000000000000..45d28b25fbf4
--- /dev/null
+++ b/testautomation/global/tools/includes/optional/t_macro_tools.inc
@@ -0,0 +1,183 @@
+'encoding UTF-8 Do not remove or change this line!
+'**************************************************************************
+'* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+'*
+'* Copyright 2008 by Sun Microsystems, Inc.
+'*
+'* OpenOffice.org - a multi-platform office productivity suite
+'*
+'* $RCSfile: t_macro_tools.inc,v $
+'*
+'* $Revision: 1.1 $
+'*
+'* last change: $Author: jsk $ $Date: 2008-06-20 07:58:44 $
+'*
+'* This file is part of OpenOffice.org.
+'*
+'* OpenOffice.org is free software: you can redistribute it and/or modify
+'* it under the terms of the GNU Lesser General Public License version 3
+'* only, as published by the Free Software Foundation.
+'*
+'* OpenOffice.org is distributed in the hope that it will be useful,
+'* but WITHOUT ANY WARRANTY; without even the implied warranty of
+'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+'* GNU Lesser General Public License version 3 for more details
+'* (a copy is included in the LICENSE file that accompanied this code).
+'*
+'* You should have received a copy of the GNU Lesser General Public License
+'* version 3 along with OpenOffice.org. If not, see
+'* <http://www.openoffice.org/license.html>
+'* for a copy of the LGPLv3 License.
+'*
+'/************************************************************************
+' **
+' ** owner : joerg.skottke@sun.com
+' **
+' ** short description : Helper functions for Macro tests
+' **
+'\******************************************************************************
+
+function hInsertMacroFromFile( cMacroId as string, optional cSource as string ) as integer
+
+ '///<h3>Paste a macro (taken from a file) to the basic IDE</h3>
+ '///<i>uses: framework/tools/input/macros.txt</i><br>
+ '///<i>Starting point: Basic IDE</i><br>
+ '///<u>Note</u>: Overwrites any existing macros in the current module<br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Name (ID) of the macro to be inserted (string)</li>
+ '///<ul>
+ '///+<li>Allowed is any string that corresponds to a section in the source file</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Number of lines inserted (integer)</li>
+ '///<ul>
+ '///+<li>0: Error, no lines inserted</li>
+ '///+<li>&gt; 0: Number of lines</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+ const CFN = "hInsertMacroFromFile::"
+
+ '///+<li>Find the path to the source file</li>
+ dim cFile as string
+
+ '///+<li>Determine the required array size</li>
+ dim iArraySize as integer
+ iArraySize = hListFileGetSize( cFile )
+
+ dim aInstructionList( iArraySize ) as string
+
+ dim iInstructionCount as integer
+ dim iCurrentInstruction as integer
+
+ dim brc as boolean
+
+ if ( IsMissing( cSource ) ) then
+ cFile = convertpath( gTesttoolPath & "global/input/macros.txt" )
+ else
+ cFile = convertpath( cSource )
+ endif
+
+ '///+<li>retrieve the macro from the file with ID as section</li>
+ iInstructionCount = hGetDataFileSection( cFile, _
+ aInstructionList(), _
+ cMacroId, "", "" )
+
+ '///+<li>Delete all content from the BASIC IDE edit window</li>
+ brc = hDeleteMacro()
+
+ '///+<li>Insert the code into the IDE line by line</li>
+ if ( brc ) then
+
+ for iCurrentInstruction = 1 to iInstructionCount
+
+ EditWindow.TypeKeys( "<HOME>" )
+ EditWindow.TypeKeys( aInstructionList( iCurrentInstruction ) )
+ EditWindow.TypeKeys( "<RETURN>" )
+
+ next iCurrentInstruction
+ printlog( CFN & "Inserted macro: " & cMacroId )
+ hInsertMacroFromFile() = iInstructionCount
+
+ else
+
+ printlog( CFN & "IDE is not empty, will not insert macro" )
+ hInsertMacroFromFile() = 0
+
+ endif
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hMacroOrganizerRunMacro( cMacroName as string ) as integer
+
+ '///<h3>Execute a macro by name</h3>
+ '///<i>Starting point: Any document</i><br>
+ '///+<i>The function runs silent</i><br>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Name of the macro to be run (string)</li>
+ '///<ul>
+ '///+<li>Any macro that can run by itself (main)</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Position of the macro in the treelist (integer)</li>
+ '///<ul>
+ '///+<li>0 = error</li>
+ '///+<li>1-n = position of macro</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+ dim irc as integer
+ const CFN = "hMacroOrganizerRunMacro::"
+
+ '///+<li>Go to Tools/Macros/Organize Macros/OpenOffice.org Basic</li>
+ printlog( CFN & "Enter with option: " & cMacroName )
+ ToolsMacro_uno
+
+ '///+<li>Find the Macro</li>
+ kontext "Makro"
+ hExpandAllNodes( MakroAus )
+ irc = hSelectNodeByName( MakroAus , cMacroName )
+ hExpandNode( MakroAus, irc )
+ hSelectNextNode( MakroAus )
+
+ if ( MakroAus.getSelText() = cMacroName ) then
+ printlog( CFN & "Matching object found: " & cMacroName )
+ else
+ irc = 0
+ endif
+
+
+ '///+<li>Run the macro</li>
+ kontext "Makro"
+ if ( Ausfuehren.exists( 1 ) ) then
+ if ( Ausfuehren.isEnabled( 1 ) ) then
+ Ausfuehren.click()
+ else
+ printlog( CFN & "Could not execute macro, button is disabled" )
+ Makro.close()
+ irc = 0
+ endif
+ else
+ printlog( CFN & "Control does not exist/context failed" )
+ Makro.close()
+ irc = 0
+ endif
+
+ hMacroOrganizerRunMacro() = irc
+ printlog( CFN & "Exit with result: " & irc )
+ '///</ul>
+
+end function
diff --git a/testautomation/global/tools/includes/optional/t_security_tools.inc b/testautomation/global/tools/includes/optional/t_security_tools.inc
new file mode 100755
index 000000000000..f4051a265aea
--- /dev/null
+++ b/testautomation/global/tools/includes/optional/t_security_tools.inc
@@ -0,0 +1,670 @@
+'encoding UTF-8 Do not remove or change this line!
+'**************************************************************************
+'* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+'*
+'* Copyright 2008 by Sun Microsystems, Inc.
+'*
+'* OpenOffice.org - a multi-platform office productivity suite
+'*
+'* $RCSfile: t_security_tools.inc,v $
+'*
+'* $Revision: 1.1 $
+'*
+'* last change: $Author: jsk $ $Date: 2008-06-20 07:58:56 $
+'*
+'* This file is part of OpenOffice.org.
+'*
+'* OpenOffice.org is free software: you can redistribute it and/or modify
+'* it under the terms of the GNU Lesser General Public License version 3
+'* only, as published by the Free Software Foundation.
+'*
+'* OpenOffice.org is distributed in the hope that it will be useful,
+'* but WITHOUT ANY WARRANTY; without even the implied warranty of
+'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+'* GNU Lesser General Public License version 3 for more details
+'* (a copy is included in the LICENSE file that accompanied this code).
+'*
+'* You should have received a copy of the GNU Lesser General Public License
+'* version 3 along with OpenOffice.org. If not, see
+'* <http://www.openoffice.org/license.html>
+'* for a copy of the LGPLv3 License.
+'*
+'/************************************************************************
+'*
+'* owner : joerg.skottke@sun.com
+'*
+'* short description : Tools to ease testing of security related funtionality
+'*
+'\******************************************************************************
+
+function hSetPasswordRecommendation( bEnable as boolean ) as boolean
+
+ '///<h3>Toggle Tools/Options/OOo/Security: Password recommendation</h3>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Mode (boolean)</li>
+ '///<ul>
+ '///+<li>TRUE: Switch password recommendation on</li>
+ '///+<li>FALSE: Switch password recommendation off</li>
+ '///</ul>
+ '///</ol>
+
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Prior state (boolean)</li>
+ '///<ul>
+ '///+<li>TRUE: Password recommendation was on</li>
+ '///+<li>FALSE: Password recommendation was off</li>
+ '///</ul>
+ '///</ol>
+
+ '///<u>Description</u>:
+ '///<ul>
+
+ const CFN = "hSetPasswordRecommendation::"
+
+ '///+<li>Open Tools/Options</li>
+ ToolsOptions
+
+ kontext "OptionenDlg"
+ if ( OptionenDlg.exists( 2 ) ) then
+
+ '///+<li>Go to the security page</li>
+ hToolsOptions( "STAROFFICE" , "SECURITY" )
+
+ '///+<li>Click on the &quot;Options...&quot; button</li>
+ kontext "TabSecurity"
+ Options.click()
+
+ kontext "TabSecurityOptionsAndWarnings"
+ if ( TabSecurityOptionsAndWarnings.exists( 1 ) ) then
+
+ '///+<li>Retrieve the current setting for passwor recommendation</li>
+ if ( RecommendPasswordProtectionOnSaving.isChecked() ) then
+ hSetPasswordRecommendation() = true
+ else
+ hSetPasswordRecommendation() = false
+ endif
+
+ '///+<li>Set the requested state</li>
+ if ( bEnable ) then
+ printlog( CFN & "Enabled password recommendation" )
+ RecommendPasswordProtectionOnSaving.check()
+ else
+ printlog( CFN & "Disabled password recommendation" )
+ RecommendPasswordProtectionOnSaving.uncheck()
+ endif
+
+ TabSecurityOptionsAndWarnings.ok()
+ else
+ warnlog( "Failed to open security options page" )
+ endif
+
+ '///+<li>Close Tools/Options</li>
+ Kontext "ToolsOptionsDlg"
+ ToolsOptionsDlg.ok()
+
+ else
+ warnlog( "Failed to open Tools/Options" )
+ endif
+ '///</ul>
+
+end function
+
+'******************************************************************************
+
+function hOpenDigitalSignaturesDialog() as boolean
+
+ '///<h3>Open the Digital Signatures Dialog via File-Menu</h3>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Nothing</li>
+ '///</ol>
+
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Errorcondition (boolean)</li>
+ '///<ul>
+ '///+<li>TRUE: The Digital Signatures Dialog is open</li>
+ '///+<li>FALSE: The Digital Signatures Dialog is not open</li>
+ '///</ul>
+ '///</ol>
+
+ '///<u>Description</u>:
+ '///<ul>
+
+ dim brc as boolean
+ const CFN = "hOpenDigitalSignaturesDialog::"
+
+ '///+<li>Open the file-menu</li>
+ call hUseMenu()
+ call hMenuSelectNr( 1 )
+
+ '///+<li>Select &quot;Digital signatures...&quot;</li>
+ try
+ if ( ucase( gApplication ) = "MATH" ) then
+ call hMenuSelectNr( 14 )
+ else
+ call hMenuSelectNr( 15 )
+ endif
+ catch
+ warnlog( CFN & "Failed to execute menuitem <Digital Signature...>" )
+ endcatch
+
+ ' At this stage either the digital signatures dialog or the messagebox
+ ' <The document needs to be saved> is open. In the latter case the function
+ ' returns false. The possibility that neither of both dialogs are open
+ ' must be handled in the parent function. This means there is no warning
+ ' here either
+
+ '///+<li>Verify that the Digital Signatures dialog is open</li>
+ kontext "DigitalSignature"
+ if ( DigitalSignature.exists() ) then
+ printlog( CFN & "Digital signatures is open" )
+ brc = true
+ else
+ brc = false
+ endif
+
+ '///</ul>
+ hOpenDigitalSignaturesDialog() = brc
+
+end function
+
+'*******************************************************************************
+
+function hAllowMacroExecution() as boolean
+
+ '///<h3>Allow macro execution on Macro Security Warning dialog</h3>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Nothing</li>
+ '///</ol>
+
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Errorcondition (boolean)</li>
+ '///<ul>
+ '///+<li>TRUE: Macro dialog is open, successfully clicked &quot;Run&quot;</li>
+ '///+<li>FALSE: Dialog was not opened</li>
+ '///</ul>
+ '///</ol>
+
+ '///<u>Description</u>:
+ '///<ul>
+
+ const CFN = "hAllowMacroExecution::"
+
+ '///+<li>Verify that the Macro security Warning is displayed</li>
+ kontext "SecurityWarning"
+ if ( SecurityWarning.exists( 5 ) ) then
+
+ '///+<li>Click &quot;Run&quot; to allow macro execution</li>
+ SecurityWarning.ok()
+ hAllowMacroExecution() = true
+ printlog( CFN & "Allowed macro execution" )
+ else
+ hAllowMacroExecution() = false
+ printlog( CFN & "Macro dialog not displayed" )
+ endif
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hDenyMacroExecution() as boolean
+
+ '///<h3>Deny macro execution on Macro Security Warning dialog</h3>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Nothing</li>
+ '///</ol>
+
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Errorcondition (boolean)</li>
+ '///<ul>
+ '///+<li>TRUE: Macro dialog is open, successfully clicked &quot;Deny&quot;</li>
+ '///+<li>FALSE: Dialog was not opened</li>
+ '///</ul>
+ '///</ol>
+
+ '///<u>Description</u>:
+ '///<ul>
+
+ const CFN = "hDenyMacroExecution::"
+
+ '///+<li>Verify that the Macro security Warning is displayed</li>
+ kontext "SecurityWarning"
+ if ( SecurityWarning.exists() ) then
+
+ '///+<li>Click &quot;Cancel&quot; to deny execution</li>
+ SecurityWarning.cancel()
+ hDenyMacroExecution() = true
+ printlog( CFN & "Denied macro execution" )
+ else
+ hDenyMacroExecution() = false
+ printlog( CFN & "Macro dialog not displayed" )
+ endif
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hSwitchMacroSecurityTab( cTab as string )
+
+ '///<h3>Switch between Security Level and Trusted Paths</h3>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>The Tabpage to be activated (string). Valid options are:</li>
+ '///<ul>
+ '///+<li>&quot;SecurityLevel&quot;</li>
+ '///+<li>&quot;TrustedPaths&quot;</li>
+ '///</ul>
+ '///</ol>
+
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Nothing</li>
+ '///</ol>
+
+ '///<u>Description</u>:
+ '///<ul>
+
+ kontext
+
+ '///+<li>Switch to the given Tabpage</li>
+ select case ( lcase( cTab ) )
+ case "securitylevel" : active.setPage TabSecurityLevel
+ case "trustedpaths" : active.setPage TabTrustedSources
+ end select
+
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hAddTrustedPath( cPath as string ) as boolean
+
+ '///<h3>Add a directory to the list of trusted paths</h3>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Fully qualified path to the directory (string)</li>
+ '///</ol>
+
+ '///<u>Return</u>:
+ '///<ol>
+ '///+<li>Errorcondition (boolean)</li>
+ '///<ul>
+ '///+<li>TRUE = Path was successfully added</li>
+ '///+<li>FALSE = Failed to add the path</li>
+ '///</ul>
+ '///</ol>
+
+ const CFN = "hAddTrustedPath::"
+
+ dim iPathCount as integer
+ dim brc as boolean
+
+ '///<u>Description</u>:
+ '///<ul>
+
+ '///+<li>Open Tools/Options</li>
+ ToolsOptions
+
+ '///+<li>Switch to the Security page</li>
+ hToolsOptions( "StarOffice" , "Security" )
+
+ '///+<li>Click Macro Security</li>
+ MacroSecurity.click()
+
+ '///+<li>Switch to the Trusted Paths tab</li>
+ hSwitchMacroSecurityTab( "trustedpaths" )
+ kontext "TabTrustedSources"
+
+ '///+<li>Get the number of currently listed items from the list</li>
+ iPathCount = LocationsListBox.getItemCount()
+
+ '///+<li>Click the &quot;Add&quot; button</li>
+ LocationsAdd.click()
+
+ '///+<li>Enter a path to some files containing macros</li>
+ kontext "OeffnenDlg"
+ DateiName.setText( cPath )
+
+ '///+<li>Click &quot;Select&quot;</li>
+ Oeffnen.click()
+
+ '///+<li>Verify that the item has been added to the list</li>
+ kontext "TabTrustedSources"
+ if ( LocationsListBox.getItemCount() <> ( iPathCount + 1 ) ) then
+ warnlog( CFN & "Incorrect number of items in locations listbox" )
+ brc = false
+ else
+ printlog( CFN & "Added: " & cPath )
+ brc = true
+ endif
+
+ '///+<li>Close the dialog</li>
+ TabTrustedSources.ok()
+
+ '///+<li>Close Tools/Options</li>
+ Kontext "OptionenDlg"
+ OptionenDlg.ok()
+
+ hAddTrustedPath() = brc
+
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hRemoveTrustedPath( cPath as string ) as boolean
+
+ '///<h3>Remove a directory from the list of trusted paths</h3>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Fully qualified path to the directory (string)</li>
+ '///</ol>
+
+ '///<u>Return</u>:
+ '///<ol>
+ '///+<li>Errorcondition (boolean)</li>
+ '///<ul>
+ '///+<li>TRUE = Path was successfully added</li>
+ '///+<li>FALSE = Failed to add the path</li>
+ '///</ul>
+ '///</ol>
+
+ const CFN = "hRemoveTrustedPath()"
+
+ dim iPathCount as integer
+ dim iCurrentPathItem as integer
+
+ dim brc as boolean
+ brc = false
+
+ '///<u>Description</u>:
+ '///<ul>
+
+ '///+<li>Open Tools/Options</li>
+ ToolsOptions
+
+ '///+<li>Switch to the Security page</li>
+ hToolsOptions( "StarOffice" , "Security" )
+
+ '///+<li>Click Macro Security</li>
+ MacroSecurity.click()
+
+ '///+<li>Switch to the Trusted Paths tab</li>
+ hSwitchMacroSecurityTab( "trustedpaths" )
+ kontext "TabTrustedSources"
+
+ '///+<li>Get the number of currently listed items from the list</li>
+ iPathCount = LocationsListBox.getItemCount()
+
+ '///+<li>Find the entry in the list</li>
+ for iCurrentPathItem = 1 to iPathCount
+
+ '///+<li>If it is there, delete it</li>
+ LocationsListBox.select( iCurrentPathItem )
+ if ( LocationsListBox.getSelText() = cPath ) then
+ LocationsRemove.click()
+ printlog( CFN & "Removed item at pos. " & iCurrentPathItem )
+ brc = true
+ exit for
+ endif
+
+ next iCurrentPathItem
+
+ '///+<li>Close the dialog</li>
+ TabTrustedSources.ok()
+
+ '///+<li>Close Tools/Options</li>
+ Kontext "OptionenDlg"
+ OptionenDlg.ok()
+
+ if ( not brc ) then
+ printlog( CFN & "The trusted path was not found in the list" )
+ endif
+
+ hRemoveTrustedPath() = brc
+
+ '///</ul>
+
+end function
+
+
+'*******************************************************************************
+
+function hSecurityEnterPasswordOnSave( cPassword as string ) as boolean
+
+
+ '///<h3>Enter password when saving a document</h3>
+ '///<i>This function enters a password into the password dialog if the &quot;
+ '///+ Save with password&quot; checkbox is checked. It will automatically
+ '///+ generate a faulty password to be entered on first try (to see whether
+ '///+ the &quot;Invalid password confirmation&quot; dialog pops up, on second
+ '///+ attempt the password is confirmed correctly and thus the document should
+ '///+ save ok. The office should return to the document, the File Save dialog
+ '///+ should close after save.</i><br><br>
+
+ '///<u>Parameter(s):</u><br>
+ '///<ol>
+
+ '///+<li>Password to use (String)</li>
+ '///<ul>
+ '///+<li>Password should contain strange characters and glyphs if possible</li>
+ '///</ul>
+
+ '///</ol>
+
+
+ '///<u>Returns:</u><br>
+ '///<ol>
+ '///+<li>Errorcondition (Boolean)</li>
+ '///<ul>
+ '///+<li>TRUE if all went well</li>
+ '///+<li>FALSE on any error</li>
+ '///</ul>
+ '///</ol>
+
+ const CFN = "hSecurityEnterPasswordOnSave::"
+ printlog( CFN & "Enter" )
+ dim brc as boolean 'a multi purpose boolean returnvalue
+ brc = true
+
+ '///<u>Description:</u>
+ '///<ul>
+ '///+<li>Verify that the password dialog is present</li>
+ kontext "PasswordDlg"
+ if ( PasswordDlg.exists( 2 ) ) then
+
+ printlog( CFN & "Password dialog is displayed" )
+
+ '///+<li>Enter the password</li>
+ Password.setText( cPassword )
+
+ '///+<li>Confirm with incorrect password (e.g. append a number at random)</li>
+ PasswordConfirm.setText( cPassword & "1" )
+
+ '///+<li>Click on OK</li>
+ PasswordDlg.ok()
+
+ '///+<li>There should be a warning about a faulty password confirmation</li>
+ kontext "Active"
+ if ( Active.exists( 1 ) ) then
+ printlog( CFN & "Message: " & Active.getText() )
+
+ '///+<li>Close messagebox with OK</li>
+ Active.OK()
+ else
+ qaerrorlog( CFN & "Warning about faulty password confirmation is missing" )
+ brc = false
+ endif
+
+ '///+<li>We should now be back on the password dialog</li>
+ kontext "PasswordDlg"
+ if ( PasswordDlg.exists( 2 ) ) then
+
+ printlog( CFN & "Password dialog is displayed" )
+
+ '///+<li>Enter the password</li>
+ Password.setText( cPassword )
+
+ '///+<li>Confirm with correct password</li>
+ PasswordConfirm.setText( cPassword )
+
+ '///+<li>Click on OK</li>
+ PasswordDlg.ok()
+
+ else
+
+ qaerrorlog( CFN & "The password dialog is missing after confirmation error" )
+ brc = false
+
+ endif
+
+ else
+
+ qaerrorlog( CFN & "The password dialog did not open" )
+ brc = false
+
+ endif
+
+ '///+<li>Verify that the &quot;File Save&quot; dialog is closed after saving</li>
+ kontext "SpeichernDlg"
+ if ( SpeichernDlg.exists() ) then
+ qaerrorlog( CFN & "File Save dialog is open, cancelling." )
+ SpeichernDlg.cancel()
+ brc = false
+ endif
+ '///</ul>
+
+ printlog( CFN & "Exit with result: " & brc )
+ hSecurityEnterPasswordOnSave() = brc
+
+end function
+
+
+'*******************************************************************************
+
+function hSecurityEnterPasswordOnLoad( cPassword as string, bValid as boolean ) as boolean
+
+ use "global\tools\includes\optional\t_stringtools.inc"
+
+ '///<h3>Enter a password while loading a document</h3>
+ '///<i>Enters a valid or invalid password while loading a passworded file</i><br><br>
+
+ '///<u>Parameter(s):</u><br>
+ '///<ol>
+
+ '///+<li>Password (String)</li>
+ '///<ul>
+ '///+<li>The password should contain special characters and glyphs</li>
+ '///</ul>
+
+ '///+<li>Password validity (Boolean)</li>
+ '///<ul>
+ '///+<li>TRUE: The password is correct, the document should load</li>
+ '///+<li>FALSE: The password is incorrect, the document should not load</li>
+ '///</ul>
+
+ '///</ol>
+
+
+ '///<u>Returns:</u><br>
+ '///<ol>
+ '///+<li>Errorcondition (Boolean)</li>
+ '///<ul>
+ '///+<li>TRUE if the password protection worked as expected</li>
+ '///+<li>FALSE on any error</li>
+ '///</ul>
+ '///</ol>
+
+ const CFN = "hSecurityEnterPasswordOnLoad::"
+ printlog( CFN & "Enter with option (Password): " & cPassword )
+ printlog( CFN & "Enter with option (Validity): " & bValid )
+ dim brc as boolean 'a multi purpose boolean returnvalue
+ brc = true
+ dim cMsg as string
+
+ '///<u>Description:</u>
+ '///<ul>
+ '///+<li>Verify that the password dialog exists</li>
+ kontext "PasswordFileOpen"
+ if ( PasswordFileOpen.exists( 3 ) ) then
+
+ '///+<li>Enter password, click OK</li>
+ PasswortName.setText( cPassword )
+ PasswordFileOpen.ok()
+
+ '///+<li>If the password was incorrect:</li>
+ '///<ul>
+ if ( not bValid ) then
+
+ '///+<li>Look for a warning message</li>
+ kontext "Active"
+ if ( Active.exists( 1 ) ) then
+
+ cMsg = Active.getText()
+ cMsg = hRemoveLineBreaks( cMsg )
+ if ( bValid ) then
+ warnlog( CFN & "Message: " & cMsg )
+ else
+ printlog( CFN & "Message: " & cMsg )
+ endif
+
+ '///+<li>Close the messagebox</li>
+ Active.ok()
+
+ '///+<li>Close the Password dialog with &quot;Cancel&quot;</li>
+ kontext "PasswordFileOpen"
+ if ( PasswordFileopen.exists( 2 ) ) then
+
+ PasswordFileOpen.cancel()
+
+ else
+
+ qaerrorlog( CFN & "Password dialog is not present" )
+ brc = false
+
+ endif
+ else
+
+ qaerrorlog( CFN & "Warning about incorrect password is missing" )
+ brc = false
+
+ endif
+
+ else
+
+ kontext "Active"
+ if ( Active.exists( 1 ) ) then
+
+ cMsg = Active.getText()
+ cMsg = hRemoveLIneBreaks( cMsg )
+ qaerrorlog( CFN & "Unexpected messagebox: " & cMsg )
+ brc = false
+
+ endif
+
+ endif
+ '///</ul>
+
+ else
+
+ qaerrorlog( CFN & "Password dialog is missing" )
+ brc = false
+
+ endif
+ '///</ul>
+
+ printlog( CFN & "Exit with result:" & brc )
+ hSecurityEnterPasswordOnLoad() = brc
+
+end function
diff --git a/testautomation/global/tools/includes/optional/t_stringtools.inc b/testautomation/global/tools/includes/optional/t_stringtools.inc
new file mode 100755
index 000000000000..d4d435222489
--- /dev/null
+++ b/testautomation/global/tools/includes/optional/t_stringtools.inc
@@ -0,0 +1,359 @@
+'encoding UTF-8 Do not remove or change this line!
+'**************************************************************************
+'* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+'*
+'* Copyright 2008 by Sun Microsystems, Inc.
+'*
+'* OpenOffice.org - a multi-platform office productivity suite
+'*
+'* $RCSfile: t_stringtools.inc,v $
+'*
+'* $Revision: 1.1 $
+'*
+'* last change: $Author: jsk $ $Date: 2008-06-20 07:59:14 $
+'*
+'* This file is part of OpenOffice.org.
+'*
+'* OpenOffice.org is free software: you can redistribute it and/or modify
+'* it under the terms of the GNU Lesser General Public License version 3
+'* only, as published by the Free Software Foundation.
+'*
+'* OpenOffice.org is distributed in the hope that it will be useful,
+'* but WITHOUT ANY WARRANTY; without even the implied warranty of
+'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+'* GNU Lesser General Public License version 3 for more details
+'* (a copy is included in the LICENSE file that accompanied this code).
+'*
+'* You should have received a copy of the GNU Lesser General Public License
+'* version 3 along with OpenOffice.org. If not, see
+'* <http://www.openoffice.org/license.html>
+'* for a copy of the LGPLv3 License.
+'*
+'/************************************************************************
+'*
+'* owner : joerg.skottke@sun.com
+'*
+'* short description : Functions for manipulation of strings
+'*
+'\******************************************************************************
+
+function hRemoveLineBreaks( cString as string ) as string
+
+ '///<h3>Remove linebreaks and tabs from a string</h3>
+ '///<i>Used to &quot;beautify&quot; content of messageboxes when printed to the log</i><br><br>
+ '///<u>Parameter(s):</u>
+ '///<ol>
+ '///+<li>Content of a messagebox as captured with .getText() (string)</li>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>A string without tabs, linebreaks and linefeed (string)</li>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+ '///+<li>Walk through the string, replace linebreaks, tabs etc. with spaces</li>
+
+ ' Function (undocumented) to remove LF and CR from strings.
+ ' When a messagebox appears with multiple lines of text this usually
+ ' breaks the output of the printlog into multiple lines making it
+ ' hard to read. So this function puts the entire text in one line.
+
+ dim iCharPos as integer
+ dim cCurrentChar as string
+ dim cNewString as string
+
+ ' walk through the string character by character and replace those
+ ' characters that break the line. Tabs and linebreaks become spaces
+ for iCharPos = 1 to len( cString )
+
+ cCurrentChar = mid( cString , iCharPos , 1 )
+
+ select case cCurrentChar
+ case CHR$(13) : cNewString = cNewString & " " ' replace linebreak
+ case CHR$(10) : ' Simply ignore linefeed
+ case CHR$(09) : cNewString = cNewString & " " ' replace tab with space
+ case else : cNewString = cNewString & cCurrentChar ' append char
+ end select
+
+ next iCharPos
+
+ hRemoveLineBreaks() = cNewString
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hCompareSubStrings( cRef as string, cSub as string ) as integer
+
+ '///<h3>Find substring in a reference string</h3>
+ '///<i>Used to determine that we are on &quot;The first doc!&quot;</i><br><br>
+ '///<u>Parameter(s):</u>
+ '///<ol>
+ '///+<li>Term to search for (string)</li>
+ '///+<li>Term to be searched (string)</li>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Errorcode (integer)</li>
+ '///<ul>
+ '///+<li>-1: Invalid parameter(s)</li>
+ '///+<li>0: Strings do not match</li>
+ '///+<li>1: Term is exact match</li>
+ '///+<li>2: Term is a substring</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+ const CFN = "hCompareSubStrings::"
+
+ '///+<li>Test function parameters</li>
+ if ( ( cRef = "" ) or ( cSub = "" ) ) then
+ warnlog( CFN & "invalid parameter(s): Empty string passed." )
+ hCompareSubStrings() = -1
+ exit function
+ endif
+
+ dim irc as integer
+
+ '///+<li>Test if we have a substring</li>
+ if ( instr( cRef, cSub ) > 0 ) then
+ irc = 2
+ else
+ irc = 0
+ endif
+
+ '///+<li>Test if we have an exact match</li>
+ if ( irc = 2 ) then
+ if ( ( cRef = cSub ) and ( len( cRef ) = len( cSub ) ) ) then
+ irc = 1
+ endif
+ endif
+
+ select case irc
+ case 0 : printlog( CFN & "No matching substring found" )
+ case 1 : printlog( CFN & "Strings are identical" )
+ case 2 : printlog( CFN & "String is substring" )
+ end select
+
+ hCompareSubStrings() = irc
+ '///</ul>
+
+end function
+
+'******************************************************************************
+
+function hGetDirTreeLevel( cFullPath as string ) as integer
+
+ '///<h3>Count the numbers of pathseparators in a path-string</h3>
+ '///<i>Used to find the level of current directory within the directory tree.<br>
+ '///+The function prints a warning when no pathseparators were found</i><br><br>
+ '///<u>Parameter(s):</u>
+ '///<ol>
+ '///+<li>Path (string) with <b>no trailing pathseparator</b></li>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Number of Pathseparators within the string (integer)</li>
+ '///<ul>
+ '///+<li>0 = failure</li>
+ '///+<li>&gt; 0 = level</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+ const CFN = "hGetDirTreeLevel::"
+
+ dim iCurrentChar as integer
+ dim cCurrentChar as string
+ dim iSeparatorCount as integer
+ iSeparatorCount = 0
+
+ '///+<li>Walk through the string</li>
+ '///<ul>
+ for iCurrentChar = 1 to len( cFullPath )
+
+ '///+<li>Get the next character</li>
+ cCurrentChar = mid( cFullPath , iCurrentChar , 1 )
+
+ '///+<li>If it is a separtator, increase the counter</li>
+ if ( cCurrentChar = gPathSigne ) then
+ iSeparatorCount = iSeparatorCount + 1
+ endif
+
+ next iCurrentChar
+ '///</ul>
+
+ '///+<li>Print a warning if no separators were found</li>
+ if ( iSeparatorCount = 0 ) then
+ warnlog( CFN & "Did not find any separators in given string: " & cFullPath )
+ endif
+ '///</ul>
+
+ hGetDirTreeLevel() = iSeparatorCount
+
+end function
+
+
+'*******************************************************************************
+
+function hGetStringFromStaticTextField( oControl as object ) as string
+
+ use "global\tools\includes\optional\t_accels.inc"
+
+ '///<h3>Get the string from a static textfield</h3>
+
+ '///<i>Static textfields like those in the document properties dialog are
+ '///+ in certain places designed in a way that the string can be selected
+ '///+ and copied to the clipboard. This has been introduced with SRC680m212
+ '///+ (9156). This function uses keyboard shortcuts for &quot;Select All&quot;
+ '///+ and &quot;Copy&quot; to get the string into the clipboard as .uno.Copy
+ '///+ is not enabled.</i><br><br>
+
+ '///<u>Parameter(s):</u><br>
+ '///<ol>
+
+ '///+<li>Name of the control (Object)</li>
+ '///<ul>
+ '///+<li>The object must exist in the current context</li>
+ '///</ul>
+
+ '///</ol>
+
+
+ '///<u>Returns:</u><br>
+ '///<ol>
+ '///+<li>Content of the field (String)</li>
+ '///<ul>
+ '///+<li>Blank if string is empty</li>
+ '///</ul>
+ '///</ol>
+
+ const CFN = "hGetStringFromStaticTextField::"
+ dim brc as boolean 'a multi purpose boolean returnvalue
+
+ dim cSelectAll as string
+ dim cCopy as string
+ dim cText as string
+
+ printlog( CFN & "Enter" )
+
+ '///<u>Description:</u>
+ '///<ul>
+ '///+<li>Verify that the object exists</li>
+ '///+<li>Get the accelerator for SelectAll and Copy</li>
+ '///+<li>Execute SelectAll and Copy on control</li>
+ '///+<li>Get the string from the clipboard</li>
+ if ( oControl.exists() ) then
+ if ( oControl.isVisible() ) then
+ cSelectAll = hGetAccel( "SelectAll" )
+ cCopy = hGetAccel( "Copy" )
+
+ oControl.typeKeys( "<right>" )
+ oControl.typeKeys( cSelectAll )
+ oControl.typeKeys( cCopy )
+
+ cText = getClipboardText()
+ printlog( CFN & "Exit with result: " & cText )
+ else
+ ctext = ""
+ qaerrorlog( CFN & "Exit: Control exists but is not visible" )
+ endif
+ else
+ cText = ""
+ qaerrorlog( CFN & "Exit: Control does not exist in this context" )
+ endif
+
+ '///</ul>
+
+ hGetStringFromStaticTextField() = cText
+
+end function
+
+
+'*******************************************************************************
+
+function hConvertStringToLong( cValue as string ) as long
+
+
+ '///<h3>Convert a stringvalue to long int</h3>
+
+ '///<i>The purpose of this function is to isolate the filesize from a string
+ '///+ of the type &quot;1.345 Bytes&quot; by removing the thousands-separator
+ '///+ and the trailing unit. The result is then a filesize as long integer
+ '///+ which then can be compared to the result from the BASIC function
+ '///+ FileLen( FileSpec )</i><br><br>
+
+ '///<u>Parameter(s):</u><br>
+ '///<ol>
+
+ '///+<li>String containing a long integer value (String)</li>
+ '///<ul>
+ '///+<li>No floating point values allowed</li>
+ '///+<li>Numeric value must be at the beginning of the string (no leading characters/spaces)</li>
+ '///+<li>Negative values are allowed</li>
+ '///+<li>Leading &quot;+&quot; is not allowed</li>
+ '///</ul>
+
+ '///</ol>
+
+
+ '///<u>Returns:</u><br>
+ '///<ol>
+ '///+<li>Value of the string as long integer (Long)</li>
+ '///<ul>
+ '///+<li>Thousands separator (. or ,) have been removed</li>
+ '///+<li>Decimal separators (though not allowed) have been removed</li>
+ '///</ul>
+ '///</ol>
+
+ const CFN = "hConvertStringToLong::"
+ printlog( CFN & "Enter with option: " & cValue )
+ dim brc as boolean 'a multi purpose boolean returnvalue
+
+ dim iLen as integer
+ iLen = len( cValue )
+
+ dim iChar as integer
+ dim cChar as string
+
+ dim cStringValue as string
+ cStringValue = ""
+
+ '///<u>Description:</u>
+ '///<ul>
+ '///+<li>Walk through the single chars of the string</li>
+ '///<ul>
+ for iChar = 1 to iLen
+
+ '///+<li>Get the current character</li>
+ cChar = mid( cValue , iChar , 1 )
+
+ '///+<li>Copy valid characters to temporary string, drop invalid, exit on first space or other character</li>
+ select case cChar
+ case "-" : cStringValue = cStringValue & cChar
+ case "1" : cStringValue = cStringValue & cChar
+ case "2" : cStringValue = cStringValue & cChar
+ case "3" : cStringValue = cStringValue & cChar
+ case "4" : cStringValue = cStringValue & cChar
+ case "5" : cStringValue = cStringValue & cChar
+ case "6" : cStringValue = cStringValue & cChar
+ case "7" : cStringValue = cStringValue & cChar
+ case "8" : cStringValue = cStringValue & cChar
+ case "9" : cStringValue = cStringValue & cChar
+ case "0" : cStringValue = cStringValue & cChar
+ case else: ' do nothing
+ end select
+
+ next iChar
+ '///</ul>
+
+ printlog( CFN & "Exit with value: " & cStringValue )
+
+ '///+<li>Convert string to long integer and return to calling function</li>
+ hConvertStringToLong() = val( cStringValue )
+ '///</ul>
+
+end function
diff --git a/testautomation/global/tools/includes/optional/t_treelist_tools.inc b/testautomation/global/tools/includes/optional/t_treelist_tools.inc
new file mode 100755
index 000000000000..a55036239a3d
--- /dev/null
+++ b/testautomation/global/tools/includes/optional/t_treelist_tools.inc
@@ -0,0 +1,509 @@
+'encoding UTF-8 Do not remove or change this line!
+'**************************************************************************
+'* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+'*
+'* Copyright 2008 by Sun Microsystems, Inc.
+'*
+'* OpenOffice.org - a multi-platform office productivity suite
+'*
+'* $RCSfile: t_treelist_tools.inc,v $
+'*
+'* $Revision: 1.1 $
+'*
+'* last change: $Author: jsk $ $Date: 2008-06-20 07:59:34 $
+'*
+'* This file is part of OpenOffice.org.
+'*
+'* OpenOffice.org is free software: you can redistribute it and/or modify
+'* it under the terms of the GNU Lesser General Public License version 3
+'* only, as published by the Free Software Foundation.
+'*
+'* OpenOffice.org is distributed in the hope that it will be useful,
+'* but WITHOUT ANY WARRANTY; without even the implied warranty of
+'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+'* GNU Lesser General Public License version 3 for more details
+'* (a copy is included in the LICENSE file that accompanied this code).
+'*
+'* You should have received a copy of the GNU Lesser General Public License
+'* version 3 along with OpenOffice.org. If not, see
+'* <http://www.openoffice.org/license.html>
+'* for a copy of the LGPLv3 License.
+'*
+'/************************************************************************
+'*
+'* owner : joerg.skottke@sun.com
+'*
+'* short description : Helpers for accessing treelists
+'*
+'\******************************************************************************
+
+private const DEBUG_ENABLE = false
+
+function hGetNodeCount( oControl as object ) as integer
+
+ '///<h3>Retrieve the number of visible (open) nodes from a treelist</h3>
+ '///<u>Input</u>:
+ '///<ol>
+ '///+<li>Treelist control object (Object)</li>
+ '///<ul>
+ '///+<li>Object must exist in current context</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Returns</u>:
+ '///<ol>
+ '///+<li>Number of items in treelist</li>
+ '///<ul>
+ '///+<li>0 on any error</li>
+ '///+<li>&gt; 0 Number of items</li>
+ '///</ul>
+ '///</ol>
+ '///<u>Description</u>:
+ '///<ul>
+
+
+ const CFN = "hGetNodeCount::"
+ dim iCount as integer
+
+ '///+<li>Verify that the control exists</li>
+ if ( oControl.exists( 5 ) ) then
+
+ '///+<li>Verify that the control is enabled</li>
+ if ( oControl.isEnabled() ) then
+
+ if ( DEBUG_ENABLE ) then
+ printlog( CFN & "Regular access, control available and enabled" )
+ endif
+
+ '///+<li>get the number of items from the control</li>
+ iCount = oControl.getItemCount()
+ else
+ printlog( CFN & "Failure: Control claims to be disabled." )
+ iCount = 0
+ endif
+ else
+ try
+ printlog( CFN & "Forcing access to non existing control" )
+ iCount = oControl.getItemCount()
+ catch
+ printlog( CFN & "Failure: Control not available." )
+ iCount = 0
+ endcatch
+ endif
+ if ( DEBUG_ENABLE ) then
+ printlog( CFN & "Exit with nodecount = " & iCount )
+ endif
+ hGetNodeCount = iCount
+ '///</ul>
+
+end function
+
+'*******************************************************************************
+
+function hSelectTopNode( oControl as object ) as boolean
+
+ '///<h3>Move selection to the first node in a treelist</h3>
+ '///<ul>
+ '///+<li>Type the &quot;Home&quot;-key in a treelist, to select index 1</li>
+ '///+<li>Verify that the top node has been selected</li>
+ '///</ul>
+
+ const CFN = "hSelectTopNode::"
+
+ try
+ oControl.select( 1 )
+ WaitSlot()
+ hSelectTopNode() = true
+ catch
+ hSelectTopNode() = false
+ endcatch
+
+ if ( DEBUG_ENABLE ) then
+ printlog( CFN & "Selected Node: " & oControl.getText() )
+ endif
+
+end function
+
+'*******************************************************************************
+
+function hSelectNextNode( oControl as object ) as integer
+
+ '///<h3>Move one node down in a treelist</h3>
+ '///<ul>
+ '///+<li>Returns new position or 0 on error</li>
+ '///</ul>
+
+ const CFN = "hSelectNextNode::"
+
+ dim iPosBefore as integer
+ dim iPosAfter as integer
+
+ iPosBefore = oControl.getSelIndex()
+
+ oControl.typeKeys( "<DOWN>" )
+
+ iPosAfter = oControl.getSelIndex()
+
+ if ( iPosAfter = iPosBefore ) then
+ hSelectNextNode() = 0
+ endif
+
+ if ( iPosAfter = ( iPosBefore + 1 ) ) then
+ hSelectnextNode() = iPosAfter
+ endif
+
+ printlog( CFN & "Selected node: " & oControl.getText() )
+
+end function
+
+'*******************************************************************************
+
+function hGetNodeName( oControl as object , iNode as integer ) as string
+
+ '///<h3>Retrieve the name of a node in a treelist specified by index</h3>
+ '///<ul>
+ '///+<li>Returns the name of the node or empty string on error</li>
+ '///</ul>
+ const CFN = "hGetNodeName::"
+ dim iItemCount as integer
+
+ iItemCount = hGetNodeCount( oControl )
+ if ( iNode > iItemCount ) then
+ warnlog( CFN & "Selected node out of range, aborting" )
+ hGetNodeName() = ""
+ else
+ oControl.select( iNode )
+ hGetNodeName() = oControl.getSelText()
+ endif
+
+end function
+
+'*******************************************************************************
+
+function hExpandNode( oControl as object, iNode as integer ) as integer
+
+ '///<h3>Expand a node in a treelist specified by index</h3>
+ '///<ul>
+ '///+<li>Returns new nodecount or 0 on error</li>
+ '///</ul>
+
+ const CFN = "hExpandNode::"
+
+ dim iOldNodeCount as integer
+
+ if ( DEBUG_ENABLE ) then
+ printlog( CFN & "Enter with option (Control): " & oControl.name() )
+ printlog( CFN & "Enter with option (iNode): " & iNode )
+ endif
+
+ iOldNodeCount = hGetNodeCount( oControl )
+ if ( iNode <= iOldNodeCount ) then
+ if ( iNode > 0 ) then
+ oControl.select( iNode )
+ endif
+ try
+ oControl.typekeys( "<RIGHT>" )
+ hExpandNode() = hGetNodeCount( oControl )
+ catch
+ warnlog( "#i84194# Treelist access failed (Keyboard navigation)" )
+ hExpandNode() = 0
+ endcatch
+ else
+ hExpandNode() = 0
+ endif
+
+end function
+
+'*******************************************************************************
+
+function hExpandAllNodes( oControl as object ) as integer
+
+ '///<h3>Expand all nodes of treelist</h3>
+ '///<ul>
+ '///+<li>Run through all items in the treelist, expand every node</li>
+ '///+<li>Returns the number of all nodes in the treelist</li>
+ '///</ul>
+
+ dim iNode as integer
+ dim iNodeCurCount as integer
+ dim iNodeRefCount as integer
+ dim iIteration as integer
+
+ const CFN = "hExpandAllNodes::"
+
+ hSelectTopNode( oControl )
+ iNodeCurCount = hGetNodeCount( oControl )
+ iNodeRefCount = -1
+ iIteration = 0
+
+ if ( DEBUG_ENABLE ) then
+ printlog( CFN & "Initial iNodeCurCount: " & iNodeCurCount )
+ printlog( CFN & "Initial iNodeRefCount: " & iNodeRefCount )
+ endif
+
+ do while ( iNodeRefCount < iNodeCurCount )
+
+ iIteration = iIteration + 1
+ iNodeRefCount = iNodeCurCount
+
+ for iNode = iNodeCurCount to 1 step -1
+ hExpandNode( oControl , iNode )
+ next iNode
+
+ iNodeCurCount = hGetNodeCount( oControl )
+
+ if ( DEBUG_ENABLE ) then
+ printlog( "" )
+ printlog( CFN & "Exit iteration....: " & iIteration )
+ printlog( CFN & "Exit iNodeCurCount: " & iNodeCurCount )
+ printlog( CFN & "Exit iNodeRefCount: " & iNodeRefCount )
+ endif
+
+ loop
+
+ if ( DEBUG_ENABLE ) then
+ printlog( CFN & "Exit with " & iNodeCurCount & _
+ " items after " & iIteration & " iterations" )
+ endif
+ hExpandAllNodes() = iNodeCurCount
+
+end function
+
+'*******************************************************************************
+
+function hGetVisibleNodeNames( oControl as object , lsList() as string ) as integer
+
+ '///<h3>Retrieve the names of all nodes in a treelist</h3>
+ '///<ul>
+ '///+<li>Expand all nodes of a treelist</li>
+ '///+<li>Store all node names into an array</li>
+ '///+<li>Return the number of nodes read (listcount), 0 on error</li>
+ '///</ul>
+
+ ' Get the list of all visible (expanded) nodes and store it
+ ' in lsList(). if _id > ubound lsList() an error is given and lsList remains
+ ' empty, thus returning "0"
+
+ const CFN = "hGetVisibleNodeNames::"
+
+ dim iNodeCount as integer
+ dim iThisNode as integer
+
+ printlog( CFN & "Enter" )
+
+ iNodeCount = hGetNodeCount( oControl )
+
+ ' Test whether the array provided is large enough to hold all items
+ ' from the treelist/list. If the array is ok fill it.
+ if ( iNodeCount > ubound( lsList() ) ) then
+ warnlog( "Array to small to hold: " & iNodeCount & " items" )
+ else
+ hSelectTopNode( oControl )
+ for iThisNode = 1 to iNodeCount
+ listappend( lsList() , hGetNodeName( oControl , iThisNode )
+ next iThisNode
+ endif
+
+ hGetVisibleNodeNames() = listcount( lsList() )
+ printlog( CFN & "Exit" )
+
+end function
+
+'*******************************************************************************
+
+function hSelectNode( oControl as object , _id as integer ) as string
+
+ '///<h3>Select a node in a treelist by index</h3>
+ '///<ul>
+ '///+<li>Return the name of the selected node</li>
+ '///</ul>
+
+ oControl.select( _id ) : hSelectNode() = hGetNodeName( oControl , _id )
+
+end function
+
+'*******************************************************************************
+
+function hSelectNodeByName( oControl as object , _name as string ) as integer
+
+ '///<h3>Select a node by name in treelist (first occurrence)</h3>
+ '///<ul>
+ '///+<li>Try to find a node by name - directly</li>
+ '///+<li>If the node is not visible, expand all and search the tree</li>
+ '///+<li>Returns index of requested node or 0 on failure</li>
+ '///</ul>
+
+ const CFN = "hSelectNodeByName::"
+
+ dim iThisNode as integer
+ dim iCurrentNode as integer
+ dim iNodeCount as integer
+
+ dim cNodeName as string
+
+ printlog( CFN & "Enter with option (NodeName): " & _name )
+
+ iThisNode = 0
+
+ ' First we try to jump to the node directly, if this fails we use the
+ ' slower but safer method (expand all nodes and step through)
+ try
+ oControl.select( _name )
+ iThisNode = oControl.getSelIndex()
+ hSelectNodeByName() = iThisNode
+ catch
+ printlog( CFN & "Node not visible: Using search method" )
+ iNodeCount = hExpandAllNodes( oControl )
+
+ for iCurrentNode = 1 to iNodeCount
+ oControl.select( iCurrentNode )
+ cNodeName = oControl.getSelText()
+
+ if ( cNodeName = _name ) then
+ iThisNode = iCurrentNode
+ exit for
+ endif
+ next iCurrentNode
+ endcatch
+
+ if ( iThisNode = 0 ) then
+ printlog( CFN & "Exit: Node not found." )
+ else
+ printlog( CFN & "Exit: Node selected at pos: " & iThisNode )
+ endif
+
+ hSelectNodeByName() = iThisNode
+
+end function
+
+'*******************************************************************************
+
+function hSelectTheLastNode( oControl as object ) as integer
+
+ '///<h3>Select the (absolute) last node in a treelist</h3>
+ '///<ul>
+ '///+<li>Expand all nodes</li>
+ '///+<li>Go to the last node, select it</li>
+ '///+<li>Return the number of the last node in the treelist</li>
+ '///</ul>
+
+ const CFN = "hSelectTheLastNode::"
+ dim iCurrentNodeCount as integer
+
+ printlog( CFN & "Enter with option (control): " & oControl.name() )
+
+ iCurrentNodeCount = -1
+
+ do while( iCurrentNodeCount < hGetNodeCount( oControl ) )
+
+ iCurrentNodeCount = hGetNodeCount( oControl )
+ hExpandNode( oControl, iCurrentNodeCount )
+
+ if ( DEBUG_ENABLE ) then
+ printlog( CFN & "Nodename.....: " & oControl.getText() )
+ printlog( CFN & "Node position: " & iCurrentNodeCount )
+ endif
+
+ loop
+
+ printlog( CFN & "Exit with result: " & iCurrentNodeCount )
+ hSelectTheLastNode() = iCurrentNodeCount
+
+end function
+
+'*******************************************************************************
+
+function hVerifyNodeName( oControl as object , cName as string ) as boolean
+
+ '///<h3>Compare the name of the current node from a treelist to a reference string</h3>
+ '///<ul>
+ '///+<li>Returns true on success, false on failure</li>
+ '///</ul>
+
+ hVerifyNodeName() = false
+ if ( oControl.getSelText() = cName ) then hVerifyNodeName() = true
+
+end function
+
+'*******************************************************************************
+
+function hWaitForTreelist( oTreeList as object, cContext as string, iItemCount as integer ) as boolean
+
+ '///<h3>Wait for a treelist to get populated (java related delay)</h3>
+ '///<b>IMPORTANT: Do not use unless absolutely necessary</b>
+ '///+<p>Retrieve the number of items from the treelist until a specified
+ '///+ number has been reached.</p>
+
+ const CFN = "hWaitForTreelist::"
+ dim iTry as integer
+ dim iObjects as integer
+ dim brc as boolean
+
+ brc = false
+ iTry = 0
+
+ kontext cContext
+
+ qaerrorlog( CFN & "Stupid function, do not use" )
+
+ iObjects = 0
+ do while ( iObjects < iItemCount )
+
+ iTry = iTry + 1
+ iObjects = hGetNodeCount( oTreeList )
+
+ if ( iObjects >= iItemCount ) then
+ brc = true
+ exit do
+ endif
+
+ ' Failsafe mechanism
+ if ( iTry = 10 ) then
+ qaerrorlog( CFN & "Requested number of items never reached" )
+ brc = false
+ exit do
+ endif
+
+ loop
+
+ hWaitForTreelist() = brc
+
+end function
+
+'******************************************************************************
+
+function hGetListItems( oControl as object, aList() as string ) as integer
+
+ '///<h3>Retrieve the names of all nodes from a plain (linear) list</h3>
+ '///<ul>
+ '///+<li>Cycle through a list, append all entries to an array</li>
+ '///+<li>Returns number of items or 0 on error</li>
+ '///</ul>
+
+ const CFN = "hGetListItems::"
+
+ printlog( CFN & "Enter with option (control): " & oControl.name() )
+
+ dim iItemCount as integer
+ dim iCurrentItem as integer
+ dim cCurrentItem as string
+
+ iItemCount = oControl.getItemCount()
+ if ( iItemCount > ubound( aList() ) ) then
+ printlog( CFN & "Array too small, needed: " & iItemCount )
+ hGetListItems() = 0
+ exit function
+ endif
+
+ for iCurrentItem = 1 to iItemCount
+
+ oControl.select( iCurrentItem )
+ cCurrentItem = oControl.getSelText()
+ hListAppend( cCurrentItem, aList() )
+
+ next iCurrentItem
+
+ printlog( CFN & "Exit with number of items: " & iItemCount )
+ hGetListItems() = iItemCount
+
+end function
+