package com.tngtech.jgiven.examples.nested;

import org.junit.Test;
import org.testng.Assert;

import com.tngtech.jgiven.Stage;
import com.tngtech.jgiven.annotation.ExtendedDescription;
import com.tngtech.jgiven.annotation.NestedSteps;
import com.tngtech.jgiven.annotation.ProvidedScenarioState;
import com.tngtech.jgiven.junit.SimpleScenarioTest;

public class NestedStepsTest extends SimpleScenarioTest<NestedStepsTest.NestedStage> {

    @Test
    @ExtendedDescription( "This scenario contains nested steps." )
    public void a_scenario_with_nested_steps() {

        given().I_fill_out_the_registration_form_with_valid_values();

        when().I_submit_the_form();

        then().the_password_matches();

    }

    static class NestedStage extends Stage<NestedStage> {

        @ProvidedScenarioState
        String name;

        @ProvidedScenarioState
        String email;

        @ProvidedScenarioState
        String password;

        @ProvidedScenarioState
        String repeatedPassword;

        @NestedSteps
        public NestedStage I_fill_out_the_registration_form_with_valid_values() {
            return I_enter_a_name( "Franky" )
                .and().I_enter_a_email_address( "franky@acme.com" )
                .and().I_enter_a_password( "password1234" )
                .and().I_enter_a_repeated_password( "password1234" );
        }

        @NestedSteps
        public NestedStage I_enter_a_name( String name ) {
            return I_think_a_name( name )
                .and().I_write_the_name( name );
        }

        public NestedStage I_think_a_name( String name ) {
            return self();
        }

        public NestedStage I_write_the_name( String name ) {
            this.name = name;
            return self();
        }

        public NestedStage I_enter_a_email_address( String email ) {
            this.email = email;
            return self();
        }

        public NestedStage I_enter_a_password( String password ) {
            this.password = password;
            return self();
        }

        public NestedStage I_enter_a_repeated_password( String repeatedPassword ) {
            this.repeatedPassword = repeatedPassword;
            return self();
        }

        public NestedStage I_submit_the_form() {
            return self();
        }

        public NestedStage the_password_matches() {
            Assert.assertEquals( password, repeatedPassword );
            return self();
        }

    }

}

@@ -38,16 +38,75 @@
 ested;%0A%0A
+import static org.assertj.core.api.Assertions.assertThat;%0A%0A
 import o
@@ -120,16 +120,16 @@
 t.Test;%0A
-
 import o
@@ -767,24 +767,261 @@
 ();%0A%0A    %7D%0A%0A
+    @Test%0A    public void a_scenario_with_a_failing_nested_step_on_purpose() %7B%0A%0A        given().I_fill_out_the_registration_form_with_invalid_values();%0A%0A        when().I_submit_the_form();%0A%0A        then().the_password_matches();%0A%0A    %7D%0A%0A
     static c
@@ -1569,24 +1569,24 @@
 word1234%22 )%0A
-
             
@@ -1646,32 +1646,510 @@
 %22 );%0A        %7D%0A%0A
+        @NestedSteps%0A        public NestedStage I_fill_out_the_registration_form_with_invalid_values() %7B%0A            return I_enter_a_name( %22Franky%22 )%0A                .and().I_enter_a_email_address( %22franky@acme.com%22 )%0A                .and().something_fails_for_demonstration_purposes();%0A        %7D%0A%0A        public NestedStage something_fails_for_demonstration_purposes() %7B%0A            assertThat( true ).as( %22Fails on purpose%22 ).isFalse();%0A            return self();%0A        %7D%0A%0A
         @NestedS

add failing nested step for demonstration (#174)