mirror of
https://github.com/divkit/divkit.git
synced 2026-06-06 20:07:59 +00:00
289 lines
7.3 KiB
Swift
289 lines
7.3 KiB
Swift
@testable import LayoutKit
|
|
import VGSL
|
|
import XCTest
|
|
|
|
final class Array_UIViewRenderableTests: XCTestCase {
|
|
func test_AttachesViewsToParent() {
|
|
let parent = UIView(frame: .zero)
|
|
|
|
let views = [].reused(
|
|
with: [TestBlock(), TestBlock(), TestBlock()],
|
|
attachTo: parent,
|
|
observer: nil,
|
|
overscrollDelegate: nil,
|
|
renderingDelegate: nil
|
|
)
|
|
|
|
XCTAssertEqual(views, parent.subviews)
|
|
}
|
|
|
|
func test_BlocksOrderDefinesViewsOrder() {
|
|
let blocks = [TestBlock(), TestBlock(), TestBlock()]
|
|
|
|
let views = [].reused(
|
|
with: blocks,
|
|
attachTo: UIView(frame: .zero),
|
|
observer: nil,
|
|
overscrollDelegate: nil,
|
|
renderingDelegate: nil
|
|
)
|
|
|
|
let viewsBlocks = (views as! [TestView]).compactMap(\.block)
|
|
XCTAssertTrue(viewsBlocks.elementsEqual(blocks, by: ===))
|
|
}
|
|
|
|
func test_ReusesSuitableViews() {
|
|
let oldView0 = TestView(frame: .zero)
|
|
let oldView1 = TestView(frame: .zero)
|
|
|
|
let views = [oldView0, oldView1].reused(
|
|
with: [TestBlock(), OtherTestBlock(), TestBlock()],
|
|
attachTo: UIView(frame: .zero),
|
|
observer: nil,
|
|
overscrollDelegate: nil,
|
|
renderingDelegate: nil
|
|
)
|
|
|
|
XCTAssertEqual(3, views.count)
|
|
XCTAssertEqual(oldView0, views[0])
|
|
XCTAssertEqual(oldView1, views[2])
|
|
}
|
|
|
|
func test_NotReusesUnsuitableViews() {
|
|
let oldView0 = OtherTestView(frame: .zero)
|
|
let oldView1 = TestView(frame: .zero)
|
|
let oldView2 = TestView(frame: .zero)
|
|
|
|
let views = [oldView0, oldView1, oldView2].reused(
|
|
with: [TestBlock(), TestBlock(), TestBlock()],
|
|
attachTo: UIView(frame: .zero),
|
|
observer: nil,
|
|
overscrollDelegate: nil,
|
|
renderingDelegate: nil
|
|
)
|
|
|
|
XCTAssertEqual(3, views.count)
|
|
XCTAssertEqual(oldView1, views[0])
|
|
XCTAssertEqual(oldView2, views[1])
|
|
}
|
|
|
|
func test_ReordersReusedViews() {
|
|
let oldView0 = OtherTestView(frame: .zero)
|
|
let oldView1 = TestView(frame: .zero)
|
|
let oldView2 = TestView(frame: .zero)
|
|
|
|
let views = [oldView0, oldView1, oldView2].reused(
|
|
with: [TestBlock(), OtherTestBlock(), TestBlock()],
|
|
attachTo: UIView(frame: .zero),
|
|
observer: nil,
|
|
overscrollDelegate: nil,
|
|
renderingDelegate: nil
|
|
)
|
|
|
|
XCTAssertEqual([oldView1, oldView0, oldView2], views)
|
|
}
|
|
|
|
func test_ReconfiguresReusedViews() {
|
|
let block0 = TestBlock()
|
|
let block1 = TestBlock()
|
|
let block2 = TestBlock()
|
|
let oldView0 = TestView(frame: .zero)
|
|
oldView0.block = TestBlock()
|
|
let oldView1 = TestView(frame: .zero)
|
|
oldView1.block = TestBlock()
|
|
let oldView2 = TestView(frame: .zero)
|
|
oldView2.block = TestBlock()
|
|
|
|
let views = [oldView0, oldView1, oldView2].reused(
|
|
with: [block0, block1, block2],
|
|
attachTo: UIView(frame: .zero),
|
|
observer: nil,
|
|
overscrollDelegate: nil,
|
|
renderingDelegate: nil
|
|
)
|
|
|
|
XCTAssertEqual([oldView0, oldView1, oldView2], views)
|
|
XCTAssertTrue(block0 === oldView0.block)
|
|
XCTAssertTrue(block1 === oldView1.block)
|
|
XCTAssertTrue(block2 === oldView2.block)
|
|
}
|
|
|
|
func test_ReusesBestViewForReuse() {
|
|
let block0 = TestBlock()
|
|
let oldView0 = TestView(frame: .zero)
|
|
let oldView1 = TestView(frame: .zero)
|
|
let oldView2 = TestView(frame: .zero)
|
|
oldView2.block = block0
|
|
|
|
let views = [oldView0, oldView1, oldView2].reused(
|
|
with: [block0, TestBlock(), TestBlock()],
|
|
attachTo: UIView(frame: .zero),
|
|
observer: nil,
|
|
overscrollDelegate: nil,
|
|
renderingDelegate: nil
|
|
)
|
|
|
|
XCTAssertEqual([oldView2, oldView0, oldView1], views)
|
|
}
|
|
|
|
func test_BlocksReuseOrder() {
|
|
let blocks = [TestBlock(), TestBlock()]
|
|
let views = [TestView(frame: .zero), TestView(frame: .zero)]
|
|
for (block, view) in zip(blocks, views) {
|
|
view.block = block
|
|
}
|
|
|
|
let newBlocks = [TestBlock(), TestBlock()]
|
|
newBlocks[0].valuableContent = 2
|
|
|
|
let newViews = (views as [BlockView]).reused(
|
|
with: newBlocks,
|
|
attachTo: UIView(frame: .zero),
|
|
observer: nil,
|
|
overscrollDelegate: nil,
|
|
renderingDelegate: nil
|
|
)
|
|
|
|
XCTAssertEqual(newViews as! [TestView], views.reversed())
|
|
}
|
|
|
|
func test_PathHolderBlocksReuseOrder() {
|
|
let blocks = [TestBlock("path1"), TestBlock("path2")]
|
|
let views = [TestView(frame: .zero), TestView(frame: .zero)]
|
|
for (block, view) in zip(blocks, views) {
|
|
view.block = block
|
|
}
|
|
|
|
let newBlocks = [TestBlock("path1"), TestBlock("path2")]
|
|
newBlocks[0].valuableContent = 2
|
|
|
|
let newViews = (views as [BlockView]).reused(
|
|
with: newBlocks,
|
|
attachTo: UIView(frame: .zero),
|
|
observer: nil,
|
|
overscrollDelegate: nil,
|
|
renderingDelegate: nil
|
|
)
|
|
|
|
XCTAssertEqual(views, newViews as! [TestView])
|
|
}
|
|
|
|
func test_DecoratingBlockIsBestViewForReuse() {
|
|
let oldBlock = DecoratingBlock(
|
|
child: DecoratingBlock(
|
|
child: TestBlock("path1")
|
|
)
|
|
)
|
|
let view = DecoratingBlock.makeBlockView()
|
|
|
|
oldBlock.configureBlockView(
|
|
view,
|
|
observer: nil,
|
|
overscrollDelegate: nil,
|
|
renderingDelegate: nil
|
|
)
|
|
|
|
let newBlock = DecoratingBlock(
|
|
child: DecoratingBlock(
|
|
child: modified(TestBlock("path1")) { $0.valuableContent = 20 }
|
|
)
|
|
)
|
|
|
|
XCTAssertTrue(newBlock.isBestViewForReuse(view))
|
|
}
|
|
}
|
|
|
|
private class TestBlock: BlockWithTraits {
|
|
var widthTrait: LayoutKit.LayoutTrait = .resizable
|
|
var heightTrait: LayoutKit.LayoutTrait = .resizable
|
|
var intrinsicContentWidth: CGFloat = 0.0
|
|
|
|
var valuableContent = 1
|
|
|
|
let path: UIElementPath?
|
|
|
|
var debugDescription = ""
|
|
|
|
init(_ path: UIElementPath? = nil) {
|
|
self.path = path
|
|
}
|
|
|
|
static func makeBlockView() -> BlockView { TestView() }
|
|
|
|
func intrinsicContentHeight(forWidth _: CGFloat) -> CGFloat {
|
|
0.0
|
|
}
|
|
|
|
func equals(_ other: LayoutKit.Block) -> Bool {
|
|
guard let other = other as? TestBlock else {
|
|
return false
|
|
}
|
|
|
|
return other.valuableContent == valuableContent
|
|
}
|
|
|
|
func getImageHolders() -> [VGSLUI.ImageHolder] {
|
|
[]
|
|
}
|
|
|
|
func laidOut(for _: CGFloat) -> LayoutKit.Block {
|
|
self
|
|
}
|
|
|
|
func laidOut(for _: CGSize) -> LayoutKit.Block {
|
|
self
|
|
}
|
|
|
|
func updated(withStates _: LayoutKit.BlocksState) throws -> Self {
|
|
self
|
|
}
|
|
|
|
func isBestViewForReuse(_ view: BlockView) -> Bool {
|
|
if let path, path == ((view as? TestView)?.block as? TestBlock)?.path {
|
|
true
|
|
} else {
|
|
(view as? TestView)?.block == self
|
|
}
|
|
}
|
|
|
|
func canConfigureBlockView(_ view: BlockView) -> Bool {
|
|
view is TestView
|
|
}
|
|
|
|
func configureBlockView(
|
|
_ view: BlockView,
|
|
observer _: ElementStateObserver?,
|
|
overscrollDelegate _: ScrollDelegate?,
|
|
renderingDelegate _: RenderingDelegate?
|
|
) {
|
|
(view as! TestView).block = self
|
|
}
|
|
}
|
|
|
|
private final class TestView: BlockView, VisibleBoundsTrackingLeaf {
|
|
var block: TestBlock?
|
|
|
|
var effectiveBackgroundColor: UIColor? { backgroundColor }
|
|
}
|
|
|
|
private final class OtherTestBlock: UIViewRenderable {
|
|
init() {}
|
|
|
|
static func makeBlockView() -> BlockView { OtherTestView() }
|
|
|
|
func canConfigureBlockView(_ view: BlockView) -> Bool {
|
|
view is OtherTestView
|
|
}
|
|
|
|
func configureBlockView(
|
|
_: BlockView,
|
|
observer _: ElementStateObserver?,
|
|
overscrollDelegate _: ScrollDelegate?,
|
|
renderingDelegate _: RenderingDelegate?
|
|
) {}
|
|
}
|
|
|
|
private final class OtherTestView: BlockView, VisibleBoundsTrackingLeaf {
|
|
var effectiveBackgroundColor: UIColor? { backgroundColor }
|
|
}
|