172 lines
5.2 KiB
Swift
172 lines
5.2 KiB
Swift
import XCTest
|
|
@testable import AIStudyApp
|
|
|
|
final class PositionAdapterTests: XCTestCase {
|
|
|
|
// MARK: - Clamping
|
|
|
|
func test_clamp_normal_value() {
|
|
let pos = ReadingPositionAdapter.buildPosition(
|
|
materialType: .markdown,
|
|
blockId: "b1",
|
|
scrollProgress: 0.5
|
|
)
|
|
if case .block(_, let progress, let overallProgress) = pos! {
|
|
XCTAssertEqual(progress, 0.5)
|
|
XCTAssertEqual(overallProgress, 0.5)
|
|
} else {
|
|
XCTFail("Expected block position")
|
|
}
|
|
}
|
|
|
|
func test_clamp_below_zero() {
|
|
let pos = ReadingPositionAdapter.buildPosition(
|
|
materialType: .markdown,
|
|
blockId: "b1",
|
|
scrollProgress: -0.5
|
|
)
|
|
if case .block(_, let progress, let overallProgress) = pos! {
|
|
XCTAssertEqual(progress, 0.0, "Negative progress should clamp to 0")
|
|
XCTAssertEqual(overallProgress, 0.0)
|
|
} else {
|
|
XCTFail("Expected block position")
|
|
}
|
|
}
|
|
|
|
func test_clamp_above_one() {
|
|
let pos = ReadingPositionAdapter.buildPosition(
|
|
materialType: .markdown,
|
|
blockId: "b1",
|
|
scrollProgress: 1.5
|
|
)
|
|
if case .block(_, let progress, let overallProgress) = pos! {
|
|
XCTAssertEqual(progress, 1.0, "Progress >1 should clamp to 1")
|
|
XCTAssertEqual(overallProgress, 1.0)
|
|
} else {
|
|
XCTFail("Expected block position")
|
|
}
|
|
}
|
|
|
|
func test_clamp_nan() {
|
|
let pos = ReadingPositionAdapter.buildPosition(
|
|
materialType: .markdown,
|
|
blockId: "b1",
|
|
scrollProgress: Float.nan
|
|
)
|
|
if case .block(_, let progress, let overallProgress) = pos! {
|
|
XCTAssertEqual(progress, 0.0, "NaN progress should clamp to 0")
|
|
XCTAssertEqual(overallProgress, 0.0)
|
|
} else {
|
|
XCTFail("Expected block position")
|
|
}
|
|
}
|
|
|
|
// MARK: - Material types
|
|
|
|
func test_pdf_position() {
|
|
let pos = ReadingPositionAdapter.buildPosition(
|
|
materialType: .pdf,
|
|
pageNumber: 3,
|
|
pageProgress: 0.5,
|
|
overallProgress: 0.3
|
|
)
|
|
if case .pdf(let page, let pageProg, let overall) = pos! {
|
|
XCTAssertEqual(page, 3)
|
|
XCTAssertEqual(pageProg, 0.5)
|
|
XCTAssertEqual(overall, 0.3)
|
|
} else {
|
|
XCTFail("Expected PDF position")
|
|
}
|
|
}
|
|
|
|
func test_text_position() {
|
|
let pos = ReadingPositionAdapter.buildPosition(
|
|
materialType: .text,
|
|
scrollProgress: 0.7,
|
|
lineNumber: 42
|
|
)
|
|
if case .text(let line, let progress) = pos! {
|
|
XCTAssertEqual(line, 42)
|
|
XCTAssertEqual(progress, 0.7)
|
|
} else {
|
|
XCTFail("Expected text position")
|
|
}
|
|
}
|
|
|
|
func test_image_position() {
|
|
let pos = ReadingPositionAdapter.buildPosition(
|
|
materialType: .image,
|
|
zoomScale: 2.0,
|
|
offsetX: 100,
|
|
offsetY: 200
|
|
)
|
|
if case .image(let zoom, let ox, let oy) = pos! {
|
|
XCTAssertEqual(zoom, 2.0)
|
|
XCTAssertEqual(ox, 100)
|
|
XCTAssertEqual(oy, 200)
|
|
} else {
|
|
XCTFail("Expected image position")
|
|
}
|
|
}
|
|
|
|
func test_epub_position() {
|
|
let pos = ReadingPositionAdapter.buildPosition(
|
|
materialType: .epub,
|
|
chapterProgress: 0.4,
|
|
overallProgress: 0.2,
|
|
chapterId: "ch3"
|
|
)
|
|
if case .epub(let ch, let chProg, let overall) = pos! {
|
|
XCTAssertEqual(ch, "ch3")
|
|
XCTAssertEqual(chProg, 0.4)
|
|
XCTAssertEqual(overall, 0.2)
|
|
} else {
|
|
XCTFail("Expected epub position")
|
|
}
|
|
}
|
|
|
|
func test_unknown_material_returns_unknown() {
|
|
let pos = ReadingPositionAdapter.buildPosition(materialType: .unknown)
|
|
if case .unknown = pos! {
|
|
// Expected
|
|
} else {
|
|
XCTFail("Expected unknown position")
|
|
}
|
|
}
|
|
|
|
func test_markdown_missing_block_id_returns_nil() {
|
|
let pos = ReadingPositionAdapter.buildPosition(
|
|
materialType: .markdown,
|
|
blockId: nil,
|
|
scrollProgress: 0.5
|
|
)
|
|
XCTAssertNil(pos, "Markdown without blockId should return nil")
|
|
}
|
|
|
|
func test_epub_missing_chapter_id_returns_nil() {
|
|
let pos = ReadingPositionAdapter.buildPosition(
|
|
materialType: .epub,
|
|
chapterId: nil,
|
|
chapterProgress: 0.5
|
|
)
|
|
XCTAssertNil(pos, "Epub without chapterId should return nil")
|
|
}
|
|
|
|
// MARK: - blockId extraction
|
|
|
|
func test_blockId_from_heading() {
|
|
let block = DocumentBlock.heading(id: "h1", level: 1, text: "Title")
|
|
XCTAssertEqual(ReadingPositionAdapter.blockId(from: block), "h1")
|
|
}
|
|
|
|
func test_blockId_from_paragraph() {
|
|
let block = DocumentBlock.paragraph(id: "p1", text: "Hello")
|
|
XCTAssertEqual(ReadingPositionAdapter.blockId(from: block), "p1")
|
|
}
|
|
|
|
func test_blockId_from_codeBlock() {
|
|
let block = DocumentBlock.codeBlock(id: "c1", language: "swift", code: "print()")
|
|
XCTAssertEqual(ReadingPositionAdapter.blockId(from: block), "c1")
|
|
}
|
|
}
|