[orca] More work on flat review



commit f5b1f521befc2c0a33f664daee48e98bcf031782
Author: Joanmarie Diggs <jdiggs igalia com>
Date:   Tue Aug 30 23:32:32 2016 -0400

    More work on flat review
    
    * Clean up some text-related code
    * Fix more instances of stale content

 src/orca/flat_review.py                            |  381 ++++++++------------
 .../firefox/flat_review_text_by_word_and_char.py   |   10 +-
 .../gnome-clocks/stop_watch_flat_review.py         |   35 +-
 test/keystrokes/gnome-clocks/timer_flat_review.py  |   60 +--
 test/keystrokes/gtk-demo/role_menu_flat_review.py  |   26 +-
 .../gtk-demo/role_text_multiline_flat_review.py    |   27 +-
 .../gtk3-demo/role_dialog_flat_review.py           |    2 +-
 .../keystrokes/gtk3-demo/role_table_flat_review.py |    6 +-
 .../gtk3-demo/role_text_multiline_flat_review.py   |   27 +-
 .../gtk3-demo/role_toggle_button_flat_review.py    |   16 +-
 test/keystrokes/oowriter/flat_review_word.py       |   19 +-
 11 files changed, 255 insertions(+), 354 deletions(-)
---
diff --git a/src/orca/flat_review.py b/src/orca/flat_review.py
index 3f779c7..eb991c6 100644
--- a/src/orca/flat_review.py
+++ b/src/orca/flat_review.py
@@ -37,176 +37,145 @@ from . import messages
 from . import orca_state
 from . import settings
 
-# [[[WDW - HACK Regular expression to split strings on whitespace
-# boundaries, which is what we'll use for word dividers instead of
-# living at the whim of whomever decided to implement the AT-SPI
-# interfaces for their toolkit or app.]]]
-#
-whitespace_re = re.compile(r'(\s+)', re.DOTALL | re.IGNORECASE | re.M)
-
 EMBEDDED_OBJECT_CHARACTER = '\ufffc'
 
 class Char:
-    """Represents a single char of an Accessibility_Text object."""
+    """A character's worth of presentable information."""
 
-    def __init__(self,
-                 word,
-                 index,
-                 string,
-                 x, y, width, height):
+    def __init__(self, word, index, startOffset, string, x, y, width, height):
         """Creates a new char.
 
         Arguments:
         - word: the Word instance this belongs to
-        - index: the index of this char in the word
+        - startOffset: the start offset with respect to the accessible
         - string: the actual char
         - x, y, width, height: the extents of this Char on the screen
         """
 
         self.word = word
-        self.string = string
         self.index = index
+        self.startOffset = startOffset
+        self.endOffset = startOffset + 1
+        self.string = string
         self.x = x
         self.y = y
         self.width = width
         self.height = height
 
+
 class Word:
-    """Represents a single word of an Accessibility_Text object, or
-    the entire name of an Image or Component if the associated object
-    does not implement the Accessibility_Text interface.  As a rule of
-    thumb, all words derived from an Accessibility_Text interface will
-    start with the word and will end with all chars up to the
-    beginning of the next word.  That is, whitespace and punctuation
-    will usually be tacked on to the end of words."""
+    """A single chunk (word or object) of presentable information."""
 
-    def __init__(self,
-                 zone,
-                 index,
-                 startOffset,
-                 string,
-                 x, y, width, height):
+    def __init__(self, zone, index, startOffset, string, x, y, width, height):
         """Creates a new Word.
 
         Arguments:
         - zone: the Zone instance this belongs to
-        - index: the index of this word in the Zone
+        - index: the index of this Word in the Zone
+        - startOffset: the start offset with respect to the accessible
         - string: the actual string
-        - x, y, width, height: the extents of this Char on the screen"""
+        - x, y, width, height: the extents of this Word on the screen
+        """
 
         self.zone = zone
         self.index = index
         self.startOffset = startOffset
         self.string = string
         self.length = len(string)
+        self.endOffset = self.startOffset + len(string)
         self.x = x
         self.y = y
         self.width = width
         self.height = height
+        self.chars = []
 
-    def __getattr__(self, attr):
-        """Used for lazily determining the chars of a word.  We do
-        this to reduce the total number of round trip calls to the app,
-        and to also spread the round trip calls out over the lifetime
-        of a flat review context.
+    def __getattribute__(self, attr):
+        if attr != "chars":
+            return super().__getattribute__(attr)
 
-        Arguments:
-        - attr: a string indicating the attribute name to retrieve
+        try:
+            text = self.zone.accessible.queryText()
+        except:
+            return []
 
-        Returns the value of the given attribute.
-        """
+        chars = []
+        for i, char in enumerate(self.string):
+            start = i + self.startOffset
+            extents = text.getRangeExtents(start, start+1, pyatspi.DESKTOP_COORDS)
+            chars.append(Char(self, i, start, char, *extents))
 
-        if attr == "chars":
-            if isinstance(self.zone, TextZone):
-                text = self.zone.accessible.queryText()
+        return chars
+
+    def getRelativeOffset(self, offset):
+        """Returns the char offset with respect to this word or -1."""
+
+        if self.startOffset <= offset < self.startOffset + len(self.string):
+            return offset - self.startOffset
+
+        return -1
 
-                # Pylint is confused and flags this warning:
-                #
-                # W0201:132:Word.__getattr__: Attribute 'chars' defined 
-                # outside __init__
-                #
-                # So for now, we just disable this error in this method.
-                #
-                # pylint: disable-msg=W0201
-
-                self.chars = []
-
-                i = 0
-                while i < self.length:
-                    [char, startOffset, endOffset] = text.getTextAtOffset(
-                        self.startOffset + i,
-                        pyatspi.TEXT_BOUNDARY_CHAR)
-                    [x, y, width, height] = text.getRangeExtents(
-                        startOffset,
-                        startOffset + 1,
-                        0)
-                    self.chars.append(Char(self,
-                                           i,
-                                           char,
-                                           x, y, width, height))
-                    i += 1
-            else:
-                self.chars = None
-            return self.chars
-        elif attr.startswith('__') and attr.endswith('__'):
-            raise AttributeError(attr)
-        else:
-            return self.__dict__[attr]
 
 class Zone:
     """Represents text that is a portion of a single horizontal line."""
 
-    def __init__(self,
-                 accessible,
-                 string,
-                 x, y,
-                 width, height,
-                 role=None):
-        """Creates a new Zone, which is a horizontal region of text.
+    WORDS_RE = re.compile("(\S+\s*)", re.UNICODE)
+
+    def __init__(self, accessible, string, x, y, width, height, role=None):
+        """Creates a new Zone.
 
         Arguments:
         - accessible: the Accessible associated with this Zone
         - string: the string being displayed for this Zone
         - extents: x, y, width, height in screen coordinates
-        - role: Role to override accesible's role.
+        - role: Role to override accessible's role.
         """
 
         self.accessible = accessible
