def adjust_subtransaction_rows(t): utils.log_debug('add_subtransactions_rows', len(t.subtransactions)) # Remove existing subtransactions memo = gui.get_by_text('user-entered-text', t.id, count=1) # TODO: why was this partial? gui.click(memo, 2) removes = gui.get('ynab-grid-sub-remove', require=False, wait=1) while removes: gui.click(removes) removes = gui.get('ynab-grid-sub-remove', require=False, wait=.5) # Add rows for the new ones n = len(t.subtransactions) if n == 0: return gui.get_by_placeholder('accounts-text-field', 'category').clear() # needed? category_dropdown = gui.get_by_placeholder('dropdown-text-field', 'category') category_dropdown.send_keys(' ') split = gui.get('modal-account-categories-split-transaction') gui.click(split) for i in range(n - 2): # gui.clicking split means we already have two gui.click(gui.get('ynab-grid-split-add-sub-transaction')) if n == 1: # which is weird but in principle OK gui.click(gui.get('ynab-grid-sub-remove')) assert len(gui.get('ynab-grid-sub-remove')) == n
def enter_transaction(t): utils.log_debug('enter_transaction', t) accounts_sidebar = gui.get_by_text('user-entered-text', t.account_name) gui.click(accounts_sidebar) # handles that it contains two elements locate_transaction(t) assert t.account_name not in ('Annotated', 'Test Data' ) # don't overwrite test data adjust_subtransaction_rows(t) date, payees, categories, memos = map( lambda p: gui.get_by_placeholder('accounts-text-field', p), ('date', 'payee', 'category', 'memo')) date.send_keys(gui_format_date(t.date)) outflows, inflows = map( lambda p: gui.get_by_placeholder('ember-text-field', p), ('outflow', 'inflow')) if len(t.subtransactions) == 0: enter(t, payees, categories, memos, outflows, inflows) ' TODO: do not approve, only save? ' ' Maybe it is only approving things that are already approved? ' approve = gui.get_by_text('button-primary', ['Approve', 'Save']) utils.log_debug('approve/save?', approve.text) gui.click(approve) else: for i, s in enumerate(t.subtransactions): enter(s, payees[i + 1], categories[i + 1], memos[i + 1], outflows[i + 1], inflows[i + 1]) outflows[-1].send_keys(gui.Keys.ENTER)
def delete_accounts(accounts): utils.log_info('Deleting %s accounts via Web App' % len(accounts)) load_gui() navlink_accounts = gui.get('navlink-accounts') gui.scroll_to(navlink_accounts) gui.click(navlink_accounts) for a in accounts: edit_account = gui.get_by_text('nav-account-name', a.name) utils.log_debug(edit_account) gui.scroll_to(edit_account) gui.right_click(edit_account) gui.get_by_text('button-red', ['Close Account', 'Delete', 'Delete Account'], partial=True).click()
def delete_transactions(): load_gui() search('Memo: ' + afy.ynab.ynab.delete_key) if not isinstance(gui.get('ynab-checkbox-button-square'), list): return # Means no transactions in results to delete, because only one element select_all() gui.send_keys(gui.Keys.TAB) gui.send_keys(gui.Keys.TAB) gui.send_keys(gui.Keys.DELETE) # Only gives confirm modal over some number of transactions. TODO: cut down this wait. confirm_delete = gui.get_by_text('button-primary', 'Delete', require=False, wait=7) if confirm_delete: gui.click(confirm_delete)
def setup_ynab_auth(): utils.log_info('Checking for YNAB authentication') # TODO: make this use oauth instead of api tokens if settings.get('api_token'): return utils.log_info('Installing YNAB authentication') api_token_url = 'https://app.youneedabudget.com/settings/developer' d = gui.driver() d.get(api_token_url) utils.log_info('Log in if needed') new_token_button = gui.get_by_text('button', 'New Token') gui.click(new_token_button) utils.log_info( 'Enter your password in the YNAB Web App, then click "Generate"') while 'New Personal Access Token' not in d.page_source: time.sleep(.5) api_token = re.search( 'New Personal Access Token: <strong>([^<]*)</strong>', d.page_source).groups()[0] settings.set('api_token', api_token) utils.log_debug('settings.api_token', settings.api_token) assert settings.api_token gui.quit()
def select_all(): gui.click(gui.get('ynab-checkbox-button-square'))