From 78de92cde03264725093868231bdb539feb4f56b Mon Sep 17 00:00:00 2001 From: charles Date: Wed, 15 Apr 2009 15:22:45 +0000 Subject: Added ClickAction and TypeTextAction + support for initial state --- diff --git a/src/sugar/tutorius/actions.py b/src/sugar/tutorius/actions.py index 2c76bd7..ad91fb4 100644 --- a/src/sugar/tutorius/actions.py +++ b/src/sugar/tutorius/actions.py @@ -250,3 +250,56 @@ class DisableWidgetAction(Action): """Action undo""" if self._widget: self._widget.set_sensitive(True) + +class TypeTextAction(Action): + """ + Simulate a user typing text in a widget + Work on any widget that implements a insert_text method + + @param widget The treehish representation of the widget + @param text the text that is typed + """ + def __init__(self, widget, text): + Action.__init__(self) + + self._widget = widget + self._text = text + + def do(self, **kwargs): + """ + Type the text + """ + widget = gtkutils.find_widget(ObjectStore().activity, self._widget) + if hasattr(widget, "insert_text"): + widget.insert_text(self._text, -1) + + def undo(self): + """ + no undo + """ + pass + +class ClickAction(Action): + """ + Action that simulate a click on a widget + Work on any widget that implements a clicked() method + + @param widget The threehish representation of the widget + """ + def __init__(self, widget): + Action.__init__(self) + self._widget = widget + + def do(self): + """ + click the widget + """ + widget = gtkutils.find_widget(ObjectStore().activity, self._widget) + if hasattr(widget, "clicked"): + widget.clicked() + + def undo(self): + """ + No undo + """ + pass diff --git a/src/sugar/tutorius/core.py b/src/sugar/tutorius/core.py index 901820f..f290f1e 100644 --- a/src/sugar/tutorius/core.py +++ b/src/sugar/tutorius/core.py @@ -24,6 +24,7 @@ This module contains the core classes for tutorius import gtk import logging import copy +import os from sugar.tutorius.dialog import TutoriusDialog from sugar.tutorius.gtkutils import find_widget @@ -36,12 +37,13 @@ class Tutorial (object): Tutorial Class, used to run through the FSM. """ - def __init__(self, name, fsm): + def __init__(self, name, fsm,filename= None): """ Creates an unattached tutorial. """ object.__init__(self) self.name = name + self.activity_init_state_filename = filename self.state_machine = fsm self.state_machine.set_tutorial(self) @@ -64,6 +66,7 @@ class Tutorial (object): self.activity = activity ObjectStore().activity = activity ObjectStore().tutorial = self + self._prepare_activity() self.state_machine.set_state("INIT") def detach(self): @@ -97,6 +100,21 @@ class Tutorial (object): #Swith to the next state pointed by the eventfilter self.set_state(eventfilter.get_next_state()) + + def _prepare_activity(self): + """ + Prepare the activity for the tutorial by loading the saved state and + emitting gtk signals + """ + #Load the saved activity if any + if self.activity_init_state_filename is not None: + #For now the file will be saved in the data folder + #of the activity root directory + filename = os.getenv("SUGAR_ACTIVITY_ROOT") + "/data/" +\ + self.activity_init_state_filename + if os.path.exists(filename): + self.activity.read_file(filename) + class State(object): """ diff --git a/src/sugar/tutorius/tests/coretests.py b/src/sugar/tutorius/tests/coretests.py index f9125ce..5f91a64 100644 --- a/src/sugar/tutorius/tests/coretests.py +++ b/src/sugar/tutorius/tests/coretests.py @@ -29,7 +29,7 @@ and event filters. Those are in their separate test module import unittest import logging -from sugar.tutorius.actions import Action +from sugar.tutorius.actions import Action, ClickAction, TypeTextAction from sugar.tutorius.core import * from sugar.tutorius.filters import * @@ -64,6 +64,44 @@ class TrueWhileActiveAction(Action): def undo(self): self.active = False + +class ClickableWidget(): + """ + This class fakes a widget with a clicked() method + """ + def __init__(self): + self.click_count = 0 + + def clicked(self): + self.click_count += 1 + +class FakeTextEntry(): + """ + This class fakes a widget with an insert_text() method + """ + def __init__(self): + self.text_lines = [] + self.last_entered_line = "" + self.displayed_text = "" + + def insert_text(self, text, index): + self.last_entered_line = text + self.text_lines.append(text) + self.displayed_text = self.displayed_text[0:index] + text + self.displayed_text[index+1:] + +class FakeParentWidget(): + """ + This class fakes a widet container, it implements the get_children() method + """ + def __init__(self): + self._children = [] + + def add_child(self, child): + self._children.append(child) + + def get_children(self): + return self._children + @@ -103,7 +141,96 @@ class FakeEventFilter(TriggerEventFilter): self.tutorial.set_state(event_filter.get_next_state()) +class ClickActionTests(unittest.TestCase): + """ + Test class for click action + """ + def test_do_action(self): + activity = FakeParentWidget() + widget = ClickableWidget() + activity.add_child(widget) + ObjectStore().activity = activity + + action = ClickAction("0.0") + + assert widget == ObjectStore().activity.get_children()[0],\ + "The clickable widget isn't reachable from the object store \ + the test cannot pass" + + action.do() + + assert widget.click_count == 1, "clicked() should have been called by do()" + + action.do() + + assert widget.click_count == 2, "clicked() should have been called by do()" + def test_undo(self): + activity = FakeParentWidget() + widget = ClickableWidget() + activity.add_child(widget) + ObjectStore().activity = activity + + action = ClickAction("0.0") + + assert widget == ObjectStore().activity.get_children()[0],\ + "The clickable widget isn't reachable from the object store \ + the test cannot pass" + + action.undo() + + #There is no undo for this action so the test should not fail + assert True + + + +class TypeTextActionTests(unittest.TestCase): + """ + Test class for type text action + """ + def test_do_action(self): + activity = FakeParentWidget() + widget = FakeTextEntry() + activity.add_child(widget) + ObjectStore().activity = activity + + test_text = "This is text" + + + action = TypeTextAction("0.0", test_text) + + assert widget == ObjectStore().activity.get_children()[0],\ + "The clickable widget isn't reachable from the object store \ + the test cannot pass" + + action.do() + + assert widget.last_entered_line == test_text, "insert_text() should have been called by do()" + + action.do() + + assert widget.last_entered_line == test_text, "insert_text() should have been called by do()" + assert len(widget.text_lines) == 2, "insert_text() should have been called twice" + + def test_undo(self): + activity = FakeParentWidget() + widget = FakeTextEntry() + activity.add_child(widget) + ObjectStore().activity = activity + + test_text = "This is text" + + + action = TypeTextAction("0.0", test_text) + + assert widget == ObjectStore().activity.get_children()[0],\ + "The clickable widget isn't reachable from the object store \ + the test cannot pass" + + action.undo() + + #There is no undo for this action so the test should not fail + assert True # State testing class class StateTest(unittest.TestCase): -- cgit v0.9.1