class TestProjectPull(unittest.TestCase):
    """Test bits & pieces of the pull method."""

    def setUp(self):
        super(TestProjectPull, self).setUp()
        self.p = Project(init=False)
        self.p.minimum_perc = None
        self.p.resource = "resource"
        self.p.host = 'foo'
        self.p.project_slug = 'foo'
        self.p.resource_slug = 'foo'
        self.stats = {
            'en': {
                'completed': '100%', 'last_update': '2011-11-01 15:00:00',
            }, 'el': {
                'completed': '60%', 'last_update': '2011-11-01 15:00:00',
            }, 'pt': {
                'completed': '70%', 'last_update': '2011-11-01 15:00:00',
            },
        }
        self.langs = list(self.stats.keys())
        self.files = dict(list(zip(self.langs, itertools.repeat(None))))
        self.details = {'available_languages': []}
        for lang in self.langs:
            self.details['available_languages'].append({'code': lang})
        self.slang = 'en'
        self.lang_map = Flipdict()

    def test_new_translations(self):
        """Test finding new transaltions to add."""
        with patch.object(self.p, 'do_url_request') as resource_mock:
            resource_mock.return_value = json.dumps(self.details), "utf-8"
            files_keys = self.langs
            new_trans = self.p._new_translations_to_add
            for force in [True, False]:
                res = new_trans(
                    self.files, self.slang, self.lang_map, self.stats, force
                )
                self.assertEqual(res, set([]))

            with patch.object(self.p,
                              '_should_add_translation') as filter_mock:
                filter_mock.return_value = True
                for force in [True, False]:
                    res = new_trans(
                        {'el': None}, self.slang, self.lang_map, self.stats,
                        force
                    )
                    self.assertEqual(res, set(['pt']))
                for force in [True, False]:
                    res = new_trans(
                        {}, self.slang, self.lang_map, self.stats, force
                    )
                    self.assertEqual(res, set(['el', 'pt']))

                files = {}
                files['pt_PT'] = None
                lang_map = {'pt': 'pt_PT'}
                for force in [True, False]:
                    res = new_trans(
                        files, self.slang, lang_map, self.stats, force
                    )
                    self.assertEqual(res, set(['el']))

    def test_get_pseudo_file(self):
        slang = 'en'
        resource = 'adriana'
        file_filter = 'adriana/<lang>.po'

        pseudo_file = self.p._get_pseudo_file(slang, resource, file_filter)

        self.assertEqual(pseudo_file, 'adriana/en_pseudo.po')

    def test_languages_to_pull_empty_initial_list(self):
        """Test determining the languages to pull, when the initial
        list is empty.
        """
        languages = []
        force = False

        res = self.p._languages_to_pull(
            languages, self.files, self.lang_map, self.stats, force
        )
        existing = res[0]
        new = res[1]
        self.assertEqual(existing, set(['el', 'en', 'pt']))
        self.assertFalse(new)

        del self.files['el']
        self.files['el-gr'] = None
        self.lang_map['el'] = 'el-gr'
        res = self.p._languages_to_pull(
            languages, self.files, self.lang_map, self.stats, force
        )
        existing = res[0]
        new = res[1]
        self.assertEqual(existing, set(['el', 'en', 'pt']))
        self.assertFalse(new)

    def test_languages_to_pull_with_initial_list(self):
        """Test determining the languages to pull, then there is a
        language selection from the user.
        """
        languages = ['el', 'en']
        self.lang_map['el'] = 'el-gr'
        del self.files['el']
        self.files['el-gr'] = None
        force = False

        with patch.object(self.p, '_should_add_translation') as mock:
            mock.return_value = True
            res = self.p._languages_to_pull(
                languages, self.files, self.lang_map, self.stats, force
            )
            existing = res[0]
            new = res[1]
            self.assertEqual(existing, set(['en', 'el-gr', ]))
            self.assertFalse(new)

            mock.return_value = False
            res = self.p._languages_to_pull(
                languages, self.files, self.lang_map, self.stats, force
            )
            existing = res[0]
            new = res[1]
            self.assertEqual(existing, set(['en', 'el-gr', ]))
            self.assertFalse(new)

            del self.files['el-gr']
            mock.return_value = True
            res = self.p._languages_to_pull(
                languages, self.files, self.lang_map, self.stats, force
            )
            existing = res[0]
            new = res[1]
            self.assertEqual(existing, set(['en', ]))
            self.assertEqual(new, set(['el', ]))

            mock.return_value = False
            res = self.p._languages_to_pull(
                languages, self.files, self.lang_map, self.stats, force
            )
            existing = res[0]
            new = res[1]
            self.assertEqual(existing, set(['en', ]))
            self.assertEqual(new, set([]))

    def test_in_combination_with_force_option(self):
        """Test the minumum-perc option along with -f."""
        with patch.object(self.p, 'get_resource_option') as mock:
            mock.return_value = 70

            res = self.p._should_download('de', self.stats, None, False)
            self.assertEqual(res, False)
            res = self.p._should_download('el', self.stats, None, False)
            self.assertEqual(res, False)
            res = self.p._should_download('el', self.stats, None, True)
            self.assertEqual(res, False)
            res = self.p._should_download('en', self.stats, None, False)
            self.assertEqual(res, True)
            res = self.p._should_download('en', self.stats, None, True)
            self.assertEqual(res, True)

            with patch.object(self.p, '_remote_is_newer') as local_file_mock:
                local_file_mock = False
                res = self.p._should_download('pt', self.stats, None, False)
                self.assertEqual(res, True)
                res = self.p._should_download('pt', self.stats, None, True)
                self.assertEqual(res, True)
