def setUp(self):
     self.mock = MagicMock()
     self.mock.KEYBOARD_KEYS = KEYBOARD_KEYS
     self.patcher = patch.dict('sys.modules', {'pyautogui': self.mock})
     self.patcher.start()
     from ImageHorizonLibrary import ImageHorizonLibrary
     self.lib = ImageHorizonLibrary()
 def setUp(self):
     self.mock = MagicMock()
     self.patcher = patch.dict('sys.modules', {'pyautogui': self.mock})
     self.patcher.start()
     from ImageHorizonLibrary import ImageHorizonLibrary
     self.lib = ImageHorizonLibrary(reference_folder=TESTIMG_DIR)
     self.locate = 'ImageHorizonLibrary.ImageHorizonLibrary.locate'
     self._locate = 'ImageHorizonLibrary.ImageHorizonLibrary._locate'
 def setUp(self):
     self.pyautogui_mock = MagicMock()
     self.Tk_mock = MagicMock()
     self.clipboard_mock = MagicMock()
     self.clipboard_mock.clipboard_get.return_value = 'copied text'
     self.Tk_mock.Tk.return_value = self.clipboard_mock
     self.patcher = patch.dict('sys.modules',
                               {'pyautogui': self.pyautogui_mock,
                                'Tkinter': self.Tk_mock})
     self.patcher.start()
     from ImageHorizonLibrary import ImageHorizonLibrary
     self.lib = ImageHorizonLibrary()
class TestScreenshot(TestCase):
    def setUp(self):
        self.mock = MagicMock()
        self.patcher = patch.dict('sys.modules', {'pyautogui': self.mock})
        self.patcher.start()
        from ImageHorizonLibrary import ImageHorizonLibrary
        self.lib = ImageHorizonLibrary()

    def tearDown(self):
        self.mock.reset_mock()
        self.patcher.stop()

    def _take_screenshot_many_times(self, expected_filename):
        folder = path_join(CURDIR, 'reference_folder')
        self.lib.set_screenshot_folder(folder)
        for i in range(1, 15):
            self.lib.take_a_screenshot()
            self.mock.screenshot.assert_called_once_with(
                path_join(folder, expected_filename % i))
            self.mock.reset_mock()

    def test_take_a_screenshot(self):
        self._take_screenshot_many_times('ImageHorizon-screenshot-%d.png')

    def test_take_a_screenshot_inside_robot(self):
        with patch.object(BuiltIn, 'get_variable_value',
                          return_value='Suite Name'):
            self._take_screenshot_many_times('SuiteName-screenshot-%d.png')

    def test_take_a_screenshot_with_invalid_folder(self):
        from ImageHorizonLibrary import ScreenshotFolderException

        for index, invalid_folder in enumerate((None, 0, False), 1):
            self.lib.screenshot_folder = invalid_folder
            expected = path_join(getcwd(),
                                 'ImageHorizon-screenshot-%d.png' % index)
            self.lib.take_a_screenshot()
            self.mock.screenshot.assert_called_once_with(expected)
            self.mock.reset_mock()

        for invalid_folder in (123, object()):
            self.lib.screenshot_folder = invalid_folder
            with self.assertRaises(ScreenshotFolderException):
                self.lib.take_a_screenshot()
