Limit max parameters + add Espresso tests

This commit is contained in:
serso 2016-02-26 14:35:25 +01:00
parent c002e7caf9
commit ea4d107b12
11 changed files with 150 additions and 24 deletions

View File

@ -0,0 +1,58 @@
package org.solovyev.android.calculator.plot;
import android.support.annotation.NonNull;
import android.support.test.espresso.action.ViewActions;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
import android.text.TextUtils;
import org.hamcrest.Matchers;
import org.junit.Rule;
import org.junit.runner.RunWith;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.functions.CppFunction;
import org.solovyev.android.calculator.functions.FunctionParamsView;
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.typeText;
import static android.support.test.espresso.action.ViewActions.typeTextIntoFocusedView;
import static android.support.test.espresso.matcher.ViewMatchers.hasFocus;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withTagValue;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;
@RunWith(AndroidJUnit4.class)
@LargeTest
public class BasePlotTest {
@Rule
public ActivityTestRule<PlotActivity> rule = new ActivityTestRule<>(PlotActivity.class);
protected void addFunction(@NonNull CppFunction function) {
openFunctionEditor();
if (!TextUtils.isEmpty(function.getName())) {
onView(withId(R.id.function_name)).perform(typeText(function.getName()));
}
for (String parameter : function.getParameters()) {
onView(withId(R.id.function_params_add)).perform(click());
onView(allOf(hasFocus(), withTagValue(Matchers.<Object>equalTo(FunctionParamsView.PARAM_VIEW_TAG)))).perform(click(), typeTextIntoFocusedView(parameter));
}
onView(withId(R.id.function_body)).perform(typeText(function.getBody()));
onView(withText(R.string.ok)).perform(click());
}
protected final void openFunctionEditor() {
onView(withId(R.id.plot_view_frame)).perform(ViewActions.click());
onView(withId(R.id.plot_add_function)).perform(click());
}
protected final void openFunctionsList() {
onView(withId(R.id.plot_view_frame)).perform(ViewActions.click());
onView(withId(R.id.plot_functions)).perform(click());
}
}

View File

@ -0,0 +1,22 @@
package org.solovyev.android.calculator.plot;
import org.junit.Test;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.functions.CppFunction;
import static android.support.test.espresso.Espresso.onView;
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;
public class PlotEditFunctionFragmentTest extends BasePlotTest {
@Test
public void testShouldAddFunction() throws Exception {
final CppFunction function = CppFunction.builder("", "x + y").withParameters("x", "y").build();
addFunction(function);
openFunctionsList();
onView(withId(R.id.function_name)).check(matches(withText("x+y")));
}
}

View File

@ -119,7 +119,11 @@
<activity <activity
android:name=".plot.PlotActivity" android:name=".plot.PlotActivity"
android:label="@string/cpp_plotter" /> android:label="@string/cpp_plotter">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
</activity>
<activity <activity
android:name=".wizard.WizardActivity" android:name=".wizard.WizardActivity"

View File

@ -84,6 +84,7 @@ public abstract class BaseFunctionFragment extends BaseDialogFragment implements
@NonNull @NonNull
private final KeyboardUser keyboardUser = new KeyboardUser(); private final KeyboardUser keyboardUser = new KeyboardUser();
@Bind(R.id.function_params) @Bind(R.id.function_params)
public
FunctionParamsView paramsView; FunctionParamsView paramsView;
@Bind(R.id.function_name_label) @Bind(R.id.function_name_label)
TextInputLayout nameLabel; TextInputLayout nameLabel;

View File

