Library to simplify and speed up the creation and work with adapters with payload.

Related tags

Testing Novalles
Overview

Novalles

Library to simplify and speed up the creation and work with adapters with payload.

License

How to use

  1. Annotate your UI model with UIModel Annotation.
@UIModel
data class PictureUIModel(
    @PrimaryTag val tag: String,
    val image: Int,
    @Decompose val line: ColorPair,
    @NonUIProperty val imageCode: String,
    val title: String,
    val desc: String,
    val likes: Int
) : BaseUiModel
  • You can use PrimaryTag annotation to define property to be used in are items the same comparison.
  • Use NonUIProperty annotation to define property that will not be used in any comparisons.
  • Use Decompose annotation to tell Novalles compare each property of decomposed value separately. See Decompose section for more details.
  1. Pass an instance of UIModelHelper in your DiffUtil using provideUiInterfaceFor or provideUiInterfaceForAs functions.
private val uiModelHelper: UIModelHelper<BaseUiModel> = Novalles.provideUiInterfaceForAs(PictureUIModel::class)
  1. Call relevant functions of UIModelHelper in your DiffUtil. This example uses diffUtil based on common interface.
class DefaultDiffUtil<T : BaseUiModel>(uiModel: KClass<T>) : DiffUtil.ItemCallback<BaseUiModel>() {

    private val uiModelHelper: UIModelHelper<BaseUiModel> = Novalles.provideUiInterfaceForAs(uiModel)

    override fun areItemsTheSame(oldItem: BaseUiModel, newItem: BaseUiModel): Boolean {
        return oldItem.areItemsTheSame(newItem, uiModelHelper)
    }

    override fun areContentsTheSame(oldItem: BaseUiModel, newItem: BaseUiModel): Boolean {
        return oldItem.areContentTheSame(newItem, uiModelHelper)
    }

    override fun getChangePayload(oldItem: BaseUiModel, newItem: BaseUiModel): Any {
        return oldItem.changePayload(newItem, uiModelHelper)
    }
}
  1. Create a class, that extends Instructor interface. Annotate it with Instruction annotation, pass your UI Model class as the annotation argument. You can also annotate it with AutoBindViewHolder (See corresponding section for more details). In this class you should create functions, that will be called on a value change. Use BindOn annotation to tell Novalles which function should be called when a value has been changed, value name should be passed as the first annotation argument.
@Instruction(PictureUIModel::class)
@AutoBindViewHolder(PictureViewHolder::class)
inner class PictureInstructor(
    private val viewHolder: PictureViewHolder,
    private val uiModel: PictureUIModel
) : Instructor {

    //This function will be called, when title changed.
    @BindOn("title")
    fun setTitleComplex(title: String) {
        val realDesc = "<b>$title</b> (${uiModel.tag})"
        viewHolder.setTitle(realDesc)
    }

}

If you completely rely on AutoBindViewHolder, you should create the simplest Instructor for your UI Model.

@Instruction(PictureUIModel::class)
@AutoBindViewHolder(PictureViewHolder::class)
inner class AutoInstructor : Instructor
  1. Create an instance of the Inspector class using Novalles.provideInspectorFromInstructor(instructor: Instructor) function. Better to create it outside any function, create it directly in the adapter itself.
private val inspector = Novalles.provideInspectorFromInstructor(PictureInstructor::class)
  1. Invoke Inspector.inspectPayloads with 4 arguments: your payload, instructor, your viewHolder and lambda for action when payload is empty. This function calls corresponding functions in your viewHolder and instructor based on gathered payload.
override fun onBindViewHolder(
    holder: PictureViewHolder,
    position: Int,
    payloads: MutableList<Any>
) {
    val model = currentList[position] as PictureUIModel
    val instructor = PictureInstructor(
        viewHolder = holder,
        model
    )
    inspector.inspectPayloads(payloads, instructor, viewHolder = holder) {
        holder.bind(model)
        holder.setOnClickActions(model, onClick)
    }
}

AutoBindViewHolder

Class annotated with it is considered to be the instruction how to handle payloads for UI Model. It should also implement Instructor interface. Your functions should be names as set{PropertyName}.

@UIModel
data class PictureUIModel(
    @PrimaryTag val tag: String,
    //...
    val desc: String,
    //...
) : BaseUiModel {

//...


    inner class PictureViewHolder(private val binding: ItemPictureBinding) : ViewHolder(binding.root) {

        //...

        //This function will be called, if desc changes.
        fun setDesc(desc: String) {
            binding.desc.text = desc
        }

        //...
    }
}

