无法使 press(forDuration:, thenDragTo:) 正常工作

问题描述 投票:0回答:0

我有一个允许在地图上拖动图钉的 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,但它是无关的。

ios xcode-ui-testing draggesture
© www.soinside.com 2019 - 2024. All rights reserved.