class TestProjectPull(unittest.TestCase):
    """Test bits & pieces of the pull method."""

    def setUp(self):
        super(TestProjectPull, self).setUp()
        self.p = Project(init=False)
        self.p.minimum_perc = None
        self.p.resource = "resource"
        self.p.host = 'foo'
        self.p.project_slug = 'foo'
        self.p.resource_slug = 'foo'
        self.stats = {
            'en': {
                'completed': '100%', 'last_update': '2011-11-01 15:00:00',
            }, 'el': {
                'completed': '60%', 'last_update': '2011-11-01 15:00:00',
            }, 'pt': {
                'completed': '70%', 'last_update': '2011-11-01 15:00:00',
            },
        }
        self.langs = self.stats.keys()
        self.files = dict(zip(self.langs, itertools.repeat(None)))
        self.details = {'available_languages': []}
        for lang in self.langs:
            self.details['available_languages'].append({'code': lang})
        self.slang = 'en'
        self.lang_map = Flipdict()

    def test_new_translations(self):
        """Test finding new transaltions to add."""
        with patch.object(self.p, 'do_url_request') as resource_mock:
            resource_mock.return_value = json.dumps(self.details)
            files_keys = self.langs
            new_trans = self.p._new_translations_to_add
            for force in [True, False]:
                res = new_trans(
                    self.files, self.slang, self.lang_map, self.stats, force
                )
                self.assertEquals(res, set([]))

            with patch.object(self.p, '_should_add_translation') as filter_mock:
                filter_mock.return_value = True
                for force in [True, False]:
                    res = new_trans(
                        {'el': None}, self.slang, self.lang_map, self.stats, force
                    )
                    self.assertEquals(res, set(['pt']))
                for force in [True, False]:
                    res = new_trans(
                        {}, self.slang, self.lang_map, self.stats, force
                    )
                    self.assertEquals(res, set(['el', 'pt']))

                files = {}
                files['pt_PT'] = None
                lang_map = {'pt': 'pt_PT'}
                for force in [True, False]:
                    res = new_trans(
                        files, self.slang, lang_map, self.stats, force
                    )
                    self.assertEquals(res, set(['el']))

    def test_languages_to_pull_empty_initial_list(self):
        """Test determining the languages to pull, when the initial
        list is empty.
        """
        languages = []
        force = False

        res = self.p._languages_to_pull(
            languages, self.files, self.lang_map, self.stats, force
        )
        existing = res[0]
        new = res[1]
        self.assertEquals(existing, set(['el', 'en', 'pt']))
        self.assertFalse(new)

        del self.files['el']
        self.files['el-gr'] = None
        self.lang_map['el'] = 'el-gr'
        res = self.p._languages_to_pull(
            languages, self.files, self.lang_map, self.stats, force
        )
        existing = res[0]
        new = res[1]
        self.assertEquals(existing, set(['el', 'en', 'pt']))
        self.assertFalse(new)

    def test_languages_to_pull_with_initial_list(self):
        """Test determining the languages to pull, then there is a
        language selection from the user.
        """
        languages = ['el', 'en']
        self.lang_map['el'] = 'el-gr'
        del self.files['el']
        self.files['el-gr'] = None
        force = False

        with patch.object(self.p, '_should_add_translation') as mock:
            mock.return_value = True
            res = self.p._languages_to_pull(
                languages, self.files, self.lang_map, self.stats, force
            )
            existing = res[0]
            new = res[1]
            self.assertEquals(existing, set(['en', 'el-gr', ]))
            self.assertFalse(new)

            mock.return_value = False
            res = self.p._languages_to_pull(
                languages, self.files, self.lang_map, self.stats, force
            )
            existing = res[0]
            new = res[1]
            self.assertEquals(existing, set(['en', 'el-gr', ]))
            self.assertFalse(new)

            del self.files['el-gr']
            mock.return_value = True
            res = self.p._languages_to_pull(
                languages, self.files, self.lang_map, self.stats, force
            )
            existing = res[0]
            new = res[1]
            self.assertEquals(existing, set(['en', ]))
            self.assertEquals(new, set(['el', ]))

            mock.return_value = False
            res = self.p._languages_to_pull(
                languages, self.files, self.lang_map, self.stats, force
            )
            existing = res[0]
            new = res[1]
            self.assertEquals(existing, set(['en', ]))
            self.assertEquals(new, set([]))

    def test_in_combination_with_force_option(self):
        """Test the minumum-perc option along with -f."""
        with patch.object(self.p, 'get_resource_option') as mock:
            mock.return_value = 70

            res = self.p._should_download('de', self.stats, None, False)
            self.assertEquals(res, False)
            res = self.p._should_download('el', self.stats, None, False)
            self.assertEquals(res, False)
            res = self.p._should_download('el', self.stats, None, True)
            self.assertEquals(res, False)
            res = self.p._should_download('en', self.stats, None, False)
            self.assertEquals(res, True)
            res = self.p._should_download('en', self.stats, None, True)
            self.assertEquals(res, True)

            with patch.object(self.p, '_remote_is_newer') as local_file_mock:
                local_file_mock = False
                res = self.p._should_download('pt', self.stats, None, False)
                self.assertEquals(res, True)
                res = self.p._should_download('pt', self.stats, None, True)
                self.assertEquals(res, True)
