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

Generate model factory methods #450

Merged
merged 14 commits into from
Jun 27, 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 epoxy-modelfactory/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
59 changes: 59 additions & 0 deletions epoxy-modelfactory/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import org.gradle.internal.jvm.Jvm

apply plugin: 'com.android.library'
apply from: 'build.workaround-missing-resource.gradle'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'

android {
compileSdkVersion rootProject.COMPILE_SDK_VERSION

defaultConfig {
minSdkVersion rootProject.MIN_SDK_VERSION
targetSdkVersion rootProject.TARGET_SDK_VERSION
}
}

configurations.all { strategy ->
strategy.resolutionStrategy.force rootProject.deps.junit, rootProject.deps.robolectric,
rootProject.deps.mockito
}

dependencies {
compile project(':epoxy-adapter')
compile rootProject.deps.paris

testCompile project(':epoxy-adapter')
// Need to include the processor directly since we create an instance of it in code for testing
testCompile project(':epoxy-processor')
testCompile project(':epoxy-processortest')
testCompile rootProject.deps.googleTestingCompile
testCompile rootProject.deps.junit
testCompile rootProject.deps.kotlin
// Need to include the processor directly since we create an instance of it in code for testing
testCompile rootProject.deps.parisProcessor
testCompile rootProject.deps.robolectric
testCompile files(getRuntimeJar())
testCompile files(Jvm.current().getToolsJar())

kaptTest project(':epoxy-processor')
}

// Javadoc isn't working well with Kotlin :(
tasks.withType(Javadoc).all { enabled = false }

static def getRuntimeJar() {
try {
final File javaBase = new File(System.getProperty("java.home")).getCanonicalFile()
File runtimeJar = new File(javaBase, "lib/rt.jar")
if (runtimeJar.exists()) {
return runtimeJar
}
runtimeJar = new File(javaBase, "jre/lib/rt.jar")
return runtimeJar.exists() ? runtimeJar : null
} catch (IOException e) {
throw new RuntimeException(e)
}
}

apply from: rootProject.file('gradle/gradle-maven-push.gradle')
23 changes: 23 additions & 0 deletions epoxy-modelfactory/build.workaround-missing-resource.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Source - https://github.com/nenick/AndroidStudioAndRobolectric/blob/master/app/build.workaround-missing-resource.gradle
// Workaround for missing test resources when running unit tests within android studio.
// This copies the test resources next to the test classes for each variant.
// Tracked at https://github.com/nenick/AndroidStudioAndRobolectric/issues/7
// Original solution comes from https://code.google.com/p/android/issues/detail?id=136013#c10
// See also https://code.google.com/p/android/issues/detail?id=64887
gradle.projectsEvaluated {
// Base path which is recognized by android studio.
def testClassesPath = "${buildDir}/intermediates/classes/test/"
// Copy must be done for each variant.
def variants = android.libraryVariants.collect()

variants.each { variant ->
def variationName = variant.name.capitalize()
def variationPath = variant.buildType.name

// Specific copy task for each variant
def copyTestResourcesTask = project.tasks.create("copyTest${variationName}Resources", Copy)
copyTestResourcesTask.from("${projectDir}/src/test/resources")
copyTestResourcesTask.into("${testClassesPath}/${variationPath}")
copyTestResourcesTask.execute()
}
}
3 changes: 3 additions & 0 deletions epoxy-modelfactory/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
POM_NAME=Epoxy Model Factory
POM_ARTIFACT_ID=epoxy-modelfactory
POM_PACKAGING=jar
2 changes: 2 additions & 0 deletions epoxy-modelfactory/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<manifest package="com.airbnb.epoxymodelfactory"
xmlns:android="http://schemas.android.com/apk/res/android" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.airbnb.epoxy;

import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View.OnClickListener;

import com.airbnb.paris.styles.Style;

import java.util.List;

