From 58b94e8cef66ff9829a7c1d8d189cf60cb05a064 Mon Sep 17 00:00:00 2001 From: Tiou Lims Date: Fri, 2 Mar 2018 12:09:28 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=BC=95=E7=94=A8=E6=8D=95?= =?UTF-8?q?=E8=8E=B7=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- library/build.gradle | 4 + library/src/androidTest/AndroidManifest.xml | 12 +++ .../esactivity/CaptureInstrumentedTest.java | 80 +++++++++++++++ .../esactivity/ExampleInstrumentedTest.java | 26 ----- .../activity/CaptureTestActivity.java | 39 ++++++++ .../esactivity/activity/EditorActivity.java | 56 +++++++++++ .../activity/OneButtonFragment.java | 59 +++++++++++ .../esactivity/util/EspressoHelper.java | 33 +++++++ .../util/OrientationChangeAction.java | 99 +++++++++++++++++++ .../res/layout/activity_editor.xml | 26 +++++ .../androidTest/res/layout/activity_test.xml | 42 ++++++++ .../src/androidTest/res/menu/menu_editor.xml | 10 ++ .../src/androidTest/res/values/strings.xml | 4 + library/src/androidTest/res/values/styles.xml | 8 ++ 14 files changed, 472 insertions(+), 26 deletions(-) create mode 100644 library/src/androidTest/AndroidManifest.xml create mode 100644 library/src/androidTest/java/info/dourok/esactivity/CaptureInstrumentedTest.java delete mode 100644 library/src/androidTest/java/info/dourok/esactivity/ExampleInstrumentedTest.java create mode 100644 library/src/androidTest/java/info/dourok/esactivity/activity/CaptureTestActivity.java create mode 100644 library/src/androidTest/java/info/dourok/esactivity/activity/EditorActivity.java create mode 100644 library/src/androidTest/java/info/dourok/esactivity/activity/OneButtonFragment.java create mode 100644 library/src/androidTest/java/info/dourok/esactivity/util/EspressoHelper.java create mode 100644 library/src/androidTest/java/info/dourok/esactivity/util/OrientationChangeAction.java create mode 100644 library/src/androidTest/res/layout/activity_editor.xml create mode 100644 library/src/androidTest/res/layout/activity_test.xml create mode 100644 library/src/androidTest/res/menu/menu_editor.xml create mode 100644 library/src/androidTest/res/values/strings.xml create mode 100644 library/src/androidTest/res/values/styles.xml diff --git a/library/build.gradle b/library/build.gradle index 57e38f4..1e00972 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -32,6 +32,10 @@ dependencies { implementation deps.support.annotations implementation deps.support.fragment + implementation 'com.android.support:support-v4:26.1.0' + androidTestImplementation 'com.android.support:appcompat-v7:27.0.2' + androidTestImplementation 'com.android.support.constraint:constraint-layout:1.0.2' + androidTestAnnotationProcessor project(':compiler') testImplementation deps.junit androidTestImplementation deps.support.test.runner androidTestImplementation deps.support.test.espresso diff --git a/library/src/androidTest/AndroidManifest.xml b/library/src/androidTest/AndroidManifest.xml new file mode 100644 index 0000000..3a4b393 --- /dev/null +++ b/library/src/androidTest/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/library/src/androidTest/java/info/dourok/esactivity/CaptureInstrumentedTest.java b/library/src/androidTest/java/info/dourok/esactivity/CaptureInstrumentedTest.java new file mode 100644 index 0000000..7e38615 --- /dev/null +++ b/library/src/androidTest/java/info/dourok/esactivity/CaptureInstrumentedTest.java @@ -0,0 +1,80 @@ +package info.dourok.esactivity; + +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; +import info.dourok.esactivity.activity.CaptureTestActivity; +import info.dourok.esactivity.test.R; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static android.support.test.InstrumentationRegistry.getInstrumentation; +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.Espresso.pressBack; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.replaceText; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static info.dourok.esactivity.util.EspressoHelper.getActivityInstance; +import static org.hamcrest.Matchers.not; +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class CaptureInstrumentedTest { + @Rule + public ActivityTestRule mActivityRule = + new ActivityTestRule<>(CaptureTestActivity.class); + + + @Test + public void activity__ref_should_be_updated_after_activity_recreate() { + String id = getActivityInstance().toString(); + onView(withText("captureActivity")).perform(click()); + + getInstrumentation().runOnMainSync(() -> mActivityRule.getActivity().recreate()); + + pressBack(); + String idNew = getActivityInstance().toString(); + onView(withId(R.id.content)).check(matches(not(withText(id)))); + onView(withId(R.id.content)).check(matches(withText(idNew))); + } + + @Test + public void view_with_id__ref_should_be_updated_after_activity_recreate() { + final String text = "text"; + onView(withText("captureView")).perform(click()); + + getInstrumentation().runOnMainSync(() -> mActivityRule.getActivity().recreate()); + + onView(withId(R.id.edit_text)).perform(replaceText(text)); + onView(withId(R.id.action_ok)).perform(click()); + onView(withId(R.id.content)).check(matches(withText(text))); + } + + @Test + public void fragment_with_id__ref_should_be_updated_after_activity_recreate(){ + final String text = "text"; + onView(withText("captureFragment")).perform(click()); + + getInstrumentation().runOnMainSync(() -> mActivityRule.getActivity().recreate()); + + onView(withId(R.id.edit_text)).perform(replaceText(text)); + onView(withId(R.id.action_ok)).perform(click()); + onView(withId(R.id.content)).check(matches(withText(text))); + } + + + @Test + public void method__ref_should_be_updated_after_activity_recreate() throws Exception { + final String text = "text"; + onView(withText("methodRef")).perform(click()); + getInstrumentation().runOnMainSync(() -> mActivityRule.getActivity().recreate()); + onView(withId(R.id.edit_text)).perform(replaceText(text)); + onView(withId(R.id.action_ok)).perform(click()); + onView(withId(R.id.content)).check(matches(withText(text))); + } +} diff --git a/library/src/androidTest/java/info/dourok/esactivity/ExampleInstrumentedTest.java b/library/src/androidTest/java/info/dourok/esactivity/ExampleInstrumentedTest.java deleted file mode 100644 index 5c8bc56..0000000 --- a/library/src/androidTest/java/info/dourok/esactivity/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package info.dourok.esactivity; - -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() throws Exception { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("info.dourok.esactivity.test", appContext.getPackageName()); - } -} diff --git a/library/src/androidTest/java/info/dourok/esactivity/activity/CaptureTestActivity.java b/library/src/androidTest/java/info/dourok/esactivity/activity/CaptureTestActivity.java new file mode 100644 index 0000000..889f8b0 --- /dev/null +++ b/library/src/androidTest/java/info/dourok/esactivity/activity/CaptureTestActivity.java @@ -0,0 +1,39 @@ +package info.dourok.esactivity.activity; + +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; + +import android.view.View; +import android.widget.TextView; +import info.dourok.esactivity.BuilderUtil; +import info.dourok.esactivity.test.R; + +public class CaptureTestActivity extends AppCompatActivity { + + private TextView textView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_test); + textView = findViewById(R.id.content); + } + + public void captureActivity(View v) { + EditorActivityBuilder.create(this).forCancel(intent -> showContent(this.toString())).start(); + } + + public void captureView(View v) { + TextView localTextView = findViewById(R.id.content); + EditorActivityBuilder.create(this).forContent(localTextView::setText).start(); + } + + public void methodRef(View v) { + + EditorActivityBuilder.create(this).forContent(this::showContent).start(); + } + + void showContent(String s) { + textView.setText(s); + } +} diff --git a/library/src/androidTest/java/info/dourok/esactivity/activity/EditorActivity.java b/library/src/androidTest/java/info/dourok/esactivity/activity/EditorActivity.java new file mode 100644 index 0000000..b14b060 --- /dev/null +++ b/library/src/androidTest/java/info/dourok/esactivity/activity/EditorActivity.java @@ -0,0 +1,56 @@ +package info.dourok.esactivity.activity; + +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.widget.EditText; +import info.dourok.esactivity.Builder; +import info.dourok.esactivity.BuilderParameter; +import info.dourok.esactivity.BuilderUtil; +import info.dourok.esactivity.Result; +import info.dourok.esactivity.ResultParameter; +import info.dourok.esactivity.test.R; + +/** @author tiaolins */ +@Builder +@Result( + name = "content", + parameters = {@ResultParameter(name = "content", type = String.class)} +) +public class EditorActivity extends AppCompatActivity { + @BuilderParameter String hint; + EditorActivityHelper mHelper; + private EditText editText; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_editor); + mHelper = BuilderUtil.createHelper(this); + editText = findViewById(R.id.edit_text); + if (hint != null) { + editText.setHint(hint); + } + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_editor, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + case R.id.action_ok: + mHelper.finishContent(editText.getText().toString()); + return true; + } + return false; + } +} diff --git a/library/src/androidTest/java/info/dourok/esactivity/activity/OneButtonFragment.java b/library/src/androidTest/java/info/dourok/esactivity/activity/OneButtonFragment.java new file mode 100644 index 0000000..f81b6b4 --- /dev/null +++ b/library/src/androidTest/java/info/dourok/esactivity/activity/OneButtonFragment.java @@ -0,0 +1,59 @@ +package info.dourok.esactivity.activity; + +import android.content.Context; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; + +/** A simple {@link Fragment} subclass. */ +public class OneButtonFragment extends Fragment { + + CaptureTestActivity activity; + + public OneButtonFragment() { + // Required empty public constructor + } + + /** + * Use this factory method to create a new instance of this fragment using the provided + * parameters. + */ + public static OneButtonFragment newInstance() { + return new OneButtonFragment(); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + Button btn = new Button(getActivity()); + btn.setText("captureFragment"); + btn.setOnClickListener( + v -> EditorActivityBuilder.create(activity).forContent(activity::showContent).start()); + return btn; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof CaptureTestActivity) { + activity = (CaptureTestActivity) context; + } else { + throw new RuntimeException(context.toString() + " must implement CaptureTestActivity"); + } + } + + @Override + public void onDetach() { + super.onDetach(); + activity = null; + } +} diff --git a/library/src/androidTest/java/info/dourok/esactivity/util/EspressoHelper.java b/library/src/androidTest/java/info/dourok/esactivity/util/EspressoHelper.java new file mode 100644 index 0000000..6fa87b5 --- /dev/null +++ b/library/src/androidTest/java/info/dourok/esactivity/util/EspressoHelper.java @@ -0,0 +1,33 @@ +package info.dourok.esactivity.util; + +import android.app.Activity; +import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry; +import info.dourok.esactivity.function.Consumer; +import java.util.Collection; + +import static android.support.test.InstrumentationRegistry.getInstrumentation; +import static android.support.test.runner.lifecycle.Stage.RESUMED; + +/** + * @author tiaolins + * @date 2018/3/2. + */ +public class EspressoHelper { + private EspressoHelper() {} + + private static Activity currentActivity; + + public static synchronized Activity getActivityInstance() { + getInstrumentation() + .runOnMainSync( + () -> { + Collection resumedActivities = + ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(RESUMED); + if (resumedActivities.iterator().hasNext()) { + currentActivity = resumedActivities.iterator().next(); + } + }); + + return currentActivity; + } +} diff --git a/library/src/androidTest/java/info/dourok/esactivity/util/OrientationChangeAction.java b/library/src/androidTest/java/info/dourok/esactivity/util/OrientationChangeAction.java new file mode 100644 index 0000000..e569eed --- /dev/null +++ b/library/src/androidTest/java/info/dourok/esactivity/util/OrientationChangeAction.java @@ -0,0 +1,99 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 - Nathan Barraille + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +package info.dourok.esactivity.util; + +import android.app.Activity; +import android.content.pm.ActivityInfo; +import android.support.test.espresso.UiController; +import android.support.test.espresso.ViewAction; +import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry; +import android.support.test.runner.lifecycle.Stage; +import android.view.View; +import java.lang.reflect.Field; +import java.util.Collection; +import org.hamcrest.Matcher; + +import static android.support.test.espresso.matcher.ViewMatchers.isRoot; + +/** An Espresso ViewAction that changes the orientation of the screen */ +public class OrientationChangeAction implements ViewAction { + private final int orientation; + + private OrientationChangeAction(int orientation) { + this.orientation = orientation; + } + + @Override + public Matcher getConstraints() { + return isRoot(); + } + + @Override + public String getDescription() { + return "change orientation to " + orientation; + } + + @Override + public void perform(UiController uiController, View view) { + uiController.loopMainThreadUntilIdle(); + final Activity activity = getActivity(view); + activity.setRequestedOrientation(orientation); + + Collection resumedActivities = + ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED); + if (resumedActivities.isEmpty()) { + throw new RuntimeException("Could not change orientation"); + } + } + + private static Activity getActivity(View view) { + Activity activity = null; + if (view.getContext() + .getClass() + .getName() + .contains("com.android.internal.policy.DecorContext")) { + try { + Field field = view.getContext().getClass().getDeclaredField("mPhoneWindow"); + field.setAccessible(true); + Object obj = field.get(view.getContext()); + java.lang.reflect.Method m1 = obj.getClass().getMethod("getContext"); + activity = (Activity) (m1.invoke(obj)); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + activity = (Activity) view.getContext(); + } + return activity; + } + + public static ViewAction orientationLandscape() { + return new OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } + + public static ViewAction orientationPortrait() { + return new OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } +} diff --git a/library/src/androidTest/res/layout/activity_editor.xml b/library/src/androidTest/res/layout/activity_editor.xml new file mode 100644 index 0000000..685ca4d --- /dev/null +++ b/library/src/androidTest/res/layout/activity_editor.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/library/src/androidTest/res/layout/activity_test.xml b/library/src/androidTest/res/layout/activity_test.xml new file mode 100644 index 0000000..a1f6706 --- /dev/null +++ b/library/src/androidTest/res/layout/activity_test.xml @@ -0,0 +1,42 @@ + + + + +