ios-projects/AIStudyApp/AIStudyAppTests/PositionAdapterTests.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")
}
}