# -*- coding: utf-8 -*-

"""
    radish
    ~~~~~~

    Behavior Driven Development tool for Python - the root from red to green

    Copyright: MIT, Timo Furrer <tuxtimo@gmail.com>
"""

import pytest

from radish.scenariooutline import ScenarioOutline
from radish.examplescenario import ExampleScenario
from radish.background import Background
from radish.stepmodel import Step
from radish.exceptions import RadishError


def test_creating_simple_scenariooutline():
    """
    Test creating a simple ScenarioOutline
    """
    # given & when
    scenario = ScenarioOutline(
        1,
        "Scenario Outline",
        "Examples",
        "I am a Scenario Outline",
        "foo.feature",
        1,
        parent=None,
        tags=None,
        preconditions=None,
        background=None,
    )

    # then
    assert scenario.id == 1
    assert scenario.keyword == "Scenario Outline"
    assert scenario.example_keyword == "Examples"
    assert scenario.sentence == "I am a Scenario Outline"
    assert scenario.path == "foo.feature"
    assert scenario.line == 1
    assert scenario.parent is None
    assert scenario.tags == []
    assert scenario.preconditions == []
    assert scenario.background is None


def test_building_scenariooutline_scenarios(mocker):
    """
    Test building Scenarios from a Scenario Outline Example
    """
    # given
    scenario_outline = ScenarioOutline(
        1,
        "Scenario Outline",
        "Examples",
        "I am a Scenario Outline",
        "foo.feature",
        1,
        parent=None,
        tags=None,
        preconditions=None,
        background=None,
    )
    # add steps
    scenario_outline.steps.extend(
        [
            mocker.MagicMock(sentence="Given I have <foo>", path="foo.feature"),
            mocker.MagicMock(sentence="And I have <bar>", path="foo.feature"),
            mocker.MagicMock(sentence="When I add those", path="foo.feature"),
        ]
    )
    # add examples
    scenario_outline.examples_header = ["foo", "bar"]
    scenario_outline.examples = [
        # row 0
        ScenarioOutline.Example(["1", "2"], "foo.feature", 1),
        # row 3
        ScenarioOutline.Example(["3", "4"], "foo.feature", 2),
    ]

    # when - build the scenarios
    scenario_outline.build_scenarios()

    # then - expect 2 built Scenarios
    assert len(scenario_outline.scenarios) == 2
    # then - expect that Scenarios are of type ExampleScenario
    assert all(isinstance(x, ExampleScenario) for x in scenario_outline.scenarios)
    # then - expect correct Example Scenario sentences
    assert scenario_outline.scenarios[0].sentence == "I am a Scenario Outline - row 0"
    assert scenario_outline.scenarios[1].sentence == "I am a Scenario Outline - row 1"
    # then - expect correctly replaced Step sentences
    assert scenario_outline.scenarios[0].steps[0].sentence == "Given I have 1"
    assert scenario_outline.scenarios[0].steps[1].sentence == "And I have 2"
    assert scenario_outline.scenarios[0].steps[2].sentence == "When I add those"
    assert scenario_outline.scenarios[1].steps[0].sentence == "Given I have 3"
    assert scenario_outline.scenarios[1].steps[1].sentence == "And I have 4"
    assert scenario_outline.scenarios[1].steps[2].sentence == "When I add those"