public interface ModelProperties {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can use kotlin for this module


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dedicated getId() method?

@NonNull
String getId();

boolean has(@NonNull String propertyName);

boolean getBoolean(@NonNull String propertyName);

double getDouble(@NonNull String propertyName);

@DrawableRes
int getDrawableRes(@NonNull String propertyName);

@NonNull
List<? extends EpoxyModel<?>> getEpoxyModelList(@NonNull String propertyName);

int getInt(@NonNull String propertyName);

@NonNull
OnClickListener getOnClickListener(@NonNull String propertyName);

@NonNull
String getString(@NonNull String propertyName);

@NonNull
List<String> getStringList(@NonNull String propertyName);

/**
* @return Null to apply the default style.
*/
@Nullable
Style getStyle();
}
3 changes: 3 additions & 0 deletions epoxy-modelfactory/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<resources>
<string name="app_name">Epoxy Model Factory</string>
</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package com.airbnb.epoxy

import android.view.View
import com.airbnb.epoxymodelfactory.R
import com.airbnb.paris.styles.Style
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Test

/**
* Asserts that using from(ModelProperties) to create a model applies the property values correctly
*/
class FromModelPropertiesKotlinTest {

@Test
fun getId() {
val model = TestModelPropertiesKotlinViewModel_.from(TestModelProperties(id = "100"))
assertFalse(model.hasDefaultId())
}

@Test
fun getBoolean() {
val model = TestModelPropertiesKotlinViewModel_.from(TestModelProperties(booleanValue = true))
assertEquals(true, model.booleanValue())
}

@Test
fun getDouble() {
val model = TestModelPropertiesKotlinViewModel_.from(TestModelProperties(doubleValue = 42.0))
assertEquals(42.0, model.doubleValue(), 0.0)
}

@Test
fun getDrawableRes() {
val drawableRes = R.drawable.abc_ic_star_black_48dp
val model =
TestModelPropertiesKotlinViewModel_.from(TestModelProperties(drawableRes = drawableRes))
assertEquals(drawableRes, model.drawableRes())
}

@Test
fun getEpoxyModelList() {
val epoxyModelList = emptyList<EpoxyModel<*>>()
val model =
TestModelPropertiesKotlinViewModel_.from(TestModelProperties(epoxyModelList = epoxyModelList))
assertEquals(epoxyModelList, model.epoxyModelList())
}

@Test
fun getInt() {
val model = TestModelPropertiesKotlinViewModel_.from(TestModelProperties(intValue = 51))
assertEquals(51, model.intValue())
}

@Test
fun getOnClickListener() {
val clickListener = View.OnClickListener { }
val model =
TestModelPropertiesKotlinViewModel_.from(TestModelProperties(onClickListener = clickListener))
assertEquals(clickListener, model.onClickListener())
}

@Test
fun getString() {
val model =
TestModelPropertiesKotlinViewModel_.from(TestModelProperties(stringValue = "ModelFactory"))
assertEquals("ModelFactory", model.stringValue())
}

@Test
fun getStringList() {
val stringList = listOf("Model", "Factory")
val model = TestModelPropertiesKotlinViewModel_.from(TestModelProperties(stringList = stringList))
assertEquals(stringList, model.stringList())
}

class TestModelProperties(
private val id: String = "",
private val booleanValue: Boolean? = null,
private val doubleValue: Double? = null,
private val drawableRes: Int? = null,
private val epoxyModelList: List<EpoxyModel<*>>? = null,
private val intValue: Int? = null,
private val onClickListener: View.OnClickListener? = null,
private val stringValue: String? = null,
private val stringList: List<String>? = null,
private val styleValue: Style? = null
) : ModelProperties {
override fun getId() = id

override fun has(propertyName: String): Boolean {
return mapOf(
"booleanValue" to booleanValue,
"doubleValue" to doubleValue,
"drawableRes" to drawableRes,
"epoxyModelList" to epoxyModelList,
"intValue" to intValue,
"onClickListener" to onClickListener,
"stringList" to stringList,
"stringValue" to stringValue
)[propertyName] != null
}

override fun getBoolean(propertyName: String) = booleanValue!!

override fun getDouble(propertyName: String) = doubleValue!!

override fun getDrawableRes(propertyName: String) = drawableRes!!

override fun getEpoxyModelList(propertyName: String) = epoxyModelList!!

override fun getInt(propertyName: String) = intValue!!

override fun getOnClickListener(propertyName: String) = onClickListener!!

override fun getString(propertyName: String) = stringValue!!

override fun getStringList(propertyName: String) = stringList!!

override fun getStyle() = styleValue
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package com.airbnb.epoxy

import android.view.View
import com.airbnb.epoxymodelfactory.R
import com.airbnb.paris.styles.Style
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Test

/**
* Asserts that using from(ModelProperties) to create a model applies the property values correctly
*/
class FromModelPropertiesTest {

@Test
fun getId() {
val model = TestModelPropertiesViewModel_.from(TestModelProperties(id = "100"))
assertFalse(model.hasDefaultId())
}

@Test
fun getBoolean() {
val model = TestModelPropertiesViewModel_.from(TestModelProperties(booleanValue = true))
assertEquals(true, model.booleanValue())
}

@Test
fun getDouble() {
val model = TestModelPropertiesViewModel_.from(TestModelProperties(doubleValue = 42.0))
assertEquals(42.0, model.doubleValue(), 0.0)
}

@Test
fun getDrawableRes() {
val drawableRes = R.drawable.abc_ic_star_black_48dp
val model =
TestModelPropertiesViewModel_.from(TestModelProperties(drawableRes = drawableRes))
assertEquals(drawableRes, model.drawableRes())
}

@Test
fun getEpoxyModelList() {
val epoxyModelList = emptyList<EpoxyModel<*>>()
val model =
TestModelPropertiesViewModel_.from(TestModelProperties(epoxyModelList = epoxyModelList))
assertEquals(epoxyModelList, model.epoxyModelList())
}

@Test
fun getInt() {
val model = TestModelPropertiesViewModel_.from(TestModelProperties(intValue = 51))
assertEquals(51, model.intValue())
}

@Test
fun getOnClickListener() {
val clickListener = View.OnClickListener { }
val model =
TestModelPropertiesViewModel_.from(TestModelProperties(onClickListener = clickListener))
assertEquals(clickListener, model.onClickListener())
}

@Test
fun getString() {
val model =
TestModelPropertiesViewModel_.from(TestModelProperties(stringValue = "ModelFactory"))
assertEquals("ModelFactory", model.stringValue())
}

@Test
fun getStringList() {
val stringList = listOf("Model", "Factory")
val model = TestModelPropertiesViewModel_.from(TestModelProperties(stringList = stringList))
assertEquals(stringList, model.stringList())
}

class TestModelProperties(
private val id: String = "",
private val booleanValue: Boolean? = null,
private val doubleValue: Double? = null,
private val drawableRes: Int? = null,
private val epoxyModelList: List<EpoxyModel<*>>? = null,
private val intValue: Int? = null,
private val onClickListener: View.OnClickListener? = null,
private val stringValue: String? = null,
private val stringList: List<String>? = null,
private val styleValue: Style? = null
) : ModelProperties {
override fun getId() = id

override fun has(propertyName: String): Boolean {
return mapOf(
"booleanValue" to booleanValue,
"doubleValue" to doubleValue,
"drawableRes" to drawableRes,
"epoxyModelList" to epoxyModelList,
"intValue" to intValue,
"onClickListener" to onClickListener,
"stringList" to stringList,
"stringValue" to stringValue
)[propertyName] != null
}

override fun getBoolean(propertyName: String) = booleanValue!!

override fun getDouble(propertyName: String) = doubleValue!!

override fun getDrawableRes(propertyName: String) = drawableRes!!

override fun getEpoxyModelList(propertyName: String) = epoxyModelList!!

override fun getInt(propertyName: String) = intValue!!

override fun getOnClickListener(propertyName: String) = onClickListener!!

override fun getString(propertyName: String) = stringValue!!

override fun getStringList(propertyName: String) = stringList!!

override fun getStyle() = styleValue
}
}
Loading