예제 #1
0
    def test_execute(self, env, fields, dom, dom_elem):
        # Test 1 same col
        # (left, width) pairs
        included = [(101, 5), (99, 5), (100, 0), (105, 0), (99, 1), (80, 40),
                    (101, 1)]

        for (left, width) in included:
            new_dom = copy.deepcopy(dom)
            new_dom["children"][1]["left"] = left
            new_dom["children"][1]["width"] = width
            new_state = MiniWoBState("utt", None, new_dom)
            same_col = SameColToken(
                MockReturnElementSet(new_state.dom.children[0]))
            dom_elem = env.buttons[0]
            env.set_last(dom_elem)
            env.observe(new_state)
            result = same_col.execute(env)

            assert isinstance(result, same_col.return_type)
            assert isinstance(result, ElementSet)
            assert len(result) == 1
            assert set([result[0].ref]) == set([2])

        # Test that these points aren't included
        excluded = [(99, 0), (98, 1), (79, 20), (106, 0), (106, 100)]

        for (left, width) in excluded:
            new_dom = copy.deepcopy(dom)
            new_dom["children"][1]["left"] = left
            new_dom["children"][1]["width"] = width
            new_state = MiniWoBState("utt", None, new_dom)
            same_col = SameColToken(
                MockReturnElementSet(new_state.dom.children[0]))
            dom_elem = env.buttons[0]
            env.set_last(dom_elem)
            env.observe(new_state)
            result = same_col.execute(env)

            assert isinstance(result, same_col.return_type)
            assert isinstance(result, ElementSet)
            assert len(result) == 0

        # Test that you can have multiple neighbors
        new_dom = copy.deepcopy(dom)
        new_dom["children"][1]["left"] = 103
        new_dom["children"][1]["width"] = 10
        new_dom["children"][2]["left"] = 99
        new_dom["children"][2]["width"] = 10

        new_state = MiniWoBState("utt", None, new_dom)
        same_col = SameColToken(MockReturnElementSet(
            new_state.dom.children[0]))
        dom_elem = env.buttons[0]
        env.set_last(dom_elem)
        env.observe(new_state)
        result = same_col.execute(env)

        assert isinstance(result, same_col.return_type)
        assert isinstance(result, ElementSet)
        assert len(result) == 2
예제 #2
0
    def test_valid_strings(self, env, dom, dom_elem):
        valid_strings = set([
            "1 2 3", "2 3 4", "3 4 5", "4 5 6", "1 2", "2 3", "3 4", "4 5",
            "5 6", "1", "2", "3", "4", "5", "6", "ONE", "TWO", "text"
        ])
        assert valid_strings == env.valid_strings

        # Make a new observation
        env.set_last(dom_elem)
        new_dom = copy.deepcopy(dom)
        new_dom["children"][0]["children"][0]["children"][3]["text"] = \
                "A B C D"
        new_state = MiniWoBState("new utterance", None, new_dom)
        env.observe(new_state)

        valid_strings.add("A B C")
        valid_strings.add("B C D")
        valid_strings.add("A B")
        valid_strings.add("B C")
        valid_strings.add("C D")
        valid_strings.add("A")
        valid_strings.add("B")
        valid_strings.add("C")
        valid_strings.add("D")

        # Check updated valid_strings
        assert valid_strings == env.valid_strings
예제 #3
0
    def test_utterance(self, env, dom, dom_elem):
        # Test that the utterance is correct.
        assert env.tokens == word_tokenize("This is the Utterance.")

        # Update utterance.
        env.set_last(dom_elem)
        new_state = MiniWoBState("new utterance", None, dom)
        env.observe(new_state)

        # Test new value
        assert env.tokens == word_tokenize("new utterance")
