diff options
author | Kenny Root <kenny@the-b.org> | 2015-08-28 00:17:24 -0700 |
---|---|---|
committer | Kenny Root <kenny@the-b.org> | 2015-08-28 00:17:24 -0700 |
commit | 1b09070fbf3f1224a5d509c5954ef9560eaf9ba1 (patch) | |
tree | c8550931954db1ce4bddc2a9fb6d80b0056cfba4 /app/src | |
parent | b3f5f9b41c89f74792f2a027ed2ab31a60c88b5e (diff) | |
parent | f6ef2b5e6a4f33ce1d14c5a0d802b30a446ae2bf (diff) | |
download | connectbot-1b09070fbf3f1224a5d509c5954ef9560eaf9ba1.tar.gz connectbot-1b09070fbf3f1224a5d509c5954ef9560eaf9ba1.tar.bz2 connectbot-1b09070fbf3f1224a5d509c5954ef9560eaf9ba1.zip |
Merge pull request #157 from kruton/android-test
Create test for local connections
Diffstat (limited to 'app/src')
5 files changed, 228 insertions, 3 deletions
diff --git a/app/src/androidTest/java/org/connectbot/StartupTest.java b/app/src/androidTest/java/org/connectbot/StartupTest.java new file mode 100644 index 0000000..ea5b584 --- /dev/null +++ b/app/src/androidTest/java/org/connectbot/StartupTest.java @@ -0,0 +1,161 @@ +package org.connectbot; + +import org.connectbot.bean.HostBean; +import org.connectbot.util.HostDatabase; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import android.content.Intent; +import android.support.annotation.NonNull; +import android.support.test.InstrumentationRegistry; +import android.support.test.espresso.ViewAssertion; +import android.support.test.espresso.intent.Intents; +import android.support.test.espresso.matcher.BoundedMatcher; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; +import android.view.KeyEvent; +import android.view.View; +import android.widget.ImageView; + +import static android.support.test.espresso.Espresso.onData; +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; +import static android.support.test.espresso.action.ViewActions.longClick; +import static android.support.test.espresso.action.ViewActions.pressBack; +import static android.support.test.espresso.action.ViewActions.pressKey; +import static android.support.test.espresso.action.ViewActions.pressMenuKey; +import static android.support.test.espresso.action.ViewActions.typeText; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.intent.Intents.intended; +import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent; +import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static org.hamcrest.CoreMatchers.allOf; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; + +@RunWith(AndroidJUnit4.class) +public class StartupTest { + @Rule + public final ActivityTestRule<HostListActivity> mActivityRule = new ActivityTestRule<>( + HostListActivity.class, false, false); + + @Before + public void makeDatabasePristine() { + HostDatabase db = new HostDatabase(InstrumentationRegistry.getTargetContext()); + db.resetDatabase(); + + mActivityRule.launchActivity(new Intent()); + } + + @Test + public void localConnectionDisconnectFromHostList() { + startNewLocalConnection(); + + onView(withId(R.id.console_flip)).perform(closeSoftKeyboard(), pressBack()); + + // Make sure we're still connected. + onData(withHostNickname("Local")).inAdapterView(withId(android.R.id.list)) + .check(hostConnected()) + .perform(longClick()); + + // Click on the disconnect context menu item. + onView(withText(R.string.list_host_disconnect)).check(matches(isDisplayed())).perform(click()); + + // Now make sure we're disconnected. + onData(withHostNickname("Local")).inAdapterView(withId(android.R.id.list)) + .check(hostDisconnected()); + } + + @Test + public void localConnectionDisconnectConsoleActivity() { + startNewLocalConnection(); + + onView(withId(R.id.console_flip)).perform(pressMenuKey()); + + // Click on the disconnect context menu item. + onView(withText(R.string.list_host_disconnect)).check(matches(isDisplayed())).perform(click()); + + // Now make sure we're disconnected. + onData(withHostNickname("Local")).inAdapterView(withId(android.R.id.list)) + .check(hostDisconnected()); + } + + private void startNewLocalConnection() { + onView(withId(R.id.transport_selection)).perform(click()); + onData(allOf(is(instanceOf(String.class)), is("local"))).perform(click()); + onView(withId(R.id.front_quickconnect)).perform(typeText("Local")); + + Intents.init(); + onView(withId(R.id.front_quickconnect)).perform(pressKey(KeyEvent.KEYCODE_ENTER)); + intended(hasComponent(ConsoleActivity.class.getName())); + Intents.release(); + + onView(withId(R.id.console_flip)).check(matches( + hasDescendant(allOf(isDisplayed(), withId(R.id.terminal_view))))); + } + + /** + * Matches the nickname of a {@link HostBean}. + */ + public static Matcher<Object> withHostNickname(final String content) { + return new BoundedMatcher<Object, HostBean>(HostBean.class) { + @Override + public boolean matchesSafely(HostBean host) { + return host.getNickname().matches(content); + } + + @Override + public void describeTo(Description description) { + description.appendText("with host nickname '" + content + "'"); + } + }; + } + + /** + * Matches the drawable state on an ImageView that is set with setImageState. + */ + public static Matcher<View> withDrawableState(final int expectedState) { + return new TypeSafeMatcher<View>() { + @Override + public boolean matchesSafely(View view) { + if (!(view instanceof ImageView)) { + return false; + } + + int[] states = view.getDrawableState(); + for (int state : states) { + if (state == expectedState) { + return true; + } + } + return false; + } + + @Override + public void describeTo(Description description) { + description.appendText("with drawable state '" + expectedState + "'"); + } + }; + } + + @NonNull + private ViewAssertion hostDisconnected() { + return matches(hasDescendant(allOf(withId(android.R.id.icon), + withDrawableState(android.R.attr.state_expanded)))); + } + + @NonNull + private ViewAssertion hostConnected() { + return matches(hasDescendant(allOf(withId(android.R.id.icon), + withDrawableState(android.R.attr.state_checked)))); + } +} diff --git a/app/src/main/java/org/connectbot/ConsoleActivity.java b/app/src/main/java/org/connectbot/ConsoleActivity.java index 0e23979..4d6b114 100644 --- a/app/src/main/java/org/connectbot/ConsoleActivity.java +++ b/app/src/main/java/org/connectbot/ConsoleActivity.java @@ -1357,7 +1357,7 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne // and add our terminal view control, using index to place behind overlay final TerminalView terminal = new TerminalView(container.getContext(), bridge); - terminal.setId(R.id.console_flip); + terminal.setId(R.id.terminal_view); view.addView(terminal, 0); // Tag the view with its bridge so it can be retrieved later. @@ -1382,7 +1382,7 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne } View view = (View) object; - TerminalView terminal = (TerminalView) view.findViewById(R.id.console_flip); + TerminalView terminal = (TerminalView) view.findViewById(R.id.terminal_view); HostBean host = terminal.bridge.host; int itemIndex = POSITION_NONE; @@ -1435,7 +1435,7 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne public TerminalView getCurrentTerminalView() { View currentView = pager.findViewWithTag(getBridgeAtPosition(pager.getCurrentItem())); if (currentView == null) return null; - return (TerminalView) currentView.findViewById(R.id.console_flip); + return (TerminalView) currentView.findViewById(R.id.terminal_view); } } } diff --git a/app/src/main/java/org/connectbot/util/HostDatabase.java b/app/src/main/java/org/connectbot/util/HostDatabase.java index d8cdf09..f721aeb 100644 --- a/app/src/main/java/org/connectbot/util/HostDatabase.java +++ b/app/src/main/java/org/connectbot/util/HostDatabase.java @@ -32,6 +32,7 @@ import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; +import android.support.annotation.VisibleForTesting; import android.util.Log; import com.trilead.ssh2.KnownHosts; @@ -155,6 +156,10 @@ public class HostDatabase extends RobustSQLiteOpenHelper { public void onCreate(SQLiteDatabase db) { super.onCreate(db); + createTables(db); + } + + private void createTables(SQLiteDatabase db) { db.execSQL("CREATE TABLE " + TABLE_HOSTS + " (_id INTEGER PRIMARY KEY, " + FIELD_HOST_NICKNAME + " TEXT, " @@ -203,6 +208,17 @@ public class HostDatabase extends RobustSQLiteOpenHelper { db.execSQL(CREATE_TABLE_COLOR_DEFAULTS_INDEX); } + @VisibleForTesting + public void resetDatabase() { + SQLiteDatabase db = getWritableDatabase(); + db.execSQL("DROP TABLE IF EXISTS " + TABLE_HOSTS); + db.execSQL("DROP TABLE IF EXISTS " + TABLE_PORTFORWARDS); + db.execSQL("DROP TABLE IF EXISTS " + TABLE_COLORS); + db.execSQL("DROP TABLE IF EXISTS " + TABLE_COLOR_DEFAULTS); + createTables(db); + db.close(); + } + @Override public void onRobustUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) throws SQLiteException { // Versions of the database before the Android Market release will be diff --git a/app/src/main/res/values/viewpager.xml b/app/src/main/res/values/viewpager.xml new file mode 100644 index 0000000..cc73c50 --- /dev/null +++ b/app/src/main/res/values/viewpager.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ ConnectBot: simple, powerful, open-source SSH client for Android + ~ Copyright 2015 Kenny Root, Jeffrey Sharkey + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<resources> + <!-- This is so that ConsoleActivity has something to refer to when + setting the ID of the TerminalView instances in the ViewPager. --> + <item name="terminal_view" type="id"/> +</resources> diff --git a/app/src/test/java/android/net/http/AndroidHttpClient.java b/app/src/test/java/android/net/http/AndroidHttpClient.java new file mode 100644 index 0000000..701510b --- /dev/null +++ b/app/src/test/java/android/net/http/AndroidHttpClient.java @@ -0,0 +1,25 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2015 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.http; + +/** + * This is a work-around until Robolectric 3.1 comes out with the fix for this. + * https://github.com/robolectric/robolectric/issues/1862 + */ +public class AndroidHttpClient { +} |