import XCTest final class LargeBookOnDemandTests: XCTestCase { private let app = XCUIApplication() private let largeBookQuery = "凡人修仙传" override func setUpWithError() throws { continueAfterFailure = false } func testLargeBookInitialOpenIsReadableWhilePaginationIsPartial() throws { app.launchAndOpenSampleBook(bookTitleQuery: largeBookQuery, resetsReaderState: true) app.waitForReader(timeout: 20) let partialState = app.waitForDemoReaderState(timeout: 15, description: "大书首开进入局部分页") { state in state.mode == "bookPageMap" && state.pagination == "partial" && (state.page ?? 0) >= 1 } XCTAssertEqual(partialState.mode, "bookPageMap") XCTAssertEqual(partialState.pagination, "partial") XCTAssertTrue(app.otherElements[IDs.readerContent].waitForExistence(timeout: 5), "首开局部分页阶段应已可阅读") } func testLargeBookBackgroundPaginationProgresses() throws { app.launchAndOpenSampleBook(bookTitleQuery: largeBookQuery, resetsReaderState: true) app.waitForReader(timeout: 20) let initialState = app.waitForDemoReaderState(timeout: 15, description: "获取初始分页进度") { state in state.mode == "bookPageMap" && state.knownChapters != nil && state.buildableChapters != nil } let initialKnownChapters = initialState.knownChapters ?? 0 let initialKnownPages = initialState.knownPages ?? 0 let progressedState = app.waitForDemoReaderState(timeout: 45, description: "后台分页推进") { state in guard state.mode == "bookPageMap" else { return false } if state.pagination == "full" { return true } return (state.knownChapters ?? 0) > initialKnownChapters || (state.knownPages ?? 0) > initialKnownPages } XCTAssertEqual(progressedState.mode, "bookPageMap") XCTAssertTrue( (progressedState.knownChapters ?? 0) >= initialKnownChapters || (progressedState.knownPages ?? 0) >= initialKnownPages ) } func testLargeBookSecondOpenRestoresFromCache() throws { app.launchAndOpenSampleBook(bookTitleQuery: largeBookQuery, resetsReaderState: true) app.waitForReader(timeout: 20) _ = app.waitForDemoReaderState(timeout: 60, description: "首次打开完成全书缓存") { state in state.mode == "bookPageMap" && state.pagination == "full" && (state.buildableChapters ?? 0) > 0 } app.showReaderChromeIfNeeded() XCTAssertTrue(app.buttons[IDs.readerBack].waitForExistence(timeout: 5), "返回按钮不存在") app.buttons[IDs.readerBack].tap() XCTAssertTrue(app.tables[IDs.demoBooksTable].waitForExistence(timeout: 5), "书架列表未出现") app.launchAndOpenSampleBook(bookTitleQuery: largeBookQuery, resetsReaderState: false) app.waitForReader(timeout: 15) let reopenedState = app.waitForDemoReaderState(timeout: 10, description: "二开直接恢复完整缓存") { state in state.mode == "bookPageMap" && state.pagination == "full" && (state.knownChapters ?? 0) == (state.buildableChapters ?? -1) } XCTAssertEqual(reopenedState.pagination, "full") XCTAssertEqual(reopenedState.knownChapters, reopenedState.buildableChapters) } func testLargeBookContinuousPagingExtendsKnownPageMap() throws { app.launchAndOpenSampleBook(bookTitleQuery: largeBookQuery, displayType: "scroll", resetsReaderState: true) app.waitForReader(timeout: 20) app.waitForReaderState(containing: "display=horizontalScroll", timeout: 8) let initialState = app.waitForDemoReaderState(timeout: 15, description: "初始局部分页") { state in state.mode == "bookPageMap" && state.knownPages != nil && state.page != nil } let initialKnownPages = initialState.knownPages ?? 0 let initialPage = initialState.page ?? 0 let paging = app.collectionViews[IDs.readerPaging] XCTAssertTrue(paging.waitForExistence(timeout: 5), "分页视图不存在") for _ in 0..<4 { paging.swipeLeft() } let extendedState = app.waitForDemoReaderState(timeout: 20, description: "连续翻页触发扩窗") { state in guard state.mode == "bookPageMap" else { return false } let pageAdvanced = (state.page ?? 0) > initialPage let pageMapExtended = (state.knownPages ?? 0) > initialKnownPages || state.pagination == "full" return pageAdvanced && pageMapExtended } XCTAssertTrue((extendedState.page ?? 0) > initialPage, "连续翻页后当前页应向后推进") XCTAssertTrue( (extendedState.knownPages ?? 0) > initialKnownPages || extendedState.pagination == "full", "连续翻页后已知页图应扩窗或直接完成全量分页" ) } }