-        self.string = string
+        self.startOffset = 0
+        self._string = string
         self.length = len(string)
         self.x = x
         self.y = y
         self.width = width
         self.height = height
         self.role = role or accessible.getRole()
+        self._words = []
 
-    def __getattr__(self, attr):
-        """Used for lazily determining the words in a Zone.
+    def __getattribute__(self, attr):
+        """To ensure we update the content."""
 
-        Arguments:
-        - attr: a string indicating the attribute name to retrieve
+        if attr not in ["words", "string"]:
+            return super().__getattribute__(attr)
 
-        Returns the value of the given attribute.
-        """
+        if attr == "string":
+            return self._string
 
-        if attr == "words":
+        if not self._shouldFakeText():
+            return self._words
 
-            # Pylint is confused and flags this warning:
-            #
-            # W0201:203:Zone.__getattr__: Attribute 'words' defined 
-            # outside __init__
-            #
-            # So for now, we just disable this error in this method.
-            #
-            # pylint: disable-msg=W0201
+        # TODO - JD: For now, don't fake character and word extents.
+        # The main goal is to improve reviewability.
+        extents = self.x, self.y, self.width, self.height
 
-            self.words = []
+        words = []
+        for i, word in enumerate(re.finditer(self.WORDS_RE, self._string)):
+            words.append(Word(self, i, word.start(), word.group(), *extents))
 
-            return self.words
-        elif attr.startswith('__') and attr.endswith('__'):
-            raise AttributeError(attr)
-        else:
-            return self.__dict__[attr]
+        self._words = words
+        return words
+
+    def _shouldFakeText(self):
+        """Returns True if we should try to fake the text interface"""
+
+        textRoles = [pyatspi.ROLE_LABEL,
+                     pyatspi.ROLE_MENU,
+                     pyatspi.ROLE_MENU_ITEM,
+                     pyatspi.ROLE_CHECK_MENU_ITEM,
+                     pyatspi.ROLE_RADIO_MENU_ITEM]
+        if self.role in textRoles:
+            return True
+
+        return False
 
     def _extentsAreOnSameLine(self, zone, pixelDelta=5):
         """Returns True if this Zone is physically on the same line as zone."""
@@ -247,91 +216,66 @@ class Zone:
         return self._extentsAreOnSameLine(zone)
 
     def getWordAtOffset(self, charOffset):
-        wordAtOffset = None
-        offset = 0
         for word in self.words:
-            nextOffset = offset + len(word.string)
-            wordAtOffset = word
-            if nextOffset > charOffset:
-                return [wordAtOffset, charOffset - offset]
-            else:
-                offset = nextOffset
+            offset = word.getRelativeOffset(charOffset)
+            if offset >= 0:
+                return word, offset
 
-        return [wordAtOffset, offset]
+        return None, -1
 
-class TextZone(Zone):
-    """Represents Accessibility_Text that is a portion of a single
-    horizontal line."""
+    def hasCaret(self):
+        """Returns True if this Zone contains the caret."""
 
-    def __init__(self,
-                 accessible,
-                 startOffset,
-                 string,
-                 x, y,
-                 width, height):
-        """Creates a new Zone, which is a horizontal region of text.
+        return False
 
-        Arguments:
-        - accessible: the Accessible associated with this Zone
-        - startOffset: the index of the char in the Accessibility_Text
-                       interface where this Zone starts
-        - string: the string being displayed for this Zone
-        - extents: x, y, width, height in screen coordinates
-        """
+    def wordWithCaret(self):
+        """Returns the Word and relative offset with the caret."""
+
+        return None, -1
+
+class TextZone(Zone):
+    """A Zone whose purpose is to display text of an object."""
+
+    def __init__(self, accessible, startOffset, string, x, y, width, height, role=None):
+        super().__init__(accessible, string, x, y, width, height, role)
 
-        Zone.__init__(self, accessible, string, x, y, width, height)
         self.startOffset = startOffset
+        self.endOffset = self.startOffset + len(string)
+        self._itext = self.accessible.queryText()
 
-    def __getattr__(self, attr):
-        """Used for lazily determining the words in a Zone.  The words
-        will either be all whitespace (interword boundaries) or actual
-        words.  To determine if a Word is whitespace, use
-        word.string.isspace()
+    def __getattribute__(self, attr):
+        """To ensure we update the content."""
 
-        Arguments:
-        - attr: a string indicating the attribute name to retrieve
+        if not attr in ["words", "string"]:
+            return super().__getattribute__(attr)
 
-        Returns the value of the given attribute.
-        """
+        string = self._itext.getText(self.startOffset, self.endOffset)
+        words = []
+        for i, word in enumerate(re.finditer(self.WORDS_RE, string)):
+            start, end = map(lambda x: x + self.startOffset, word.span())
+            extents = self._itext.getRangeExtents(start, end, pyatspi.DESKTOP_COORDS)
+            words.append(Word(self, i, start, word.group(), *extents))
 
-        if attr == "words":
-            text = self.accessible.queryText()
+        self._string = string
+        self._words = words
+        return super().__getattribute__(attr)
 
-            # Pylint is confused and flags this warning:
-            #
-            # W0201:288:TextZone.__getattr__: Attribute 'words' defined
-            # outside __init__
-            #
-            # So for now, we just disable this error in this method.
-            #
-            # pylint: disable-msg=W0201
+    def hasCaret(self):
+        """Returns True if this Zone contains the caret."""
 
-            self.words = []
+        offset = self._itext.caretOffset
+        if self.startOffset <= offset < self.endOffset:
+            return True
 
