api-generator tests & boolean_int representation tests

boolean_int tests

api-generator-tests
This commit is contained in:
timatifey
2022-09-12 17:14:14 +03:00
parent 5bbbba2dcf
commit d4390912ae
43 changed files with 2065 additions and 27 deletions
+4
View File
@@ -1 +1,5 @@
/tests/output/
config_hash
generator_hash
input_hash
output_hash
+4
View File
@@ -1 +1,5 @@
/tests/output/
config_hash
generator_hash
input_hash
output_hash
+9 -8
View File
@@ -31,7 +31,7 @@ def __build_generator(config: Config) -> Generator:
return generator(config)
def generate_api(config: Config):
def generate_api(config: Config, save_hash_files: bool = True):
root_directory = schema_preprocessing(config)
objects = build_objects(root_directory, config.generation)
@@ -49,11 +49,12 @@ def generate_api(config: Config):
generator.generate(objects)
def save_hash_file(filename: str, hash: str):
with open(os.path.join(config.output_path, filename), 'w') as f:
f.write(hash)
if save_hash_files:
def save_hash_file(filename: str, hash: str):
with open(os.path.join(config.output_path, filename), 'w') as f:
f.write(hash)
save_hash_file('input_hash', root_directory.hash)
save_hash_file('output_hash', expected_output_hash)
save_hash_file('generator_hash', config.generator_hash)
save_hash_file('config_hash', config.config_hash)
save_hash_file('input_hash', root_directory.hash)
save_hash_file('output_hash', expected_output_hash)
save_hash_file('generator_hash', config.generator_hash)
save_hash_file('config_hash', config.config_hash)
@@ -676,7 +676,7 @@ class KotlinPropertyType(PropertyType):
elif isinstance(self, Color):
return 'STRING_TO_COLOR_INT'
elif isinstance(self, (Bool, BoolInt)):
return 'NUMBER_TO_BOOLEAN'
return 'ANY_TO_BOOLEAN'
elif isinstance(self, Object) and isinstance(self.object, StringEnumeration):
if string_enum_prefixed:
typename = self.object.resolved_prefixed_declaration
@@ -719,9 +719,7 @@ class KotlinPropertyType(PropertyType):
def serialization_transform(self, string_enum_prefixed: bool) -> str:
prefix = ', converter = '
if isinstance(self, (Bool, BoolInt)):
return f'{prefix}BOOLEAN_TO_INT'
elif isinstance(self, String):
if isinstance(self, String):
return f'{prefix}SPANNED_TO_HTML' if self.formatted else ''
elif isinstance(self, Url):
return f'{prefix}URI_TO_STRING'
@@ -30,8 +30,8 @@ class EntityWithSimpleProperties(
override fun writeToJSON(): JSONObject {
val json = JSONObject()
json.writeExpression(key = "boolean", value = boolean, converter = BOOLEAN_TO_INT)
json.writeExpression(key = "boolean_int", value = booleanInt, converter = BOOLEAN_TO_INT)
json.writeExpression(key = "boolean", value = boolean)
json.writeExpression(key = "boolean_int", value = booleanInt)
json.writeExpression(key = "color", value = color, converter = COLOR_INT_TO_STRING)
json.writeExpression(key = "double", value = double)
json.write(key = "id", value = id)
@@ -51,8 +51,8 @@ class EntityWithSimpleProperties(
operator fun invoke(env: ParsingEnvironment, json: JSONObject): EntityWithSimpleProperties {
val logger = env.logger
return EntityWithSimpleProperties(
boolean = JsonParser.readOptionalExpression(json, "boolean", NUMBER_TO_BOOLEAN, logger, env, TYPE_HELPER_BOOLEAN),
booleanInt = JsonParser.readOptionalExpression(json, "boolean_int", NUMBER_TO_BOOLEAN, logger, env, TYPE_HELPER_BOOLEAN),
boolean = JsonParser.readOptionalExpression(json, "boolean", ANY_TO_BOOLEAN, logger, env, TYPE_HELPER_BOOLEAN),
booleanInt = JsonParser.readOptionalExpression(json, "boolean_int", ANY_TO_BOOLEAN, logger, env, TYPE_HELPER_BOOLEAN),
color = JsonParser.readOptionalExpression(json, "color", STRING_TO_COLOR_INT, logger, env, TYPE_HELPER_COLOR),
double = JsonParser.readOptionalExpression(json, "double", NUMBER_TO_DOUBLE, logger, env, TYPE_HELPER_DOUBLE),
id = JsonParser.readOptional(json, "id", NUMBER_TO_INT, logger, env),
@@ -34,8 +34,8 @@ class EntityWithSimplePropertiesTemplate : JSONSerializable, JsonTemplate<Entity
json: JSONObject
) {
val logger = env.logger
boolean = JsonTemplateParser.readOptionalFieldWithExpression(json, "boolean", topLevel, parent?.boolean, NUMBER_TO_BOOLEAN, logger, env, TYPE_HELPER_BOOLEAN)
booleanInt = JsonTemplateParser.readOptionalFieldWithExpression(json, "boolean_int", topLevel, parent?.booleanInt, NUMBER_TO_BOOLEAN, logger, env, TYPE_HELPER_BOOLEAN)
boolean = JsonTemplateParser.readOptionalFieldWithExpression(json, "boolean", topLevel, parent?.boolean, ANY_TO_BOOLEAN, logger, env, TYPE_HELPER_BOOLEAN)
booleanInt = JsonTemplateParser.readOptionalFieldWithExpression(json, "boolean_int", topLevel, parent?.booleanInt, ANY_TO_BOOLEAN, logger, env, TYPE_HELPER_BOOLEAN)
color = JsonTemplateParser.readOptionalFieldWithExpression(json, "color", topLevel, parent?.color, STRING_TO_COLOR_INT, logger, env, TYPE_HELPER_COLOR)
double = JsonTemplateParser.readOptionalFieldWithExpression(json, "double", topLevel, parent?.double, NUMBER_TO_DOUBLE, logger, env, TYPE_HELPER_DOUBLE)
id = JsonTemplateParser.readOptionalField(json, "id", topLevel, parent?.id, NUMBER_TO_INT, logger, env)
@@ -61,8 +61,8 @@ class EntityWithSimplePropertiesTemplate : JSONSerializable, JsonTemplate<Entity
override fun writeToJSON(): JSONObject {
val json = JSONObject()
json.writeFieldWithExpression(key = "boolean", field = boolean, converter = BOOLEAN_TO_INT)
json.writeFieldWithExpression(key = "boolean_int", field = booleanInt, converter = BOOLEAN_TO_INT)
json.writeFieldWithExpression(key = "boolean", field = boolean)
json.writeFieldWithExpression(key = "boolean_int", field = booleanInt)
json.writeFieldWithExpression(key = "color", field = color, converter = COLOR_INT_TO_STRING)
json.writeFieldWithExpression(key = "double", field = double)
json.writeField(key = "id", field = id)
@@ -82,8 +82,8 @@ class EntityWithSimplePropertiesTemplate : JSONSerializable, JsonTemplate<Entity
private val STRING_TEMPLATE_VALIDATOR = ValueValidator<String> { it: String -> it.length >= 1 }
private val STRING_VALIDATOR = ValueValidator<String> { it: String -> it.length >= 1 }
val BOOLEAN_READER: Reader<Expression<Boolean>?> = { key, json, env -> JsonParser.readOptionalExpression(json, key, NUMBER_TO_BOOLEAN, env.logger, env, TYPE_HELPER_BOOLEAN) }
val BOOLEAN_INT_READER: Reader<Expression<Boolean>?> = { key, json, env -> JsonParser.readOptionalExpression(json, key, NUMBER_TO_BOOLEAN, env.logger, env, TYPE_HELPER_BOOLEAN) }
val BOOLEAN_READER: Reader<Expression<Boolean>?> = { key, json, env -> JsonParser.readOptionalExpression(json, key, ANY_TO_BOOLEAN, env.logger, env, TYPE_HELPER_BOOLEAN) }
val BOOLEAN_INT_READER: Reader<Expression<Boolean>?> = { key, json, env -> JsonParser.readOptionalExpression(json, key, ANY_TO_BOOLEAN, env.logger, env, TYPE_HELPER_BOOLEAN) }
val COLOR_READER: Reader<Expression<Int>?> = { key, json, env -> JsonParser.readOptionalExpression(json, key, STRING_TO_COLOR_INT, env.logger, env, TYPE_HELPER_COLOR) }
val DOUBLE_READER: Reader<Expression<Double>?> = { key, json, env -> JsonParser.readOptionalExpression(json, key, NUMBER_TO_DOUBLE, env.logger, env, TYPE_HELPER_DOUBLE) }
val ID_READER: Reader<Int?> = { key, json, env -> JsonParser.readOptional(json, key, NUMBER_TO_INT, env.logger, env) }
+1 -1
View File
@@ -89,7 +89,7 @@ def assert_test_generator(config_filename: str, schema_path: str, references_fol
output_path=OUTPUT_PATH)
if not os.path.exists(OUTPUT_PATH):
os.makedirs(OUTPUT_PATH)
generate_api(config)
generate_api(config, save_hash_files=False)
references_path = utils.path_generator_tests(os.path.join('references', references_folder_name))
if SHOULD_UPDATE_REFERENCES:
@@ -0,0 +1,93 @@
import com.android.build.gradle.internal.tasks.factory.dependsOn
plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android")
}
val generatedSrcDir = File(buildDir, "generated/source/generator")
val projectDir = project.projectDir
val divKitPublicDir = "${projectDir}/../../.."
val testDataPath = "${divKitPublicDir}/test_data"
apply(from = "${projectDir}/../div-library.gradle")
apply(from = "${projectDir}/../div-tests.gradle")
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjvm-default=all")
languageVersion = "1.6"
apiVersion = "1.6"
}
}
android {
buildFeatures { buildConfig = true }
sourceSets.getByName("main") {
java.srcDir(generatedSrcDir)
}
buildToolsVersion = rootProject.ext["buildToolsVersion"] as String
compileSdk = rootProject.ext["compileSdkVersion"] as Int
defaultConfig {
minSdk = rootProject.ext["minSdkVersion"] as Int
targetSdk = rootProject.ext["targetSdkVersion"] as Int
buildConfigField("String", "TEMPLATES_JSON_PATH", "\"$testDataPath\"")
}
project.tasks.preBuild.dependsOn("generateHomePojoTask")
testOptions {
unitTests {
all {
it.jvmArgs = listOf("-noverify")
it.testLogging {
events("passed", "skipped", "failed", "standardOut", "standardError")
}
}
isIncludeAndroidResources = true
}
}
}
dependencies {
implementation(project(":assertion"))
implementation(project(":div-core"))
implementation(project(":div-json"))
}
val schemes = listOf(
mapOf(
"name" to "testing",
"scheme" to File(testDataPath, "test_schema"),
"generated" to "${generatedSrcDir.absolutePath}/com/yandex/testing",
"config" to File(projectDir, "testing-generator-config.json")
)
)
schemes.forEach { item ->
tasks.register<Exec>("scheme_${item["name"]}") {
val schemesDirectory = (item["scheme"] as File).absolutePath
val generatedDir = item["generated"] as String
val configPath = (item["config"] as File).absolutePath
val binPath = File(divKitPublicDir, "api_generator/api_generator.sh").absolutePath
commandLine = listOf(binPath, configPath, schemesDirectory, generatedDir)
println("Process schemes: $schemesDirectory")
println(commandLine.joinToString(" "))
inputs.dir(item["scheme"]!!)
inputs.file(item["config"]!!)
outputs.dir(generatedDir)
}
}
tasks.register("generateHomePojoTask") {
dependsOn(provider {
tasks.filter { task -> task.name.startsWith("scheme_") }
})
}
@@ -0,0 +1,18 @@
###########################
# Android support classes #
###########################
android/support/design/**
android/support/v7/**
android/support/constraint/**
###########################
# Dagger
###########################
#####################
# Generated classes #
#####################
**/R.class
**/R$*.class
**/BuildConfig.*
**/Manifest*.*
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
</lint>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.yandex.generator">
</manifest>
@@ -0,0 +1,86 @@
package com.yandex.generator
import com.yandex.div.json.ParsingException
import com.yandex.generator.ENTITY_WITH_ARRAY_OF_NESTED_ITEMS
import com.yandex.generator.EntityTemplateTestCase
import com.yandex.testing.Entity
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class ArrayOfNestedItemsTest {
private val case = EntityTemplateTestCase(
ctor = Entity.Companion::invoke
)
@Test
fun `array of nested items is parsed correctly`() {
val actual = case.parse(
directory = "array_of_nested_items",
filename = "test_array_of_nested_items_without_templates.json"
)
Assert.assertEquals(ENTITY_WITH_ARRAY_OF_NESTED_ITEMS, actual)
}
@Test
fun `array of nested item templates is parsed correctly`() {
val actual = case.parse(
directory = "array_of_nested_items",
filename = "test_array_of_nested_items_with_item_template.json"
)
Assert.assertEquals(ENTITY_WITH_ARRAY_OF_NESTED_ITEMS, actual)
}
@Test
fun `referenced array of nested items is parsed correctly`() {
val actual = case.parse(
directory = "array_of_nested_items",
filename = "test_array_of_nested_items_with_link_for_items.json"
)
Assert.assertEquals(ENTITY_WITH_ARRAY_OF_NESTED_ITEMS, actual)
}
@Test
fun `referenced array of nested item templates is parsed correctly`() {
val actual = case.parse(
directory = "array_of_nested_items",
filename = "test_array_of_nested_items_with_link_for_items_with_item_template.json"
)
Assert.assertEquals(ENTITY_WITH_ARRAY_OF_NESTED_ITEMS, actual)
}
@Test(expected = ParsingException::class)
fun `when data for nested item property references is missing parsing fails`() {
case.parse(
directory = "array_of_nested_items",
filename = "test_array_of_nested_items_with_item_template_without_data.json"
)
}
@Test(expected = ParsingException::class)
fun `when required property of nested item is missing parsing fails`() {
case.parse(
directory = "array_of_nested_items",
filename = "test_array_of_nested_items_without_item_required_property.json"
)
}
@Test(expected = ParsingException::class)
fun `when required property of nested item template is missing parsing fails`() {
case.parse(
directory = "array_of_nested_items",
filename = "test_array_of_nested_items_with_item_template_without_item_required_property.json"
)
}
@Test(expected = ParsingException::class)
fun `when referenced array contains nested items without required property parsing fails`() {
case.parse(
directory = "array_of_nested_items",
filename = "test_array_of_nested_items_with_link_for_items_without_item_required_property.json"
)
}
}
@@ -0,0 +1,156 @@
package com.yandex.generator
import com.yandex.div.json.ParsingException
import com.yandex.testing.Entity
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class ArrayTest {
private val case = EntityTemplateTestCase(
ctor = Entity.Companion::invoke
)
@Test
fun `when array is defined by link it is parsed correctly`() {
val actual = case.parse(
directory = "array",
filename = "test_array_with_link.json"
)
assertEquals(ENTITY_WITH_ARRAY, actual)
}
@Test
fun `when array does not contain link it is parsed correctly`() {
val actual = case.parse(
directory = "array",
filename = "test_array_without_link.json"
)
assertEquals(ENTITY_WITH_ARRAY, actual)
}
@Test
fun `when array contains elements defined by links it is parsed correctly`() {
val actual = case.parse(
directory = "array",
filename = "test_array_with_internal_links.json"
)
assertEquals(ENTITY_WITH_ARRAY, actual)
}
@Test
fun `when array contains links inside elements it is parsed correctly`() {
val actual = case.parse(
directory = "array",
filename = "test_array_with_complex_items_with_internal_links.json"
)
assertEquals(ENTITY_WITH_ARRAY, actual)
}
@Test(expected = ParsingException::class)
fun `array has minItems 1 and empty array received`() {
case.parse(
directory = "array",
filename = "test_array_empty.json"
)
}
@Test(expected = ParsingException::class)
fun `when array has all items invalid in template parsing fails`() {
case.parse(
directory = "array",
filename = "test_array_invalid_items.json"
)
}
@Test(expected = ParsingException::class)
fun `when array has all items invalid in data parsing fails`() {
case.parse(
directory = "array",
filename = "test_array_invalid_items_in_data.json"
)
}
@Test(expected = ParsingException::class)
fun `when data is missing parsing fails`() {
case.parse(
directory = "array",
filename = "test_array_invalid_items_in_data.json"
)
}
@Test
fun `when array has some invalid items they are skipped`() {
val actual = case.parse(
directory = "array",
filename = "test_array_one_invalid_item.json"
)
assertEquals(ENTITY_WITH_ARRAY, actual)
}
@Test
fun `when array has some invalid links they are skipped`() {
val actual = case.parse(
directory = "array",
filename = "test_array_missing_one_link.json"
)
assertEquals(ENTITY_WITH_ARRAY, actual)
}
@Test
fun `when array is not templated parsing succeeds`() {
val actual = case.parse(
directory = "array",
filename = "test_array_not_templated.json"
)
assertEquals(ENTITY_WITH_ARRAY, actual)
}
@Test
fun `when array has heterogeneous items parsing succeeds`() {
val actual = case.parse(
directory = "array",
filename = "test_array_with_heterogeneous_items.json"
)
assertEquals(ENTITY_WITH_HETEROGENOUS_ARRAY, actual)
}
@Test
fun `when array has heterogeneous items with internal links parsing succeeds`() {
val actual = case.parse(
directory = "array",
filename = "test_array_with_heterogeneous_items_with_internal_links.json"
)
assertEquals(ENTITY_WITH_HETEROGENOUS_ARRAY, actual)
}
@Test
fun `when array has nested array parsing succeeds`() {
val actual = case.parse(
directory = "array",
filename = "test_array_nested.json"
)
assertEquals(ENTITY_WITH_NESTED_ARRAY, actual)
}
@Test
fun `when array has nested array with links inside parsing succeeds`() {
val actual = case.parse(
directory = "array",
filename = "test_array_nested_with_internal_link.json"
)
assertEquals(ENTITY_WITH_NESTED_ARRAY, actual)
}
@Test
fun `when array has nested templated array parsing succeeds`() {
val actual = case.parse(
directory = "array",
filename = "test_array_nested_with_internal_link.json"
)
assertEquals(ENTITY_WITH_NESTED_ARRAY, actual)
}
}
@@ -0,0 +1,50 @@
package com.yandex.generator
import com.yandex.div.json.ParsingException
import com.yandex.testing.Entity
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class ArrayWithTransformTest {
private val case = EntityTemplateTestCase(
ctor = Entity.Companion::invoke
)
@Test
fun `invalid item with transform skipped`() {
val actual = case.parse(
directory = "array_with_transform",
filename = "test_array_with_transform_not_templated_one_invalid_item.json"
)
assertEquals(ENTITY_WITH_ARRAY_WITH_TRANSFORM, actual)
}
@Test
fun `invalid templated item with transform skipped`() {
val actual = case.parse(
directory = "array_with_transform",
filename = "test_array_with_transform_one_invalid_item.json"
)
assertEquals(ENTITY_WITH_ARRAY_WITH_TRANSFORM, actual)
}
@Test(expected = ParsingException::class)
fun `array parsing failed when all items is invalid`() {
case.parse(
directory = "array_with_transform",
filename = "test_array_with_transform_not_templated_invalid_items.json"
)
}
@Test(expected = ParsingException::class)
fun `array parsing failed when all templated items is invalid`() {
case.parse(
directory = "array_with_transform",
filename = "test_array_with_transform_invalid_items.json"
)
}
}
@@ -0,0 +1,86 @@
package com.yandex.generator
import com.yandex.div.json.ParsingException
import com.yandex.generator.ENTITY_WITH_REQUIRED_COMPLEX_PROPERTY
import com.yandex.generator.EntityTemplateTestCase
import com.yandex.testing.Entity
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class ComplexPropertyTest {
private val case = EntityTemplateTestCase(
ctor = Entity.Companion::invoke
)
@Test
fun `required complex property with reference is parsed correctly`() {
val actual = case.parse(
directory = "complex_property",
filename = "test_complex_property_with_link.json"
)
assertEquals(ENTITY_WITH_REQUIRED_COMPLEX_PROPERTY, actual)
}
@Test
fun `required complex property without reference is parsed correctly`() {
val actual = case.parse(
directory = "complex_property",
filename = "test_complex_property_without_link.json"
)
assertEquals(ENTITY_WITH_REQUIRED_COMPLEX_PROPERTY, actual)
}
@Test
fun `required complex property with internal reference is parsed correctly`() {
val actual = case.parse(
directory = "complex_property",
filename = "test_complex_property_with_internal_link.json"
)
assertEquals(ENTITY_WITH_REQUIRED_COMPLEX_PROPERTY, actual)
}
@Test(expected = ParsingException::class)
fun `when data for required complex property with reference is missing parsing fails`() {
case.parse(
directory = "complex_property",
filename = "test_complex_property_with_link_missing_data.json"
)
}
@Test(expected = ParsingException::class)
fun `when data for required complex property without reference is missing parsing fails`() {
case.parse(
directory = "complex_property",
filename = "test_complex_property_without_link_missing_data.json"
)
}
@Test(expected = ParsingException::class)
fun `when data for required complex property with internal reference is missing parsing fails`() {
case.parse(
directory = "complex_property",
filename = "test_complex_property_with_internal_link_missing_data.json"
)
}
@Test
fun `required complex property without template is parsed correctly`() {
val actual = case.parse(
directory = "complex_property",
filename = "test_complex_property_not_templated.json"
)
assertEquals(ENTITY_WITH_REQUIRED_COMPLEX_PROPERTY, actual)
}
@Test(expected = ParsingException::class)
fun `when required complex property is invalid parsing fails`() {
case.parse(
directory = "complex_property",
filename = "test_invalid_complex_property_not_templated.json"
)
}
}
@@ -0,0 +1,22 @@
package com.yandex.generator
import com.yandex.div.json.ParsingEnvironment
import com.yandex.div.json.ParsingErrorLogger
import com.yandex.div.json.TemplateParsingEnvironment
import com.yandex.testing.EntityTemplate
import org.json.JSONObject
internal class EntityParsingEnvironment(
logger: ParsingErrorLogger
) : TemplateParsingEnvironment<EntityTemplate>(logger) {
override val templateFactory = object: TemplateFactory<EntityTemplate> {
override fun create(env: ParsingEnvironment, topLevel: Boolean, json: JSONObject): EntityTemplate {
return EntityTemplate(env, topLevel, json)
}
}
}
internal val LOG_ENVIRONMENT = EntityParsingEnvironment(logger = ParsingErrorLogger.LOG)
internal val ASSERT_ENVIRONMENT = EntityParsingEnvironment(logger = ParsingErrorLogger.ASSERT)
@@ -0,0 +1,37 @@
package com.yandex.generator
import com.yandex.div.json.JSONSerializable
import com.yandex.div.json.ParsingEnvironment
import com.yandex.div.json.ParsingErrorLogger
import org.json.JSONObject
import java.io.File
class EntityTemplateTestCase<T : JSONSerializable>(
private val ctor: (ParsingEnvironment, JSONObject) -> T,
) {
private val environment = EntityParsingEnvironment(ParsingErrorLogger.LOG)
fun parse(directory: String, filename: String): T {
val bytes = readData(directory, filename)
return parse(jsonObject(bytes))
}
private fun readData(directory: String, filename: String): ByteArray {
val path = "${BuildConfig.TEMPLATES_JSON_PATH}/template_test_data/$directory/$filename"
return File(path).readBytes()
}
private fun parse(json: JSONObject): T {
val templatesJson = json.optJSONObject("templates")
if (templatesJson != null) {
environment.parseTemplates(templatesJson)
}
val entityJson = json.getJSONObject("entity")
return ctor.invoke(environment, entityJson)
}
private fun jsonObject(json: ByteArray): JSONObject {
return JSONObject(json.toString(charset = Charsets.UTF_8))
}
}
@@ -0,0 +1,14 @@
package com.yandex.generator
import com.yandex.div.json.JSONSerializable
import com.yandex.div.json.ParsingEnvironment
import org.json.JSONObject
class EntityTestCase<T : JSONSerializable>(
private val ctor: (ParsingEnvironment, JSONObject) -> T,
) {
fun parse(env: ParsingEnvironment, json: String): T {
return ctor.invoke(env, JSONObject(json))
}
}
@@ -0,0 +1,49 @@
package com.yandex.generator
import android.net.Uri
import com.yandex.div.json.ParsingException
import com.yandex.div.json.expressions.ExpressionResolver
import com.yandex.testing.EntityWithComplexProperty
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class EntityWithComplexPropertyTest {
private val case = EntityTestCase(
ctor = EntityWithComplexProperty.Companion::invoke,
)
@Test
fun `property value is set`() {
val json = """{
"property": {
"value": "https://ya.ru"
}
}"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals(Uri.parse("https://ya.ru"), entity.property.value.evaluate(ExpressionResolver.EMPTY))
}
@Test(expected = ParsingException::class)
fun `null property value`() {
val json = """{ }"""
case.parse(LOG_ENVIRONMENT, json)
}
@Test(expected = ParsingException::class)
fun `invalid property`() {
val json = """{
"property": {
"value": 1
}
}"""
case.parse(LOG_ENVIRONMENT, json)
}
}
@@ -0,0 +1,38 @@
package com.yandex.generator
import com.yandex.div.json.expressions.ExpressionResolver
import com.yandex.testing.EntityWithComplexPropertyWithDefaultValue
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class EntityWithComplexPropertyWithDefaultValueTest {
private val case = EntityTestCase(
ctor = EntityWithComplexPropertyWithDefaultValue.Companion::invoke,
)
@Test
fun `property value is set`() {
val json = """{
"property": {
"value": "Some text"
}
}"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals("Some text", entity.property.value.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `null property value resolves as default value`() {
val json = """{ }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals("Default text", entity.property.value.evaluate(ExpressionResolver.EMPTY))
}
}
@@ -0,0 +1,103 @@
package com.yandex.generator
import com.yandex.div.json.ParsingException
import com.yandex.div.json.expressions.ExpressionResolver
import com.yandex.testing.EntityWithArray
import com.yandex.testing.EntityWithRequiredProperty
import com.yandex.testing.EntityWithStringEnumPropertyWithDefaultValue
import org.hamcrest.Matchers.hasSize
import org.junit.Assert.assertEquals
import org.junit.Assert.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class EntityWithEntityArrayPropertyTest {
private val case = EntityTestCase(
ctor = EntityWithArray.Companion::invoke
)
@Test
fun `homogeneous array`() {
val json = """{
"array": [
{
"type": "entity_with_required_property",
"property": "Some text 1"
},
{
"type": "entity_with_required_property",
"property": "Some text 2"
}
]
}"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertThat(entity.array, hasSize(2))
assertEquals("Some text 1", (entity.array[0].value() as EntityWithRequiredProperty).property.evaluate(ExpressionResolver.EMPTY))
assertEquals("Some text 2", (entity.array[1].value() as EntityWithRequiredProperty).property.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `heterogeneous array`() {
val json = """{
"array": [
{
"type": "entity_with_required_property",
"property": "Some text 1"
},
{
"type": "entity_with_string_enum_property_with_default_value"
}
]
}"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertThat(entity.array, hasSize(2))
assertEquals("Some text 1", (entity.array[0].value() as EntityWithRequiredProperty).property
.evaluate(ExpressionResolver.EMPTY))
assertEquals(
EntityWithStringEnumPropertyWithDefaultValue.Value.SECOND,
(entity.array[1].value() as EntityWithStringEnumPropertyWithDefaultValue).value
.evaluate(ExpressionResolver.EMPTY)
)
}
@Test
fun `invalid object in array`() {
val json = """{
"array": [
{
"type": "entity_with_required_property",
"property": "Some text 1"
},
{
"type": "entity_with_required_property"
},
{
"type": "entity_with_required_property",
"property": "Some text 3"
}
]
}"""
val entity = case.parse(LOG_ENVIRONMENT, json)
assertThat(entity.array, hasSize(2))
assertEquals("Some text 1", (entity.array[0].value() as EntityWithRequiredProperty).property
.evaluate(ExpressionResolver.EMPTY))
assertEquals("Some text 3", (entity.array[1].value() as EntityWithRequiredProperty).property
.evaluate(ExpressionResolver.EMPTY))
}
@Test(expected = ParsingException::class)
fun `null property value`() {
val json = """{ }"""
case.parse(LOG_ENVIRONMENT, json)
}
}
@@ -0,0 +1,63 @@
package com.yandex.generator
import com.yandex.div.json.expressions.ExpressionResolver
import com.yandex.testing.EntityWithEntityProperty
import com.yandex.testing.EntityWithRequiredProperty
import com.yandex.testing.EntityWithStringEnumProperty
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class EntityWithEntityPropertyTest {
private val case = EntityTestCase(
ctor = EntityWithEntityProperty.Companion::invoke
)
@Test
fun `property value is set`() {
val json = """{
"entity": {
"type": "entity_with_required_property",
"property": "Some text"
}
}"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals("Some text", (entity.entity.value() as EntityWithRequiredProperty).property
.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `invalid value resoles as default value`() {
val json = """{
"entity": {
"type": "entity_with_required_property"
}
}"""
val entity = case.parse(LOG_ENVIRONMENT, json)
assertEquals(
EntityWithStringEnumProperty.Property.SECOND,
(entity.entity.value() as EntityWithStringEnumProperty).property
.evaluate(ExpressionResolver.EMPTY)
)
}
@Test
fun `null value resolves as default value`() {
val json = """{ }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals(
EntityWithStringEnumProperty.Property.SECOND,
(entity.entity.value() as EntityWithStringEnumProperty).property
.evaluate(ExpressionResolver.EMPTY)
)
}
}
@@ -0,0 +1,51 @@
package com.yandex.generator
import com.yandex.div.json.expressions.ExpressionResolver
import com.yandex.testing.EntityWithOptionalProperty
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class EntityWithOptionalPropertyTest {
private val case = EntityTestCase(
ctor = EntityWithOptionalProperty.Companion::invoke
)
@Test
fun `property value is set`() {
val json = """{ "property": "Some text" }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals("Some text", entity.property!!.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `invalid value type`() {
val json = """{ "value": [ "Some text" ] }"""
val entity = case.parse(LOG_ENVIRONMENT, json)
assertNull(entity.property)
}
@Test(expected = AssertionError::class)
fun `error in value is logged`() {
val json = """{ "property": [ "Some text" ] }"""
case.parse(ASSERT_ENVIRONMENT, json)
}
@Test
fun `null property value`() {
val json = """{ }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertNull(entity.property)
}
}
@@ -0,0 +1,36 @@
package com.yandex.generator
import com.yandex.div.json.expressions.ExpressionResolver
import com.yandex.testing.EntityWithOptionalStringEnumProperty
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class EntityWithOptionalStringEnumPropertyTest {
private val case = EntityTestCase(
ctor = EntityWithOptionalStringEnumProperty.Companion::invoke
)
@Test
fun `property value is set`() {
val json = """{ "property": "second" }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals(EntityWithOptionalStringEnumProperty.Property.SECOND,
entity.property?.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `null property value`() {
val json = """{ }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertNull(entity.property)
}
}
@@ -0,0 +1,40 @@
package com.yandex.generator
import com.yandex.div.json.ParsingException
import com.yandex.div.json.expressions.ExpressionResolver
import com.yandex.testing.EntityWithRequiredProperty
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class EntityWithRequiredPropertyTest {
private val case = EntityTestCase(
ctor = EntityWithRequiredProperty.Companion::invoke
)
@Test
fun `property value is set`() {
val json = """{ "property": "Some text" }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals("Some text", entity.property.evaluate(ExpressionResolver.EMPTY))
}
@Test(expected = ParsingException::class)
fun `invalid property type`() {
val json = """{ "property": [ "Some text" ] }"""
case.parse(LOG_ENVIRONMENT, json)
}
@Test(expected = ParsingException::class)
fun `null property value`() {
val json = """{ }"""
case.parse(LOG_ENVIRONMENT, json)
}
}
@@ -0,0 +1,158 @@
package com.yandex.generator
import android.graphics.Color
import android.net.Uri
import com.yandex.div.json.expressions.ExpressionResolver
import com.yandex.testing.EntityWithSimpleProperties
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class EntityWithSimplePropertiesTest {
private val case = EntityTestCase(
ctor = EntityWithSimpleProperties.Companion::invoke
)
@Test
fun `string value`() {
val json = """{ "string": "Some text" }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals("Some text", entity.string!!.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `integer value`() {
val json = """{ "integer": 20 }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals(20, entity.integer!!.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `double value as integer`() {
// sometimes Moshi reads integers as doubles for some reason
val json = """{ "integer": 20.0 }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals(20, entity.integer!!.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `double value`() {
val json = """{ "double": 20.123 }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals(20.123, entity.double!!.evaluate(ExpressionResolver.EMPTY), 0.0)
}
@Test
fun `integer value as double`() {
val json = """{ "double": 20 }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals(20.0, entity.double!!.evaluate(ExpressionResolver.EMPTY), 0.0)
}
@Test
fun `positive integer value`() {
val json = """{ "positive_integer": 20 }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals(20, entity.positiveInteger!!.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `invalid positive integer value`() {
val json = """{ "positive_integer": 0 }"""
val entity = case.parse(LOG_ENVIRONMENT, json)
assertNull(entity.positiveInteger)
}
@Test
fun `1 as true`() {
val json = """{ "boolean": 1 }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertTrue(entity.boolean!!.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `0 as false`() {
val json = """{ "boolean": 0 }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertFalse(entity.boolean!!.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `random integer value as null`() {
val json = """{ "boolean": 123 }"""
val entity = case.parse(LOG_ENVIRONMENT, json)
assertNull(entity.boolean)
}
@Test
fun `double value as true`() {
// sometimes Moshi reads integers as doubles for some reason
val json = """{ "boolean": 1.0 }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertTrue(entity.boolean!!.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `Url value`() {
val json = """{ "url": "https://yandex.ru" }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals(Uri.parse("https://yandex.ru"), entity.url!!.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `Color without alpha value`() {
val json = """{ "color": "#BBCCDD" }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals(Color.parseColor("#BBCCDD"), entity.color!!.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `Color with alpha value`() {
val json = """{ "color": "#AABBCCDD" }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals(Color.parseColor("#AABBCCDD"), entity.color!!.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `invalid Color value`() {
val json = """{ "color": "#ABBCCDD" }"""
val entity = case.parse(LOG_ENVIRONMENT, json)
assertNull(entity.color)
}
}
@@ -0,0 +1,101 @@
package com.yandex.generator
import com.yandex.div.json.ParsingException
import com.yandex.div.json.expressions.ExpressionResolver
import com.yandex.testing.EntityWithStringArrayProperty
import org.hamcrest.Matchers.hasSize
import org.junit.Assert.assertEquals
import org.junit.Assert.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class EntityWithStringArrayPropertyTest {
private val case = EntityTestCase(
ctor = EntityWithStringArrayProperty.Companion::invoke
)
@Test
fun `valid array`() {
val json = """{
"array": [
"Some text 1",
"Some text 2"
]
}"""
val entity = case.parse(LOG_ENVIRONMENT, json)
val array = entity.array.evaluate(ExpressionResolver.EMPTY)
assertThat(array, hasSize(2))
assertEquals("Some text 1", array[0])
assertEquals("Some text 2", array[1])
}
@Test
fun `invalid object in array`() {
val json = """{
"array": [
"Some text 1",
123,
"Some text 3"
]
}"""
val entity = case.parse(LOG_ENVIRONMENT, json)
val array = entity.array.evaluate(ExpressionResolver.EMPTY)
assertThat(array, hasSize(2))
assertEquals("Some text 1", array[0])
assertEquals("Some text 3", array[1])
}
@Test
fun `array of expressions`() {
val json = """{
"array": [
"@{expression_1}",
"@{expression_2}",
"@{expression_3}"
]
}"""
val entity = case.parse(LOG_ENVIRONMENT, json)
val array = entity.array.evaluate(ExpressionResolver.EMPTY)
assertThat(array, hasSize(3))
val typeDefault = ""
assertEquals(typeDefault, array[0])
assertEquals(typeDefault, array[1])
assertEquals(typeDefault, array[2])
}
@Test
fun `mixed array from expressions and values`() {
val json = """{
"array": [
"@{expression_1}",
"Some Text 2",
"@{expression_3}"
]
}"""
val entity = case.parse(LOG_ENVIRONMENT, json)
val array = entity.array.evaluate(ExpressionResolver.EMPTY)
assertThat(array, hasSize(3))
val typeDefault = ""
assertEquals(typeDefault, array[0])
assertEquals("Some Text 2", array[1])
assertEquals(typeDefault, array[2])
}
@Test(expected = ParsingException::class)
fun `null property value`() {
val json = """{ }"""
case.parse(LOG_ENVIRONMENT, json)
}
}
@@ -0,0 +1,34 @@
package com.yandex.generator
import com.yandex.div.json.ParsingException
import com.yandex.div.json.expressions.ExpressionResolver
import com.yandex.testing.EntityWithStringEnumProperty
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class EntityWithStringEnumPropertyTest {
private val case = EntityTestCase(
ctor = EntityWithStringEnumProperty.Companion::invoke
)
@Test
fun `property value is set`() {
val json = """{ "property": "second" }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals(EntityWithStringEnumProperty.Property.SECOND,
entity.property.evaluate(ExpressionResolver.EMPTY))
}
@Test(expected = ParsingException::class)
fun `null property value`() {
val json = """{ }"""
case.parse(LOG_ENVIRONMENT, json)
}
}
@@ -0,0 +1,56 @@
package com.yandex.generator
import com.yandex.div.json.expressions.ExpressionResolver
import com.yandex.testing.EntityWithStringEnumPropertyWithDefaultValue
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class EntityWithStringEnumPropertyWithDefaultValueTest {
private val case = EntityTestCase(
ctor = EntityWithStringEnumPropertyWithDefaultValue.Companion::invoke
)
@Test
fun `property value is set`() {
val json = """{ "value": "third" }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals(EntityWithStringEnumPropertyWithDefaultValue.Value.THIRD,
entity.value.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `invalid value resolves as default value`() {
val json = """{ "value": "no value" }"""
val entity = case.parse(LOG_ENVIRONMENT, json)
assertEquals(EntityWithStringEnumPropertyWithDefaultValue.Value.SECOND,
entity.value.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `invalid value type resolves as default value`() {
val json = """{ "value": [ "first" ] }"""
val entity = case.parse(LOG_ENVIRONMENT, json)
assertEquals(EntityWithStringEnumPropertyWithDefaultValue.Value.SECOND,
entity.value.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `null value resolves as default value`() {
val json = """{ }"""
val entity = case.parse(ASSERT_ENVIRONMENT, json)
assertEquals(EntityWithStringEnumPropertyWithDefaultValue.Value.SECOND,
entity.value.evaluate(ExpressionResolver.EMPTY))
}
}
@@ -0,0 +1,92 @@
package com.yandex.generator
import android.graphics.Color
import android.net.Uri
import com.yandex.div.json.expressions.ConstantExpressionsList
import com.yandex.div.json.expressions.Expression
import com.yandex.testing.Entity
import com.yandex.testing.EntityWithArray
import com.yandex.testing.EntityWithArrayOfNestedItems
import com.yandex.testing.EntityWithArrayWithTransform
import com.yandex.testing.EntityWithComplexProperty
import com.yandex.testing.EntityWithOptionalComplexProperty
import com.yandex.testing.EntityWithOptionalProperty
import com.yandex.testing.EntityWithOptionalStringEnumProperty
import com.yandex.testing.EntityWithRequiredProperty
import com.yandex.testing.EntityWithStrictArray
import com.yandex.testing.EntityWithStringEnumProperty
internal val ENTITY_WITH_STRING_ENUM_PROPERTY = Entity.WithStringEnumProperty(
EntityWithStringEnumProperty(Expression.constant(EntityWithStringEnumProperty.Property.SECOND))
)
internal val ENTITY_WITH_OPTIONAL_STRING_ENUM_PROPERTY = Entity.WithOptionalStringEnumProperty(
EntityWithOptionalStringEnumProperty(Expression.constant(EntityWithOptionalStringEnumProperty.Property.SECOND))
)
internal val ENTITY_WITH_MISSING_STRING_ENUM_PROPERTY = Entity.WithOptionalStringEnumProperty(
EntityWithOptionalStringEnumProperty(null)
)
internal val ENTITY_WITH_REQUIRED_PROPERTY = Entity.WithRequiredProperty(
EntityWithRequiredProperty(Expression.constant("Some text"))
)
internal val ENTITY_WITH_OPTIONAL_PROPERTY = Entity.WithOptionalProperty(
EntityWithOptionalProperty(Expression.constant("Some text"))
)
internal val ENTITY_WITH_MISSING_OPTIONAL_PROPERTY = Entity.WithOptionalProperty(
EntityWithOptionalProperty(null)
)
internal val ENTITY_WITH_REQUIRED_COMPLEX_PROPERTY = Entity.WithComplexProperty(
EntityWithComplexProperty(EntityWithComplexProperty.Property(Expression.constant(Uri.parse("https://ya.ru"))))
)
internal val ENTITY_WITH_OPTIONAL_COMPLEX_PROPERTY = Entity.WithOptionalComplexProperty(
EntityWithOptionalComplexProperty(EntityWithOptionalComplexProperty.Property(Expression.constant(Uri.parse("https://ya.ru"))))
)
internal val ENTITY_WITH_MISSING_OPTIONAL_COMPLEX_PROPERTY = Entity.WithOptionalComplexProperty(
EntityWithOptionalComplexProperty(null)
)
internal val ENTITY_WITH_ARRAY = Entity.WithArray(
EntityWithArray(listOf(
ENTITY_WITH_REQUIRED_COMPLEX_PROPERTY,
ENTITY_WITH_REQUIRED_COMPLEX_PROPERTY
))
)
internal val ENTITY_WITH_HETEROGENOUS_ARRAY = Entity.WithArray(
EntityWithArray(listOf(
ENTITY_WITH_REQUIRED_COMPLEX_PROPERTY,
ENTITY_WITH_REQUIRED_PROPERTY,
ENTITY_WITH_STRING_ENUM_PROPERTY
))
)
internal val ENTITY_WITH_NESTED_ARRAY = Entity.WithArray(
EntityWithArray(listOf(ENTITY_WITH_ARRAY))
)
internal val ENTITY_WITH_ARRAY_WITH_TRANSFORM = Entity.WithArrayWithTransform(
EntityWithArrayWithTransform(ConstantExpressionsList(listOf(
Color.parseColor("#FF00FF00"),
Color.parseColor("#AAFF0000")
)))
)
internal val ENTITY_WITH_ARRAY_OF_NESTED_ITEMS = Entity.WithArrayOfNestedItems(
EntityWithArrayOfNestedItems(listOf(
EntityWithArrayOfNestedItems.Item(ENTITY_WITH_REQUIRED_COMPLEX_PROPERTY, Expression.constant("Some text")),
EntityWithArrayOfNestedItems.Item(ENTITY_WITH_REQUIRED_COMPLEX_PROPERTY, Expression.constant("Some text"))
))
)
internal val ENTITY_WITH_STRICT_ARRAY = Entity.WithStrictArray(
EntityWithStrictArray(listOf(
ENTITY_WITH_REQUIRED_COMPLEX_PROPERTY,
ENTITY_WITH_REQUIRED_COMPLEX_PROPERTY
))
)
@@ -0,0 +1,90 @@
package com.yandex.generator
import com.yandex.generator.ENTITY_WITH_MISSING_OPTIONAL_COMPLEX_PROPERTY
import com.yandex.generator.ENTITY_WITH_OPTIONAL_COMPLEX_PROPERTY
import com.yandex.generator.EntityTemplateTestCase
import com.yandex.testing.Entity
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class OptionalComplexPropertyTest {
private val case = EntityTemplateTestCase(
ctor = Entity.Companion::invoke
)
@Test
fun `optional complex property with reference is parsed correctly`() {
val actual = case.parse(
directory = "optional_complex_property",
filename = "test_optional_complex_property_with_link.json"
)
assertEquals(ENTITY_WITH_OPTIONAL_COMPLEX_PROPERTY, actual)
}
@Test
fun `optional complex property without reference is parsed correctly`() {
val actual = case.parse(
directory = "optional_complex_property",
filename = "test_optional_complex_property_without_link.json"
)
assertEquals(ENTITY_WITH_OPTIONAL_COMPLEX_PROPERTY, actual)
}
@Test
fun `optional complex property with internal reference is parsed correctly`() {
val actual = case.parse(
directory = "optional_complex_property",
filename = "test_optional_complex_property_with_internal_link.json"
)
assertEquals(ENTITY_WITH_OPTIONAL_COMPLEX_PROPERTY, actual)
}
@Test
fun `when data for optional complex property with reference is missing entity created`() {
val actual = case.parse(
directory = "optional_complex_property",
filename = "test_optional_complex_property_with_link_missing_data.json"
)
assertEquals(ENTITY_WITH_MISSING_OPTIONAL_COMPLEX_PROPERTY, actual)
}
@Test
fun `when data for optional complex property without reference is missing entity created`() {
val actual = case.parse(
directory = "optional_complex_property",
filename = "test_optional_complex_property_without_link_missing_data.json"
)
assertEquals(ENTITY_WITH_MISSING_OPTIONAL_COMPLEX_PROPERTY, actual)
}
@Test
fun `when data for optional complex property with internal reference is missing entity created`() {
val actual = case.parse(
directory = "optional_complex_property",
filename = "test_optional_complex_property_with_internal_link_missing_data.json"
)
assertEquals(ENTITY_WITH_MISSING_OPTIONAL_COMPLEX_PROPERTY, actual)
}
@Test
fun `optional complex property without template is parsed correctly`() {
val actual = case.parse(
directory = "optional_complex_property",
filename = "test_optional_complex_property_not_templated.json"
)
assertEquals(ENTITY_WITH_OPTIONAL_COMPLEX_PROPERTY, actual)
}
@Test
fun `when optional complex property is invalid entity created`() {
val actual = case.parse(
directory = "optional_complex_property",
filename = "test_optional_invalid_complex_property_not_templated.json"
)
assertEquals(ENTITY_WITH_MISSING_OPTIONAL_COMPLEX_PROPERTY, actual)
}
}
@@ -0,0 +1,72 @@
package com.yandex.generator
import com.yandex.generator.ENTITY_WITH_MISSING_OPTIONAL_PROPERTY
import com.yandex.generator.ENTITY_WITH_OPTIONAL_PROPERTY
import com.yandex.generator.EntityTemplateTestCase
import com.yandex.testing.Entity
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class OptionalPropertyTest {
private val case = EntityTemplateTestCase(
ctor = Entity.Companion::invoke
)
@Test
fun `optional property with reference is parsed correctly`() {
val actual = case.parse(
directory = "optional_property",
filename = "test_optional_property_with_link.json"
)
assertEquals(ENTITY_WITH_OPTIONAL_PROPERTY, actual)
}
@Test
fun `optional property without reference is parsed correctly`() {
val actual = case.parse(
directory = "optional_property",
filename = "test_optional_property_without_link.json"
)
assertEquals(ENTITY_WITH_OPTIONAL_PROPERTY, actual)
}
@Test
fun `missing optional property with reference is parsed correctly`() {
val actual = case.parse(
directory = "optional_property",
filename = "test_optional_property_with_link_missing_data.json"
)
assertEquals(ENTITY_WITH_MISSING_OPTIONAL_PROPERTY, actual)
}
@Test
fun `missing optional property without reference is parsed correctly`() {
val actual = case.parse(
directory = "optional_property",
filename = "test_optional_property_without_link_missing_data.json"
)
assertEquals(ENTITY_WITH_MISSING_OPTIONAL_PROPERTY, actual)
}
@Test
fun `optional property with override is parsed correctly`() {
val actual = case.parse(
directory = "optional_property",
filename = "test_optional_property_with_override.json"
)
assertEquals(ENTITY_WITH_OPTIONAL_PROPERTY, actual)
}
@Test
fun `optional property without template is parsed correctly`() {
val actual = case.parse(
directory = "optional_property",
filename = "test_optional_property_not_templated.json"
)
assertEquals(ENTITY_WITH_OPTIONAL_PROPERTY, actual)
}
}
@@ -0,0 +1,72 @@
package com.yandex.generator
import com.yandex.generator.ENTITY_WITH_MISSING_STRING_ENUM_PROPERTY
import com.yandex.generator.ENTITY_WITH_OPTIONAL_STRING_ENUM_PROPERTY
import com.yandex.generator.EntityTemplateTestCase
import com.yandex.testing.Entity
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class OptionalStringEnumTest {
private val case = EntityTemplateTestCase(
ctor = Entity.Companion::invoke
)
@Test
fun `optional string enum property with reference is parsed correctly`() {
val actual = case.parse(
directory = "optional_string_enum_property",
filename = "test_optional_string_enum_property_with_link.json"
)
assertEquals(ENTITY_WITH_OPTIONAL_STRING_ENUM_PROPERTY, actual)
}
@Test
fun `optional string enum property without reference is parsed correctly`() {
val actual = case.parse(
directory = "optional_string_enum_property",
filename = "test_optional_string_enum_property_without_link.json"
)
assertEquals(ENTITY_WITH_OPTIONAL_STRING_ENUM_PROPERTY, actual)
}
@Test
fun `missing optional string enum property with reference is parsed correctly`() {
val actual = case.parse(
directory = "optional_string_enum_property",
filename = "test_optional_string_enum_property_with_link_missing_data.json"
)
assertEquals(ENTITY_WITH_MISSING_STRING_ENUM_PROPERTY, actual)
}
@Test
fun `missing optional string enum property without reference is parsed correctly`() {
val actual = case.parse(
directory = "optional_string_enum_property",
filename = "test_optional_string_enum_property_without_link_missing_data.json"
)
assertEquals(ENTITY_WITH_MISSING_STRING_ENUM_PROPERTY, actual)
}
@Test
fun `string optional enum property with override is parsed correctly`() {
val actual = case.parse(
directory = "optional_string_enum_property",
filename = "test_optional_string_enum_property_with_override.json"
)
assertEquals(ENTITY_WITH_OPTIONAL_STRING_ENUM_PROPERTY, actual)
}
@Test
fun `string optional enum property without template is parsed correctly`() {
val actual = case.parse(
directory = "optional_string_enum_property",
filename = "test_optional_string_enum_property_not_templated.json"
)
assertEquals(ENTITY_WITH_OPTIONAL_STRING_ENUM_PROPERTY, actual)
}
}
@@ -0,0 +1,181 @@
package com.yandex.generator
import com.yandex.div.json.ParsingErrorLogger
import com.yandex.div.json.ParsingException
import com.yandex.div.json.summary
import com.yandex.testing.EntityWithOptionalProperty
import com.yandex.testing.EntityWithRequiredProperty
import com.yandex.testing.EntityWithOptionalComplexProperty
import org.json.JSONObject
import org.junit.Assert.assertEquals
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.verifyZeroInteractions
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class ParsingErrorLoggerTest {
private val logger = mock<ParsingErrorLogger>()
private val environment = EntityParsingEnvironment(logger = logger)
private val exceptionCaptor = argumentCaptor<ParsingException>()
private val exception: ParsingException
get() = exceptionCaptor.firstValue
@Test
fun `error when optional property has invalid value`() {
val json = JSONObject("""{ "property": 123 }""")
EntityWithOptionalProperty(environment, json)
verify(logger).logError(exceptionCaptor.capture())
assertEquals(
"Value for key 'property' has wrong type java.lang.Integer",
exception.message
)
assertEquals(json.summary(), exception.jsonSummary)
}
@Test
fun `no error when optional property has null value`() {
val json = JSONObject("""{ "property": null }""")
EntityWithOptionalProperty(environment, json)
verifyZeroInteractions(logger)
}
@Test
fun `error when optional complex property has has null value`() {
val json = JSONObject("""{ "property": { "value": null } }""")
try {
EntityWithOptionalComplexProperty(environment, json)
} catch (e: ParsingException) {
// expected
}
verify(logger).logError(exceptionCaptor.capture())
assertEquals(
"Value for key 'value' is missing",
exception.message
)
assertEquals(json.getJSONObject("property").summary(), exception.jsonSummary)
}
@Test
fun `no error when required property has invalid value`() {
val json = JSONObject("""{ "property": 123 }""")
try {
EntityWithRequiredProperty(environment, json)
} catch (e: ParsingException) {
// expected
}
verifyZeroInteractions(logger)
}
@Test
fun `no error when required property has null value`() {
val json = JSONObject("""{ "property": null }""")
try {
EntityWithRequiredProperty(environment, json)
} catch (e: ParsingException) {
// expected
}
verifyZeroInteractions(logger)
}
@Ignore
@Test
fun `error when template without type`() {
val json = JSONObject("""{ "template1": { } }""")
environment.parseTemplates(json)
verify(logger).logTemplateError(exceptionCaptor.capture(), eq("template1"))
assertEquals(
"Value for key 'type' is missing",
exception.message
)
assertEquals(json.getJSONObject("template1").summary(), exception.jsonSummary)
}
@Test
fun `error when template has invalid optional property value`() {
val json = JSONObject(
"""{
"template1": {
"type": "entity_with_optional_property",
"property": 123
}
}"""
)
environment.parseTemplates(json)
verify(logger).logTemplateError(exceptionCaptor.capture(), eq("template1"))
assertEquals(
"Value for key 'property' has wrong type java.lang.Integer",
exception.message
)
assertEquals(json.getJSONObject("template1").summary(), exception.jsonSummary)
}
@Test
fun `error when template has invalid link`() {
val json = JSONObject(
"""{
"template1": {
"type": "entity_with_optional_property",
"${'$'}property": 123
}
}"""
)
environment.parseTemplates(json)
verify(logger).logTemplateError(exceptionCaptor.capture(), eq("template1"))
assertEquals(
"Value for key '\$property' has wrong type java.lang.Integer",
exception.message
)
assertEquals(json.getJSONObject("template1").summary(), exception.jsonSummary)
}
@Test
fun `multiple errors when errors in multiple templates`() {
val json = JSONObject(
"""{
"template1": {
"type": "entity_with_optional_property",
"property": 123
},
"template2": {
"type": "entity_with_optional_property",
"property": 123
}
}"""
)
environment.parseTemplates(json)
val templateIdCaptor = argumentCaptor<String>()
verify(logger, times(2)).logTemplateError(any(), templateIdCaptor.capture())
val ids = templateIdCaptor.allValues
assertEquals("template1", ids[0])
assertEquals("template2", ids[1])
}
}
@@ -0,0 +1,47 @@
package com.yandex.generator
import com.yandex.div.json.expressions.ExpressionResolver
import com.yandex.generator.EntityTemplateTestCase
import com.yandex.testing.EntityWithSimpleProperties
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class SimplePropertiesTest {
private val case = EntityTemplateTestCase(
ctor = EntityWithSimpleProperties.Companion::invoke
)
@Test
fun `boolean as int`() {
val actual = case.parse(
directory = "simple_properties",
filename = "boolean_as_int.json"
)
// TODO: boolean property represented by integer value must fail
// Assert.assertNull(actual.boolean!!.evaluate(ExpressionResolver.EMPTY))
Assert.assertTrue(actual.boolean!!.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `boolean_int as boolean`() {
val actual = case.parse(
directory = "simple_properties",
filename = "boolean_int_as_boolean.json"
)
Assert.assertTrue(actual.booleanInt!!.evaluate(ExpressionResolver.EMPTY))
}
@Test
fun `boolean_int as int`() {
val actual = case.parse(
directory = "simple_properties",
filename = "boolean_int_as_int.json"
)
Assert.assertTrue(actual.booleanInt!!.evaluate(ExpressionResolver.EMPTY))
}
}
@@ -0,0 +1,84 @@
package com.yandex.generator
import com.yandex.div.json.ParsingException
import com.yandex.generator.ENTITY_WITH_STRICT_ARRAY
import com.yandex.generator.EntityTemplateTestCase
import com.yandex.testing.Entity
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class StrictArrayTest {
private val case = EntityTemplateTestCase(
ctor = Entity.Companion::invoke
)
@Test
fun `strict array is parsed correctly`() {
val actual = case.parse(
directory = "strict_array",
filename = "test_strict_array_happy_case.json"
)
assertEquals(ENTITY_WITH_STRICT_ARRAY, actual)
}
@Test
fun `referenced strict array is parsed correctly`() {
val actual = case.parse(
directory = "strict_array",
filename = "test_strict_array_happy_case_referenced.json"
)
assertEquals(ENTITY_WITH_STRICT_ARRAY, actual)
}
@Test(expected = ParsingException::class)
fun `strict array with non-object item parsing failed`() {
case.parse(
directory = "strict_array",
filename = "test_strict_array_with_non_object_item.json"
)
}
@Test(expected = ParsingException::class)
fun `referenced strict array with non-object item parsing failed`() {
case.parse(
directory = "strict_array",
filename = "test_referenced_strict_array_with_non_object_item.json"
)
}
@Test(expected = ParsingException::class)
fun `strict array with non-resolvable item parsing failed`() {
case.parse(
directory = "strict_array",
filename = "test_strict_array_with_non_resolvable_item.json"
)
}
@Test(expected = ParsingException::class)
fun `referenced strict array with non-resolvable item parsing failed`() {
case.parse(
directory = "strict_array",
filename = "test_referenced_strict_array_with_non_resolvable_item.json"
)
}
@Test(expected = ParsingException::class)
fun `strict array with non-object item reference parsing failed`() {
case.parse(
directory = "strict_array",
filename = "test_strict_array_with_non_object_item_ref.json"
)
}
@Test(expected = ParsingException::class)
fun `strict array with non-resolvable item reference parsing failed`() {
case.parse(
directory = "strict_array",
filename = "test_strict_array_with_non_resolvable_item_ref.json"
)
}
}
@@ -0,0 +1,70 @@
package com.yandex.generator
import com.yandex.div.json.ParsingException
import com.yandex.generator.ENTITY_WITH_STRING_ENUM_PROPERTY
import com.yandex.generator.EntityTemplateTestCase
import com.yandex.testing.Entity
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class StringEnumTest {
private val case = EntityTemplateTestCase(
ctor = Entity.Companion::invoke
)
@Test
fun `string enum property with reference is parsed correctly`() {
val actual = case.parse(
directory = "string_enum_property",
filename = "test_string_enum_property_with_link.json"
)
assertEquals(ENTITY_WITH_STRING_ENUM_PROPERTY, actual)
}
@Test
fun `string enum property without reference is parsed correctly`() {
val actual = case.parse(
directory = "string_enum_property",
filename = "test_string_enum_property_without_link.json"
)
assertEquals(ENTITY_WITH_STRING_ENUM_PROPERTY, actual)
}
@Test(expected = ParsingException::class)
fun `missing string enum property with reference parsing fails`() {
case.parse(
directory = "string_enum_property",
filename = "test_string_enum_property_with_link_missing_data.json"
)
}
@Test(expected = ParsingException::class)
fun `missing string enum property without reference parsing fails`() {
case.parse(
directory = "string_enum_property",
filename = "test_string_enum_property_without_link_missing_data.json"
)
}
@Test
fun `string enum property with override is parsed correctly`() {
val actual = case.parse(
directory = "string_enum_property",
filename = "test_string_enum_property_with_override.json"
)
assertEquals(ENTITY_WITH_STRING_ENUM_PROPERTY, actual)
}
@Test
fun `string enum property without template is parsed correctly`() {
val actual = case.parse(
directory = "string_enum_property",
filename = "test_string_enum_property_not_templated.json"
)
assertEquals(ENTITY_WITH_STRING_ENUM_PROPERTY, actual)
}
}
@@ -0,0 +1,11 @@
package com.yandex.generator
import android.app.Application
import com.yandex.div.core.util.Assert
class TestApplication : Application() {
init {
Assert.setEnabled(true)
}
}
@@ -0,0 +1,2 @@
sdk=28
application=com.yandex.generator.TestApplication
@@ -0,0 +1,8 @@
{
"lang": "kotlin",
"header": "// Generated code. Do not modify.\n\npackage com.yandex.testing\n\nimport android.graphics.Color\nimport android.net.Uri\nimport androidx.annotation.ColorInt\nimport com.yandex.div.json.*\nimport com.yandex.div.json.expressions.Expression\nimport com.yandex.div.json.expressions.ExpressionsList\nimport com.yandex.div.json.schema.*\nimport com.yandex.div.core.annotations.Mockable\nimport java.io.IOException\nimport java.util.BitSet\nimport org.json.JSONObject\n",
"kotlinAnnotations": [
"@Mockable"
],
"generateEquality": true
}
@@ -4,7 +4,6 @@ package com.yandex.div.json
import android.net.Uri
import com.yandex.div.evaluable.types.Color
import java.lang.ClassCastException
typealias Converter<T, R> = (T) -> R
@@ -17,8 +16,6 @@ internal inline fun <T, R> Converter<T, R?>.tryConvert(value: T): R? {
}
}
val BOOLEAN_TO_INT: Converter<Boolean, Int> = { value -> if (value) 1 else 0 }
val COLOR_INT_TO_STRING: Converter<Int, String> = { value -> Color(value).toString() }
val STRING_TO_COLOR_INT: Converter<Any?, Int?> = { value ->
when (value) {
@@ -32,7 +29,13 @@ val STRING_TO_COLOR_INT: Converter<Any?, Int?> = { value ->
val URI_TO_STRING: Converter<Uri, String> = { uri -> uri.toString() }
val STRING_TO_URI: Converter<String, Uri> = { value -> Uri.parse(value) }
val NUMBER_TO_BOOLEAN: Converter<Number, Boolean?> = { n -> n.toBoolean() }
val ANY_TO_BOOLEAN: Converter<Any, Boolean?> = { value ->
when (value) {
is Number -> value.toBoolean()
is Boolean -> value
else -> throw ClassCastException("Received value of wrong type")
}
}
val NUMBER_TO_DOUBLE: Converter<Number, Double> = { n: Number -> n.toDouble() }
val NUMBER_TO_INT: Converter<Number, Int> = { n: Number -> n.toInt() }
+1
View File
@@ -1,5 +1,6 @@
includeBuild('screenshot-test-plugin')
include ':api-generator-test'
include ':assertion'
include ':beacon'
include ':div'