Support expressions with dict in schema

commit_hash:30fce799ccb23434f200edd0798b01f7c17754a7
This commit is contained in:
grechka62
2025-04-17 16:07:13 +03:00
parent 95381b6414
commit b61426304b
27 changed files with 237 additions and 49 deletions
+1
View File
@@ -20584,6 +20584,7 @@
"test_data/integration_test_data/local_functions_number.json":"divkit/public/test_data/integration_test_data/local_functions_number.json",
"test_data/integration_test_data/local_functions_string.json":"divkit/public/test_data/integration_test_data/local_functions_string.json",
"test_data/integration_test_data/local_functions_url.json":"divkit/public/test_data/integration_test_data/local_functions_url.json",
"test_data/integration_test_data/set_dict_variable.json":"divkit/public/test_data/integration_test_data/set_dict_variable.json",
"test_data/interactive_snapshot_test_data/div-action/array-variable-mutation.json":"divkit/public/test_data/interactive_snapshot_test_data/div-action/array-variable-mutation.json",
"test_data/interactive_snapshot_test_data/div-action/base.json":"divkit/public/test_data/interactive_snapshot_test_data/div-action/base.json",
"test_data/interactive_snapshot_test_data/div-action/focus-actions.json":"divkit/public/test_data/interactive_snapshot_test_data/div-action/focus-actions.json",
@@ -20,6 +20,7 @@ from ...schema.modeling.entities import (
Color,
String,
Dictionary,
RawObject,
RawArray,
StringEnumeration,
EntityEnumeration,
@@ -46,6 +47,8 @@ def update_property_type_base(property_type: PropertyType):
property_type.__class__ = DartColor
elif isinstance(property_type, Dictionary):
property_type.__class__ = DartDictionary
elif isinstance(property_type, RawObject):
property_type.__class__ = DartRawObject
elif isinstance(property_type, RawArray):
property_type.__class__ = DartRawArray
elif isinstance(property_type, Double):
@@ -208,7 +211,7 @@ class DartProperty(Property):
return f"safeParseBool{expr}({src},{fallback})"
elif isinstance(prop_type, (String, StaticString)):
return f"safeParseStr{expr}({src},{fallback})"
elif isinstance(prop_type, Dictionary):
elif isinstance(prop_type, (Dictionary, RawObject)):
return f"safeParseMap{expr}({src},{fallback})"
elif isinstance(prop_type, RawArray):
return f"safeParseList{expr}({src},{fallback})"
@@ -233,7 +236,7 @@ class DartProperty(Property):
strategy = "reqProp<bool>(safeParseBool(v),)"
elif isinstance(list_item_type, (String, StaticString)):
strategy = "reqProp<String>(safeParseStr(v),)"
elif isinstance(list_item_type, Dictionary):
elif isinstance(list_item_type, (Dictionary, RawObject)):
strategy = "reqProp<Obj>(safeParseMap(v),)"
elif isinstance(list_item_type, RawArray):
strategy = "reqProp<Arr>(safeParseList(v),)"
@@ -333,7 +336,7 @@ class DartPropertyType(PropertyType):
return 'String'
elif isinstance(self, Color):
return 'Color'
elif isinstance(self, Dictionary):
elif isinstance(self, (Dictionary, RawObject)):
return 'Obj'
elif isinstance(self, RawArray):
return 'Arr'
@@ -477,6 +480,10 @@ class DartDictionary(DartPropertyType, Dictionary):
pass
class DartRawObject(DartPropertyType, RawObject):
pass
class DartRawArray(DartPropertyType, RawArray):
pass
@@ -21,6 +21,7 @@ from ...schema.modeling.entities import (
Color,
String,
Dictionary,
RawObject,
RawArray,
DivanGeneratorProperties,
)
@@ -123,6 +124,8 @@ def update_property_type_base(property_type: PropertyType):
property_type.__class__ = DivanColor
elif isinstance(property_type, Dictionary):
property_type.__class__ = DivanDictionary
elif isinstance(property_type, RawObject):
property_type.__class__ = DivanRawObject
elif isinstance(property_type, RawArray):
property_type.__class__ = DivanRawArray
elif isinstance(property_type, Double):
@@ -628,7 +631,7 @@ class DivanPropertyType(PropertyType):
return 'Color'
elif isinstance(self, Url):
return 'Url'
elif isinstance(self, Dictionary):
elif isinstance(self, (Dictionary, RawObject)):
return 'Map<String, Any>'
elif isinstance(self, RawArray):
return 'List<Any>'
@@ -656,7 +659,7 @@ class DivanPropertyType(PropertyType):
def is_primitive(self) -> bool:
if isinstance(self, (Int, Double, Bool, BoolInt, String, StaticString, Color, Url, RawArray)):
return True
elif isinstance(self, (Dictionary, Array)):
elif isinstance(self, (Dictionary, RawObject, Array)):
return False
elif isinstance(self, Object):
inner_obj = self.object
@@ -690,6 +693,10 @@ class DivanDictionary(DivanPropertyType, Dictionary):
pass
class DivanRawObject(DivanPropertyType, RawObject):
pass
class DivanRawArray(DivanPropertyType, RawArray):
pass
@@ -14,6 +14,7 @@ from ...schema.modeling.entities import (
BoolInt,
Color,
Dictionary,
RawObject,
RawArray,
Double,
Int,
@@ -105,6 +106,8 @@ def update_property_type_base(property_type: PropertyType):
property_type.__class__ = DocumentationColor
elif isinstance(property_type, Dictionary):
property_type.__class__ = DocumentationDictionary
elif isinstance(property_type, RawObject):
property_type.__class__ = DocumentationRawObject
elif isinstance(property_type, RawArray):
property_type.__class__ = DocumentationRawArray
elif isinstance(property_type, Double):
@@ -263,6 +266,16 @@ class DocumentationColor(Color, DocumentationPropertyType):
class DocumentationDictionary(Dictionary, DocumentationPropertyType):
@property
def description(self) -> str:
return 'dictionary'
def constraints(self, dictionary: Dict[str, str]) -> str:
return ''
class DocumentationRawObject(RawObject, DocumentationPropertyType):
@property
def description(self) -> str:
return 'object'
@@ -271,7 +284,7 @@ class DocumentationDictionary(Dictionary, DocumentationPropertyType):
return ''
class DocumentationRawArray(Dictionary, DocumentationPropertyType):
class DocumentationRawArray(RawArray, DocumentationPropertyType):
@property
def description(self) -> str:
@@ -22,6 +22,7 @@ from ...schema.modeling.entities import (
Color,
String,
Dictionary,
RawObject,
RawArray,
ObjectFormat,
KotlinGeneratorProperties
@@ -73,6 +74,7 @@ class KotlinEntity(Entity):
Color.__bases__ = (KotlinPropertyType, PropertyType,)
String.__bases__ = (KotlinPropertyType, PropertyType,)
Dictionary.__bases__ = (KotlinPropertyType, PropertyType,)
RawObject.__bases__ = (KotlinPropertyType, PropertyType,)
RawArray.__bases__ = (KotlinPropertyType, PropertyType,)
for prop in self.properties:
prop.__class__ = KotlinProperty
@@ -1280,7 +1282,7 @@ class KotlinPropertyType(PropertyType):
args.append(f'{prop.declaration_name} = {declaration}')
args = ', '.join(args)
return wrap(f'{entity.resolved_prefixed_declaration}({args})')
elif isinstance(self, Dictionary):
elif isinstance(self, (Dictionary, RawObject)):
return wrap(f'JSONObject("""\n{default_value}\n""")')
else:
return None
@@ -1335,7 +1337,7 @@ class KotlinPropertyType(PropertyType):
return 'Boolean'
elif isinstance(self, String):
return 'CharSequence' if self.formatted else 'String'
elif isinstance(self, Dictionary):
elif isinstance(self, (Dictionary, RawObject)):
return 'JSONObject'
elif isinstance(self, RawArray):
return 'JSONArray'
@@ -1513,6 +1515,8 @@ class KotlinPropertyType(PropertyType):
return f'{prefix}INT'
elif isinstance(self, Double):
return f'{prefix}DOUBLE'
elif isinstance(self, Dictionary):
return f'{prefix}DICT'
elif isinstance(self, RawArray):
return f'{prefix}JSON_ARRAY'
elif isinstance(self, Array):
@@ -18,6 +18,7 @@ from ...schema.modeling.entities import (
Color,
String,
Dictionary,
RawObject,
RawArray
)
from ... import utils
@@ -47,6 +48,8 @@ def update_property_type_base(property_type: PropertyType):
property_type.__class__ = KotlinDSLColor
elif isinstance(property_type, Dictionary):
property_type.__class__ = KotlinDSLDictionary
elif isinstance(property_type, RawObject):
property_type.__class__ = KotlinDSLRawObject
elif isinstance(property_type, RawArray):
property_type.__class__ = KotlinDSLRawArray
elif isinstance(property_type, Double):
@@ -274,7 +277,7 @@ class KotlinDSLPropertyType(PropertyType):
return 'Color'
elif isinstance(self, Url):
return 'URI'
elif isinstance(self, Dictionary):
elif isinstance(self, (Dictionary, RawObject)):
return 'Map<String, Any>'
elif isinstance(self, RawArray):
return 'List<Any>'
@@ -322,6 +325,10 @@ class KotlinDSLDictionary(KotlinDSLPropertyType, Dictionary):
pass
class KotlinDSLRawObject(KotlinDSLPropertyType, RawObject):
pass
class KotlinDSLRawArray(KotlinDSLPropertyType, RawArray):
pass
@@ -11,6 +11,7 @@ from ...schema.modeling.entities import (
BoolInt,
Color,
Dictionary,
RawObject,
RawArray,
Double,
Int,
@@ -43,6 +44,8 @@ def update_property_type_base(property_type: PropertyType):
property_type.__class__ = PythonColor
elif isinstance(property_type, Dictionary):
property_type.__class__ = PythonDictionary
elif isinstance(property_type, RawObject):
property_type.__class__ = PythonRawObject
elif isinstance(property_type, RawArray):
property_type.__class__ = PythonRawArray
elif isinstance(property_type, Double):
@@ -288,7 +291,7 @@ class PythonPropertyType(PropertyType):
return 'str'
elif isinstance(self, StaticString):
raise TypeError(f'{self} is a static type')
elif isinstance(self, Dictionary):
elif isinstance(self, (Dictionary, RawObject)):
return 'typing.Dict[str, typing.Any]'
elif isinstance(self, RawArray):
return 'typing.Sequence[typing.Any]'
@@ -306,7 +309,7 @@ class PythonPropertyType(PropertyType):
@property
def constraints(self) -> str:
if isinstance(self, (Bool, BoolInt, Dictionary, RawArray)):
if isinstance(self, (Bool, BoolInt, Dictionary, RawObject, RawArray)):
return ''
elif isinstance(self, Array):
result = ''
@@ -358,6 +361,10 @@ class PythonDictionary(PythonPropertyType, Dictionary):
pass
class PythonRawObject(PythonPropertyType, RawObject):
pass
class PythonRawArray(PythonPropertyType, RawArray):
pass
@@ -15,6 +15,7 @@ from ... import utils
from ...schema.modeling.entities import (
Declarable,
Dictionary,
RawObject,
EntityEnumeration,
Entity,
Property,
@@ -290,7 +291,7 @@ class SwiftGenerator(Generator):
properties_to_declare = entity.properties_to_declare_swift
if properties_to_declare:
for prop in properties_to_declare:
if isinstance(prop.property_type, Dictionary) or isinstance(prop.property_type, RawArray):
if isinstance(prop.property_type, (Dictionary, RawObject, RawArray)):
sendable_conformance = '@unchecked Sendable'
protocols = list(filter(None, [entity.protocol_plus_super_entities(), sendable_conformance]))
conformance = f': {", ".join(protocols)}'
@@ -20,6 +20,7 @@ from ...schema.modeling.entities import (
Color,
String,
Dictionary,
RawObject,
RawArray,
ObjectFormat,
SwiftGeneratorProperties,
@@ -84,6 +85,7 @@ class SwiftEntity(Entity):
Color.__bases__ = (SwiftPropertyType, PropertyType,)
String.__bases__ = (SwiftPropertyType, PropertyType,)
Dictionary.__bases__ = (SwiftPropertyType, PropertyType,)
RawObject.__bases__ = (SwiftPropertyType, PropertyType,)
RawArray.__bases__ = (SwiftPropertyType, PropertyType,)
for prop in self.properties:
prop.__class__ = SwiftProperty
@@ -476,6 +478,8 @@ class SwiftProperty(Property):
return 'resolveNumeric'
elif isinstance(property_type, Object) and isinstance(property_type.object, StringEnumeration):
return 'resolveEnum'
elif isinstance(property_type, Dictionary):
return 'resolveDict'
elif isinstance(property_type, RawArray):
return 'resolveArray'
elif isinstance(property_type, Array):
@@ -678,7 +682,7 @@ class SwiftPropertyType(PropertyType):
return 'URL'
elif isinstance(self, Color):
return 'Color'
elif isinstance(self, Dictionary):
elif isinstance(self, (Dictionary, RawObject)):
return '[String: Any]'
elif isinstance(self, RawArray):
return '[Any]'
@@ -783,7 +787,7 @@ class SwiftPropertyType(PropertyType):
args.append(f'{prop.declaration_name}: {default_value}')
args = ', '.join(args)
return f'{entity.declaration_prefix}{utils.capitalize_camel_case(entity.original_name)}({args})'
elif isinstance(self, Dictionary):
elif isinstance(self, (Dictionary, RawObject)):
return f'(try! JSONSerialization.jsonObject(jsonString: """\n{default_value}\n""") as! [String: Any])'
else:
return None
@@ -806,7 +810,7 @@ class SwiftPropertyType(PropertyType):
@property
def is_equatable(self) -> bool:
if isinstance(self, (Dictionary, RawArray)):
if isinstance(self, (Dictionary, RawObject, RawArray)):
return False
elif isinstance(self, Array):
return cast(SwiftPropertyType, self.property_type).is_equatable
@@ -814,9 +818,9 @@ class SwiftPropertyType(PropertyType):
return True
def serialization_suffix(self, use_expressions: bool) -> str:
if isinstance(self, (Dictionary)):
if isinstance(self, RawObject):
return ''
elif isinstance(self, (String, Int, Double, Bool, BoolInt, RawArray)):
elif isinstance(self, (String, Int, Double, Bool, BoolInt, Dictionary, RawArray)):
return '.toValidSerializationValue()' if use_expressions else ''
elif isinstance(self, Object):
if isinstance(self.object, StringEnumeration):
@@ -16,6 +16,7 @@ from ...schema.modeling.entities import (
Color,
String,
Dictionary,
RawObject,
RawArray,
Declarable,
TypeScriptGeneratorProperties
@@ -67,7 +68,7 @@ def _type_script_type_name(property_type: PropertyType, supports_expressions: bo
return 'string'
elif isinstance(property_type, StaticString):
raise TypeError('Is a static type')
elif isinstance(property_type, Dictionary):
elif isinstance(property_type, (Dictionary, RawObject)):
return '{}'
elif isinstance(property_type, RawArray):
return 'unknown[]'
@@ -30,6 +30,7 @@ from .entities import (
Color,
String,
Dictionary,
RawObject,
BoolInt,
RawArray,
_build_documentation_generator_properties
@@ -276,9 +277,11 @@ def type_property_build(dictionary: Dict[str, any],
mode=mode,
config=config)
return Array(property_type=property_type, min_items=min_items), declarations
elif type_value == 'dict':
return Dictionary(), []
elif type_value == 'object':
if dictionary.get('additionalProperties', False) and 'properties' not in dictionary:
return Dictionary(), []
return RawObject(), []
entity: Entity = Entity(name=name,
original_name=outer_name,
dictionary=dictionary,
@@ -797,9 +797,9 @@ def default_value(lang: GeneratedLanguage,
class PropertyType(ABC):
@property
def supports_expressions(self) -> bool:
if isinstance(self, (Int, Double, Bool, BoolInt, String, Color, Url, RawArray)):
if isinstance(self, (Int, Double, Bool, BoolInt, String, Color, Url, RawArray, Dictionary)):
return True
elif isinstance(self, (Dictionary, StaticString)):
elif isinstance(self, (RawObject, StaticString)):
return False
elif isinstance(self, Array):
if isinstance(self.property_type, Object) and \
@@ -837,7 +837,7 @@ class PropertyType(ABC):
@property
def as_json(self) -> Dict:
if isinstance(self, (Int, Double, Bool, BoolInt, String, StaticString, Color, Url, Dictionary)):
if isinstance(self, (Int, Double, Bool, BoolInt, String, StaticString, Color, Url, Dictionary, RawObject)):
return {
'value': str(type(self).__name__)
}
@@ -907,6 +907,11 @@ class Dictionary(PropertyType):
pass
@dataclass
class RawObject(PropertyType):
pass
@dataclass
class RawArray(PropertyType):
min_items: int
@@ -3,6 +3,7 @@ package com.yandex.div.internal.parser
import android.graphics.Color
import android.net.Uri
import org.json.JSONArray
import org.json.JSONObject
interface TypeHelper<T> {
@@ -63,3 +64,9 @@ val TYPE_HELPER_JSON_ARRAY = object : TypeHelper<JSONArray> {
override val typeDefault = JSONArray()
override fun isTypeValid(value: Any) = value is JSONArray
}
@JvmField
val TYPE_HELPER_DICT = object : TypeHelper<JSONObject> {
override val typeDefault = JSONObject()
override fun isTypeValid(value: Any) = value is JSONObject
}
@@ -52,7 +52,7 @@ internal class DivActionTypedSetStoredValueHandler @Inject constructor() : DivAc
is DivTypedValue.Color -> StoredValue.ColorStoredValue(name, Color(value.value.value.evaluate(resolver)))
is DivTypedValue.Url -> StoredValue.UrlStoredValue(name, Url.from(value.value.value.evaluate(resolver).toString()))
is DivTypedValue.Array -> StoredValue.ArrayStoredValue(name, value.value.value.evaluate(resolver))
is DivTypedValue.Dict -> StoredValue.DictStoredValue(name, value.value.value)
is DivTypedValue.Dict -> StoredValue.DictStoredValue(name, value.value.value.evaluate(resolver))
}
}
@@ -31,7 +31,7 @@ internal fun DivTypedValue.evaluate(expressionResolver: ExpressionResolver): Any
is DivTypedValue.Number -> value.value.evaluate(expressionResolver)
is DivTypedValue.Url -> value.value.evaluate(expressionResolver)
is DivTypedValue.Array -> value.value.evaluate(expressionResolver)
is DivTypedValue.Dict -> value.value
is DivTypedValue.Dict -> value.value.evaluate(expressionResolver)
}
return newValue
}
@@ -46,7 +46,7 @@ internal fun DivTypedValue.longValue(expressionResolver: ExpressionResolver): Lo
internal fun DivTypedValue.doubleValue(expressionResolver: ExpressionResolver): Double? {
return when (this) {
is DivTypedValue.Integer -> value.value.evaluate(expressionResolver).toDouble()
is DivTypedValue.Number -> value.value.evaluate(expressionResolver).toDouble()
is DivTypedValue.Number -> value.value.evaluate(expressionResolver)
else -> null
}
}
@@ -33,8 +33,8 @@ object ExpressionTestCaseUtils {
private const val VALUE_TYPE_DATE_TIME = "datetime"
private const val VALUE_TYPE_URL = "url"
private const val VALUE_TYPE_COLOR = "color"
private const val VALUE_TYPE_DICT = "dict"
private const val VALUE_TYPE_ARRAY = "array"
const val VALUE_TYPE_DICT = "dict"
const val VALUE_TYPE_ARRAY = "array"
private const val VALUE_TYPE_UNIT = "unit"
private const val VALUE_TYPE_ERROR = "error"
private const val VALUE_TYPE_VARIABLE = "variable"
@@ -6,6 +6,8 @@ import com.yandex.div.DivDataTag
import com.yandex.div.core.Div2Context
import com.yandex.div.core.DivConfiguration
import com.yandex.div.core.expression.ExpressionTestCaseUtils
import com.yandex.div.core.expression.ExpressionTestCaseUtils.VALUE_TYPE_ARRAY
import com.yandex.div.core.expression.ExpressionTestCaseUtils.VALUE_TYPE_DICT
import com.yandex.div.core.expression.ExpressionTestCaseUtils.createVariable
import com.yandex.div.core.images.DivImageDownloadCallback
import com.yandex.div.core.images.DivImageLoader
@@ -53,8 +55,15 @@ class IntegrationMultiplatformTest(testCase: TestCaseOrError<IntegrationTestCase
logger.messages.contains(it.message)
)
}
is IntegrationTestCase.ExpectedResult.Variable ->
Assert.assertEquals(it.value, variableController.get(it.name)?.getValue())
is IntegrationTestCase.ExpectedResult.Variable -> {
val expectedValue = it.value
val actualValue = variableController.get(it.name)?.getValue()
if (it.type == VALUE_TYPE_DICT || it.type == VALUE_TYPE_ARRAY) {
Assert.assertEquals(expectedValue.toString(), actualValue.toString())
} else {
Assert.assertEquals(expectedValue, actualValue)
}
}
}
}
}
@@ -1,6 +1,7 @@
package com.yandex.div.interactive
import com.yandex.div.core.expression.ExpressionTestCaseUtils.getVariableValue
import com.yandex.div.core.expression.ExpressionTestCaseUtils.type
import com.yandex.div2.DivAction
import com.yandex.div2.DivData
import org.json.JSONObject
@@ -16,7 +17,7 @@ class IntegrationTestCase(
sealed interface ExpectedResult {
class Variable(val name: String, json: JSONObject): ExpectedResult {
val type: String = json.getString("type")
val type: String = json.type
val value = json.getVariableValue(type)
}
@@ -89,3 +89,14 @@ extension Expression where T: RawRepresentable, T.RawValue == String {
}
}
}
extension Expression where T == [String: Any] {
func toValidSerializationValue() -> ValidSerializationValue {
switch self {
case let .value(value):
value
case let .link(link):
link.rawValue
}
}
}
@@ -22,8 +22,9 @@ extension DivTypedValue {
}
return nil
case let .dictValue(value):
if let dictValue = DivDictionary.fromAny(value.value) {
return .dict(dictValue)
if let dictValue = value.resolveValue(expressionResolver),
let divDict = DivDictionary.fromAny(dictValue) {
return .dict(divDict)
}
return nil
case let .integerValue(value):
@@ -69,7 +70,10 @@ extension DivTypedValue {
}
return nil
case let .dictValue(value):
return DivDictionary.fromAny(value.value)
if let dictValue = value.resolveValue(expressionResolver) {
return DivDictionary.fromAny(dictValue)
}
return nil
case let .integerValue(value):
if let integerValue = value.resolveValue(expressionResolver) {
return integerValue
@@ -6,10 +6,14 @@ import VGSL
public final class DictValue: @unchecked Sendable {
public static let type: String = "dict"
public let value: [String: Any]
public let value: Expression<[String: Any]>
public func resolveValue(_ resolver: ExpressionResolver) -> [String: Any]? {
resolver.resolveDict(value)
}
init(
value: [String: Any]
value: Expression<[String: Any]>
) {
self.value = value
}
@@ -28,7 +32,7 @@ extension DictValue: Serializable {
public func toDictionary() -> [String: ValidSerializationValue] {
var result: [String: ValidSerializationValue] = [:]
result["type"] = Self.type
result["value"] = value
result["value"] = value.toValidSerializationValue()
return result
}
}
@@ -7,18 +7,18 @@ import VGSL
public final class DictValueTemplate: TemplateValue, @unchecked Sendable {
public static let type: String = "dict"
public let parent: String?
public let value: Field<[String: Any]>?
public let value: Field<Expression<[String: Any]>>?
public convenience init(dictionary: [String: Any], templateToType: [TemplateName: String]) throws {
self.init(
parent: dictionary["type"] as? String,
value: dictionary.getOptionalField("value")
value: dictionary.getOptionalExpressionField("value")
)
}
init(
parent: String?,
value: Field<[String: Any]>? = nil
value: Field<Expression<[String: Any]>>? = nil
) {
self.parent = parent
self.value = value
@@ -47,7 +47,7 @@ public final class DictValueTemplate: TemplateValue, @unchecked Sendable {
if useOnlyLinks {
return resolveOnlyLinks(context: context, parent: parent)
}
var valueValue: DeserializationResult<[String: Any]> = { parent?.value?.value() ?? .noValue }()
var valueValue: DeserializationResult<Expression<[String: Any]>> = { parent?.value?.value() ?? .noValue }()
_ = {
// Each field is parsed in its own lambda to keep the stack size managable
// Otherwise the compiler will allocate stack for each intermediate variable
@@ -247,7 +247,7 @@ final class DivActionHandlerTests: XCTestCase {
handle(.divActionArraySetValue(
DivActionArraySetValue(
index: .value(1),
value: .dictValue(DictValue(value: ["key1": "value", "key2": 123.45])),
value: dictValue(["key1": "value", "key2": 123.45]),
variableName: .value("array_var")
)
))
@@ -306,7 +306,7 @@ final class DivActionHandlerTests: XCTestCase {
handle(.divActionDictSetValue(
DivActionDictSetValue(
key: .value("key"),
value: .dictValue(DictValue(value: ["new_key": "new value"])),
value: dictValue(["new_key": "new value"]),
variableName: .value("dict_var")
)
))
@@ -325,7 +325,7 @@ final class DivActionHandlerTests: XCTestCase {
divAction(
typed: .divActionDictSetValue(DivActionDictSetValue(
key: .value("key"),
value: .dictValue(DictValue(value: ["new_key": "new value"])),
value: dictValue(["new_key": "new value"]),
variableName: .value("dict_var")
))
),
@@ -507,7 +507,7 @@ final class DivActionHandlerTests: XCTestCase {
let value: [String: Any] = ["key1": "value", "key2": 123.45, "nested": ["key": "value"]]
handle(.divActionSetVariable(
DivActionSetVariable(
value: .dictValue(DictValue(value: value)),
value: dictValue(value),
variableName: .value("dict_var")
)
))
@@ -621,6 +621,10 @@ private func stringValue(_ value: String) -> DivTypedValue {
.stringValue(StringValue(value: .value(value)))
}
private func dictValue(_ value: [String: Any]) -> DivTypedValue {
.dictValue(DictValue(value: .value(value)))
}
private let cardId: DivCardID = "test_card"
private final class MockReporter: DivReporter {
@@ -123,7 +123,7 @@ final class SetStoredValueActionHandlerTests: XCTestCase {
handle(
action(
name: "name",
value: .dictValue(DictValue(value: ["key": "value"]))
value: .dictValue(DictValue(value: .value(["key": "value"])))
)
)
+1 -2
View File
@@ -120,8 +120,7 @@
]
},
"value": {
"type": "object",
"additionalProperties": true
"type": "dict"
}
},
"required": [
+1 -2
View File
@@ -176,8 +176,7 @@
},
"value": {
"supports_expressions": false,
"type": "object",
"additionalProperties": true,
"type": "dict",
"$description": "translations.json#/div_variable_value"
}
},
@@ -0,0 +1,90 @@
{
"description": "Set dict variable from variable.",
"div_data": {
"card": {
"log_id": "dict_variable",
"variables": [
{
"name": "dict_var",
"type": "dict",
"value": {
"boolean": true,
"integer": 1,
"number": 1.0,
"string": "value"
}
}
],
"states": [
{
"state_id": 0,
"div": {
"type": "text",
"text": "text"
}
}
]
}
},
"cases": [
{
"div_actions": [
{
"log_id": "check usual action",
"url": "div-action://set_variable?name=result&value=@{dict_var}"
}
],
"expected": [
{
"type": "variable",
"variable_name": "result",
"value": {
"type": "dict",
"value": {
"boolean": true,
"integer": 1,
"number": 1.0,
"string": "value"
}
}
}
],
"platforms": [
"android"
]
},
{
"div_actions": [
{
"log_id": "check typed action",
"typed": {
"type": "set_variable",
"variable_name": "result",
"value": {
"type": "dict",
"value": "@{dict_var}"
}
}
}
],
"expected": [
{
"type": "variable",
"variable_name": "result",
"value": {
"type": "dict",
"value": {
"boolean": true,
"integer": 1,
"number": 1.0,
"string": "value"
}
}
}
],
"platforms": [
"android"
]
}
]
}