-            wordIndex = 0
-            offset = self.startOffset
-            for string in whitespace_re.split(self.string):
-                if len(string):
-                    endOffset = offset + len(string)
-                    [x, y, width, height] = text.getRangeExtents(
-                        offset,
-                        endOffset,
-                        0)
-                    word = Word(self,
-                                wordIndex,
-                                offset,
-                                string,
-                                x, y, width, height)
-                    self.words.append(word)
-                    wordIndex += 1
-                    offset = endOffset
-
-            return self.words
-
-        elif attr.startswith('__') and attr.endswith('__'):
-            raise AttributeError(attr)
-        else:
-            return self.__dict__[attr]
+        return self.endOffset == self._itext.characterCount
+
+    def wordWithCaret(self):
+        """Returns the Word and relative offset with the caret."""
+
+        if not self.hasCaret():
+            return None, -1
+
+        return self.getWordAtOffset(self._itext.caretOffset)
 
 
 class StateZone(Zone):
@@ -403,46 +347,23 @@ class Line:
         self.zones = zones
         self.brailleRegions = None
 
-    def __getattr__(self, attr):
-        # We dynamically create the string each time to handle
-        # StateZone and ValueZone zones.
-        #
-        if attr in ["string", "length", "x", "y", "width", "height"]:
-            bounds = None
-            string = ""
-            for zone in self.zones:
-                if not bounds:
-                    bounds = [zone.x, zone.y,
-                              zone.x + zone.width, zone.y + zone.height]
-                else:
-                    bounds[0] = min(bounds[0], zone.x)
-                    bounds[1] = min(bounds[1], zone.y)
-                    bounds[2] = max(bounds[2], zone.x + zone.width)
-                    bounds[3] = max(bounds[3], zone.y + zone.height)
-                if len(zone.string):
-                    if len(string):
-                        string += " "
-                    string += zone.string
-
-            if not bounds:
-                bounds = [-1, -1, -1, -1]
-
-            if attr == "string":
-                return string
-            elif attr == "length":
-                return len(string)
-            elif attr == "x":
-                return bounds[0]
-            elif attr == "y":
-                return bounds[1]
-            elif attr == "width":
-                return bounds[2] - bounds[0]
-            elif attr == "height":
-                return bounds[3] - bounds[1]
-        elif attr.startswith('__') and attr.endswith('__'):
-            raise AttributeError(attr)
-        else:
-            return self.__dict__[attr]
+    def __getattribute__(self, attr):
+        if attr == "string":
+            return " ".join([zone.string for zone in self.zones])
+
+        if attr == "x":
+            return min([zone.x for zone in self.zones])
+
+        if attr == "y":
+            return min([zone.y for zone in self.zones])
+
+        if attr == "width":
+            return sum([zone.width for zone in self.zones])
+
+        if attr == "height":
+            return max([zone.height for zone in self.zones])
+
+        return super().__getattribute__(attr)
 
     def getBrailleRegions(self):
         # [[[WDW - We'll always compute the braille regions.  This
@@ -768,6 +689,14 @@ class Context:
         else:
             zones = []
 
+        # TODO - JD: This is here temporarily whilst I sort out the rest
+        # of the text-related mess.
+        if "EditableText" in pyatspi.listInterfaces(accessible) \
+           and accessible.getState().contains(pyatspi.STATE_SINGLE_LINE):
+            extents = accessible.queryComponent().getExtents(0)
+            return [TextZone(accessible, 0, text.getText(0, -1), *extents)]
+
+
         offset = 0
         lastEndOffset = -1
         upperMax = lowerMax = text.characterCount
@@ -887,21 +816,6 @@ class Context:
                 #
                 break
 
-        # We might have a zero length text area.  In that case, well,
-        # lets hack if this is something whose sole purpose is to
-        # act as a text entry area.
-        #
-        if len(zones) == 0:
-            if (accessible.getRole() == pyatspi.ROLE_TEXT) \
-               or ((accessible.getRole() == pyatspi.ROLE_ENTRY)) \
-               or ((accessible.getRole() == pyatspi.ROLE_PASSWORD_TEXT)):
-                extents = accessible.queryComponent().getExtents(0)
-                zones.append(TextZone(accessible,
-                                      0,
-                                      "",
-                                      extents.x, extents.y,
-                                      extents.width, extents.height))
-
         return zones
 
     def _insertStateZone(self, zones, accessible, extents):
@@ -994,7 +908,8 @@ class Context:
             pass
         elif not zones:
             string = self.script.speechGenerator.getName(accessible)
-            if not string and role != pyatspi.ROLE_TABLE_CELL:
+            useless = [pyatspi.ROLE_TABLE_CELL, pyatspi.ROLE_LABEL]
+            if not string and role not in useless:
                 string = self.script.speechGenerator.getLocalizedRoleName(accessible)
 
             # TODO - JD: This check will become obsolete soon.