class TestProjectPull(unittest.TestCase):
    """Test bits & pieces of the pull method."""

    def setUp(self):
        super(TestProjectPull, self).setUp()
        self.p = Project(init=False)
        self.p.minimum_perc = None
        self.p.resource = "resource"
        self.p.host = 'foo'
        self.p.project_slug = 'foo'
        self.p.resource_slug = 'foo'
        self.stats = {
            'en': {
                'completed': '100%', 'last_update': '2011-11-01 15:00:00',
            }, 'el': {
                'completed': '60%', 'last_update': '2011-11-01 15:00:00',
            }, 'pt': {
                'completed': '70%', 'last_update': '2011-11-01 15:00:00',
            },
        }
        self.langs = list(self.stats.keys())
        self.files = dict(list(zip(self.langs, itertools.repeat(None))))
        self.details = {'available_languages': []}
        for lang in self.langs:
            self.details['available_languages'].append({'code': lang})
        self.slang = 'en'
        self.lang_map = Flipdict()

    def test_new_translations(self):
        """Test finding new translations to add."""
        with patch.object(self.p, 'do_url_request') as resource_mock:
            resource_mock.return_value = json.dumps(self.details), "utf-8"
            new_trans = self.p._new_translations_to_add
            for force in [True, False]:
                res = new_trans(
                    self.files, self.slang, self.lang_map, self.stats, force
                )
                self.assertEqual(res, set([]))

            with patch.object(self.p,
                              '_should_add_translation') as filter_mock:
                filter_mock.return_value = True
                for force in [True, False]:
                    res = new_trans(
                        {'el': None}, self.slang, self.lang_map, self.stats,
                        force
                    )
                    self.assertEqual(res, set(['pt']))
                for force in [True, False]:
                    res = new_trans(
                        {}, self.slang, self.lang_map, self.stats, force
                    )
                    self.assertEqual(res, set(['el', 'pt']))

                files = {}
                files['pt_PT'] = None
                lang_map = {'pt': 'pt_PT'}
                for force in [True, False]:
                    res = new_trans(
                        files, self.slang, lang_map, self.stats, force
                    )
                    self.assertEqual(res, set(['el']))

    def test_get_pseudo_file(self):
        slang = 'en'
        resource = 'adriana'
        file_filter = 'adriana/<lang>.po'

        pseudo_file = self.p._get_pseudo_file(slang, resource, file_filter)

        self.assertEqual(pseudo_file, 'adriana/en_pseudo.po')

    def test_languages_to_pull_empty_initial_list(self):
        """Test determining the languages to pull, when the initial
        list is empty.
        """
        languages = []
        force = False

        res = self.p._languages_to_pull(
            languages, self.files, self.lang_map, self.stats, force
        )
        existing = res[0]
        new = res[1]
        self.assertEqual(existing, set(['el', 'en', 'pt']))
        self.assertFalse(new)

        del self.files['el']
        self.files['el-gr'] = None
        self.lang_map['el'] = 'el-gr'
        res = self.p._languages_to_pull(
            languages, self.files, self.lang_map, self.stats, force
        )
        existing = res[0]
        new = res[1]
        self.assertEqual(existing, set(['el', 'en', 'pt']))
        self.assertFalse(new)

    def test_languages_to_pull_with_initial_list(self):
        """Test determining the languages to pull, then there is a
        language selection from the user.
        """
        languages = ['el', 'en']
        self.lang_map['el'] = 'el-gr'
        del self.files['el']
        self.files['el-gr'] = None
        force = False

        with patch.object(self.p, '_should_add_translation') as mock:
            mock.return_value = True
            res = self.p._languages_to_pull(
                languages, self.files, self.lang_map, self.stats, force
            )
            existing = res[0]
            new = res[1]
            self.assertEqual(existing, set(['en', 'el-gr', ]))
            self.assertFalse(new)

            mock.return_value = False
            res = self.p._languages_to_pull(
                languages, self.files, self.lang_map, self.stats, force
            )
            existing = res[0]
            new = res[1]
            self.assertEqual(existing, set(['en', 'el-gr', ]))
            self.assertFalse(new)

            del self.files['el-gr']
            mock.return_value = True
            res = self.p._languages_to_pull(
                languages, self.files, self.lang_map, self.stats, force
            )
            existing = res[0]
            new = res[1]
            self.assertEqual(existing, set(['en', ]))
            self.assertEqual(new, set(['el', ]))

            mock.return_value = False
            res = self.p._languages_to_pull(
                languages, self.files, self.lang_map, self.stats, force
            )
            existing = res[0]
            new = res[1]
            self.assertEqual(existing, set(['en', ]))
            self.assertEqual(new, set([]))

    def test_in_combination_with_force_option(self):
        """Test the minimum-perc option along with -f."""
        with patch.object(self.p, 'get_resource_option') as mock:
            mock.return_value = 70

            res = self.p._should_download('de', self.stats, None, False)
            self.assertEqual(res, False)
            res = self.p._should_download('el', self.stats, None, False)
            self.assertEqual(res, False)
            res = self.p._should_download('el', self.stats, None, True)
            self.assertEqual(res, False)
            res = self.p._should_download('en', self.stats, None, False)
            self.assertEqual(res, True)
            res = self.p._should_download('en', self.stats, None, True)
            self.assertEqual(res, True)

            with patch.object(self.p, '_remote_is_newer'):
                res = self.p._should_download('pt', self.stats, None, False)
                self.assertEqual(res, True)
                res = self.p._should_download('pt', self.stats, None, True)
                self.assertEqual(res, True)

    def test_get_url_by_pull_mode(self):
        self.assertEqual(
            'pull_sourceastranslation_file',
            self.p._get_url_by_pull_mode(mode='sourceastranslation')
        )
        self.assertEqual(
            DEFAULT_PULL_URL,
            self.p._get_url_by_pull_mode(mode='invalid mode')
        )
        self.assertEqual(
            DEFAULT_PULL_URL,
            self.p._get_url_by_pull_mode(mode=None)
        )

    def fixture_mocked_project(func):
        """A mock object with main os and http operations mocked"""
        @wraps(func)
        def wrapper(*args, **kwargs):
            app_dir = dirname(modules['txclib'].__file__)
            config_file = app_dir + "/../tests/templates/config"
            transifex_file = app_dir + "/../tests/templates/transifexrc"
            with patch("txclib.utils.encode_args") as mock_encode_args, \
                patch("txclib.utils.determine_charset")\
                    as mock_determine_charset, \
                    patch("txclib.utils.get_transifex_file",
                          return_value=transifex_file) \
                    as mock_get_transifex_file, \
                    patch("txclib.utils.get_config_file_path",
                          return_value=config_file) \
                    as mock_get_config_file_path, \
                    patch("txclib.utils.save_txrc_file") \
                    as mock_save_txrc_file, \
                    patch("txclib.project.Project._get_stats_for_resource") \
                    as mock_get_stats_for_resource:

                # Create fake https response
                def encode_args(*args, **kwargs):
                    struct = namedtuple("response", "data status close")
                    return struct(status=401, data="mock_response",
                                  close=Mock())
                mock_determine_charset.return_value = "utf-8"
                mock_encode_args.return_value = encode_args

                # Mock configuration files
                p = Project(init=False)
                p._init(path_to_tx=app_dir + "/../templates")

                kwargs['mock_project'] = p
                kwargs['mocks'] = {
                    'mock_determine_charset': mock_determine_charset,
                    "mock_encode_args": mock_encode_args,
                    "mock_get_config_file_path": mock_get_config_file_path,
                    "mock_get_stats_for_resource": mock_get_stats_for_resource,
                    "mock_get_transifex_file": mock_get_transifex_file,
                    "mock_save_txrc_file": mock_save_txrc_file
                }
                return func(*args, **kwargs)
        return wrapper

    @fixture_mocked_project
    @patch("txclib.project.logger.error")
    def test_pull_raises_authentication_exception(self, mock_logger, **kwargs):
        project = kwargs['mock_project']
        with self.assertRaises(AuthenticationError):
            project.pull()
            mock_logger.assert_called_once_with(
                Project.AUTHENTICATION_FAILED_MESSAGE)

    @fixture_mocked_project
    @patch('txclib.project.Project.do_url_request')
    def test_pull_with_branch_pulls_from_right_resource(self, m, **kwargs):
        m.return_value = ('{"i18n_type": "PO"}', '')
        project = kwargs['mock_project']
        project.pull(branch='somebranch')
        self.assertDictEqual(project.url_info, {
            'host': 'https://fake.com',
            'project': 'example',
            'resource': 'somebranch--enpo'
        })

    @fixture_mocked_project
    @patch('txclib.project.Project.do_url_request')
    def test_push_with_branch_pushes_to_right_resource(self, m, **kwargs):
        m.return_value = ('{"i18n_type": "PO"}', '')
        project = kwargs['mock_project']
        project.push(source=True, branch='somebranch')
        self.assertDictEqual(project.url_info, {
            'host': 'https://fake.com',
            'project': 'example',
            'resource': 'somebranch--enpo'
        })

    @fixture_mocked_project
    @patch('txclib.project.Project.do_url_request')
    def test_push_with_branch_weird_characters_are_handled(self, m, **kwargs):
        m.return_value = ('{"i18n_type": "PO"}', '')
        project = kwargs['mock_project']
        project.push(source=True, branch='some/b**r:a&n!ch')
        self.assertDictEqual(project.url_info, {
            'host': 'https://fake.com',
            'project': 'example',
            'resource': 'some-b-r-a-n-ch--enpo'
        })

    @fixture_mocked_project
    @patch("txclib.project.logger.error")
    def test_push_raises_authentication_exception(self, mock_logger, **kwargs):
        project = kwargs['mock_project']
        with self.assertRaises(AuthenticationError):
            project.push()

    @fixture_mocked_project
    @patch("txclib.project.logger.error")
    def test_delete_raises_authentication_exception(self, mock_logger,
                                                    **kwargs):
        project = kwargs['mock_project']
        with self.assertRaises(AuthenticationError):
            project.delete()

    @fixture_mocked_project
    @patch("txclib.project.logger.error")
    @patch("txclib.utils.make_request")
    def test_pull_raises_connection_exception(self, mock_request, mock_logger,
                                              **kwargs):
        """Test that all connection errors are properly handled."""
        project = kwargs["mock_project"]
        response = 502
        msg = "Failed with code %d" % response
        mock_request.side_effect = TXConnectionError(msg, code=response)
        with self.assertRaises(TXConnectionError):
            project.pull()

    @fixture_mocked_project
    @patch("txclib.project.logger.error")
    @patch("txclib.utils.make_request")
    def test_push_raises_connection_exception(self, mock_request, mock_logger,
                                              **kwargs):
        """Test that all connection errors are properly handled."""
        project = kwargs["mock_project"]
        response = 500
        msg = "Failed with code %d" % response
        mock_request.side_effect = TXConnectionError(msg, code=response)
        with self.assertRaises(TXConnectionError):
            project.push()

    @fixture_mocked_project
    @patch('txclib.utils.queue_request')
    @patch('txclib.utils.make_request')
    @patch('txclib.project.Project._resource_exists')
    def test_push_async(self, mock_exists, mock_request, mock_queue, **kwargs):
        mock_queue.return_value = None
        mock_request.return_value = ('{"i18n_type": "PO"}', '')
        mock_exists.return_value = True
        project = kwargs['mock_project']
        patch_open = ("builtins.open" if version_info.major > 2
                      else "__builtin__.open")
        with patch(patch_open, mock_open(read_data="")):
            project.push(source=True, parallel=True)
            self.assertEqual(mock_queue.call_count, 1)

            project.push(translations=True, parallel=True)
            self.assertEqual(mock_queue.call_count, 1)

            project.pull(parallel=True)
            self.assertEqual(mock_queue.call_count, 1)
