diff options
author | Joerg Skottke <jsk@openoffice.org> | 2008-06-20 06:59:34 +0000 |
---|---|---|
committer | Joerg Skottke <jsk@openoffice.org> | 2008-06-20 06:59:34 +0000 |
commit | 7ecf6630c2b195ba14743d27deb19367ac303a0e (patch) | |
tree | 33bb2bd0c5d73bbb12098272f4589f5f81180255 /testautomation/global/tools/includes/optional | |
parent | 3bb16f65ef1e228b17569210353b97f26095c7c5 (diff) |
Add files that fit into the naming scheme
Diffstat (limited to 'testautomation/global/tools/includes/optional')
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>"FileOpen"</li> + '///+<li>"FileSave"</li> + '///+<li>"Print"</li> + '///+<li>"SelectAll"</li> + '///+<li>"Copy"</li> + '///+<li>"DocumentConverter_ShowLog"</li> + '///+<li>"IDE_SWITCH_TAB+"</li> + '///+<li>"IDE_SWITCH_TAB-"</li> + '///</ul> + '///</ol> + '///<u>Returns</u>: + '///<ol> + '///+<li>Accelerator (string)</li> + '///<ul> + '///+<li>A string ready to use by .typeKeys(...) method</li> + '///+<li>"Error" 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 "Rename". 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 ≤ present number of tabs</li> + '///+<li>If Index > 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 "Rename"</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 "New..." 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>"Changed <Documenttype>"</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>"<SHIFT HOME>"</li> + '///+<li>"<MOD1 A>"</li> + '///+<li>"<MOD2 Q>"</li> + '///+<li>"Hello"</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 "OK"</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 "YES"</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, + '///+ "InstallForAll,BrokenDeps,DenyUpdate" )</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>> 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 "Add.." button is available</li> + if ( add.exists() and add.isEnabled() ) then + + '///+<li>Click the "Add..." button</li> + add.click() + else + printlog( CFN & "Add button is missing or disabled" ) + hExtensionAddGUI() = -2 + exit function + endif + + '///+<li>Test for the dreaded "The office workdirectory does not exist" 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>> 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>> 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 (> 0 and ≤ 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 "OptionsListe"</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 "$(user)"-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 "Work"</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 & "[project]\input\[dir]"</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. "680", from environment)</li> + '///+<li>ProducName (e.g "OpenOffice.org", 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 "KEY"-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 "KEY"-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 "KEY"-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 "KEY"-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 "KEY"-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 "KEY"-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 "KEY"-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 "KEY"-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 "KEY"-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 > 0 and ≤ 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)) > 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 "MyString" the items will be changed to + '///+ read "Some Text : MyString"</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>> 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 "Options..." 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 "Digital signatures..."</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 "Run"</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 "Run" 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 "Deny"</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 "Cancel" 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>"SecurityLevel"</li> + '///+<li>"TrustedPaths"</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 "Add" button</li> + LocationsAdd.click() + + '///+<li>Enter a path to some files containing macros</li> + kontext "OeffnenDlg" + DateiName.setText( cPath ) + + '///+<li>Click "Select"</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 " + '///+ Save with password" checkbox is checked. It will automatically + '///+ generate a faulty password to be entered on first try (to see whether + '///+ the "Invalid password confirmation" 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 "File Save" 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 "Cancel"</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 "beautify" 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 "The first doc!"</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>> 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 "Select All" + '///+ and "Copy" 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 "1.345 Bytes" 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 "+" 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>> 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 "Home"-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 + |