ios-projects/AIStudyApp/AIStudyAppReaderTests/ReadingPositionAdapterTests.swift

136 lines
4.7 KiB
Swift

import XCTest
@testable import AIStudyApp
final class ReadingPositionAdapterTests: XCTestCase {
private func makeValue(
type: String?,
blockId: String? = nil,
blockProgress: Float? = nil,
lineNumber: UInt32? = nil,
pageNumber: UInt32? = nil,
scrollProgress: Float? = nil,
pageProgress: Float? = nil,
overallProgress: Float? = nil,
zoomScale: Float? = nil,
offsetX: Float? = nil,
offsetY: Float? = nil,
chapterId: String? = nil,
chapterProgress: Float? = nil
) -> ReadingPositionValue {
ReadingPositionValue(
type: type,
pageNumber: pageNumber,
blockId: blockId,
blockProgress: blockProgress,
scrollProgress: scrollProgress,
lineNumber: lineNumber,
pageProgress: pageProgress,
overallProgress: overallProgress,
zoomScale: zoomScale,
offsetX: offsetX,
offsetY: offsetY,
chapterId: chapterId,
chapterProgress: chapterProgress,
offset: nil,
percent: nil,
section: nil
)
}
func test_fromValue_markdown_with_blockId() {
let v = makeValue(type: "Markdown", blockId: "b1", scrollProgress: 0.5)
let pos = ReadingPositionAdapter.fromValue(v)
guard case let .markdown(blockId, scrollProgress) = pos else {
return XCTFail("Expected .markdown, got \(String(describing: pos))")
}
XCTAssertEqual(blockId, "b1")
XCTAssertEqual(scrollProgress, 0.5)
}
func test_fromValue_markdown_nil_blockId_returns_nil() {
let v = makeValue(type: "Markdown")
XCTAssertNil(ReadingPositionAdapter.fromValue(v))
}
func test_fromValue_text_with_optional_fields() {
let v = makeValue(type: "Text", lineNumber: 42, scrollProgress: 0.8)
guard case let .text(lineNumber, scrollProgress) = ReadingPositionAdapter.fromValue(v) else {
return XCTFail("Expected .text")
}
XCTAssertEqual(lineNumber, 42)
XCTAssertEqual(scrollProgress, 0.8)
}
func test_fromValue_pdf_with_all_fields() {
let v = makeValue(type: "Pdf", pageNumber: 5, pageProgress: 0.3, overallProgress: 0.15)
guard case let .pdf(pageNumber, pageProgress, overallProgress) = ReadingPositionAdapter.fromValue(v) else {
return XCTFail("Expected .pdf")
}
XCTAssertEqual(pageNumber, 5)
XCTAssertEqual(pageProgress, 0.3)
XCTAssertEqual(overallProgress, 0.15)
}
func test_fromBlockScroll_markdown_returns_position() {
let blocks: [DocumentBlock] = [
.heading(id: "h1", level: 1, text: "Title"),
.paragraph(id: "p1", text: "Content"),
]
let pos = ReadingPositionAdapter.fromBlockScroll(
materialType: .markdown, blocks: blocks, scrollProgress: 0.5, blockIndex: 0
)
guard case .block(let blockId, let blockProgress, let overallProgress) = pos else {
return XCTFail("Expected .block")
}
XCTAssertEqual(blockId, "h1")
XCTAssertEqual(blockProgress, 0.5)
XCTAssertEqual(overallProgress, 0.5)
}
func test_blockIdForRestore_prefers_existing_blockId() {
let blocks: [DocumentBlock] = [
.heading(id: "h1", level: 1, text: "Title"),
.paragraph(id: "p1", text: "Content"),
.paragraph(id: "p2", text: "Tail"),
]
let restored = ReadingPositionAdapter.blockIdForRestore(
from: .block(blockId: "p1", blockProgress: 0.25, overallProgress: 0.8),
in: blocks
)
XCTAssertEqual(restored, "p1")
}
func test_blockIdForRestore_fallsBack_to_progress_when_blockId_missing() {
let blocks: [DocumentBlock] = [
.heading(id: "h1", level: 1, text: "Title"),
.paragraph(id: "p1", text: "Content"),
.paragraph(id: "p2", text: "Tail"),
]
let restored = ReadingPositionAdapter.blockIdForRestore(
from: .block(blockId: "missing", blockProgress: 0.1, overallProgress: 0.9),
in: blocks
)
XCTAssertEqual(restored, "p2")
}
func test_blockIdForRestore_text_out_of_range_fallsBack_to_scroll_progress() {
let blocks: [DocumentBlock] = [
.heading(id: "h1", level: 1, text: "Title"),
.paragraph(id: "p1", text: "Content"),
.paragraph(id: "p2", text: "Tail"),
]
let restored = ReadingPositionAdapter.blockIdForRestore(
from: .text(lineNumber: 99, scrollProgress: 0.45),
in: blocks
)
XCTAssertEqual(restored, "p1")
}
}