mirror of
https://github.com/divkit/divkit.git
synced 2026-06-06 20:07:59 +00:00
Added array_set_value action
11883c3007bea2a24f07a4eecb29560e8fb4c786
This commit is contained in:
+4
-2
@@ -10315,8 +10315,7 @@
|
||||
"client/ios/DivKit.xcodeproj/xcshareddata/xcschemes/SnapshotTests.xcscheme":"divkit/public/client/ios/DivKit.xcodeproj/xcshareddata/xcschemes/SnapshotTests.xcscheme",
|
||||
"client/ios/DivKit.xcodeproj/xcshareddata/xcschemes/SnapshotTestsHostApp.xcscheme":"divkit/public/client/ios/DivKit.xcodeproj/xcshareddata/xcschemes/SnapshotTestsHostApp.xcscheme",
|
||||
"client/ios/DivKit.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme":"divkit/public/client/ios/DivKit.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme",
|
||||
"client/ios/DivKit/Actions/ArrayInsertValueActionHandler.swift":"divkit/public/client/ios/DivKit/Actions/ArrayInsertValueActionHandler.swift",
|
||||
"client/ios/DivKit/Actions/ArrayRemoveValueActionHandler.swift":"divkit/public/client/ios/DivKit/Actions/ArrayRemoveValueActionHandler.swift",
|
||||
"client/ios/DivKit/Actions/ArrayActionsHandler.swift":"divkit/public/client/ios/DivKit/Actions/ArrayActionsHandler.swift",
|
||||
"client/ios/DivKit/Actions/ClearFocusActionHandler.swift":"divkit/public/client/ios/DivKit/Actions/ClearFocusActionHandler.swift",
|
||||
"client/ios/DivKit/Actions/CopyToClipboardActionHandler.swift":"divkit/public/client/ios/DivKit/Actions/CopyToClipboardActionHandler.swift",
|
||||
"client/ios/DivKit/Actions/DictSetValueActionHandler.swift":"divkit/public/client/ios/DivKit/Actions/DictSetValueActionHandler.swift",
|
||||
@@ -10511,6 +10510,8 @@
|
||||
"client/ios/DivKit/generated_sources/DivActionArrayInsertValueTemplate.swift":"divkit/public/client/ios/DivKit/generated_sources/DivActionArrayInsertValueTemplate.swift",
|
||||
"client/ios/DivKit/generated_sources/DivActionArrayRemoveValue.swift":"divkit/public/client/ios/DivKit/generated_sources/DivActionArrayRemoveValue.swift",
|
||||
"client/ios/DivKit/generated_sources/DivActionArrayRemoveValueTemplate.swift":"divkit/public/client/ios/DivKit/generated_sources/DivActionArrayRemoveValueTemplate.swift",
|
||||
"client/ios/DivKit/generated_sources/DivActionArraySetValue.swift":"divkit/public/client/ios/DivKit/generated_sources/DivActionArraySetValue.swift",
|
||||
"client/ios/DivKit/generated_sources/DivActionArraySetValueTemplate.swift":"divkit/public/client/ios/DivKit/generated_sources/DivActionArraySetValueTemplate.swift",
|
||||
"client/ios/DivKit/generated_sources/DivActionClearFocus.swift":"divkit/public/client/ios/DivKit/generated_sources/DivActionClearFocus.swift",
|
||||
"client/ios/DivKit/generated_sources/DivActionClearFocusTemplate.swift":"divkit/public/client/ios/DivKit/generated_sources/DivActionClearFocusTemplate.swift",
|
||||
"client/ios/DivKit/generated_sources/DivActionCopyToClipboard.swift":"divkit/public/client/ios/DivKit/generated_sources/DivActionCopyToClipboard.swift",
|
||||
@@ -15978,6 +15979,7 @@
|
||||
"schema/div-accessibility.json":"divkit/public/schema/div-accessibility.json",
|
||||
"schema/div-action-array-insert-value.json":"divkit/public/schema/div-action-array-insert-value.json",
|
||||
"schema/div-action-array-remove-value.json":"divkit/public/schema/div-action-array-remove-value.json",
|
||||
"schema/div-action-array-set-value.json":"divkit/public/schema/div-action-array-set-value.json",
|
||||
"schema/div-action-base.json":"divkit/public/schema/div-action-base.json",
|
||||
"schema/div-action-clear-focus.json":"divkit/public/schema/div-action-clear-focus.json",
|
||||
"schema/div-action-copy-to-clipboard-content.json":"divkit/public/schema/div-action-copy-to-clipboard-content.json",
|
||||
|
||||
+79
-53
@@ -6,6 +6,7 @@ import com.yandex.div.internal.util.asList
|
||||
import com.yandex.div.json.expressions.ExpressionResolver
|
||||
import com.yandex.div2.DivActionArrayInsertValue
|
||||
import com.yandex.div2.DivActionArrayRemoveValue
|
||||
import com.yandex.div2.DivActionArraySetValue
|
||||
import com.yandex.div2.DivActionTyped
|
||||
import org.json.JSONArray
|
||||
import javax.inject.Inject
|
||||
@@ -20,21 +21,22 @@ internal class DivActionTypedArrayMutationHandler @Inject constructor()
|
||||
view: Div2View,
|
||||
resolver: ExpressionResolver,
|
||||
): Boolean = when (action) {
|
||||
|
||||
is DivActionTyped.ArrayInsertValue -> {
|
||||
handleInsert(action.value, view, resolver)
|
||||
handle(action.value, view, resolver)
|
||||
true
|
||||
}
|
||||
|
||||
is DivActionTyped.ArrayRemoveValue -> {
|
||||
handleRemove(action.value, view, resolver)
|
||||
handle(action.value, view, resolver)
|
||||
true
|
||||
}
|
||||
is DivActionTyped.ArraySetValue -> {
|
||||
handle(action.value, view, resolver)
|
||||
true
|
||||
}
|
||||
|
||||
else -> false
|
||||
}
|
||||
|
||||
private fun handleInsert(
|
||||
private fun handle(
|
||||
action: DivActionArrayInsertValue,
|
||||
view: Div2View,
|
||||
resolver: ExpressionResolver
|
||||
@@ -42,67 +44,91 @@ internal class DivActionTypedArrayMutationHandler @Inject constructor()
|
||||
val variableName = action.variableName.evaluate(resolver)
|
||||
val index = action.index?.evaluate(resolver)?.toInt()
|
||||
val newValue = action.value.evaluate(resolver)
|
||||
view.setVariable(variableName) { variable: Variable ->
|
||||
if (variable !is Variable.ArrayVariable) {
|
||||
view.logError(
|
||||
IllegalArgumentException("array_insert_value action requires array variable")
|
||||
)
|
||||
return@setVariable variable
|
||||
view.updateVariable(variableName) { array ->
|
||||
val length = array.length()
|
||||
when (index) {
|
||||
null, length -> array.mutate { add(newValue) }
|
||||
in 0 until length -> array.mutate { add(index, newValue) }
|
||||
else -> {
|
||||
view.logError(IndexOutOfBoundsException(
|
||||
"Index out of bound ($index) for mutation $variableName ($length)"
|
||||
))
|
||||
array
|
||||
}
|
||||
}
|
||||
|
||||
val value = variable.getValue() as? JSONArray
|
||||
if (value == null) {
|
||||
view.logError(IllegalArgumentException("Invalid variable value"))
|
||||
return@setVariable variable
|
||||
}
|
||||
|
||||
val length = value.length()
|
||||
when (val indexToInsert = index ?: length) {
|
||||
in 0..length -> variable.set(value.mutate { add(indexToInsert, newValue) })
|
||||
else -> view.logError(IndexOutOfBoundsException(
|
||||
"Index out of bound ($indexToInsert) for mutation ${variable.name} (${length})"
|
||||
))
|
||||
}
|
||||
return@setVariable variable
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleRemove(
|
||||
private fun handle(
|
||||
action: DivActionArrayRemoveValue,
|
||||
view: Div2View,
|
||||
resolver: ExpressionResolver
|
||||
) {
|
||||
val variableName = action.variableName.evaluate(resolver)
|
||||
val index = action.index.evaluate(resolver).toInt()
|
||||
view.setVariable(variableName) { variable: Variable ->
|
||||
if (variable !is Variable.ArrayVariable) {
|
||||
view.logError(
|
||||
IllegalArgumentException("array_remove_value action requires array variable")
|
||||
)
|
||||
return@setVariable variable
|
||||
}
|
||||
|
||||
val value = variable.getValue() as? JSONArray
|
||||
if (value == null) {
|
||||
view.logError(IllegalArgumentException("Invalid variable value"))
|
||||
return@setVariable variable
|
||||
}
|
||||
|
||||
val length = value.length()
|
||||
view.updateVariable(variableName) { array ->
|
||||
val length = array.length()
|
||||
when (index) {
|
||||
in 0 until length -> variable.set(value.mutate { removeAt(index) })
|
||||
else -> view.logError(IndexOutOfBoundsException(
|
||||
"Index out of bound ($index) for mutation ${variable.name} (${length})"
|
||||
))
|
||||
in 0 until length -> array.mutate { removeAt(index) }
|
||||
else -> {
|
||||
view.logError(IndexOutOfBoundsException(
|
||||
"Index out of bound ($index) for mutation $variableName ($length)"
|
||||
))
|
||||
array
|
||||
}
|
||||
}
|
||||
return@setVariable variable
|
||||
}
|
||||
}
|
||||
|
||||
private fun JSONArray.mutate(action: MutableList<Any>.() -> Unit): JSONArray {
|
||||
return asList<Any>()
|
||||
.toMutableList()
|
||||
.apply(action::invoke)
|
||||
.let(::JSONArray)
|
||||
private fun handle(
|
||||
action: DivActionArraySetValue,
|
||||
view: Div2View,
|
||||
resolver: ExpressionResolver
|
||||
) {
|
||||
val variableName = action.variableName.evaluate(resolver)
|
||||
val index = action.index.evaluate(resolver).toInt()
|
||||
val newValue = action.value.evaluate(resolver)
|
||||
view.updateVariable(variableName) { array ->
|
||||
val length = array.length()
|
||||
when (index) {
|
||||
in 0 until length -> array.mutate { this[index] = newValue }
|
||||
else -> {
|
||||
view.logError(IndexOutOfBoundsException(
|
||||
"Index out of bound ($index) for mutation $variableName ($length)"
|
||||
))
|
||||
array
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun JSONArray.mutate(action: MutableList<Any>.() -> Unit): JSONArray {
|
||||
return asList<Any>()
|
||||
.toMutableList()
|
||||
.apply(action::invoke)
|
||||
.let(::JSONArray)
|
||||
}
|
||||
|
||||
private fun Div2View.updateVariable(
|
||||
name: String,
|
||||
valueMutation: (JSONArray) -> JSONArray
|
||||
) {
|
||||
view.setVariable(name) { variable: Variable ->
|
||||
if (variable !is Variable.ArrayVariable) {
|
||||
view.logError(
|
||||
IllegalArgumentException("Action requires array variable")
|
||||
)
|
||||
return@setVariable variable
|
||||
}
|
||||
|
||||
val value = variable.getValue() as? JSONArray
|
||||
if (value == null) {
|
||||
view.logError(IllegalArgumentException("Invalid variable value"))
|
||||
return@setVariable variable
|
||||
}
|
||||
|
||||
variable.set(valueMutation(value))
|
||||
return@setVariable variable
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.yandex.div2.Div
|
||||
import com.yandex.div2.DivAction
|
||||
import com.yandex.div2.DivActionArrayInsertValue
|
||||
import com.yandex.div2.DivActionArrayRemoveValue
|
||||
import com.yandex.div2.DivActionArraySetValue
|
||||
import com.yandex.div2.DivActionDictSetValue
|
||||
import com.yandex.div2.DivActionSetVariable
|
||||
import com.yandex.div2.DivActionTyped
|
||||
@@ -184,6 +185,45 @@ class DivActionHandlerTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ArrayInsertValue action with index equal to length inserts value`() {
|
||||
setVariable("array_var", JSONArray().put("value 1"))
|
||||
|
||||
val isHandled = handleTypedAction(
|
||||
DivActionTyped.ArrayInsertValue(
|
||||
DivActionArrayInsertValue(
|
||||
index = Expression.constant(1),
|
||||
value = typedValue("new value"),
|
||||
variableName = Expression.constant("array_var")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
Assert.assertTrue(isHandled)
|
||||
|
||||
Assert.assertEquals(
|
||||
JSONArray().put("value 1").put("new value"),
|
||||
getVariableValue("array_var")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ArrayInsertValue action does not change original value`() {
|
||||
val array = JSONArray().put("value 1").put("value 2")
|
||||
setVariable("array_var", array)
|
||||
|
||||
handleTypedAction(
|
||||
DivActionTyped.ArrayInsertValue(
|
||||
DivActionArrayInsertValue(
|
||||
value = typedValue("new value"),
|
||||
variableName = Expression.constant("array_var")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
Assert.assertEquals(JSONArray().put("value 1").put("value 2"), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ArrayInsertValue action does nothing for invalid index`() {
|
||||
setVariable("array_var", JSONArray().put("value 1"))
|
||||
@@ -236,6 +276,23 @@ class DivActionHandlerTest {
|
||||
Assert.assertEquals(JSONArray().put("value 2"), getVariableValue("array_var"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ArrayRemoveValue action does not change original array`() {
|
||||
val array = JSONArray().put("value 1").put("value 2")
|
||||
setVariable("array_var", array)
|
||||
|
||||
handleTypedAction(
|
||||
DivActionTyped.ArrayRemoveValue(
|
||||
DivActionArrayRemoveValue(
|
||||
index = Expression.constant(0),
|
||||
variableName = Expression.constant("array_var")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
Assert.assertEquals(JSONArray().put("value 1").put("value 2"), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ArrayRemoveValue action does nothing for invalid index`() {
|
||||
setVariable("array_var", JSONArray().put("value 1"))
|
||||
@@ -270,6 +327,86 @@ class DivActionHandlerTest {
|
||||
Assert.assertEquals("value", getVariableValue("string_var"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ArraySetValue action sets value`() {
|
||||
setVariable("array_var", JSONArray().put("value 1").put("value 2"))
|
||||
|
||||
val isHandled = handleTypedAction(
|
||||
DivActionTyped.ArraySetValue(
|
||||
DivActionArraySetValue(
|
||||
index = Expression.constant(1),
|
||||
value = typedValue("new value"),
|
||||
variableName = Expression.constant("array_var")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
Assert.assertTrue(isHandled)
|
||||
|
||||
Assert.assertEquals(
|
||||
JSONArray().put("value 1").put("new value"),
|
||||
getVariableValue("array_var")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ArraySetValue action does not change original array`() {
|
||||
val array = JSONArray().put("value 1").put("value 2")
|
||||
setVariable("array_var", array)
|
||||
|
||||
handleTypedAction(
|
||||
DivActionTyped.ArraySetValue(
|
||||
DivActionArraySetValue(
|
||||
index = Expression.constant(1),
|
||||
value = typedValue("new value"),
|
||||
variableName = Expression.constant("array_var")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
Assert.assertEquals(JSONArray().put("value 1").put("value 2"), array)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ArraySetValue action does nothing for invalid index`() {
|
||||
setVariable("array_var", JSONArray().put("value 1").put("value 2"))
|
||||
|
||||
val isHandled = handleTypedAction(
|
||||
DivActionTyped.ArraySetValue(
|
||||
DivActionArraySetValue(
|
||||
index = Expression.constant(2),
|
||||
value = typedValue("new value"),
|
||||
variableName = Expression.constant("array_var")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
Assert.assertTrue(isHandled)
|
||||
|
||||
Assert.assertEquals(
|
||||
JSONArray().put("value 1").put("value 2"),
|
||||
getVariableValue("array_var")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ArraySetValue action does nothing for not array variable`() {
|
||||
setVariable("string_var", "value")
|
||||
|
||||
val isHandled = handleTypedAction(
|
||||
DivActionTyped.ArraySetValue(
|
||||
DivActionArraySetValue(
|
||||
index = Expression.constant(0),
|
||||
value = typedValue("new value"),
|
||||
variableName = Expression.constant("string_var")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
Assert.assertTrue(isHandled)
|
||||
Assert.assertEquals("value", getVariableValue("string_var"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `DictSetValue action removes value`() {
|
||||
setVariable("dict_var", JSONObject().put("key", "value"))
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
import Foundation
|
||||
|
||||
final class ArrayActionsHandler {
|
||||
func handle(_ action: DivActionArrayInsertValue, context: DivActionHandlingContext) {
|
||||
let expressionResolver = context.expressionResolver
|
||||
guard let variableName = action.resolveName(expressionResolver),
|
||||
let value = action.value.resolve(expressionResolver),
|
||||
var array = context.getVariableValue(variableName) else {
|
||||
return
|
||||
}
|
||||
|
||||
if let index = action.resolveIndex(expressionResolver) {
|
||||
guard index >= 0, index <= array.count else {
|
||||
DivKitLogger.error(
|
||||
"Failed to insert value in array \(variableName). Index out of bounds: \(index)."
|
||||
)
|
||||
return
|
||||
}
|
||||
array.insert(value, at: index)
|
||||
} else {
|
||||
array.append(value)
|
||||
}
|
||||
|
||||
context.setVariableValue(variableName, array)
|
||||
}
|
||||
|
||||
func handle(_ action: DivActionArrayRemoveValue, context: DivActionHandlingContext) {
|
||||
let expressionResolver = context.expressionResolver
|
||||
guard let variableName = action.resolveName(expressionResolver),
|
||||
let index = action.resolveIndex(expressionResolver),
|
||||
var array = context.getVariableValue(variableName) else {
|
||||
return
|
||||
}
|
||||
|
||||
guard index >= 0, index < array.count else {
|
||||
DivKitLogger.error(
|
||||
"Failed to remove value from array \(variableName). Index out of bounds: \(index)."
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
array.remove(at: index)
|
||||
context.setVariableValue(variableName, array)
|
||||
}
|
||||
|
||||
func handle(_ action: DivActionArraySetValue, context: DivActionHandlingContext) {
|
||||
let expressionResolver = context.expressionResolver
|
||||
guard let variableName = action.resolveName(expressionResolver),
|
||||
let index = action.resolveIndex(expressionResolver),
|
||||
let value = action.value.resolve(expressionResolver),
|
||||
var array = context.getVariableValue(variableName) else {
|
||||
return
|
||||
}
|
||||
|
||||
guard index >= 0, index < array.count else {
|
||||
DivKitLogger.error(
|
||||
"Failed to set value in array \(variableName). Index out of bounds: \(index)."
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
array[index] = value
|
||||
context.setVariableValue(variableName, array)
|
||||
}
|
||||
}
|
||||
|
||||
extension DivActionHandlingContext {
|
||||
fileprivate func getVariableValue(_ name: DivVariableName) -> [AnyHashable]? {
|
||||
variablesStorage.getVariableValue(cardId: cardId, name: name)
|
||||
}
|
||||
|
||||
fileprivate func setVariableValue(_ name: DivVariableName, _ value: [AnyHashable]) {
|
||||
variablesStorage.update(cardId: cardId, name: name, value: .array(value))
|
||||
}
|
||||
}
|
||||
|
||||
private protocol ArrayAction {
|
||||
func resolveVariableName(_ resolver: ExpressionResolver) -> String?
|
||||
}
|
||||
|
||||
extension ArrayAction {
|
||||
func resolveName(_ resolver: ExpressionResolver) -> DivVariableName? {
|
||||
if let name = resolveVariableName(resolver) {
|
||||
return DivVariableName(rawValue: name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
extension DivActionArrayInsertValue: ArrayAction {}
|
||||
|
||||
extension DivActionArrayRemoveValue: ArrayAction {}
|
||||
|
||||
extension DivActionArraySetValue: ArrayAction {}
|
||||
@@ -1,33 +0,0 @@
|
||||
import Foundation
|
||||
|
||||
final class ArrayInsertValueActionHandler {
|
||||
func handle(_ action: DivActionArrayInsertValue, context: DivActionHandlingContext) {
|
||||
let expressionResolver = context.expressionResolver
|
||||
guard let variableName = action.resolveVariableName(expressionResolver),
|
||||
let value = action.value.resolve(expressionResolver),
|
||||
var array: [AnyHashable] = context.variablesStorage.getVariableValue(
|
||||
cardId: context.cardId,
|
||||
name: DivVariableName(rawValue: variableName)
|
||||
) else {
|
||||
return
|
||||
}
|
||||
|
||||
if let index = action.resolveIndex(expressionResolver) {
|
||||
guard index >= 0, index <= array.count else {
|
||||
DivKitLogger.error(
|
||||
"Index out of bound \(index) for inserting value in \(variableName) with length \(array.count)"
|
||||
)
|
||||
return
|
||||
}
|
||||
array.insert(value, at: index)
|
||||
} else {
|
||||
array.append(value)
|
||||
}
|
||||
|
||||
context.variablesStorage.update(
|
||||
cardId: context.cardId,
|
||||
name: DivVariableName(rawValue: variableName),
|
||||
value: .array(array)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import Foundation
|
||||
|
||||
final class ArrayRemoveValueActionHandler {
|
||||
func handle(_ action: DivActionArrayRemoveValue, context: DivActionHandlingContext) {
|
||||
let expressionResolver = context.expressionResolver
|
||||
guard let variableName = action.resolveVariableName(expressionResolver),
|
||||
let index = action.resolveIndex(expressionResolver),
|
||||
var array: [AnyHashable] = context.variablesStorage.getVariableValue(
|
||||
cardId: context.cardId,
|
||||
name: DivVariableName(rawValue: variableName)
|
||||
) else {
|
||||
return
|
||||
}
|
||||
|
||||
guard index >= 0, index < array.count else {
|
||||
DivKitLogger.error(
|
||||
"Index out of bound \(index) for removing value of \(variableName) with length \(array.count)"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
array.remove(at: index)
|
||||
|
||||
context.variablesStorage.update(
|
||||
cardId: context.cardId,
|
||||
name: DivVariableName(rawValue: variableName),
|
||||
value: .array(array)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,7 @@ public final class DivActionHandler {
|
||||
private let updateCard: DivActionURLHandler.UpdateCardAction
|
||||
private let reporter: DivReporter
|
||||
|
||||
private let arrayInsertValueActionHandler = ArrayInsertValueActionHandler()
|
||||
private let arrayRemoveValueActionHandler = ArrayRemoveValueActionHandler()
|
||||
private let arrayActionsHandler = ArrayActionsHandler()
|
||||
private let dictSetValueActionHandler = DictSetValueActionHandler()
|
||||
private let clearFocusActionHandler = ClearFocusActionHandler()
|
||||
private let copyToClipboardActionHandler = CopyToClipboardActionHandler()
|
||||
@@ -135,9 +134,11 @@ public final class DivActionHandler {
|
||||
var isHandled = true
|
||||
switch action.typed {
|
||||
case let .divActionArrayInsertValue(action):
|
||||
arrayInsertValueActionHandler.handle(action, context: context)
|
||||
arrayActionsHandler.handle(action, context: context)
|
||||
case let .divActionArrayRemoveValue(action):
|
||||
arrayRemoveValueActionHandler.handle(action, context: context)
|
||||
arrayActionsHandler.handle(action, context: context)
|
||||
case let .divActionArraySetValue(action):
|
||||
arrayActionsHandler.handle(action, context: context)
|
||||
case let .divActionDictSetValue(action):
|
||||
dictSetValueActionHandler.handle(action, context: context)
|
||||
case .divActionClearFocus:
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// Generated code. Do not modify.
|
||||
|
||||
import CommonCorePublic
|
||||
import Foundation
|
||||
import Serialization
|
||||
|
||||
public final class DivActionArraySetValue {
|
||||
public static let type: String = "array_set_value"
|
||||
public let index: Expression<Int>
|
||||
public let value: DivTypedValue
|
||||
public let variableName: Expression<String>
|
||||
|
||||
public func resolveIndex(_ resolver: ExpressionResolver) -> Int? {
|
||||
resolver.resolveNumeric(index)
|
||||
}
|
||||
|
||||
public func resolveVariableName(_ resolver: ExpressionResolver) -> String? {
|
||||
resolver.resolveString(variableName)
|
||||
}
|
||||
|
||||
init(
|
||||
index: Expression<Int>,
|
||||
value: DivTypedValue,
|
||||
variableName: Expression<String>
|
||||
) {
|
||||
self.index = index
|
||||
self.value = value
|
||||
self.variableName = variableName
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
extension DivActionArraySetValue: Equatable {
|
||||
public static func ==(lhs: DivActionArraySetValue, rhs: DivActionArraySetValue) -> Bool {
|
||||
guard
|
||||
lhs.index == rhs.index,
|
||||
lhs.value == rhs.value,
|
||||
lhs.variableName == rhs.variableName
|
||||
else {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
extension DivActionArraySetValue: Serializable {
|
||||
public func toDictionary() -> [String: ValidSerializationValue] {
|
||||
var result: [String: ValidSerializationValue] = [:]
|
||||
result["type"] = Self.type
|
||||
result["index"] = index.toValidSerializationValue()
|
||||
result["value"] = value.toDictionary()
|
||||
result["variable_name"] = variableName.toValidSerializationValue()
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
// Generated code. Do not modify.
|
||||
|
||||
import CommonCorePublic
|
||||
import Foundation
|
||||
import Serialization
|
||||
|
||||
public final class DivActionArraySetValueTemplate: TemplateValue {
|
||||
public static let type: String = "array_set_value"
|
||||
public let parent: String?
|
||||
public let index: Field<Expression<Int>>?
|
||||
public let value: Field<DivTypedValueTemplate>?
|
||||
public let variableName: Field<Expression<String>>?
|
||||
|
||||
public convenience init(dictionary: [String: Any], templateToType: [TemplateName: String]) throws {
|
||||
self.init(
|
||||
parent: dictionary["type"] as? String,
|
||||
index: dictionary.getOptionalExpressionField("index"),
|
||||
value: dictionary.getOptionalField("value", templateToType: templateToType),
|
||||
variableName: dictionary.getOptionalExpressionField("variable_name")
|
||||
)
|
||||
}
|
||||
|
||||
init(
|
||||
parent: String?,
|
||||
index: Field<Expression<Int>>? = nil,
|
||||
value: Field<DivTypedValueTemplate>? = nil,
|
||||
variableName: Field<Expression<String>>? = nil
|
||||
) {
|
||||
self.parent = parent
|
||||
self.index = index
|
||||
self.value = value
|
||||
self.variableName = variableName
|
||||
}
|
||||
|
||||
private static func resolveOnlyLinks(context: TemplatesContext, parent: DivActionArraySetValueTemplate?) -> DeserializationResult<DivActionArraySetValue> {
|
||||
let indexValue = parent?.index?.resolveValue(context: context) ?? .noValue
|
||||
let valueValue = parent?.value?.resolveValue(context: context, useOnlyLinks: true) ?? .noValue
|
||||
let variableNameValue = parent?.variableName?.resolveValue(context: context) ?? .noValue
|
||||
var errors = mergeErrors(
|
||||
indexValue.errorsOrWarnings?.map { .nestedObjectError(field: "index", error: $0) },
|
||||
valueValue.errorsOrWarnings?.map { .nestedObjectError(field: "value", error: $0) },
|
||||
variableNameValue.errorsOrWarnings?.map { .nestedObjectError(field: "variable_name", error: $0) }
|
||||
)
|
||||
if case .noValue = indexValue {
|
||||
errors.append(.requiredFieldIsMissing(field: "index"))
|
||||
}
|
||||
if case .noValue = valueValue {
|
||||
errors.append(.requiredFieldIsMissing(field: "value"))
|
||||
}
|
||||
if case .noValue = variableNameValue {
|
||||
errors.append(.requiredFieldIsMissing(field: "variable_name"))
|
||||
}
|
||||
guard
|
||||
let indexNonNil = indexValue.value,
|
||||
let valueNonNil = valueValue.value,
|
||||
let variableNameNonNil = variableNameValue.value
|
||||
else {
|
||||
return .failure(NonEmptyArray(errors)!)
|
||||
}
|
||||
let result = DivActionArraySetValue(
|
||||
index: indexNonNil,
|
||||
value: valueNonNil,
|
||||
variableName: variableNameNonNil
|
||||
)
|
||||
return errors.isEmpty ? .success(result) : .partialSuccess(result, warnings: NonEmptyArray(errors)!)
|
||||
}
|
||||
|
||||
public static func resolveValue(context: TemplatesContext, parent: DivActionArraySetValueTemplate?, useOnlyLinks: Bool) -> DeserializationResult<DivActionArraySetValue> {
|
||||
if useOnlyLinks {
|
||||
return resolveOnlyLinks(context: context, parent: parent)
|
||||
}
|
||||
var indexValue: DeserializationResult<Expression<Int>> = parent?.index?.value() ?? .noValue
|
||||
var valueValue: DeserializationResult<DivTypedValue> = .noValue
|
||||
var variableNameValue: DeserializationResult<Expression<String>> = parent?.variableName?.value() ?? .noValue
|
||||
context.templateData.forEach { key, __dictValue in
|
||||
switch key {
|
||||
case "index":
|
||||
indexValue = deserialize(__dictValue).merged(with: indexValue)
|
||||
case "value":
|
||||
valueValue = deserialize(__dictValue, templates: context.templates, templateToType: context.templateToType, type: DivTypedValueTemplate.self).merged(with: valueValue)
|
||||
case "variable_name":
|
||||
variableNameValue = deserialize(__dictValue).merged(with: variableNameValue)
|
||||
case parent?.index?.link:
|
||||
indexValue = indexValue.merged(with: { deserialize(__dictValue) })
|
||||
case parent?.value?.link:
|
||||
valueValue = valueValue.merged(with: { deserialize(__dictValue, templates: context.templates, templateToType: context.templateToType, type: DivTypedValueTemplate.self) })
|
||||
case parent?.variableName?.link:
|
||||
variableNameValue = variableNameValue.merged(with: { deserialize(__dictValue) })
|
||||
default: break
|
||||
}
|
||||
}
|
||||
if let parent = parent {
|
||||
valueValue = valueValue.merged(with: { parent.value?.resolveValue(context: context, useOnlyLinks: true) })
|
||||
}
|
||||
var errors = mergeErrors(
|
||||
indexValue.errorsOrWarnings?.map { .nestedObjectError(field: "index", error: $0) },
|
||||
valueValue.errorsOrWarnings?.map { .nestedObjectError(field: "value", error: $0) },
|
||||
variableNameValue.errorsOrWarnings?.map { .nestedObjectError(field: "variable_name", error: $0) }
|
||||
)
|
||||
if case .noValue = indexValue {
|
||||
errors.append(.requiredFieldIsMissing(field: "index"))
|
||||
}
|
||||
if case .noValue = valueValue {
|
||||
errors.append(.requiredFieldIsMissing(field: "value"))
|
||||
}
|
||||
if case .noValue = variableNameValue {
|
||||
errors.append(.requiredFieldIsMissing(field: "variable_name"))
|
||||
}
|
||||
guard
|
||||
let indexNonNil = indexValue.value,
|
||||
let valueNonNil = valueValue.value,
|
||||
let variableNameNonNil = variableNameValue.value
|
||||
else {
|
||||
return .failure(NonEmptyArray(errors)!)
|
||||
}
|
||||
let result = DivActionArraySetValue(
|
||||
index: indexNonNil,
|
||||
value: valueNonNil,
|
||||
variableName: variableNameNonNil
|
||||
)
|
||||
return errors.isEmpty ? .success(result) : .partialSuccess(result, warnings: NonEmptyArray(errors)!)
|
||||
}
|
||||
|
||||
private func mergedWithParent(templates: [TemplateName: Any]) throws -> DivActionArraySetValueTemplate {
|
||||
guard let parent = parent, parent != Self.type else { return self }
|
||||
guard let parentTemplate = templates[parent] as? DivActionArraySetValueTemplate else {
|
||||
throw DeserializationError.unknownType(type: parent)
|
||||
}
|
||||
let mergedParent = try parentTemplate.mergedWithParent(templates: templates)
|
||||
|
||||
return DivActionArraySetValueTemplate(
|
||||
parent: nil,
|
||||
index: index ?? mergedParent.index,
|
||||
value: value ?? mergedParent.value,
|
||||
variableName: variableName ?? mergedParent.variableName
|
||||
)
|
||||
}
|
||||
|
||||
public func resolveParent(templates: [TemplateName: Any]) throws -> DivActionArraySetValueTemplate {
|
||||
let merged = try mergedWithParent(templates: templates)
|
||||
|
||||
return DivActionArraySetValueTemplate(
|
||||
parent: nil,
|
||||
index: merged.index,
|
||||
value: try merged.value?.resolveParent(templates: templates),
|
||||
variableName: merged.variableName
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import Serialization
|
||||
public enum DivActionTyped {
|
||||
case divActionArrayInsertValue(DivActionArrayInsertValue)
|
||||
case divActionArrayRemoveValue(DivActionArrayRemoveValue)
|
||||
case divActionArraySetValue(DivActionArraySetValue)
|
||||
case divActionClearFocus(DivActionClearFocus)
|
||||
case divActionCopyToClipboard(DivActionCopyToClipboard)
|
||||
case divActionDictSetValue(DivActionDictSetValue)
|
||||
@@ -20,6 +21,8 @@ public enum DivActionTyped {
|
||||
return value
|
||||
case let .divActionArrayRemoveValue(value):
|
||||
return value
|
||||
case let .divActionArraySetValue(value):
|
||||
return value
|
||||
case let .divActionClearFocus(value):
|
||||
return value
|
||||
case let .divActionCopyToClipboard(value):
|
||||
@@ -42,6 +45,8 @@ extension DivActionTyped: Equatable {
|
||||
return l == r
|
||||
case let (.divActionArrayRemoveValue(l), .divActionArrayRemoveValue(r)):
|
||||
return l == r
|
||||
case let (.divActionArraySetValue(l), .divActionArraySetValue(r)):
|
||||
return l == r
|
||||
case let (.divActionClearFocus(l), .divActionClearFocus(r)):
|
||||
return l == r
|
||||
case let (.divActionCopyToClipboard(l), .divActionCopyToClipboard(r)):
|
||||
|
||||
@@ -8,6 +8,7 @@ import Serialization
|
||||
public enum DivActionTypedTemplate: TemplateValue {
|
||||
case divActionArrayInsertValueTemplate(DivActionArrayInsertValueTemplate)
|
||||
case divActionArrayRemoveValueTemplate(DivActionArrayRemoveValueTemplate)
|
||||
case divActionArraySetValueTemplate(DivActionArraySetValueTemplate)
|
||||
case divActionClearFocusTemplate(DivActionClearFocusTemplate)
|
||||
case divActionCopyToClipboardTemplate(DivActionCopyToClipboardTemplate)
|
||||
case divActionDictSetValueTemplate(DivActionDictSetValueTemplate)
|
||||
@@ -20,6 +21,8 @@ public enum DivActionTypedTemplate: TemplateValue {
|
||||
return value
|
||||
case let .divActionArrayRemoveValueTemplate(value):
|
||||
return value
|
||||
case let .divActionArraySetValueTemplate(value):
|
||||
return value
|
||||
case let .divActionClearFocusTemplate(value):
|
||||
return value
|
||||
case let .divActionCopyToClipboardTemplate(value):
|
||||
@@ -39,6 +42,8 @@ public enum DivActionTypedTemplate: TemplateValue {
|
||||
return .divActionArrayInsertValueTemplate(try value.resolveParent(templates: templates))
|
||||
case let .divActionArrayRemoveValueTemplate(value):
|
||||
return .divActionArrayRemoveValueTemplate(try value.resolveParent(templates: templates))
|
||||
case let .divActionArraySetValueTemplate(value):
|
||||
return .divActionArraySetValueTemplate(try value.resolveParent(templates: templates))
|
||||
case let .divActionClearFocusTemplate(value):
|
||||
return .divActionClearFocusTemplate(try value.resolveParent(templates: templates))
|
||||
case let .divActionCopyToClipboardTemplate(value):
|
||||
@@ -78,6 +83,14 @@ public enum DivActionTypedTemplate: TemplateValue {
|
||||
case let .failure(errors): return .failure(errors)
|
||||
case .noValue: return .noValue
|
||||
}
|
||||
case let .divActionArraySetValueTemplate(value):
|
||||
let result = value.resolveValue(context: context, useOnlyLinks: useOnlyLinks)
|
||||
switch result {
|
||||
case let .success(value): return .success(.divActionArraySetValue(value))
|
||||
case let .partialSuccess(value, warnings): return .partialSuccess(.divActionArraySetValue(value), warnings: warnings)
|
||||
case let .failure(errors): return .failure(errors)
|
||||
case .noValue: return .noValue
|
||||
}
|
||||
case let .divActionClearFocusTemplate(value):
|
||||
let result = value.resolveValue(context: context, useOnlyLinks: useOnlyLinks)
|
||||
switch result {
|
||||
@@ -143,6 +156,14 @@ public enum DivActionTypedTemplate: TemplateValue {
|
||||
case let .failure(errors): return .failure(errors)
|
||||
case .noValue: return .noValue
|
||||
}
|
||||
case DivActionArraySetValue.type:
|
||||
let result = DivActionArraySetValueTemplate.resolveValue(context: context, useOnlyLinks: useOnlyLinks)
|
||||
switch result {
|
||||
case let .success(value): return .success(.divActionArraySetValue(value))
|
||||
case let .partialSuccess(value, warnings): return .partialSuccess(.divActionArraySetValue(value), warnings: warnings)
|
||||
case let .failure(errors): return .failure(errors)
|
||||
case .noValue: return .noValue
|
||||
}
|
||||
case DivActionClearFocus.type:
|
||||
let result = DivActionClearFocusTemplate.resolveValue(context: context, useOnlyLinks: useOnlyLinks)
|
||||
switch result {
|
||||
@@ -198,6 +219,8 @@ extension DivActionTypedTemplate {
|
||||
self = .divActionArrayInsertValueTemplate(try DivActionArrayInsertValueTemplate(dictionary: dictionary, templateToType: templateToType))
|
||||
case DivActionArrayRemoveValueTemplate.type:
|
||||
self = .divActionArrayRemoveValueTemplate(try DivActionArrayRemoveValueTemplate(dictionary: dictionary, templateToType: templateToType))
|
||||
case DivActionArraySetValueTemplate.type:
|
||||
self = .divActionArraySetValueTemplate(try DivActionArraySetValueTemplate(dictionary: dictionary, templateToType: templateToType))
|
||||
case DivActionClearFocusTemplate.type:
|
||||
self = .divActionClearFocusTemplate(try DivActionClearFocusTemplate(dictionary: dictionary, templateToType: templateToType))
|
||||
case DivActionCopyToClipboardTemplate.type:
|
||||
|
||||
@@ -53,17 +53,12 @@ final class DivActionHandlerTests: XCTestCase {
|
||||
func test_ArrayInsertValueAction_AppendsValue() {
|
||||
setVariableValue("array_var", .array([1, "two"]))
|
||||
|
||||
handle(
|
||||
divAction(
|
||||
logId: "test_log_id",
|
||||
typed: .divActionArrayInsertValue(
|
||||
DivActionArrayInsertValue(
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
)
|
||||
handle(.divActionArrayInsertValue(
|
||||
DivActionArrayInsertValue(
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual([1, "two", "new value"] as [AnyHashable], getVariableValue("array_var"))
|
||||
}
|
||||
@@ -71,55 +66,54 @@ final class DivActionHandlerTests: XCTestCase {
|
||||
func test_ArrayInsertValueAction_InsertsValue() {
|
||||
setVariableValue("array_var", .array([1, "two"]))
|
||||
|
||||
handle(
|
||||
divAction(
|
||||
logId: "test_log_id",
|
||||
typed: .divActionArrayInsertValue(
|
||||
DivActionArrayInsertValue(
|
||||
index: .value(1),
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
)
|
||||
handle(.divActionArrayInsertValue(
|
||||
DivActionArrayInsertValue(
|
||||
index: .value(1),
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual([1, "new value", "two"] as [AnyHashable], getVariableValue("array_var"))
|
||||
}
|
||||
|
||||
func test_ArrayInsertValueAction_WithIndexEqualLength_InsertsValue() {
|
||||
setVariableValue("array_var", .array(["one", "two"]))
|
||||
|
||||
handle(.divActionArrayInsertValue(
|
||||
DivActionArrayInsertValue(
|
||||
index: .value(2),
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual(["one", "two", "new value"], getVariableValue("array_var"))
|
||||
}
|
||||
|
||||
func test_ArrayInsertValueAction_DoesNothingForInvalidIndex() {
|
||||
setVariableValue("array_var", .array([1, "two"]))
|
||||
|
||||
handle(
|
||||
divAction(
|
||||
logId: "test_log_id",
|
||||
typed: .divActionArrayInsertValue(
|
||||
DivActionArrayInsertValue(
|
||||
index: .value(10),
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
)
|
||||
handle(.divActionArrayInsertValue(
|
||||
DivActionArrayInsertValue(
|
||||
index: .value(10),
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual([1, "two"] as [AnyHashable], getVariableValue("array_var"))
|
||||
}
|
||||
|
||||
func test_ArrayInsertValueAction__DoesNothingForDifferentTypeVar() {
|
||||
func test_ArrayInsertValueAction_DoesNothingForNotArrayVar() {
|
||||
setVariableValue("string_var", .string("value"))
|
||||
|
||||
handle(
|
||||
divAction(
|
||||
logId: "test_log_id",
|
||||
typed: .divActionArrayInsertValue(
|
||||
DivActionArrayInsertValue(
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("string_var")
|
||||
)
|
||||
)
|
||||
handle(.divActionArrayInsertValue(
|
||||
DivActionArrayInsertValue(
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("string_var")
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual("value", getVariableValue("string_var"))
|
||||
}
|
||||
@@ -127,17 +121,12 @@ final class DivActionHandlerTests: XCTestCase {
|
||||
func test_ArrayRemoveValueAction_RemovesValue() {
|
||||
setVariableValue("array_var", .array([1, "two"]))
|
||||
|
||||
handle(
|
||||
divAction(
|
||||
logId: "test_log_id",
|
||||
typed: .divActionArrayRemoveValue(
|
||||
DivActionArrayRemoveValue(
|
||||
index: .value(1),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
)
|
||||
handle(.divActionArrayRemoveValue(
|
||||
DivActionArrayRemoveValue(
|
||||
index: .value(1),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual([1] as [AnyHashable], getVariableValue("array_var"))
|
||||
}
|
||||
@@ -145,36 +134,81 @@ final class DivActionHandlerTests: XCTestCase {
|
||||
func test_ArrayRemoveValueAction_DoesNothingForInvalidIndex() {
|
||||
setVariableValue("array_var", .array([1, "two"]))
|
||||
|
||||
handle(
|
||||
divAction(
|
||||
logId: "test_log_id",
|
||||
typed: .divActionArrayRemoveValue(
|
||||
DivActionArrayRemoveValue(
|
||||
index: .value(10),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
)
|
||||
handle(.divActionArrayRemoveValue(
|
||||
DivActionArrayRemoveValue(
|
||||
index: .value(10),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual([1, "two"] as [AnyHashable], getVariableValue("array_var"))
|
||||
}
|
||||
|
||||
func test_ArrayRemoveValueAction_DoesNothingForNotArrayVar() {
|
||||
setVariableValue("string_var", .string("value"))
|
||||
|
||||
handle(.divActionArrayRemoveValue(
|
||||
DivActionArrayRemoveValue(
|
||||
index: .value(0),
|
||||
variableName: .value("string_var")
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual("value", getVariableValue("string_var"))
|
||||
}
|
||||
|
||||
func test_ArraySetValueAction_SetsValue() {
|
||||
setVariableValue("array_var", .array(["one", "two"]))
|
||||
|
||||
handle(.divActionArraySetValue(
|
||||
DivActionArraySetValue(
|
||||
index: .value(1),
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual(["one", "new value"], getVariableValue("array_var"))
|
||||
}
|
||||
|
||||
func test_ArraySetValueAction_DoesNothingForInvalidIndex() {
|
||||
setVariableValue("array_var", .array(["one", "two"]))
|
||||
|
||||
handle(.divActionArraySetValue(
|
||||
DivActionArraySetValue(
|
||||
index: .value(2),
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual(["one", "two"], getVariableValue("array_var"))
|
||||
}
|
||||
|
||||
func test_ArraySetValueAction_DoesNothingForNotArrayVar() {
|
||||
setVariableValue("string_var", .string("value"))
|
||||
|
||||
handle(.divActionArraySetValue(
|
||||
DivActionArraySetValue(
|
||||
index: .value(0),
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("string_var")
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual("value", getVariableValue("string_var"))
|
||||
}
|
||||
|
||||
func test_DictSetValueAction_AddsValue() {
|
||||
setVariableValue("dict_var", .dict([:]))
|
||||
|
||||
handle(
|
||||
divAction(
|
||||
logId: "test_log_id",
|
||||
typed: .divActionDictSetValue(
|
||||
DivActionDictSetValue(
|
||||
key: .value("key"),
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("dict_var")
|
||||
)
|
||||
)
|
||||
handle(.divActionDictSetValue(
|
||||
DivActionDictSetValue(
|
||||
key: .value("key"),
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("dict_var")
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual(["key": "new value"], getVariableValue("dict_var"))
|
||||
}
|
||||
@@ -182,18 +216,13 @@ final class DivActionHandlerTests: XCTestCase {
|
||||
func test_DictSetValueAction_UpdatesValue() {
|
||||
setVariableValue("dict_var", .dict(["key": "value"]))
|
||||
|
||||
handle(
|
||||
divAction(
|
||||
logId: "test_log_id",
|
||||
typed: .divActionDictSetValue(
|
||||
DivActionDictSetValue(
|
||||
key: .value("key"),
|
||||
value: .dictValue(DictValue(value: ["new_key": "new value"])),
|
||||
variableName: .value("dict_var")
|
||||
)
|
||||
)
|
||||
handle(.divActionDictSetValue(
|
||||
DivActionDictSetValue(
|
||||
key: .value("key"),
|
||||
value: .dictValue(DictValue(value: ["new_key": "new value"])),
|
||||
variableName: .value("dict_var")
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual(["key": ["new_key": "new value"]], getVariableValue("dict_var"))
|
||||
}
|
||||
@@ -201,36 +230,26 @@ final class DivActionHandlerTests: XCTestCase {
|
||||
func test_DictSetValueAction_RemovesValue() {
|
||||
setVariableValue("dict_var", .dict(["key": "value"]))
|
||||
|
||||
handle(
|
||||
divAction(
|
||||
logId: "test_log_id",
|
||||
typed: .divActionDictSetValue(
|
||||
DivActionDictSetValue(
|
||||
key: .value("key"),
|
||||
variableName: .value("dict_var")
|
||||
)
|
||||
)
|
||||
handle(.divActionDictSetValue(
|
||||
DivActionDictSetValue(
|
||||
key: .value("key"),
|
||||
variableName: .value("dict_var")
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual([String: AnyHashable](), getVariableValue("dict_var"))
|
||||
}
|
||||
|
||||
func test_DictSetValueAction_DoesNothingForDifferentTypeVar() {
|
||||
func test_DictSetValueAction_DoesNothingForNotDictVar() {
|
||||
setVariableValue("array_var", .array(["one", "two"]))
|
||||
|
||||
handle(
|
||||
divAction(
|
||||
logId: "test_log_id",
|
||||
typed: .divActionDictSetValue(
|
||||
DivActionDictSetValue(
|
||||
key: .value("key"),
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
)
|
||||
handle(.divActionDictSetValue(
|
||||
DivActionDictSetValue(
|
||||
key: .value("key"),
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual(["one", "two"], getVariableValue("array_var"))
|
||||
}
|
||||
@@ -238,17 +257,12 @@ final class DivActionHandlerTests: XCTestCase {
|
||||
func test_SetVariableAction_SetsStringVariable() {
|
||||
setVariableValue("string_var", .string("default"))
|
||||
|
||||
handle(
|
||||
divAction(
|
||||
logId: "test_log_id",
|
||||
typed: .divActionSetVariable(
|
||||
DivActionSetVariable(
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("string_var")
|
||||
)
|
||||
)
|
||||
handle(.divActionSetVariable(
|
||||
DivActionSetVariable(
|
||||
value: stringValue("new value"),
|
||||
variableName: .value("string_var")
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual("new value", getVariableValue("string_var"))
|
||||
}
|
||||
@@ -256,17 +270,12 @@ final class DivActionHandlerTests: XCTestCase {
|
||||
func test_SetVariableAction_SetsArrayVariable() {
|
||||
setVariableValue("array_var", .array([]))
|
||||
|
||||
handle(
|
||||
divAction(
|
||||
logId: "test_log_id",
|
||||
typed: .divActionSetVariable(
|
||||
DivActionSetVariable(
|
||||
value: .arrayValue(ArrayValue(value: .value(["value 1", "value 2"]))),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
)
|
||||
handle(.divActionSetVariable(
|
||||
DivActionSetVariable(
|
||||
value: .arrayValue(ArrayValue(value: .value(["value 1", "value 2"]))),
|
||||
variableName: .value("array_var")
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
XCTAssertEqual(["value 1", "value 2"], getVariableValue("array_var"))
|
||||
}
|
||||
@@ -314,10 +323,19 @@ final class DivActionHandlerTests: XCTestCase {
|
||||
)
|
||||
}
|
||||
|
||||
private func handle(_ action: DivActionTyped) {
|
||||
actionHandler.handle(
|
||||
divAction(logId: "log_id", typed: action),
|
||||
cardId: cardId,
|
||||
source: .tap,
|
||||
sender: nil
|
||||
)
|
||||
}
|
||||
|
||||
private func getVariableValue<T>(_ name: DivVariableName) -> T? {
|
||||
variablesStorage.makeVariables(for: cardId)[name]?.typedValue()
|
||||
}
|
||||
|
||||
|
||||
private func setVariableValue(_ name: DivVariableName, _ value: DivVariableValue) {
|
||||
variablesStorage.set(cardId: cardId, variables: [name: value])
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"type": "object",
|
||||
"$description": "translations.json#/div_action_array_set_value",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"array_set_value"
|
||||
]
|
||||
},
|
||||
"variable_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"index": {
|
||||
"type": "integer"
|
||||
},
|
||||
"value": {
|
||||
"$ref": "div-typed-value.json"
|
||||
}
|
||||
},
|
||||
"platforms": [
|
||||
"android",
|
||||
"ios"
|
||||
],
|
||||
"required": [
|
||||
"type",
|
||||
"variable_name",
|
||||
"index",
|
||||
"value"
|
||||
]
|
||||
}
|
||||
@@ -6,6 +6,9 @@
|
||||
{
|
||||
"$ref": "div-action-array-remove-value.json"
|
||||
},
|
||||
{
|
||||
"$ref": "div-action-array-set-value.json"
|
||||
},
|
||||
{
|
||||
"$ref": "div-action-clear-focus.json"
|
||||
},
|
||||
|
||||
@@ -43,6 +43,10 @@
|
||||
"en": "Deletes a value from the array",
|
||||
"ru": "Удаляет значение из массива"
|
||||
},
|
||||
"div_action_array_set_value": {
|
||||
"en": "Sets value in the array",
|
||||
"ru": "Устанавливает значение в массиве по индексу"
|
||||
},
|
||||
"div_action_base_download_callbacks": {
|
||||
"en": "Callbacks that are called after [data loading](../../interaction#loading-data).",
|
||||
"ru": "Колбэки, которые вызываются после [дозагрузки данных](../../interaction#loading-data)."
|
||||
|
||||
Reference in New Issue
Block a user