예제 #4
0
파일: instance.py 프로젝트: wayne9qiu/wge
 def get_state(self):
     """Get the current state.
     
     Returns:
         MiniWoBState
     """
     # Get the utterance
     response = self.driver.execute_script('return core.getUtterance();')
     if isinstance(response, dict):
         utterance = response['utterance']
         fields = Fields(response['fields'])
     else:
         utterance = response
         fields = self.field_extractor(utterance)
     # Get the DOM
     dom_info = self.driver.execute_script('return core.getDOMInfo();')
     state = MiniWoBState(utterance, fields, dom_info)
     # Get screenshot if requested
     if self.record_screenshots:
         img = get_screenshot(self.driver, self.task_width,
                              self.task_height)
         state.set_screenshot(img)
     return state
예제 #5
0
    def test_text(self, env, dom, dom_elem):
        # Test that text elements are reported
        text = env.text
        assert len(text) == 1
        assert text[0].text == "text"

        # Make a new observation
        env.set_last(dom_elem)
        new_dom = copy.deepcopy(dom)
        new_dom["children"][0]["children"][0]["children"][2]["text"] = "Hello"
        new_state = MiniWoBState("new utterance", None, new_dom)
        env.observe(new_state)

        # Make sure changes are reflected
        text = env.text
        assert len(text) == 1
        assert text[0].text == "Hello"
예제 #6
0
    def test_buttons(self, env, dom, dom_elem):
        # Test that buttons are reported
        buttons = env.buttons
        assert len(buttons) == 2
        text = sorted([buttons[0].text, buttons[1].text])
        assert text == ["ONE.", "TWO;"]

        # Make a new observation
        env.set_last(dom_elem)
        new_dom = copy.deepcopy(dom)
        new_dom["children"][0]["children"][0]["children"][0]["text"] = "Hello"
        new_state = MiniWoBState("new utterance", None, new_dom)
        env.observe(new_state)

        # Make sure changes are reflected
        buttons = env.buttons
        assert len(buttons) == 2
        text = sorted([buttons[0].text, buttons[1].text])
        assert text == ["Hello", "TWO;"]
예제 #7
0
    def test_last(self, env, dom, dom_elem):
        # Last should not be set yet.
        with pytest.raises(Exception):
            env.last

        # Set last and check
        env.set_last(dom_elem)
        assert env.last == dom_elem

        # Check can't double update last
        with pytest.raises(Exception):
            env.set_last(dom_elem)

        # Set a new observation
        state = MiniWoBState("utt", None, dom)

        # Check can't double update observation
        env.observe(state)
        with pytest.raises(Exception):
            env.observe(state)
예제 #8
0
    def test_input(self, env, dom, dom_elem):
        # Test that env recognizes all types of input elems
        input_elems = env.input
        assert len(input_elems) == 3
        assert input_elems[0].text == ""
        assert input_elems[1].text == ""
        assert input_elems[2].text == ""

        # Make a new observation
        env.set_last(dom_elem)
        new_dom = copy.deepcopy(dom)
        new_dom["children"][0]["children"][0]["children"][3]["text"] = "Hello"
        new_state = MiniWoBState("new utterance", None, new_dom)
        env.observe(new_state)

        # Make sure changes are reflected
        input_elems = env.input
        assert len(input_elems) == 3
        text = "".join(
            [input_elems[0].text, input_elems[1].text, input_elems[2].text])
        assert text == "Hello"
예제 #9
0
    def test_execute(self, env, fields, dom, dom_elem):
        # Test from StringToken
        like = LikeToken(StringToken(u"ONE"))
        result = like.execute(env)

        assert isinstance(result, like.return_type)
        assert isinstance(result, ElementSet)
        assert len(result) == 1
        assert result[0].text == "ONE."

        # Test from UtteranceSelectorToken
        env.set_last(dom_elem)
        new_state = MiniWoBState("TWO utterance blah", None, dom)
        env.observe(new_state)

        like = LikeToken(UtteranceSelectorToken(0, 1))
        result = like.execute(env)

        assert isinstance(result, like.return_type)
        assert isinstance(result, ElementSet)
        assert len(result) == 1
        assert result[0].text == "TWO;"

        # Test return none
        like = LikeToken(StringToken(u"abcd"))
        result = like.execute(env)

        assert isinstance(result, like.return_type)
        assert isinstance(result, ElementSet)
        assert len(result) == 0

        # Test punctuation and whitespace
        like = LikeToken(StringToken(u"T ?W O ."))
        result = like.execute(env)

        assert isinstance(result, like.return_type)
        assert isinstance(result, ElementSet)
        assert len(result) == 1
        assert result[0].text == "TWO;"