class TestRecognizeImages(TestCase):
    def setUp(self):
        self.mock = MagicMock()
        self.patcher = patch.dict('sys.modules', {'pyautogui': self.mock})
        self.patcher.start()
        from ImageHorizonLibrary import ImageHorizonLibrary
        self.lib = ImageHorizonLibrary(reference_folder=TESTIMG_DIR)
        self.locate = 'ImageHorizonLibrary.ImageHorizonLibrary.locate'
        self._locate = 'ImageHorizonLibrary.ImageHorizonLibrary._locate'

    def tearDown(self):
        self.mock.reset_mock()
        self.patcher.stop()

    def test_click_image(self):
        with patch(self.locate, return_value=(0, 0)):
            self.lib.click_image('my_picture')
            self.mock.click.assert_called_once_with((0, 0))

    def _call_all_directional_functions(self, fn_name):
        from ImageHorizonLibrary import ImageHorizonLibrary
        retvals = []
        for direction in ['above', 'below', 'left', 'right']:
            fn = getattr(self.lib, fn_name % direction)
            with patch(self.locate, return_value=(0, 0)):
                retvals.append(fn('my_picture', 10))
        return retvals

    def _verify_calls_to_pyautogui(self, mock_calls, clicks=1):
        self.assertEquals(
            mock_calls,
            [call(0, -10, button='left', interval=0.0, clicks=clicks),
             call(0, 10, button='left', interval=0.0, clicks=clicks),
             call(-10, 0, button='left', interval=0.0, clicks=clicks),
             call(10, 0, button='left', interval=0.0, clicks=clicks)])

    def test_directional_clicks(self):
        self._call_all_directional_functions('click_to_the_%s_of_image')
        self._verify_calls_to_pyautogui(self.mock.click.mock_calls)

    def test_directional_copies(self):
        copy = 'ImageHorizonLibrary.ImageHorizonLibrary.copy'
        with patch(copy, return_value='Some Text'):
            ret = self._call_all_directional_functions('copy_from_the_%s_of')
        self._verify_calls_to_pyautogui(self.mock.click.mock_calls, clicks=3)
        for retval in ret:
            self.assertEquals(retval, 'Some Text')

    def test_does_exist(self):
        from ImageHorizonLibrary import ImageNotFoundException

        with patch(self._locate, return_value=(0, 0)):
            self.assertTrue(self.lib.does_exist('my_picture'))

        run_on_failure = MagicMock()
        with patch(self._locate, side_effect=ImageNotFoundException('')), \
             patch.object(self.lib, '_run_on_failure', run_on_failure):
            self.assertFalse(self.lib.does_exist('my_picture'))
            self.assertEquals(len(run_on_failure.mock_calls), 0)

    def test_wait_for_happy_path(self):
        from ImageHorizonLibrary import InvalidImageException
        run_on_failure = MagicMock()

        with patch(self._locate, return_value=(0, 0)), \
             patch.object(self.lib, '_run_on_failure', run_on_failure):
            self.lib.wait_for('my_picture', timeout=1)
            self.assertEquals(len(run_on_failure.mock_calls), 0)

    def test_wait_for_negative_path(self):
        from ImageHorizonLibrary import InvalidImageException
        run_on_failure = MagicMock()

        with self.assertRaises(InvalidImageException), \
             patch(self.locate, side_effect=InvalidImageException('')), \
             patch.object(self.lib, '_run_on_failure', run_on_failure):

            start = time.time()
            self.lib.wait_for('notfound', timeout=u'1')
            stop = time.time()

            run_on_failure.assert_called_once_with()
            # check that timeout given as string works and it does not use
            # default timeout
            self.assertLess(stop-start, 10)

    def _verify_path_works(self, image_name, expected):
        self.lib.locate(image_name)
        expected_path = path_join(TESTIMG_DIR, expected)
        self.mock.locateCenterOnScreen.assert_called_once_with(expected_path)
        self.mock.reset_mock()

    def test_locate(self):
        from ImageHorizonLibrary import InvalidImageException

        for image_name in ('my_picture.png', 'my picture.png', 'MY PICTURE',
                           'mY_PiCtURe'):
            self._verify_path_works(image_name, 'my_picture.png')

        self.mock.locateCenterOnScreen.return_value = None
        run_on_failure = MagicMock()
        with self.assertRaises(InvalidImageException), \
             patch.object(self.lib, '_run_on_failure', run_on_failure):
            self.lib.locate('nonexistent')
            run_on_failure.assert_called_once_with()

    def test_locate_with_valid_reference_folder(self):
        for ref, img in (('reference_images', 'my_picture.png'),
                         (u'./reference_images', u'my picture.png'),
                         ('../../tests/utest/reference_images', 'MY PICTURE')):

            self.lib.set_reference_folder(path_join(CURDIR, ref))
            self._verify_path_works(img, 'my_picture.png')

        self.lib.reference_folder = path_join(CURDIR, 'symbolic_link')
        self.lib.locate('mY_PiCtURe')
        expected_path = path_join(CURDIR, 'symbolic_link', 'my_picture.png')
        self.mock.locateCenterOnScreen.assert_called_once_with(expected_path)
        self.mock.reset_mock()

        self.lib.reference_folder = path_join(CURDIR, u'rëförence_imägës')
        self.lib.locate(u'mŸ PäKSÖR')
        expected_path = path_join(CURDIR, u'rëförence_imägës',
                                  u'mÿ_päksör.png').encode('utf-8')
        self.mock.locateCenterOnScreen.assert_called_once_with(expected_path)
        self.mock.reset_mock()

    def test_locate_with_invalid_reference_folder(self):
        from ImageHorizonLibrary import ReferenceFolderException

        for invalid_folder in (None, 123, 'nonexistent', u'nönëxistänt'):
            self.lib.reference_folder = invalid_folder
            with self.assertRaises(ReferenceFolderException):
                self.lib.locate('my_picture')

        if not self.lib.is_windows:
            self.lib.reference_folder = TESTIMG_DIR.replace('/', '\\')
            with self.assertRaises(ReferenceFolderException):
                self.lib.locate('my_picture')

    def test_locate_with_invalid_image_name(self):
        from ImageHorizonLibrary import InvalidImageException

        for invalid_image_name in (None, 123, 1.2, True, self.lib.__class__()):
            with self.assertRaises(InvalidImageException):
                self.lib.locate(invalid_image_name)
    def setUp(self):
        self.patcher = patch.dict("sys.modules", {"pyautogui": MagicMock()})
        self.patcher.start()
        from ImageHorizonLibrary import ImageHorizonLibrary

        self.lib = ImageHorizonLibrary()
