def test_add_acount(self):
        '''
        [test conditions] remove the account file
        [test success condition] A new account file with new account is created and authenticate new account
        '''
        new_account_email_1 = Email('*****@*****.**')
        new_account_password_1 = Password('your1_password')
        new_account_email_2 = Email('*****@*****.**')
        new_account_password_2 = Password('your2_password')

        self.account.add(new_account_email_1, new_account_password_1)
        self.account.add(new_account_email_2, new_account_password_2)

        self.assertTrue(
            self.account.authenticate(new_account_email_1,
                                      new_account_password_1))
        self.assertTrue(
            self.account.authenticate(new_account_email_2,
                                      new_account_password_2))

        error_account_email = Email('*****@*****.**')
        error_account_password = Password('error_password')
        self.assertFalse(
            self.account.authenticate(new_account_email_1,
                                      error_account_password))
        self.assertFalse(
            self.account.authenticate(error_account_email,
                                      error_account_password))
    def test_delte_account(self):
        '''
        [test conditions] There are accounts in the account file
        [test success condition] The account is deleted
        '''
        account_email_deleted = Email('*****@*****.**')
        account_password_deleted = Password('your1_password')
        account_email = Email('*****@*****.**')
        account_password = Password('your2_password')

        self.account.add(account_email_deleted, account_password_deleted)
        self.account.add(account_email, account_password)
        self.account.delete(account_email_deleted)

        self.assertTrue(
            self.account.authenticate(account_email, account_password))
        self.assertFalse(
            self.account.authenticate(account_email_deleted,
                                      account_password_deleted))

        account_email_error = Email('*****@*****.**')
        account_password_error = Password('error_password')

        with self.assertRaises(KeyError):
            self.account.delete(account_email_error)

        self.assertFalse(
            self.account.authenticate(account_email_error,
                                      account_password_error))
 def update_email(self, current_email: Email, new_email: Email) -> None:
     ''' update account email
     Raises KeyError
     '''
     account = self.__load_account_file()
     password = account[current_email.value()][Item.PASSWORD.value]
     account.pop(current_email.value())
     account[new_email.value()] = {Item.PASSWORD.value: password}
     self.__write_accoutn_file(account)
    def test_email_value(self):
        value = '*****@*****.**'
        self.assertEqual(Email(value), Email(value))

        with self.assertRaises(TypeError):
            Email(None)
        with self.assertRaises(TypeError):
            Email('')
        with self.assertRaises(TypeError):
            Email('email')  # '@' is not in email string
 def update_password(self, email: Email, password: Password) -> None:
     ''' update account password
     Raises KeyError
     '''
     account = self.__load_account_file()
     account[email.value()][Item.PASSWORD.value] = password.value()
     self.__write_accoutn_file(account)
    def test_initalize_account_file(self):
        '''
        [test conditions] exist the account file
        [test success condition] A new account file with new account is created
        '''
        account_email = Email('*****@*****.**')
        account_password = Password('your_password')
        self.account.add(account_email, account_password)

        new_account_email = Email('*****@*****.**')
        new_account_password = Password('new_your_password')
        self.account.initalize(new_account_email, new_account_password)

        self.assertFalse(
            self.account.authenticate(account_email, account_password))
        self.assertTrue(
            self.account.authenticate(new_account_email, new_account_password))
    def add(self, email: Email, password: Password) -> None:
        ''' add new account that email and password
        Raise KeyError
        '''
        try:
            account = self.__load_account_file()
            if (email.value() in account):
                raise KeyError
            account[email.value()] = {Item.PASSWORD.value: password.value()}
        except IOError:
            with open(self.account_file_path, 'w'):
                account = {
                    email.value(): {
                        Item.PASSWORD.value: password.value()
                    }
                }

        self.__write_accoutn_file(account)
    def delete(self, email: Email) -> None:
        ''' delete account using email
        Raises KeyError when The account file not have the email
        Raises RuntimeError when The account file have one account
        '''
        account = self.__load_account_file()
        account.pop(email.value())
        if (not account):
            raise RuntimeError

        self.__write_accoutn_file(account)
    def test_add_acount_failure_with_duplicate_account(self):
        '''
        [test conditions] add two same email account
        [test success condition] raise KeyError
        '''
        new_account_email_1 = Email('*****@*****.**')
        new_account_password_1 = Password('your1_password')
        self.account.add(new_account_email_1, new_account_password_1)

        with self.assertRaises(KeyError):
            self.account.add(new_account_email_1, new_account_password_1)
    def authenticate(self, email: Email, password: Password) -> bool:
        ''' authenticate using email and password
        '''
        try:
            account = self.__load_account_file()
        except IOError:
            return False

        try:
            return password.verify(account[email.value()][Item.PASSWORD.value])
        except KeyError:
            return False
    def test_update_account_password(self):
        '''
        [test conditions] exist the account file
        [test success condition] The account's password is changed
        '''
        account_email = Email('*****@*****.**')
        account_password = Password('your_password')
        self.account.add(account_email, account_password)

        changed_account_password = Password('changed_password')
        self.account.update_password(account_email, changed_account_password)
        self.assertTrue(
            self.account.authenticate(account_email, changed_account_password))
        self.assertFalse(
            self.account.authenticate(account_email, account_password))

        error_account_email = Email('*****@*****.**')
        error_account_password = Password('error_password')
        with self.assertRaises(KeyError):
            self.account.update_password(error_account_email,
                                         error_account_password)
 def initalize(self, default_account_email: Email,
               default_account_password: Password) -> None:
     ''' initalize account file
     all account delete and create default account
     '''
     if (not default_account_password):
         raise TypeError
     account = self.__load_account_file()
     account.clear()
     account[default_account_email.value()] = {
         Item.PASSWORD.value: default_account_password.value()
     }
     self.__write_accoutn_file(account)
    def test_delte_account_failure_with_delet_all_account(self):
        '''
        [test conditions] There an accounts in the account file
        [test success condition] The last account is left in the account file
        '''
        account_email_deleted = Email('*****@*****.**')
        account_password_deleted = Password('your1_password')
        self.account.add(account_email_deleted, account_password_deleted)

        with self.assertRaises(RuntimeError):
            self.account.delete(account_email_deleted)

        self.assertTrue(
            self.account.authenticate(account_email_deleted,
                                      account_password_deleted))
    def test_authenticate_with_no_account_file(self):
        email = Email('*****@*****.**')
        password = Password('your_password')

        self.assertFalse(self.account.authenticate(email, password))