예제 #10
0
    def test_execute(self, env, fields, dom, dom_elem):
        # Three button simple DOM
        dom = {
            unicode("top"):
            0,
            unicode("height"):
            0,
            unicode("width"):
            0,
            unicode("tag"):
            unicode("BODY"),
            unicode("ref"):
            0,
            unicode("left"):
            0,
            unicode("children"): [{
                unicode("top"): 100,
                unicode("left"): 100,
                unicode("height"): 5,
                unicode("width"): 5,
                unicode("ref"): 1,
                unicode("tag"): unicode("BUTTON"),
                unicode("text"): unicode("ONE"),
                unicode("children"): []
            }, {
                unicode("top"): 0,
                unicode("left"): 210,
                unicode("height"): 5,
                unicode("width"): 5,
                unicode("ref"): 2,
                unicode("tag"): unicode("BUTTON"),
                unicode("text"): unicode("TWO"),
                unicode("children"): []
            }, {
                unicode("top"): 0,
                unicode("left"): 0,
                unicode("height"): 5,
                unicode("width"): 5,
                unicode("ref"): 3,
                unicode("tag"): unicode("BUTTON"),
                unicode("text"): unicode("THREE"),
                unicode("children"): []
            }]
        }
        env = ExecutionEnvironment(MiniWoBState("utt", None, dom))
        dom_elem = env.buttons[0]

        # Check all the pts that are near ONE
        included_points = [
            (75, 95),
            (75, 105),  # Edge on left
            (95, 125),
            (105, 125),  # Edge on bottom
            (125, 105),
            (125, 95),  # Edge on right
            (95, 75),
            (105, 75),  # Edge on top
            (100, 100),  # Full overlap
            (95, 95),
            (105, 95),  # Overlap top corners
            (95, 105),
            (105, 105),  # Overlap bottom corners
            (81, 81),  # Top left corner
            (119, 81),  # Top right corner
            (119, 119),  # Bottom right corner
            (81, 119),  # Bottom left corner
        ]

        # Check that all of the included pts are there
        for (left, top) in included_points:
            new_dom = copy.deepcopy(dom)
            new_dom["children"][1]["left"] = left
            new_dom["children"][1]["top"] = top
            new_state = MiniWoBState("utt", None, new_dom)
            near = NearToken(MockReturnElementSet(new_state.dom.children[0]))
            env.set_last(dom_elem)
            env.observe(new_state)
            dom_elem = env.buttons[0]
            result = near.execute(env)

            assert isinstance(result, near.return_type)
            assert isinstance(result, ElementSet)
            assert len(result) == 1
            assert set([result[0].ref]) == set([2])

        excluded_points = [
            (74, 95),
            (75, 106),  # Edge on left
            (94, 125),
            (105, 126),  # Edge on bottom
            (125, 106),
            (126, 95),  # Edge on right
            (95, 74),
            (106, 75),  # Edge on top
            (0, 0),  # Not even close
            (80, 81),  # Top left corner
            (119, 80),  # Top right corner
            (120, 119),  # Bottom right corner
            (81, 120),  # Bottom left corner
        ]

        # Check that all of the excluded pts are not there
        for (left, top) in excluded_points:
            new_dom = copy.deepcopy(dom)
            new_dom["children"][1]["left"] = left
            new_dom["children"][1]["top"] = top
            new_state = MiniWoBState("utt", None, new_dom)
            near = NearToken(MockReturnElementSet(new_state.dom.children[0]))
            env.set_last(dom_elem)
            env.observe(new_state)
            dom_elem = env.buttons[0]
            result = near.execute(env)

            assert isinstance(result, near.return_type)
            assert isinstance(result, ElementSet)
            assert len(result) == 0

        # Check that you can have multiple pts in there
        new_dom = copy.deepcopy(dom)
        left, top = included_points[0]
        new_dom["children"][1]["left"] = left
        new_dom["children"][1]["top"] = top
        left, top = included_points[1]
        new_dom["children"][2]["left"] = left
        new_dom["children"][2]["top"] = top
        new_state = MiniWoBState("utt", None, new_dom)
        near = NearToken(MockReturnElementSet(new_state.dom.children[0]))
        env.set_last(dom_elem)
        env.observe(new_state)

        result = near.execute(env)
        assert isinstance(result, near.return_type)
        assert isinstance(result, ElementSet)
        assert len(result) == 2
        assert set([result[0].ref, result[1].ref]) == set([2, 3])

        # Check for more than one input element
        near = NearToken(ButtonsToken())

        result = near.execute(env)
        assert isinstance(result, near.return_type)
        assert isinstance(result, ElementSet)
        assert len(result) == 3
        assert set([result[0].ref, result[1].ref,
                    result[2].ref]) == set([1, 2, 3])