class TestOperatingSystem(TestCase):
    def setUp(self):
        self.patcher = patch.dict("sys.modules", {"pyautogui": MagicMock()})
        self.patcher.start()
        from ImageHorizonLibrary import ImageHorizonLibrary

        self.lib = ImageHorizonLibrary()

    def tearDown(self):
        self.patcher.stop()

    def test_launch_application(self):
        mock = MagicMock()
        with patch("subprocess.Popen", autospec=True, return_value=mock) as mock_popen:
            self.lib.launch_application("application -argument")
            mock_popen.assert_called_once_with(["application", "-argument"])
            self.assertDictEqual(self.lib.open_applications, {"0": mock})
            mock_popen.reset_mock()

            self.lib.launch_application("application -a -r --gu ment", "MY ALIAS")
            mock_popen.assert_called_once_with(["application", "-a", "-r", "--gu", "ment"])
            self.assertDictEqual(self.lib.open_applications, {"0": mock, "MY ALIAS": mock})
            mock_popen.reset_mock()

            self.lib.launch_application("application", "ÛMLÄYT ÖLIAS")
            mock_popen.assert_called_once_with(["application"])
            self.assertDictEqual(self.lib.open_applications, {"0": mock, "MY ALIAS": mock, "ÛMLÄYT ÖLIAS": mock})

    def test_terminate_application_when_application_was_not_launched(self):
        from ImageHorizonLibrary import OSException

        with self.assertRaises(OSException):
            self.lib.terminate_application()

    def test_terminate_application(self):
        from ImageHorizonLibrary import OSException

        mock = MagicMock()
        with patch("subprocess.Popen", autospec=True, return_value=mock) as mock_popen:
            for args in (("app1",), ("app2", "my alias"), ("app3", "youalias"), ("app4", "shelias")):
                self.lib.launch_application(*args)
            self.assertDictEqual(
                self.lib.open_applications, {"0": mock, "my alias": mock, "youalias": mock, "shelias": mock}
            )

            self.lib.terminate_application()
            self.assertDictEqual(self.lib.open_applications, {"0": mock, "my alias": mock, "youalias": mock})
            self.lib.terminate_application("my alias")
            self.assertDictEqual(self.lib.open_applications, {"0": mock, "youalias": mock})
            self.lib.terminate_application("0")
            self.assertDictEqual(self.lib.open_applications, {"youalias": mock})

            self.lib.terminate_application()
            self.assertDictEqual(self.lib.open_applications, {})

            with self.assertRaises(OSException):
                self.lib.terminate_application("nonexistent alias")
 def setUp(self):
     self.mock = MagicMock()
     self.patcher = patch.dict('sys.modules', {'pyautogui': self.mock})
     self.patcher.start()
     from ImageHorizonLibrary import ImageHorizonLibrary, MouseException
     self.lib = ImageHorizonLibrary()
