def getSpyLib(): """ Gets the spy library instance. This has been augmented with methods for all supported keywords. Requires NvdaLib and nvdaSpy (remote library - see speechSpyGlobalPlugin) to be initialised. On failure check order of keywords in Robot log and NVDA log for failures. @rtype: SystemTestSpy.speechSpyGlobalPlugin.NVDASpyLib @return: Remote NVDA spy Robot Framework library. """ nvdaLib = _getLib("NvdaLib") spy = nvdaLib.nvdaSpy if spy is None: raise AssertionError("Spy not yet available, check order of keywords and NVDA log for errors.") return spy
from robotremoteserver import ( test_remote_server as _testRemoteServer, stop_remote_server as _stopRemoteServer, ) from SystemTestSpy import (_blockUntilConditionMet, _getLib, _nvdaSpyAlias, configManager) # Imported for type information from robot.libraries.BuiltIn import BuiltIn from robot.libraries.OperatingSystem import OperatingSystem as _OpSysLib from robot.libraries.Process import Process as _Process from robot.libraries.Remote import Remote as _Remote builtIn: BuiltIn = BuiltIn() opSys: _OpSysLib = _getLib('OperatingSystem') process: _Process = _getLib('Process') class _NvdaLocationData: def __init__(self): # robot is expected to be run from the NVDA repo root directory. We want all repo specific # paths to be relative to this. This would allow us to change where it is run from if we decided to. self.repoRoot = _abspath("./") self.stagingDir = _tempFile.gettempdir() opSys.directory_should_exist(self.stagingDir) self.whichNVDA = builtIn.get_variable_value("${whichNVDA}", "source") self._installFilePath = builtIn.get_variable_value( "${installDir}", None) self.NVDAInstallerCommandline = None
from os.path import join as _pJoin import tempfile as _tempfile from typing import Optional as _Optional from SystemTestSpy import ( _getLib, ) from robot.libraries.BuiltIn import BuiltIn # Imported for type information from robot.libraries.OperatingSystem import OperatingSystem as _OpSysLib from robot.libraries.Process import Process as _ProcessLib from KeyInputLib import KeyInputLib as _KeyInputLib from AssertsLib import AssertsLib as _AssertsLib import NvdaLib as _NvdaLib builtIn: BuiltIn = BuiltIn() opSys: _OpSysLib = _getLib('OperatingSystem') process: _ProcessLib = _getLib('Process') keyInputLib: _KeyInputLib = _getLib('KeyInputLib') assertsLib: _AssertsLib = _getLib('AssertsLib') # In Robot libraries, class name must match the name of the module. Use caps for both. class ChromeLib: _testFileStagingPath = _tempfile.mkdtemp() def __init__(self): self.chromeHandle: _Optional[int] = None @staticmethod def _getTestCasePath(filename): return _pJoin(ChromeLib._testFileStagingPath, filename)
"""Logic for NVDA + Google Chrome tests """ import os from robot.libraries.BuiltIn import BuiltIn # imported methods start with underscore (_) so they don't get imported into robot files as keywords from SystemTestSpy import ( _getLib, ) # Imported for type information from ChromeLib import ChromeLib as _ChromeLib from AssertsLib import AssertsLib as _AssertsLib import NvdaLib as _NvdaLib _builtIn: BuiltIn = BuiltIn() _chrome: _ChromeLib = _getLib("ChromeLib") _asserts: _AssertsLib = _getLib("AssertsLib") ARIAExamplesDir = os.path.join(_NvdaLib._locations.repoRoot, "include", "w3c-aria-practices", "examples") def checkbox_labelled_by_inner_element(): _chrome.prepareChrome(r""" <div tabindex="0" role="checkbox" aria-labelledby="inner-label"> <div style="display:inline" id="inner-label"> Simulate evil cat </div> </div> """) actualSpeech = _chrome.getSpeechAfterTab()
# Copyright (C) 2021 NV Access Limited # This file may be used under the terms of the GNU General Public License, version 2 or later. # For more details see: https://www.gnu.org/licenses/gpl-2.0.html """Logic for reading text using NVDA in the notepad text editor. """ # imported methods start with underscore (_) so they don't get imported into robot files as keywords from SystemTestSpy import ( _getLib, ) # Imported for type information from NotepadLib import NotepadLib as _NotepadLib from AssertsLib import AssertsLib as _AssertsLib _notepad: _NotepadLib = _getLib("NotepadLib") _asserts: _AssertsLib = _getLib("AssertsLib") # unlike other symbols used, symbols.dic doesn't preserve quote symbols with SYMPRES_ALWAYS _wordsToExpectedSymbolLevelAllSpeech = { 'Say': 'Say', '(quietly)': 'left paren(quietly right paren)', '"Hello,': 'quote Hello comma,', 'Jim".': 'Jim quote dot.', } _wordsToExpectedSymbolLevelDefaultSpeech = { 'Say': 'Say', '(quietly)': '(quietly)', '"Hello,': 'Hello,', 'Jim".': 'Jim .',
_getLib, _blockUntilConditionMet, ) from SystemTestSpy.windows import waitUntilWindowFocused # Imported for type information from robot.libraries.Process import Process as _ProcessLib from robot.libraries.OperatingSystem import OperatingSystem as _OpSysLib from AssertsLib import AssertsLib as _AssertsLib import NvdaLib as _nvdaLib from NvdaLib import NvdaLib as _nvdaRobotLib _nvdaProcessAlias = _nvdaRobotLib.nvdaProcessAlias _nvdaRobot: _nvdaRobotLib = _getLib("NvdaLib") _opSys: _OpSysLib = _getLib('OperatingSystem') _builtIn: BuiltIn = BuiltIn() _process: _ProcessLib = _getLib("Process") _asserts: _AssertsLib = _getLib("AssertsLib") def NVDA_Starts(): """ Test that NVDA can start""" _process.process_should_be_running(_nvdaProcessAlias) def quits_from_menu(showExitDialog=True): """Ensure NVDA can be quit from menu.""" spy = _nvdaLib.getSpyLib() _builtIn.sleep(1)
def test_tableHeaders(): """Test symbol substitution for secondary content / context provided in addition to primary content. For example, table headers are spoken when moving between cells. The table headers are not the primary content (based on review / caret location), but supplement the information for the cell. The behaviour is currently questionable, when the contextual content (table headers) contain symbols, should the symbols be substituted according to: - the same rules as the primary content ie influenced by degree of movement, - the global symbol level be used, - some other specific symbol level (None, the default (some)) https://github.com/nvaccess/nvda/pull/12710#issuecomment-1031277294 """ _chrome: _ChromeLib = _getLib("ChromeLib") _chrome.prepareChrome( r""" <table> <tr> <th>First-name</th> <th>➔ 👕</th> <th>Don't</th> </tr> <tr> <td>a</td> <td>b</td> <td>c</td> </tr> </table> """ ) _setSymbolLevel(SymLevel.ALL) # Expected to be in browse mode actualSpeech = _chrome.getSpeechAfterKey("downArrow") _asserts.strings_match( actualSpeech, # into the table, describe first column header ' '.join([ "table", # enter table context "with 2 rows and 3 columns", # details of the table context "row 1", # enter row 1 context "column 1", # enter column 1 context "First dash name", # the contents of the cell ]) ) actualSpeech = _chrome.getSpeechAfterKey("downArrow") _asserts.strings_match( actualSpeech, # describe second column header ' '.join([ "column 2", # enter column 2 context, still in row 1, still in table "right-pointing arrow t-shirt", # the contents of the cell ]) ) actualSpeech = _chrome.getSpeechAfterKey("downArrow") _asserts.strings_match( actualSpeech, # describe third column header ' '.join([ "column 3", # enter column 3 context, still in row 1, still in table "Don tick t", # the contents of the cell ]) ) # into the first (non-header) row actualSpeech = _chrome.getSpeechAfterKey("downArrow") _asserts.strings_match( actualSpeech, # describe third column header ' '.join([ "row 2", # enter row 2 context, still in table "First dash name", # reminder of the column name "column 1", # explicit column 2 context, "a", # the contents of the cell ]) ) _doTest( navKey=Move.CARET_CHAR, symbolLevel=SymLevel.NONE, reportedAfterLast=EndSpeech.NONE, expectedSpeech=[ # name of column, column number, \n cell contents 't-shirt column 2\nb', # note symbols NOT replaced in column name "Don't column 3\nc", # note symbols NOT replaced in column name ] ) # reset to start of row. _NvdaLib.getSpeechAfterKey(Move.CARET_CHAR_BACK.value) _NvdaLib.getSpeechAfterKey(Move.CARET_CHAR_BACK.value) _doTest( navKey=Move.CARET_CHAR, symbolLevel=SymLevel.ALL, reportedAfterLast=EndSpeech.NONE, expectedSpeech=[ # name of column, column number 2, \n cell contents 'right-pointing arrow t-shirt column 2\nb', # note symbols ARE replaced in column name "Don tick t column 3\nc", # note symbols ARE replaced in column name ] )
# imported methods start with underscore (_) so they don't get imported into robot files as keywords from SystemTestSpy import ( _getLib, ) # Imported for type information from robot.libraries.Process import Process as _ProcessLib from AssertsLib import AssertsLib as _AssertsLib import NvdaLib as _nvdaLib from NvdaLib import NvdaLib as _nvdaRobotLib _nvdaProcessAlias = _nvdaRobotLib.nvdaProcessAlias _builtIn: BuiltIn = BuiltIn() _process: _ProcessLib = _getLib("Process") _asserts: _AssertsLib = _getLib("AssertsLib") def NVDA_Starts(): """ Test that NVDA can start""" _process.process_should_be_running(_nvdaProcessAlias) def quits_from_keyboard(): """Ensure NVDA can be quit from keyboard.""" spy = _nvdaLib.getSpyLib() spy.wait_for_specific_speech("Welcome to NVDA") # ensure the dialog is present. spy.wait_for_speech_to_finish() _builtIn.sleep(1) # the dialog is not always receiving the enter keypress, wait a little longer for it spy.emulateKeyPress("enter")
# relative import not used for 'systemTestUtils' because the folder is added to the path for 'libraries' # imported methods start with underscore (_) so they don't get imported into robot files as keywords from SystemTestSpy import ( _getLib, ) # Imported for type information from robot.libraries.Process import Process as _ProcessLib from KeyInputLib import KeyInputLib as _KeyInputLib from AssertsLib import AssertsLib as _AssertsLib import NvdaLib as _nvdaLib from NvdaLib import NvdaLib as _nvdaRobotLib _nvdaProcessAlias = _nvdaRobotLib.nvdaProcessAlias _builtIn: BuiltIn = BuiltIn() _process: _ProcessLib = _getLib("Process") _keyInputs: _KeyInputLib = _getLib("KeyInputLib") _asserts: _AssertsLib = _getLib("AssertsLib") def NVDA_Starts(): """ Test that NVDA can start""" _process.process_should_be_running(_nvdaProcessAlias) def quits_from_keyboard(): """Ensure NVDA can be quit from keyboard.""" spy = _nvdaLib.getSpyLib() spy.wait_for_specific_speech( "Welcome to NVDA") # ensure the dialog is present. spy.wait_for_speech_to_finish()