123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- # -*- coding: utf-8 -*-
- from __future__ import with_statement
- import unittest
- import contextlib
- import itertools
- try:
- import json
- except ImportError:
- import simplejson as json
- from mock import Mock, patch
- from txclib.project import Project
- from txclib.config import Flipdict
- class TestProject(unittest.TestCase):
- def test_extract_fields(self):
- """Test the functions that extract a field from a stats object."""
- stats = {
- 'completed': '80%',
- 'last_update': '00:00',
- 'foo': 'bar',
- }
- self.assertEqual(
- stats['completed'], '%s%%' % Project._extract_completed(stats)
- )
- self.assertEqual(stats['last_update'], Project._extract_updated(stats))
- def test_specifying_resources(self):
- """Test the various ways to specify resources in a project."""
- p = Project(init=False)
- resources = [
- 'proj1.res1',
- 'proj2.res2',
- 'transifex.txn',
- 'transifex.txo',
- ]
- with patch.object(p, 'get_resource_list') as mock:
- mock.return_value = resources
- cmd_args = [
- 'proj1.res1', '*1*', 'transifex*', '*r*',
- '*o', 'transifex.tx?', 'transifex.txn',
- ]
- results = [
- ['proj1.res1', ],
- ['proj1.res1', ],
- ['transifex.txn', 'transifex.txo', ],
- ['proj1.res1', 'proj2.res2', 'transifex.txn', 'transifex.txo', ],
- ['transifex.txo', ],
- ['transifex.txn', 'transifex.txo', ],
- ['transifex.txn', ],
- [],
- ]
- for i, arg in enumerate(cmd_args):
- resources = [arg]
- self.assertEqual(p.get_chosen_resources(resources), results[i])
- # wrong argument
- resources = ['*trasnifex*', ]
- self.assertRaises(Exception, p.get_chosen_resources, resources)
- class TestProjectMinimumPercent(unittest.TestCase):
- """Test the minimum-perc option."""
- def setUp(self):
- super(TestProjectMinimumPercent, self).setUp()
- self.p = Project(init=False)
- self.p.minimum_perc = None
- self.p.resource = "resource"
- def test_cmd_option(self):
- """Test command-line option."""
- self.p.minimum_perc = 20
- results = itertools.cycle([80, 90 ])
- def side_effect(*args):
- return results.next()
- with patch.object(self.p, "get_resource_option") as mock:
- mock.side_effect = side_effect
- self.assertFalse(self.p._satisfies_min_translated({'completed': '12%'}))
- self.assertTrue(self.p._satisfies_min_translated({'completed': '20%'}))
- self.assertTrue(self.p._satisfies_min_translated({'completed': '30%'}))
- def test_global_only(self):
- """Test only global option."""
- results = itertools.cycle([80, None ])
- def side_effect(*args):
- return results.next()
- with patch.object(self.p, "get_resource_option") as mock:
- mock.side_effect = side_effect
- self.assertFalse(self.p._satisfies_min_translated({'completed': '70%'}))
- self.assertTrue(self.p._satisfies_min_translated({'completed': '80%'}))
- self.assertTrue(self.p._satisfies_min_translated({'completed': '90%'}))
- def test_local_lower_than_global(self):
- """Test the case where the local option is lower than the global."""
- results = itertools.cycle([80, 70 ])
- def side_effect(*args):
- return results.next()
- with patch.object(self.p, "get_resource_option") as mock:
- mock.side_effect = side_effect
- self.assertFalse(self.p._satisfies_min_translated({'completed': '60%'}))
- self.assertTrue(self.p._satisfies_min_translated({'completed': '70%'}))
- self.assertTrue(self.p._satisfies_min_translated({'completed': '80%'}))
- self.assertTrue(self.p._satisfies_min_translated({'completed': '90%'}))
- def test_local_higher_than_global(self):
- """Test the case where the local option is lower than the global."""
- results = itertools.cycle([60, 70 ])
- def side_effect(*args):
- return results.next()
- with patch.object(self.p, "get_resource_option") as mock:
- mock.side_effect = side_effect
- self.assertFalse(self.p._satisfies_min_translated({'completed': '60%'}))
- self.assertTrue(self.p._satisfies_min_translated({'completed': '70%'}))
- self.assertTrue(self.p._satisfies_min_translated({'completed': '80%'}))
- self.assertTrue(self.p._satisfies_min_translated({'completed': '90%'}))
- def test_local_only(self):
- """Test the case where the local option is lower than the global."""
- results = itertools.cycle([None, 70 ])
- def side_effect(*args):
- return results.next()
- with patch.object(self.p, "get_resource_option") as mock:
- mock.side_effect = side_effect
- self.assertFalse(self.p._satisfies_min_translated({'completed': '60%'}))
- self.assertTrue(self.p._satisfies_min_translated({'completed': '70%'}))
- self.assertTrue(self.p._satisfies_min_translated({'completed': '80%'}))
- self.assertTrue(self.p._satisfies_min_translated({'completed': '90%'}))
- def test_no_option(self):
- """"Test the case there is nothing defined."""
- results = itertools.cycle([None, None ])
- def side_effect(*args):
- return results.next()
- with patch.object(self.p, "get_resource_option") as mock:
- mock.side_effect = side_effect
- self.assertTrue(self.p._satisfies_min_translated({'completed': '0%'}))
- self.assertTrue(self.p._satisfies_min_translated({'completed': '10%'}))
- self.assertTrue(self.p._satisfies_min_translated({'completed': '90%'}))
- class TestProjectFilters(unittest.TestCase):
- """Test filters used to decide whether to push/pull a translation or not."""
- def setUp(self):
- super(TestProjectFilters, self).setUp()
- self.p = Project(init=False)
- self.p.minimum_perc = None
- self.p.resource = "resource"
- 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()
- def test_add_translation(self):
- """Test filters for adding translations.
- We do not test here for minimum percentages.
- """
- with patch.object(self.p, "get_resource_option") as mock:
- mock.return_value = None
- should_add = self.p._should_add_translation
- for force in [True, False]:
- for lang in self.langs:
- self.assertTrue(should_add(lang, self.stats, force))
- # unknown language
- self.assertFalse(should_add('es', self.stats))
- def test_update_translation(self):
- """Test filters for updating a translation.
- We do not test here for minimum percentages.
- """
- with patch.object(self.p, "get_resource_option") as mock:
- mock.return_value = None
- should_update = self.p._should_update_translation
- force = True
- for lang in self.langs:
- self.assertTrue(should_update(lang, self.stats, 'foo', force))
- force = False # reminder
- local_file = 'foo'
- # unknown language
- self.assertFalse(should_update('es', self.stats, local_file))
- # no local file
- with patch.object(self.p, "_get_time_of_local_file") as time_mock:
- time_mock.return_value = None
- with patch.object(self.p, "get_full_path") as path_mock:
- path_mock.return_value = "foo"
- for lang in self.langs:
- self.assertTrue(
- should_update(lang, self.stats, local_file)
- )
- # older local files
- local_times = [self.p._generate_timestamp('2011-11-01 14:00:59')]
- results = itertools.cycle(local_times)
- def side_effect(*args):
- return results.next()
- with patch.object(self.p, "_get_time_of_local_file") as time_mock:
- time_mock.side_effect = side_effect
- with patch.object(self.p, "get_full_path") as path_mock:
- path_mock.return_value = "foo"
- for lang in self.langs:
- self.assertTrue(
- should_update(lang, self.stats, local_file)
- )
- # newer local files
- local_times = [self.p._generate_timestamp('2011-11-01 15:01:59')]
- results = itertools.cycle(local_times)
- def side_effect(*args):
- return results.next()
- with patch.object(self.p, "_get_time_of_local_file") as time_mock:
- time_mock.side_effect = side_effect
- with patch.object(self.p, "get_full_path") as path_mock:
- path_mock.return_value = "foo"
- for lang in self.langs:
- self.assertFalse(
- should_update(lang, self.stats, local_file)
- )
- def test_push_translation(self):
- """Test filters for pushing a translation file."""
- with patch.object(self.p, "get_resource_option") as mock:
- mock.return_value = None
- local_file = 'foo'
- should_push = self.p._should_push_translation
- force = True
- for lang in self.langs:
- self.assertTrue(should_push(lang, self.stats, local_file, force))
- force = False # reminder
- # unknown language
- self.assertTrue(should_push('es', self.stats, local_file))
- # older local files
- local_times = [self.p._generate_timestamp('2011-11-01 14:00:59')]
- results = itertools.cycle(local_times)
- def side_effect(*args):
- return results.next()
- with patch.object(self.p, "_get_time_of_local_file") as time_mock:
- time_mock.side_effect = side_effect
- with patch.object(self.p, "get_full_path") as path_mock:
- path_mock.return_value = "foo"
- for lang in self.langs:
- self.assertFalse(
- should_push(lang, self.stats, local_file)
- )
- # newer local files
- local_times = [self.p._generate_timestamp('2011-11-01 15:01:59')]
- results = itertools.cycle(local_times)
- def side_effect(*args):
- return results.next()
- with patch.object(self.p, "_get_time_of_local_file") as time_mock:
- time_mock.side_effect = side_effect
- with patch.object(self.p, "get_full_path") as path_mock:
- path_mock.return_value = "foo"
- for lang in self.langs:
- self.assertTrue(
- should_push(lang, self.stats, local_file)
- )
- 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 TestFormats(unittest.TestCase):
- """Tests for the supported formats."""
- def setUp(self):
- self.p = Project(init=False)
- def test_extensions(self):
- """Test returning the correct extension for a format."""
- sample_formats = {
- 'PO': {'file-extensions': '.po, .pot'},
- 'QT': {'file-extensions': '.ts'},
- }
- extensions = ['.po', '.ts', '', ]
- with patch.object(self.p, "do_url_request") as mock:
- mock.return_value = json.dumps(sample_formats)
- for (type_, ext) in zip(['PO', 'QT', 'NONE', ], extensions):
- extension = self.p._extension_for(type_)
- self.assertEquals(extension, ext)
- class TestOptions(unittest.TestCase):
- """Test the methods related to parsing the configuration file."""
- def setUp(self):
- self.p = Project(init=False)
- def test_get_option(self):
- """Test _get_option method."""
- with contextlib.nested(
- patch.object(self.p, 'get_resource_option'),
- patch.object(self.p, 'config', create=True)
- ) as (rmock, cmock):
- rmock.return_value = 'resource'
- cmock.has_option.return_value = 'main'
- cmock.get.return_value = 'main'
- self.assertEqual(self.p._get_option(None, None), 'resource')
- rmock.return_value = None
- cmock.has_option.return_value = 'main'
- cmock.get.return_value = 'main'
- self.assertEqual(self.p._get_option(None, None), 'main')
- cmock.has_option.return_value = None
- self.assertIs(self.p._get_option(None, None), None)
- class TestConfigurationOptions(unittest.TestCase):
- """Test the various configuration options."""
- def test_i18n_type(self):
- p = Project(init=False)
- type_string = 'type'
- i18n_type = 'PO'
- with patch.object(p, 'config', create=True) as config_mock:
- p.set_i18n_type([], i18n_type)
- calls = config_mock.method_calls
- self.assertEquals('set', calls[0][0])
- self.assertEquals('main', calls[0][1][0])
- p.set_i18n_type(['transifex.txo'], 'PO')
- calls = config_mock.method_calls
- self.assertEquals('set', calls[0][0])
- p.set_i18n_type(['transifex.txo', 'transifex.txn'], 'PO')
- calls = config_mock.method_calls
- self.assertEquals('set', calls[0][0])
- self.assertEquals('set', calls[1][0])
- class TestStats(unittest.TestCase):
- """Test the access to the stats objects."""
- def setUp(self):
- self.stats = Mock()
- self.stats.__getitem__ = Mock()
- self.stats.__getitem__.return_value = '12%'
- def test_field_used_per_mode(self):
- """Test the fields used for each mode."""
- Project._extract_completed(self.stats, 'translate')
- self.stats.__getitem__.assert_called_with('completed')
- Project._extract_completed(self.stats, 'reviewed')
- self.stats.__getitem__.assert_called_with('reviewed_percentage')
|