[pitivi] tests: Added tests for clipproperties.TransformationProperties



commit 7653541fdcee384647618fae4492779f23296609
Author: Stefan Popa <stefanpopa2209 gmail com>
Date:   Fri Jun 23 15:43:20 2017 +0300

    tests: Added tests for clipproperties.TransformationProperties
    
    Differential Revision: https://phabricator.freedesktop.org/D1767

 pitivi/clipproperties.py     |   40 +++---
 tests/test_clipproperties.py |  272 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 292 insertions(+), 20 deletions(-)
---
diff --git a/pitivi/clipproperties.py b/pitivi/clipproperties.py
index 5218051..d0e5c07 100644
--- a/pitivi/clipproperties.py
+++ b/pitivi/clipproperties.py
@@ -561,16 +561,16 @@ class TransformationProperties(Gtk.Expander, Loggable):
         clear_button = self.builder.get_object("clear_button")
         clear_button.connect("clicked", self._defaultValuesCb)
 
-        self.__activate_keyframes_btn = self.builder.get_object("activate_keyframes_button")
-        self.__activate_keyframes_btn.connect("toggled", self.__show_keyframes_toggled_cb)
+        self._activate_keyframes_btn = self.builder.get_object("activate_keyframes_button")
+        self._activate_keyframes_btn.connect("toggled", self.__show_keyframes_toggled_cb)
 
-        self.__next_keyframe_btn = self.builder.get_object("next_keyframe_button")
-        self.__next_keyframe_btn.connect("clicked", self.__go_to_keyframe, True)
-        self.__next_keyframe_btn.set_sensitive(False)
+        self._next_keyframe_btn = self.builder.get_object("next_keyframe_button")
+        self._next_keyframe_btn.connect("clicked", self.__go_to_keyframe, True)
+        self._next_keyframe_btn.set_sensitive(False)
 
-        self.__prev_keyframe_btn = self.builder.get_object("prev_keyframe_button")
-        self.__prev_keyframe_btn.connect("clicked", self.__go_to_keyframe, False)
-        self.__prev_keyframe_btn.set_sensitive(False)
+        self._prev_keyframe_btn = self.builder.get_object("prev_keyframe_button")
+        self._prev_keyframe_btn.connect("clicked", self.__go_to_keyframe, False)
+        self._prev_keyframe_btn.set_sensitive(False)
 
         self.__setup_spin_button("xpos_spinbtn", "posx")
         self.__setup_spin_button("ypos_spinbtn", "posy")
@@ -617,29 +617,29 @@ class TransformationProperties(Gtk.Expander, Loggable):
         pipeline.simple_seek(seekval)
 
     def __show_keyframes_toggled_cb(self, unused_button):
-        if self.__activate_keyframes_btn.props.active:
+        if self._activate_keyframes_btn.props.active:
             self.__set_control_bindings()
         self.__update_keyframes_ui()
 
     def __update_keyframes_ui(self):
         if self.__source_uses_keyframes():
-            self.__activate_keyframes_btn.props.label = "◆"
+            self._activate_keyframes_btn.props.label = "◆"
         else:
-            self.__activate_keyframes_btn.props.label = "◇"
-            self.__activate_keyframes_btn.props.active = False
+            self._activate_keyframes_btn.props.label = "◇"
+            self._activate_keyframes_btn.props.active = False
 
-        if not self.__activate_keyframes_btn.props.active:
-            self.__prev_keyframe_btn.set_sensitive(False)
-            self.__next_keyframe_btn.set_sensitive(False)
+        if not self._activate_keyframes_btn.props.active:
+            self._prev_keyframe_btn.set_sensitive(False)
+            self._next_keyframe_btn.set_sensitive(False)
             if self.__source_uses_keyframes():
-                self.__activate_keyframes_btn.set_tooltip_text(_("Show keyframes"))
+                self._activate_keyframes_btn.set_tooltip_text(_("Show keyframes"))
             else:
-                self.__activate_keyframes_btn.set_tooltip_text(_("Activate keyframes"))
+                self._activate_keyframes_btn.set_tooltip_text(_("Activate keyframes"))
             self.source.ui_element.showDefaultKeyframes()
         else:
