mirror of
https://github.com/divkit/divkit.git
synced 2026-06-06 20:07:59 +00:00
328 lines
8.8 KiB
Swift
328 lines
8.8 KiB
Swift
@testable import LayoutKit
|
|
import XCTest
|
|
|
|
final class BlockTooltipTests: XCTestCase {
|
|
private let tooltipSize = CGSize(width: 100.0, height: 100.0)
|
|
private let targetRect = CGRect(x: 50.0, y: 50.0, width: 200.0, height: 50.0)
|
|
private let boundsRect = CGRect(x: 0.0, y: 0.0, width: 300.0, height: 500.0)
|
|
|
|
private var testCaseOffsets: [CGPoint] {
|
|
[
|
|
CGPoint(x: 0.0, y: 0.0), // fits
|
|
CGPoint(x: tooltipSize.width, y: 0.0), // doesn't fit horisontally
|
|
CGPoint(x: -tooltipSize.width, y: 0.0), // doesn't fit horisontally
|
|
CGPoint(x: 0.0, y: tooltipSize.height), // doesn't fit vertically
|
|
CGPoint(x: 0.0, y: -tooltipSize.height), // doesn't fit vertically
|
|
]
|
|
}
|
|
|
|
func test_TooltipThatFitsCalculation() {
|
|
for (index, offset) in testCaseOffsets.enumerated() {
|
|
let tooltip = makeTooltip(
|
|
offset: offset,
|
|
block: EmptyBlock(
|
|
widthTrait: .fixed(tooltipSize.width),
|
|
heightTrait: .fixed(tooltipSize.height)
|
|
)
|
|
)
|
|
|
|
let resultRect = tooltip.calculateFrame(
|
|
targeting: targetRect,
|
|
constrainedBy: boundsRect
|
|
)
|
|
|
|
XCTAssertTrue(
|
|
resultRect.isInside(boundsRect),
|
|
"The tooltip with offset \(index) doesn't fit on the screen"
|
|
)
|
|
}
|
|
}
|
|
|
|
func test_TooltipWindowClose() {
|
|
let tooltipView = TooltipContainerView(
|
|
tooltip: DefaultTooltipManager.Tooltip(
|
|
params: BlockTooltipParams(
|
|
id: "tooltip",
|
|
mode: .modal,
|
|
duration: 0,
|
|
closeByTapOutside: true
|
|
),
|
|
view: TestView(),
|
|
substrateView: nil,
|
|
bringToTopId: nil
|
|
),
|
|
handleAction: { _ in },
|
|
onCloseAction: {},
|
|
getViewById: { _ in nil }
|
|
)
|
|
|
|
let mainView = UIView()
|
|
mainView.addSubview(tooltipView)
|
|
|
|
tooltipView.bounds = CGRect(
|
|
x: 0.0, y: 0.0,
|
|
width: 20.0, height: 20.0
|
|
)
|
|
tooltipView.forceLayout()
|
|
XCTAssertEqual(tooltipView.superview, mainView)
|
|
|
|
tooltipView.bounds = CGRect(
|
|
x: 0.0, y: 0.0,
|
|
width: 100.0, height: 100.0
|
|
)
|
|
tooltipView.forceLayout()
|
|
|
|
let predicate = NSPredicate { _, _ in
|
|
tooltipView.superview == nil
|
|
}
|
|
|
|
let expectSuperviewChange = expectation(for: predicate, evaluatedWith: nil)
|
|
wait(for: [expectSuperviewChange], timeout: 2)
|
|
}
|
|
|
|
func test_TooltipWithSubstrateView() {
|
|
let substrateView = TestView()
|
|
let tooltipView = TooltipContainerView(
|
|
tooltip: DefaultTooltipManager.Tooltip(
|
|
params: BlockTooltipParams(
|
|
id: "tooltip_with_substrate",
|
|
mode: .modal,
|
|
duration: 0,
|
|
closeByTapOutside: true
|
|
),
|
|
view: TestView(),
|
|
substrateView: substrateView,
|
|
bringToTopId: nil
|
|
),
|
|
handleAction: { _ in },
|
|
onCloseAction: {},
|
|
getViewById: { _ in nil }
|
|
)
|
|
|
|
let mainView = UIView()
|
|
mainView.addSubview(tooltipView)
|
|
|
|
tooltipView.bounds = CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0)
|
|
tooltipView.forceLayout()
|
|
|
|
XCTAssertEqual(
|
|
tooltipView.subviews.first,
|
|
substrateView,
|
|
"Substrate view should be first subview (below tooltip)"
|
|
)
|
|
|
|
XCTAssertEqual(
|
|
substrateView.frame,
|
|
tooltipView.bounds,
|
|
"Substrate view should fill the entire container"
|
|
)
|
|
}
|
|
|
|
func test_GetViewById_ReturnsView_CreatesSnapshot() {
|
|
let targetView = TestView()
|
|
targetView.frame = CGRect(x: 10.0, y: 20.0, width: 50.0, height: 30.0)
|
|
|
|
var getViewByIdCallCount = 0
|
|
|
|
let substrateView = TestView()
|
|
let tooltipView = TooltipContainerView(
|
|
tooltip: DefaultTooltipManager.Tooltip(
|
|
params: BlockTooltipParams(
|
|
id: "tooltip",
|
|
mode: .modal,
|
|
duration: 0,
|
|
closeByTapOutside: true
|
|
),
|
|
view: TestView(),
|
|
substrateView: substrateView,
|
|
bringToTopId: "target_view"
|
|
),
|
|
handleAction: { _ in },
|
|
onCloseAction: {},
|
|
getViewById: { viewId in
|
|
getViewByIdCallCount += 1
|
|
if viewId.rawValue == "target_view" {
|
|
return targetView
|
|
}
|
|
return nil
|
|
}
|
|
)
|
|
|
|
let mainView = UIView()
|
|
mainView.addSubview(tooltipView)
|
|
tooltipView.bounds = CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0)
|
|
tooltipView.forceLayout()
|
|
|
|
XCTAssertEqual(
|
|
tooltipView.subviews.count,
|
|
3,
|
|
"Should have substrate, snapshot, and tooltip views"
|
|
)
|
|
XCTAssertEqual(getViewByIdCallCount, 1)
|
|
XCTAssertTrue(tooltipView.subviews[0] === substrateView, "First subview should be substrate")
|
|
XCTAssertTrue(
|
|
tooltipView.subviews[1] !== targetView,
|
|
"Second subview should be snapshot, not original view"
|
|
)
|
|
XCTAssertFalse(
|
|
tooltipView.subviews[1].isUserInteractionEnabled,
|
|
"Snapshot should not be user-interactive"
|
|
)
|
|
}
|
|
|
|
func test_BringToTopId_WithoutSubstrateView_DoesNotCreateSnapshot() {
|
|
let targetView = TestView()
|
|
targetView.frame = CGRect(x: 10.0, y: 20.0, width: 50.0, height: 30.0)
|
|
|
|
var getViewByIdCallCount = 0
|
|
|
|
let tooltipView = TooltipContainerView(
|
|
tooltip: DefaultTooltipManager.Tooltip(
|
|
params: BlockTooltipParams(
|
|
id: "tooltip",
|
|
mode: .modal,
|
|
duration: 0,
|
|
closeByTapOutside: true
|
|
),
|
|
view: TestView(),
|
|
substrateView: nil,
|
|
bringToTopId: "target_view"
|
|
),
|
|
handleAction: { _ in },
|
|
onCloseAction: {},
|
|
getViewById: { viewId in
|
|
getViewByIdCallCount += 1
|
|
if viewId.rawValue == "target_view" {
|
|
return targetView
|
|
}
|
|
return nil
|
|
}
|
|
)
|
|
|
|
let mainView = UIView()
|
|
mainView.addSubview(tooltipView)
|
|
tooltipView.bounds = CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0)
|
|
tooltipView.forceLayout()
|
|
|
|
XCTAssertEqual(
|
|
getViewByIdCallCount,
|
|
0,
|
|
"getViewById should not be called without substrate view"
|
|
)
|
|
XCTAssertEqual(tooltipView.subviews.count, 1, "Should only have tooltip view")
|
|
}
|
|
|
|
func test_BringToTopId_NilValue_DoesNotCallGetViewById() {
|
|
var getViewByIdCallCount = 0
|
|
|
|
let substrateView = TestView()
|
|
let tooltipView = TooltipContainerView(
|
|
tooltip: DefaultTooltipManager.Tooltip(
|
|
params: BlockTooltipParams(
|
|
id: "tooltip",
|
|
mode: .modal,
|
|
duration: 0,
|
|
closeByTapOutside: true
|
|
),
|
|
view: TestView(),
|
|
substrateView: substrateView,
|
|
bringToTopId: nil
|
|
),
|
|
handleAction: { _ in },
|
|
onCloseAction: {},
|
|
getViewById: { _ in
|
|
getViewByIdCallCount += 1
|
|
return nil
|
|
}
|
|
)
|
|
|
|
let mainView = UIView()
|
|
mainView.addSubview(tooltipView)
|
|
tooltipView.bounds = CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0)
|
|
tooltipView.forceLayout()
|
|
|
|
XCTAssertEqual(
|
|
getViewByIdCallCount,
|
|
0,
|
|
"getViewById should not be called when bringToTopId is nil"
|
|
)
|
|
XCTAssertEqual(tooltipView.subviews.count, 2, "Should have substrate and tooltip views")
|
|
}
|
|
|
|
func test_SnapshotView_UpdatesFrameOnLayout() {
|
|
let window = UIWindow(frame: CGRect(x: 0.0, y: 0.0, width: 400.0, height: 600.0))
|
|
|
|
let targetView = TestView()
|
|
targetView.frame = CGRect(x: 50.0, y: 100.0, width: 80.0, height: 40.0)
|
|
|
|
let containerView = UIView(frame: window.bounds)
|
|
window.addSubview(containerView)
|
|
containerView.addSubview(targetView)
|
|
|
|
let substrateView = TestView()
|
|
let tooltipView = TooltipContainerView(
|
|
tooltip: DefaultTooltipManager.Tooltip(
|
|
params: BlockTooltipParams(
|
|
id: "tooltip",
|
|
mode: .modal,
|
|
duration: 0,
|
|
closeByTapOutside: true
|
|
),
|
|
view: TestView(),
|
|
substrateView: substrateView,
|
|
bringToTopId: "target_view"
|
|
),
|
|
handleAction: { _ in },
|
|
onCloseAction: {},
|
|
getViewById: { viewId in
|
|
if viewId.rawValue == "target_view" {
|
|
return targetView
|
|
}
|
|
return nil
|
|
}
|
|
)
|
|
|
|
window.addSubview(tooltipView)
|
|
tooltipView.frame = window.bounds
|
|
tooltipView.layoutIfNeeded()
|
|
|
|
let snapshotView = tooltipView.subviews[1]
|
|
let expectedFrame = tooltipView.convert(
|
|
targetView.convert(targetView.bounds, to: window),
|
|
from: window
|
|
)
|
|
|
|
XCTAssertEqual(
|
|
snapshotView.frame,
|
|
expectedFrame,
|
|
"Snapshot frame should match target view position in window"
|
|
)
|
|
}
|
|
}
|
|
|
|
extension CGRect {
|
|
fileprivate func isInside(_ boundsRect: CGRect) -> Bool {
|
|
intersection(boundsRect) == self
|
|
}
|
|
}
|
|
|
|
fileprivate func makeTooltip(offset: CGPoint, block: Block) -> BlockTooltip {
|
|
BlockTooltip(
|
|
block: block,
|
|
params: BlockTooltipParams(
|
|
id: "tooltip",
|
|
mode: .modal,
|
|
duration: 0,
|
|
closeByTapOutside: true
|
|
),
|
|
offset: offset,
|
|
position: .center
|
|
)
|
|
}
|
|
|
|
fileprivate class TestView: UIView, BlockViewProtocol {
|
|
var effectiveBackgroundColor: UIColor?
|
|
|
|
func onVisibleBoundsChanged(from _: CGRect, to _: CGRect) {}
|
|
}
|