125 lines
3.9 KiB
Python
125 lines
3.9 KiB
Python
|
"""Test the Home Assistant local auth provider."""
|
||
|
from unittest.mock import patch, mock_open
|
||
|
|
||
|
import pytest
|
||
|
|
||
|
from homeassistant import data_entry_flow
|
||
|
from homeassistant.auth_providers import homeassistant as hass_auth
|
||
|
|
||
|
|
||
|
MOCK_PATH = '/bla/users.json'
|
||
|
JSON__OPEN_PATH = 'homeassistant.util.json.open'
|
||
|
|
||
|
|
||
|
def test_initialize_empty_config_file_not_found():
|
||
|
"""Test that we initialize an empty config."""
|
||
|
with patch('homeassistant.util.json.open', side_effect=FileNotFoundError):
|
||
|
data = hass_auth.load_data(MOCK_PATH)
|
||
|
|
||
|
assert data is not None
|
||
|
|
||
|
|
||
|
def test_adding_user():
|
||
|
"""Test adding a user."""
|
||
|
data = hass_auth.Data(MOCK_PATH, None)
|
||
|
data.add_user('test-user', 'test-pass')
|
||
|
data.validate_login('test-user', 'test-pass')
|
||
|
|
||
|
|
||
|
def test_adding_user_duplicate_username():
|
||
|
"""Test adding a user."""
|
||
|
data = hass_auth.Data(MOCK_PATH, None)
|
||
|
data.add_user('test-user', 'test-pass')
|
||
|
with pytest.raises(hass_auth.InvalidUser):
|
||
|
data.add_user('test-user', 'other-pass')
|
||
|
|
||
|
|
||
|
def test_validating_password_invalid_user():
|
||
|
"""Test validating an invalid user."""
|
||
|
data = hass_auth.Data(MOCK_PATH, None)
|
||
|
|
||
|
with pytest.raises(hass_auth.InvalidAuth):
|
||
|
data.validate_login('non-existing', 'pw')
|
||
|
|
||
|
|
||
|
def test_validating_password_invalid_password():
|
||
|
"""Test validating an invalid user."""
|
||
|
data = hass_auth.Data(MOCK_PATH, None)
|
||
|
data.add_user('test-user', 'test-pass')
|
||
|
|
||
|
with pytest.raises(hass_auth.InvalidAuth):
|
||
|
data.validate_login('test-user', 'invalid-pass')
|
||
|
|
||
|
|
||
|
def test_changing_password():
|
||
|
"""Test adding a user."""
|
||
|
user = 'test-user'
|
||
|
data = hass_auth.Data(MOCK_PATH, None)
|
||
|
data.add_user(user, 'test-pass')
|
||
|
data.change_password(user, 'new-pass')
|
||
|
|
||
|
with pytest.raises(hass_auth.InvalidAuth):
|
||
|
data.validate_login(user, 'test-pass')
|
||
|
|
||
|
data.validate_login(user, 'new-pass')
|
||
|
|
||
|
|
||
|
def test_changing_password_raises_invalid_user():
|
||
|
"""Test that we initialize an empty config."""
|
||
|
data = hass_auth.Data(MOCK_PATH, None)
|
||
|
|
||
|
with pytest.raises(hass_auth.InvalidUser):
|
||
|
data.change_password('non-existing', 'pw')
|
||
|
|
||
|
|
||
|
async def test_login_flow_validates(hass):
|
||
|
"""Test login flow."""
|
||
|
data = hass_auth.Data(MOCK_PATH, None)
|
||
|
data.add_user('test-user', 'test-pass')
|
||
|
|
||
|
provider = hass_auth.HassAuthProvider(hass, None, {})
|
||
|
flow = hass_auth.LoginFlow(provider)
|
||
|
result = await flow.async_step_init()
|
||
|
assert result['type'] == data_entry_flow.RESULT_TYPE_FORM
|
||
|
|
||
|
with patch.object(provider, '_auth_data', return_value=data):
|
||
|
result = await flow.async_step_init({
|
||
|
'username': 'incorrect-user',
|
||
|
'password': 'test-pass',
|
||
|
})
|
||
|
assert result['type'] == data_entry_flow.RESULT_TYPE_FORM
|
||
|
assert result['errors']['base'] == 'invalid_auth'
|
||
|
|
||
|
result = await flow.async_step_init({
|
||
|
'username': 'test-user',
|
||
|
'password': 'incorrect-pass',
|
||
|
})
|
||
|
assert result['type'] == data_entry_flow.RESULT_TYPE_FORM
|
||
|
assert result['errors']['base'] == 'invalid_auth'
|
||
|
|
||
|
result = await flow.async_step_init({
|
||
|
'username': 'test-user',
|
||
|
'password': 'test-pass',
|
||
|
})
|
||
|
assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||
|
|
||
|
|
||
|
async def test_saving_loading(hass):
|
||
|
"""Test saving and loading JSON."""
|
||
|
data = hass_auth.Data(MOCK_PATH, None)
|
||
|
data.add_user('test-user', 'test-pass')
|
||
|
data.add_user('second-user', 'second-pass')
|
||
|
|
||
|
with patch(JSON__OPEN_PATH, mock_open(), create=True) as mock_write:
|
||
|
await hass.async_add_job(data.save)
|
||
|
|
||
|
# Mock open calls are: open file, context enter, write, context leave
|
||
|
written = mock_write.mock_calls[2][1][0]
|
||
|
|
||
|
with patch('os.path.isfile', return_value=True), \
|
||
|
patch(JSON__OPEN_PATH, mock_open(read_data=written), create=True):
|
||
|
await hass.async_add_job(hass_auth.load_data, MOCK_PATH)
|
||
|
|
||
|
data.validate_login('test-user', 'test-pass')
|
||
|
data.validate_login('second-user', 'second-pass')
|