diff --git a/test/keystrokes/firefox/flat_review_text_by_word_and_char.py 
b/test/keystrokes/firefox/flat_review_text_by_word_and_char.py
index a17b994..0e740f0 100644
--- a/test/keystrokes/firefox/flat_review_text_by_word_and_char.py
+++ b/test/keystrokes/firefox/flat_review_text_by_word_and_char.py
@@ -20,7 +20,7 @@ sequence.append(utils.AssertPresentationAction(
     "1. Flat review current word",
     ["BRAILLE LINE:  'On weaponry: $l'",
      "     VISIBLE:  'On weaponry: $l', cursor=1",
-     "SPEECH OUTPUT: 'On'"]))
+     "SPEECH OUTPUT: 'On '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_6"))
@@ -88,7 +88,7 @@ sequence.append(utils.AssertPresentationAction(
     "5. flat review next word",
     ["BRAILLE LINE:  'NOBODY expects the Spanish Inquisition! Our chief weapon is surprise. Surprise and 
fear. Fear and  $l'",
      "     VISIBLE:  'NOBODY expects the Spanish Inqui', cursor=1",
-     "SPEECH OUTPUT: 'NOBODY'"]))
+     "SPEECH OUTPUT: 'NOBODY '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_6"))
@@ -96,7 +96,7 @@ sequence.append(utils.AssertPresentationAction(
     "6. flat review next word",
     ["BRAILLE LINE:  'NOBODY expects the Spanish Inquisition! Our chief weapon is surprise. Surprise and 
fear. Fear and  $l'",
      "     VISIBLE:  'NOBODY expects the Spanish Inqui', cursor=8",
-     "SPEECH OUTPUT: 'expects'"]))
+     "SPEECH OUTPUT: 'expects '"]))
 
 sequence.append(KeyComboAction("KP_2"))
 sequence.append(utils.AssertPresentationAction(
@@ -105,7 +105,7 @@ sequence.append(utils.AssertPresentationAction(
      "     VISIBLE:  'NOBODY expects the Spanish Inqui', cursor=8",
      "BRAILLE LINE:  'NOBODY expects the Spanish Inquisition! Our chief weapon is surprise. Surprise and 
fear. Fear and  $l'",
      "     VISIBLE:  'NOBODY expects the Spanish Inqui', cursor=8",
-     "SPEECH OUTPUT: 'expects'",
+     "SPEECH OUTPUT: 'expects '",
      "SPEECH OUTPUT: 'e'"]))
 
 sequence.append(utils.StartRecordingAction())
@@ -174,7 +174,7 @@ sequence.append(utils.AssertPresentationAction(
     "14. flat review previous word",
     ["BRAILLE LINE:  'NOBODY expects the Spanish Inquisition! Our chief weapon is surprise. Surprise and 
fear. Fear and  $l'",
      "     VISIBLE:  'NOBODY expects the Spanish Inqui', cursor=1",
-     "SPEECH OUTPUT: 'NOBODY'"]))
+     "SPEECH OUTPUT: 'NOBODY '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_4"))
diff --git a/test/keystrokes/gnome-clocks/stop_watch_flat_review.py 
b/test/keystrokes/gnome-clocks/stop_watch_flat_review.py
index eec02ff..117b177 100644
--- a/test/keystrokes/gnome-clocks/stop_watch_flat_review.py
+++ b/test/keystrokes/gnome-clocks/stop_watch_flat_review.py
@@ -43,10 +43,9 @@ sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_7"))
 sequence.append(utils.AssertPresentationAction(
     "4. Review previous line",
-    ["KNOWN ISSUE: We're not updating the values",
-     "BRAILLE LINE:  '00‎∶00.0 $l'",
-     "     VISIBLE:  '00‎∶00.0 $l', cursor=1",
-     "SPEECH OUTPUT: '00‎∶00.0'"]))
+    ["BRAILLE LINE:  '00‎∶04\.[0-9] \$l'",
+     "     VISIBLE:  '00‎∶04\.[0-9] \$l', cursor=1",
+     "SPEECH OUTPUT: '00‎∶04\.[0-9]'"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_7"))
@@ -59,17 +58,16 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_9"))
 sequence.append(utils.AssertPresentationAction(
-    "5. Review next line",
-    ["KNOWN ISSUE: We're not updating the values",
-     "BRAILLE LINE:  '00‎∶00.0 $l'",
-     "     VISIBLE:  '00‎∶00.0 $l', cursor=1",
-     "SPEECH OUTPUT: '00‎∶00.0'"]))
+    "6. Review next line",
+    ["BRAILLE LINE:  '00‎∶0(8|9)\.[0-9] \$l'",
+     "     VISIBLE:  '00‎∶0(8|9)\.[0-9] \$l', cursor=1",
+     "SPEECH OUTPUT: '00‎∶0(8|9)\.[0-9]'"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_Subtract"))
 sequence.append(KeyComboAction("KP_Subtract"))
 sequence.append(utils.AssertPresentationAction(
-    "6. Toggle flat review",
+    "7. Toggle flat review",
     ["BRAILLE LINE:  'Leaving flat review.'",
      "     VISIBLE:  'Leaving flat review.', cursor=0",
      "BRAILLE LINE:  'gnome-clocks application frame Stop push button'",
@@ -85,21 +83,20 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_7"))
 sequence.append(utils.AssertPresentationAction(
-    "7. Review previous line",
-    ["BRAILLE LINE:  '00‎∶11.5 $l'",
-     "     VISIBLE:  '00‎∶11.5 $l', cursor=1",
-     "SPEECH OUTPUT: '00‎∶11.5'"]))
+    "8. Review previous line",
+    ["BRAILLE LINE:  '00‎∶(13|14)\.[0-9] \$l'",
+     "     VISIBLE:  '00‎∶(13|14)\.[0-9] \$l', cursor=1",
+     "SPEECH OUTPUT: '00‎∶(13|14)\.[0-9]'"]))
 
 sequence.append(PauseAction(3000))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_8"))
 sequence.append(utils.AssertPresentationAction(
-    "8. Review current line",
-    ["KNOWN ISSUE: We're not presenting the updated value",
-     "BRAILLE LINE:  '00‎∶11.5 $l'",
-     "     VISIBLE:  '00‎∶11.5 $l', cursor=1",
-     "SPEECH OUTPUT: '00‎∶11.5'"]))
+    "9. Review current line",
+    ["BRAILLE LINE:  '00‎∶(19|20)\.[0-9] \$l'",
+     "     VISIBLE:  '00‎∶(19|20)\.[0-9] \$l', cursor=1",
+     "SPEECH OUTPUT: '00‎∶(19|20)\.[0-9]'"]))
 
 sequence.append(utils.AssertionSummaryAction())
 sequence.start()
diff --git a/test/keystrokes/gnome-clocks/timer_flat_review.py 
b/test/keystrokes/gnome-clocks/timer_flat_review.py
index 3a27bcc..b42fdaf 100644
--- a/test/keystrokes/gnome-clocks/timer_flat_review.py
+++ b/test/keystrokes/gnome-clocks/timer_flat_review.py
@@ -44,13 +44,15 @@ sequence.append(utils.AssertPresentationAction(
      "     VISIBLE:  'Pause Reset $l', cursor=1",
      "SPEECH OUTPUT: 'Pause Reset'"]))
 
+sequence.append(PauseAction(5000))
+
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_7"))
 sequence.append(utils.AssertPresentationAction(
     "4. Review previous line",
-    ["BRAILLE LINE:  'label 00 ∶ 04 ∶ 58 label $l'",
-     "     VISIBLE:  'label 00 ∶ 04 ∶ 58 label $l', cursor=1",
-     "SPEECH OUTPUT: 'label 00 ∶ 04 ∶ 58 label'"])) 
+    ["BRAILLE LINE:  '00 ∶ 04 ∶ 5[0-9] \$l'",
+     "     VISIBLE:  '00 ∶ 04 ∶ 5[0-9] \$l', cursor=1",
+     "SPEECH OUTPUT: '00 ∶ 04 ∶ 5[0-9]'"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_7"))
@@ -60,57 +62,35 @@ sequence.append(utils.AssertPresentationAction(
      "     VISIBLE:  '& y World & y Alarm & y Stopwatc', cursor=1",
      "SPEECH OUTPUT: 'not selected World not selected Alarm not selected Stopwatch selected Timer'"]))
 