Decompose annotations

Value, annotated with Decompose will be decomposed with its own values. For example, if your field have 2 properties, they will be used in any Novalles' actions separately: Novalles will generate 2 different payloads objects in UIModelHelper.changePayloads, compare them in UIModelHelper.areContentsTheSame separately.

Also, if you use AutoBindViewHolder, you should use set${FieldName}In${DecomposedFieldName}() functions in your viewHolder for each field of your decomposed value.

data class ColorPair(
    val left: Int,
    val right: Int
)

@UIModel
data class PictureUIModel(
    @PrimaryTag val tag: String,
    //...
    @Decompose val line: ColorPair,
    //...
) : BaseUiModel {

//...

    inner class PictureViewHolder(private val binding: ItemPictureBinding) : ViewHolder(binding.root) {

        //...

        //This function will be called, if left in line value changes.
        fun setLeftInLine(color: Int) {
            binding.colour.animateColors(color)
        }

        //This function will be called, if right in line value changes.
        fun setRightInLine(color: Int) {
            binding.colourSecond.animateColors(color)
        }

        //...
    }
}

Conclusions and usage

  • To maximize benefit of the Novalles, you can animate your views inside your set functions in a viewHolder.
fun setImage(image: Int) {
    binding.image.animateColors(image)
}
  • Do not create any Novalles instances in functions, better to create an instance of UiModelHelper in your DiffUtil and an instance of Inspector in your adapter.
  • Novalles does not use android components directly, so it does not have any SDK restrictions. This can be changed in the future, because Novalles uses Any instead of ViewHolder in its interfaces. This may lead to misunderstandings of functions usage.
  • Novalles does not require any proguard rules and should work normally in release builds if your Ui Models and adapters work normally.
  • Decompose annotation should be used careful, because it is very lightly tested.
  • Please, report any issues you've encountered. Novalles is still in development, so your feedback is very helpful.

How to integrate in your project

  1. Add KSP dependencies in your top level gradle file.
buildscript {
    dependencies {
        classpath("com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:1.6.21-1.0.5")
    }
}
  1. Add KSP plugin in your app level gradle file.
plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    //...
    id 'com.google.devtools.ksp'
}
  1. Import the Novalles library as dependency.
allprojects {
    repositories {
        //...
        maven { url 'https://jitpack.io' }
    }
}
//...

dependencies {
    //...
    implementation 'com.github.flexeiprata:novalles:0.4.0'
    ksp 'com.github.flexeiprata:novalles:0.4.0'
    //...
}

License

Copyright (C) 2022 FlexeiPrata.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
You might also like...
An experimental library for dealing with legacy code

All Super experimental! no guarantees to the public API surface. At the moment, this project is the outcome of the limitations of my search skills. Bu

Selenium WebDriver and Appium based Web, Mobile (Android, iOS) and Windows desktop Automation Framework with BDD & Non-BDD implementation support

Selenium WebDriver and Appium based Web, Mobile (Android, iOS) and Windows desktop Automation Framework with BDD & Non-BDD implementation support

Powerful, elegant and flexible test framework for Kotlin with additional assertions, property testing and data driven testing
Powerful, elegant and flexible test framework for Kotlin with additional assertions, property testing and data driven testing

Kotest is a flexible and comprehensive testing tool for Kotlin with multiplatform support. To learn more about Kotest, visit kotest.io or see our quic

A tool for scan and replace file content. Instead of global search and replace, it can specify replace scope

ScanReplace.kt A tool for scan and replace file content Instead of global search and replace, it can specify replace scope Usage java -jar ScanReplace

A collection of tests and easy to reuse pieces of code for bdk-jvm and bdk-android

Readme This repo is a collection of tests and easy to reuse pieces of code for bdk-jvm and bdk-android. Note that they don't aim to provide a full cov

Control and manage Android devices from your browser.
Control and manage Android devices from your browser.

Warning This project along with other ones in OpenSTF organisation is provided as is for community, without active development. You can check any othe

TestObserver to easily test LiveData and make assertions on them.
TestObserver to easily test LiveData and make assertions on them.

JCenter Update LiveData Testing is currently published on JCenter - it will serve packages until February 1st, 2022. LiveData Testing packages will be

