def test_text_migration_python_code(mock_echo): """Test the mode that migrates directly given text instead of files (Python/gettext code).""" command = Command() call_command(command, 'migrate', text=PYTHON_SAMPLE) expected = Color.format( '\n[high]Transifex Native syntax:[end]\n[green]{}[end]'.format( PYTHON_SAMPLE_MIGRATED)) native = Color.format(mock_echo.call_args_list[1][0][0]) assert expected == native # Make sure it's idempotent mock_echo.reset_mock() call_command(command, 'migrate', text=PYTHON_SAMPLE_MIGRATED) actual = Color.format(mock_echo.call_args_list[1][0][0]) assert expected == actual
def test_text_migration_template_code(mock_echo): """Test the mode that migrates directly given text instead of files (Django HTML templates).""" command = Command() call_command(command, 'migrate', text=DJANGO_TEMPLATE) expected = Color.format( '\n[high]Transifex Native syntax:[end]\n[green]{}[end]'.format( TRANSIFEX_TEMPLATE)) actual = Color.format(mock_echo.call_args_list[1][0][0]) assert expected == actual # Make sure it's idempotent mock_echo.reset_mock() call_command(command, 'migrate', text=TRANSIFEX_TEMPLATE) actual = Color.format(mock_echo.call_args_list[1][0][0]) assert expected == actual
def print_new_file(file_migration): """Print all the lines of the file, highlighting the new chars only.""" Color.echo('[prompt]This is the final file[end]') Color.echo('[prompt]-------------------------------------[end]') output = [] for string_migration in file_migration.strings: if not string_migration.modified: output.append(Color.format(string_migration.original)) else: output.append( Color.format('[green]{}[end]'.format( string_migration.new))) print(add_line_prefix(''.join(output), '', 0)) Color.echo('[prompt]-------------------------------------[end]')
def test_purge_cache_success(mock_echo, mock_invalidate_cache): mock_invalidate_cache.return_value = 200, { 'data': { 'count': 5, } } expected = Color.format('[green]\nSuccessfully purged CDS cache.[end]\n' '[high]Status:[end] [warn]{code}[end]\n' '[high]Records purged: {count}[end]\n'.format( code=200, count=5, )) # Make sure it's idempotent mock_echo.reset_mock() command = get_transifex_command() call_command(command, 'invalidate', purge=True) actual = Color.format(mock_echo.call_args_list[1][0][0]) assert expected == actual
def test_invalidate_cache_fail(mock_echo, mock_invalidate_cache): mock_invalidate_cache.return_value = 500, { 'message': 'error message', 'details': 'error details', } expected = Color.format( '[error]\nCould not invalidate CDS.[end]\n' '[high]Status:[end] [warn]{code}[end]\n' '[high]Message:[end] [warn]{message}[end]\n'.format( code=500, message='error message', )) # Make sure it's idempotent mock_echo.reset_mock() command = get_transifex_command() call_command(command, 'invalidate') actual = Color.format(mock_echo.call_args_list[1][0][0]) assert expected == actual
def test_invalidate_cache_success(mock_echo, mock_invalidate_cache): mock_invalidate_cache.return_value = 200, { 'data': { 'count': 5, }, } expected = Color.format( '[green]\nSuccessfully invalidated CDS cache.[end]\n' '[high]Status:[end] [warn]{code}[end]\n' '[high]Records invalidated: {count}[end]\n' '[high]Note: It might take a few minutes for ' 'fresh content to be available\n'.format( code=200, count=5, )) # Make sure it's idempotent mock_echo.reset_mock() command = get_transifex_command() call_command(command, 'invalidate') actual = Color.format(mock_echo.call_args_list[1][0][0]) assert expected == actual
def _file_prompt_intro(self): """Prompt the user with available actions when reviewing a file.""" reply = prompt( Color.format('[opt](A)[end] Accept ' '[opt](R)[end] Reject ' '[opt](M)[end] Accept & Mark for proofreading ' '\n' '[opt](P)[end] Print diff only ' '[opt](PP)[end] Print new file with diff ' '[opt](O)[end] Print original file ' '[opt](F)[end] Print new file ' '\n' '[opt](AA)[end] Accept remaining files ' '[opt](X)[end] Exit the migration'), default=str(ACCEPT_CHOICE), ) return reply.upper()
def _prompt_to_start(self, total_files): """Prompt the user before starting the migration. If the user chooses to not go through with it, sys.exit() is called. :param int total_files: the total number of files to migrate """ msg = pluralized( 'Found [warn]{cnt}[end] file to check for translatable strings.', 'Found [warn]{cnt}[end] files to check for translatable strings.', total_files, ) Color.echo('\n{}'.format(msg)) if not total_files: Color.echo('\n[high]Migration ended.[end]') sys.exit(1) if (self.options['save_policy'] != NoopSavePolicy.name and self.options['review_policy'] == NoopReviewPolicy.name): Color.echo( '\n[warn]WARNING! The selected configuration will save ' 'all files automatically, without allowing you to do any ' 'reviewing first.[end]') while True: reply = prompt( Color.format('[opt](Y)[end] Yes [opt](N)[end] No'), description='Are you sure you want to continue?', default='N', ) reply = reply.upper() if reply == 'Y': return elif reply == 'N': Color.echo('\n[high]Migration aborted.[end]') sys.exit(1)
def yes_no(description, yes_message=None, no_message=None): """Prompts the user to reply to a Yes/No question. :param basestring description: the message to display before prompting :param basestring yes_message: the message to display if user accepts :param basestring no_message: the message to display is user declines :return: True if the user chose to go through, false otherwise :rtype: bool """ while True: reply = prompt( Color.format('[opt](Y)[end] Yes [opt](N)[end] No'), description=description, default='N', ) reply = reply.upper() if reply == 'Y': if yes_message: Color.echo('[high]{}[end]'.format(yes_message)) return True elif reply == 'N': if no_message: Color.echo('[high]{}[end]'.format(no_message)) return False
def prompt_for_string(self, string_migration, string_cnt, strings_total): """Prompt the user to review the string migration and decide what to do. :param StringMigration string_migration: the migration object :param int string_cnt: the current index of the migrated string (0-based) :param int strings_total: the total number of strings in the corresponding file migration :return: an integer directive that determines what to do with the string :rtype: int """ Color.echo( '\n[{cnt}/{total}] [prompt]' 'Please review the following change:[end] ' '(confidence={confidence})'.format( cnt=string_cnt + 1, total=strings_total, confidence=('{}' if string_migration.confidence == Confidence.HIGH else '[warn]{}[end]').format( Confidence.to_string( string_migration.confidence)), )) Color.echo('[red]{}[end]'.format( add_line_prefix(string_migration.original, '- '))) Color.echo('[green]{}[end]'.format( add_line_prefix(string_migration.new, '+ '))) while True: reply = prompt( Color.format( '[opt](A)[end] Accept ' '[opt](R)[end] Reject ' '[opt](M)[end] Accept & Mark for proofreading ' '\n[opt](AA)[end] Accept remaining strings in file ' '[opt](RR)[end] Reject remaining strings in file ' '\n[opt](X)[end] Exit the migration'), default=str(ACCEPT_CHOICE), ) reply = reply.upper() if reply == ACCEPT_CHOICE: Color.echo('✅️ Change accepted') return REVIEW_ACCEPT elif reply == ACCEPT_ALL_CHOICE: Color.echo('✅ ✅️ All remaining changes accepted') return REVIEW_ACCEPT_ALL elif reply == REJECT_CHOICE: string_migration.revert() Color.echo('❌ Change rejected') return REVIEW_REJECT elif reply == REJECT_ALL_CHOICE: string_migration.revert() Color.echo('❌ ❌ All remaining changes rejected') return REVIEW_REJECT_ALL elif reply == EXIT_CHOICE: string_migration.revert() Color.echo('❌ ❌ All remaining changes rejected') Color.echo('❕Exiting the migration') return REVIEW_EXIT elif reply == MARK_CHOICE: mark_string( string_migration, self._comment_format, MARK_PROOFREAD_STRING, ) Color.echo('📝 Change marked for proofreading') return REVIEW_MARK_STRING