77 lines
2.9 KiB
Swift
77 lines
2.9 KiB
Swift
|
|
import XCTest
|
||
|
|
@testable import SaplingEditor
|
||
|
|
|
||
|
|
final class EditorScrollStabilityTests: XCTestCase {
|
||
|
|
func testRenderMetricsCountScrollRestorationDuringDirtyEdit() {
|
||
|
|
var instrumentation = EditorInstrumentationSnapshot()
|
||
|
|
instrumentation.recordRenderPass(EditorRenderPassMetric(
|
||
|
|
reason: .sourceChange,
|
||
|
|
durationMilliseconds: 0.4,
|
||
|
|
characterCount: 1_200,
|
||
|
|
lineCount: 80,
|
||
|
|
dirtyLineCount: 3,
|
||
|
|
activeLineIndex: 40,
|
||
|
|
isFullRender: false,
|
||
|
|
restoredScrollPosition: true
|
||
|
|
))
|
||
|
|
|
||
|
|
XCTAssertEqual(instrumentation.renderPassCount, 1)
|
||
|
|
XCTAssertEqual(instrumentation.fullRenderCount, 0)
|
||
|
|
XCTAssertEqual(instrumentation.totalDirtyLineCount, 3)
|
||
|
|
XCTAssertEqual(instrumentation.lastDirtyLineCount, 3)
|
||
|
|
XCTAssertEqual(instrumentation.scrollRestorationCount, 1)
|
||
|
|
}
|
||
|
|
|
||
|
|
func testRapidNavigationSchedulesOnlyOldAndNewActiveLines() {
|
||
|
|
let source = (1...500).map { "Line \($0)" }.joined(separator: "\n")
|
||
|
|
|
||
|
|
let firstJump = EditorDirtyLineInvalidator.plan(
|
||
|
|
previousText: source,
|
||
|
|
currentText: source,
|
||
|
|
previousActiveLineIndex: 10,
|
||
|
|
currentActiveLineIndex: 250
|
||
|
|
)
|
||
|
|
let secondJump = EditorDirtyLineInvalidator.plan(
|
||
|
|
previousText: source,
|
||
|
|
currentText: source,
|
||
|
|
previousActiveLineIndex: 250,
|
||
|
|
currentActiveLineIndex: 490
|
||
|
|
)
|
||
|
|
|
||
|
|
XCTAssertEqual(firstJump.dirtyLineIndexes, [10, 250])
|
||
|
|
XCTAssertEqual(secondJump.dirtyLineIndexes, [250, 490])
|
||
|
|
XCTAssertFalse(firstJump.isFullRender)
|
||
|
|
XCTAssertFalse(secondJump.isFullRender)
|
||
|
|
}
|
||
|
|
|
||
|
|
func testEditingWhileScrolledDoesNotRequireFullRender() {
|
||
|
|
let previous = (1...200).map { "Line \($0)" }.joined(separator: "\n")
|
||
|
|
var lines = previous.components(separatedBy: "\n")
|
||
|
|
lines[120] = "Line 121 edited while viewport is away from the top"
|
||
|
|
let current = lines.joined(separator: "\n")
|
||
|
|
|
||
|
|
let plan = EditorDirtyLineInvalidator.plan(
|
||
|
|
previousText: previous,
|
||
|
|
currentText: current,
|
||
|
|
previousActiveLineIndex: 120,
|
||
|
|
currentActiveLineIndex: 120
|
||
|
|
)
|
||
|
|
var instrumentation = EditorInstrumentationSnapshot()
|
||
|
|
instrumentation.recordRenderPass(EditorRenderPassMetric(
|
||
|
|
reason: plan.reason,
|
||
|
|
durationMilliseconds: 0.5,
|
||
|
|
characterCount: current.utf16.count,
|
||
|
|
lineCount: 200,
|
||
|
|
dirtyLineCount: plan.dirtyLineCount,
|
||
|
|
activeLineIndex: 120,
|
||
|
|
isFullRender: plan.isFullRender,
|
||
|
|
restoredScrollPosition: true
|
||
|
|
))
|
||
|
|
|
||
|
|
XCTAssertEqual(plan.reason, .sourceChange)
|
||
|
|
XCTAssertFalse(plan.isFullRender)
|
||
|
|
XCTAssertEqual(plan.dirtyLineIndexes, [119, 120, 121])
|
||
|
|
XCTAssertEqual(instrumentation.scrollRestorationCount, 1)
|
||
|
|
}
|
||
|
|
}
|