+sequence.append(PauseAction(5000))
+
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_9"))
 sequence.append(utils.AssertPresentationAction(
     "6. Review next line",
-    ["BRAILLE LINE:  'label 00 ∶ 04 ∶ 58 label $l'",
-     "     VISIBLE:  'label 00 ∶ 04 ∶ 58 label $l', cursor=1",
-     "SPEECH OUTPUT: 'label 00 ∶ 04 ∶ 58 label'"])) 
-
-sequence.append(utils.StartRecordingAction())
-sequence.append(KeyComboAction("KP_Subtract"))
-sequence.append(KeyComboAction("KP_Subtract"))
-sequence.append(utils.AssertPresentationAction(
-    "7. Toggle flat review",
-    ["BRAILLE LINE:  'Leaving flat review.'",
-     "     VISIBLE:  'Leaving flat review.', cursor=0",
-     "BRAILLE LINE:  'gnome-clocks application frame Pause push button'",
-     "     VISIBLE:  'Pause push button', cursor=1",
-     "BRAILLE LINE:  'Entering flat review.'",
-     "     VISIBLE:  'Entering flat review.', cursor=0",
-     "BRAILLE LINE:  'Pause Reset $l'",
-     "     VISIBLE:  'Pause Reset $l', cursor=1",
-     "SPEECH OUTPUT: 'Leaving flat review.' voice=system",
-     "SPEECH OUTPUT: 'Entering flat review.' voice=system",
-     "SPEECH OUTPUT: 'Pause'"]))
+    ["BRAILLE LINE:  '00 ∶ 04 ∶ 4[0-9] \$l'",
+     "     VISIBLE:  '00 ∶ 04 ∶ 4[0-9] \$l', cursor=1",
+     "SPEECH OUTPUT: '00 ∶ 04 ∶ 4[0-9]'"]))
 
-sequence.append(utils.StartRecordingAction())
-sequence.append(KeyComboAction("KP_7"))
-sequence.append(utils.AssertPresentationAction(
-    "8. Review previous line",
-    ["BRAILLE LINE:  'label 00 ∶ 04 ∶ 49 label $l'",
-     "     VISIBLE:  'label 00 ∶ 04 ∶ 49 label $l', cursor=1",
-     "SPEECH OUTPUT: 'label 00 ∶ 04 ∶ 49 label'"])) 
+sequence.append(PauseAction(5000))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_8"))
 sequence.append(utils.AssertPresentationAction(
-    "9. Review current line",
-    ["BRAILLE LINE:  'label 00 ∶ 04 ∶ 49 label $l'",
-     "     VISIBLE:  'label 00 ∶ 04 ∶ 49 label $l', cursor=1",
-     "SPEECH OUTPUT: 'label 00 ∶ 04 ∶ 49 label'"]))
+    "7. Review current line",
+    ["BRAILLE LINE:  '00 ∶ 04 ∶ 3[0-9] \$l'",
+     "     VISIBLE:  '00 ∶ 04 ∶ 3[0-9] \$l', cursor=1",
+     "SPEECH OUTPUT: '00 ∶ 04 ∶ 3[0-9]'"]))
 
-sequence.append(PauseAction(3000))
+sequence.append(PauseAction(5000))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_8"))
 sequence.append(utils.AssertPresentationAction(
-    "10. Review current line",
-    ["KNOWN ISSUE: The values are now being displayed, but are not yet being updated. Also the labels are 
useless.",
-     "BRAILLE LINE:  'label 00 ∶ 04 ∶ 49 label $l'",
-     "     VISIBLE:  'label 00 ∶ 04 ∶ 49 label $l', cursor=1",
-     "SPEECH OUTPUT: 'label 00 ∶ 04 ∶ 49 label'"]))
+    "8. Review current line",
+    ["BRAILLE LINE:  '00 ∶ 04 ∶ 2[0-9] \$l'",
+     "     VISIBLE:  '00 ∶ 04 ∶ 2[0-9] \$l', cursor=1",
+     "SPEECH OUTPUT: '00 ∶ 04 ∶ 2[0-9]'"]))
 
 sequence.append(utils.AssertionSummaryAction())
 sequence.start()
