# -*- coding: utf-8 -*-
# pylint: disable=r0904, c0415, c0413, r0913, w0212
""" unittests for dkb_robo """
import sys
import os
from datetime import date
import unittest
import logging
import json
from unittest.mock import patch, Mock, mock_open
from bs4 import BeautifulSoup
from mechanicalsoup import LinkNotFoundError
sys.path.insert(0, '.')
sys.path.insert(0, '..')
from dkb_robo.legacy import Wrapper


def json_load(fname):
    """ simple json load """

    with open(fname, 'r', encoding='utf8') as myfile:
        data_dic = json.load(myfile)

    return data_dic


def read_file(fname):
    """ read file into string """
    with open(fname, "rb") as myfile:
        data = myfile.read()

    return data


def cnt_list(value):
    """ customized function return just the number if entries in input list """
    return len(value)


def my_side_effect(*args):
    """ my sideeffect funtion """
    return [200, args[1], [args[4]]]


@patch('dkb_robo.legacy.Wrapper.dkb_br')
class TestDKBRobo(unittest.TestCase):
    """ test class """

    maxDiff = None

    def setUp(self):
        self.dir_path = os.path.dirname(os.path.realpath(__file__))
        self.wrapper = Wrapper()

    def test_001_get_cc_limit(self, mock_browser):
        """ test Legacy._get_credit_limits() method """
        html = read_file(self.dir_path + '/mocks/konto-kreditkarten-limits.html')
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        e_result = {'1111********1111': 100.00,
                    '1111********1112': 2000.00,
                    'DE01 1111 1111 1111 1111 11': 1000.00,
                    'DE02 1111 1111 1111 1111 12': 2000.00}

        self.assertEqual(e_result, self.wrapper.get_credit_limits())

    def test_002_get_cc_limit(self, mock_browser):
        """ test legacy.get_credit_limits() triggers exceptions """
        html = read_file(self.dir_path + '/mocks/konto-kreditkarten-limits-exception.html')
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        e_result = {'DE01 1111 1111 1111 1111 11': 1000.00, 'DE02 1111 1111 1111 1111 12': 2000.00}
        with self.assertLogs('dkb_robo', level='INFO') as lcm:
            self.assertEqual(e_result, self.wrapper.get_credit_limits())
        self.assertIn("ERROR:dkb_robo.legacy:Wrapper.get_credit_limits() get credit card limits: 'NoneType' object has no attribute 'find'\n", lcm.output)

    def test_003_get_cc_limit(self, mock_browser):
        """ test legacy.get_credit_limits() no limits """
        # html = read_file(self.dir_path + '/mocks/konto-kreditkarten-limits-exception.html')
        html = '<html><body>fooo</body></html>'
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        e_result = {}
        self.assertEqual(e_result, self.wrapper.get_credit_limits())

    def test_004_get_exo_single(self, mock_browser):
        """ test legacy.get_exemption_order() method for a single exemption order """
        html = read_file(self.dir_path + '/mocks/freistellungsauftrag.html')
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        e_result = {1: {'available': 1000.0, 'amount': 1000.0, 'used': 0.0, 'description': 'Gemeinsam mit Firstname Familyname', 'validity': '01.01.2016 unbefristet'}}
        self.assertEqual(self.wrapper.get_exemption_order(), e_result)

    def test_005_get_exo_single_nobr(self, mock_browser):
        """ test legacy.get_exemption_order() method for a single exemption order without line-breaks"""
        html = read_file(self.dir_path + '/mocks/freistellungsauftrag-nobr.html')
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        e_result = {1: {'available': 1000.0, 'amount': 1000.0, 'used': 0.0, 'description': 'Gemeinsam mit Firstname Familyname', 'validity': '01.01.2016 unbefristet'}}
        self.assertEqual(self.wrapper.get_exemption_order(), e_result)

    def test_006_get_exo_multiple(self, mock_browser):
        """ test legacy.get_exemption_order() method for a multiple exemption orders """
        html = read_file(self.dir_path + '/mocks/freistellungsauftrag-multiple.html')
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        e_result = {1: {'available': 1000.0,
                        'amount': 1000.0,
                        'used': 0.0,
                        'description': 'Gemeinsam mit Firstname1 Familyname1',
                        'validity': '01.01.2016 unbefristet'},
                    2: {'available': 2000.0,
                        'amount': 2000.0,
                        'used': 0.0,
                        'description': 'Gemeinsam mit Firstname2 Familyname2',
                        'validity': '02.01.2016 unbefristet'}}

        self.assertEqual(self.wrapper.get_exemption_order(), e_result)

    def test_007_get_exo_single(self, mock_browser):
        """ test legacy.get_exemption_order() method try throws exception """
        html = read_file(self.dir_path + '/mocks/freistellungsauftrag-indexerror.html')
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        e_result = {1: {}}
        with self.assertLogs('dkb_robo', level='INFO') as lcm:
            self.assertEqual(self.wrapper.get_exemption_order(), e_result)
        self.assertIn('ERROR:dkb_robo.legacy:Wrapper.get_exemption_order(): list index out of range\n', lcm.output)

    def test_008_new_instance(self, _unused):
        """ test legacy._new_instance() method """
        self.assertIn('mechanicalsoup.stateful_browser.StatefulBrowser object at', str(self.wrapper._new_instance()))

    def test_009_new_instance(self, _unused):
        """ test legacy._new_instance() method with proxies """
        self.wrapper.proxies = 'proxies'
        self.assertIn('mechanicalsoup.stateful_browser.StatefulBrowser object at', str(self.wrapper._new_instance()))
        self.assertEqual('proxies', self.wrapper.dkb_br.session.proxies)

    def test_010_new_instance(self, _unused):
        """ test legacy._new_instance() method with clientcookies """
        cookieobj = Mock()
        cookieobj.value = 'value'
        cookieobj.name = 'name'
        self.assertIn('mechanicalsoup.stateful_browser.StatefulBrowser object at', str(self.wrapper._new_instance([cookieobj])))

    def test_011_get_points(self, mock_browser):
        """ test legacy.get_points() method """
        html = read_file(self.dir_path + '/mocks/dkb_punkte.html')
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        e_result = {'DKB-Punkte': 100000, 'davon verfallen zum  31.12.2017': 90000}
        self.assertEqual(self.wrapper.get_points(), e_result)

    def test_012_get_so_multiple(self, mock_browser):
        """ test legacy._get_standing_orders() method """
        html = read_file(self.dir_path + '/mocks/dauerauftraege.html')
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        e_result = [{'amount': 100.0, 'interval': '1. monatlich 01.03.2017', 'recipient': 'RECPIPIENT-1', 'purpose': 'KV 1234567890'},
                    {'amount': 200.0, 'interval': '1. monatlich geloescht', 'recipient': 'RECPIPIENT-2', 'purpose': 'KV 0987654321'}]
        self.assertEqual(self.wrapper.get_standing_orders(), e_result)

    @patch('dkb_robo.legacy.Wrapper._parse_overview')
    @patch('dkb_robo.legacy.Wrapper._get_financial_statement')
    @patch('dkb_robo.legacy.Wrapper._login_confirm')
    @patch('dkb_robo.legacy.Wrapper._ctan_check')
    @patch('dkb_robo.legacy.Wrapper._new_instance')
    def test_013_login(self, mock_instance, mock_ctan, mock_confirm, mock_fs, mock_pov, mock_browser):
        """ test legacy._login() method - no confirmation """
        html = """
                <h1>Anmeldung bestätigen</h1>
                <div id="lastLoginContainer" class="lastLogin deviceFloatRight ">
                        Letzte Anmeldung:
                        01.03.2017, 01:00 Uhr
                </div>
               """
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        mock_ctan.return_value = False
        mock_confirm.return_value = False
        mock_instance.return_value = mock_browser
        mock_pov.return_value = '_parse_overview'
        mock_fs.return_value = 'mock_fs'
        self.assertEqual(({}, '01.03.2017, 01:00 Uhr'), self.wrapper.login())
        self.assertTrue(mock_confirm.called)
        self.assertFalse(mock_ctan.called)
        self.assertFalse(mock_fs.called)
        self.assertFalse(mock_pov.called)

    @patch('dkb_robo.legacy.Wrapper._parse_overview')
    @patch('dkb_robo.legacy.Wrapper._get_financial_statement')
    @patch('dkb_robo.legacy.Wrapper._login_confirm')
    @patch('dkb_robo.legacy.Wrapper._ctan_check')
    @patch('dkb_robo.legacy.Wrapper._new_instance')
    def test_014_login(self, mock_instance, mock_ctan, mock_confirm, mock_fs, mock_pov, mock_browser):
        """ test legacy.login() method - confirmation """
        html = """
                <h1>Anmeldung bestätigen</h1>
                <div id="lastLoginContainer" class="lastLogin deviceFloatRight ">
                        Letzte Anmeldung:
                        01.03.2017, 01:00 Uhr
                </div>
               """
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        mock_ctan.return_value = False
        mock_confirm.return_value = True
        mock_instance.return_value = mock_browser
        mock_pov.return_value = '_parse_overview'
        mock_fs.return_value = 'mock_fs'
        self.assertEqual(('_parse_overview', '01.03.2017, 01:00 Uhr'), self.wrapper.login())
        self.assertTrue(mock_confirm.called)
        self.assertFalse(mock_ctan.called)
        self.assertTrue(mock_fs.called)
        self.assertTrue(mock_pov.called)

    @patch('dkb_robo.legacy.Wrapper._parse_overview')
    @patch('dkb_robo.legacy.Wrapper._get_financial_statement')
    @patch('dkb_robo.legacy.Wrapper._login_confirm')
    @patch('dkb_robo.legacy.Wrapper._ctan_check')
    @patch('dkb_robo.legacy.Wrapper._new_instance')
    def test_015_login(self, mock_instance, mock_ctan, mock_confirm, mock_fs, mock_pov, mock_browser):
        """ test legacy._login() method - no confirmation """
        html = """
                <h1>Anmeldung bestätigen</h1>
                <div id="lastLoginContainer" class="lastLogin deviceFloatRight ">
                        Letzte Anmeldung:
                        01.03.2017, 01:00 Uhr
                </div>
               """
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        mock_ctan.return_value = False
        mock_confirm.return_value = False
        mock_instance.return_value = mock_browser
        mock_pov.return_value = '_parse_overview'
        mock_fs.return_value = 'mock_fs'
        self.wrapper.tan_insert = True
        self.assertEqual(({}, '01.03.2017, 01:00 Uhr'), self.wrapper.login())
        self.assertFalse(mock_confirm.called)
        self.assertTrue(mock_ctan.called)
        self.assertFalse(mock_fs.called)
        self.assertFalse(mock_pov.called)

    @patch('dkb_robo.legacy.Wrapper._parse_overview')
    @patch('dkb_robo.legacy.Wrapper._get_financial_statement')
    @patch('dkb_robo.legacy.Wrapper._login_confirm')
    @patch('dkb_robo.legacy.Wrapper._ctan_check')
    @patch('dkb_robo.legacy.Wrapper._new_instance')
    def test_016_login(self, mock_instance, mock_ctan, mock_confirm, mock_fs, mock_pov, mock_browser):
        """ test legacy._login() method - confirmation """
        html = """
                <h1>Anmeldung bestätigen</h1>
                <div id="lastLoginContainer" class="lastLogin deviceFloatRight ">
                        Letzte Anmeldung:
                        01.03.2017, 01:00 Uhr
                </div>
               """
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        mock_ctan.return_value = True
        mock_confirm.return_value = False
        mock_instance.return_value = mock_browser
        mock_pov.return_value = '_parse_overview'
        mock_fs.return_value = 'mock_fs'
        self.wrapper.tan_insert = True
        self.assertEqual(('_parse_overview', '01.03.2017, 01:00 Uhr'), self.wrapper.login())
        self.assertFalse(mock_confirm.called)
        self.assertTrue(mock_ctan.called)
        self.assertTrue(mock_fs.called)
        self.assertTrue(mock_pov.called)

    @patch('dkb_robo.legacy.Wrapper._parse_overview')
    @patch('dkb_robo.legacy.Wrapper._get_financial_statement')
    @patch('dkb_robo.legacy.Wrapper._login_confirm')
    @patch('dkb_robo.legacy.Wrapper._ctan_check')
    @patch('dkb_robo.legacy.Wrapper._new_instance')
    def test_017_login(self, mock_instance, mock_ctan, mock_confirm, mock_fs, mock_pov, mock_browser):
        """ test legacy._login() login failed """
        html = """
                <div id="lastLoginContainer" class="clearfix module text errorMessage">foo</div>
               """
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        mock_ctan.return_value = True
        mock_confirm.return_value = False
        mock_instance.return_value = mock_browser
        mock_pov.return_value = '_parse_overview'
        mock_fs.return_value = 'mock_fs'
        self.wrapper.tan_insert = True
        with self.assertRaises(Exception) as err:
            self.assertEqual(self.wrapper.login(), None)
        self.assertEqual('Login failed', str(err.exception))
        self.assertFalse(mock_confirm.called)
        self.assertFalse(mock_ctan.called)
        self.assertFalse(mock_fs.called)
        self.assertFalse(mock_pov.called)

    @patch('dkb_robo.legacy.Wrapper._parse_overview')
    @patch('dkb_robo.legacy.Wrapper._get_financial_statement')
    @patch('dkb_robo.legacy.Wrapper._login_confirm')
    @patch('dkb_robo.legacy.Wrapper._ctan_check')
    @patch('dkb_robo.legacy.Wrapper._new_instance')
    def test_018_login(self, mock_instance, mock_ctan, mock_confirm, mock_fs, mock_pov, mock_browser):
        """ test legacy._login() login failed """
        mock_browser.select_form.side_effect = LinkNotFoundError
        mock_ctan.return_value = True
        mock_confirm.return_value = False
        mock_instance.return_value = mock_browser
        mock_pov.return_value = '_parse_overview'
        mock_fs.return_value = 'mock_fs'
        self.wrapper.tan_insert = True
        with self.assertRaises(Exception) as err:
            self.assertEqual(self.wrapper.login(), None)
        self.assertEqual('Login failed: LinkNotFoundError', str(err.exception))
        self.assertFalse(mock_confirm.called)
        self.assertFalse(mock_ctan.called)
        self.assertFalse(mock_fs.called)
        self.assertFalse(mock_pov.called)

    @patch('dkb_robo.legacy.Wrapper._parse_overview')
    @patch('dkb_robo.legacy.Wrapper._get_financial_statement')
    @patch('dkb_robo.legacy.Wrapper._login_confirm')
    @patch('dkb_robo.legacy.Wrapper._ctan_check')
    @patch('dkb_robo.legacy.Wrapper._new_instance')
    def test_019_login(self, mock_instance, mock_ctan, mock_confirm, mock_fs, mock_pov, mock_browser):
        """ test legacy._login() method - notice form """
        html = """
                <h1>Anmeldung bestätigen</h1>
                <form id="genericNoticeForm">foo</form>
                <div id="lastLoginContainer" class="lastLogin deviceFloatRight ">
                        Letzte Anmeldung:
                        01.03.2017, 01:00 Uhr
                </div>
               """
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        mock_ctan.return_value = True
        mock_confirm.return_value = False
        mock_instance.return_value = mock_browser
        mock_pov.return_value = '_parse_overview'
        mock_fs.return_value = 'mock_fs'
        self.wrapper.tan_insert = True
        self.assertEqual(('_parse_overview', '01.03.2017, 01:00 Uhr'), self.wrapper.login())
        self.assertFalse(mock_confirm.called)
        self.assertTrue(mock_ctan.called)
        self.assertTrue(mock_fs.called)
        self.assertTrue(mock_pov.called)

    def test_020_parse_overview(self, _unused):
        """ test DKBRobo._parse_overview() method """
        html = read_file(self.dir_path + '/mocks/finanzstatus.html')
        e_result = {0: {'account': 'XY99 1111 1111 0000 1111 99',
                        'amount': 1367.82,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=0&group=0',
                        'name': 'hauptkonto',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=0&group=0',
                        'type': 'account'},
                    1: {'account': '9999********1111',
                        'amount': 9613.31,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=1&group=0',
                        'name': 'first visa',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=1&group=0',
                        'type': 'creditcard'},
                    2: {'account': '9999********8888',
                        'amount': -260.42,
                        'date': '26.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=2&group=0',
                        'name': 'MilesnMoreMaster',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=2&group=0',
                        'type': 'creditcard'},
                    3: {'account': '9999********2222',
                        'amount': 515.52,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=0&group=1',
                        'name': 'second visa',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=0&group=1',
                        'type': 'creditcard'},
                    4: {'account': 'XY99 1111 1111 2155 2788 99',
                        'amount': 588.37,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=1&group=1',
                        'name': 'zweitkonto',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=1&group=1',
                        'type': 'account'},
                    5: {'account': '9999********3333',
                        'amount': 515.52,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=2&group=1',
                        'name': '3rd visa',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=2&group=1',
                        'type': 'creditcard'},
                    6: {'account': 'XY99 3333 1111 0000 3333 99',
                        'amount': -334.34,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=3&group=1',
                        'name': '3rd acc',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=3&group=1',
                        'type': 'account'}}

        self.assertEqual(self.wrapper._parse_overview(BeautifulSoup(html, 'html5lib')), e_result)

    def test_021_parse_overview(self, _unused):
        """ test DKBRobo._parse_overview() method """
        html = read_file(self.dir_path + '/mocks/finanzstatus-error1.html')
        e_result = {0: {'account': 'XY99 1111 1111 0000 1111 99',
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=0&group=0',
                        'name': 'hauptkonto',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=0&group=0',
                        'type': 'account'},
                    1: {'account': '9999********1111',
                        'amount': 9613.31,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=1&group=0',
                        'name': 'first visa',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=1&group=0',
                        'type': 'creditcard'},
                    2: {'account': '9999********8888',
                        'amount': -260.42,
                        'date': '26.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=2&group=0',
                        'name': 'MilesnMoreMaster',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=2&group=0',
                        'type': 'creditcard'},
                    3: {'account': '9999********2222',
                        'amount': 515.52,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=0&group=1',
                        'name': 'second visa',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=0&group=1',
                        'type': 'creditcard'},
                    4: {'account': 'XY99 1111 1111 2155 2788 99',
                        'amount': 588.37,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=1&group=1',
                        'name': 'zweitkonto',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=1&group=1',
                        'type': 'account'},
                    5: {'account': '9999********3333',
                        'amount': 515.52,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=2&group=1',
                        'name': '3rd visa',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=2&group=1',
                        'type': 'creditcard'},
                    6: {'account': 'XY99 3333 1111 0000 3333 99',
                        'amount': -334.34,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=3&group=1',
                        'name': '3rd acc',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=3&group=1',
                        'type': 'account'}}
        with self.assertLogs('dkb_robo', level='INFO') as lcm:
            self.assertEqual(self.wrapper._parse_overview(BeautifulSoup(html, 'html5lib')), e_result)
        self.assertIn("ERROR:dkb_robo.legacy:Wrapper._parse_overview() convert amount: could not convert string to float: 'aaa'\n", lcm.output)

    def test_022_parse_overview(self, _unused):
        """ test DKBRobo._parse_overview() exception detail link"""
        html = read_file(self.dir_path + '/mocks/finanzstatus-error2.html')
        e_result = {0: {'account': 'XY99 1111 1111 0000 1111 99',
                        'amount': 1367.82,
                        'date': '27.04.2018',
                        'name': 'hauptkonto',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=0&group=0',
                        'type': 'account'},
                    1: {'account': '9999********1111',
                        'amount': 9613.31,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=1&group=0',
                        'name': 'first visa',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=1&group=0',
                        'type': 'creditcard'},
                    2: {'account': '9999********8888',
                        'amount': -260.42,
                        'date': '26.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=2&group=0',
                        'name': 'MilesnMoreMaster',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=2&group=0',
                        'type': 'creditcard'},
                    3: {'account': '9999********2222',
                        'amount': 515.52,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=0&group=1',
                        'name': 'second visa',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=0&group=1',
                        'type': 'creditcard'},
                    4: {'account': 'XY99 1111 1111 2155 2788 99',
                        'amount': 588.37,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=1&group=1',
                        'name': 'zweitkonto',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=1&group=1',
                        'type': 'account'},
                    5: {'account': '9999********3333',
                        'amount': 515.52,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=2&group=1',
                        'name': '3rd visa',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=2&group=1',
                        'type': 'creditcard'},
                    6: {'account': 'XY99 3333 1111 0000 3333 99',
                        'amount': -334.34,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=3&group=1',
                        'name': '3rd acc',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=3&group=1',
                        'type': 'account'}}
        with self.assertLogs('dkb_robo', level='INFO') as lcm:
            self.assertEqual(self.wrapper._parse_overview(BeautifulSoup(html, 'html5lib')), e_result)
        self.assertIn("ERROR:dkb_robo.legacy:Wrapper._parse_overview() get link: 'NoneType' object is not subscriptable\n", lcm.output)

    def test_023_parse_overview(self, _unused):
        """ test DKBRobo._parse_overview() exception depot """
        html = read_file(self.dir_path + '/mocks/finanzstatus-error3.html')
        e_result = {0: {'account': 'XY99 1111 1111 0000 1111 99',
                        'amount': 1367.82,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=0&group=0',
                        'name': 'hauptkonto',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=0&group=0',
                        'type': 'account'},
                    1: {'account': '9999********1111',
                        'amount': 9613.31,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=1&group=0',
                        'name': 'first visa',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=1&group=0',
                        'type': 'creditcard'},
                    2: {'account': '9999********8888',
                        'amount': -260.42,
                        'date': '26.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=2&group=0',
                        'name': 'MilesnMoreMaster',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=2&group=0',
                        'type': 'creditcard'},
                    3: {'account': '9999********2222',
                        'amount': 515.52,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=0&group=1',
                        'name': 'second visa',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=0&group=1',
                        'type': 'creditcard'},
                    4: {'account': 'XY99 1111 1111 2155 2788 99',
                        'amount': 588.37,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=1&group=1',
                        'name': 'zweitkonto',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=1&group=1',
                        'type': 'account'},
                    5: {'account': '9999********3333',
                        'amount': 515.52,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=2&group=1',
                        'name': '3rd visa',
                        'transactions': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=paymentTransaction&row=2&group=1',
                        'type': 'creditcard'},
                    6: {'account': 'XY99 3333 1111 0000 3333 99',
                        'amount': -334.34,
                        'date': '27.04.2018',
                        'details': 'https://www.ib.dkb.de/DkbTransactionBanking/content/banking/financialstatus/FinancialComposite/FinancialStatus.xhtml?$event=details&row=3&group=1',
                        'name': '3rd acc',
                        'type': 'depot'}}
        with self.assertLogs('dkb_robo', level='INFO') as lcm:
            self.assertEqual(e_result, self.wrapper._parse_overview(BeautifulSoup(html, 'html5lib')))
        self.assertIn("ERROR:dkb_robo.legacy:Wrapper._parse_overview() parse depot: 'NoneType' object is not subscriptable\n", lcm.output)

    def test_024_parse_overview_mbank(self, _unused):
        """ test DKBRobo._parse_overview() method for accounts from other banks"""
        html = read_file(self.dir_path + '/mocks/finanzstatus-mbank.html')
        e_result = {0: {'account': '1111********1111',
                        'name': 'credit-card-1',
                        'transactions': 'https://www.ib.dkb.de/tcc-1',
                        'amount': 1000.0,
                        'details': 'https://www.ib.dkb.de/dcc-1',
                        'date': '01.03.2017',
                        'type': 'creditcard'},
                    1: {'account': '1111********1112',
                        'name': 'credit-card-2',
                        'transactions': 'https://www.ib.dkb.de/tcc-2',
                        'amount': 2000.0,
                        'details': 'https://www.ib.dkb.de/dcc-2',
                        'date': '02.03.2017',
                        'type': 'creditcard'},
                    2: {'account': 'DE11 1111 1111 1111 1111 11',
                        'name': 'checking-account-1',
                        'transactions': 'https://www.ib.dkb.de/tac-1',
                        'amount': 1000.0,
                        'details': 'https://www.ib.dkb.de/banking/dac-1',
                        'date': '03.03.2017',
                        'type': 'account'},
                    3: {'account': 'DE11 1111 1111 1111 1111 12',
                        'name': 'checking-account-2',
                        'transactions': 'https://www.ib.dkb.de/tac-2',
                        'amount': 2000.0,
                        'details': 'https://www.ib.dkb.de/banking/dac-2',
                        'date': '04.03.2017',
                        'type': 'account'},
                    4: {'account': '1111111',
                        'name': 'Depot-1',
                        'transactions': 'https://www.ib.dkb.de/tdepot-1',
                        'amount': 5000.0,
                        'details': 'https://www.ib.dkb.de/ddepot-1',
                        'date': '06.03.2017',
                        'type': 'depot'},
                    5: {'account': '1111112',
                        'name': 'Depot-2',
                        'transactions': 'https://www.ib.dkb.de/tdepot-2',
                        'amount': 6000.0,
                        'details': 'https://www.ib.dkb.de/ddepot-2',
                        'date': '06.03.2017',
                        'type': 'depot'}}
        self.assertEqual(self.wrapper._parse_overview(BeautifulSoup(html, 'html5lib')), e_result)

    def test_025_get_document_links(self, mock_browser):
        """ test DKBRobo._get_document_links() method """
        html = read_file(self.dir_path + '/mocks/doclinks.html')
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        e_result = {'Kontoauszug Nr. 003_2017 zu Konto 87654321': 'https://www.ib.dkb.de/doc-2',
                    'Kontoauszug Nr. 003_2017 zu Konto 12345678': 'https://www.ib.dkb.de/doc-1'}
        self.assertEqual(self.wrapper._get_document_links('http://foo.bar/foo'), e_result)

    @patch('dkb_robo.legacy.Wrapper._update_downloadstate')
    @patch('dkb_robo.legacy.Wrapper._get_document')
    def test_026_get_document_links(self, mock_doc, mock_updow, mock_browser):
        """ test DKBRobo._get_document_links() method """
        html = read_file(self.dir_path + '/mocks/doclinks-2.html')
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        mock_doc.return_value = (200, 'fname', ['foo'])
        e_result = {'Kontoauszug Nr. 003_2017 zu Konto 12345678': {'rcode': 200, 'link': 'https://www.ib.dkb.de/doc-1', 'fname': 'fname'}, 'Kontoauszug Nr. 003_2017 zu Konto 87654321': {'rcode': 200, 'link': 'https://www.ib.dkb.de/doc-2', 'fname': 'fname'}}
        self.assertEqual(e_result, self.wrapper._get_document_links('http://foo.bar/foo', path='path'))
        self.assertTrue(mock_updow.called)

    @patch('dkb_robo.legacy.Wrapper._update_downloadstate')
    @patch('dkb_robo.legacy.Wrapper._get_document')
    def test_027_get_document_links(self, mock_doc, mock_updow, mock_browser):
        """ test DKBRobo._get_document_links() method """
        html1 = read_file(self.dir_path + '/mocks/doclinks-3.html')
        html2 = read_file(self.dir_path + '/mocks/doclinks-2.html')
        mock_browser.get_current_page.side_effect = [BeautifulSoup(html1, 'html5lib'), BeautifulSoup(html2, 'html5lib')]
        mock_browser.open.return_value = True
        mock_doc.return_value = (None, 'fname', ['foo'])
        e_result = {'Kontoauszug Nr. 003_2017 zu Konto 23456789': 'https://www.ib.dkb.de/doc-1',
                    'Kontoauszug Nr. 003_2017 zu Konto 12345678': 'https://www.ib.dkb.de/doc-1',
                    'Kontoauszug Nr. 003_2017 zu Konto 87654321': 'https://www.ib.dkb.de/doc-2',
                    'Kontoauszug Nr. 003_2017 zu Konto 98765432': 'https://www.ib.dkb.de/doc-2'}
        self.assertEqual(e_result, self.wrapper._get_document_links('http://foo.bar/foo', path='path'))
        self.assertFalse(mock_updow.called)

    @patch('dkb_robo.legacy.Wrapper._update_downloadstate')
    @patch('dkb_robo.legacy.Wrapper._get_document')
    def test_028_get_document_links(self, mock_doc, mock_updow, mock_browser):
        """ test DKBRobo._get_document_links() method no html return """
        mock_browser.get_current_page.return_value = None
        mock_browser.open.return_value = True
        mock_doc.return_value = (None, 'fname', ['foo'])
        e_result = {}
        self.assertEqual(e_result, self.wrapper._get_document_links('http://foo.bar/foo', path='path'))
        self.assertFalse(mock_updow.called)

    @patch('dkb_robo.legacy.Wrapper._update_downloadstate')
    @patch('dkb_robo.legacy.Wrapper._get_document')
    def test_029_get_document_links(self, mock_doc, mock_updow, mock_browser):
        """ test DKBRobo._get_document_links() method  wrong html return """
        html = '<html><body>fooo</body></html>'
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        mock_browser.open.return_value = True
        mock_doc.return_value = (None, 'fname', ['foo'])
        e_result = {}
        self.assertEqual(e_result, self.wrapper._get_document_links('http://foo.bar/foo', path='path'))
        self.assertFalse(mock_updow.called)

    @patch('dkb_robo.legacy.Wrapper._get_document_links')
    def test_030_scan_postbox(self, mock_doclinks, mock_browser):
        """ test DKBRobo.scan_postbox() method """
        html = read_file(self.dir_path + '/mocks/postbox.html')
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        mock_doclinks.return_value = {}
        e_result = {'Kreditkartenabrechnungen': {'documents': {}, 'name': 'Kreditkartenabrechnungen', 'details': 'https://www.ib.dkb.de/banking/postfach/Kreditkartenabrechnungen'},
                    'Mitteilungen': {'documents': {}, 'name': 'Mitteilungen', 'details': 'https://www.ib.dkb.de/banking/postfach/Mitteilungen'},
                    'Vertragsinformationen': {'documents': {}, 'name': 'Vertragsinformationen', 'details': 'https://www.ib.dkb.de/banking/postfach/Vertragsinformationen'}}
        self.assertEqual(self.wrapper.scan_postbox(), e_result)

    @patch('dkb_robo.legacy.Wrapper._get_document_links')
    def test_031_scan_postbox(self, mock_doclinks, mock_browser):
        """ test DKBRobo.scan_postbox() method """
        html = read_file(self.dir_path + '/mocks/postbox.html')
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        mock_doclinks.return_value = {}
        e_result = {'Kreditkartenabrechnungen':
                        {'documents': {},
                         'name': 'Kreditkartenabrechnungen',
                         'details': 'https://www.ib.dkb.de/banking/postfach/Kreditkartenabrechnungen'},
                    'Mitteilungen':
                        {'documents': {},
                         'name': 'Mitteilungen',
                         'details': 'https://www.ib.dkb.de/banking/postfach/Mitteilungen'},
                    'Vertragsinformationen':
                        {'documents': {},
                         'name': 'Vertragsinformationen',
                         'details': 'https://www.ib.dkb.de/banking/postfach/Vertragsinformationen'}}
        self.assertEqual(self.wrapper.scan_postbox(path='path'), e_result)

    @patch('dkb_robo.legacy.Wrapper._get_document_links')
    def test_032_scan_postbox(self, mock_doclinks, mock_browser):
        """ test DKBRobo.scan_postbox() method """
        html = read_file(self.dir_path + '/mocks/postbox-2.html')
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        mock_doclinks.return_value = {}
        e_result = {'Kreditkartenabrechnungen':
                        {'documents': {},
                         'name': 'Kreditkartenabrechnungen',
                         'details': 'https://www.ib.dkb.de/banking/postfach/Kreditkartenabrechnungen'},
                    'Mitteilungen':
                        {'documents': {},
                         'name': 'Mitteilungen',
                         'details': 'https://www.ib.dkb.de/banking/postfach/Mitteilungen'},
                    'Vertragsinformationen':
                        {'documents': {},
                         'name': 'Vertragsinformationen',
                         'details': 'https://www.ib.dkb.de/banking/postfach/Vertragsinformationen'}}
        self.assertEqual(self.wrapper.scan_postbox(archive=True), e_result)

    def test_033_get_tr_invalid(self, _unused):
        """ test DKBRobo.get_transactions() method with an invalid account type"""
        self.assertEqual(self.wrapper.get_transactions('url', 'foo', '01.03.2017', '02.03.2017'), [])

    @patch('dkb_robo.legacy.Wrapper._get_creditcard_transactions')
    def test_034_get_tr_cc(self, mock_cc_tran, _unused):
        """ test DKBRobo.get_transactions() method with an credit-card account"""
        mock_cc_tran.return_value = ['credit_card']
        self.assertEqual(self.wrapper.get_transactions('url', 'creditcard', '01.03.2017', '02.03.2017'), ['credit_card'])
        self.assertTrue(mock_cc_tran.called)

    @patch('dkb_robo.legacy.Wrapper._get_account_transactions')
    def test_035_get_tr_ac(self, mock_ca_tran, _unused):
        """ test DKBRobo.get_transactions() method with an checking account"""
        mock_ca_tran.return_value = ['account']
        self.assertEqual(self.wrapper.get_transactions('url', 'account', '01.03.2017', '02.03.2017'), ['account'])
        self.assertTrue(mock_ca_tran.called)

    @patch('dkb_robo.legacy.Wrapper._get_depot_status')
    def test_036_get_tr_ac(self, mock_dep_tran, _unused):
        """ test DKBRobo.get_transactions() method for a deptot """
        mock_dep_tran.return_value = ['dep']
        self.assertEqual(self.wrapper.get_transactions('url', 'depot', '01.03.2017', '02.03.2017'), ['dep'])
        self.assertTrue(mock_dep_tran.called)

    def test_037_parse_account_tr(self, _mock_browser):
        """ test DKBRobo.get_account_transactions for one page only """
        csv = read_file(self.dir_path + '/mocks/test_parse_account_tr.csv')
        result = [
            {'amount': 100.0, 'bdate': '01.03.2017', 'customerreferenz': 'Kundenreferenz1', 'customerreference': 'Kundenreferenz1', 'date': '01.03.2017', 'mandatereference': 'Mandatsreferenz1', 'peer': 'Auftraggeber1', 'peeraccount': 'Kontonummer1', 'peerbic': 'BLZ1', 'peerid': 'GID1', 'postingtext': 'Buchungstext1', 'reasonforpayment': 'Verwendungszweck1', 'text': 'Buchungstext1 Auftraggeber1 Verwendungszweck1', 'vdate': '01.03.2017'},
            {'amount': -200.0, 'bdate': '02.03.2017', 'customerreferenz': 'Kundenreferenz2', 'customerreference': 'Kundenreferenz2', 'date': '02.03.2017', 'mandatereference': 'Mandatsreferenz2', 'peer': 'Auftraggeber2', 'peeraccount': 'Kontonummer2', 'peerbic': 'BLZ2', 'peerid': 'GID2', 'postingtext': 'Buchungstext2', 'reasonforpayment': 'Verwendungszweck2', 'text': 'Buchungstext2 Auftraggeber2 Verwendungszweck2', 'vdate': '02.03.2017'},
            {'amount': 3000.0, 'bdate': '03.03.2017', 'customerreferenz': 'Kundenreferenz3', 'customerreference': 'Kundenreferenz3', 'date': '03.03.2017', 'mandatereference': 'Mandatsreferenz3', 'peer': 'Auftraggeber3', 'peeraccount': 'Kontonummer3', 'peerbic': 'BLZ3', 'peerid': 'GID3', 'postingtext': 'Buchungstext3', 'reasonforpayment': 'Verwendungszweck3', 'text': 'Buchungstext3 Auftraggeber3 Verwendungszweck3', 'vdate': '03.03.2017'},
            {'amount': -4000.0, 'bdate': '04.03.2017', 'customerreferenz': 'Kundenreferenz4', 'customerreference': 'Kundenreferenz4', 'date': '04.03.2017', 'mandatereference': 'Mandatsreferenz4', 'peer': 'Auftraggeber4', 'peeraccount': 'Kontonummer4', 'peerbic': 'BLZ4', 'peerid': 'GID4', 'postingtext': 'Buchungstext4', 'reasonforpayment': 'Verwendungszweck4', 'text': 'Buchungstext4 Auftraggeber4 Verwendungszweck4', 'vdate': '04.03.2017'}]

        self.assertEqual(result, self.wrapper._parse_account_transactions(csv))

    def test_038_parse_no_account_tr(self, _mock_browser):
        """ test DKBRobo.get_account_transactions for one page only """
        csv = read_file(self.dir_path + '/mocks/test_parse_no_account_tr.csv')
        self.assertEqual(self.wrapper._parse_account_transactions(csv), [])

    def test_039_parse_dkb_cc_tr(self, _mock_browser):
        """ test DKBRobo._parse_cc_transactions """
        csv = read_file(self.dir_path + '/mocks/test_parse_dkb_cc_tr.csv')
        self.assertEqual(self.wrapper._parse_cc_transactions(csv), [{'amount': -100.00,
                                                                'amount_original': '-110',
                                                                'bdate': '01.03.2017',
                                                                'show_date': '01.03.2017',
                                                                'store_date': '01.03.2017',
                                                                'text': 'AAA',
                                                                'vdate': '01.03.2017'},
                                                               {'amount': -200.00,
                                                                'amount_original': '-210',
                                                                'bdate': '02.03.2017',
                                                                'show_date': '02.03.2017',
                                                                'store_date': '02.03.2017',
                                                                'text': 'BBB',
                                                                'vdate': '02.03.2017'},
                                                               {'amount': -300.00,
                                                                'amount_original': '-310',
                                                                'bdate': '03.03.2017',
                                                                'show_date': '03.03.2017',
                                                                'store_date': '03.03.2017',
                                                                'text': 'CCC',
                                                                'vdate': '03.03.2017'}])

    def test_040_parse_no_cc_tr(self, _mock_browser):
        """ test DKBRobo._parse_cc_transactions """
        csv = read_file(self.dir_path + '/mocks/test_parse_no_cc_tr.csv')
        self.assertEqual(self.wrapper._parse_cc_transactions(csv), [])

    def test_041_get_financial_statement(self, mock_browser):
        """ get financial statement """
        html = '<html><head>header</head><body>body</body></html>'
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        self.assertEqual('<html><head></head><body>headerbody</body></html>', str(self.wrapper._get_financial_statement()))

    def test_042_get_financial_statement(self, mock_browser):
        """ get financial statement with tan_insert """
        html = '<html><head>header</head><body>body</body></html>'
        self.wrapper.tan_insert = True
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        self.assertEqual('<html><head></head><body>headerbody</body></html>', str(self.wrapper._get_financial_statement()))

    @patch('dkb_robo.legacy.Wrapper._parse_account_transactions')
    def test_043_get_account_transactions(self, mock_parse, mock_browser):
        """ test _get_account_transactions """
        mock_browser.get_current_page.return_value = 'mock_browser'
        mock_parse.return_value = 'mock_parse'
        self.assertEqual('mock_parse', self.wrapper._get_account_transactions('url', 'date_from', 'date_to'))

    @patch('dkb_robo.legacy.Wrapper._parse_account_transactions')
    def test_044_get_account_transactions(self, mock_parse, mock_browser):
        """ test _get_account_transactions """
        mock_browser.get_current_page.return_value = 'mock_browser'
        mock_parse.return_value = 'mock_parse'
        self.assertEqual('mock_parse', self.wrapper._get_account_transactions('url', 'date_from', 'date_to', transaction_type='reserved'))

    @patch('dkb_robo.legacy.Wrapper._parse_cc_transactions')
    def test_045_get_cc_transactions(self, mock_parse, mock_browser):
        """ test _get_account_transactions """
        mock_browser.get_current_page.return_value = 'mock_browser'
        mock_parse.return_value = 'mock_parse'
        self.assertEqual('mock_parse', self.wrapper._get_creditcard_transactions('url', 'date_from', 'date_to'))

    @patch('dkb_robo.legacy.Wrapper._parse_cc_transactions')
    def test_046_get_cc_transactions(self, mock_parse, mock_browser):
        """ test _get_account_transactions """
        mock_browser.get_current_page.return_value = 'mock_browser'
        mock_parse.return_value = 'mock_parse'
        self.assertEqual('mock_parse', self.wrapper._get_creditcard_transactions('url', 'date_from', 'date_to', transaction_type='reserved'))

    def test_047_update_downloadstate(self, _unused):
        """ test update downloadstats """
        url = 'https://www.ib.dkb.de/DkbTransactionBanking/content/mailbox/MessageList/%24{1}.xhtml?$event=updateDownloadState&row=1'
        self.assertFalse(self.wrapper._update_downloadstate(link_name='link_name', url=url))

    def test_048_update_downloadstate(self, _unused):
        """ test update downloadstats """
        url = 'https://www.ib.dkb.de/DkbTransactionBanking/content/mailbox/MessageList/%24{1}.xhtml?$event=updateDownloadState&row=1'
        self.assertFalse(self.wrapper._update_downloadstate(link_name='Kontoauszüge', url=url))

    @patch('dkb_robo.legacy.generate_random_string')
    @patch('os.makedirs')
    @patch('os.path.exists')
    def test_049_get_document(self, mock_exists, mock_makedir, mock_rand, _unused):
        """ test get_document create path """
        mock_exists.return_value = False
        mock_rand.return_value = 'mock_rand'
        self.assertEqual((None, 'path/mock_rand.pdf', []), self.wrapper._get_document('folder_url', 'path', 'url', [], False))
        self.assertTrue(mock_makedir.called)
        self.assertTrue(mock_rand.called)

    @patch('dkb_robo.legacy.generate_random_string')
    @patch('os.makedirs')
    @patch('os.path.exists')
    def test_050_get_document(self, mock_exists, mock_makedir, mock_rand, _unused):
        """ test get_document create path """
        mock_exists.return_value = True
        mock_rand.return_value = 'mock_rand'
        self.assertEqual((None, 'path/mock_rand.pdf', []), self.wrapper._get_document('folder_url', 'path', 'url', [], False))
        self.assertFalse(mock_makedir.called)
        self.assertTrue(mock_rand.called)

    @patch("builtins.open", mock_open(read_data='test'), create=True)
    @patch('re.findall')
    @patch('dkb_robo.utilities.generate_random_string')
    @patch('os.makedirs')
    @patch('os.path.exists')
    def test_051_get_document(self, mock_exists, mock_makedir, mock_rand, mock_re, mock_browser):
        """ test get_document create path """
        mock_exists.return_value = True
        mock_rand.return_value = 'mock_rand'
        mock_browser.open.return_value.headers = {'Content-Disposition': ['foo', 'bar']}
        mock_browser.open.return_value.status_code = 200
        mock_re.return_value = ['mock_re.pdf', 'mock_re2.pdf']
        self.assertEqual((200, 'path/mock_re.pdf', ['mock_re.pdf']), self.wrapper._get_document('folder_url', 'path', 'url', [], False))
        self.assertFalse(mock_makedir.called)

    @patch('dkb_robo.legacy.datetime', Mock(now=lambda: date(2022, 9, 30)))
    @patch("builtins.open", mock_open(read_data='test'), create=True)
    @patch('re.findall')
    @patch('dkb_robo.utilities.generate_random_string')
    @patch('os.makedirs')
    @patch('os.path.exists')
    def test_052_get_document(self, mock_exists, mock_makedir, mock_rand, mock_re, mock_browser):
        """ test get_document override """
        mock_exists.return_value = True
        mock_rand.return_value = 'mock_rand'
        mock_browser.open.return_value.headers = {'Content-Disposition': ['foo', 'bar']}
        mock_browser.open.return_value.status_code = 200
        mock_re.return_value = ['mock_re.pdf', 'mock_re2.pdf']
        self.assertEqual((200, 'path/2022-09-30-00-00-00_mock_re.pdf', ['mock_re.pdf', '2022-09-30-00-00-00_mock_re.pdf']), self.wrapper._get_document('folder_url', 'path', 'url', ['mock_re.pdf'], False))
        self.assertFalse(mock_makedir.called)

    @patch("builtins.open", mock_open(read_data='test'), create=True)
    @patch('os.makedirs')
    @patch('os.path.exists')
    def test_053_get_document(self, mock_exists, mock_makedir, mock_browser):
        """ test get_document create path """
        mock_exists.return_value = True
        mock_browser.open.return_value.headers = {'Content-Disposition': 'inline; filename=Mitteilung_%c3%bcber_steigende_Sollzinss%c3%a4tze_ab_01.10.2022.pdf'}
        mock_browser.open.return_value.status_code = 200
        self.assertEqual((200, 'path/Mitteilung_über_steigende_Sollzinssätze_ab_01.10.2022.pdf', ['Mitteilung_über_steigende_Sollzinssätze_ab_01.10.2022.pdf']), self.wrapper._get_document('folder_url', 'path', 'url', [], False))
        self.assertFalse(mock_makedir.called)

    @patch('dkb_robo.legacy.datetime', Mock(now=lambda: date(2022, 9, 30)))
    @patch("builtins.open", mock_open(read_data='test'), create=True)
    @patch('os.makedirs')
    @patch('os.path.exists')
    def test_054_get_document(self, mock_exists, mock_makedir, mock_browser):
        """ test get_document create path """
        mock_exists.return_value = True
        mock_browser.open.return_value.headers = {'Content-Disposition': 'inline; filename=Mitteilung_%c3%bcber_steigende_Sollzinss%c3%a4tze_ab_01.10.2022.pdf'}
        mock_browser.open.return_value.status_code = 200
        self.assertEqual((200, 'path/2022-09-30-00-00-00_Mitteilung_über_steigende_Sollzinssätze_ab_01.10.2022.pdf', ['Mitteilung_über_steigende_Sollzinssätze_ab_01.10.2022.pdf', '2022-09-30-00-00-00_Mitteilung_über_steigende_Sollzinssätze_ab_01.10.2022.pdf']), self.wrapper._get_document('folder_url', 'path', 'url', ['Mitteilung_über_steigende_Sollzinssätze_ab_01.10.2022.pdf'], False))
        self.assertFalse(mock_makedir.called)

    @patch("builtins.open", mock_open(read_data='test'), create=True)
    @patch('os.makedirs')
    @patch('os.path.exists')
    def test_055_get_document(self, mock_exists, mock_makedir, mock_browser):
        """ test get_document create path """
        mock_exists.return_value = True
        mock_browser.open.return_value.headers = {'Content-Disposition': 'inline; filename=foo.pdf'}
        mock_browser.open.return_value.status_code = 200
        self.assertEqual((200, 'path/foo.pdf', ['foo.pdf']), self.wrapper._get_document('folder_url', 'path', 'url', [], False))
        self.assertFalse(mock_makedir.called)

    @patch('dkb_robo.legacy.datetime', Mock(now=lambda: date(2022, 9, 30)))
    @patch("builtins.open", mock_open(read_data='test'), create=True)
    @patch('os.makedirs')
    @patch('os.path.exists')
    def test_056_get_document(self, mock_exists, mock_makedir, mock_browser):
        """ test get_document create path """
        mock_exists.return_value = True
        mock_browser.open.return_value.headers = {'Content-Disposition': 'inline; filename=foo.pdf'}
        mock_browser.open.return_value.status_code = 200
        self.assertEqual((200, 'path/2022-09-30-00-00-00_foo.pdf', ['foo.pdf', '2022-09-30-00-00-00_foo.pdf']), self.wrapper._get_document('folder_url', 'path', 'url', ['foo.pdf'], False))
        self.assertFalse(mock_makedir.called)

    @patch("builtins.open", mock_open(read_data='test'), create=True)
    @patch('urllib.parse.unquote')
    @patch('os.makedirs')
    @patch('os.path.exists')
    def test_057_get_document(self, mock_exists, mock_makedir, mock_parse, mock_browser):
        """ test get_document create path """
        mock_exists.return_value = True
        mock_browser.open.return_value.headers = {'Content-Disposition': 'inline; filename=Mitteilung_%c3%bcber_steigende_Sollzinss%c3%a4tze_ab_01.10.2022.pdf'}
        mock_browser.open.return_value.status_code = 200
        mock_parse.side_effect = [Exception('exc1')]
        self.assertEqual((200, 'path/Mitteilung_%c3%bcber_steigende_Sollzinss%c3%a4tze_ab_01.10.2022.pdf', ['Mitteilung_%c3%bcber_steigende_Sollzinss%c3%a4tze_ab_01.10.2022.pdf']), self.wrapper._get_document('folder_url', 'path', 'url', [], False))
        self.assertFalse(mock_makedir.called)

    @patch("builtins.open", mock_open(read_data='test'), create=True)
    @patch('os.makedirs')
    @patch('os.path.exists')
    def test_058_get_document(self, mock_exists, mock_makedir, mock_browser):
        """ test get_document prepend string """
        mock_exists.return_value = True
        mock_browser.open.return_value.headers = {'Content-Disposition': 'inline; filename=Mitteilung_%c3%bcber_steigende_Sollzinss%c3%a4tze_ab_01.10.2022.pdf'}
        mock_browser.open.return_value.status_code = 200
        self.assertEqual((200, 'path/prepend_Mitteilung_über_steigende_Sollzinssätze_ab_01.10.2022.pdf', ['prepend_Mitteilung_über_steigende_Sollzinssätze_ab_01.10.2022.pdf']), self.wrapper._get_document('folder_url', 'path', 'url', [], 'prepend_'))
        self.assertFalse(mock_makedir.called)

    @patch("builtins.open", mock_open(read_data='test'), create=True)
    @patch('os.makedirs')
    @patch('os.path.exists')
    def test_059_get_document(self, mock_exists, mock_makedir, mock_browser):
        """ test get_document create path """
        mock_exists.return_value = True
        mock_browser.open.return_value.headers = {'Content-Disposition': 'inline; filename=foo.pdf'}
        mock_browser.open.return_value.status_code = 200
        self.assertEqual((200, 'path/prepend_foo.pdf', ['prepend_foo.pdf']), self.wrapper._get_document('folder_url', 'path', 'url', [], 'prepend_'))
        self.assertFalse(mock_makedir.called)

    @patch('builtins.input')
    def test_060_ctan_check(self, mock_input, mock_browser):
        """ test ctan_check """
        mock_input.return_value = 'tan'
        html = '<html><head>header</head><body><ol><li>li</li></ol></body></html>'
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        self.assertTrue(self.wrapper._ctan_check('soup'))

    @patch('builtins.input')
    def test_061_ctan_check(self, mock_input, mock_browser):
        """ test ctan_check """
        mock_input.return_value = 'tan'
        html = '<html><head>header</head><body>body</body></html>'
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        self.assertTrue(self.wrapper._ctan_check('soup'))

    @patch('builtins.input')
    def test_062_ctan_check(self, mock_input, mock_browser):
        """ test ctan_check wrong tan """
        mock_input.return_value = 'tan'
        html = '<html><head>header</head><body><div class="clearfix module text errorMessage">div</div></body></html>'
        mock_browser.get_current_page.return_value = BeautifulSoup(html, 'html5lib')
        with self.assertRaises(Exception) as err:
            self.wrapper._ctan_check('soup')
        self.assertEqual('Login failed due to wrong TAN', str(err.exception))

    @patch('dkb_robo.legacy.Wrapper._check_confirmation')
    def test_063_login_confirm(self, mock_confirm, mock_browser, ):
        """ test login confirmed check_cofirmation returns true """
        mock_browser.open.return_value.json.return_value = {"foo": "bar"}
        mock_confirm.return_value = True
        self.assertTrue(self.wrapper._login_confirm())

    @patch('time.sleep', return_value=None)
    @patch('dkb_robo.legacy.Wrapper._check_confirmation')
    def test_064_login_confirm(self, mock_confirm, _mock_sleep, mock_browser):
        """ test login confirmed check_cofirmation returns multiple false but then true """
        mock_browser.open.return_value.json.return_value = {"foo": "bar"}
        mock_confirm.side_effect = [False, False, False, True]
        self.assertTrue(self.wrapper._login_confirm())

    @patch('time.sleep', return_value=None)
    @patch('dkb_robo.legacy.Wrapper._check_confirmation')
    def test_065_login_confirm(self, mock_confirm, _mock_sleep, mock_browser):
        """ test login confirmed  """
        mock_browser.open.return_value.json.return_value = {"foo": "bar"}
        mock_confirm.return_value = False
        with self.assertRaises(Exception) as err:
            self.assertFalse(self.wrapper._login_confirm())
        self.assertEqual('No session confirmation after 120 polls', str(err.exception))

    def test_066_login_confirm(self, mock_browser):
        """ test login confirmed - exception when getting the token """
        mock_browser.open.return_value.json.return_value = {"foo": "bar"}
        mock_browser.get_current_page.side_effect = Exception('exc')
        with self.assertRaises(Exception) as err:
            self.assertTrue(self.wrapper._login_confirm())
        self.assertEqual('Error while getting the confirmation page', str(err.exception))

    def test_067_check_confirmation(self, _unused):
        """ test confirmation """
        result = {'foo': 'bar'}
        with self.assertRaises(Exception) as err:
            self.wrapper._check_confirmation(result, 1)
        self.assertEqual('Error during session confirmation', str(err.exception))

    def test_068_check_confirmation(self, _unused):
        """ test confirmation state expired"""
        result = {'state': 'EXPIRED'}
        with self.assertRaises(Exception) as err:
            self.wrapper._check_confirmation(result, 1)
        self.assertEqual('Session expired', str(err.exception))

    def test_069_check_confirmation(self, _unused):
        """ test confirmation state processed"""
        result = {'state': 'PROCESSED'}
        self.assertTrue(self.wrapper._check_confirmation(result, 1))

    def test_070_check_confirmation(self, _unused):
        """ test confirmation state unknown """
        result = {'state': 'UNK'}
        self.assertFalse(self.wrapper._check_confirmation(result, 1))

    def test_071_check_confirmation(self, _unused):
        """ test confirmation guiState expired"""
        result = {'guiState': 'EXPIRED'}
        with self.assertRaises(Exception) as err:
            self.wrapper._check_confirmation(result, 1)
        self.assertEqual('Session expired', str(err.exception))

    def test_072_check_confirmation(self, _unused):
        """ test confirmation guiState MAP_TO_EXIT"""
        result = {'guiState': 'MAP_TO_EXIT'}
        self.assertTrue(self.wrapper._check_confirmation(result, 1))

    def test_073_check_confirmation(self, _unused):
        """ test confirmation guiState unknown """
        result = {'guiState': 'UNK'}
        self.assertFalse(self.wrapper._check_confirmation(result, 1))

    def test_074_parse_depot_status_tr(self, _mock_browser):
        """ test DKBRobo._parse_cc_transactions """
        csv = read_file(self.dir_path + '/mocks/test_parse_depot.csv')
        result = [{'shares': 10.0, 'shares_unit': 'cnt1', 'isin_wkn': 'WKN1', 'text': 'Bezeichnung1', 'price': 11.0, 'win_loss': '', 'win_loss_currency': '', 'aquisition_cost': '', 'aquisition_cost_currency': '', 'dev_price': '', 'price_euro': 1110.1, 'availability': 'Frei'}, {'shares': 20.0, 'shares_unit': 'cnt2', 'isin_wkn': 'WKN2', 'text': 'Bezeichnung2', 'price': 12.0, 'win_loss': '', 'win_loss_currency': '', 'aquisition_cost': '', 'aquisition_cost_currency': '', 'dev_price': '', 'price_euro': 2220.2, 'availability': 'Frei'}]
        self.assertEqual(result, self.wrapper._parse_depot_status(csv))

    @patch('dkb_robo.legacy.Wrapper._parse_depot_status')
    def test_075_get_depot_status(self, mock_pds, _unused):
        """ test get depot status """
        mock_pds.return_value = 'mock_pds'
        self.assertEqual('mock_pds', self.wrapper._get_depot_status('url', 'fdate', 'tdate', 'booked'))

    @patch('dkb_robo.legacy.Wrapper._get_document')
    def test_076_legacy_download_document(self, mock_get_doc, _ununsed):
        """ test download document """
        html = read_file(self.dir_path + '/mocks/document_list.html')
        table = BeautifulSoup(html, 'html5lib')
        mock_get_doc.side_effect = my_side_effect
        class_filter = {}
        doc_dic = {'Name 04.01.2022': {'rcode': 200, 'link': 'https://www.ib.dkb.dehttps://www.dkb.de/DkbTransactionBanking/content/mailbox/MessageList.xhtml?$event=getMailboxAttachment&filename=Name+04.01.2022&row=0', 'fname': 'path/link_name'}}
        result = (doc_dic, [''])
        self.assertEqual(result, self.wrapper._download_document('folder_url', 'path', class_filter, 'link_name', table, False))

    @patch('dkb_robo.legacy.Wrapper._get_document')
    def test_077_legacy_download_document(self, mock_get_doc, _ununsed):
        """ test download document prepend date """
        html = read_file(self.dir_path + '/mocks/document_list.html')
        table = BeautifulSoup(html, 'html5lib')
        mock_get_doc.side_effect = my_side_effect
        class_filter = {}
        doc_dic = {'Name 04.01.2022': {'rcode': 200, 'link': 'https://www.ib.dkb.dehttps://www.dkb.de/DkbTransactionBanking/content/mailbox/MessageList.xhtml?$event=getMailboxAttachment&filename=Name+04.01.2022&row=0', 'fname': 'path/link_name'}}
        result = (doc_dic, ['2022-01-04_'])
        self.assertEqual(result, self.wrapper._download_document('folder_url', 'path', class_filter, 'link_name', table, True))

    @patch('dkb_robo.legacy.Wrapper._get_document')
    def test_078_legacy_download_document(self, mock_get_doc, _ununsed):
        """ test download document prepend date """
        html = read_file(self.dir_path + '/mocks/document_list-2.html')
        table = BeautifulSoup(html, 'html5lib')
        mock_get_doc.side_effect = my_side_effect
        class_filter = {}
        doc_dic = {'Name 04.01.2022': {'rcode': 200, 'link': 'https://www.ib.dkb.dehttps://www.dkb.de/DkbTransactionBanking/content/mailbox/MessageList.xhtml?$event=getMailboxAttachment&filename=Name+04.01.2022&row=0', 'fname': 'path/link_name'}}
        result = (doc_dic, [''])
        with self.assertLogs('dkb_robo', level='INFO') as lcm:
            self.assertEqual(result, self.wrapper._download_document('folder_url', 'path', class_filter, 'link_name', table, True))
        self.assertIn("ERROR:dkb_robo.legacy:Can't parse date, this could i.e. be for archived documents.", lcm.output)

    def test_079__get_formatted_date(self, _ununsed):
        """ test _get_formatted_date() prepend True """
        html = '<table><tr><td>foo</td><td class="abaxx-aspect-messageWithState-mailboxMessage-created">04.01.2022</td><td>bar</td></tr><table>'
        table = BeautifulSoup(html, 'html5lib')
        self.assertEqual('2022-01-04_', self.wrapper._get_formatted_date(True, table))

    def test_080__get_formatted_date(self, _ununsed):
        """ test _get_formatted_date() prepend False """
        html = '<table><tr><td>foo</td><td class="abaxx-aspect-messageWithState-mailboxMessage-created">04.01.2022</td><td>bar</td></tr><table>'
        table = BeautifulSoup(html, 'html5lib')
        self.assertEqual('', self.wrapper._get_formatted_date(False, table))

    def test_081__get_formatted_date(self, _ununsed):
        """ test _get_formatted_date() prepend False """
        html = '<table><tr><td>foo</td><td class="abaxx-aspect-messageWithState-mailboxMessage-created">fii</td><td>bar</td></tr><table>'
        table = BeautifulSoup(html, 'html5lib')
        with self.assertLogs('dkb_robo', level='INFO') as lcm:
            self.assertEqual('', self.wrapper._get_formatted_date(True, table))
        self.assertIn("ERROR:dkb_robo.legacy:Can't parse date, this could i.e. be for archived documents.", lcm.output)

    def test_082_logout(self, _unused):
        """" test logout """
        self.wrapper.dkb_br = Mock()
        self.wrapper.dkb_br.open = Mock()
        self.assertFalse(self.wrapper.logout())
        self.assertTrue(self.wrapper.dkb_br.open.called)

    def test_083_logout(self, _unused):
        """" test logout """
        self.wrapper.dkb_br = None
        self.assertFalse(self.wrapper.logout())


if __name__ == '__main__':

    unittest.main()
