Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate @OnClick codegen tests to functional tests #1360

Merged
merged 1 commit into from
Sep 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions butterknife-integration-test/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ dependencies {

codegenImplementation project(':butterknife')
codegenAnnotationProcessor project(':butterknife-compiler')
androidTestCodegenAnnotationProcessor project(':butterknife-compiler')

androidTestImplementation deps.junit
androidTestImplementation deps.truth
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
package com.example.butterknife.functional;

import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Optional;
import butterknife.Unbinder;
import com.example.butterknife.BuildConfig;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assume.assumeFalse;

@SuppressWarnings("unused") // Used reflectively / by code gen.
public final class OnClickTest {
static final class Simple {
int clicks = 0;

@OnClick(1) void click() {
clicks++;
}
}

@Test public void simple() {
View tree = treeWithIds(1);
View view1 = tree.findViewById(1);

Simple target = new Simple();
Unbinder unbinder = ButterKnife.bind(target, tree);
assertEquals(0, target.clicks);

view1.performClick();
assertEquals(1, target.clicks);

unbinder.unbind();
view1.performClick();
assertEquals(1, target.clicks);
}

static final class MultipleBindings {
int clicks = 0;

@OnClick(1) void click1() {
clicks++;
}

@OnClick(1) void clicks2() {
clicks++;
}
}

@Test public void multipleBindings() {
assumeFalse("Not implemented", BuildConfig.FLAVOR.equals("reflect")); // TODO

View tree = treeWithIds(1);
View view1 = tree.findViewById(1);

MultipleBindings target = new MultipleBindings();
Unbinder unbinder = ButterKnife.bind(target, tree);
assertEquals(0, target.clicks);

view1.performClick();
assertEquals(2, target.clicks);

unbinder.unbind();
view1.performClick();
assertEquals(2, target.clicks);
}

static final class Visibilities {
int clicks = 0;

@OnClick(1) public void publicClick() {
clicks++;
}

@OnClick(2) void packageClick() {
clicks++;
}

@OnClick(3) protected void protectedClick() {
clicks++;
}
}

@Test public void visibilities() {
View tree = treeWithIds(1, 2, 3);
View view1 = tree.findViewById(1);
View view2 = tree.findViewById(2);
View view3 = tree.findViewById(3);

Visibilities target = new Visibilities();
ButterKnife.bind(target, tree);
assertEquals(0, target.clicks);

view1.performClick();
assertEquals(1, target.clicks);

view2.performClick();
assertEquals(2, target.clicks);

view3.performClick();
assertEquals(3, target.clicks);
}

static final class MultipleIds {
int clicks = 0;

@OnClick({1, 2}) void click() {
clicks++;
}
}

@Test public void multipleIds() {
View tree = treeWithIds(1, 2);
View view1 = tree.findViewById(1);
View view2 = tree.findViewById(2);

MultipleIds target = new MultipleIds();
Unbinder unbinder = ButterKnife.bind(target, tree);
assertEquals(0, target.clicks);

view1.performClick();
assertEquals(1, target.clicks);

view2.performClick();
assertEquals(2, target.clicks);

unbinder.unbind();
view1.performClick();
view2.performClick();
assertEquals(2, target.clicks);
}

static final class OptionalId {
int clicks = 0;

@Optional @OnClick(1) public void click() {
clicks++;
}
}

@Test public void optionalIdPresent() {
View tree = treeWithIds(1);
View view1 = tree.findViewById(1);

OptionalId target = new OptionalId();
Unbinder unbinder = ButterKnife.bind(target, tree);
assertEquals(0, target.clicks);

view1.performClick();
assertEquals(1, target.clicks);

unbinder.unbind();
view1.performClick();
assertEquals(1, target.clicks);
}

@Test public void optionalIdAbsent() {
View tree = treeWithIds(2);
View view2 = tree.findViewById(2);

OptionalId target = new OptionalId();
Unbinder unbinder = ButterKnife.bind(target, tree);
assertEquals(0, target.clicks);

view2.performClick();
assertEquals(0, target.clicks);

unbinder.unbind();
view2.performClick();
assertEquals(0, target.clicks);
}

static final class ArgumentCast {
interface MyInterface {}

View last;

@OnClick(1) void clickView(View view) {
last = view;
}

@OnClick(2) void clickTextView(TextView view) {
last = view;
}

@OnClick(3) void clickButton(Button view) {
last = view;
}

@OnClick(4) void clickMyInterface(MyInterface view) {
last = (View) view;
}
}

@Test public void argumentCast() {
class MyView extends Button implements ArgumentCast.MyInterface {
MyView(Context context) {
super(context);
}

@Override public boolean post(Runnable action) {
// Because of DebouncingOnClickListener, we run any posted Runnables synchronously.
action.run();
return true;
}
}

View view1 = new MyView(InstrumentationRegistry.getContext());
view1.setId(1);
View view2 = new MyView(InstrumentationRegistry.getContext());
view2.setId(2);
View view3 = new MyView(InstrumentationRegistry.getContext());
view3.setId(3);
View view4 = new MyView(InstrumentationRegistry.getContext());
view4.setId(4);
ViewGroup tree = new FrameLayout(InstrumentationRegistry.getContext());
tree.addView(view1);
tree.addView(view2);
tree.addView(view3);
tree.addView(view4);

ArgumentCast target = new ArgumentCast();
ButterKnife.bind(target, tree);

view1.performClick();
assertSame(view1, target.last);

view2.performClick();
assertSame(view2, target.last);

view3.performClick();
assertSame(view3, target.last);

view4.performClick();
assertSame(view4, target.last);
}

private static View treeWithIds(int... ids) {
Context context = InstrumentationRegistry.getContext();
FrameLayout group = new FrameLayout(context);

class SuperGrossView extends View {
SuperGrossView(Context context) {
super(context);
}

@Override public boolean post(Runnable action) {
// Because of DebouncingOnClickListener, we run any posted Runnables synchronously.
action.run();
return true;
}
}

for (int id : ids) {
View view = new SuperGrossView(context);
view.setId(id);
group.addView(view);
}
return group;
}
}
4 changes: 4 additions & 0 deletions butterknife-integration-test/src/main/proguard.pro
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

# STUFF USED BY TESTS:

-keep class butterknife.internal.Utils {
<methods>;
}

-keep class butterknife.Unbinder {
void unbind();
}
Expand Down
Loading