def test_add_password_regenerate_password(self, pmui_empty, monkeypatch, capsys, choice, num_of_tries): # generate some random info = (username, app, email, url) info = tuple(crypto_stuff.generate_password() for _ in range(4)) monkeypatch.setattr(pm_ui.PM_UI, 'get_unique_info_from_user', lambda *args: info) count = [0] monkeypatch.setattr(pm_ui, 'how_to_generate_pw', lambda: choice) # pw = crypto_stuff.generate_password() monkeypatch.setattr(pm_ui, 'generate_pw', lambda *args: crypto_stuff.generate_password()) monkeypatch.setattr(pm_ui, 'reveal_password', lambda *args: print(f'Try {count[0]}')) def time_to_stop(*args): count[0] += 1 if count[0] >= num_of_tries: return True return False monkeypatch.setattr(pm_ui.PM_UI, 'save_password_to_db_or_not', time_to_stop) pmui_empty.add_password() printed = capsys.readouterr()[0] assert 'Password has been generated.' in printed for i in range(num_of_tries): assert f'Try {i}' in printed
def generate_pw(type_num: int) -> str: # add the cancel password option just to be sure if type_num == 0: return '' # generate using all characters if type_num == 1: return generate_password() # generate using letters and numbers if type_num == 2: return generate_password(choice=1) # user makes the password (or saves an existing one to database) if type_num == 3: while True: pw = getpass.getpass('Type the password you want: ') pw2 = getpass.getpass('Type the password again: ') if pw == pw2: if pw: return pw ans = yes_or_no_question('you did not type any password. Do you want to try again?') if ans == 'n': return '' else: ans = yes_or_no_question('Passwords were not the same. Do you want to try again?') if ans == 'n': return ''
def test_add_password(self, pmui_empty, monkeypatch, capsys): # generate some random info = (username, app, email, url) info = tuple(crypto_stuff.generate_password() for _ in range(4)) monkeypatch.setattr(pm_ui.PM_UI, 'get_unique_info_from_user', lambda *args: info) # generate a password to go with the info monkeypatch.setattr(pm_ui, 'how_to_generate_pw', lambda: 3) pw = crypto_stuff.generate_password() monkeypatch.setattr(pm_ui, 'generate_pw', lambda *args: pw) monkeypatch.setattr(pm_ui, 'yes_or_no_question', lambda *args: 'y') pmui_empty.add_password() is None # text indicating success was printed on the screen printed = capsys.readouterr()[0] success_text = f'Password for user {info[0]} to app {info[2]} has been saved to the database.' assert success_text in printed # the password and related info was saved to db pw_info = pmui_empty.pm.find_password(info[2]) # it is extremely unlikely that the previous app would show up here assert len(pw_info) == 1 assert pw_info[0][1] == info[0] assert pw_info[0][3] == pw assert pw_info[0][4] == info[2]
def test_generate_password(): pwd = cs.generate_password() assert len(pwd) == 20 # only letters and numbers chars = "abcdefghijklmnopqrstuvwxyz" chars += chars.upper() + "0123456789" pwd = cs.generate_password(20, True) assert len(pwd) == 20 for char in pwd: assert char in chars
def test_find_app_and_username(self, pmui_empty, monkeypatch, capsys): # random header line first_line = crypto_stuff.generate_password() # 'input' random app name name_of_the_app = crypto_stuff.generate_password() monkeypatch.setattr('builtins.input', lambda *args: name_of_the_app) # there is nothing so this should find nothing assert pmui_empty.find_app_and_username(first_line) is None printed = capsys.readouterr()[0] assert first_line in printed assert f'No passwords related to {name_of_the_app} found' in printed
def test_password_manager_clean_start(monkeypatch, capsys, paths, password, default_paths, inputs): inputs.insert(1, password) inputs.insert(1, password) # random app_name should be noticeable app_name = crypto_stuff.generate_password(10, True) inputs.insert(4, app_name) monkeypatch.setattr(file_locations, 'paths', paths) # clearing screen might be bad for debugging monkeypatch.setattr(pm, 'clear_screen', lambda: None) if os.name == 'nt': monkeypatch.setattr(msvcrt, 'kbhit', lambda *args: True) monkeypatch.setattr(msvcrt, 'getch', lambda *args: b'\r') else: monkeypatch.setattr(select, 'select', lambda *args: (False, None, None)) count = [-1] def give_input(prompt=None): count[0] += 1 return inputs[count[0]] monkeypatch.setattr('builtins.input', give_input) monkeypatch.setattr(getpass, 'getpass', give_input) pm.password_manager() assert app_name in capsys.readouterr()[0]
def generate_dummy_string( type_of_string: str, fernet_obj: Optional[Fernet] = None, password_hasher: Optional[cs.argon2.PasswordHasher] = None): if type_of_string == 'normal': if fernet_obj is None: fernet_obj = Fernet(Fernet.generate_key()) return cs.encrypt_text(cs.generate_password(), fernet_obj) elif type_of_string == 'key': if fernet_obj is None: fernet_obj = Fernet(Fernet.generate_key()) return fernet_obj.encrypt(Fernet.generate_key()) elif type_of_string == 'hash': if password_hasher is None: password_hasher = cs.PasswordHasher() return password_hasher.hash(cs.generate_password()) else: raise Exception('Invalid type of dummy data')
def give_input(*args): if args: return app count[0] += 1 if count[0] < 3: return crypto_stuff.generate_password() if count[0] < 5: return 1729 return '1'
def test_add_password_no_password(self, pmui_empty, monkeypatch, capsys): # generate some random info = (username, app, email, url) info = tuple(crypto_stuff.generate_password() for _ in range(4)) monkeypatch.setattr(pm_ui.PM_UI, 'get_unique_info_from_user', lambda *args: info) monkeypatch.setattr(pm_ui, 'how_to_generate_pw', lambda: 3) monkeypatch.setattr(pm_ui, 'generate_pw', lambda *args: '') pmui_empty.add_password() printed = capsys.readouterr()[0] assert 'Adding password canceled.' in printed
def test_change_password(self, pmui_w_stuff, monkeypatch, capsys, some_info, index): info_line = some_info[index] monkeypatch.setattr('builtins.input', lambda *args: info_line[2]) monkeypatch.setattr(pm_ui, 'how_to_generate_pw', lambda *args: 3) pw = crypto_stuff.generate_password() monkeypatch.setattr(pm_ui, 'generate_pw', lambda *args: pw) monkeypatch.setattr(pm_ui, 'yes_or_no_question', lambda *args: 'y') assert pmui_w_stuff.change_password() is None db_search = pmui_w_stuff.pm.find_password(info_line[2])[0] assert db_search[1:] == (*info_line[:2], pw, *info_line[2:])
def test_find_password_for_app(self, pmui_empty, monkeypatch, capsys): # 'input' random app name name_of_the_app = crypto_stuff.generate_password() monkeypatch.setattr('builtins.input', lambda *args: name_of_the_app) # if obtain_password is called, something has gone wrong def error_message(*args): print('ERROR') monkeypatch.setattr(pm_ui, 'obtain_password', error_message) assert pmui_empty.find_password_for_app() is None printed = capsys.readouterr()[0] assert 'Email' not in printed assert 'Username' not in printed assert 'ERROR' not in printed
def test_save_password_to_db_or_not(self, pmui_empty, monkeypatch, capsys, ans, is_done, text): info = tuple(crypto_stuff.generate_password() for _ in range(5)) count = [-1] def answer(*args): count[0] += 1 return ans[count[0]] monkeypatch.setattr(pm_ui, 'yes_or_no_question', answer) assert pmui_empty.save_password_to_db_or_not(info) == is_done if text: printed = capsys.readouterr()[0] assert text in printed if ans[:2] == ('y', 'y'): pw_info = pmui_empty.pm.find_password(info[3]) assert len(pw_info) == 1 # username, password and app name should be the same assert pw_info[0][1] == info[0] assert pw_info[0][3:5] == info[2:4]
def test_change_password_in_db(self, pmui_w_stuff, monkeypatch, capsys, type_choice): monkeypatch.setattr(pm_ui, 'how_to_generate_pw', lambda *args: type_choice) pw = crypto_stuff.generate_password() monkeypatch.setattr(pm_ui, 'generate_pw', lambda *args: pw) monkeypatch.setattr(pm_ui, 'reveal_password', lambda *args: print('revelation happening')) # monkeypatch.setattr(pm_ui, 'yes_or_no_question', lambda *args: 'y') monkeypatch.setattr(pm_ui.PM_UI, 'change_password_in_db_or_not', lambda *args: True) assert pmui_w_stuff.change_password_in_db( (0, '1', '2', '3', '4', '5')) is None printed = capsys.readouterr()[0] if type_choice in (1, 2): assert 'revelation happening' in printed else: assert 'revelation happening' not in printed
def password(): return crypto_stuff.generate_password(32, True)