def test_building_scenariooutline_scenarios_with_background(mocker):
    """
    Test building Scenarios from a Scenario Outline Example including a Background
    """
    # given
    background = Background("Background", "I am a Background", "foo.feature", 1, parent=None)
    # add some Steps
    background.steps.extend(
        [
            Step(1, "Foo", "foo.feature", 2, background, False),
            Step(2, "Foo", "foo.feature", 3, background, False),
        ]
    )
    scenario_outline = ScenarioOutline(
        1,
        "Scenario Outline",
        "Examples",
        "I am a Scenario Outline",
        "foo.feature",
        1,
        parent=None,
        tags=None,
        preconditions=None,
        background=background,
    )
    # add steps
    scenario_outline.steps.extend(
        [
            mocker.MagicMock(sentence="Given I have <foo>", path="foo.feature"),
            mocker.MagicMock(sentence="And I have <bar>", path="foo.feature"),
            mocker.MagicMock(sentence="When I add those", path="foo.feature"),
        ]
    )
    # add examples
    scenario_outline.examples_header = ["foo", "bar"]
    scenario_outline.examples = [
        # row 0
        ScenarioOutline.Example(["1", "2"], "foo.feature", 1),
        # row 3
        ScenarioOutline.Example(["3", "4"], "foo.feature", 2),
    ]

    # when - build the scenarios
    scenario_outline.build_scenarios()

    # then - expect ExampleScenarios to have background copy assigned
    assert scenario_outline.scenarios[0].background.sentence == "I am a Background"
    assert scenario_outline.scenarios[1].background.sentence == "I am a Background"


def test_scenariooutline_example_colum_width():
    """
    Test calculation for maximum width of Example columns
    """
    # given
    scenario_outline = ScenarioOutline(
        1,
        "Scenario Outline",
        "Examples",
        "I am a Scenario Outline",
        "foo.feature",
        1,
        parent=None,
        tags=None,
        preconditions=None,
        background=None,
    )
    # add examples
    scenario_outline.examples_header = ["foo", "bar"]
    scenario_outline.examples = [
        # row 0
        ScenarioOutline.Example(["Spiderman", "Batman"], "foo.feature", 1),
        # row 3
        ScenarioOutline.Example(["Peter", "Bruce Wayne"], "foo.feature", 2),
    ]

    # when
    index_0_width = scenario_outline.get_column_width(0)
    # then
    assert index_0_width == len("Spiderman")

    # when
    index_1_width = scenario_outline.get_column_width(1)
    # then
    assert index_1_width == len("Bruce Wayne")


def test_scenariooutline_example_invalid_colum_width():
    """
    Test invalid column id exception when calculating column width for Scenario Outline Examples
    """
    # given
    scenario_outline = ScenarioOutline(
        1,
        "Scenario Outline",
        "Examples",
        "I am a Scenario Outline",
        "foo.feature",
        1,
        parent=None,
        tags=None,
        preconditions=None,
        background=None,
    )
    # add examples
    scenario_outline.examples_header = ["foo", "bar"]
    scenario_outline.examples = [
        # row 0
        ScenarioOutline.Example(["Spiderman", "Batman"], "foo.feature", 1),
        # row 3
        ScenarioOutline.Example(["Peter", "Bruce Wayne"], "foo.feature", 2),
    ]

    # when
    with pytest.raises(RadishError) as exc:
        scenario_outline.get_column_width(42)

    # then
    assert str(exc.value) == "Invalid colum_index to get column width for ScenarioOutline 'I am a Scenario Outline'"


def test_scenariooutline_afterparse_logic(mocker):
    """
    Test Scenario Outline after parse logic
    """
    # given
    scenario_outline = ScenarioOutline(
        1,
        "Scenario Outline",
        "Examples",
        "I am a Scenario Outline",
        "foo.feature",
        1,
        parent=None,
        tags=None,
        preconditions=None,
        background=None,
    )
    # add steps
    scenario_outline.steps.extend(
        [
            mocker.MagicMock(sentence="Given I have <foo>", path="foo.feature"),
            mocker.MagicMock(sentence="And I have <bar>", path="foo.feature"),
            mocker.MagicMock(sentence="When I add those", path="foo.feature"),
        ]
    )
    # add examples
    scenario_outline.examples_header = ["foo", "bar"]
    scenario_outline.examples = [
        # row 0
        ScenarioOutline.Example(["1", "2"], "foo.feature", 1),
        # row 3
        ScenarioOutline.Example(["3", "4"], "foo.feature", 2),
    ]

    # when
    scenario_outline.after_parse()

    # then - expect 2 built Scenarios
    assert len(scenario_outline.scenarios) == 2
    assert scenario_outline.complete is True