class TestProjectPull(unittest.TestCase):
    """Test bits & pieces of the pull method."""
    def setUp(self):
        super(TestProjectPull, self).setUp()
        self.p = Project(init=False)
        self.p.minimum_perc = None
        self.p.resource = "resource"
        self.p.host = 'foo'
        self.p.project_slug = 'foo'
        self.p.resource_slug = 'foo'
        self.stats = {
            'en': {
                'completed': '100%',
                'last_update': '2011-11-01 15:00:00',
            },
            'el': {
                'completed': '60%',
                'last_update': '2011-11-01 15:00:00',
            },
            'pt': {
                'completed': '70%',
                'last_update': '2011-11-01 15:00:00',
            },
        }
        self.langs = list(self.stats.keys())
        self.files = dict(list(zip(self.langs, itertools.repeat(None))))
        self.details = {'available_languages': []}
        for lang in self.langs:
            self.details['available_languages'].append({'code': lang})
        self.slang = 'en'
        self.lang_map = Flipdict()

    def test_new_translations(self):
        """Test finding new transaltions to add."""
        with patch.object(self.p, 'do_url_request') as resource_mock:
            resource_mock.return_value = json.dumps(self.details), "utf-8"
            new_trans = self.p._new_translations_to_add
            for force in [True, False]:
                res = new_trans(self.files, self.slang, self.lang_map,
                                self.stats, force)
                self.assertEqual(res, set([]))

            with patch.object(self.p,
                              '_should_add_translation') as filter_mock:
                filter_mock.return_value = True
                for force in [True, False]:
                    res = new_trans({'el': None}, self.slang, self.lang_map,
                                    self.stats, force)
                    self.assertEqual(res, set(['pt']))
                for force in [True, False]:
                    res = new_trans({}, self.slang, self.lang_map, self.stats,
                                    force)
                    self.assertEqual(res, set(['el', 'pt']))

                files = {}
                files['pt_PT'] = None
                lang_map = {'pt': 'pt_PT'}
                for force in [True, False]:
                    res = new_trans(files, self.slang, lang_map, self.stats,
                                    force)
                    self.assertEqual(res, set(['el']))

    def test_get_pseudo_file(self):
        slang = 'en'
        resource = 'adriana'
        file_filter = 'adriana/<lang>.po'

        pseudo_file = self.p._get_pseudo_file(slang, resource, file_filter)

        self.assertEqual(pseudo_file, 'adriana/en_pseudo.po')

    def test_languages_to_pull_empty_initial_list(self):
        """Test determining the languages to pull, when the initial
        list is empty.
        """
        languages = []
        force = False

        res = self.p._languages_to_pull(languages, self.files, self.lang_map,
                                        self.stats, force)
        existing = res[0]
        new = res[1]
        self.assertEqual(existing, set(['el', 'en', 'pt']))
        self.assertFalse(new)

        del self.files['el']
        self.files['el-gr'] = None
        self.lang_map['el'] = 'el-gr'
        res = self.p._languages_to_pull(languages, self.files, self.lang_map,
                                        self.stats, force)
        existing = res[0]
        new = res[1]
        self.assertEqual(existing, set(['el', 'en', 'pt']))
        self.assertFalse(new)

    def test_languages_to_pull_with_initial_list(self):
        """Test determining the languages to pull, then there is a
        language selection from the user.
        """
        languages = ['el', 'en']
        self.lang_map['el'] = 'el-gr'
        del self.files['el']
        self.files['el-gr'] = None
        force = False

        with patch.object(self.p, '_should_add_translation') as mock:
            mock.return_value = True
            res = self.p._languages_to_pull(languages, self.files,
                                            self.lang_map, self.stats, force)
            existing = res[0]
            new = res[1]
            self.assertEqual(existing, set([
                'en',
                'el-gr',
            ]))
            self.assertFalse(new)

            mock.return_value = False
            res = self.p._languages_to_pull(languages, self.files,
                                            self.lang_map, self.stats, force)
            existing = res[0]
            new = res[1]
            self.assertEqual(existing, set([
                'en',
                'el-gr',
            ]))
            self.assertFalse(new)

            del self.files['el-gr']
            mock.return_value = True
            res = self.p._languages_to_pull(languages, self.files,
                                            self.lang_map, self.stats, force)
            existing = res[0]
            new = res[1]
            self.assertEqual(existing, set([
                'en',
            ]))
            self.assertEqual(new, set([
                'el',
            ]))

            mock.return_value = False
            res = self.p._languages_to_pull(languages, self.files,
                                            self.lang_map, self.stats, force)
            existing = res[0]
            new = res[1]
            self.assertEqual(existing, set([
                'en',
            ]))
            self.assertEqual(new, set([]))

    def test_in_combination_with_force_option(self):
        """Test the minumum-perc option along with -f."""
        with patch.object(self.p, 'get_resource_option') as mock:
            mock.return_value = 70

            res = self.p._should_download('de', self.stats, None, False)
            self.assertEqual(res, False)
            res = self.p._should_download('el', self.stats, None, False)
            self.assertEqual(res, False)
            res = self.p._should_download('el', self.stats, None, True)
            self.assertEqual(res, False)
            res = self.p._should_download('en', self.stats, None, False)
            self.assertEqual(res, True)
            res = self.p._should_download('en', self.stats, None, True)
            self.assertEqual(res, True)

            with patch.object(self.p, '_remote_is_newer'):
                res = self.p._should_download('pt', self.stats, None, False)
                self.assertEqual(res, True)
                res = self.p._should_download('pt', self.stats, None, True)
                self.assertEqual(res, True)

    def test_get_url_by_pull_mode(self):
        self.assertEqual(
            'pull_sourceastranslation_file',
            self.p._get_url_by_pull_mode(mode='sourceastranslation'))
        self.assertEqual(DEFAULT_PULL_URL,
                         self.p._get_url_by_pull_mode(mode='invalid mode'))
        self.assertEqual(DEFAULT_PULL_URL,
                         self.p._get_url_by_pull_mode(mode=None))

    def fixture_mocked_project(func):
        """A mock object with main os and http operations mocked"""
        @wraps(func)
        def wrapper(*args, **kwargs):
            app_dir = dirname(modules['txclib'].__file__)
            config_file = app_dir + "/../tests/templates/config"
            transifex_file = app_dir + "/../tests/templates/transifexrc"
            with patch("txclib.utils.encode_args") as mock_encode_args, \
                patch("txclib.utils.determine_charset")\
                    as mock_determine_charset, \
                    patch("txclib.utils.get_transifex_file",
                          return_value=transifex_file) \
                    as mock_get_transifex_file, \
                    patch("txclib.utils.get_config_file_path",
                          return_value=config_file) \
                    as mock_get_config_file_path, \
                    patch("txclib.utils.save_txrc_file") \
                    as mock_save_txrc_file, \
                    patch("txclib.project.Project._get_stats_for_resource") \
                    as mock_get_stats_for_resource:

                # Create fake https response
                def encode_args(*args, **kwargs):
                    struct = namedtuple("response", "data status close")
                    return struct(status=401,
                                  data="mock_response",
                                  close=Mock())

                mock_determine_charset.return_value = "utf-8"
                mock_encode_args.return_value = encode_args

                # Mock configuration files
                p = Project(init=False)
                p._init(path_to_tx=app_dir + "/../templates")

                kwargs['mock_project'] = p
                kwargs['mocks'] = {
                    'mock_determine_charset': mock_determine_charset,
                    "mock_encode_args": mock_encode_args,
                    "mock_get_config_file_path": mock_get_config_file_path,
                    "mock_get_stats_for_resource": mock_get_stats_for_resource,
                    "mock_get_transifex_file": mock_get_transifex_file,
                    "mock_save_txrc_file": mock_save_txrc_file
                }
                return func(*args, **kwargs)

        return wrapper

    @fixture_mocked_project
    @patch("txclib.project.logger.error")
    def test_pull_raises_authentication_exception(self, mock_logger, **kwargs):
        project = kwargs['mock_project']
        with self.assertRaises(AuthenticationError):
            project.pull()
            mock_logger.assert_called_once_with(
                Project.AUTHENTICATION_FAILED_MESSAGE)

    @fixture_mocked_project
    @patch('txclib.project.Project.do_url_request')
    def test_pull_with_branch_pulls_from_right_resource(self, m, **kwargs):
        m.return_value = ('{"i18n_type": "PO"}', '')
        project = kwargs['mock_project']
        project.pull(branch='somebranch')
        self.assertDictEqual(
            project.url_info, {
                'host': 'https://fake.com',
                'project': 'example',
                'resource': 'somebranch--enpo'
            })

    @fixture_mocked_project
    @patch('txclib.project.Project.do_url_request')
    def test_push_with_branch_pushes_to_right_resource(self, m, **kwargs):
        m.return_value = ('{"i18n_type": "PO"}', '')
        project = kwargs['mock_project']
        project.push(source=True, branch='somebranch')
        self.assertDictEqual(
            project.url_info, {
                'host': 'https://fake.com',
                'project': 'example',
                'resource': 'somebranch--enpo'
            })

    @fixture_mocked_project
    @patch('txclib.project.Project.do_url_request')
    def test_push_with_branch_weird_characters_are_handled(self, m, **kwargs):
        m.return_value = ('{"i18n_type": "PO"}', '')
        project = kwargs['mock_project']
        project.push(source=True, branch='some/b**r:a&n!ch')
        self.assertDictEqual(
            project.url_info, {
                'host': 'https://fake.com',
                'project': 'example',
                'resource': 'some-b-r-a-n-ch--enpo'
            })

    @fixture_mocked_project
    @patch("txclib.project.logger.error")
    def test_push_raises_authentication_exception(self, mock_logger, **kwargs):
        project = kwargs['mock_project']
        with self.assertRaises(AuthenticationError):
            project.push()

    @fixture_mocked_project
    @patch("txclib.project.logger.error")
    def test_delete_raises_authentication_exception(self, mock_logger,
                                                    **kwargs):
        project = kwargs['mock_project']
        with self.assertRaises(AuthenticationError):
            project.delete()

    @fixture_mocked_project
    @patch("txclib.project.logger.error")
    @patch("txclib.utils.make_request")
    def test_pull_raises_connection_exception(self, mock_request, mock_logger,
                                              **kwargs):
        """Test that all connection errors are properly handled."""
        project = kwargs["mock_project"]
        response = 502
        msg = "Failed with code %d" % response
        mock_request.side_effect = TXConnectionError(msg, code=response)
        with self.assertRaises(TXConnectionError):
            project.pull()

    @fixture_mocked_project
    @patch("txclib.project.logger.error")
    @patch("txclib.utils.make_request")
    def test_push_raises_connection_exception(self, mock_request, mock_logger,
                                              **kwargs):
        """Test that all connection errors are properly handled."""
        project = kwargs["mock_project"]
        response = 500
        msg = "Failed with code %d" % response
        mock_request.side_effect = TXConnectionError(msg, code=response)
        with self.assertRaises(TXConnectionError):
            project.push()
