forked from nvaccess/nvda
-
Notifications
You must be signed in to change notification settings - Fork 0
/
NotepadLib.py
136 lines (119 loc) · 4.52 KB
/
NotepadLib.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# A part of NonVisual Desktop Access (NVDA)
# 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.plaintext
""" This module provides the NotepadLib Robot Framework Library which allows system tests to start
Windows Notepad with a text sample and assert NVDA interacts with it in the expected way.
"""
# imported methods start with underscore (_) so they don't get imported into robot files as keywords
from os.path import join as _pJoin
import tempfile as _tempfile
from typing import Optional as _Optional
from SystemTestSpy import (
_blockUntilConditionMet,
_getLib,
)
from SystemTestSpy.windows import (
GetForegroundWindowTitle,
GetVisibleWindowTitles,
SetForegroundWindow,
)
import re
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 AssertsLib import AssertsLib as _AssertsLib
import NvdaLib as _NvdaLib
builtIn: BuiltIn = BuiltIn()
opSys: _OpSysLib = _getLib('OperatingSystem')
process: _ProcessLib = _getLib('Process')
assertsLib: _AssertsLib = _getLib('AssertsLib')
# In Robot libraries, class name must match the name of the module. Use caps for both.
class NotepadLib:
_testFileStagingPath = _tempfile.mkdtemp()
_testCaseTitle = "test"
def __init__(self):
self.notepadHandle: _Optional[int] = None
@staticmethod
def _getTestCasePath(filename):
return _pJoin(NotepadLib._testFileStagingPath, filename)
def exit_notepad(self):
spy = _NvdaLib.getSpyLib()
spy.emulateKeyPress('alt+f4')
process.wait_for_process(self.notepadHandle, timeout="1 minute", on_timeout="continue")
def start_notepad(self, filePath):
builtIn.log(f"starting notepad: {filePath}")
self.notepadHandle = process.start_process(
"start notepad"
f' "{filePath}"',
shell=True,
alias='NotepadAlias',
)
process.process_should_be_running(self.notepadHandle)
return self.notepadHandle
@staticmethod
def getUniqueTestCaseTitle(testCase: str) -> str:
return f"{NotepadLib._testCaseTitle} ({abs(hash(testCase))}).txt"
@staticmethod
def getUniqueTestCaseTitleRegex(testCase: str) -> re.Pattern:
return re.compile(f"^{NotepadLib._testCaseTitle} \\({abs(hash(testCase))}\\)")
@staticmethod
def _writeTestFile(testCase) -> str:
"""
Creates a file for a plaintext test case.
@param testCase: The plaintext sample that is to be tested.
@return: path to the plaintext file.
"""
filePath = NotepadLib._getTestCasePath(NotepadLib.getUniqueTestCaseTitle(testCase))
with open(file=filePath, mode='w', encoding='UTF-8') as f:
f.write(testCase)
return filePath
def _focusNotepad(self, startsWithTestCaseTitle: re.Pattern):
""" Ensure Notepad started and is focused.
"""
success, _success = _blockUntilConditionMet(
getValue=lambda: SetForegroundWindow(startsWithTestCaseTitle, builtIn.log),
giveUpAfterSeconds=3,
intervalBetweenSeconds=0.5
)
if success:
return
windowInformation = ""
try:
windowInformation = f"Foreground Window: {GetForegroundWindowTitle()}.\n"
windowInformation += f"Open Windows: {GetVisibleWindowTitles()}"
except OSError as e:
builtIn.log(f"Couldn't retrieve active window information.\nException: {e}")
raise AssertionError(
"Unable to focus Notepad.\n"
f"{windowInformation}"
)
def prepareNotepad(self, testCase: str) -> None:
"""
Starts Notepad opening a file containing the plaintext sample.
Different versions of notepad/windows have variations in how the title is presented.
This may mean that there is a file extension in the title.
E.G. "test.txt - Notepad" or "test – Notepad".
@param testCase - The plaintext sample to test.
"""
spy = _NvdaLib.getSpyLib()
path = self._writeTestFile(testCase)
spy.wait_for_speech_to_finish()
self.start_notepad(path)
self._focusNotepad(NotepadLib.getUniqueTestCaseTitleRegex(testCase))
# Move to the start of file
spy.emulateKeyPress('home')
spy.wait_for_speech_to_finish()
@staticmethod
def getSpeechAfterKey(key) -> str:
"""Ensure speech has stopped, press key, and get speech until it stops.
@return: The speech after key press.
"""
spy = _NvdaLib.getSpyLib()
spy.wait_for_speech_to_finish()
nextSpeechIndex = spy.get_next_speech_index()
spy.emulateKeyPress(key)
spy.wait_for_speech_to_finish(speechStartedIndex=nextSpeechIndex)
speech = spy.get_speech_at_index_until_now(nextSpeechIndex)
return speech