@ -4,9 +4,7 @@ import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.text.TextUtils; import android.text.TextUtils;
import jscl.math.function.CustomFunction;
import jscl.math.function.Function;
import jscl.math.function.IFunction;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -16,11 +14,18 @@ import org.solovyev.android.calculator.json.Jsonable;
import org.solovyev.common.JBuilder; import org.solovyev.common.JBuilder;
import org.solovyev.common.text.Strings; import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
import jscl.math.function.CustomFunction;
import jscl.math.function.Function;
import jscl.math.function.IFunction;
import static java.util.Arrays.asList;
public class CppFunction implements Jsonable, Parcelable { public class CppFunction implements Jsonable, Parcelable {
public static final Json.Creator<CppFunction> JSON_CREATOR = new Json.Creator<CppFunction>() { public static final Json.Creator<CppFunction> JSON_CREATOR = new Json.Creator<CppFunction>() {
@ -230,6 +235,13 @@ public class CppFunction implements Jsonable, Parcelable {
return this; return this;
} }
@Nonnull
public Builder withParameters(@Nonnull String... parameters) {
Check.isTrue(!built);
function.parameters.addAll(asList(parameters));
return this;
}
@Nonnull @Nonnull
public Builder withParameter(@Nonnull String parameter) { public Builder withParameter(@Nonnull String parameter) {
Check.isTrue(!built); Check.isTrue(!built);

View File

@ -36,17 +36,23 @@ import android.view.Gravity;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.widget.*; import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.solovyev.android.Check; import org.solovyev.android.Check;
import org.solovyev.android.calculator.App; import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.Preferences; import org.solovyev.android.calculator.Preferences;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
@ -63,6 +69,9 @@ public class FunctionParamsView extends LinearLayout {
@Nonnull @Nonnull
private final Preferences.Gui.Theme theme = App.getTheme(); private final Preferences.Gui.Theme theme = App.getTheme();
private int maxRowId = START_ROW_ID; private int maxRowId = START_ROW_ID;
private int maxParams = Integer.MAX_VALUE;
@Nonnull
private LinearLayout headerView;
{ {
final Resources resources = getResources(); final Resources resources = getResources();
@ -91,8 +100,9 @@ public class FunctionParamsView extends LinearLayout {
setOrientation(VERTICAL); setOrientation(VERTICAL);
final Context context = getContext(); final Context context = getContext();
final LinearLayout headerView = makeRowView(context); headerView = makeRowView(context);
final ImageButton addButton = makeButton(theme.light ? R.drawable.ic_add_black_24dp : R.drawable.ic_add_white_24dp); final ImageButton addButton = makeButton(theme.light ? R.drawable.ic_add_black_24dp : R.drawable.ic_add_white_24dp);
addButton.setId(R.id.function_params_add);
addButton.setOnClickListener(new View.OnClickListener() { addButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
@ -187,9 +197,15 @@ public class FunctionParamsView extends LinearLayout {
// for row is added at 0 position, the consequent rows // for row is added at 0 position, the consequent rows
addView(rowView, Math.max(0, getChildCount() - 1), new ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT)); addView(rowView, Math.max(0, getChildCount() - 1), new ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
onParamsChanged();
return rowView; return rowView;
} }
private void onParamsChanged() {
final boolean enabled = getParamsCount() < maxParams;
headerView.setVisibility(enabled ? VISIBLE : GONE);
}
@NonNull @NonNull
private LayoutParams makeButtonParams() { private LayoutParams makeButtonParams() {
return new LayoutParams(imageButtonSize, imageButtonSize); return new LayoutParams(imageButtonSize, imageButtonSize);
@ -224,19 +240,20 @@ public class FunctionParamsView extends LinearLayout {
@Nonnull @Nonnull
private ViewGroup getRow(int index) { private ViewGroup getRow(int index) {
Check.isTrue(index >= 0 && index < getChildCount() - FOOTERS); Check.isTrue(index >= 0 && index < getParamsCount());
return (ViewGroup) getChildAt(index); return (ViewGroup) getChildAt(index);
} }
public void removeRow(@Nonnull ViewGroup row) { public void removeRow(@Nonnull ViewGroup row) {
removeView(row); removeView(row);
onParamsChanged();
} }
@Nonnull @Nonnull
public List<String> getParams() { public List<String> getParams() {
final List<String> params = new ArrayList<>(getChildCount()); final List<String> params = new ArrayList<>(getParamsCount());
for (int i = 0; i < getChildCount() - FOOTERS; i++) { for (int i = 0; i < getParamsCount(); i++) {
final ViewGroup row = getRow(i); final ViewGroup row = getRow(i);
final EditText paramView = getParamView(row); final EditText paramView = getParamView(row);
params.add(paramView.getText().toString()); params.add(paramView.getText().toString());
@ -245,6 +262,15 @@ public class FunctionParamsView extends LinearLayout {
return params; return params;
} }
private int getParamsCount() {
return getChildCount() - FOOTERS;
}
public void setMaxParams(int maxParams) {
this.maxParams = maxParams;
onParamsChanged();
}
@Nonnull @Nonnull
private EditText getParamView(@Nonnull ViewGroup row) { private EditText getParamView(@Nonnull ViewGroup row) {
final TextInputLayout paramLabel = getParamLabel(row); final TextInputLayout paramLabel = getParamLabel(row);

View File

@ -16,12 +16,12 @@ import org.solovyev.android.plotter.Dimensions;
import org.solovyev.android.plotter.PlotViewFrame; import org.solovyev.android.plotter.PlotViewFrame;
import org.solovyev.android.plotter.Plotter; import org.solovyev.android.plotter.Plotter;
import butterknife.Bind;
import butterknife.ButterKnife;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.inject.Inject; import javax.inject.Inject;
import butterknife.Bind;
import butterknife.ButterKnife;
public class PlotActivity extends BaseActivity { public class PlotActivity extends BaseActivity {
public static class MyFragment extends BaseFragment implements PlotViewFrame.Listener { public static class MyFragment extends BaseFragment implements PlotViewFrame.Listener {
@ -79,7 +79,7 @@ public class PlotActivity extends BaseActivity {
PlotFunctionsFragment.show(getActivity().getSupportFragmentManager()); PlotFunctionsFragment.show(getActivity().getSupportFragmentManager());
return true; return true;
} else if (id == R.id.plot_add_function) { } else if (id == R.id.plot_add_function) {
//App.getBus().post(new AddFunctionDialog.ShowEvent()); PlotEditFunctionFragment.show(null, getActivity().getSupportFragmentManager());
return true; return true;
} }
return false; return false;

View File

@ -111,6 +111,7 @@ public class PlotEditFunctionFragment extends BaseFunctionFragment
final int[] colors = MeshSpec.LightColors.asIntArray(); final int[] colors = MeshSpec.LightColors.asIntArray();
colorPicker.setColors(colors); colorPicker.setColors(colors);
paramsView.setMaxParams(2);
if (savedInstanceState == null) { if (savedInstanceState == null) {
if (plotFunction != null) { if (plotFunction != null) {
setupViews(plotFunction.meshSpec); setupViews(plotFunction.meshSpec);

View File

@ -1,8 +1,5 @@
package org.solovyev.android.calculator.plot; package org.solovyev.android.calculator.plot;
import static android.support.v7.widget.LinearLayoutManager.VERTICAL;
import static android.view.Menu.NONE;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
@ -32,14 +29,17 @@ import org.solovyev.android.plotter.Plotter;
import org.solovyev.android.views.llm.DividerItemDecoration; import org.solovyev.android.views.llm.DividerItemDecoration;
import org.solovyev.android.views.llm.LinearLayoutManager; import org.solovyev.android.views.llm.LinearLayoutManager;
import butterknife.Bind;
import butterknife.ButterKnife;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.inject.Inject; import javax.inject.Inject;
import butterknife.Bind;
import butterknife.ButterKnife;
import static android.support.v7.widget.LinearLayoutManager.VERTICAL;
import static android.view.Menu.NONE;
public class PlotFunctionsFragment extends BaseDialogFragment { public class PlotFunctionsFragment extends BaseDialogFragment {
@Inject @Inject
@ -120,7 +120,7 @@ public class PlotFunctionsFragment extends BaseDialogFragment {
@Bind(R.id.function_icon) @Bind(R.id.function_icon)
PlotIconView icon; PlotIconView icon;
@Bind(R.id.fn_name_edittext) @Bind(R.id.function_name)
TextView name; TextView name;
private PlotFunction function; private PlotFunction function;

View File

@ -16,7 +16,7 @@
android:layout_height="match_parent" /> android:layout_height="match_parent" />
<TextView <TextView
android:id="@+id/fn_name_edittext" android:id="@+id/function_name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"

View File

@ -73,4 +73,6 @@
<item name="cpp_kb_button_close" type="id" /> <item name="cpp_kb_button_close" type="id" />
<item name="cpp_kb_button_change_case" type="id" /> <item name="cpp_kb_button_change_case" type="id" />
<item name="function_params_add" type="id" />
</resources> </resources>