class TestMouse(TestCase):
    def setUp(self):
        self.mock = MagicMock()
        self.patcher = patch.dict('sys.modules', {'pyautogui': self.mock})
        self.patcher.start()
        from ImageHorizonLibrary import ImageHorizonLibrary, MouseException
        self.lib = ImageHorizonLibrary()

    def tearDown(self):
        self.mock.reset_mock()
        self.patcher.stop()

    def test_all_directional_clicks(self):
        for direction in ['above', 'below', 'left', 'right']:
            fn = getattr(self.lib, 'click_to_the_%s_of' % direction)
            fn((0, 0), '10')
        self.assertEqual(self.mock.click.mock_calls, [
            call(0, -10, button='left', interval=0.0, clicks=1),
            call(0, 10, button='left', interval=0.0, clicks=1),
            call(-10, 0, button='left', interval=0.0, clicks=1),
            call(10, 0, button='left', interval=0.0, clicks=1)
        ])

    def _verify_directional_clicks_fail(self, direction, kwargs):
        from ImageHorizonLibrary import MouseException

        fn = getattr(self.lib, 'click_to_the_%s_of' % direction)
        with self.assertRaises(MouseException):
            fn((0, 0), 10, **kwargs)
        self.assertEqual(self.mock.click.mock_calls, [])

    def test_arguments_in_directional_clicks(self):
        self.lib.click_to_the_above_of((0, 0),
                                       10,
                                       clicks='2',
                                       button='middle',
                                       interval='1.2')
        self.assertEqual(
            self.mock.click.mock_calls,
            [call(0, -10, button='middle', interval=1.2, clicks=2)])
        self.mock.reset_mock()
        for args in (('below', {
                'clicks': 'notvalid'
        }), ('right', {
                'button': 'notvalid'
        }), ('left', {
                'interval': 'notvalid'
        })):
            self._verify_directional_clicks_fail(*args)

    def _verify_move_to_fails(self, *args):
        from ImageHorizonLibrary import MouseException
        with self.assertRaises(MouseException):
            self.lib.move_to(*args)

    def test_move_to(self):
        for args in [(1, 2), ((1, 2), ), ('1', '2'), (('1', '2'), )]:
            self.lib.move_to(*args)
            self.assertEqual(self.mock.moveTo.mock_calls, [call(1, 2)])
            self.mock.reset_mock()

        for args in [(1, ), (1, 2, 3), ('1', 'lollerskates'),
                     (('1', 'lollerskates'), )]:
            self._verify_move_to_fails(*args)

    def test_mouse_down(self):
        for args in [tuple(), ('right', )]:
            self.lib.mouse_down(*args)
        self.assertEqual(
            self.mock.mouseDown.mock_calls,
            [call(button='left'), call(button='right')])

    def test_mouse_up(self):
        for args in [tuple(), ('right', )]:
            self.lib.mouse_up(*args)
        self.assertEqual(
            self.mock.mouseUp.mock_calls,
            [call(button='left'), call(button='right')])
