import pytest

from leapp.repository.actor_definition import ActorDefinition, ActorInspectionFailedError, MultipleActorsError
from leapp.exceptions import UnsupportedDefinitionKindError
from leapp.repository import DefinitionKind
from helpers import repository_dir
import logging
import mock

_FAKE_META_DATA = {
    'description': 'Fake Description',
    'class_name': 'FakeActor',
    'name': 'fake-actor',
    'path': 'actors/test',
    'tags': (),
    'consumes': (),
    'produces': (),
    'dialogs': (),
}


def test_actor_definition(repository_dir):
    with repository_dir.as_cwd():
        logger = logging.getLogger('leapp.actor.test')
        with mock.patch.object(logger, 'log') as log_mock:
            definition = ActorDefinition('actors/test', '.', log=log_mock)
            for kind in set(DefinitionKind.REPO_WHITELIST + DefinitionKind.ACTOR_WHITELIST):
                if kind in DefinitionKind.ACTOR_WHITELIST:
                    definition.add(kind, '.')
                else:
                    with pytest.raises(UnsupportedDefinitionKindError):
                        definition.add(kind, '.')
                    log_mock.error.assert_called_with(
                        "Attempt to add item type %s to actor that is not supported", kind.name)
                    log_mock.reset_mock()
            with mock.patch('leapp.repository.actor_definition.get_actor_metadata', return_value=_FAKE_META_DATA):
                with mock.patch('leapp.repository.actor_definition.get_actors', return_value=[True]):
                    definition._module = True
                    assert definition.consumes == _FAKE_META_DATA['consumes']
                    assert definition.produces == _FAKE_META_DATA['produces']
                    assert definition.tags == _FAKE_META_DATA['tags']
                    assert definition.class_name == _FAKE_META_DATA['class_name']
                    assert definition.dialogs == _FAKE_META_DATA['dialogs']
                    assert definition.name == _FAKE_META_DATA['name']
                    assert definition.description == _FAKE_META_DATA['description']
                    dumped = definition.dump()
                    assert dumped.pop('path') == _FAKE_META_DATA['path']
                    assert dumped.pop('name') == definition.name
                    assert dumped.pop('files') == ('.',)
                    assert dumped.pop('libraries') == ('.',)
                    assert dumped.pop('tests') == ('.',)
                    assert dumped.pop('tools') == ('.',)
                    # Assert to ensure we covered all keys
                    assert not dumped

            with pytest.raises(ActorInspectionFailedError):
                with mock.patch('leapp.repository.actor_definition.get_actors', return_value=[]):
                    definition._discovery = None
                    definition.discover()

            with pytest.raises(ActorInspectionFailedError):
                with mock.patch('leapp.repository.actor_definition.get_actors') as mocked_actors:
                    mocked_actors.side_effect = RuntimeError('Test error')
                    definition._discovery = None
                    definition.discover()

            with pytest.raises(MultipleActorsError):
                with mock.patch('leapp.repository.actor_definition.get_actor_metadata', return_value=_FAKE_META_DATA):
                    with mock.patch('leapp.repository.actor_definition.get_actors', return_value=[True, True]):
                        definition._discovery = None
                        definition.discover()

[((567, 590), 'helpers.repository_dir.as_cwd', 'repository_dir.as_cwd', ([], {}), '()\n', (588, 590), False, 'from helpers import repository_dir\n'), ((609, 646), 'logging.getLogger', 'logging.getLogger', (['"""leapp.actor.test"""'], {}), "('leapp.actor.test')\n", (626, 646), False, 'import logging\n'), ((660, 692), 'mock.patch.object', 'mock.patch.object', (['logger', '"""log"""'], {}), "(logger, 'log')\n", (677, 692), False, 'import mock\n'), ((731, 780), 'leapp.repository.actor_definition.ActorDefinition', 'ActorDefinition', (['"""actors/test"""', '"""."""'], {'log': 'log_mock'}), "('actors/test', '.', log=log_mock)\n", (746, 780), False, 'from leapp.repository.actor_definition import ActorDefinition, ActorInspectionFailedError, MultipleActorsError\n'), ((1334, 1434), 'mock.patch', 'mock.patch', (['"""leapp.repository.actor_definition.get_actor_metadata"""'], {'return_value': '_FAKE_META_DATA'}), "('leapp.repository.actor_definition.get_actor_metadata',\n    return_value=_FAKE_META_DATA)\n", (1344, 1434), False, 'import mock\n'), ((2650, 2691), 'pytest.raises', 'pytest.raises', (['ActorInspectionFailedError'], {}), '(ActorInspectionFailedError)\n', (2663, 2691), False, 'import pytest\n'), ((2900, 2941), 'pytest.raises', 'pytest.raises', (['ActorInspectionFailedError'], {}), '(ActorInspectionFailedError)\n', (2913, 2941), False, 'import pytest\n'), ((3225, 3259), 'pytest.raises', 'pytest.raises', (['MultipleActorsError'], {}), '(MultipleActorsError)\n', (3238, 3259), False, 'import pytest\n'), ((1453, 1532), 'mock.patch', 'mock.patch', (['"""leapp.repository.actor_definition.get_actors"""'], {'return_value': '[True]'}), "('leapp.repository.actor_definition.get_actors', return_value=[True])\n", (1463, 1532), False, 'import mock\n'), ((2714, 2789), 'mock.patch', 'mock.patch', (['"""leapp.repository.actor_definition.get_actors"""'], {'return_value': '[]'}), "('leapp.repository.actor_definition.get_actors', return_value=[])\n", (2724, 2789), False, 'import mock\n'), ((2964, 3022), 'mock.patch', 'mock.patch', (['"""leapp.repository.actor_definition.get_actors"""'], {}), "('leapp.repository.actor_definition.get_actors')\n", (2974, 3022), False, 'import mock\n'), ((3282, 3382), 'mock.patch', 'mock.patch', (['"""leapp.repository.actor_definition.get_actor_metadata"""'], {'return_value': '_FAKE_META_DATA'}), "('leapp.repository.actor_definition.get_actor_metadata',\n    return_value=_FAKE_META_DATA)\n", (3292, 3382), False, 'import mock\n'), ((1026, 1071), 'pytest.raises', 'pytest.raises', (['UnsupportedDefinitionKindError'], {}), '(UnsupportedDefinitionKindError)\n', (1039, 1071), False, 'import pytest\n'), ((3405, 3495), 'mock.patch', 'mock.patch', (['"""leapp.repository.actor_definition.get_actors"""'], {'return_value': '[True, True]'}), "('leapp.repository.actor_definition.get_actors', return_value=[\n    True, True])\n", (3415, 3495), False, 'import mock\n')]