我有一个允许在地图上拖动图钉的 SwiftUI 应用程序。
首先长按一个引脚。最后,将销向上移动,以便可以看到其底部。然后可以拖动它。
我想编写一个 UI 测试来检查操作是否正确。
但是我的测试失败了,因为获得的屏幕点是错误的。
因此,我写了一个最小的项目来演示这个问题。
这是
ContentView
:
import SwiftUI
struct ContentView: View {
@GestureState private var dragAmount = CGSize.zero
@State private var pinOffset = CGSize.zero
var body: some View {
let longPressGesture = LongPressGesture(minimumDuration: 0.2)
.onEnded { _ in
withAnimation(.easeInOut(duration: 0.3)) {
pinOffset = CGSize(width: 0, height: -60)
}
}
let dragGesture = DragGesture(coordinateSpace: .global)
.updating($dragAmount) { dragGestureValue, dragAmount, transaction in
dragAmount = dragGestureValue.translation
}
.onEnded { dragGestureValue in
pinOffset = CGSize(width: dragGestureValue.translation.width,
height: dragGestureValue.translation.height - 60)
}
let combinedGesture = longPressGesture.sequenced(before: dragGesture)
Image(systemName: "pin")
.offset(CGSize(width: dragAmount.width + pinOffset.width,
height: dragAmount.height + pinOffset.height))
.simultaneousGesture(combinedGesture)
}
}
这是我的 UI 测试:
func test_dragging() throws {
let app = XCUIApplication()
app.launch()
// setup
let dragAmountX: CGFloat = 100
let dragAmountY: CGFloat = 100
let allowedError: CGFloat = 2
var actualError: CGFloat
let pinDraggingLiftOff: CGFloat = 60
let pinLongPressDuration = 1.0
// Long press the pin. On ended, the pin is lifted off. Then drag it to another location.
// given
let expectedDistance = sqrt(dragAmountX * dragAmountX + (dragAmountY - pinDraggingLiftOff) * (dragAmountY - pinDraggingLiftOff))
let pinBeforeDrag = app.images.firstMatch
let pinBaseBeforeDrag = pinBeforeDrag.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.99)).screenPoint
let pinCenterBeforeDrag = pinBeforeDrag.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5))
let pinCenterAfterDrag = pinCenterBeforeDrag.withOffset(CGVector(dx: dragAmountX, dy: dragAmountY))
// when
pinCenterBeforeDrag.press(forDuration: pinLongPressDuration, thenDragTo: pinCenterAfterDrag)
// then
let pinAfterDrag = app.images.firstMatch
let pinBaseAfterDrag = pinAfterDrag.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.99)).screenPoint
let actualDistance = sqrt(pow(pinBaseBeforeDrag.x - pinBaseAfterDrag.x, 2) + pow(pinBaseBeforeDrag.y - pinBaseAfterDrag.y, 2))
actualError = abs(actualDistance - expectedDistance)
XCTAssert(actualError < allowedError, "Found distance \(actualDistance); expected: \(expectedDistance)")
}
获得的几个值:
dragAmountX dragAmountY expectedDistance actualDistance
0 0 60 60
0 100 40 33
100 0 116.6 110.7
100 100 107.7 101.7
不明白为什么一拖pin就所有距离都不对
PS:我看过this question,但它是无关的。