class TestMainClass(TestCase):
    def setUp(self):
        self.pyautogui_mock = MagicMock()
        self.Tk_mock = MagicMock()
        self.clipboard_mock = MagicMock()
        self.clipboard_mock.clipboard_get.return_value = 'copied text'
        self.Tk_mock.Tk.return_value = self.clipboard_mock
        self.patcher = patch.dict('sys.modules',
                                  {'pyautogui': self.pyautogui_mock,
                                   'Tkinter': self.Tk_mock})
        self.patcher.start()
        from ImageHorizonLibrary import ImageHorizonLibrary
        self.lib = ImageHorizonLibrary()

    def tearDown(self):
        for mock in (self.Tk_mock, self.clipboard_mock, self.pyautogui_mock):
            mock.reset_mock()
        self.patcher.stop()

    def test_copy(self):
        from ImageHorizonLibrary import ImageHorizonLibrary

        with patch.object(ImageHorizonLibrary, '_press') as press_mock:
            retval = self.lib.copy()
            self.assertEquals(retval, 'copied text')
            self.clipboard_mock.clipboard_get.assert_called_once_with()
            if self.lib.is_mac:
                press_mock.assert_called_once_with('Key.command', 'c')
            else:
                press_mock.assert_called_once_with('Key.ctrl', 'c')

    def test_clipboard_content(self):
        retval = self.lib.get_clipboard_content()
        self.assertEquals(retval, 'copied text')
        self.clipboard_mock.clipboard_get.assert_called_once_with()

    def test_alert(self):
        self.lib.pause()
        self.pyautogui_mock.alert.assert_called_once_with(
            button='Continue', text='Test execution paused.', title='Pause')

    def _get_cmd(self, jython, path):
        cmd = ('JYTHONPATH={path} {jython} -c '
               '"from ImageHorizonLibrary import ImageHorizonLibrary"')
        return cmd.format(jython=jython, path=path)

    def test_importing_fails_on_java(self):
        # This test checks that importing fails when any of the dependencies
        # are not installed or, at least, importing Tkinter fails because
        # it's not supported on Jython.
        if 'JYTHON_HOME' not in os.environ:
            self.skipTest('%s() was not run because JYTHON_HOME '
                          'was not set.' % self._testMethodName)
        jython_cmd = path_join(os.environ['JYTHON_HOME'], 'bin', 'jython')
        cmd = self._get_cmd(jython_cmd, SRCDIR)
        p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
        _, stderr = p.communicate()
        self.assertNotEqual(stderr, '')

    def test_set_reference_folder(self):
        self.assertEquals(self.lib.reference_folder, None)
        self.lib.set_reference_folder('/test/path')
        self.assertEquals(self.lib.reference_folder, '/test/path')

    def test_set_screenshot_folder(self):
        self.assertEquals(self.lib.screenshot_folder, None)
        self.lib.set_screenshot_folder('/test/path')
        self.assertEquals(self.lib.screenshot_folder, '/test/path')
class TestKeyboard(TestCase):
    def setUp(self):
        self.mock = MagicMock()
        self.mock.KEYBOARD_KEYS = KEYBOARD_KEYS
        self.patcher = patch.dict('sys.modules', {'pyautogui': self.mock})
        self.patcher.start()
        from ImageHorizonLibrary import ImageHorizonLibrary
        self.lib = ImageHorizonLibrary()

    def tearDown(self):
        self.mock.reset_mock()
        self.patcher.stop()

    def test_type_with_text(self):
        self.lib.type('hey you fool')
        self.mock.typewrite.assert_called_once_with('hey you fool')
        self.mock.reset_mock()

        self.lib.type('.')
        self.mock.press.assert_called_once_with('.')

    def test_type_with_umlauts(self):
        self.lib.type(u'öäöäü')
        self.mock.typewrite.assert_called_once_with(u'öäöäü')

    def test_type_with_text_and_keys(self):
        self.lib.type('I love you', 'Key.ENTER')
        self.mock.typewrite.assert_called_once_with('I love you')
        self.mock.press.assert_called_once_with('enter')

    def test_type_with_utf8_keys(self):
        self.lib.type(u'key.Tab')
        self.assertEquals(self.mock.typewrite.call_count, 0)
        self.mock.press.assert_called_once_with('tab')
        self.assertEquals(type(self.mock.press.call_args[0][0]),
                          type(str()))

    def test_type_with_keys_down(self):
        self.lib.type_with_keys_down('hello', 'key.shift')
        self.mock.keyDown.assert_called_once_with('shift')
        self.mock.typewrite.assert_called_once_with('hello')
        self.mock.keyUp.assert_called_once_with('shift')

    def test_type_with_keys_down_with_invalid_keys(self):
        from ImageHorizonLibrary import KeyboardException

        expected_msg = ('Invalid keyboard key "enter", valid keyboard keys '
                        'are:\n%r' % ', '.join(self.mock.KEYBOARD_KEYS))
        with self.assertRaises(KeyboardException) as cm:
            self.lib.type_with_keys_down('sometext', 'enter')
        self.assertEquals(cm.exception.message, expected_msg)

    def test_press_combination(self):
            self.lib.press_combination('Key.ctrl', 'A')
            self.mock.hotkey.assert_called_once_with('ctrl', 'a')
            self.mock.reset_mock()

            for key in self.mock.KEYBOARD_KEYS:
                self.lib.press_combination('Key.%s' % key)
                self.mock.hotkey.assert_called_once_with(key.lower())
                self.mock.reset_mock()
 def setUp(self):
     self.mock = MagicMock()
     self.patcher = patch.dict('sys.modules', {'pyautogui': self.mock})
     self.patcher.start()
     from ImageHorizonLibrary import ImageHorizonLibrary, MouseException
     self.lib = ImageHorizonLibrary()