예제 #11
0
    def test_execute(self, env, fields, dom, dom_elem):
        # TODO: Refactor these tests (put the loop into own method)
        # Test 1 same row
        # (y, height) pairs
        included = [(101, 5), (99, 5), (100, 0), (105, 0), (99, 1), (80, 40),
                    (101, 1)]

        for (top, height) in included:
            new_dom = copy.deepcopy(dom)
            new_dom["children"][1]["top"] = top
            new_dom["children"][1]["height"] = height
            new_state = MiniWoBState("utt", None, new_dom)
            same_row = SameRowToken(
                MockReturnElementSet(new_state.dom.children[0]))
            dom_elem = env.buttons[0]
            env.set_last(dom_elem)
            env.observe(new_state)
            result = same_row.execute(env)

            assert isinstance(result, same_row.return_type)
            assert isinstance(result, ElementSet)
            assert len(result) == 1
            assert set([result[0].ref]) == set([2])

        # Test that these points aren't included
        excluded = [(99, 0), (98, 1), (79, 20), (106, 0), (106, 100)]

        for (top, height) in excluded:
            new_dom = copy.deepcopy(dom)
            new_dom["children"][1]["top"] = top
            new_dom["children"][1]["height"] = height
            new_state = MiniWoBState("utt", None, new_dom)
            same_row = SameRowToken(
                MockReturnElementSet(new_state.dom.children[0]))
            dom_elem = env.buttons[0]
            env.set_last(dom_elem)
            env.observe(new_state)
            result = same_row.execute(env)

            assert isinstance(result, same_row.return_type)
            assert isinstance(result, ElementSet)
            assert len(result) == 0

        # Test that you can have multiple neighbors
        new_dom = copy.deepcopy(dom)
        new_dom["children"][1]["top"] = 103
        new_dom["children"][1]["height"] = 10
        new_dom["children"][2]["top"] = 99
        new_dom["children"][2]["height"] = 10

        new_state = MiniWoBState("utt", None, new_dom)
        same_row = SameRowToken(MockReturnElementSet(
            new_state.dom.children[0]))
        dom_elem = env.buttons[0]
        env.set_last(dom_elem)
        env.observe(new_state)
        result = same_row.execute(env)

        assert isinstance(result, same_row.return_type)
        assert isinstance(result, ElementSet)
        assert len(result) == 2