-            self.__prev_keyframe_btn.set_sensitive(True)
-            self.__next_keyframe_btn.set_sensitive(True)
-            self.__activate_keyframes_btn.set_tooltip_text(_("Hide keyframes"))
+            self._prev_keyframe_btn.set_sensitive(True)
+            self._next_keyframe_btn.set_sensitive(True)
+            self._activate_keyframes_btn.set_tooltip_text(_("Hide keyframes"))
             self.source.ui_element.showMultipleKeyframes(
                 list(self.__control_bindings.values()))
 
diff --git a/tests/test_clipproperties.py b/tests/test_clipproperties.py
index 2a8f189..7d9dde5 100644
--- a/tests/test_clipproperties.py
+++ b/tests/test_clipproperties.py
@@ -17,10 +17,14 @@
 # Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 # Boston, MA 02110-1301, USA.
 import unittest
+from unittest import mock
 
 from gi.repository import Gtk
 
 from pitivi.clipproperties import EffectProperties
+from pitivi.clipproperties import TransformationProperties
+from tests import common
+from tests.test_timeline_timeline import BaseTestTimeline
 
 
 class EffectPropertiesTest(unittest.TestCase):
@@ -59,3 +63,271 @@ class EffectPropertiesTest(unittest.TestCase):
             2, 1, Gtk.TreeViewDropPosition.INTO_OR_BEFORE))
         self.assertEqual(1, EffectProperties.calculateEffectPriority(
             2, 1, Gtk.TreeViewDropPosition.INTO_OR_AFTER))
