Skip to content

Commit 4b3d75f

Browse files
authored
Merge df3f8e7 into 5ce7545
2 parents 5ce7545 + df3f8e7 commit 4b3d75f

9 files changed

Lines changed: 97 additions & 7 deletions

File tree

source/braille.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@
221221
controlTypes.STATE_SORTED_ASCENDING: _("sorted asc"),
222222
# Translators: Displayed in braille when an object is sorted descending.
223223
controlTypes.STATE_SORTED_DESCENDING: _("sorted desc"),
224+
# Translators: Displayed in braille when an object has additional details (such as a comment section).
225+
controlTypes.STATE_HAS_ARIA_DETAILS: _("details"),
224226
# Translators: Displayed in braille when an object (usually a graphic) has a long description.
225227
controlTypes.STATE_HASLONGDESC: _("ldesc"),
226228
# Translators: Displayed in braille when there is a formula on a spreadsheet cell.

source/browseMode.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,22 @@ def script_activateLongDesc(self,gesture):
13981398
# Translators: the description for the activateLongDescription script on browseMode documents.
13991399
script_activateLongDesc.__doc__=_("Shows the long description at this position if one is found.")
14001400

1401+
def script_activateAriaDetailsSummary(self, gesture):
1402+
info = self.makeTextInfo(textInfos.POSITION_CARET)
1403+
info.expand("character")
1404+
for field in reversed(info.getTextWithFields()):
1405+
if isinstance(field, textInfos.FieldCommand) and field.command == "controlStart":
1406+
states = field.field.get('states')
1407+
if states and controlTypes.STATE_HAS_ARIA_DETAILS in states:
1408+
ui.message(field.field['detailsSummary'])
1409+
return
1410+
1411+
# Translators: the message presented when the activateAriaDetailsSummary script cannot locate a
1412+
# set of details to read.
1413+
ui.message(_("No additional details"))
1414+
# Translators: the description for the activateAriaDetailsSummary script on browseMode documents.
1415+
script_activateAriaDetailsSummary.__doc__ = _("Shows a summary of the details at this position if found.")
1416+
14011417
def event_caretMovementFailed(self, obj, nextHandler, gesture=None):
14021418
if not self.passThrough or not gesture or not config.conf["virtualBuffers"]["autoPassThroughOnCaretMove"]:
14031419
return nextHandler()

source/controlTypes.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@
203203
STATE_CROPPED=0x8000000000
204204
STATE_OVERFLOWING=0x10000000000
205205
STATE_UNLOCKED=0x20000000000
206+
STATE_HAS_ARIA_DETAILS = 0x40000000000
206207