diff --git a/test/keystrokes/gtk-demo/role_menu_flat_review.py 
b/test/keystrokes/gtk-demo/role_menu_flat_review.py
index ea9279b..92d44b9 100644
--- a/test/keystrokes/gtk-demo/role_menu_flat_review.py
+++ b/test/keystrokes/gtk-demo/role_menu_flat_review.py
@@ -66,25 +66,25 @@ sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_9"))
 sequence.append(utils.AssertPresentationAction(
     "7. Review next line",
-    ["BRAILLE LINE:  ' $l'",
-     "     VISIBLE:  ' $l', cursor=1",
-     "SPEECH OUTPUT: 'blank'"]))
+    ["BRAILLE LINE:  'text $l'",
+     "     VISIBLE:  'text $l', cursor=1",
+     "SPEECH OUTPUT: 'text'"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_5"))
 sequence.append(utils.AssertPresentationAction(
     "8. Review current word",
-    ["BRAILLE LINE:  ' $l'",
-     "     VISIBLE:  ' $l', cursor=1",
-     "SPEECH OUTPUT: 'blank'"]))
+    ["BRAILLE LINE:  'text $l'",
+     "     VISIBLE:  'text $l', cursor=1",
+     "SPEECH OUTPUT: 'text'"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_2"))
 sequence.append(utils.AssertPresentationAction(
     "9. Review current char",
-    ["BRAILLE LINE:  ' $l'",
-     "     VISIBLE:  ' $l', cursor=1",
-     "SPEECH OUTPUT: 'blank'"]))
+    ["BRAILLE LINE:  'text $l'",
+     "     VISIBLE:  'text $l', cursor=1",
+     "SPEECH OUTPUT: 'text'"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_6"))
@@ -92,7 +92,7 @@ sequence.append(utils.AssertPresentationAction(
     "10. Review next word",
     ["BRAILLE LINE:  'Cursor at row 0 column 0 - 0 chars in document $l'",
      "     VISIBLE:  'Cursor at row 0 column 0 - 0 cha', cursor=1",
-     "SPEECH OUTPUT: 'Cursor'"]))
+     "SPEECH OUTPUT: 'Cursor '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_3"))
@@ -114,9 +114,9 @@ sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_1"))
 sequence.append(utils.AssertPresentationAction(
     "13. Review previous char",
-    ["BRAILLE LINE:  ' $l'",
-     "     VISIBLE:  ' $l', cursor=1",
-     "SPEECH OUTPUT: 'blank'"]))
+    ["BRAILLE LINE:  'text $l'",
+     "     VISIBLE:  'text $l', cursor=1",
+     "SPEECH OUTPUT: 'text'"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_4"))
diff --git a/test/keystrokes/gtk-demo/role_text_multiline_flat_review.py 
b/test/keystrokes/gtk-demo/role_text_multiline_flat_review.py
index 7bb978e..c0c74e1 100644
--- a/test/keystrokes/gtk-demo/role_text_multiline_flat_review.py
+++ b/test/keystrokes/gtk-demo/role_text_multiline_flat_review.py
@@ -36,7 +36,7 @@ sequence.append(utils.AssertPresentationAction(
      "BRAILLE LINE:  'PLEASE DO NOT PANIC. $l'",
      "     VISIBLE:  'PLEASE DO NOT PANIC. $l', cursor=1",
      "SPEECH OUTPUT: 'Entering flat review.' voice=system",
-     "SPEECH OUTPUT: 'PLEASE'"]))
+     "SPEECH OUTPUT: 'PLEASE '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_8"))
@@ -50,10 +50,10 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_5"))
 sequence.append(utils.AssertPresentationAction(
-    "3. KP_5 to flat review 'PLEASE'",
+    "3. KP_5 to flat review 'PLEASE '",
     ["BRAILLE LINE:  'PLEASE DO NOT PANIC. $l'",
      "     VISIBLE:  'PLEASE DO NOT PANIC. $l', cursor=1",
-     "SPEECH OUTPUT: 'PLEASE'"]))
+     "SPEECH OUTPUT: 'PLEASE '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_2"))
@@ -69,47 +69,50 @@ sequence.append(KeyComboAction("Down"))
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_5"))
 sequence.append(utils.AssertPresentationAction(
-    "5. KP_5 to flat review 'This'",
+    "5. KP_5 to flat review 'This '",
     ["BRAILLE LINE:  'This is only a test. $l'",
      "     VISIBLE:  'This is only a test. $l', cursor=1",
-     "SPEECH OUTPUT: 'This'"]))
+     "SPEECH OUTPUT: 'This '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_5"))
 sequence.append(KeyComboAction("KP_5"))
 sequence.append(utils.AssertPresentationAction(
-    "6. KP_5 2X to spell 'This'",
+    "6. KP_5 2X to spell 'This '",
     ["BRAILLE LINE:  'This is only a test. $l'",
      "     VISIBLE:  'This is only a test. $l', cursor=1",
      "BRAILLE LINE:  'This is only a test. $l'",
      "     VISIBLE:  'This is only a test. $l', cursor=1",
-     "SPEECH OUTPUT: 'This'",
+     "SPEECH OUTPUT: 'This '",
      "SPEECH OUTPUT: 'T'",
      "SPEECH OUTPUT: 'h'",
      "SPEECH OUTPUT: 'i'",
-     "SPEECH OUTPUT: 's'"]))
+     "SPEECH OUTPUT: 's'",
+     "SPEECH OUTPUT: 'space'"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_5"))
 sequence.append(KeyComboAction("KP_5"))
 sequence.append(KeyComboAction("KP_5"))
 sequence.append(utils.AssertPresentationAction(
-    "7. KP_5 3X to military spell 'This'",
+    "7. KP_5 3X to military spell 'This '",
     ["BRAILLE LINE:  'This is only a test. $l'",
      "     VISIBLE:  'This is only a test. $l', cursor=1",
      "BRAILLE LINE:  'This is only a test. $l'",
      "     VISIBLE:  'This is only a test. $l', cursor=1",
      "BRAILLE LINE:  'This is only a test. $l'",
      "     VISIBLE:  'This is only a test. $l', cursor=1",
-     "SPEECH OUTPUT: 'This'",
+     "SPEECH OUTPUT: 'This '",
      "SPEECH OUTPUT: 'T'",
      "SPEECH OUTPUT: 'h'",
      "SPEECH OUTPUT: 'i'",
      "SPEECH OUTPUT: 's'",
+     "SPEECH OUTPUT: 'space'",
      "SPEECH OUTPUT: 'tango'",
      "SPEECH OUTPUT: 'hotel'",
      "SPEECH OUTPUT: 'india'",
-     "SPEECH OUTPUT: 'sierra'"]))
+     "SPEECH OUTPUT: 'sierra'",
+     "SPEECH OUTPUT: ' '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_8"))
@@ -237,7 +240,7 @@ sequence.append(utils.AssertPresentationAction(
     "13. KP_6 to flat review 'is'",
     ["BRAILLE LINE:  'This is only a test. $l'",
      "     VISIBLE:  'This is only a test. $l', cursor=6",
-     "SPEECH OUTPUT: 'is'"]))
+     "SPEECH OUTPUT: 'is '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_7"))
diff --git a/test/keystrokes/gtk3-demo/role_dialog_flat_review.py 
b/test/keystrokes/gtk3-demo/role_dialog_flat_review.py
index 467eb33..23d50db 100644
--- a/test/keystrokes/gtk3-demo/role_dialog_flat_review.py
+++ b/test/keystrokes/gtk3-demo/role_dialog_flat_review.py
@@ -89,7 +89,7 @@ sequence.append(utils.AssertPresentationAction(
     "9. Review next word",
     ["BRAILLE LINE:  'File: ~/Documents/gtk-demo.pdf Output format: &=y PDF & y Postscript & y SVG $l'",
      "     VISIBLE:  'File: ~/Documents/gtk-demo.pdf O', cursor=32",
-     "SPEECH OUTPUT: 'Output'"]))
+     "SPEECH OUTPUT: 'Output '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_3"))
diff --git a/test/keystrokes/gtk3-demo/role_table_flat_review.py 
b/test/keystrokes/gtk3-demo/role_table_flat_review.py
index 925112e..66e63c8 100644
--- a/test/keystrokes/gtk3-demo/role_table_flat_review.py
+++ b/test/keystrokes/gtk3-demo/role_table_flat_review.py
@@ -68,7 +68,7 @@ sequence.append(utils.AssertPresentationAction(
     "7. Review next word'",
     ["BRAILLE LINE:  '2 packages of chocolate chip cookies $l'",
      "     VISIBLE:  '2 packages of chocolate chip coo', cursor=3",
-     "SPEECH OUTPUT: 'packages'"]))
+     "SPEECH OUTPUT: 'packages '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_6"))
@@ -76,7 +76,7 @@ sequence.append(utils.AssertPresentationAction(
     "8. Review next word'",
     ["BRAILLE LINE:  '2 packages of chocolate chip cookies $l'",
      "     VISIBLE:  '2 packages of chocolate chip coo', cursor=12",
-     "SPEECH OUTPUT: 'of'"]))
+     "SPEECH OUTPUT: 'of '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_3"))
@@ -116,7 +116,7 @@ sequence.append(utils.AssertPresentationAction(
     "13. Review previous word'",
     ["BRAILLE LINE:  '2 packages of chocolate chip cookies $l'",
      "     VISIBLE:  '2 packages of chocolate chip coo', cursor=3",
-     "SPEECH OUTPUT: 'packages'"]))
+     "SPEECH OUTPUT: 'packages '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_4"))
diff --git a/test/keystrokes/gtk3-demo/role_text_multiline_flat_review.py 
b/test/keystrokes/gtk3-demo/role_text_multiline_flat_review.py
index a084911..da953ad 100644
--- a/test/keystrokes/gtk3-demo/role_text_multiline_flat_review.py
+++ b/test/keystrokes/gtk3-demo/role_text_multiline_flat_review.py
@@ -36,7 +36,7 @@ sequence.append(utils.AssertPresentationAction(
      "BRAILLE LINE:  'PLEASE DO NOT PANIC. $l'",
      "     VISIBLE:  'PLEASE DO NOT PANIC. $l', cursor=1",
      "SPEECH OUTPUT: 'Entering flat review.' voice=system",
-     "SPEECH OUTPUT: 'PLEASE'"]))
+     "SPEECH OUTPUT: 'PLEASE '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_8"))
@@ -50,10 +50,10 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_5"))
 sequence.append(utils.AssertPresentationAction(
-    "3. KP_5 to flat review 'PLEASE'",
+    "3. KP_5 to flat review 'PLEASE '",
     ["BRAILLE LINE:  'PLEASE DO NOT PANIC. $l'",
      "     VISIBLE:  'PLEASE DO NOT PANIC. $l', cursor=1",
-     "SPEECH OUTPUT: 'PLEASE'"]))
+     "SPEECH OUTPUT: 'PLEASE '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_2"))
@@ -69,47 +69,50 @@ sequence.append(KeyComboAction("Down"))
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_5"))
 sequence.append(utils.AssertPresentationAction(
-    "5. KP_5 to flat review 'This'",
+    "5. KP_5 to flat review 'This '",
     ["BRAILLE LINE:  'This is only a test. $l'",
      "     VISIBLE:  'This is only a test. $l', cursor=1",
-     "SPEECH OUTPUT: 'This'"]))
+     "SPEECH OUTPUT: 'This '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_5"))
 sequence.append(KeyComboAction("KP_5"))
 sequence.append(utils.AssertPresentationAction(
-    "6. KP_5 2X to spell 'This'",
+    "6. KP_5 2X to spell 'This '",
     ["BRAILLE LINE:  'This is only a test. $l'",
      "     VISIBLE:  'This is only a test. $l', cursor=1",
      "BRAILLE LINE:  'This is only a test. $l'",
      "     VISIBLE:  'This is only a test. $l', cursor=1",
-     "SPEECH OUTPUT: 'This'",
+     "SPEECH OUTPUT: 'This '",
      "SPEECH OUTPUT: 'T'",
      "SPEECH OUTPUT: 'h'",
      "SPEECH OUTPUT: 'i'",
-     "SPEECH OUTPUT: 's'"]))
+     "SPEECH OUTPUT: 's'",
+     "SPEECH OUTPUT: 'space'"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_5"))
 sequence.append(KeyComboAction("KP_5"))
 sequence.append(KeyComboAction("KP_5"))
 sequence.append(utils.AssertPresentationAction(
-    "7. KP_5 3X to military spell 'This'",
+    "7. KP_5 3X to military spell 'This '",
     ["BRAILLE LINE:  'This is only a test. $l'",
      "     VISIBLE:  'This is only a test. $l', cursor=1",
      "BRAILLE LINE:  'This is only a test. $l'",
      "     VISIBLE:  'This is only a test. $l', cursor=1",
      "BRAILLE LINE:  'This is only a test. $l'",
      "     VISIBLE:  'This is only a test. $l', cursor=1",
-     "SPEECH OUTPUT: 'This'",
+     "SPEECH OUTPUT: 'This '",
      "SPEECH OUTPUT: 'T'",
      "SPEECH OUTPUT: 'h'",
      "SPEECH OUTPUT: 'i'",
      "SPEECH OUTPUT: 's'",
+     "SPEECH OUTPUT: 'space'",
      "SPEECH OUTPUT: 'tango'",
      "SPEECH OUTPUT: 'hotel'",
      "SPEECH OUTPUT: 'india'",
-     "SPEECH OUTPUT: 'sierra'"]))
+     "SPEECH OUTPUT: 'sierra'",
+     "SPEECH OUTPUT: ' '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_8"))
@@ -237,7 +240,7 @@ sequence.append(utils.AssertPresentationAction(
     "13. KP_6 to flat review 'is'",
     ["BRAILLE LINE:  'This is only a test. $l'",
      "     VISIBLE:  'This is only a test. $l', cursor=6",
-     "SPEECH OUTPUT: 'is'"]))
+     "SPEECH OUTPUT: 'is '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_7"))
diff --git a/test/keystrokes/gtk3-demo/role_toggle_button_flat_review.py 
b/test/keystrokes/gtk3-demo/role_toggle_button_flat_review.py
index bde7dcb..723609f 100644
--- a/test/keystrokes/gtk3-demo/role_toggle_button_flat_review.py
+++ b/test/keystrokes/gtk3-demo/role_toggle_button_flat_review.py
@@ -63,7 +63,7 @@ sequence.append(utils.AssertPresentationAction(
     "7. Review next word",
     ["BRAILLE LINE:  'Here are some more details but not the full story. $l'",
      "     VISIBLE:  'Here are some more details but n', cursor=6",
-     "SPEECH OUTPUT: 'are'"]))
+     "SPEECH OUTPUT: 'are '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_6"))
@@ -71,7 +71,7 @@ sequence.append(utils.AssertPresentationAction(
     "8. Review next word",
     ["BRAILLE LINE:  'Here are some more details but not the full story. $l'",
      "     VISIBLE:  'Here are some more details but n', cursor=10",
-     "SPEECH OUTPUT: 'some'"]))
+     "SPEECH OUTPUT: 'some '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_6"))
@@ -79,7 +79,7 @@ sequence.append(utils.AssertPresentationAction(
     "9. Review next word",
     ["BRAILLE LINE:  'Here are some more details but not the full story. $l'",
      "     VISIBLE:  'Here are some more details but n', cursor=15",
-     "SPEECH OUTPUT: 'more'"]))
+     "SPEECH OUTPUT: 'more '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_6"))
@@ -87,7 +87,7 @@ sequence.append(utils.AssertPresentationAction(
     "10. Review next word",
     ["BRAILLE LINE:  'Here are some more details but not the full story. $l'",
      "     VISIBLE:  'Here are some more details but n', cursor=20",
-     "SPEECH OUTPUT: 'details'"]))
+     "SPEECH OUTPUT: 'details '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_6"))
@@ -95,7 +95,7 @@ sequence.append(utils.AssertPresentationAction(
     "11. Review next word",
     ["BRAILLE LINE:  'Here are some more details but not the full story. $l'",
      "     VISIBLE:  'Here are some more details but n', cursor=28",
-     "SPEECH OUTPUT: 'but'"]))
+     "SPEECH OUTPUT: 'but '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_6"))
@@ -103,7 +103,7 @@ sequence.append(utils.AssertPresentationAction(
     "12. Review next word",
     ["BRAILLE LINE:  'Here are some more details but not the full story. $l'",
      "     VISIBLE:  'Here are some more details but n', cursor=32",
-     "SPEECH OUTPUT: 'not'"]))
+     "SPEECH OUTPUT: 'not '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_6"))
@@ -111,7 +111,7 @@ sequence.append(utils.AssertPresentationAction(
     "13. Review next word",
     ["BRAILLE LINE:  'Here are some more details but not the full story. $l'",
      "     VISIBLE:  'ot the full story. $l', cursor=4",
-     "SPEECH OUTPUT: 'the'"]))
+     "SPEECH OUTPUT: 'the '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_6"))
@@ -119,7 +119,7 @@ sequence.append(utils.AssertPresentationAction(
     "14. Review next word",
     ["BRAILLE LINE:  'Here are some more details but not the full story. $l'",
      "     VISIBLE:  'ot the full story. $l', cursor=8",
-     "SPEECH OUTPUT: 'full'"]))
+     "SPEECH OUTPUT: 'full '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_6"))
diff --git a/test/keystrokes/oowriter/flat_review_word.py b/test/keystrokes/oowriter/flat_review_word.py
index a6089b1..9a431bc 100644
--- a/test/keystrokes/oowriter/flat_review_word.py
+++ b/test/keystrokes/oowriter/flat_review_word.py
@@ -30,7 +30,7 @@ sequence.append(utils.AssertPresentationAction(
     "1. Review current word.",
     ["BRAILLE LINE:  'Line 1 $l'",
      "     VISIBLE:  'Line 1 $l', cursor=1",
-     "SPEECH OUTPUT: 'Line'"]))
+     "SPEECH OUTPUT: 'Line '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_5"))
@@ -41,11 +41,12 @@ sequence.append(utils.AssertPresentationAction(
      "     VISIBLE:  'Line 1 $l', cursor=1",
      "BRAILLE LINE:  'Line 1 $l'",
      "     VISIBLE:  'Line 1 $l', cursor=1",
-     "SPEECH OUTPUT: 'Line'",
+     "SPEECH OUTPUT: 'Line '",
      "SPEECH OUTPUT: 'L'",
      "SPEECH OUTPUT: 'i'",
      "SPEECH OUTPUT: 'n'",
-     "SPEECH OUTPUT: 'e'"]))
+     "SPEECH OUTPUT: 'e'",
+     "SPEECH OUTPUT: 'space'"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_5"))
@@ -59,15 +60,17 @@ sequence.append(utils.AssertPresentationAction(
      "     VISIBLE:  'Line 1 $l', cursor=1",
      "BRAILLE LINE:  'Line 1 $l'",
      "     VISIBLE:  'Line 1 $l', cursor=1",
-     "SPEECH OUTPUT: 'Line'",
+     "SPEECH OUTPUT: 'Line '",
      "SPEECH OUTPUT: 'L'",
      "SPEECH OUTPUT: 'i'",
      "SPEECH OUTPUT: 'n'",
      "SPEECH OUTPUT: 'e'",
+     "SPEECH OUTPUT: 'space'",
      "SPEECH OUTPUT: 'lima'",
      "SPEECH OUTPUT: 'india'",
      "SPEECH OUTPUT: 'november'",
-     "SPEECH OUTPUT: 'echo'"]))
+     "SPEECH OUTPUT: 'echo'",
+     "SPEECH OUTPUT: ' '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_6"))
@@ -83,7 +86,7 @@ sequence.append(utils.AssertPresentationAction(
     "5. Review next word.",
     ["BRAILLE LINE:  'Line 2 $l'",
      "     VISIBLE:  'Line 2 $l', cursor=1",
-     "SPEECH OUTPUT: 'Line'"]))
+     "SPEECH OUTPUT: 'Line '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_6"))
@@ -99,7 +102,7 @@ sequence.append(utils.AssertPresentationAction(
     "7. Review previous word.",
     ["BRAILLE LINE:  'Line 2 $l'",
      "     VISIBLE:  'Line 2 $l', cursor=1",
-     "SPEECH OUTPUT: 'Line'"]))
+     "SPEECH OUTPUT: 'Line '"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("KP_4"))
@@ -115,7 +118,7 @@ sequence.append(utils.AssertPresentationAction(
     "9. Review previous word.",
     ["BRAILLE LINE:  'Line 1 $l'",
      "     VISIBLE:  'Line 1 $l', cursor=1",
-     "SPEECH OUTPUT: 'Line'"]))
+     "SPEECH OUTPUT: 'Line '"]))
 
 sequence.append(utils.AssertionSummaryAction())
 sequence.start()



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]