예제 #12
0
    def test_execute(self, env, fields, dom, dom_elem):
        # Test input
        input_token = InputElementsToken()
        result = input_token.execute(env)
        assert env.input == result
        assert isinstance(result, input_token.return_type)
        assert isinstance(result, ElementSet)

        # Test buttons
        buttons_token = ButtonsToken()
        result = buttons_token.execute(env)
        assert env.buttons == result
        assert isinstance(result, buttons_token.return_type)
        assert isinstance(result, ElementSet)

        # Test text
        text_token = TextToken()
        result = text_token.execute(env)
        assert env.text == result
        assert isinstance(result, text_token.return_type)
        assert isinstance(result, ElementSet)

        # Reset DOM
        env.set_last(dom_elem)
        new_dom = {
            unicode("top"): 0,
            unicode("height"): 210,
            unicode("width"): 500,
            unicode("tag"): unicode("BODY"),
            unicode("ref"): 30,
            unicode("children"): [],
            unicode("left"): 0
        }
        new_state = MiniWoBState("new utterance", None, new_dom)
        env.observe(new_state)

        # Test input
        input_token = InputElementsToken()
        result = input_token.execute(env)
        assert env.input == result
        assert isinstance(result, input_token.return_type)
        assert isinstance(result, ElementSet)

        # Test buttons
        buttons_token = ButtonsToken()
        result = buttons_token.execute(env)
        assert env.buttons == result
        assert isinstance(result, buttons_token.return_type)
        assert isinstance(result, ElementSet)

        # Test text
        text_token = TextToken()
        result = text_token.execute(env)
        assert env.text == result
        assert isinstance(result, text_token.return_type)
        assert isinstance(result, ElementSet)

        # Test last
        last_token = LastToken()
        result = last_token.execute(env)
        assert ElementSet([dom_elem]) == result
        assert isinstance(result, last_token.return_type)
        assert isinstance(result, ElementSet)
예제 #13
0
 def env(self, dom, fields):
     state = MiniWoBState(u"This is the Utterance.", fields, dom)
     env = ExecutionEnvironment(state)
     return env
예제 #14
0
 def dom_elem(self, dom):
     state = MiniWoBState("", None, dom)
     return state.dom_elements[-1]
예제 #15
0
    def _chunk_events(self, raw_state_pairs, utterance, fields):
        """Find chunks of events that express a single action."""

        chunks = []
        last_mousedown = None
        last_mouseup = None
        last_keydown = None
        # Current modifier keys (shift, ctrl, alt)
        current_modifiers = set()
        # Number of keypresses left to be checked with keydowns
        pending_keypresses = 0

        for i, (raw_state, raw_state_after) in enumerate(raw_state_pairs):
            raw_action = raw_state['action']
            state = MiniWoBState(utterance, fields, raw_state['dom'])
            target = self._target(state.dom_elements)
            t = raw_action['type']
            if t == 'mousedown':
                if last_mousedown:
                    logging.warning('Two consecutive mousedowns @ %d', i)
                    # Click is missing; convert the last mousedown into a click
                    chunks.append(
                        Chunk('click', last_mousedown.state,
                              last_mousedown.target, last_mousedown.args))
                    last_mousedown = last_mouseup = None
                coord = (raw_action['x'], raw_action['y'])
                last_mousedown = Chunk('mousedown', state, target, coord)
            elif t == 'mouseup':
                assert last_mousedown, 'Cannot have mouseup without mousedown @ {}'.format(
                    i)
                assert not last_mouseup, 'Two consecutive mouseups @ {}'.format(
                    i)
                coord = (raw_action['x'], raw_action['y'])
                last_mouseup = Chunk('mouseup', state, target, coord)
            elif t == 'click':
                if last_mouseup:
                    # TODO: Currently dragging is interpreted as clicking
                    chunks.append(
                        Chunk('click', last_mousedown.state,
                              last_mousedown.target, last_mousedown.args))
                    last_mousedown = last_mouseup = None
                else:
                    # Spurious click event from <label> tag
                    pass
            elif t == 'dblclick':
                # dblclick is ignored (two clicks are already in the chunk list)
                continue
            elif t == 'keydown':
                keycode = raw_action['keyCode']
                if keycode in EpisodeGraph.MODIFIERS:
                    current_modifiers.add(keycode)
                else:
                    last_keydown = Chunk(
                        'keydown', state, target,
                        sorted(list(current_modifiers) + [keycode]))

            elif t == 'keyup':
                keycode = raw_action['keyCode']
                if keycode in EpisodeGraph.MODIFIERS:
                    assert keycode in current_modifiers,\
                            'keyup on modifier without keydown @ {}'.format(i)
                    current_modifiers.remove(keycode)
                elif pending_keypresses:
                    pending_keypresses -= 1
                else:
                    assert last_keydown,\
                            'keyup without keydown @ {}'.format(i)
                    # Hotkey
                    state_after = MiniWoBState(utterance, fields,
                                               raw_state_after['dom'])
                    chunk = self._resolve_hotkey(last_keydown.state, target,
                                                 last_keydown.args,
                                                 state_after)
                    if chunk:
                        chunks.append(chunk)
            elif t == 'keypress':
                char = chr(raw_action['charCode'])
                chunks.append(
                    Chunk('type', last_keydown.state, last_keydown.target,
                          char))
                pending_keypresses += 1
            else:
                raise ValueError('Unknown action type: {}'.format(t))

        return chunks