207208
roleLabels: Dict[int, str] = {
208209
# Translators: The word for an unknown control type.
@@ -573,6 +574,8 @@
573574
STATE_SORTED_DESCENDING:_("sorted descending"),
574575
# Translators: a state that denotes that an object (usually a graphic) has a long description.
575576
STATE_HASLONGDESC:_("has long description"),
577+
# Translators: a state that denotes that an object has additional details (such as a comment section).
578+
STATE_HAS_ARIA_DETAILS: _("has details"),
576579
# Translators: a state that denotes that an object is pinned in its current location
577580
STATE_PINNED:_("pinned"),
578581
# Translators: a state that denotes the existance of a formula on a spreadsheet cell

source/virtualBuffers/gecko_ia2.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ def _normalizeControlField(self,attrs):
7575
# This is a text leaf.
7676
# See NVDAObjects.Iaccessible.mozilla.findOverlayClasses for an explanation of these checks.
7777
role = controlTypes.ROLE_STATICTEXT
78+
if attrs.get("detailsSummary") is not None:
79+
states.add(controlTypes.STATE_HAS_ARIA_DETAILS)
7880
if attrs.get("IAccessibleAction_showlongdesc") is not None:
7981
states.add(controlTypes.STATE_HASLONGDESC)
8082
if "IAccessibleAction_click" in attrs:

tests/system/libraries/NvdaLib.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,12 @@ def _createTestIdFileName(name):
114114
return outputFileName
115115

116116
@staticmethod
117-
def setup_nvda_profile(configFileName):
117+
def setup_nvda_profile(configFileName, gesturesFileName: Optional[str] = None):
118118
configManager.setupProfile(
119119
_locations.repoRoot,
120120
configFileName,
121-
_locations.stagingDir
121+
_locations.stagingDir,
122+
gesturesFileName,
122123
)
123124

124125
@staticmethod
@@ -247,9 +248,9 @@ def start_NVDAInstaller(self, settingsFileName):
247248
self.nvdaSpy.wait_for_NVDA_startup_to_complete()
248249
return nvdaProcessHandle
249250

250-
def start_NVDA(self, settingsFileName):
251+
def start_NVDA(self, settingsFileName: str, gesturesFileName: Optional[str] = None):
251252
builtIn.log(f"Starting NVDA with config: {settingsFileName}")
252-
self.setup_nvda_profile(settingsFileName)
253+
self.setup_nvda_profile(settingsFileName, gesturesFileName)
253254
nvdaProcessHandle = self._startNVDAProcess()
254255
process.process_should_be_running(nvdaProcessHandle)
255256
self._connectToRemoteServer()

tests/system/libraries/SystemTestSpy/configManager.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from os.path import join as _pJoin
1212
from .getLib import _getLib
1313
import sys
14-
14+
from typing import Optional
1515

1616
# Imported for type information
1717
from robot.libraries.BuiltIn import BuiltIn
@@ -91,13 +91,24 @@ def _copyPythonLibs(pythonImports, libsDest):
9191
opSys.copy_file(libSource, libsDest)
9292

9393

94-
def setupProfile(repoRoot: str, settingsFileName: str, stagingDir: str):
94+
def setupProfile(
95+
repoRoot: str,
96+
settingsFileName: str,
97+
stagingDir: str,
98+
gesturesFileName: Optional[str] = None,
99+
):
95100
builtIn.log("Copying files into NVDA profile", level='DEBUG')
96101
opSys.copy_file(
97102
# Despite duplication, specify full paths for clarity.
98103
_pJoin(repoRoot, "tests", "system", "nvdaSettingsFiles", settingsFileName),
99104
_pJoin(stagingDir, "nvdaProfile", "nvda.ini")
100105
)
106+
if gesturesFileName is not None:
107+
opSys.copy_file(
108+
# Despite duplication, specify full paths for clarity.
109+
_pJoin(repoRoot, "tests", "system", "nvdaSettingsFiles", gesturesFileName),
110+
_pJoin(stagingDir, "nvdaProfile", "gestures.ini")
111+
)
101112
# create a package to use as the globalPlugin
102113
_installSystemTestSpyToScratchPad(
103114
repoRoot,
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[browseMode.BrowseModeDocumentTreeInterceptor]
2+
activateAriaDetailsSummary = kb:nvda+\

tests/system/robot/chromeTests.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,55 @@ def checkbox_labelled_by_inner_element():
4848
)
4949

5050

51+
def test_aria_details():
52+
_chrome.prepareChrome(
53+
"""
54+
<div>
55+
<p>The word <mark aria-details="cat-details">cat</mark> has a comment tied to it.</p>
56+
<div id="cat-details" role="comment">
57+
Cats go woof BTW<br>&mdash;Jonathon Commentor
58+
<div role="comment">
59+
No they don't<br>&mdash;Zara
60+
</div>
61+
<div role="form">
62+
<textarea cols="80" placeholder="Add reply..."></textarea>
63+
<input type="submit">
64+
</div>
65+
</div>
66+
</div>
67+
"""
68+
)
69+
actualSpeech = _chrome.getSpeechAfterKey('downArrow')
70+
_asserts.strings_match(
71+
actualSpeech,
72+
"The word marked content cat out of marked content has a comment tied to it."
73+
)
74+
# this word has no details attached
75+
actualSpeech = _chrome.getSpeechAfterKey("control+rightArrow")
76+
_asserts.strings_match(
77+
actualSpeech,
78+
"word"
79+
)
80+
# check that there is no summary reported
81+
actualSpeech = _chrome.getSpeechAfterKey("NVDA+\\")
82+
_asserts.strings_match(
83+
actualSpeech,
84+
"No additional details"
85+
)
86+
# this word has details attached to it
87+
actualSpeech = _chrome.getSpeechAfterKey("control+rightArrow")
88+
_asserts.strings_match(
89+
actualSpeech,
90+
"marked content cat out of marked content"
91+
)
92+
# read the details summary
93+
actualSpeech = _chrome.getSpeechAfterKey("NVDA+\\")
94+
_asserts.strings_match(
95+
actualSpeech,
96+
"Cats go woof BTW —Jonathon Commentor No they don't —Zara"
97+
)
98+
99+
51100
def announce_list_item_when_moving_by_word_or_character():
52101
_chrome.prepareChrome(
53102
r"""

tests/system/robot/chromeTests.robot

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ default teardown
2323
quit NVDA
2424
2525
default setup
26-
start NVDA standard-dontShowWelcomeDialog.ini
26+
start NVDA standard-dontShowWelcomeDialog.ini chrome-gestures.ini
2727
2828
*** Test Cases ***
2929
@@ -50,6 +50,10 @@ ARIA checkbox
5050
[Documentation] Navigate to an unchecked checkbox in reading mode.
5151
[Tags] aria-at
5252
test_ariaCheckbox_browseMode
53+
ARIA details
54+
[Documentation] Ensure a summary of aria-details is read on command.
55+
[Tags] annotations
56+
test aria details
5357
i12147
5458
[Documentation] New focus target should be announced if the triggering element is removed when activated
5559
test_i12147

0 commit comments

Comments
 (0)