Beispiel #5
0
class TestProjectPull(unittest.TestCase):
    """Test bits & pieces of the pull method."""

    def setUp(self):
        super(TestProjectPull, self).setUp()
        self.p = Project(init=False)
        self.p.minimum_perc = None
        self.p.resource = "resource"
        self.p.host = "foo"
        self.p.project_slug = "foo"
        self.p.resource_slug = "foo"
        self.stats = {
            "en": {"completed": "100%", "last_update": "2011-11-01 15:00:00"},
            "el": {"completed": "60%", "last_update": "2011-11-01 15:00:00"},
            "pt": {"completed": "70%", "last_update": "2011-11-01 15:00:00"},
        }
        self.langs = self.stats.keys()
        self.files = dict(zip(self.langs, itertools.repeat(None)))
        self.details = {"available_languages": []}
        for lang in self.langs:
            self.details["available_languages"].append({"code": lang})
        self.slang = "en"
        self.lang_map = Flipdict()

    def test_new_translations(self):
        """Test finding new transaltions to add."""
        with patch.object(self.p, "do_url_request") as resource_mock:
            resource_mock.return_value = json.dumps(self.details)
            files_keys = self.langs
            new_trans = self.p._new_translations_to_add
            for force in [True, False]:
                res = new_trans(self.files, self.slang, self.lang_map, self.stats, force)
                self.assertEquals(res, set([]))

            with patch.object(self.p, "_should_add_translation") as filter_mock:
                filter_mock.return_value = True
                for force in [True, False]:
                    res = new_trans({"el": None}, self.slang, self.lang_map, self.stats, force)
                    self.assertEquals(res, set(["pt"]))
                for force in [True, False]:
                    res = new_trans({}, self.slang, self.lang_map, self.stats, force)
                    self.assertEquals(res, set(["el", "pt"]))

                files = {}
                files["pt_PT"] = None
                lang_map = {"pt": "pt_PT"}
                for force in [True, False]:
                    res = new_trans(files, self.slang, lang_map, self.stats, force)
                    self.assertEquals(res, set(["el"]))

    def test_languages_to_pull_empty_initial_list(self):
        """Test determining the languages to pull, when the initial
        list is empty.
        """
        languages = []
        force = False

        res = self.p._languages_to_pull(languages, self.files, self.lang_map, self.stats, force)
        existing = res[0]
        new = res[1]
        self.assertEquals(existing, set(["el", "en", "pt"]))
        self.assertFalse(new)

        del self.files["el"]
        self.files["el-gr"] = None
        self.lang_map["el"] = "el-gr"
        res = self.p._languages_to_pull(languages, self.files, self.lang_map, self.stats, force)
        existing = res[0]
        new = res[1]
        self.assertEquals(existing, set(["el", "en", "pt"]))
        self.assertFalse(new)

    def test_languages_to_pull_with_initial_list(self):
        """Test determining the languages to pull, then there is a
        language selection from the user.
        """
        languages = ["el", "en"]
        self.lang_map["el"] = "el-gr"
        del self.files["el"]
        self.files["el-gr"] = None
        force = False

        with patch.object(self.p, "_should_add_translation") as mock:
            mock.return_value = True
            res = self.p._languages_to_pull(languages, self.files, self.lang_map, self.stats, force)
            existing = res[0]
            new = res[1]
            self.assertEquals(existing, set(["en", "el-gr"]))
            self.assertFalse(new)

            mock.return_value = False
            res = self.p._languages_to_pull(languages, self.files, self.lang_map, self.stats, force)
            existing = res[0]
            new = res[1]
            self.assertEquals(existing, set(["en", "el-gr"]))
            self.assertFalse(new)

            del self.files["el-gr"]
            mock.return_value = True
            res = self.p._languages_to_pull(languages, self.files, self.lang_map, self.stats, force)
            existing = res[0]
            new = res[1]
            self.assertEquals(existing, set(["en"]))
            self.assertEquals(new, set(["el"]))

            mock.return_value = False
            res = self.p._languages_to_pull(languages, self.files, self.lang_map, self.stats, force)
            existing = res[0]
            new = res[1]
            self.assertEquals(existing, set(["en"]))
            self.assertEquals(new, set([]))

    def test_in_combination_with_force_option(self):
        """Test the minumum-perc option along with -f."""
        with patch.object(self.p, "get_resource_option") as mock:
            mock.return_value = 70

            res = self.p._should_download("de", self.stats, None, False)
            self.assertEquals(res, False)
            res = self.p._should_download("el", self.stats, None, False)
            self.assertEquals(res, False)
            res = self.p._should_download("el", self.stats, None, True)
            self.assertEquals(res, False)
            res = self.p._should_download("en", self.stats, None, False)
            self.assertEquals(res, True)
            res = self.p._should_download("en", self.stats, None, True)
            self.assertEquals(res, True)

            with patch.object(self.p, "_remote_is_newer") as local_file_mock:
                local_file_mock = False
                res = self.p._should_download("pt", self.stats, None, False)
                self.assertEquals(res, True)
                res = self.p._should_download("pt", self.stats, None, True)
                self.assertEquals(res, True)