text: # -*- coding: utf-8 -*-
  import unittest
  import time
  
  from ._mouse_event import MoveEvent, ButtonEvent, WheelEvent, LEFT, RIGHT, MIDDLE, X, X2, UP, DOWN, DOUBLE
  import mouse
  
  class FakeOsMouse(object):
      def __init__(self):
          self.append = None
          self.position = (0, 0)
          self.queue = None
          self.init = lambda: None
  
      def listen(self, queue):
          self.listening = True
          self.queue = queue
  
      def press(self, button):
          self.append((DOWN, button))
  
      def release(self, button):
          self.append((UP, button))
  
      def get_position(self):
          return self.position
  
      def move_to(self, x, y):
          self.append(('move', (x, y)))
          self.position = (x, y)
  
      def wheel(self, delta):
          self.append(('wheel', delta))
  
      def move_relative(self, x, y):
          self.position = (self.position[0] + x, self.position[1] + y)
  
  class TestMouse(unittest.TestCase):
      @staticmethod
      def setUpClass():
          mouse._os_mouse= FakeOsMouse()
          mouse._listener.start_if_necessary()
          assert mouse._os_mouse.listening
  
      def setUp(self):
          self.events = []
          mouse._pressed_events.clear()
          mouse._os_mouse.append = self.events.append
  
      def tearDown(self):
          mouse.unhook_all()
          # Make sure there's no spill over between tests.
          self.wait_for_events_queue()
  
      def wait_for_events_queue(self):
          mouse._listener.queue.join()
  
      def flush_events(self):
          self.wait_for_events_queue()
          events = list(self.events)
          # Ugly, but requried to work in Python2. Python3 has list.clear
          del self.events[:]
          return events
  
      def press(self, button=LEFT):
          mouse._os_mouse.queue.put(ButtonEvent(DOWN, button, time.time()))
          self.wait_for_events_queue()
  
      def release(self, button=LEFT):
          mouse._os_mouse.queue.put(ButtonEvent(UP, button, time.time()))
          self.wait_for_events_queue()
  
      def double_click(self, button=LEFT):
          mouse._os_mouse.queue.put(ButtonEvent(DOUBLE, button, time.time()))
          self.wait_for_events_queue()
  
      def click(self, button=LEFT):
          self.press(button)
          self.release(button)
  
      def wheel(self, delta=1):
          mouse._os_mouse.queue.put(WheelEvent(delta, time.time()))
          self.wait_for_events_queue()
  
      def move(self, x=0, y=0):
          mouse._os_mouse.queue.put(MoveEvent(x, y, time.time()))
          self.wait_for_events_queue()
  
      def test_hook(self):
          events = []
          self.press()
          mouse.hook(events.append)
          self.press()
          mouse.unhook(events.append)
          self.press()
          self.assertEqual(len(events), 1)
  
      def test_is_pressed(self):
          self.assertFalse(mouse.is_pressed())
          self.press()
          self.assertTrue(mouse.is_pressed())
          self.release()
          self.press(X2)
          self.assertFalse(mouse.is_pressed())
  
          self.assertTrue(mouse.is_pressed(X2))
          self.press(X2)
          self.assertTrue(mouse.is_pressed(X2))
          self.release(X2)
          self.release(X2)
          self.assertFalse(mouse.is_pressed(X2))
  
      def test_buttons(self):
          mouse.press()
          self.assertEqual(self.flush_events(), [(DOWN, LEFT)])
          mouse.release()
          self.assertEqual(self.flush_events(), [(UP, LEFT)])
          mouse.click()
          self.assertEqual(self.flush_events(), [(DOWN, LEFT), (UP, LEFT)])
          mouse.double_click()
          self.assertEqual(self.flush_events(), [(DOWN, LEFT), (UP, LEFT), (DOWN, LEFT), (UP, LEFT)])
          mouse.press(X2)
          self.assertEqual(self.flush_events(), [(DOWN, X2)])
          mouse.right_press()
          self.assertEqual(self.flush_events(), [(DOWN, RIGHT)])
          mouse.right_release()
          self.assertEqual(self.flush_events(), [(UP, RIGHT)])
          mouse.right_click()
          self.assertEqual(self.flush_events(), [(DOWN, RIGHT), (UP, RIGHT)])
          mouse.double_right_click()
          self.assertEqual(self.flush_events(), [(DOWN, RIGHT), (UP, RIGHT), (DOWN, RIGHT), (UP, RIGHT)])
          mouse.right_press(X2)
          self.assertEqual(self.flush_events(), [(DOWN, X2)])
  
      def test_position(self):
          self.assertEqual(mouse.get_position(), mouse._os_mouse.get_position())
  
      def test_move(self):
          mouse.move(0, 0)
          self.assertEqual(mouse._os_mouse.get_position(), (0, 0))
          mouse.move(100, 500)
          self.assertEqual(mouse._os_mouse.get_position(), (100, 500))
          mouse.move(1, 2, False)
          self.assertEqual(mouse._os_mouse.get_position(), (101, 502))
  
          mouse.move(0, 0)
          mouse.move(100, 499, True, duration=0.01)
          self.assertEqual(mouse._os_mouse.get_position(), (100, 499))
          mouse.move(100, 1, False, duration=0.01)
          self.assertEqual(mouse._os_mouse.get_position(), (200, 500))
          mouse.move(0, 0, False, duration=0.01)
          self.assertEqual(mouse._os_mouse.get_position(), (200, 500))
  
      def triggers(self, fn, events, **kwargs):
          self.triggered = False
          def callback():
              self.triggered = True
          handler = fn(callback, **kwargs)
  
          for event_type, arg in events:
              if event_type == DOWN:
                  self.press(arg)
              elif event_type == UP:
                  self.release(arg)
              elif event_type == DOUBLE:
                  self.double_click(arg)
              elif event_type == 'WHEEL':
                  self.wheel()
  
          mouse._listener.remove_handler(handler)
          return self.triggered
  
      def test_on_button(self):
          self.assertTrue(self.triggers(mouse.on_button, [(DOWN, LEFT)]))
          self.assertTrue(self.triggers(mouse.on_button, [(DOWN, RIGHT)]))
          self.assertTrue(self.triggers(mouse.on_button, [(DOWN, X)]))
  
          self.assertFalse(self.triggers(mouse.on_button, [('WHEEL', '')]))
  
          self.assertFalse(self.triggers(mouse.on_button, [(DOWN, X)], buttons=MIDDLE))
          self.assertTrue(self.triggers(mouse.on_button, [(DOWN, MIDDLE)], buttons=MIDDLE))
          self.assertTrue(self.triggers(mouse.on_button, [(DOWN, MIDDLE)], buttons=MIDDLE))
          self.assertFalse(self.triggers(mouse.on_button, [(DOWN, MIDDLE)], buttons=MIDDLE, types=UP))
          self.assertTrue(self.triggers(mouse.on_button, [(UP, MIDDLE)], buttons=MIDDLE, types=UP))
  
          self.assertTrue(self.triggers(mouse.on_button, [(UP, MIDDLE)], buttons=[MIDDLE, LEFT], types=[UP, DOWN]))
          self.assertTrue(self.triggers(mouse.on_button, [(DOWN, LEFT)], buttons=[MIDDLE, LEFT], types=[UP, DOWN]))
          self.assertFalse(self.triggers(mouse.on_button, [(UP, X)], buttons=[MIDDLE, LEFT], types=[UP, DOWN]))
  
      def test_ons(self):
          self.assertTrue(self.triggers(mouse.on_click, [(UP, LEFT)]))
          self.assertFalse(self.triggers(mouse.on_click, [(UP, RIGHT)]))
          self.assertFalse(self.triggers(mouse.on_click, [(DOWN, LEFT)]))
          self.assertFalse(self.triggers(mouse.on_click, [(DOWN, RIGHT)]))
  
          self.assertTrue(self.triggers(mouse.on_right_click, [(UP, RIGHT)]))
          self.assertFalse(self.triggers(mouse.on_right_click, [(UP, LEFT)]))
          self.assertFalse(self.triggers(mouse.on_right_click, [(DOWN, LEFT)]))
          self.assertFalse(self.triggers(mouse.on_right_click, [(DOWN, RIGHT)]))
  
          self.assertTrue(self.triggers(mouse.on_middle_click, [(UP, MIDDLE)]))
          self.assertFalse(self.triggers(mouse.on_middle_click, [(UP, LEFT)]))
          self.assertFalse(self.triggers(mouse.on_middle_click, [(DOWN, LEFT)]))
          self.assertFalse(self.triggers(mouse.on_middle_click, [(DOWN, RIGHT)]))
  
          self.assertTrue(self.triggers(mouse.on_double_click, [(DOUBLE, LEFT)]))
          self.assertFalse(self.triggers(mouse.on_double_click, [(DOUBLE, RIGHT)]))
          self.assertFalse(self.triggers(mouse.on_double_click, [(DOWN, RIGHT)]))
  
          self.assertTrue(self.triggers(mouse.on_right_double_click, [(DOUBLE, RIGHT)]))
          self.assertFalse(self.triggers(mouse.on_right_double_click, [(DOUBLE, LEFT)]))
          self.assertFalse(self.triggers(mouse.on_right_double_click, [(DOWN, RIGHT)]))
  
          self.assertTrue(self.triggers(mouse.on_middle_double_click, [(DOUBLE, MIDDLE)]))
          self.assertFalse(self.triggers(mouse.on_middle_double_click, [(DOUBLE, LEFT)]))
          self.assertFalse(self.triggers(mouse.on_middle_double_click, [(DOWN, RIGHT)]))
  
      def test_wait(self):
          # If this fails it blocks. Unfortunately, but I see no other way of testing.
          from threading import Thread, Lock
          lock = Lock()
          lock.acquire()
          def t():
              mouse.wait()
              lock.release()
          Thread(target=t).start()
          self.press()
          lock.acquire()
  
      def test_record_play(self):
          from threading import Thread, Lock
          lock = Lock()
          lock.acquire()
          def t():
              self.recorded = mouse.record(RIGHT)
              lock.release()
          Thread(target=t).start()
          self.click()
          self.wheel(5)
          self.move(100, 50)
          self.press(RIGHT)
          lock.acquire()
  
          self.assertEqual(len(self.recorded), 5)
          self.assertEqual(self.recorded[0]._replace(time=None), ButtonEvent(DOWN, LEFT, None))
          self.assertEqual(self.recorded[1]._replace(time=None), ButtonEvent(UP, LEFT, None))
          self.assertEqual(self.recorded[2]._replace(time=None), WheelEvent(5, None))
          self.assertEqual(self.recorded[3]._replace(time=None), MoveEvent(100, 50, None))
          self.assertEqual(self.recorded[4]._replace(time=None), ButtonEvent(DOWN, RIGHT, None))
  
          mouse.play(self.recorded, speed_factor=0)
          events = self.flush_events()
          self.assertEqual(len(events), 5)
          self.assertEqual(events[0], (DOWN, LEFT))
          self.assertEqual(events[1], (UP, LEFT))
          self.assertEqual(events[2], ('wheel', 5))
          self.assertEqual(events[3], ('move', (100, 50)))
          self.assertEqual(events[4], (DOWN, RIGHT))
  
          mouse.play(self.recorded)
          events = self.flush_events()
          self.assertEqual(len(events), 5)
          self.assertEqual(events[0], (DOWN, LEFT))
          self.assertEqual(events[1], (UP, LEFT))
          self.assertEqual(events[2], ('wheel', 5))
          self.assertEqual(events[3], ('move', (100, 50)))
          self.assertEqual(events[4], (DOWN, RIGHT))
  
          mouse.play(self.recorded, include_clicks=False)
          events = self.flush_events()
          self.assertEqual(len(events), 2)
          self.assertEqual(events[0], ('wheel', 5))
          self.assertEqual(events[1], ('move', (100, 50)))
  
          mouse.play(self.recorded, include_moves=False)
          events = self.flush_events()
          self.assertEqual(len(events), 4)
          self.assertEqual(events[0], (DOWN, LEFT))
          self.assertEqual(events[1], (UP, LEFT))
          self.assertEqual(events[2], ('wheel', 5))
          self.assertEqual(events[3], (DOWN, RIGHT))
  
          mouse.play(self.recorded, include_wheel=False)
          events = self.flush_events()
          self.assertEqual(len(events), 4)
          self.assertEqual(events[0], (DOWN, LEFT))
          self.assertEqual(events[1], (UP, LEFT))
          self.assertEqual(events[2], ('move', (100, 50)))
          self.assertEqual(events[3], (DOWN, RIGHT))
  
  if __name__ == '__main__':
      unittest.main()
  