Added download action handler

commit_hash:356512da68f2ed46479425dd365d06a9ca266514
This commit is contained in:
pkurchatov
2025-01-24 19:45:13 +03:00
parent 0f88ae74ac
commit 93113c7bb3
17 changed files with 290 additions and 275 deletions
+1
View File
@@ -12665,6 +12665,7 @@
"client/ios/DivKit/Actions/DivActionURLHandler.swift":"divkit/public/client/ios/DivKit/Actions/DivActionURLHandler.swift",
"client/ios/DivKit/Actions/DivUrlHandler.swift":"divkit/public/client/ios/DivKit/Actions/DivUrlHandler.swift",
"client/ios/DivKit/Actions/DivVideoAction.swift":"divkit/public/client/ios/DivKit/Actions/DivVideoAction.swift",
"client/ios/DivKit/Actions/DownloadActionHandler.swift":"divkit/public/client/ios/DivKit/Actions/DownloadActionHandler.swift",
"client/ios/DivKit/Actions/FocusElementActionHandler.swift":"divkit/public/client/ios/DivKit/Actions/FocusElementActionHandler.swift",
"client/ios/DivKit/Actions/ScrollActionHandler.swift":"divkit/public/client/ios/DivKit/Actions/ScrollActionHandler.swift",
"client/ios/DivKit/Actions/ScrollMode.swift":"divkit/public/client/ios/DivKit/Actions/ScrollMode.swift",
@@ -3,6 +3,6 @@ import Foundation
final class ClearFocusActionHandler {
func handle(context: DivActionHandlingContext) {
context.blockStateStorage.clearFocus()
context.updateCard(.state(context.path.cardId))
context.updateCard(.state(context.cardId))
}
}
+103 -88
View File
@@ -15,7 +15,6 @@ public final class DivActionHandler {
typealias UpdateCardAction = (DivActionURLHandler.UpdateReason) -> Void
private let divActionURLHandler: DivActionURLHandler
private let urlHandler: DivUrlHandler
private let trackVisibility: TrackVisibility
private let trackDisappear: TrackVisibility
@@ -33,6 +32,7 @@ public final class DivActionHandler {
private let clearFocusActionHandler = ClearFocusActionHandler()
private let copyToClipboardActionHandler = CopyToClipboardActionHandler()
private let dictSetValueActionHandler = DictSetValueActionHandler()
private let downloadActionHandler: DownloadActionHandler
private let focusElementActionHandler = FocusElementActionHandler()
private let scrollActionHandler: ScrollActionHandler
private let setStateActionHandler: SetStateActionHandler
@@ -103,33 +103,6 @@ public final class DivActionHandler {
animatorController: DivAnimatorController,
flags: DivFlagsInfo
) {
let scrollActionHandler = ScrollActionHandler(
blockStateStorage: blockStateStorage,
updateCard: updateCard
)
self.scrollActionHandler = scrollActionHandler
let setStateActionHandler = SetStateActionHandler(stateUpdater: stateUpdater)
self.setStateActionHandler = setStateActionHandler
let timerActionHandler = TimerActionHandler(performer: performTimerAction)
self.timerActionHandler = timerActionHandler
let tooltipActionHandler = TooltipActionHandler(
performer: tooltipActionPerformer,
showTooltip: showTooltip
)
self.tooltipActionHandler = tooltipActionHandler
self.divActionURLHandler = DivActionURLHandler(
patchProvider: patchProvider,
updateCard: updateCard,
persistentValuesStorage: persistentValuesStorage,
scrollActionHandler: scrollActionHandler,
setStateActionHandler: setStateActionHandler,
timerActionHandler: timerActionHandler,
tooltipActionHandler: tooltipActionHandler
)
self.urlHandler = urlHandler
self.trackVisibility = trackVisibility
self.trackDisappear = trackDisappear
@@ -143,10 +116,24 @@ public final class DivActionHandler {
self.flags = flags
animatorActionHandler = AnimatorActionHandler(animatorController: animatorController)
downloadActionHandler = DownloadActionHandler(
patchProvider: patchProvider,
updateCard: updateCard
)
scrollActionHandler = ScrollActionHandler(
blockStateStorage: blockStateStorage,
updateCard: updateCard
)
setStateActionHandler = SetStateActionHandler(stateUpdater: stateUpdater)
setStoredValueActionHandler = SetStoredValueActionHandler(
persistentValuesStorage: persistentValuesStorage
)
submitActionHandler = SubmitActionHandler(submitter: submitter)
timerActionHandler = TimerActionHandler(performer: performTimerAction)
tooltipActionHandler = TooltipActionHandler(
performer: tooltipActionPerformer,
showTooltip: showTooltip
)
}
public func handle(
@@ -204,8 +191,9 @@ public final class DivActionHandler {
} else {
path
}
let info = action.resolveInfo(expressionResolver, path: path, source: source)
let context = DivActionHandlingContext(
path: path,
info: info,
expressionResolver: expressionResolver,
variablesStorage: variablesStorage,
blockStateStorage: blockStateStorage,
@@ -213,7 +201,6 @@ public final class DivActionHandler {
updateCard: updateCard
)
var isHandled = true
switch action.typed {
case let .divActionAnimatorStart(action):
animatorActionHandler.handle(action, context: context)
@@ -231,6 +218,8 @@ public final class DivActionHandler {
copyToClipboardActionHandler.handle(action, context: context)
case let .divActionDictSetValue(action):
dictSetValueActionHandler.handle(action, context: context)
case let .divActionDownload(action):
downloadActionHandler.handle(action, context: context)
case let .divActionFocusElement(action):
focusElementActionHandler.handle(action, context: context)
case let .divActionHideTooltip(action):
@@ -253,88 +242,114 @@ public final class DivActionHandler {
timerActionHandler.handle(action, context: context)
case let .divActionVideo(action):
videoActionHandler.handle(action, context: context)
case .divActionDownload:
break
case .none:
isHandled = false
handleUrl(action, context: context, sender: sender)
}
let logId = action.resolveLogId(expressionResolver) ?? ""
let logUrl = action.resolveLogUrl(expressionResolver)
let referer = action.resolveReferer(expressionResolver)
let divActionInfo = DivActionInfo(
path: path,
logId: logId,
url: action.resolveUrl(expressionResolver),
logUrl: logUrl,
referer: referer,
source: source,
payload: action.payload
)
if !isHandled {
handleUrl(
action,
info: divActionInfo,
context: context,
sender: sender
)
}
reporter.reportAction(
cardId: cardId,
info: divActionInfo
)
reporter.reportAction(cardId: cardId, info: info)
if source == .visibility {
trackVisibility(logId, cardId)
trackVisibility(info.logId, cardId)
} else if source == .disappear {
trackDisappear(logId, cardId)
trackDisappear(info.logId, cardId)
}
}
private func handleUrl(
_ action: DivActionBase,
info: DivActionInfo,
context: DivActionHandlingContext,
sender: AnyObject?
) {
guard let url = info.url else {
guard let url = context.info.url else {
return
}
let isDivActionURLHandled = divActionURLHandler.handleURL(
url,
info: info,
context: context,
completion: { [weak self] result in
guard let self else {
return
}
let callbackActions: [DivAction] = switch result {
case .success:
action.downloadCallbacks?.onSuccessActions ?? []
case .failure:
action.downloadCallbacks?.onFailActions ?? []
}
for action in callbackActions {
self.handle(
action,
path: info.path,
source: info.source,
sender: sender
if let intent = DivActionIntent(url: url) {
let cardId = context.cardId
switch intent {
case let .showTooltip(id, multiple):
let tooltipInfo = TooltipInfo(id: id, showsOnStart: false, multiple: multiple)
tooltipActionHandler.showTooltip(tooltipInfo)
case let .hideTooltip(id):
tooltipActionHandler.hideTooltip(id: id)
case let .download(patchUrl):
downloadActionHandler.handle(
url: patchUrl,
context: context,
onSuccessActions: action.downloadCallbacks?.onSuccessActions,
onFailActions: action.downloadCallbacks?.onFailActions
)
case let .setState(divStatePath, lifetime):
setStateActionHandler.handle(
divStatePath: divStatePath,
lifetime: lifetime,
context: context
)
case let .setVariable(name, value):
context.variablesStorage.update(
path: context.path,
name: DivVariableName(rawValue: name),
value: value
)
case let .setCurrentItem(id, index):
scrollActionHandler.scrollToItem(cardId: cardId, id: id, index: index)
case let .setNextItem(id, step, overflow):
scrollActionHandler.scrollToNextItem(
cardId: cardId,
id: id,
step: step,
overflow: overflow
)
case let .setPreviousItem(id, step, overflow):
scrollActionHandler.scrollToNextItem(
cardId: cardId,
id: id,
step: -step,
overflow: overflow
)
case let .scroll(id, mode):
switch mode {
case .start:
scrollActionHandler.scrollToStart(cardId: cardId, id: id)
case .end:
scrollActionHandler.scrollToEnd(cardId: cardId, id: id)
case let .forward(offset, overflow):
scrollActionHandler.scrollToOffset(
cardId: cardId,
id: id,
offset: offset,
isRelative: true,
overflow: overflow
)
case let .backward(offset, overflow):
scrollActionHandler.scrollToOffset(
cardId: cardId,
id: id,
offset: -offset,
isRelative: true,
overflow: overflow
)
case let .position(position):
scrollActionHandler.scrollToOffset(cardId: cardId, id: id, offset: position)
}
case let .video(id: id, action: action):
context.blockStateStorage.setState(
id: id,
cardId: cardId,
state: VideoBlockViewState(state: action == .play ? .playing : .paused)
)
context.updateCard(.state(cardId))
case let .timer(timerId, action):
timerActionHandler.handle(cardId: cardId, timerId: timerId, action: action)
case let .setStoredValue(storedValue):
persistentValuesStorage.set(value: storedValue)
}
)
if isDivActionURLHandled {
return
}
let info = context.info
if !flags.useUrlHandlerForVisibilityActions,
(info.source == .visibility || info.source == .disappear) {
info.source == .visibility || info.source == .disappear {
return
}
@@ -1,10 +1,18 @@
import LayoutKit
struct DivActionHandlingContext {
let path: UIElementPath
let info: DivActionInfo
let expressionResolver: ExpressionResolver
let variablesStorage: DivVariablesStorage
let blockStateStorage: DivBlockStateStorage
let actionHandler: DivActionHandler
let updateCard: DivActionHandler.UpdateCardAction
var cardId: DivCardID {
info.cardId
}
var path: UIElementPath {
info.path
}
}
@@ -1,10 +1,8 @@
import CoreGraphics
import Foundation
import LayoutKit
import VGSL
/// Deprecated. Use `DivActionHandler`.
public final class DivActionURLHandler {
public enum DivActionURLHandler {
@frozen
public enum UpdateReason {
case patch(DivCardID, DivPatch)
@@ -13,138 +11,4 @@ public final class DivActionURLHandler {
case variable([DivCardID: Set<DivVariableName>])
case external
}
private let patchProvider: DivPatchProvider
private let updateCard: DivActionHandler.UpdateCardAction
private let persistentValuesStorage: DivPersistentValuesStorage
private let setStateActionHandler: SetStateActionHandler
private let scrollActionHandler: ScrollActionHandler
private let timerActionHandler: TimerActionHandler
private let tooltipActionHandler: TooltipActionHandler
init(
patchProvider: DivPatchProvider,
updateCard: @escaping DivActionHandler.UpdateCardAction,
persistentValuesStorage: DivPersistentValuesStorage,
scrollActionHandler: ScrollActionHandler,
setStateActionHandler: SetStateActionHandler,
timerActionHandler: TimerActionHandler,
tooltipActionHandler: TooltipActionHandler
) {
self.patchProvider = patchProvider
self.updateCard = updateCard
self.persistentValuesStorage = persistentValuesStorage
self.setStateActionHandler = setStateActionHandler
self.scrollActionHandler = scrollActionHandler
self.timerActionHandler = timerActionHandler
self.tooltipActionHandler = tooltipActionHandler
}
func handleURL(
_ url: URL,
info: DivActionInfo,
context: DivActionHandlingContext,
completion: @escaping (Result<Void, Error>) -> Void = { _ in }
) -> Bool {
guard let intent = DivActionIntent(url: url) else {
return false
}
let cardId = info.path.cardId
switch intent {
case let .showTooltip(id, multiple):
let tooltipInfo = TooltipInfo(id: id, showsOnStart: false, multiple: multiple)
tooltipActionHandler.showTooltip(tooltipInfo)
case let .hideTooltip(id):
tooltipActionHandler.hideTooltip(id: id)
case let .download(patchUrl):
patchProvider.getPatch(
url: patchUrl,
info: info,
completion: { [unowned self] in
self.applyPatch(cardId: cardId, result: $0, completion: completion)
}
)
case let .setState(divStatePath, lifetime):
setStateActionHandler.handle(
divStatePath: divStatePath,
lifetime: lifetime,
context: context
)
case let .setVariable(name, value):
context.variablesStorage.update(
path: info.path,
name: DivVariableName(rawValue: name),
value: value
)
case let .setCurrentItem(id, index):
scrollActionHandler.scrollToItem(cardId: cardId, id: id, index: index)
case let .setNextItem(id, step, overflow):
scrollActionHandler.scrollToNextItem(
cardId: cardId,
id: id,
step: step,
overflow: overflow
)
case let .setPreviousItem(id, step, overflow):
scrollActionHandler.scrollToNextItem(
cardId: cardId,
id: id,
step: -step,
overflow: overflow
)
case let .scroll(id, mode):
switch mode {
case .start:
scrollActionHandler.scrollToStart(cardId: cardId, id: id)
case .end:
scrollActionHandler.scrollToEnd(cardId: cardId, id: id)
case let .forward(offset, overflow):
scrollActionHandler.scrollToOffset(
cardId: cardId,
id: id,
offset: offset,
isRelative: true,
overflow: overflow
)
case let .backward(offset, overflow):
scrollActionHandler.scrollToOffset(
cardId: cardId,
id: id,
offset: -offset,
isRelative: true,
overflow: overflow
)
case let .position(position):
scrollActionHandler.scrollToOffset(cardId: cardId, id: id, offset: position)
}
case let .video(id: id, action: action):
context.blockStateStorage.setState(
id: id,
cardId: cardId,
state: VideoBlockViewState(state: action == .play ? .playing : .paused)
)
context.updateCard(.state(cardId))
case let .timer(timerId, action):
timerActionHandler.handle(cardId: cardId, timerId: timerId, action: action)
case let .setStoredValue(storedValue):
persistentValuesStorage.set(value: storedValue)
}
return true
}
private func applyPatch(
cardId: DivCardID,
result: Result<DivPatch, Error>,
completion: @escaping (Result<Void, Error>) -> Void
) {
switch result {
case let .success(patch):
updateCard(.patch(cardId, patch))
completion(.success(()))
case let .failure(error):
completion(.failure(error))
}
}
}
@@ -0,0 +1,63 @@
import Foundation
import VGSL
final class DownloadActionHandler {
private let patchProvider: DivPatchProvider
private let updateCard: DivActionHandler.UpdateCardAction
init(
patchProvider: DivPatchProvider,
updateCard: @escaping DivActionHandler.UpdateCardAction
) {
self.patchProvider = patchProvider
self.updateCard = updateCard
}
func handle(_ action: DivActionDownload, context: DivActionHandlingContext) {
guard let urlString = action.resolveUrl(context.expressionResolver),
let url = URL(string: urlString) else {
return
}
handle(
url: url,
context: context,
onSuccessActions: action.onSuccessActions,
onFailActions: action.onFailActions
)
}
func handle(
url: URL,
context: DivActionHandlingContext,
onSuccessActions: [DivAction]?,
onFailActions: [DivAction]?
) {
let info = context.info
patchProvider.getPatch(
url: url,
info: info,
completion: { [weak self] in
guard let self else {
return
}
let callbackActions: [DivAction]
switch $0 {
case let .success(patch):
updateCard(.patch(info.cardId, patch))
callbackActions = onSuccessActions ?? []
case .failure:
callbackActions = onFailActions ?? []
}
for action in callbackActions {
context.actionHandler.handle(
action,
path: info.path,
source: .callback,
sender: nil
)
}
}
)
}
}
@@ -5,18 +5,16 @@ final class FocusElementActionHandler {
guard let elementId = action.resolveElementId(context.expressionResolver) else {
return
}
let cardId = context.path.cardId
let cardId = context.cardId
if let previousCard = context.blockStateStorage.getFocusedElement()?.cardId,
previousCard != cardId {
context.updateCard(.state(previousCard))
}
let element = IdAndCardId(id: elementId, cardId: cardId)
context.blockStateStorage.setFocused(
isFocused: true,
element: element
element: IdAndCardId(id: elementId, cardId: cardId)
)
context.updateCard(.state(cardId))
}
@@ -26,7 +26,7 @@ final class ScrollActionHandler {
}
let itemCount = action.resolveItemCount(expressionResolver)
let cardId = context.path.cardId
let cardId = context.cardId
if itemCount == 0 {
let offset = action.resolveOffset(expressionResolver)
scrollToOffset(
@@ -47,7 +47,7 @@ final class ScrollActionHandler {
return
}
let cardId = context.path.cardId
let cardId = context.cardId
switch action.destination {
case let .indexDestination(destination):
if let index = destination.resolveValue(expressionResolver) {
@@ -26,7 +26,7 @@ final class SetStateActionHandler {
lifetime: DivStateLifetime,
context: DivActionHandlingContext
) {
let cardId = context.path.cardId
let cardId = context.cardId
let fullStatePath: DivStatePath = if let tooltipId = context.path.tooltipId,
divStatePath.isLocal {
DivStatePath.makeDivStatePath(
@@ -20,7 +20,7 @@ final class SubmitActionHandler {
}
let containerData = context.variablesStorage.getVariables(
cardId: context.path.cardId,
cardId: context.cardId,
elementId: containerId
).map(
key: { $0.rawValue },
@@ -19,7 +19,7 @@ final class TimerActionHandler {
return
}
handle(cardId: context.path.cardId, timerId: id, action: command.toDivTimerAction())
handle(cardId: context.cardId, timerId: id, action: command.toDivTimerAction())
}
func handle(cardId: DivCardID, timerId: String, action: DivTimerAction) {
@@ -8,20 +8,17 @@ final class VideoActionHandler {
context: DivActionHandlingContext
) {
let expressionResolver = context.expressionResolver
guard let id = action.resolveId(expressionResolver),
let command = action.resolveAction(expressionResolver) else {
return
}
let cardId = context.path.cardId
let cardId = context.cardId
context.blockStateStorage.setState(
id: id,
cardId: cardId,
state: VideoBlockViewState(state: command == .start ? .playing : .paused)
)
context.updateCard(.state(cardId))
}
}
@@ -17,6 +17,22 @@ public protocol DivActionBase: Serializable {
}
extension DivActionBase {
func resolveInfo(
_ expressionResolver: ExpressionResolver,
path: UIElementPath,
source: UserInterfaceAction.DivActionSource
) -> DivActionInfo {
DivActionInfo(
path: path,
logId: resolveLogId(expressionResolver) ?? "",
url: resolveUrl(expressionResolver),
logUrl: resolveLogUrl(expressionResolver),
referer: resolveReferer(expressionResolver),
source: source,
payload: payload
)
}
func makeDivActionPayload(
path: UIElementPath,
source: UserInterfaceAction.DivActionSource,
@@ -4,6 +4,7 @@ import XCTest
final class DivActionHandlerTests: XCTestCase {
private var flags: DivFlagsInfo = .default
private var patchProvider = MockPatchProvider()
private let reporter = MockReporter()
private let stateManagement = DefaultDivStateManagement()
private let variablesStorage = DivVariablesStorage()
@@ -14,8 +15,10 @@ final class DivActionHandlerTests: XCTestCase {
return DivActionHandler(
flags: flags,
idToPath: idToPath,
patchProvider: patchProvider,
reporter: reporter,
stateManagement: stateManagement,
updateCard: { self.lastUpdateReason = $0 },
urlHandler: DivUrlHandlerDelegate { url, _ in
self.handledUrl = url
},
@@ -24,13 +27,11 @@ final class DivActionHandlerTests: XCTestCase {
}()
private var handledUrl: URL?
private var lastUpdateReason: DivActionURLHandler.UpdateReason?
func test_UrlPassedToUrlHandler() {
handle(
divAction(
logId: "test_log_id",
url: "https://some.url"
)
divAction(url: "https://some.url")
)
XCTAssertEqual(url("https://some.url"), handledUrl)
@@ -38,10 +39,7 @@ final class DivActionHandlerTests: XCTestCase {
func test_UrlNotPassedToUrlHandler_VisibilityAction() {
handle(
divAction(
logId: "test_log_id",
url: "https://some.url"
),
divAction(url: "https://some.url"),
source: .visibility
)
@@ -50,10 +48,7 @@ final class DivActionHandlerTests: XCTestCase {
func test_UrlNotPassedToUrlHandler_DisappearAction() {
handle(
divAction(
logId: "test_log_id",
url: "https://some.url"
),
divAction(url: "https://some.url"),
source: .disappear
)
@@ -64,10 +59,7 @@ final class DivActionHandlerTests: XCTestCase {
flags = DivFlagsInfo(useUrlHandlerForVisibilityActions: true)
handle(
divAction(
logId: "test_log_id",
url: "https://some.url"
),
divAction(url: "https://some.url"),
source: .visibility
)
@@ -77,7 +69,6 @@ final class DivActionHandlerTests: XCTestCase {
func test_UrlNotPassedToUrlHandler_IfTypedActionHandled() {
handle(
divAction(
logId: "test_log_id",
typed: .divActionSetVariable(
DivActionSetVariable(
value: stringValue("new value"),
@@ -95,10 +86,7 @@ final class DivActionHandlerTests: XCTestCase {
variablesStorage.set(cardId: cardId, variables: ["host": .string("test.url")])
handle(
divAction(
logId: "test_log_id",
urlExpression: "https://@{host}"
)
divAction(urlExpression: "https://@{host}")
)
XCTAssertEqual(url("https://test.url"), handledUrl)
@@ -108,10 +96,7 @@ final class DivActionHandlerTests: XCTestCase {
variablesStorage.set(cardId: cardId, variables: ["host": .string("test.url")])
handle(
divAction(
logId: "test_log_id",
urlExpression: "https://@{host}"
),
divAction(urlExpression: "https://@{host}"),
localValues: ["host": "localhost"]
)
@@ -304,7 +289,6 @@ final class DivActionHandlerTests: XCTestCase {
handle(
divAction(
logId: "log_id",
typed: .divActionDictSetValue(DivActionDictSetValue(
key: .value("key"),
value: .dictValue(DictValue(value: ["new_key": "new value"])),
@@ -347,10 +331,71 @@ final class DivActionHandlerTests: XCTestCase {
XCTAssertEqual(["one", "two"], getVariableValue("array_var"))
}
func test_DownloadAction_updateCardIsCalled() {
let expectedPatch = DivPatch(
changes: [
DivPatch.Change(id: "id", items: [ divText() ])
]
)
patchProvider = MockPatchProvider {
$0(.success(expectedPatch))
}
handle(.divActionDownload(
DivActionDownload(
onSuccessActions: [
divAction(url: "result://success"),
],
url: .value("https://download.url")
)
))
switch lastUpdateReason {
case let .patch(cardId, patch):
XCTAssertEqual("test_card", cardId)
XCTAssertEqual(expectedPatch, patch)
default:
XCTFail("UpdateReason.patch expected")
}
}
func test_DownloadAction_onSuccessActionIsCalled() {
patchProvider = MockPatchProvider {
$0(.success(DivPatch(changes: [])))
}
handle(.divActionDownload(
DivActionDownload(
onSuccessActions: [
divAction(url: "result://success"),
],
url: .value("https://download.url")
)
))
XCTAssertEqual(url("result://success"), handledUrl)
}
func test_DownloadAction_onFailActionIsCalled() {
patchProvider = MockPatchProvider {
$0(.failure(ExpressionError("Error")))
}
handle(.divActionDownload(
DivActionDownload(
onFailActions: [
divAction(url: "result://error"),
],
url: .value("https://download.url")
)
))
XCTAssertEqual(url("result://error"), handledUrl)
}
func test_SetStateAction_SetsState() {
handle(
divAction(
logId: "log_id",
typed: .divActionSetState(DivActionSetState(
stateId: .value("0/div_state/state1")
))
@@ -366,7 +411,6 @@ final class DivActionHandlerTests: XCTestCase {
func test_SetStateAction_InTooltip_SetsMainCardState() {
handle(
divAction(
logId: "log_id",
typed: .divActionSetState(DivActionSetState(
stateId: .value("0/div_state/state1")
))
@@ -383,7 +427,6 @@ final class DivActionHandlerTests: XCTestCase {
func test_SetStateAction_InTooltip_SetsTooltipState() {
handle(
divAction(
logId: "log_id",
typed: .divActionSetState(DivActionSetState(
stateId: .value("div_state_in_tooltip/state1")
))
@@ -450,7 +493,6 @@ final class DivActionHandlerTests: XCTestCase {
handle(
divAction(
logId: "log_id",
typed: .divActionSetVariable(DivActionSetVariable(
value: stringValue("new value"),
variableName: .value("local_var")
@@ -474,7 +516,6 @@ final class DivActionHandlerTests: XCTestCase {
handle(
divAction(
logId: "log_id",
scopeId: "element_id",
typed: .divActionSetVariable(DivActionSetVariable(
value: stringValue("new value"),
@@ -525,7 +566,7 @@ final class DivActionHandlerTests: XCTestCase {
private func handle(_ action: DivActionTyped) {
actionHandler.handle(
divAction(logId: "log_id", typed: action),
divAction(typed: action),
path: cardId.path,
source: .tap,
sender: nil
@@ -8,6 +8,7 @@ extension DivActionHandler {
blockStateStorage: DivBlockStateStorage = DivBlockStateStorage(),
flags: DivFlagsInfo = .default,
idToPath: IdToPath = IdToPath(),
patchProvider: DivPatchProvider = MockPatchProvider(),
persistentValuesStorage: DivPersistentValuesStorage = DivPersistentValuesStorage(),
reporter: DivReporter = DefaultDivReporter(),
stateManagement: DivStateManagement = DefaultDivStateManagement(),
@@ -18,7 +19,7 @@ extension DivActionHandler {
self.init(
stateUpdater: stateManagement,
blockStateStorage: blockStateStorage,
patchProvider: MockPatchProvider(),
patchProvider: patchProvider,
submitter: MockSubmitter(),
variablesStorage: variablesStorage,
functionsStorage: nil,
@@ -55,7 +56,17 @@ private final class MockSubmitter: DivSubmitter {
}
final class MockPatchProvider: DivPatchProvider {
func getPatch(url _: URL, completion _: @escaping DivPatchProviderCompletion) {}
private let delegate: (DivPatchProviderCompletion) -> Void
init(
delegate: @escaping (DivPatchProviderCompletion) -> Void = { _ in }
) {
self.delegate = delegate
}
func getPatch(url _: URL, completion: @escaping DivPatchProviderCompletion) {
delegate(completion)
}
func cancelRequests() {}
}
@@ -7,7 +7,7 @@ import VGSL
func divAction(
isEnabled: Bool = true,
logId: String,
logId: String = "test",
payload: [String: Any]? = nil,
scopeId: String? = nil,
typed: DivActionTyped? = nil,
+1
View File
@@ -29,6 +29,7 @@
},
"platforms": [
"android",
"ios",
"web"
],
"required": [