+
+
+class TransformationPropertiesTest(BaseTestTimeline):
+    """Tests for the TransformationProperties widget."""
+
+    def setup_transformation_box(self):
+        """Creates a TransformationProperties widget."""
+        timeline_container = common.create_timeline_container()
+        app = timeline_container.app
+        transformation_box = TransformationProperties(app)
+        project = timeline_container._project
+        transformation_box._newProjectLoadedCb(app, project)
+
+        return transformation_box
+
+    def test_spin_buttons_read(self):
+        """
+        Tests that the transformation properties spin buttons display
+        the correct values of the source properties.
+        """
+        # Create tranformation box
+        transformation_box = self.setup_transformation_box()
+        timeline = transformation_box.app.gui.timeline_ui.timeline
+        spin_buttons = transformation_box.spin_buttons
+
+        # Add a clip and select it
+        clip = self.addClipsSimple(timeline, 1)[0]
+        timeline.selection.select([clip])
+
+        # Check that spin buttons display the correct values by default
+        source = transformation_box.source
+        self.assertIsNotNone(source)
+        for prop in ["posx", "posy", "width", "height"]:
+            self.assertIn(prop, spin_buttons)
+            ret, source_value = source.get_child_property(prop)
+            self.assertTrue(ret)
+            spin_btn_value = spin_buttons[prop].get_value_as_int()
+            self.assertEqual(spin_btn_value, source_value)
+
+        # Change the source properties and check the spin buttons update
+        # correctly.
+        new_values = {"posx": 20, "posy": -50, "width": 70, "height": 450}
+        for prop, new_val in new_values.items():
+            self.assertTrue(source.set_child_property(prop, new_val))
+            spin_btn_value = spin_buttons[prop].get_value_as_int()
+            self.assertEqual(new_val, spin_btn_value)
+
+    def test_spin_buttons_write(self):
+        """
+        Tests that changes in spin buttons values are reflected in source
+        properties.
+        """
+        # Create tranformation box
+        transformation_box = self.setup_transformation_box()
+        timeline = transformation_box.app.gui.timeline_ui.timeline
+        spin_buttons = transformation_box.spin_buttons
+
+        # Add a clip and select it
+        clip = self.addClipsSimple(timeline, 1)[0]
+        timeline.selection.select([clip])
+        source = transformation_box.source
+        self.assertIsNotNone(source)
+
+        # Get current spin buttons values
+        current_spin_values = {}
+        for prop in ["posx", "posy", "width", "height"]:
+            current_spin_values[prop] = spin_buttons[prop].get_value_as_int()
+
+        changes = [
+            ("posx", -300), ("posy", 450), ("width", 1), ("height", 320),
+            ("posx", 230), ("posx", 520), ("posy", -10), ("posy", -1000),
+            ("width", 600), ("width", 1000), ("height", 1), ("height", 1000)
+        ]
+
+        # Change the spin buttons values and check the source properties are
+        # updated correctly.
+        for prop, new_value in changes:
+            spin_buttons[prop].set_value(new_value)
+            current_spin_values[prop] = new_value
+            for source_prop in ["posx", "posy", "width", "height"]:
+                ret, source_value = source.get_child_property(source_prop)
+                self.assertTrue(ret)
+                self.assertEqual(current_spin_values[source_prop], source_value)
+
+    def test_spin_buttons_source_change(self):
+        """
+        Check that spin buttons update correctly when changing the selected
+        clip.
+        """
+        # Create tranformation box
+        transformation_box = self.setup_transformation_box()
+        timeline = transformation_box.app.gui.timeline_ui.timeline
+        spin_buttons = transformation_box.spin_buttons
+
+        # Add two clips and select the first one
+        clips = self.addClipsSimple(timeline, 2)
+        timeline.selection.select([clips[0]])
+        source = transformation_box.source
+        self.assertIsNotNone(source)
+
+        # Change the spin buttons values
+        new_values = {"posx": 45, "posy": 10, "width": 450, "height": 25}
+        for prop, new_val in new_values.items():
+            spin_buttons[prop].set_value(new_val)
+
+        # Select the second clip and check the spin buttons values update
+        # correctly
+        timeline.selection.select([clips[1]])
+        source = transformation_box.source
+        self.assertIsNotNone(source)
+        for prop in ["posx", "posy", "width", "height"]:
+            ret, source_value = source.get_child_property(prop)
+            self.assertTrue(ret)
+            self.assertEqual(spin_buttons[prop].get_value_as_int(), source_value)
+
+        # Select the first clip again and check spin buttons values
+        timeline.selection.select([clips[0]])
+        for prop in ["posx", "posy", "width", "height"]:
+            self.assertEqual(spin_buttons[prop].get_value_as_int(), new_values[prop])
+
+    def test_keyframes_activate(self):
+        """Tests transformation properties keyframes activation."""
+        # Create transformation box
+        transformation_box = self.setup_transformation_box()
+        timeline = transformation_box.app.gui.timeline_ui.timeline
+
+        # Add a clip and select it
+        clip = self.addClipsSimple(timeline, 1)[0]
+        timeline.selection.select([clip])
+        source = transformation_box.source
+        self.assertIsNotNone(source)
+        inpoint = source.props.in_point
+        duration = source.props.duration
+
+        # Check keyframes are deactivated by default
+        for prop in ["posx", "posy", "width", "height"]:
+            self.assertIsNone(source.get_control_binding(prop))
+
+        # Get current source properties
+        initial_values = {}
+        for prop in ["posx", "posy", "width", "height"]:
+            ret, value = source.get_child_property(prop)
+            self.assertTrue(ret)
+            initial_values[prop] = value
+
+        # Activate keyframes and check the default keyframes are created
+        transformation_box._activate_keyframes_btn.set_active(True)
+        for prop in ["posx", "posy", "width", "height"]:
+            control_binding = source.get_control_binding(prop)
+            self.assertIsNotNone(control_binding)
+            control_source = control_binding.props.control_source
+            keyframes = [(item.timestamp, item.value) for item in control_source.get_all()]
+            self.assertEqual(keyframes, [(inpoint, initial_values[prop]),
+                                         (inpoint + duration, initial_values[prop])])
+
+    def test_keyframes_add(self):
+        """Tests keyframe creation."""
+        # Create transformation box
+        transformation_box = self.setup_transformation_box()
+        timeline = transformation_box.app.gui.timeline_ui.timeline
+        pipeline = timeline._project.pipeline
+        spin_buttons = transformation_box.spin_buttons
+
+        # Add a clip and select it
+        clip = self.addClipsSimple(timeline, 1)[0]
+        timeline.selection.select([clip])
+        source = transformation_box.source
+        self.assertIsNotNone(source)
+        start = source.props.start
+        inpoint = source.props.in_point
+        duration = source.props.duration
+
+        # Activate keyframes
+        transformation_box._activate_keyframes_btn.set_active(True)
+
+        # Add some more keyframes
+        offsets = [1, int(duration / 2), duration - 1]
+        for prop in ["posx", "posy", "width", "height"]:
+            for index, offset in enumerate(offsets):
+                timestamp, value = inpoint + offset, offset * 10
+                with mock.patch.object(pipeline, "getPosition") as get_position:
+                    get_position.return_value = start + offset
+                    spin_buttons[prop].set_value(value)
+
+                control_source = source.get_control_binding(prop).props.control_source
+                keyframes = [(item.timestamp, item.value) for item in control_source.get_all()]
+                self.assertEqual((timestamp, value), keyframes[index + 1])
+
+    def test_keyframes_navigation(self):
+        """Tests keyframe navigation."""
+        # Create transformation box
+        transformation_box = self.setup_transformation_box()
+        timeline = transformation_box.app.gui.timeline_ui.timeline
+        pipeline = timeline._project.pipeline
+
+        # Add a clip and select it
+        clip = self.addClipsSimple(timeline, 1)[0]
+        timeline.selection.select([clip])
+        source = transformation_box.source
+        self.assertIsNotNone(source)
+        start = source.props.start
+        inpoint = source.props.in_point
+        duration = source.props.duration
+
+        # Activate keyframes and add some more keyframes
+        transformation_box._activate_keyframes_btn.set_active(True)
+        offsets = [1, int(duration / 2), duration - 1]
+        for prop in ["posx", "posy", "width", "height"]:
+            for offset in offsets:
+                timestamp, value = inpoint + offset, offset * 10
+                control_source = source.get_control_binding(prop).props.control_source
+                control_source.set(timestamp, value)
+
+        # Add edge keyframes in the offsets array
+        offsets.insert(0, 0)
+        offsets.append(duration)
+
+        # Test keyframe navigation
+        prev_index = 0
+        next_index = 1
+        for position in range(duration + 1):
+            prev_keyframe_ts = offsets[prev_index] + inpoint
+            next_keyframe_ts = offsets[next_index] + inpoint
+
+            with mock.patch.object(pipeline, "getPosition") as get_position:
+                get_position.return_value = start + position
+                with mock.patch.object(pipeline, "simple_seek") as simple_seek:
+                    transformation_box._prev_keyframe_btn.clicked()
+                    simple_seek.assert_called_with(prev_keyframe_ts)
+                    transformation_box._next_keyframe_btn.clicked()
+                    simple_seek.assert_called_with(next_keyframe_ts)
+
+            if position + 1 == next_keyframe_ts and next_index + 1 < len(offsets):
+                next_index += 1
+            if position in offsets and position != 0:
+                prev_index += 1
+
+    def test_reset_to_default(self):
+        """Tests "reset to default" button."""
+        # Create transformation box
+        transformation_box = self.setup_transformation_box()
+        timeline = transformation_box.app.gui.timeline_ui.timeline
+
+        # Add a clip and select it
+        clip = self.addClipsSimple(timeline, 1)[0]
+        timeline.selection.select([clip])
+        source = transformation_box.source
+        self.assertIsNotNone(source)
+
+        # Change source properties
+        new_values = {"posx": 20, "posy": -50, "width": 70, "height": 450}
+        for prop, new_val in new_values.items():
+            self.assertTrue(source.set_child_property(prop, new_val))
+
+        # Activate keyframes
+        transformation_box._activate_keyframes_btn.set_active(True)
+
+        # Press "reset to default" button
+        clear_button = transformation_box.builder.get_object("clear_button")
+        clear_button.clicked()
+
+        # Check that control bindings were erased and the properties were
+        # reset to their default values
+        for prop in ["posx", "posy", "width", "height"]:
+            self.assertIsNone(source.get_control_binding(prop))
+            ret, value = source.get_child_property(prop)
+            self.assertTrue(ret)
+            self.assertEqual(value, source.ui.default_position[prop])


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