예제 #16
0
    def _parse_raw_demo_original(self, raw_demo, field_extractor):
        """Takes the raw demo and spits out the relevant states.

        Algorithm: Look at mousedown / keypress events

        Args:
            raw_demo (dict): json contents of demo file
            field_extractor (FieldsExtractor): the fields extractor for this task

        Returns:
            state_vertices (list[StateVertex])
        """
        # Filter out only for keypresses and mousedowns (BEFORE)
        utterance = raw_demo['utterance']
        if 'fields' in raw_demo:
            fields = Fields(raw_demo['fields'])
        else:
            fields = field_extractor(utterance)
        raw_states = raw_demo["states"]
        state_vertices = []
        actions = []
        vertex_number = 0
        for i, raw_state in enumerate(raw_states[1:]):
            raw_action = raw_state["action"]
            if raw_action["timing"] == EpisodeGraph.BEFORE:
                if raw_action["type"] == "mousedown":
                    miniwob_state = MiniWoBState(utterance, fields,
                                                 raw_state['dom'])
                    target = self._target(miniwob_state.dom_elements)
                    if not target:  # target = yellow instruction box
                        continue
                    click = MiniWoBElementClick(target)
                    state_vertex = StateVertex(
                        miniwob_state,
                        [ActionEdge(click, vertex_number, vertex_number + 1)])
                    state_vertices.append(state_vertex)
                    vertex_number += 1
                elif raw_action["type"] == "keypress":
                    miniwob_state = MiniWoBState(utterance, fields,
                                                 raw_state['dom'])
                    char = chr(raw_action["keyCode"])
                    target = self._target(miniwob_state.dom_elements)
                    if not target:  # target = yellow instruction box
                        continue
                    type_action = MiniWoBFocusAndType(target, char)
                    state_vertex = StateVertex(miniwob_state, [
                        ActionEdge(type_action, vertex_number,
                                   vertex_number + 1)
                    ])
                    state_vertices.append(state_vertex)
                    vertex_number += 1

        # Collapse consecutive FocusAndTypes into one
        for i, vertex in enumerate(state_vertices):
            curr_action = vertex.action_edges[0].action
            if not isinstance(curr_action, MiniWoBFocusAndType):
                continue

            aggregated_text = curr_action.text
            while i + 1 < len(state_vertices):
                next_action = state_vertices[i + 1].action_edges[0].action
                if not isinstance(next_action, MiniWoBFocusAndType) or \
                    curr_action.element != next_action.element:
                    break
                aggregated_text += next_action.text
                del next_action
                del state_vertices[i + 1]
            vertex.action_edges[0] = ActionEdge(
                MiniWoBFocusAndType(curr_action.element, aggregated_text), i,
                i + 1)

        # Collapse Click then FocusAndType into just FocusAndType
        collapsed_state_vertices = []
        for index in range(len(state_vertices) - 1):
            curr_action = state_vertices[index].action_edges[0].action
            next_action = state_vertices[index + 1].action_edges[0].action
            if not(isinstance(curr_action, MiniWoBElementClick) and \
                   isinstance(next_action, MiniWoBFocusAndType) and \
                   curr_action.element == next_action.element):
                collapsed_state_vertices.append(state_vertices[index])
        collapsed_state_vertices.append(state_vertices[-1])

        # Correct the edge indices
        for i, state_vertex in enumerate(collapsed_state_vertices):
            state_vertex.action_edges[0] = ActionEdge(
                state_vertex.action_edges[0].action, i, i + 1)

        return collapsed_state_vertices