diff --git a/.travis.yml b/.travis.yml index 4707cf4..32f2642 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: android jdk: oraclejdk8 -sudo: false +sudo: true env: global: diff --git a/README.md b/README.md index e114509..4ca09a6 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Moreover, you can find there other examples, e.g. how to persist state on rotati - [StepperLayout attributes](#stepperlayout-attributes) - [View attributes](#view-attributes) - [StepperLayout style attributes](#stepperlayout-style-attributes) +- [Contributing](#contributing) - [License](#license) ## Supported steppers @@ -56,7 +57,7 @@ Moreover, you can find there other examples, e.g. how to persist state on rotati ### Download (from JCenter) ```groovy -compile 'com.stepstone.stepper:material-stepper:3.2.2' +compile 'com.stepstone.stepper:material-stepper:3.2.3' ``` ### Create layout in XML @@ -68,7 +69,6 @@ compile 'com.stepstone.stepper:material-stepper:3.2.2' android:id="@+id/stepperLayout" android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="vertical" app:ms_stepperType="progress_bar" /> ``` @@ -487,6 +487,16 @@ A list of `ms_stepperLayoutTheme` attributes responsible for styling of StepperL | *ms_stepTabIconBackgroundStyle* | Used by ms_stepIconBackground in layout/ms_step_tab | | *ms_stepTabTitleStyle* | Used by ms_stepTitle in layout/ms_step_tab | | *ms_stepTabDividerStyle* | Used by ms_stepDivider in layout/ms_step_tab | + + +## Contributing +All contributions are welcome and encouraged! + +Pull requests should be merged to the ```develop``` branch (Rebase & merge preferred). +Once ```develop``` is stable and we're ready to release the next version +it should be merged to ```master```. Next, a new version should be +uploaded to Bintray and a new release should be created on GitHub. +Library releases should be made from the ```master``` branch. ## License Copyright 2016 StepStone Services diff --git a/build.gradle b/build.gradle index cdf1049..7ea1a82 100644 --- a/build.gradle +++ b/build.gradle @@ -18,6 +18,7 @@ buildscript { allprojects { repositories { jcenter() + mavenCentral() } } @@ -31,7 +32,8 @@ configure(allprojects) { androidSupportLibraryVersion = '25.3.1' junitVersion = '4.12' - mockitoVersion = '1.10.19' + mockitoVersion = '2.7.21' + mockitoKotlinVersion = '1.4.0' robolectricVersion = '3.3.1' assertjVersion = '1.1.1' diff --git a/gradle.properties b/gradle.properties index e5dfb0a..2944288 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,4 +19,4 @@ POM_GROUP_ID=com.stepstone.stepper POM_ARTIFACT_ID=material-stepper -POM_VERSION=3.2.2 \ No newline at end of file +POM_VERSION=3.2.3 \ No newline at end of file diff --git a/material-stepper/build.gradle b/material-stepper/build.gradle index 5661885..5cfe84c 100644 --- a/material-stepper/build.gradle +++ b/material-stepper/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' apply plugin: 'maven' apply from: '../material-stepper/code_coverage.gradle' apply from: '../config/quality/quality.gradle' @@ -29,7 +30,7 @@ ext { android { compileSdkVersion project.androidCompileSdkVersion - buildToolsVersion ("$androidBuildToolsVersion") + buildToolsVersion("$androidBuildToolsVersion") defaultConfig { minSdkVersion project.androidMinSdkVersion @@ -59,15 +60,18 @@ android { } dependencies { - compile ("com.android.support:appcompat-v7:$androidSupportLibraryVersion") + compile "com.android.support:appcompat-v7:$androidSupportLibraryVersion" - testCompile("junit:junit:$junitVersion") - testCompile("org.mockito:mockito-core:$mockitoVersion") - testCompile("com.squareup.assertj:assertj-android:$assertjVersion") + testCompile "junit:junit:$junitVersion" + testCompile "org.mockito:mockito-core:$mockitoVersion" + testCompile "com.squareup.assertj:assertj-android:$assertjVersion" testCompile("org.robolectric:robolectric:$robolectricVersion") { exclude group: 'commons-logging', module: 'commons-logging' exclude group: 'org.apache.httpcomponents', module: 'httpclient' } + testCompile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlinVersion" + testCompile "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion" + testCompile "com.nhaarman:mockito-kotlin:$mockitoKotlinVersion" } gradle.taskGraph.beforeTask { Task task -> @@ -81,7 +85,7 @@ gradle.taskGraph.beforeTask { Task task -> } // Log out test results to console -tasks.matching {it instanceof Test}.all { +tasks.matching { it instanceof Test }.all { testLogging.events = ["failed", "passed", "skipped"] } diff --git a/material-stepper/src/main/java/com/stepstone/stepper/StepperLayout.java b/material-stepper/src/main/java/com/stepstone/stepper/StepperLayout.java index 3d386b9..76108aa 100644 --- a/material-stepper/src/main/java/com/stepstone/stepper/StepperLayout.java +++ b/material-stepper/src/main/java/com/stepstone/stepper/StepperLayout.java @@ -320,6 +320,7 @@ public void setAdapter(@NonNull StepAdapter stepAdapter) { mPager.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { + //noinspection deprecation mPager.getViewTreeObserver().removeGlobalOnLayoutListener(this); onUpdate(mCurrentStepPosition, false); } diff --git a/material-stepper/src/test/java/com/stepstone/stepper/StepperLayoutSanityTest.java b/material-stepper/src/test/java/com/stepstone/stepper/StepperLayoutSanityTest.java deleted file mode 100644 index b5a2377..0000000 --- a/material-stepper/src/test/java/com/stepstone/stepper/StepperLayoutSanityTest.java +++ /dev/null @@ -1,223 +0,0 @@ -package com.stepstone.stepper; - -import android.content.Context; -import android.support.annotation.IntRange; -import android.support.annotation.NonNull; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentManager; -import android.util.AttributeSet; -import android.widget.LinearLayout; - -import com.stepstone.stepper.adapter.AbstractFragmentStepAdapter; -import com.stepstone.stepper.test.runner.StepperRobolectricTestRunner; -import com.stepstone.stepper.viewmodel.StepViewModel; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.Robolectric; - -import static com.stepstone.stepper.test.assertion.StepperLayoutAssert.assertThat; -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; - - -/** - * @author Piotr Zawadzki - */ -@RunWith(StepperRobolectricTestRunner.class) -public class StepperLayoutSanityTest { - - private static final String TYPE_PROGRESS_BAR = "progress_bar"; - private static final String TYPE_DOTS = "dots"; - private static final String TYPE_TABS = "tabs"; - - private static final String ORIENTATION_HORIZONTAL = "horizontal"; - - FragmentActivity activity; - - @Before - public void setUp() throws Exception { - activity = Robolectric.setupActivity(DummyActivity.class); - } - - @Test - public void stepper_with_progress_bar_without_adapter_should_have_all_type_specific_indicators_hidden() { - //given - AttributeSet attributeSet = createAttributeSetWithStepperType(TYPE_PROGRESS_BAR); - - //when - StepperLayout stepperLayout = new StepperLayout(activity, attributeSet); - - //then - assertThat(stepperLayout) - .hasHorizontalProgressBarHidden() - .hasDottedProgressBarHidden() - .hasTabsHidden(); - } - - @Test - public void stepper_with_dots_without_adapter_should_have_all_type_specific_indicators_hidden() { - //given - AttributeSet attributeSet = createAttributeSetWithStepperType(TYPE_DOTS); - - //when - StepperLayout stepperLayout = new StepperLayout(activity, attributeSet); - - //then - assertThat(stepperLayout) - .hasDottedProgressBarHidden() - .hasHorizontalProgressBarHidden() - .hasTabsHidden(); - } - - @Test - public void stepper_with_tabs_without_adapter_should_have_all_type_specific_indicators_hidden() { - //given - AttributeSet attributeSet = createAttributeSetWithStepperType(TYPE_TABS); - - //when - StepperLayout stepperLayout = new StepperLayout(activity, attributeSet); - - //then - assertThat(stepperLayout) - .hasTabsHidden() - .hasHorizontalProgressBarHidden() - .hasDottedProgressBarHidden(); - } - - @Test - public void should_show_horizontal_progress_bar_when_adapter_is_set_for_progress_bar_type() { - //given - AttributeSet attributeSet = createAttributeSetWithStepperType(TYPE_PROGRESS_BAR); - StepperLayout stepperLayout = new StepperLayout(activity, attributeSet); - - //when - whenAdapterIsSet(stepperLayout); - - //then - assertThat(stepperLayout) - .hasHorizontalProgressBarShown() - .hasDottedProgressBarHidden() - .hasTabsHidden(); - } - - @Test - public void should_show_dotted_progress_bar_when_adapter_is_set_for_dots_type() { - //given - AttributeSet attributeSet = createAttributeSetWithStepperType(TYPE_DOTS); - StepperLayout stepperLayout = new StepperLayout(activity, attributeSet); - - //when - whenAdapterIsSet(stepperLayout); - - //then - assertThat(stepperLayout) - .hasDottedProgressBarShown() - .hasHorizontalProgressBarHidden() - .hasTabsHidden(); - } - - @Test - public void should_show_tabs_when_adapter_is_set_for_tabs_type() { - //given - AttributeSet attributeSet = createAttributeSetWithStepperType(TYPE_TABS); - StepperLayout stepperLayout = new StepperLayout(activity, attributeSet); - - //when - whenAdapterIsSet(stepperLayout); - - //then - assertThat(stepperLayout) - .hasTabsShown() - .hasHorizontalProgressBarHidden() - .hasDottedProgressBarHidden(); - } - - @Test - public void should_ignore_horizontal_orientation_if_provided_from_attributes() { - //given - AttributeSet attributeSet = Robolectric.buildAttributeSet() - .addAttribute(R.attr.ms_stepperType, TYPE_DOTS) - .addAttribute(android.R.attr.orientation, ORIENTATION_HORIZONTAL) - .build(); - - //when - StepperLayout stepperLayout = new StepperLayout(activity, attributeSet); - - //then - assertVerticalOrientationUsed(stepperLayout); - } - - @Test - public void should_ignore_horizontal_orientation_if_provided_programmatically() { - //given - AttributeSet attributeSet = createAttributeSetWithStepperType(TYPE_DOTS); - StepperLayout stepperLayout = new StepperLayout(activity, attributeSet); - - //when - stepperLayout.setOrientation(LinearLayout.HORIZONTAL); - - //then - assertVerticalOrientationUsed(stepperLayout); - } - - private void assertVerticalOrientationUsed(StepperLayout stepperLayout) { - assertEquals("Invalid orientation", stepperLayout.getOrientation(), LinearLayout.VERTICAL); - } - - private void whenAdapterIsSet(StepperLayout stepperLayout) { - stepperLayout.setAdapter(new DummyStepAdapter(activity.getSupportFragmentManager(), activity)); - } - - private AttributeSet createAttributeSetWithStepperType(String stepperType) { - return Robolectric.buildAttributeSet() - .addAttribute(R.attr.ms_stepperType, stepperType) - .build(); - } - - public static class DummyActivity extends FragmentActivity {} - - public static class DummyStepAdapter extends AbstractFragmentStepAdapter { - - public DummyStepAdapter(@NonNull FragmentManager fm, @NonNull Context context) { - super(fm, context); - } - - @NonNull - @Override - public StepViewModel getViewModel(@IntRange(from = 0) int position) { - return new StepViewModel.Builder(context) - .setTitle("Dummy title") - .create(); - } - - @Override - public Step createStep(int position) { - return mock(DummyStepFragment.class); - } - - @Override - public int getCount() { - return 3; - } - } - - public static class DummyStepFragment extends Fragment implements Step { - - @Override - public VerificationError verifyStep() { - return null; - } - - @Override - public void onSelected() { - } - - @Override - public void onError(@NonNull VerificationError error) { - } - } - -} \ No newline at end of file diff --git a/material-stepper/src/test/java/com/stepstone/stepper/StepperLayoutTest.kt b/material-stepper/src/test/java/com/stepstone/stepper/StepperLayoutTest.kt new file mode 100644 index 0000000..7a6f8e6 --- /dev/null +++ b/material-stepper/src/test/java/com/stepstone/stepper/StepperLayoutTest.kt @@ -0,0 +1,187 @@ +package com.stepstone.stepper + +import android.util.AttributeSet +import android.widget.LinearLayout +import com.stepstone.stepper.test.assertion.StepperLayoutAssert +import com.stepstone.stepper.test.assertion.StepperLayoutAssert.Companion.assertThat +import com.stepstone.stepper.test.runner.StepperRobolectricTestRunner +import com.stepstone.stepper.test.test_double.SpyStepAdapter +import org.junit.Assert.assertNotNull +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.verify +import org.robolectric.Robolectric +import org.robolectric.android.controller.ActivityController + + +/** + * @author Piotr Zawadzki + */ +@RunWith(StepperRobolectricTestRunner::class) +class StepperLayoutTest { + + companion object { + + const val TYPE_PROGRESS_BAR = "progress_bar" + const val TYPE_DOTS = "dots" + const val TYPE_TABS = "tabs" + + const val ORIENTATION_HORIZONTAL = "horizontal" + + } + + lateinit var stepperLayout: StepperLayout + + @Test + fun `All type specific indicators should be hidden when adapter is not set for StepperLayout with 'progress_bar' type`() { + //given + val attributeSet = createAttributeSetWithStepperType(TYPE_PROGRESS_BAR) + + //when + stepperLayout = createStepperLayoutInActivity(attributeSet) + + //then + assertStepperLayout() + .hasHorizontalProgressBarHidden() + .hasDottedProgressBarHidden() + .hasTabsHidden() + } + + @Test + fun `All type specific indicators should be hidden when adapter is not set for StepperLayout with 'dots' type`() { + //given + val attributeSet = createAttributeSetWithStepperType(TYPE_DOTS) + + //when + stepperLayout = createStepperLayoutInActivity(attributeSet) + + //then + assertStepperLayout() + .hasDottedProgressBarHidden() + .hasHorizontalProgressBarHidden() + .hasTabsHidden() + } + + @Test + fun `All type specific indicators should be hidden when adapter is not set for StepperLayout with 'tabs' type`() { + //given + val attributeSet = createAttributeSetWithStepperType(TYPE_TABS) + + //when + stepperLayout = createStepperLayoutInActivity(attributeSet) + + //then + assertStepperLayout() + .hasTabsHidden() + .hasHorizontalProgressBarHidden() + .hasDottedProgressBarHidden() + } + + @Test + fun `Horizontal progress bar should be shown when adapter is set for Stepper with 'progress_bar' type`() { + //given + val attributeSet = createAttributeSetWithStepperType(TYPE_PROGRESS_BAR) + + //when + stepperLayout = createStepperLayoutWithAdapterSetInActivity(attributeSet) + + //then + assertStepperLayout() + .hasHorizontalProgressBarShown() + .hasDottedProgressBarHidden() + .hasTabsHidden() + assertFirstFragmentWasNotifiedAboutBeingSelected() + } + + @Test + fun `Dotted progress bar should be shown when adapter is set for Stepper with 'dots' type`() { + //given + val attributeSet = createAttributeSetWithStepperType(TYPE_DOTS) + + //when + stepperLayout = createStepperLayoutWithAdapterSetInActivity(attributeSet) + + //then + assertStepperLayout() + .hasDottedProgressBarShown() + .hasHorizontalProgressBarHidden() + .hasTabsHidden() + assertFirstFragmentWasNotifiedAboutBeingSelected() + } + + @Test + fun `Tabs should be shown when adapter is set for Stepper with 'tabs' type`() { + //given + val attributeSet = createAttributeSetWithStepperType(TYPE_TABS) + + //when + stepperLayout = createStepperLayoutWithAdapterSetInActivity(attributeSet) + + //then + assertStepperLayout() + .hasTabsShown() + .hasHorizontalProgressBarHidden() + .hasDottedProgressBarHidden() + assertFirstFragmentWasNotifiedAboutBeingSelected() + } + + @Test + fun `Horizontal orientation should be ignored if set in View attributes`() { + //given + val attributeSet = Robolectric.buildAttributeSet() + .addAttribute(R.attr.ms_stepperType, TYPE_DOTS) + .addAttribute(android.R.attr.orientation, ORIENTATION_HORIZONTAL) + .build() + + //when + stepperLayout = createStepperLayoutInActivity(attributeSet) + + //then + assertStepperLayout().hasOrientation(LinearLayout.VERTICAL) + } + + @Test + fun `Horizontal orientation should be ignored if set programmatically`() { + //given + val attributeSet = createAttributeSetWithStepperType(TYPE_DOTS) + stepperLayout = createStepperLayoutInActivity(attributeSet) + + //when + stepperLayout.orientation = LinearLayout.HORIZONTAL + + //then + assertStepperLayout().hasOrientation(LinearLayout.VERTICAL) + } + + fun createAttributeSetWithStepperType(stepperType: String): AttributeSet { + return Robolectric.buildAttributeSet() + .addAttribute(R.attr.ms_stepperType, stepperType) + .build() + } + + fun createStepperLayoutInActivity(attributeSet: AttributeSet): StepperLayout { + val activity = ActivityController.of(Robolectric.getShadowsAdapter(), StepperLayoutActivity().withStepperLayoutAttributes(attributeSet)) + .setup() + .get() + return activity.stepperLayout + } + + fun createStepperLayoutWithAdapterSetInActivity(attributeSet: AttributeSet): StepperLayout { + val activity = ActivityController.of(Robolectric.getShadowsAdapter(), StepperLayoutWithAdapterActivity().withStepperLayoutAttributes(attributeSet)) + .setup() + .get() + return activity.stepperLayout + } + + fun assertStepperLayout(): StepperLayoutAssert { + return assertThat(stepperLayout) + } + + fun assertFirstFragmentWasNotifiedAboutBeingSelected() { + val stepAdapter = stepperLayout.adapter as SpyStepAdapter + val firstStep = stepAdapter.steps.get(0) + assertNotNull("Step not found", firstStep) + verify(firstStep).onSelected() + } + +} \ No newline at end of file diff --git a/material-stepper/src/test/java/com/stepstone/stepper/internal/widget/pagetransformer/StepPageTransformerFactoryTest.java b/material-stepper/src/test/java/com/stepstone/stepper/internal/widget/pagetransformer/StepPageTransformerFactoryTest.java deleted file mode 100644 index 672959f..0000000 --- a/material-stepper/src/test/java/com/stepstone/stepper/internal/widget/pagetransformer/StepPageTransformerFactoryTest.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.stepstone.stepper.internal.widget.pagetransformer; - -import android.os.Build; -import android.support.v4.view.ViewPager; - -import com.stepstone.stepper.test.runner.StepperRobolectricTestRunner; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -/** - * @author Piotr Zawadzki - */ -@RunWith(StepperRobolectricTestRunner.class) -public class StepPageTransformerFactoryTest { - - @Test - @Config(sdk = Build.VERSION_CODES.JELLY_BEAN_MR1, qualifiers = StepperRobolectricTestRunner.QUALIFIER_LDRTL) - public void should_create_rtl_page_transformer_on_JB_MR1_when_RTL_locale_selected() { - //when - ViewPager.PageTransformer pageTransformer = StepPageTransformerFactory.createPageTransformer(RuntimeEnvironment.application); - - //then - assertNotNull("PageTransformer cannot be null", pageTransformer); - assertThat(pageTransformer, is(instanceOf(StepperRtlPageTransformer.class))); - } - - @Test - @Config(sdk = Build.VERSION_CODES.JELLY_BEAN_MR1) - public void should_return_null_by_default_on_JB_MR1() { - //when - ViewPager.PageTransformer pageTransformer = StepPageTransformerFactory.createPageTransformer(RuntimeEnvironment.application); - - //then - assertNull("PageTransformer must be null", pageTransformer); - } - - @Test - @Config(sdk = Build.VERSION_CODES.JELLY_BEAN) - public void should_return_null_by_default_on_JB() { - //when - ViewPager.PageTransformer pageTransformer = StepPageTransformerFactory.createPageTransformer(RuntimeEnvironment.application); - - //then - assertNull("PageTransformer must be null", pageTransformer); - } - - /** - * Layout direction qualifiers were added in JB MR1 so below this OS version RTL should be ignored. - */ - @Test - @Config(sdk = Build.VERSION_CODES.JELLY_BEAN, qualifiers = StepperRobolectricTestRunner.QUALIFIER_LDRTL) - public void should_return_null_on_JB_when_RTL_locale_selected() { - //when - ViewPager.PageTransformer pageTransformer = StepPageTransformerFactory.createPageTransformer(RuntimeEnvironment.application); - - //then - assertNull("PageTransformer must be null", pageTransformer); - } - -} \ No newline at end of file diff --git a/material-stepper/src/test/java/com/stepstone/stepper/internal/widget/pagetransformer/StepPageTransformerFactoryTest.kt b/material-stepper/src/test/java/com/stepstone/stepper/internal/widget/pagetransformer/StepPageTransformerFactoryTest.kt new file mode 100644 index 0000000..b7dfdb2 --- /dev/null +++ b/material-stepper/src/test/java/com/stepstone/stepper/internal/widget/pagetransformer/StepPageTransformerFactoryTest.kt @@ -0,0 +1,69 @@ +package com.stepstone.stepper.internal.widget.pagetransformer + +import android.os.Build +import android.support.v4.view.ViewPager +import com.stepstone.stepper.test.runner.StepperRobolectricTestRunner +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.instanceOf +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertNull +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RuntimeEnvironment +import org.robolectric.annotation.Config + +/** + * @author Piotr Zawadzki + */ +@RunWith(StepperRobolectricTestRunner::class) +class StepPageTransformerFactoryTest { + + @Test + @Config(sdk = intArrayOf(Build.VERSION_CODES.JELLY_BEAN_MR1), qualifiers = StepperRobolectricTestRunner.QUALIFIER_LDRTL) + fun `Should create StepperRtlPageTransformer on JellyBean_MR1 when RTL locale selected`() { + //when + val pageTransformer = StepPageTransformerFactory.createPageTransformer(RuntimeEnvironment.application) + + //then + assertNotNull("PageTransformer cannot be null", pageTransformer) + assertThat(pageTransformer, instanceOf(StepperRtlPageTransformer::class.java)) + } + + @Test + @Config(sdk = intArrayOf(Build.VERSION_CODES.JELLY_BEAN_MR1)) + fun `Should return 'null' by default on JellyBean_MR1`() { + //when + val pageTransformer = StepPageTransformerFactory.createPageTransformer(RuntimeEnvironment.application) + + //then + assertPageTransformerIsNull(pageTransformer) + } + + @Test + @Config(sdk = intArrayOf(Build.VERSION_CODES.JELLY_BEAN)) + fun `Should return 'null' by default on JellyBean`() { + //when + val pageTransformer = StepPageTransformerFactory.createPageTransformer(RuntimeEnvironment.application) + + //then + assertPageTransformerIsNull(pageTransformer) + } + + /** + * Layout direction qualifiers were added in JB MR1 so below this OS version RTL should be ignored. + */ + @Test + @Config(sdk = intArrayOf(Build.VERSION_CODES.JELLY_BEAN), qualifiers = StepperRobolectricTestRunner.QUALIFIER_LDRTL) + fun `Should return 'null' on JellyBean when RTL locale selected`() { + //when + val pageTransformer = StepPageTransformerFactory.createPageTransformer(RuntimeEnvironment.application) + + //then + assertPageTransformerIsNull(pageTransformer) + } + + fun assertPageTransformerIsNull(pageTransformer: ViewPager.PageTransformer?) { + assertNull("PageTransformer must be null", pageTransformer) + } + +} \ No newline at end of file diff --git a/material-stepper/src/test/java/com/stepstone/stepper/internal/widget/pagetransformer/StepperRtlPageTransformerTest.java b/material-stepper/src/test/java/com/stepstone/stepper/internal/widget/pagetransformer/StepperRtlPageTransformerTest.java deleted file mode 100644 index b5986d1..0000000 --- a/material-stepper/src/test/java/com/stepstone/stepper/internal/widget/pagetransformer/StepperRtlPageTransformerTest.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.stepstone.stepper.internal.widget.pagetransformer; - -import android.view.View; - -import com.stepstone.stepper.test.runner.StepperRobolectricTestRunner; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; - -import static org.mockito.AdditionalMatchers.or; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -/** - * @author Piotr Zawadzki - */ -@RunWith(StepperRobolectricTestRunner.class) -public class StepperRtlPageTransformerTest { - - private static final int VIEW_WIDTH = 320; - - @Mock - View mockView; - - StepperRtlPageTransformer pageTransformer = new StepperRtlPageTransformer(); - - @Before - public void setUp() { - when(mockView.getWidth()).thenReturn(VIEW_WIDTH); - } - - @Test - public void should_reset_translationX_when_at_front_center() { - //when - pageTransformer.transformPage(mockView, 0.0f); - - //then - verify(mockView).setTranslationX(isZero()); - } - - @Test - public void should_reverse_view_when_at_one_full_position_to_the_right() { - //when - pageTransformer.transformPage(mockView, 1.0f); - - //then - verify(mockView).setTranslationX(-2 * VIEW_WIDTH); - } - - @Test - public void should_reverse_view_when_at_one_full_position_to_the_left() { - //when - pageTransformer.transformPage(mockView, -1.0f); - - //then - verify(mockView).setTranslationX(2 * VIEW_WIDTH); - } - - @Test - public void should_reverse_view_when_in_the_middle() { - //when - pageTransformer.transformPage(mockView, 0.5f); - - //then - verify(mockView).setTranslationX(-VIEW_WIDTH); - } - - private float isZero() { - return or(eq(0.0f), eq(-0.0f)); - } - -} \ No newline at end of file diff --git a/material-stepper/src/test/java/com/stepstone/stepper/internal/widget/pagetransformer/StepperRtlPageTransformerTest.kt b/material-stepper/src/test/java/com/stepstone/stepper/internal/widget/pagetransformer/StepperRtlPageTransformerTest.kt new file mode 100644 index 0000000..060d1c5 --- /dev/null +++ b/material-stepper/src/test/java/com/stepstone/stepper/internal/widget/pagetransformer/StepperRtlPageTransformerTest.kt @@ -0,0 +1,70 @@ +package com.stepstone.stepper.internal.widget.pagetransformer + +import android.view.View +import com.nhaarman.mockito_kotlin.doReturn +import com.nhaarman.mockito_kotlin.mock +import com.stepstone.stepper.test.runner.StepperRobolectricTestRunner +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.AdditionalMatchers.or +import org.mockito.ArgumentMatchers.eq +import org.mockito.Mockito.verify + +/** + * @author Piotr Zawadzki + */ +@RunWith(StepperRobolectricTestRunner::class) +class StepperRtlPageTransformerTest { + + companion object { + + const val VIEW_WIDTH = 320 + + } + + val mockView: View = mock { + on { width } doReturn VIEW_WIDTH + } + + val pageTransformer = StepperRtlPageTransformer() + + @Test + fun `Should reset 'translationX' when page is at front center`() { + //when + pageTransformer.transformPage(mockView, 0.0f) + + //then + verify(mockView).translationX = isZero + } + + @Test + fun `Should reverse view position on X axis when page is at one full position to the right`() { + //when + pageTransformer.transformPage(mockView, 1.0f) + + //then + verify(mockView).translationX = -2.0f * VIEW_WIDTH + } + + @Test + fun `Should reverse view position on X axis when page is at one full position to the left`() { + //when + pageTransformer.transformPage(mockView, -1.0f) + + //then + verify(mockView).translationX = 2.0f * VIEW_WIDTH + } + + @Test + fun `Should reverse view position on X axis when page is half moved`() { + //when + pageTransformer.transformPage(mockView, 0.5f) + + //then + verify(mockView).translationX = -VIEW_WIDTH.toFloat() + } + + val isZero: Float + get() = or(eq(0.0f), eq(-0.0f)) + +} \ No newline at end of file diff --git a/material-stepper/src/test/java/com/stepstone/stepper/test/TestApplication.java b/material-stepper/src/test/java/com/stepstone/stepper/test/TestApplication.java deleted file mode 100644 index 94404a9..0000000 --- a/material-stepper/src/test/java/com/stepstone/stepper/test/TestApplication.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.stepstone.stepper.test; - -import android.app.Application; - -import org.mockito.MockitoAnnotations; -import org.robolectric.TestLifecycleApplication; - -import java.lang.reflect.Method; - -/** - * @author Piotr Zawadzki - */ -public class TestApplication extends Application implements TestLifecycleApplication { - - @Override - public void beforeTest(Method method) { - } - - @Override - public void prepareTest(Object test) { - MockitoAnnotations.initMocks(test);//initialize all the mocks that were specified using annotations - } - - @Override - public void afterTest(Method method) { - } - -} \ No newline at end of file diff --git a/material-stepper/src/test/java/com/stepstone/stepper/test/TestApplication.kt b/material-stepper/src/test/java/com/stepstone/stepper/test/TestApplication.kt new file mode 100644 index 0000000..f11c363 --- /dev/null +++ b/material-stepper/src/test/java/com/stepstone/stepper/test/TestApplication.kt @@ -0,0 +1,23 @@ +package com.stepstone.stepper.test + +import android.app.Application + +import org.mockito.MockitoAnnotations +import org.robolectric.TestLifecycleApplication + +import java.lang.reflect.Method + +/** + * @author Piotr Zawadzki + */ +class TestApplication : Application(), TestLifecycleApplication { + + override fun beforeTest(method: Method) {} + + override fun prepareTest(test: Any) { + MockitoAnnotations.initMocks(test)//initialize all the mocks that were specified using annotations + } + + override fun afterTest(method: Method) {} + +} \ No newline at end of file diff --git a/material-stepper/src/test/java/com/stepstone/stepper/test/assertion/StepperLayoutAssert.java b/material-stepper/src/test/java/com/stepstone/stepper/test/assertion/StepperLayoutAssert.java deleted file mode 100644 index 501fd01..0000000 --- a/material-stepper/src/test/java/com/stepstone/stepper/test/assertion/StepperLayoutAssert.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.stepstone.stepper.test.assertion; - -import android.support.annotation.IdRes; -import android.support.annotation.NonNull; -import android.view.View; - -import com.stepstone.stepper.R; -import com.stepstone.stepper.StepperLayout; - -import org.assertj.android.api.Assertions; -import org.assertj.android.api.view.ViewAssert; -import org.assertj.android.api.widget.AbstractLinearLayoutAssert; - -/** - * @author Piotr Zawadzki - */ -public class StepperLayoutAssert extends AbstractLinearLayoutAssert { - - public static StepperLayoutAssert assertThat(@NonNull StepperLayout actual) { - return new StepperLayoutAssert(actual); - } - - protected StepperLayoutAssert(StepperLayout actual) { - super(actual, StepperLayoutAssert.class); - } - - public StepperLayoutAssert hasHorizontalProgressBarShown() { - hasNotNullChildView(R.id.ms_stepProgressBar) - .isVisible(); - return this; - } - - public StepperLayoutAssert hasHorizontalProgressBarHidden() { - hasNotNullChildView(R.id.ms_stepProgressBar) - .isGone(); - return this; - } - - public StepperLayoutAssert hasDottedProgressBarShown() { - hasNotNullChildView(R.id.ms_stepDottedProgressBar) - .isVisible(); - return this; - } - - public StepperLayoutAssert hasDottedProgressBarHidden() { - hasNotNullChildView(R.id.ms_stepDottedProgressBar) - .isGone(); - return this; - } - - public StepperLayoutAssert hasTabsShown() { - hasNotNullChildView(R.id.ms_stepTabsContainer) - .isVisible(); - return this; - } - - public StepperLayoutAssert hasTabsHidden() { - hasNotNullChildView(R.id.ms_stepTabsContainer) - .isGone(); - return this; - } - - private ViewAssert hasNotNullChildView(@IdRes int childId) { - View progressBar = actual.findViewById(childId); - return Assertions.assertThat(progressBar) - .isNotNull(); - } -} diff --git a/material-stepper/src/test/java/com/stepstone/stepper/test/assertion/StepperLayoutAssert.kt b/material-stepper/src/test/java/com/stepstone/stepper/test/assertion/StepperLayoutAssert.kt new file mode 100644 index 0000000..363b166 --- /dev/null +++ b/material-stepper/src/test/java/com/stepstone/stepper/test/assertion/StepperLayoutAssert.kt @@ -0,0 +1,60 @@ +package com.stepstone.stepper.test.assertion + +import android.support.annotation.IdRes +import android.view.View + +import com.stepstone.stepper.R +import com.stepstone.stepper.StepperLayout + +import org.assertj.android.api.Assertions +import org.assertj.android.api.view.ViewAssert +import org.assertj.android.api.widget.AbstractLinearLayoutAssert + +/** + * @author Piotr Zawadzki + */ +class StepperLayoutAssert constructor(actual: StepperLayout) : AbstractLinearLayoutAssert(actual, StepperLayoutAssert::class.java) { + + companion object { + + fun assertThat(actual: StepperLayout): StepperLayoutAssert { + return StepperLayoutAssert(actual) + } + + } + + fun hasHorizontalProgressBarShown(): StepperLayoutAssert { + hasNotNullChildView(R.id.ms_stepProgressBar).isVisible + return this + } + + fun hasHorizontalProgressBarHidden(): StepperLayoutAssert { + hasNotNullChildView(R.id.ms_stepProgressBar).isGone + return this + } + + fun hasDottedProgressBarShown(): StepperLayoutAssert { + hasNotNullChildView(R.id.ms_stepDottedProgressBar).isVisible + return this + } + + fun hasDottedProgressBarHidden(): StepperLayoutAssert { + hasNotNullChildView(R.id.ms_stepDottedProgressBar).isGone + return this + } + + fun hasTabsShown(): StepperLayoutAssert { + hasNotNullChildView(R.id.ms_stepTabsContainer).isVisible + return this + } + + fun hasTabsHidden(): StepperLayoutAssert { + hasNotNullChildView(R.id.ms_stepTabsContainer).isGone + return this + } + + private fun hasNotNullChildView(@IdRes childId: Int): ViewAssert { + val progressBar = actual.findViewById(childId) + return Assertions.assertThat(progressBar).isNotNull + } +} diff --git a/material-stepper/src/test/java/com/stepstone/stepper/test/runner/StepperRobolectricTestRunner.java b/material-stepper/src/test/java/com/stepstone/stepper/test/runner/StepperRobolectricTestRunner.java deleted file mode 100644 index 8df94e7..0000000 --- a/material-stepper/src/test/java/com/stepstone/stepper/test/runner/StepperRobolectricTestRunner.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.stepstone.stepper.test.runner; - -import android.os.Build; - -import com.stepstone.stepper.BuildConfig; -import com.stepstone.stepper.test.TestApplication; - -import org.junit.runners.model.InitializationError; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - -import java.lang.reflect.Method; - -/** - * Test runner with default config for this library. - * Inspired by Robolectric Bulk Test Configuration. - */ -public class StepperRobolectricTestRunner extends RobolectricTestRunner { - - public static final String QUALIFIER_LDRTL = "ldrtl"; - - public StepperRobolectricTestRunner(Class testClass) throws InitializationError { - super(testClass); - } - - @Override - public Config getConfig(Method method) { - Config config = super.getConfig(method); - return new Config.Builder(config) - .setSdk(getSdk(config.sdk())) - .setConstants(getBuildConfig(config.constants())) - .setApplication(TestApplication.class) - .build(); - } - - private int[] getSdk(int[] sdks) { - if (sdks == null || sdks.length == 0) { - return new int[]{Build.VERSION_CODES.LOLLIPOP}; - } else { - return sdks; - } - } - - private Class getBuildConfig(Class constants) { - if (constants == Void.class) { - return BuildConfig.class; - } else { - return constants; - } - } - -} diff --git a/material-stepper/src/test/java/com/stepstone/stepper/test/runner/StepperRobolectricTestRunner.kt b/material-stepper/src/test/java/com/stepstone/stepper/test/runner/StepperRobolectricTestRunner.kt new file mode 100644 index 0000000..ca11566 --- /dev/null +++ b/material-stepper/src/test/java/com/stepstone/stepper/test/runner/StepperRobolectricTestRunner.kt @@ -0,0 +1,51 @@ +package com.stepstone.stepper.test.runner + +import android.os.Build + +import com.stepstone.stepper.BuildConfig +import com.stepstone.stepper.test.TestApplication + +import org.junit.runners.model.InitializationError +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config + +import java.lang.reflect.Method + +/** + * Test runner with default config for this library. + * Inspired by [Robolectric Bulk Test Configuration](https://medium.com/@andrewlord1990/robolectric-bulk-test-configuration-28ddf82abf4a). + */ +class StepperRobolectricTestRunner @Throws(InitializationError::class) constructor(testClass: Class<*>) : RobolectricTestRunner(testClass) { + + companion object { + + const val QUALIFIER_LDRTL = "ldrtl" + + } + + override fun getConfig(method: Method): Config { + val config = super.getConfig(method) + return Config.Builder(config) + .setSdk(*resolveSdk(config.sdk)) + .setConstants(resolveBuildConfig(config.constants.java)) + .setApplication(TestApplication::class.java) + .build() + } + + private fun resolveSdk(sdks: IntArray?): IntArray { + if (sdks == null || sdks.isEmpty()) { + return intArrayOf(Build.VERSION_CODES.LOLLIPOP) + } else { + return sdks + } + } + + private fun resolveBuildConfig(constants: Class<*>): Class<*> { + if (constants == Void::class.java) { + return BuildConfig::class.java + } else { + return constants + } + } + +} diff --git a/material-stepper/src/test/java/com/stepstone/stepper/test/test_double/DummyStepFragment.kt b/material-stepper/src/test/java/com/stepstone/stepper/test/test_double/DummyStepFragment.kt new file mode 100644 index 0000000..d1209ee --- /dev/null +++ b/material-stepper/src/test/java/com/stepstone/stepper/test/test_double/DummyStepFragment.kt @@ -0,0 +1,25 @@ +package com.stepstone.stepper + +import android.os.Bundle +import android.support.v4.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup + +/** + * A dummy fragment with no view. + */ +open class DummyStepFragment : Fragment(), Step { + + override fun verifyStep(): VerificationError? { + return null + } + + override fun onSelected() {} + + override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return null + } + + override fun onError(error: VerificationError) {} +} \ No newline at end of file diff --git a/material-stepper/src/test/java/com/stepstone/stepper/test/test_double/SpyStepAdapter.kt b/material-stepper/src/test/java/com/stepstone/stepper/test/test_double/SpyStepAdapter.kt new file mode 100644 index 0000000..cd12827 --- /dev/null +++ b/material-stepper/src/test/java/com/stepstone/stepper/test/test_double/SpyStepAdapter.kt @@ -0,0 +1,33 @@ +package com.stepstone.stepper.test.test_double + +import android.content.Context +import android.support.annotation.IntRange +import android.support.v4.app.FragmentManager +import android.util.SparseArray +import com.nhaarman.mockito_kotlin.spy +import com.stepstone.stepper.DummyStepFragment +import com.stepstone.stepper.Step +import com.stepstone.stepper.adapter.AbstractFragmentStepAdapter +import com.stepstone.stepper.viewmodel.StepViewModel + +/** + * Creates Spy [DummyStepFragment]s which can be later verified. + */ +class SpyStepAdapter(fm: FragmentManager, context: Context) : AbstractFragmentStepAdapter(fm, context) { + + val steps = SparseArray() + + override fun getViewModel(@IntRange(from = 0) position: Int): StepViewModel { + return StepViewModel.Builder(context) + .setTitle("Dummy title") + .create() + } + + override fun createStep(position: Int): Step { + val stepFragment = spy(DummyStepFragment()) + steps.put(position, stepFragment) + return stepFragment + } + + override fun getCount() = 3 +} \ No newline at end of file diff --git a/material-stepper/src/test/java/com/stepstone/stepper/test/test_double/StepperLayoutActivity.kt b/material-stepper/src/test/java/com/stepstone/stepper/test/test_double/StepperLayoutActivity.kt new file mode 100644 index 0000000..79a18f7 --- /dev/null +++ b/material-stepper/src/test/java/com/stepstone/stepper/test/test_double/StepperLayoutActivity.kt @@ -0,0 +1,31 @@ +package com.stepstone.stepper + +import android.os.Bundle +import android.support.v4.app.FragmentActivity +import android.util.AttributeSet +import android.view.ViewGroup + +/** + * An Activity with a StepperLayout added in [onCreate]. + */ +open class StepperLayoutActivity : FragmentActivity() { + + internal lateinit var stepperLayoutAttributeSet: AttributeSet + + internal lateinit var stepperLayout: StepperLayout + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + stepperLayout = StepperLayout(this, stepperLayoutAttributeSet) + stepperLayout.layoutParams = layoutParams + setContentView(stepperLayout) + } + + internal fun withStepperLayoutAttributes(attributeSet: AttributeSet): StepperLayoutActivity { + this.stepperLayoutAttributeSet = attributeSet + return this + } +} \ No newline at end of file diff --git a/material-stepper/src/test/java/com/stepstone/stepper/test/test_double/StepperLayoutWithAdapterActivity.kt b/material-stepper/src/test/java/com/stepstone/stepper/test/test_double/StepperLayoutWithAdapterActivity.kt new file mode 100644 index 0000000..ac2313a --- /dev/null +++ b/material-stepper/src/test/java/com/stepstone/stepper/test/test_double/StepperLayoutWithAdapterActivity.kt @@ -0,0 +1,17 @@ +package com.stepstone.stepper + +import android.os.Bundle +import com.stepstone.stepper.test.test_double.SpyStepAdapter + +/** + * A [StepperLayoutActivity] which also sets an adapter in [onCreate]. + */ +class StepperLayoutWithAdapterActivity : StepperLayoutActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val stepAdapter = SpyStepAdapter(supportFragmentManager, this) + stepperLayout.adapter = stepAdapter + } +} \ No newline at end of file diff --git a/sample/build.gradle b/sample/build.gradle index ed6c32b..50ff866 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -37,7 +37,3 @@ dependencies { compile "uk.co.chrisjenx:calligraphy:$calligraphyVersion" } - -repositories { - mavenCentral() -} diff --git a/sample/src/main/java/com/stepstone/stepper/sample/step/fragment/ButterknifeFragment.kt b/sample/src/main/java/com/stepstone/stepper/sample/step/fragment/ButterKnifeFragment.kt similarity index 100% rename from sample/src/main/java/com/stepstone/stepper/sample/step/fragment/ButterknifeFragment.kt rename to sample/src/main/java/com/stepstone/stepper/sample/step/fragment/ButterKnifeFragment.kt diff --git a/sample/src/main/java/com/stepstone/stepper/sample/step/fragment/FormStepFragment.kt b/sample/src/main/java/com/stepstone/stepper/sample/step/fragment/FormStepFragment.kt index b95f845..da0e844 100644 --- a/sample/src/main/java/com/stepstone/stepper/sample/step/fragment/FormStepFragment.kt +++ b/sample/src/main/java/com/stepstone/stepper/sample/step/fragment/FormStepFragment.kt @@ -21,15 +21,13 @@ import android.text.TextUtils import android.view.animation.AnimationUtils import android.view.inputmethod.EditorInfo import android.widget.EditText - +import butterknife.BindView +import butterknife.OnEditorAction import com.stepstone.stepper.Step import com.stepstone.stepper.VerificationError import com.stepstone.stepper.sample.OnProceedListener import com.stepstone.stepper.sample.R -import butterknife.BindView -import butterknife.OnEditorAction - internal class FormStepFragment : ButterKnifeFragment(), Step { companion object {