Add tests for the introduced fixes
Add a test for applying kotlin-android plugin with com.android.feature Add a test for Databinding (not passing yet with 3.0.0+, until 3.0.0-alpha4 is released, which contains the fix from the Android side). Add missing test project android-databinding. Refactor and improve the tests * Remove redundant files from test project 'android-databinding' * Refactoring and minor improvements in the tests
This commit is contained in:
+28
-2
@@ -8,13 +8,39 @@ import java.io.File
|
||||
|
||||
|
||||
class KotlinAndroidGradleIT : AbstractKotlinAndroidGradleTests(gradleVersion = "3.3", androidGradlePluginVersion = "2.3.0")
|
||||
class KotlinAndroid30GradleIT : AbstractKotlinAndroidGradleTests(gradleVersion = "4.0-rc-1", androidGradlePluginVersion = "3.0.0-alpha2")
|
||||
class KotlinAndroidWithJackGradleIT : AbstractKotlinAndroidWithJackGradleTests(gradleVersion = "3.3", androidGradlePluginVersion = "2.3.+")
|
||||
|
||||
class KotlinAndroid30GradleIT : AbstractKotlinAndroidGradleTests(gradleVersion = "4.0-rc-1", androidGradlePluginVersion = "3.0.0-alpha2") {
|
||||
|
||||
@Test
|
||||
fun testApplyWithFeaturePlugin() {
|
||||
val project = Project("AndroidProject", gradleVersion)
|
||||
|
||||
project.setupWorkingDir()
|
||||
File(project.projectDir, "Lib/build.gradle").modify { text ->
|
||||
// Change the applied plugin to com.android.feature
|
||||
text.replace("com.android.library", "com.android.feature").apply { assert(!equals(text)) }
|
||||
}
|
||||
|
||||
// Check that Kotlin tasks were created for both lib and feature variants:
|
||||
val kotlinTaskNames =
|
||||
listOf("Debug", "Release").flatMap { buildType ->
|
||||
listOf("Flavor1", "Flavor2").flatMap { flavor ->
|
||||
listOf("", "Feature").map { isFeature -> ":Lib:compile$flavor$buildType${isFeature}Kotlin" }
|
||||
}
|
||||
}
|
||||
|
||||
project.build(":Lib:assemble") {
|
||||
assertSuccessful()
|
||||
assertContains(*kotlinTaskNames.toTypedArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const val ANDROID_HOME_PATH = "../../../dependencies/androidSDK"
|
||||
|
||||
abstract class AbstractKotlinAndroidGradleTests(
|
||||
private val gradleVersion: String,
|
||||
protected val gradleVersion: String,
|
||||
private val androidGradlePluginVersion: String
|
||||
) : BaseGradleIT() {
|
||||
|
||||
|
||||
+14
-1
@@ -6,7 +6,7 @@ import java.io.File
|
||||
|
||||
class Kapt3Android30IT : Kapt3AndroidIT() {
|
||||
override val androidGradlePluginVersion: String
|
||||
get() = "3.0.0-alpha1"
|
||||
get() = "3.0.0-alpha3"
|
||||
}
|
||||
|
||||
open class Kapt3AndroidIT : Kapt3BaseIT() {
|
||||
@@ -106,4 +106,17 @@ open class Kapt3AndroidIT : Kapt3BaseIT() {
|
||||
assertFileExists("build/generated/source/kapt/release/io/realm/DefaultRealmModuleMediator.java")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
open fun testDatabinding() {
|
||||
val project = Project("android-databinding", GRADLE_VERSION, directoryPrefix = "kapt2")
|
||||
val options = androidBuildOptions()
|
||||
|
||||
project.build("compileReleaseSources", options = options) {
|
||||
assertSuccessful()
|
||||
assertKaptSuccessful()
|
||||
assertFileExists("app/build/generated/source/kapt/release/com/example/databinding/BR.java")
|
||||
assertFileExists("app/build/generated/source/kapt/release/com/example/databinding/databinding/ActivityTestBinding.java")
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
android {
|
||||
compileSdkVersion 24
|
||||
buildToolsVersion "25.0.2"
|
||||
defaultConfig {
|
||||
applicationId "com.example.databinding"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 24
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
dataBinding {
|
||||
enabled = true
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { url 'https://maven.google.com' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
kapt "com.android.databinding:compiler:$android_tools_version"
|
||||
compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||
testCompile 'junit:junit:4.12'
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.databinding">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name=".MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
package com.example.databinding
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.databinding.*
|
||||
import android.databinding.adapters.AdapterViewBindingAdapter
|
||||
import android.support.annotation.IntegerRes
|
||||
import android.util.Log
|
||||
import android.view.*
|
||||
import android.widget.*
|
||||
|
||||
|
||||
interface Displayable {
|
||||
fun displayString(res: Resources): String
|
||||
}
|
||||
|
||||
|
||||
@InverseBindingMethods(
|
||||
InverseBindingMethod(type = Spinner::class, attribute = "selectionEnum", method = "getSelectedItem", event = "app:selectionAttrChanged")
|
||||
)
|
||||
open class EnumAdapter<DispEnum>(val context: Context,
|
||||
enumClass: Class<DispEnum>,
|
||||
@IntegerRes var resource: Int = android.R.layout.simple_spinner_item,
|
||||
@IntegerRes var dropDownResource: Int = android.R.layout.simple_spinner_dropdown_item,
|
||||
val isOptional: Boolean = false) :
|
||||
BaseAdapter() where DispEnum : Displayable, DispEnum : Enum<DispEnum>
|
||||
{
|
||||
val inflater: LayoutInflater = LayoutInflater.from(context)
|
||||
val konstants: Array<DispEnum> = enumClass.enumConstants
|
||||
|
||||
override fun getItem(position: Int): DispEnum? {
|
||||
if (isOptional) {
|
||||
return if (position == 0) null else konstants[position - 1]
|
||||
}
|
||||
return konstants[position]
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long = position + 0L
|
||||
|
||||
override fun getCount(): Int = konstants.size + if (isOptional) 1 else 0
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
return createViewFromResource(position, convertView, parent, resource)
|
||||
}
|
||||
|
||||
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
return createViewFromResource(position, convertView, parent, dropDownResource)
|
||||
}
|
||||
|
||||
private fun createViewFromResource(position: Int, convertView: View?, parent: ViewGroup, resource: Int): View {
|
||||
val view = convertView ?: inflater.inflate(resource, parent, false)
|
||||
val textView: TextView
|
||||
try {
|
||||
textView = view as TextView
|
||||
} catch (e: ClassCastException) {
|
||||
Log.e("EnumAdapter", "You must supply a resource ID for a TextView")
|
||||
return view
|
||||
}
|
||||
|
||||
val enum = getItem(position)
|
||||
textView.text = enum?.displayString(context.resources) ?: "-----"
|
||||
return view
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic fun optionalPosition(e: Enum<*>?): Int {
|
||||
e?.let { return it.ordinal + 1}
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("app:selectionEnum", "app:selectionChanged", "app:selectionAttrChanged", requireAll = false)
|
||||
fun bindSpinnerEnum(spinner: Spinner, newValue: Enum<*>?,
|
||||
itemSelectedListener: AdapterViewBindingAdapter.OnItemSelected?,
|
||||
changeListener: InverseBindingListener?) {
|
||||
val spinnerAdapter = spinner.adapter
|
||||
if (spinnerAdapter !is EnumAdapter<*>) {
|
||||
throw UnsupportedOperationException("app:selectionEnum attribute on Spinner requires EnumAdapter")
|
||||
}
|
||||
if (changeListener == null && itemSelectedListener == null)
|
||||
spinner.onItemSelectedListener = null
|
||||
else
|
||||
spinner.onItemSelectedListener = AdapterViewBindingAdapter.OnItemSelectedComponentListener(itemSelectedListener, nothingingSelectedListener, changeListener)
|
||||
|
||||
val isOptional = spinnerAdapter.isOptional
|
||||
if (!isOptional && newValue == null) {
|
||||
throw IllegalStateException("Can't set a null value for app:selectionEnum, adapter.isOptional is false")
|
||||
}
|
||||
if (spinner.selectedItem != newValue) {
|
||||
val sel = if (isOptional) EnumAdapter.optionalPosition(newValue) else newValue!!.ordinal
|
||||
spinner.setSelection(sel)
|
||||
}
|
||||
}
|
||||
|
||||
val nothingingSelectedListener = object : AdapterViewBindingAdapter.OnNothingSelected {
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.example.databinding
|
||||
|
||||
import android.app.Activity
|
||||
import android.databinding.DataBindingUtil
|
||||
import android.os.Bundle
|
||||
import android.view.MotionEvent
|
||||
import android.widget.Toast
|
||||
import com.example.databinding.databinding.ActivityTestBinding
|
||||
|
||||
class MainActivity : Activity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val binding: ActivityTestBinding = DataBindingUtil.setContentView(this, R.layout.activity_test)
|
||||
val uprof = UserProfile()
|
||||
binding.userProfile = uprof
|
||||
binding.context = this
|
||||
binding.genderPicker.adapter = EnumAdapter(this, Gender::class.java)
|
||||
binding.genderPicker.setOnTouchListener { v, event ->
|
||||
if (event.actionMasked == MotionEvent.ACTION_DOWN)
|
||||
spinnerClicked = true
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
var spinnerClicked = false
|
||||
fun spinnerClicked() {
|
||||
spinnerClicked = true
|
||||
}
|
||||
fun selectionChanged() {
|
||||
if (spinnerClicked)
|
||||
Toast.makeText(this, "sdds", Toast.LENGTH_LONG).show()
|
||||
spinnerClicked = false
|
||||
}
|
||||
|
||||
fun clickHandler(uprof: UserProfile): Boolean = true
|
||||
|
||||
fun longClickHandler(uprof: UserProfile): Boolean = true
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.example.databinding
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.databinding.BaseObservable
|
||||
|
||||
class UserProfile : BaseObservable() {
|
||||
open var gender: Gender = Gender.Female
|
||||
}
|
||||
|
||||
enum class Gender(val display: String): Displayable {
|
||||
Male("male"), Female("female");
|
||||
override fun displayString(res: Resources): String = display
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<data>
|
||||
<variable name="userProfile" type="com.example.databinding.UserProfile" />
|
||||
<variable name="context" type="com.example.databinding.MainActivity" />
|
||||
</data>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent" android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:onClick="@{() -> context.clickHandler(userProfile)}"
|
||||
android:onLongClick="@{() -> context.longClickHandler(userProfile)}"
|
||||
>
|
||||
<Spinner
|
||||
android:id="@+id/genderPicker"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:selectionEnum="@={userProfile.gender}"
|
||||
app:selectionChanged="@{(p, v, pos, id) -> context.selectionChanged()}"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
</layout>
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">ActivityRideUpTest</string>
|
||||
</resources>
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
<style name="EditProfileRow">
|
||||
<item name="android:layout_marginBottom">18dp</item>
|
||||
<item name="android:layout_column">0</item>
|
||||
</style>
|
||||
|
||||
<style name="EditProfileRowColumn" parent="EditProfileRow">
|
||||
<item name="android:layout_marginEnd">5dp</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenLocal()
|
||||
maven { url 'https://maven.google.com' }
|
||||
}
|
||||
dependencies {
|
||||
classpath "com.android.tools.build:gradle:$android_tools_version"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenLocal()
|
||||
maven { url 'https://maven.google.com' }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user