''' Animations tests ================ ''' import pytest @pytest.fixture(scope='module') def ec_cls(): class EventCounter: def __init__(self, anim): self.n_start = 0 self.n_progress = 0 self.n_complete = 0 anim.bind(on_start=self.on_start, on_progress=self.on_progress, on_complete=self.on_complete) def on_start(self, anim, widget): self.n_start += 1 def on_progress(self, anim, widget, progress): self.n_progress += 1 def on_complete(self, anim, widget): self.n_complete += 1 def assert_(self, n_start, n_progress_greater_than_zero, n_complete): assert self.n_start == n_start if n_progress_greater_than_zero: assert self.n_progress > 0 else: assert self.n_progress == 0 assert self.n_complete == n_complete return EventCounter @pytest.fixture(autouse=True) def cleanup(): from kivy.animation import Animation Animation.cancel_all(None) def no_animations_being_played(): from kivy.animation import Animation return len(Animation._instances) == 0 def sleep(t): from time import time, sleep from kivy.clock import Clock tick = Clock.tick deadline = time() + t while time() < deadline: sleep(.01) tick() class TestAnimation: def test_start_animation(self): from kivy.animation import Animation from kivy.uix.widget import Widget a = Animation(x=100, d=1) w = Widget() a.start(w) sleep(1.5) assert w.x == pytest.approx(100) assert no_animations_being_played() def test_animation_duration_0(self): from kivy.animation import Animation from kivy.uix.widget import Widget a = Animation(x=100, d=0) w = Widget() a.start(w) sleep(.5) assert no_animations_being_played() def test_cancel_all(self): from kivy.animation import Animation from kivy.uix.widget import Widget a1 = Animation(x=100) a2 = Animation(y=100) w1 = Widget() w2 = Widget() a1.start(w1) a1.start(w2) a2.start(w1) a2.start(w2) assert not no_animations_being_played() Animation.cancel_all(None) assert no_animations_being_played() def test_cancel_all_2(self): from kivy.animation import Animation from kivy.uix.widget import Widget a1 = Animation(x=100) a2 = Animation(y=100) w1 = Widget() w2 = Widget() a1.start(w1) a1.start(w2) a2.start(w1) a2.start(w2) assert not no_animations_being_played() Animation.cancel_all(None, 'x', 'z') assert not no_animations_being_played() Animation.cancel_all(None, 'y') assert no_animations_being_played() def test_stop_animation(self): from kivy.animation import Animation from kivy.uix.widget import Widget a = Animation(x=100, d=1) w = Widget() a.start(w) sleep(.5) a.stop(w) assert w.x != pytest.approx(100) assert w.x != pytest.approx(0) assert no_animations_being_played() def test_stop_all(self): from kivy.animation import Animation from kivy.uix.widget import Widget a = Animation(x=100, d=1) w = Widget() a.start(w) sleep(.5) Animation.stop_all(w) assert no_animations_being_played() def test_stop_all_2(self): from kivy.animation import Animation from kivy.uix.widget import Widget a = Animation(x=100, d=1) w = Widget() a.start(w) sleep(.5) Animation.stop_all(w, 'x') assert no_animations_being_played() def test_duration(self): from kivy.animation import Animation a = Animation(x=100, d=1) assert a.duration == 1 def test_transition(self): from kivy.animation import Animation, AnimationTransition a = Animation(x=100, t='out_bounce') assert a.transition is AnimationTransition.out_bounce def test_animated_properties(self): from kivy.animation import Animation a = Animation(x=100) assert a.animated_properties == {'x': 100, } def test_animated_instruction(self): from kivy.graphics import Scale from kivy.animation import Animation a = Animation(x=100, d=1) instruction = Scale(3, 3, 3) a.start(instruction) assert a.animated_properties == {'x': 100, } assert instruction.x == pytest.approx(3) sleep(1.5) assert instruction.x == pytest.approx(100) assert no_animations_being_played() def test_weakref(self): import gc from kivy.animation import Animation from kivy.uix.widget import Widget w = Widget() a = Animation(x=100) a.start(w.proxy_ref) del w gc.collect() try: sleep(1.) except ReferenceError: pass assert no_animations_being_played() class TestSequence: def test_cancel_all(self): from kivy.animation import Animation from kivy.uix.widget import Widget a = Animation(x=100) + Animation(x=0) w = Widget() a.start(w) sleep(.5) Animation.cancel_all(w) assert no_animations_being_played() def test_cancel_all_2(self): from kivy.animation import Animation from kivy.uix.widget import Widget a = Animation(x=100) + Animation(x=0) w = Widget() a.start(w) sleep(.5) Animation.cancel_all(w, 'x') assert no_animations_being_played() def test_stop_all(self): from kivy.animation import Animation from kivy.uix.widget import Widget a = Animation(x=100) + Animation(x=0) w = Widget() a.start(w) sleep(.5) Animation.stop_all(w) assert no_animations_being_played() def test_stop_all_2(self): from kivy.animation import Animation from kivy.uix.widget import Widget a = Animation(x=100) + Animation(x=0) w = Widget() a.start(w) sleep(.5) Animation.stop_all(w, 'x') assert no_animations_being_played() def test_count_events(self, ec_cls): from kivy.animation import Animation from kivy.uix.widget import Widget a = Animation(x=100, d=.5) + Animation(x=0, d=.5) w = Widget() ec = ec_cls(a) ec1 = ec_cls(a.anim1) ec2 = ec_cls(a.anim2) a.start(w) # right after the animation starts ec.assert_(1, False, 0) ec1.assert_(1, False, 0) ec2.assert_(0, False, 0) sleep(.2) # during the first half of the animation ec.assert_(1, True, 0) ec1.assert_(1, True, 0) ec2.assert_(0, False, 0) sleep(.5) # during the second half of the animation ec.assert_(1, True, 0) ec1.assert_(1, True, 1) ec2.assert_(1, True, 0) sleep(.5) # after the animation completed ec.assert_(1, True, 1) ec1.assert_(1, True, 1) ec2.assert_(1, True, 1) assert no_animations_being_played() def test_have_properties_to_animate(self): from kivy.animation import Animation from kivy.uix.widget import Widget a = Animation(x=100) + Animation(x=0) w = Widget() assert not a.have_properties_to_animate(w) a.start(w) assert a.have_properties_to_animate(w) a.stop(w) assert not a.have_properties_to_animate(w) assert no_animations_being_played() def test_animated_properties(self): from kivy.animation import Animation a = Animation(x=100, y=200) + Animation(x=0) assert a.animated_properties == {'x': 0, 'y': 200, } def test_transition(self): from kivy.animation import Animation a = Animation(x=100) + Animation(x=0) with pytest.raises(AttributeError): a.transition class TestRepetitiveSequence: def test_stop(self): from kivy.animation import Animation from kivy.uix.widget import Widget a = Animation(x=100) + Animation(x=0) a.repeat = True w = Widget() a.start(w) a.stop(w) assert no_animations_being_played() def test_count_events(self, ec_cls): from kivy.animation import Animation from kivy.uix.widget import Widget a = Animation(x=100, d=.5) + Animation(x=0, d=.5) a.repeat = True w = Widget() ec = ec_cls(a) ec1 = ec_cls(a.anim1) ec2 = ec_cls(a.anim2) a.start(w) # right after the animation starts ec.assert_(1, False, 0) ec1.assert_(1, False, 0) ec2.assert_(0, False, 0) sleep(.2) # during the first half of the first round of the animation ec.assert_(1, True, 0) ec1.assert_(1, True, 0) ec2.assert_(0, False, 0) sleep(.5) # during the second half of the first round of the animation ec.assert_(1, True, 0) ec1.assert_(1, True, 1) ec2.assert_(1, True, 0) sleep(.5) # during the first half of the second round of the animation ec.assert_(1, True, 0) ec1.assert_(2, True, 1) ec2.assert_(1, True, 1) sleep(.5) # during the second half of the second round of the animation ec.assert_(1, True, 0) ec1.assert_(2, True, 2) ec2.assert_(2, True, 1) a.stop(w) # after the animation stopped ec.assert_(1, True, 1) ec1.assert_(2, True, 2) ec2.assert_(2, True, 2) assert no_animations_being_played() class TestParallel: def test_have_properties_to_animate(self): from kivy.animation import Animation from kivy.uix.widget import Widget a = Animation(x=100) & Animation(y=100) w = Widget() assert not a.have_properties_to_animate(w) a.start(w) assert a.have_properties_to_animate(w) a.stop(w) assert not a.have_properties_to_animate(w) assert no_animations_being_played() def test_cancel_property(self): from kivy.animation import Animation from kivy.uix.widget import Widget a = Animation(x=100) & Animation(y=100) w = Widget() a.start(w) a.cancel_property(w, 'x') assert not no_animations_being_played() a.stop(w) assert no_animations_being_played() def test_animated_properties(self): from kivy.animation import Animation a = Animation(x=100) & Animation(y=100) assert a.animated_properties == {'x': 100, 'y': 100, } def test_transition(self): from kivy.animation import Animation a = Animation(x=100) & Animation(y=100) with pytest.raises(AttributeError): a.transition def test_count_events(self, ec_cls): from kivy.animation import Animation from kivy.uix.widget import Widget a = Animation(x=100) & Animation(y=100, d=.5) w = Widget() ec = ec_cls(a) ec1 = ec_cls(a.anim1) ec2 = ec_cls(a.anim2) a.start(w) # right after the animation started ec.assert_(1, False, 0) ec1.assert_(1, False, 0) ec2.assert_(1, False, 0) sleep(.2) # during the first half of the animation ec.assert_(1, False, 0) # n_progress is still 0 !! ec1.assert_(1, True, 0) ec2.assert_(1, True, 0) sleep(.5) # during the second half of the animation ec.assert_(1, False, 0) # n_progress is still 0 !! ec1.assert_(1, True, 0) ec2.assert_(1, True, 1) sleep(.5) # after the animation compeleted ec.assert_(1, False, 1) # n_progress is still 0 ! ec1.assert_(1, True, 1) ec2.assert_(1, True, 1) assert no_animations_being_played()