An ActivityScenario extension and a Junit4 TestRule to simulate changing the font size on a device/emulator, as it would be done by going to Settings display Font size

FontSizeActivityScenario and FontSizeTestRule An ActivityScenario and a Junit4 TestRule to be used together with its org.junit.runners.Parameterized.

Releases(0.8.0)
  • 0.8.0(Jan 2, 2023)

    Added

    • The Bind function in the inspector interface. This function calls all bound to fileds functions in a viewholder or an inspector.

    Changed

    • The provideInspectorFromUiModel function is now uses type argument instead of a class one.
    • Code generation optimisations

    Fixed

    • Docs errors
    Source code(tar.gz)
    Source code(zip)
  • 0.7.0(Dec 17, 2022)

    Added:

    • BindOnFields annotation (you can now bind more than 1 fields in the instructor)
    • BindViewHolder annotation (you can now configure prefix and postfix of viewHolder functions)

    Changed:

    • AutoBindViewHolder is now deprecated and should be replaced with BindViewHolder.
    • BindViewHolder (or AutoBindViewHolder) annotation is now obligatory for any Instructor
    • Functions annotated with BindOn preferably should have no arguments. You can get any necessary values from your Inspector instanse.

    Fixed:

    • You can now create UIModels without any UI fields.
    Source code(tar.gz)
    Source code(zip)
  • 0.6.0(Aug 31, 2022)

    • Type Arguments support (f.e. Pair<Int, Int>).
    • Inspector provider changes. Now it is recommended to create it via provideInspectorFromUiModel.
    Source code(tar.gz)
    Source code(zip)
  • 0.5.0(Aug 14, 2022)

  • 0.4.0(Jul 24, 2022)

    • Updated inspectPayloads from Inspector
      • Now Any? is passed instead of List
      • Novalles now extract payload got from onBindViewHolder by itself
    • Updated ReadMe and example
    Source code(tar.gz)
    Source code(zip)
  • 0.3.0(Jul 17, 2022)

Owner
Бырна Алексей
Бырна Алексей
Selenium locators for Java/Kotlin that resemble the Testing Library (testing-library.com).

Selenium Testing Library Testing Library selectors available as Selenium locators for Kotlin/Java. Why? When I use Selenium, I don't want to depend on

Luís Soares 5 Dec 15, 2022
Android library that allows you to run your acceptance tests written in Gherkin in your Android instrumentation tests.

Green Coffee Green Coffee is a library that allows you to run your acceptance tests written in Gherkin in your Android instrumentation tests using the

Mauricio Togneri 227 Nov 21, 2022
A multiplatform assertion library for Kotlin

Atrium is an open-source multiplatform assertion library for Kotlin with support for JVM, JS and Android. It is designed to support multiple APIs, dif

Robert Stoll 439 Dec 29, 2022
mocking library for Kotlin

Kotlin Academy articles Check the series of articles "Mocking is not rocket science" at Kt. Academy describing MockK from the very basics of mocking u

MockK 4.8k Jan 3, 2023
Linkester is an Android library that aims to help Android developers test their deep links implementation.

Linkester Linkester is an Android library that aims to help Android developers test their deep links implementation. The idea is to have a new launche

Ahmad Melegy 79 Dec 9, 2022
Jitpack Library Tester

jitpack-library-test Repository for testing build from jitpack.io Red : Failed Green : Success / Pass Colaborator Very open to anyone, I'll write your

Faisal Amir 7 Dec 10, 2022
Strikt is an assertion library for Kotlin intended for use with a test runner such as JUnit, Minutest, Spek, or KotlinTest.

Strikt is an assertion library for Kotlin intended for use with a test runner such as JUnit, Minutest, Spek, or KotlinTest.

Rob Fletcher 447 Dec 26, 2022
Turbine is a small testing library for kotlinx.coroutines Flow.

A small testing library for kotlinx.coroutines Flow

Cash App 1.8k Jan 5, 2023
A Kotlin Android library for heuristics evasion that prevents your code from being tested.

EvadeMe An Android library for heuristics evasion that prevents your code from being tested. User Instructions Add the maven repository to your projec

Chris Basinger 29 Dec 26, 2022
A library that makes it easier to write high quality automated acceptance tests

Getting started with Serenity and Cucumber Serenity BDD is a library that makes it easier to write high quality automated acceptance tests, with power

ricardo larrahondo 1 Oct 20, 2021