Skip to content

Commit

Permalink
Merge pull request #1360 from JakeWharton/jakew/functional/2018-09-11
Browse files Browse the repository at this point in the history
Migrate @OnClick codegen tests to functional tests
  • Loading branch information
JakeWharton authored Sep 11, 2018
2 parents 51e3c4f + 3ef792c commit 83216d8
Show file tree
Hide file tree
Showing 4 changed files with 275 additions and 436 deletions.
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

0 comments on commit 83216d8

Please sign in to comment.