# coding: utf-8
"""
Test suite for spacecmd.schedule module.
"""

from unittest.mock import MagicMock, patch

# pylint: disable-next=unused-import
from helpers import shell, assert_expect, assert_list_args_expect, assert_args_expect
import spacecmd.schedule
from xmlrpc import client as xmlrpclib


class TestSCSchedule:
    """
    Test suite for "schedule" module.
    """

    @patch("spacecmd.utils.input", create=True, new=MagicMock(return_value="y"))
    @patch("spacecmd.utils.raw_input", create=True, new=MagicMock(return_value="y"))
    # pylint: disable-next=redefined-outer-name
    def test_schedule_deletearchived_without_archived(self, shell):
        """
        Test do_schedule_deletearchived with no archived actions.

        :param shell:
        :return:
        """

        shell.help_schedule_deletearchived = MagicMock()
        shell.client.schedule.listAllArchivedActions = MagicMock(return_value=[])
        shell.client.schedule.deleteActions = MagicMock()
        # pylint: disable-next=unused-variable
        logger = MagicMock()

        spacecmd.schedule.do_schedule_deletearchived(shell, "")

        assert shell.client.schedule.listAllArchivedActions.called
        assert not shell.client.schedule.deleteActions.called

    @patch("spacecmd.utils.input", create=True, new=MagicMock(return_value="y"))
    @patch("spacecmd.utils.raw_input", create=True, new=MagicMock(return_value="y"))
    # pylint: disable-next=redefined-outer-name
    def test_schedule_deletearchived_with_archived(self, shell):
        """
        Test do_schedule_deletearchived with archived actions.

        :param shell:
        :return:
        """
        archived_dummy_actions = [{"id": 1}, {"id": 2}, {"id": 3}]

        shell.help_schedule_deletearchived = MagicMock()
        shell.client.schedule.listAllArchivedActions = MagicMock()
        shell.client.schedule.listAllArchivedActions.side_effect = [
            archived_dummy_actions
        ] + [[]]
        shell.client.schedule.deleteActions = MagicMock()
        # pylint: disable-next=unused-variable
        logger = MagicMock()

        spacecmd.schedule.do_schedule_deletearchived(shell, "")

        assert shell.client.schedule.deleteActions.call_count == 1
        assert shell.client.schedule.deleteActions.call_args[0][1] == [1, 2, 3]

    @patch("spacecmd.utils.input", create=True, new=MagicMock(return_value="n"))
    @patch("spacecmd.utils.raw_input", create=True, new=MagicMock(return_value="n"))
    # pylint: disable-next=redefined-outer-name
    def test_schedule_deletearchived_with_archived_but_user_answer_is_no(self, shell):
        """
        Test do_schedule_deletearchived with archived actions and the user answers with
        no "n".

        :param shell:
        :return:
        """
        archived_dummy_actions = [{"id": 1}, {"id": 2}, {"id": 3}]

        shell.help_schedule_deletearchived = MagicMock()
        shell.client.schedule.listAllArchivedActions = MagicMock()
        shell.client.schedule.listAllArchivedActions.side_effect = [
            archived_dummy_actions
        ] + [[]]
        shell.client.schedule.deleteActions = MagicMock()
        # pylint: disable-next=unused-variable
        logger = MagicMock()

        spacecmd.schedule.do_schedule_deletearchived(shell, "")

        assert shell.client.schedule.deleteActions.call_count == 0

    @patch("spacecmd.utils.input", create=True, new=MagicMock(return_value=""))
    @patch("spacecmd.utils.raw_input", create=True, new=MagicMock(return_value=""))
    # pylint: disable-next=redefined-outer-name
    def test_schedule_deletearchived_with_archived_but_no_user_answer(self, shell):
        """
        Test do_schedule_deletearchived with archived actions, but the user gives no answer.
        This should default to no.

        :param shell:
        :return:
        """
        archived_dummy_actions = [{"id": 1}, {"id": 2}, {"id": 3}]

        shell.help_schedule_deletearchived = MagicMock()
        shell.client.schedule.listAllArchivedActions = MagicMock()
        shell.client.schedule.listAllArchivedActions.side_effect = [
            archived_dummy_actions
        ] + [[]]
        shell.client.schedule.deleteActions = MagicMock()
        # pylint: disable-next=unused-variable
        logger = MagicMock()

        spacecmd.schedule.do_schedule_deletearchived(shell, "")

        assert shell.client.schedule.deleteActions.call_count == 0

    # pylint: disable-next=redefined-outer-name
    def test_schedule_cancel_noargs(self, shell):
        """
        Test do_schedule_cancel without arguments.

        :param shell:
        :return:
        """

        shell.help_schedule_cancel = MagicMock()
        shell.client.schedule.listInProgressActions = MagicMock()
        shell.client.schedule.cancelActions = MagicMock()
        shell.user_confirm = MagicMock()
        mprint = MagicMock()
        logger = MagicMock()

        # pylint: disable-next=unused-variable
        with patch("spacecmd.schedule.print", mprint) as prt, patch(
            "spacecmd.schedule.logging",
            logger,
            # pylint: disable-next=unused-variable
        ) as lgr:
            spacecmd.schedule.do_schedule_cancel(shell, "")

        assert not shell.client.schedule.listInProgressActions.called
        assert not shell.client.schedule.cancelActions.called
        assert not shell.user_confirm.called
        assert not mprint.called
        assert not logger.warning.called
        assert shell.help_schedule_cancel.called

    # pylint: disable-next=redefined-outer-name
    def test_schedule_cancel_globbing(self, shell):
        """
        Test do_schedule_cancel with globbing.

        :param shell:
        :return:
        """

        shell.help_schedule_cancel = MagicMock()
        shell.client.schedule.listInProgressActions = MagicMock()
        shell.client.schedule.cancelActions = MagicMock()
        shell.user_confirm = MagicMock(return_value=False)
        mprint = MagicMock()
        logger = MagicMock()

        # pylint: disable-next=unused-variable
        with patch("spacecmd.schedule.print", mprint) as prt, patch(
            "spacecmd.schedule.logging",
            logger,
            # pylint: disable-next=unused-variable
        ) as lgr:
            spacecmd.schedule.do_schedule_cancel(shell, "*")

        assert not shell.client.schedule.listInProgressActions.called
        assert not shell.client.schedule.cancelActions.called
        assert not mprint.called
        assert not logger.warning.called
        assert not shell.help_schedule_cancel.called
        assert shell.user_confirm.called
        assert logger.info.called

        assert_expect(logger.info.call_args_list, "All pending actions left untouched")

    # pylint: disable-next=redefined-outer-name
    def test_schedule_cancel_invalid_action_id(self, shell):
        """
        Test do_schedule_cancel with invalid action ids.

        :param shell:
        :return:
        """

        shell.help_schedule_cancel = MagicMock()
        shell.client.schedule.listInProgressActions = MagicMock()
        shell.client.schedule.cancelActions = MagicMock()
        shell.user_confirm = MagicMock(return_value=False)
        mprint = MagicMock()
        logger = MagicMock()

        # pylint: disable-next=unused-variable
        with patch("spacecmd.schedule.print", mprint) as prt, patch(
            "spacecmd.schedule.logging",
            logger,
            # pylint: disable-next=unused-variable
        ) as lgr:
            spacecmd.schedule.do_schedule_cancel(shell, "1 two 3, and 4")

        assert not shell.help_schedule_cancel.called
        assert not shell.user_confirm.called
        assert not shell.client.schedule.listInProgressActions.called
        assert shell.client.schedule.cancelActions.called
        assert mprint.called
        assert logger.warning.called
        assert logger.info.called

        assert_list_args_expect(
            logger.warning.call_args_list,
            [
                '"two" is not a valid ID',
                '"3," is not a valid ID',
                '"and" is not a valid ID',
            ],
        )
        assert_args_expect(
            logger.info.call_args_list,
            [
                (("Canceled action: %i", 1), {}),
                (("Canceled action: %i", 4), {}),
                (("Failed action: %s", "two"), {}),
                (("Failed action: %s", "3,"), {}),
                (("Failed action: %s", "and"), {}),
            ],
        )

    # pylint: disable-next=redefined-outer-name
    def test_schedule_reschedule_noargs(self, shell):
        """
        Test do_schedule_reschedule without arguments.

        :param shell:
        :return:
        """

        shell.help_schedule_reschedule = MagicMock()
        shell.client.schedule.listInProgressActions = MagicMock()
        shell.client.schedule.rescheduleActions = MagicMock()
        shell.user_confirm = MagicMock()
        mprint = MagicMock()
        logger = MagicMock()

        # pylint: disable-next=unused-variable
        with patch("spacecmd.schedule.print", mprint) as prt, patch(
            "spacecmd.schedule.logging",
            logger,
            # pylint: disable-next=unused-variable
        ) as lgr:
            spacecmd.schedule.do_schedule_reschedule(shell, "")

        assert not shell.client.schedule.listInProgressActions.called
        assert not shell.client.schedule.rescheduleActions.called
        assert not shell.user_confirm.called
        assert not mprint.called
        assert not logger.warning.called
        assert shell.help_schedule_reschedule.called

    # pylint: disable-next=redefined-outer-name
    def test_schedule_reschedule_globbing(self, shell):
        """
        Test do_schedule_reschedule with globbing.

        :param shell:
        :return:
        """

        shell.help_schedule_reschedule = MagicMock()
        shell.client.schedule.listFailedActions = MagicMock()
        shell.client.schedule.rescheduleActions = MagicMock()
        shell.user_confirm = MagicMock(return_value=False)
        mprint = MagicMock()
        logger = MagicMock()

        # pylint: disable-next=unused-variable
        with patch("spacecmd.schedule.print", mprint) as prt, patch(
            "spacecmd.schedule.logging",
            logger,
            # pylint: disable-next=unused-variable
        ) as lgr:
            spacecmd.schedule.do_schedule_reschedule(shell, "*")

        assert not shell.client.schedule.rescheduleActions.called
        assert not mprint.called
        assert not logger.warning.called
        assert not shell.help_schedule_reschedule.called
        assert shell.client.schedule.listFailedActions.called
        assert shell.user_confirm.called

    # pylint: disable-next=redefined-outer-name
    def test_schedule_reschedule_failed_actions(self, shell):
        """
        Test do_schedule_reschedule with failed actions.

        :param shell:
        :return:
        """

        shell.help_schedule_reschedule = MagicMock()
        shell.client.schedule.listFailedActions = MagicMock(
            return_value=[{"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}]
        )
        shell.client.schedule.rescheduleActions = MagicMock()
        shell.user_confirm = MagicMock(return_value=False)
        mprint = MagicMock()
        logger = MagicMock()

        # pylint: disable-next=unused-variable
        with patch("spacecmd.schedule.print", mprint) as prt, patch(
            "spacecmd.schedule.logging",
            logger,
            # pylint: disable-next=unused-variable
        ) as lgr:
            spacecmd.schedule.do_schedule_reschedule(shell, "one 2 3, 5 and 4")

        assert not shell.help_schedule_reschedule.called
        assert not shell.user_confirm.called
        assert shell.client.schedule.rescheduleActions.called
        assert mprint.called
        assert logger.warning.called
        assert shell.client.schedule.listFailedActions.called

        assert_expect(mprint.call_args_list, "Rescheduled 2 action(s)")
        assert_list_args_expect(
            logger.warning.call_args_list,
            [
                '"one" is not a valid ID',
                '"3," is not a valid ID',
                '"5" is not a failed action',
                '"and" is not a valid ID',
            ],
        )

    # pylint: disable-next=redefined-outer-name
    def test_schedule_reschedule_missing_actions(self, shell):
        """
        Test do_schedule_reschedule with missing actions.

        :param shell:
        :return:
        """

        shell.help_schedule_reschedule = MagicMock()
        shell.client.schedule.listFailedActions = MagicMock(
            return_value=[{"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}]
        )
        shell.client.schedule.rescheduleActions = MagicMock()
        shell.user_confirm = MagicMock(return_value=False)
        mprint = MagicMock()
        logger = MagicMock()

        # pylint: disable-next=unused-variable
        with patch("spacecmd.schedule.print", mprint) as prt, patch(
            "spacecmd.schedule.logging",
            logger,
            # pylint: disable-next=unused-variable
        ) as lgr:
            spacecmd.schedule.do_schedule_reschedule(shell, "one 5 and 6")

        assert not shell.client.schedule.rescheduleActions.called
        assert not mprint.called
        assert not shell.help_schedule_reschedule.called
        assert not shell.user_confirm.called
        assert logger.warning.called
        assert shell.client.schedule.listFailedActions.called
        assert_list_args_expect(
            logger.warning.call_args_list,
            [
                '"one" is not a valid ID',
                '"5" is not a failed action',
                '"and" is not a valid ID',
                '"6" is not a failed action',
                "No failed actions to reschedule",
            ],
        )

    # pylint: disable-next=redefined-outer-name
    def test_schedule_details_noargs(self, shell):
        """
        Test do_schedule_details without arguments.

        :param shell:
        :return:
        """
        shell.client.schedule.listCompletedSystems = MagicMock()
        shell.client.schedule.listFailedSystems = MagicMock()
        shell.client.schedule.listInProgressSystems = MagicMock()
        shell.client.schedule.listAllActions = MagicMock()

        shell.help_schedule_details = MagicMock()

        mprint = MagicMock()
        logger = MagicMock()

        # pylint: disable-next=unused-variable
        with patch("spacecmd.schedule.print", mprint) as prt, patch(
            "spacecmd.schedule.logging",
            logger,
            # pylint: disable-next=unused-variable
        ) as lgr:
            spacecmd.schedule.do_schedule_details(shell, "")

        assert not shell.client.schedule.listCompletedSystems.called
        assert not shell.client.schedule.listFailedSystems.called
        assert not shell.client.schedule.listInProgressSystems.called
        assert not shell.client.schedule.listAllActions.called

        assert not mprint.called
        assert not logger.warning.called
        assert shell.help_schedule_details.called

    # pylint: disable-next=redefined-outer-name
    def test_schedule_details_invalid_action_id(self, shell):
        """
        Test do_schedule_details with invalid action ID.

        :param shell:
        :return:
        """
        shell.client.schedule.listCompletedSystems = MagicMock()
        shell.client.schedule.listFailedSystems = MagicMock()
        shell.client.schedule.listInProgressSystems = MagicMock()
        shell.client.schedule.listAllActions = MagicMock()

        shell.help_schedule_details = MagicMock()

        mprint = MagicMock()
        logger = MagicMock()

        # pylint: disable-next=unused-variable
        with patch("spacecmd.schedule.print", mprint) as prt, patch(
            "spacecmd.schedule.logging",
            logger,
            # pylint: disable-next=unused-variable
        ) as lgr:
            spacecmd.schedule.do_schedule_details(shell, "something")

        assert not shell.client.schedule.listCompletedSystems.called
        assert not shell.client.schedule.listFailedSystems.called
        assert not shell.client.schedule.listInProgressSystems.called
        assert not shell.client.schedule.listAllActions.called

        assert not mprint.called
        assert logger.warning.called
        assert not shell.help_schedule_details.called

        assert_expect(logger.warning.call_args_list, 'The ID "something" is invalid')

    # pylint: disable-next=redefined-outer-name
    def test_schedule_details_missing_action_id(self, shell):
        """
        Test do_schedule_details with the missing action ID.

        :param shell:
        :return:
        """
        shell.client.schedule.listCompletedSystems = MagicMock(return_value=[])
        shell.client.schedule.listFailedSystems = MagicMock(return_value=[])
        shell.client.schedule.listInProgressSystems = MagicMock(return_value=[])
        shell.client.schedule.listAllActions = MagicMock(
            return_value=[{"id": 1}, {"id": 2}, {"id": 3}]
        )

        shell.help_schedule_details = MagicMock()

        mprint = MagicMock()
        logger = MagicMock()

        # pylint: disable-next=unused-variable
        with patch("spacecmd.schedule.print", mprint) as prt, patch(
            "spacecmd.schedule.logging",
            logger,
            # pylint: disable-next=unused-variable
        ) as lgr:
            spacecmd.schedule.do_schedule_details(shell, "42")

        assert not mprint.called
        assert not logger.warning.called
        assert not shell.help_schedule_details.called

        assert shell.client.schedule.listCompletedSystems.called
        assert shell.client.schedule.listFailedSystems.called
        assert shell.client.schedule.listInProgressSystems.called
        assert shell.client.schedule.listAllActions.called
        assert logger.error.called

        assert_expect(logger.error.call_args_list, 'No action found with the ID "42"')

    # pylint: disable-next=redefined-outer-name
    def test_schedule_details_report(self, shell):
        """
        Test do_schedule_details report layout

        :param shell:
        :return:
        """
        shell.client.schedule.listCompletedSystems = MagicMock(
            return_value=[
                {"server_name": "one"},
                {"server_name": "two"},
                {"server_name": "three"},
            ]
        )
        shell.client.schedule.listFailedSystems = MagicMock(
            return_value=[
                {"server_name": "failed-machine"},
            ]
        )
        shell.client.schedule.listInProgressSystems = MagicMock(
            return_value=[
                {"server_name": "four"},
                {"server_name": "five"},
            ]
        )
        shell.client.schedule.listAllActions = MagicMock(
            return_value=[
                {
                    "id": 1,
                    "name": "Reboot Coffee Machine",
                    "scheduler": "qa-guy",
                    "earliest": "2019-01-01",
                },
                {
                    "id": 2,
                    "name": "Upgrade Coffee Machine",
                    "scheduler": "qa-guy",
                    "earliest": "2019-01-01",
                },
                {
                    "id": 3,
                    "name": "Reinstall Coffee Machine Firmware",
                    "scheduler": "qa-guy",
                    "earliest": "2019-01-01",
                },
            ]
        )

        shell.help_schedule_details = MagicMock()

        mprint = MagicMock()
        logger = MagicMock()

        # pylint: disable-next=unused-variable
        with patch("spacecmd.schedule.print", mprint) as prt, patch(
            "spacecmd.schedule.logging",
            logger,
            # pylint: disable-next=unused-variable
        ) as lgr:
            spacecmd.schedule.do_schedule_details(shell, "3")

        assert not logger.warning.called
        assert not shell.help_schedule_details.called
        assert not logger.error.called

        assert shell.client.schedule.listCompletedSystems.called
        assert shell.client.schedule.listFailedSystems.called
        assert shell.client.schedule.listInProgressSystems.called
        assert shell.client.schedule.listAllActions.called
        assert mprint.called

        assert_list_args_expect(
            mprint.call_args_list,
            [
                "ID:        3",
                "Action:    Reinstall Coffee Machine Firmware",
                "User:      qa-guy",
                "Date:      2019-01-01",
                "",
                "Completed:   3",
                "Failed:      1",
                "Pending:     2",
                "",
                "Completed Systems",
                "-----------------",
                "one",
                "two",
                "three",
                "",
                "Failed Systems",
                "--------------",
                "failed-machine",
                "",
                "Pending Systems",
                "---------------",
                "four",
                "five",
            ],
        )

    # pylint: disable-next=redefined-outer-name
    def test_schedule_getoutput_noargs(self, shell):
        """
        Test do_schedule_getoutput without arguments.

        :param shell:
        :return:
        """
        shell.client.schedule.listCompletedSystems = MagicMock()
        shell.client.system.getScriptResults = MagicMock()
        shell.help_schedule_getoutput = MagicMock()

        mprint = MagicMock()
        logger = MagicMock()

        # pylint: disable-next=unused-variable
        with patch("spacecmd.schedule.print", mprint) as prt, patch(
            "spacecmd.schedule.logging",
            logger,
            # pylint: disable-next=unused-variable
        ) as lgr:
            spacecmd.schedule.do_schedule_getoutput(shell, "")

        assert not shell.client.system.getScriptResults.called
        assert not shell.client.schedule.listCompletedSystems.called
        assert not mprint.called
        assert not logger.warning.called
        assert shell.help_schedule_getoutput.called

    # pylint: disable-next=redefined-outer-name
    def test_schedule_getoutput_invalid_action_id(self, shell):
        """
        Test do_schedule_getoutput with an invalid action ID.

        :param shell:
        :return:
        """
        shell.client.schedule.listCompletedSystems = MagicMock()
        shell.client.system.getScriptResults = MagicMock()
        shell.help_schedule_getoutput = MagicMock()

        mprint = MagicMock()
        logger = MagicMock()

        # pylint: disable-next=unused-variable
        with patch("spacecmd.schedule.print", mprint) as prt, patch(
            "spacecmd.schedule.logging",
            logger,
            # pylint: disable-next=unused-variable
        ) as lgr:
            spacecmd.schedule.do_schedule_getoutput(shell, "fortytwo")

        assert not shell.client.system.getScriptResults.called
        assert not shell.client.schedule.listCompletedSystems.called
        assert not mprint.called
        assert not logger.warning.called
        assert not shell.help_schedule_getoutput.called

        assert logger.error.called

        assert_expect(
            logger.error.call_args_list, '"fortytwo" is not a valid action ID'
        )

    # pylint: disable-next=redefined-outer-name
    def test_schedule_getoutput_no_script_results(self, shell):
        """
        Test do_schedule_getoutput with no script results (failed or None)

        :param shell:
        :return:
        """
        shell.client.schedule.listCompletedSystems = MagicMock(
            return_value=[
                {
                    "server_name": "web.foo.com",
                    "timestamp": "2019-01-01",
                    "message": "Message from the web.foo.com",
                },
                {
                    "server_name": "web1.foo.com",
                    "timestamp": "2019-01-01",
                    "message": "Message from the web1.foo.com as well",
                },
                {
                    "server_name": "web2.foo.com",
                    "timestamp": "2019-01-01",
                    "message": "And some more message from web2.foo.com here",
                },
            ]
        )
        shell.client.schedule.listFailedSystems = MagicMock(
            return_value=[
                {
                    "server_name": "faulty.foo.com",
                    "timestamp": "2019-01-01",
                    "message": "Nothing good is happening on faulty.foo.com",
                },
            ]
        )
        shell.client.system.getScriptResults = MagicMock(
            side_effect=xmlrpclib.Fault(faultCode=42, faultString="Happy NPE!")
        )
        shell.help_schedule_getoutput = MagicMock()

        mprint = MagicMock()
        logger = MagicMock()

        # pylint: disable-next=unused-variable
        with patch("spacecmd.schedule.print", mprint) as prt, patch(
            "spacecmd.schedule.logging",
            logger,
            # pylint: disable-next=unused-variable
        ) as lgr:
            spacecmd.schedule.do_schedule_getoutput(shell, "42")

        assert not logger.warning.called
        assert not shell.help_schedule_getoutput.called
        assert shell.client.system.getScriptResults.called
        assert shell.client.schedule.listCompletedSystems.called
        assert shell.client.schedule.listFailedSystems.called
        assert mprint.called
        assert logger.debug.called

        assert_args_expect(
            logger.debug.call_args_list,
            [
                (
                    (
                        "Exception occurrect while get script results: %s",
                        "<Fault 42: 'Happy NPE!'>",
                    ),
                    {},
                )
            ],
        )
        assert_list_args_expect(
            mprint.call_args_list,
            [
                "System:    web.foo.com",
                "Completed: 2019-01-01",
                "",
                "Output",
                "------",
                "Message from the web.foo.com",
                "----------",
                "System:    web1.foo.com",
                "Completed: 2019-01-01",
                "",
                "Output",
                "------",
                "Message from the web1.foo.com as well",
                "----------",
                "System:    web2.foo.com",
                "Completed: 2019-01-01",
                "",
                "Output",
                "------",
                "And some more message from web2.foo.com here",
                "----------",
                "System:    faulty.foo.com",
                "Completed: 2019-01-01",
                "",
                "Output",
                "------",
                "Nothing good is happening on faulty.foo.com",
            ],
        )

    # pylint: disable-next=redefined-outer-name
    def test_schedule_getoutput_no_any_results(self, shell):
        """
        Test do_schedule_getoutput with no any results available

        :param shell:
        :return:
        """
        shell.client.schedule.listCompletedSystems = MagicMock(return_value=[])
        shell.client.schedule.listFailedSystems = MagicMock(return_value=[])
        shell.client.system.getScriptResults = MagicMock(
            side_effect=xmlrpclib.Fault(faultCode=42, faultString="Happy NPE!")
        )
        shell.help_schedule_getoutput = MagicMock()

        mprint = MagicMock()
        logger = MagicMock()

        # pylint: disable-next=unused-variable
        with patch("spacecmd.schedule.print", mprint) as prt, patch(
            "spacecmd.schedule.logging",
            logger,
            # pylint: disable-next=unused-variable
        ) as lgr:
            spacecmd.schedule.do_schedule_getoutput(shell, "42")

        assert not logger.warning.called
        assert not shell.help_schedule_getoutput.called
        assert not mprint.called
        assert shell.client.system.getScriptResults.called
        assert shell.client.schedule.listCompletedSystems.called
        assert shell.client.schedule.listFailedSystems.called
        assert logger.debug.called
        assert logger.error.called

        assert_args_expect(
            logger.debug.call_args_list,
            [
                (
                    (
                        "Exception occurrect while get script results: %s",
                        "<Fault 42: 'Happy NPE!'>",
                    ),
                    {},
                )
            ],
        )
        assert_args_expect(logger.error.call_args_list, [(("No systems found",), {})])

    # pylint: disable-next=redefined-outer-name
    def test_schedule_getoutput_scripts(self, shell):
        """
        Test do_schedule_getoutput with scripts

        :param shell:
        :return:
        """
        shell.get_system_name = MagicMock(side_effect=["web.foo.com", "db.foo.com"])
        shell.client.schedule.listCompletedSystems = MagicMock(return_value=[])
        shell.client.schedule.listFailedSystems = MagicMock(return_value=[])
        shell.client.system.getScriptResults = MagicMock(
            return_value=[
                {
                    "serverId": 1000010000,
                    "startDate": "2019-01-01",
                    "stopDate": "2019-01-02",
                    "returnCode": 42,
                    "output": "Normal output",
                },
                {
                    "startDate": "2019-02-01",
                    "stopDate": "2019-02-02",
                    "returnCode": 1,
                    "output_enc64": True,
                    "output": b"Tm93IHlvdSBzZWUgbWUh\n",
                },
                {
                    "serverId": 1000010001,
                    "startDate": "2019-01-11",
                    "stopDate": "2019-01-22",
                    "returnCode": 13,
                    "output": None,
                },
            ]
        )
        shell.help_schedule_getoutput = MagicMock()

        mprint = MagicMock()
        logger = MagicMock()

        # pylint: disable-next=unused-variable
        with patch("spacecmd.schedule.print", mprint) as prt, patch(
            "spacecmd.schedule.logging",
            logger,
            # pylint: disable-next=unused-variable
        ) as lgr:
            spacecmd.schedule.do_schedule_getoutput(shell, "42")

        assert not logger.warning.called
        assert not shell.help_schedule_getoutput.called
        assert not shell.client.schedule.listCompletedSystems.called
        assert not shell.client.schedule.listFailedSystems.called
        assert not logger.debug.called
        assert not logger.error.called
        assert mprint.called
        assert shell.client.system.getScriptResults.called

        assert_list_args_expect(
            mprint.call_args_list,
            [
                "System:      web.foo.com",
                "Start Time:  2019-01-01",
                "Stop Time:   2019-01-02",
                "Return Code: 42",
                "",
                "Output",
                "------",
                "Normal output",
                "----------",
                "System:      UNKNOWN",
                "Start Time:  2019-02-01",
                "Stop Time:   2019-02-02",
                "Return Code: 1",
                "",
                "Output",
                "------",
                "Now you see me!",
                "----------",
                "System:      db.foo.com",
                "Start Time:  2019-01-11",
                "Stop Time:   2019-01-22",
                "Return Code: 13",
                "",
                "Output",
                "------",
                "N/A",
            ],
        )