class TestMouse(TestCase):

    def setUp(self):
        self.mock = MagicMock()
        self.patcher = patch.dict('sys.modules', {'pyautogui': self.mock})
        self.patcher.start()
        from ImageHorizonLibrary import ImageHorizonLibrary, MouseException
        self.lib = ImageHorizonLibrary()

    def tearDown(self):
        self.mock.reset_mock()
        self.patcher.stop()

    def test_all_directional_clicks(self):
        for direction in ['above', 'below', 'left', 'right']:
            fn = getattr(self.lib, 'click_to_the_%s_of' % direction)
            fn((0, 0), '10')
        self.assertEquals(self.mock.click.mock_calls,
                          [call(0, -10, button='left', interval=0.0, clicks=1),
                           call(0, 10, button='left', interval=0.0, clicks=1),
                           call(-10, 0, button='left', interval=0.0, clicks=1),
                           call(10, 0, button='left', interval=0.0, clicks=1)])

    def _verify_directional_clicks_fail(self, direction, kwargs):
        from ImageHorizonLibrary import MouseException

        fn = getattr(self.lib, 'click_to_the_%s_of' % direction)
        with self.assertRaises(MouseException):
            fn((0, 0), 10, **kwargs)
        self.assertEquals(self.mock.click.mock_calls, [])

    def test_arguments_in_directional_clicks(self):
        self.lib.click_to_the_above_of((0, 0), 10, clicks=u'2',
                                       button=u'middle', interval=u'1.2')
        self.assertEquals(self.mock.click.mock_calls, [call(0, -10,
                                                            button='middle',
                                                            interval=1.2,
                                                            clicks=2)])
        self.mock.reset_mock()
        for args in (('below', {'clicks': 'notvalid'}),
                     ('right', {'button': 'notvalid'}),
                     ('left',  {'interval': 'notvalid'})):
            self._verify_directional_clicks_fail(*args)

    def _verify_move_to_fails(self, *args):
        from ImageHorizonLibrary import MouseException
        with self.assertRaises(MouseException):
            self.lib.move_to(*args)

    def test_move_to(self):
        for args in [(1, 2), ((1, 2),), ('1', u'2'), ((u'1', '2'),)]:
            self.lib.move_to(*args)
            self.assertEquals(self.mock.moveTo.mock_calls, [call(1, 2)])
            self.mock.reset_mock()

        for args in [(1,),
                     (1, 2, 3),
                     (u'1', u'lollerskates'),
                     ((u'1', u'lollerskates'),)]:
            self._verify_move_to_fails(*args)

    def test_mouse_down(self):
        for args in [tuple(), ('right',)]:
            self.lib.mouse_down(*args)
        self.assertEquals(self.mock.mouseDown.mock_calls, [call('left'), call('right')])

    def test_mouse_up(self):
        for args in [tuple(), ('right',)]:
            self.lib.mouse_up(*args)
        self.assertEquals(self.mock.mouseUp.mock_calls, [call('left'), call('right')])