test: 增强 UI 测试基础设施与阅读器自动化测试
- 新增 BookmarkTests/PageNavigationTests/TableOfContentsTests 等阅读器功能测试 - 扩展 AccessibilityIdentifiers 支持更多 UI 元素定位 - XCUIApplication+Launch: 增加启动参数支持(reset state、自定义书籍) - ReaderAnnotationTests: 完善标注测试覆盖 - ViewController: 支持 --demo-reset-state 参数清理持久化状态 - 新增凡人修仙传测试样本 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
c76beed03c
commit
9801af05d3
@@ -0,0 +1,82 @@
|
||||
import XCTest
|
||||
|
||||
final class BookmarkTests: XCTestCase {
|
||||
private let app = XCUIApplication()
|
||||
|
||||
override func setUpWithError() throws {
|
||||
continueAfterFailure = false
|
||||
}
|
||||
|
||||
func testBookmarkButtonExistsInToolbar() {
|
||||
app.launchAndOpenSampleBook()
|
||||
app.waitForReader()
|
||||
app.showReaderChromeIfNeeded()
|
||||
|
||||
let bookmarkButton = app.buttons[IDs.readerBookmark]
|
||||
XCTAssertTrue(bookmarkButton.waitForExistence(timeout: 5), "书签按钮未出现")
|
||||
}
|
||||
|
||||
func testToggleBookmark() {
|
||||
app.launchAndOpenSampleBook()
|
||||
app.waitForReader()
|
||||
app.showReaderChromeIfNeeded()
|
||||
|
||||
let bookmarkButton = app.buttons[IDs.readerBookmark]
|
||||
XCTAssertTrue(bookmarkButton.waitForExistence(timeout: 5), "书签按钮未出现")
|
||||
bookmarkButton.tap()
|
||||
Thread.sleep(forTimeInterval: 1)
|
||||
|
||||
app.showReaderChromeIfNeeded()
|
||||
XCTAssertTrue(bookmarkButton.waitForExistence(timeout: 5), "书签按钮再次点击后未出现")
|
||||
bookmarkButton.tap()
|
||||
}
|
||||
|
||||
func testBookmarksButtonVisibleAfterBookmarkAdded() {
|
||||
app.launchAndOpenSampleBook()
|
||||
app.waitForReader()
|
||||
app.showReaderChromeIfNeeded()
|
||||
|
||||
let bookmarkButton = app.buttons[IDs.readerBookmark]
|
||||
XCTAssertTrue(bookmarkButton.waitForExistence(timeout: 5), "书签按钮未出现")
|
||||
bookmarkButton.tap()
|
||||
Thread.sleep(forTimeInterval: 1)
|
||||
|
||||
app.showReaderChromeIfNeeded()
|
||||
let bookmarksListButton = app.buttons[IDs.readerBookmarks]
|
||||
XCTAssertTrue(bookmarksListButton.waitForExistence(timeout: 5), "书签列表按钮未出现")
|
||||
}
|
||||
|
||||
func testBookmarksListButtonExists() {
|
||||
app.launchAndOpenSampleBook()
|
||||
app.waitForReader()
|
||||
app.showReaderChromeIfNeeded()
|
||||
|
||||
let bookmarksListButton = app.buttons[IDs.readerBookmarks]
|
||||
XCTAssertTrue(bookmarksListButton.waitForExistence(timeout: 5), "书签列表按钮未出现")
|
||||
}
|
||||
|
||||
func testBookmarksPanelIsAccessible() {
|
||||
app.launchAndOpenSampleBook()
|
||||
app.waitForReader()
|
||||
app.showReaderChromeIfNeeded()
|
||||
|
||||
let bookmarkButton = app.buttons[IDs.readerBookmark]
|
||||
XCTAssertTrue(bookmarkButton.waitForExistence(timeout: 5), "书签按钮未出现")
|
||||
bookmarkButton.tap()
|
||||
|
||||
app.showReaderChromeIfNeeded()
|
||||
let bookmarksListButton = app.buttons[IDs.readerBookmarks]
|
||||
XCTAssertTrue(bookmarksListButton.waitForExistence(timeout: 5), "书签列表按钮未出现")
|
||||
|
||||
let enabledPredicate = NSPredicate(format: "isEnabled == true")
|
||||
expectation(for: enabledPredicate, evaluatedWith: bookmarksListButton)
|
||||
waitForExpectations(timeout: 10)
|
||||
|
||||
XCTAssertTrue(bookmarksListButton.isEnabled, "书签列表按钮未启用")
|
||||
bookmarksListButton.tap()
|
||||
|
||||
let bookmarksPanel = app.tables[IDs.readerBookmarksTable]
|
||||
XCTAssertTrue(bookmarksPanel.waitForExistence(timeout: 5), "书签面板未出现")
|
||||
XCTAssertTrue(app.navigationBars[IDs.readerBookmarksNavBar].waitForExistence(timeout: 2), "书签导航栏未暴露")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import XCTest
|
||||
|
||||
final class PageNavigationTests: XCTestCase {
|
||||
private let app = XCUIApplication()
|
||||
|
||||
override func setUpWithError() throws {
|
||||
continueAfterFailure = false
|
||||
}
|
||||
|
||||
func testContentAreaExistsForNavigation() {
|
||||
app.launchAndOpenSampleBook()
|
||||
app.waitForReader()
|
||||
|
||||
let content = app.otherElements[IDs.readerContent]
|
||||
XCTAssertTrue(content.waitForExistence(timeout: 5), "阅读内容区域未出现")
|
||||
}
|
||||
|
||||
func testPagingViewExistsInScrollMode() {
|
||||
app.launchAndOpenSampleBook(displayType: "scroll")
|
||||
app.waitForReader()
|
||||
app.waitForReaderState(containing: "display=horizontalScroll", timeout: 5)
|
||||
|
||||
let paging = app.collectionViews[IDs.readerPaging]
|
||||
XCTAssertTrue(paging.waitForExistence(timeout: 5), "分页滚动视图未出现")
|
||||
}
|
||||
|
||||
func testPagingViewExistsInVerticalScrollMode() {
|
||||
app.launchAndOpenSampleBook(displayType: "vertical")
|
||||
app.waitForReader()
|
||||
app.waitForReaderState(containing: "display=verticalScroll", timeout: 5)
|
||||
|
||||
let paging = app.collectionViews[IDs.readerPaging]
|
||||
XCTAssertTrue(paging.waitForExistence(timeout: 5), "分页滚动视图未出现")
|
||||
}
|
||||
|
||||
func testSwipeInHorizontalScrollMode() {
|
||||
app.launchAndOpenSampleBook(displayType: "scroll")
|
||||
app.waitForReader()
|
||||
app.waitForReaderState(containing: "display=horizontalScroll", timeout: 5)
|
||||
|
||||
let paging = app.collectionViews[IDs.readerPaging]
|
||||
XCTAssertTrue(paging.waitForExistence(timeout: 5))
|
||||
|
||||
let state = app.staticTexts[IDs.demoReaderState]
|
||||
let beforeLabel = state.label
|
||||
|
||||
paging.swipeLeft()
|
||||
let deadline = Date().addingTimeInterval(5)
|
||||
while Date() < deadline {
|
||||
if state.exists && state.label != beforeLabel { break }
|
||||
RunLoop.current.run(until: Date().addingTimeInterval(0.1))
|
||||
}
|
||||
XCTAssertNotEqual(beforeLabel, state.label, "水平滑动后页码未变化")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import XCTest
|
||||
|
||||
final class ReaderAnnotationExtendedTests: XCTestCase {
|
||||
private let app = XCUIApplication()
|
||||
|
||||
override func setUpWithError() throws {
|
||||
continueAfterFailure = false
|
||||
}
|
||||
|
||||
func testBottomToolbarHasAddHighlightButton() {
|
||||
app.launchAndOpenSampleBook()
|
||||
app.waitForReader()
|
||||
app.showReaderChromeIfNeeded()
|
||||
|
||||
let addHighlightButton = app.buttons[IDs.readerAddHighlight]
|
||||
XCTAssertTrue(addHighlightButton.waitForExistence(timeout: 5), "底部工具栏标注按钮未出现")
|
||||
}
|
||||
|
||||
func testBottomToolbarHasHighlightsButton() {
|
||||
app.launchAndOpenSampleBook()
|
||||
app.waitForReader()
|
||||
app.showReaderChromeIfNeeded()
|
||||
|
||||
let highlightsButton = app.buttons[IDs.readerHighlights]
|
||||
XCTAssertTrue(highlightsButton.waitForExistence(timeout: 5), "底部工具栏高亮列表按钮未出现")
|
||||
}
|
||||
|
||||
func testBottomToolbarButtonsLayout() {
|
||||
app.launchAndOpenSampleBook()
|
||||
app.waitForReader()
|
||||
app.showReaderChromeIfNeeded()
|
||||
|
||||
XCTAssertTrue(app.buttons[IDs.readerToc].waitForExistence(timeout: 5), "目录按钮未出现")
|
||||
XCTAssertTrue(app.buttons[IDs.readerBookmarks].exists, "书签按钮未出现")
|
||||
XCTAssertTrue(app.buttons[IDs.readerHighlights].exists, "高亮按钮未出现")
|
||||
XCTAssertTrue(app.buttons[IDs.readerAddHighlight].exists, "标注按钮未出现")
|
||||
XCTAssertTrue(app.buttons[IDs.readerSettings].exists, "设置按钮未出现")
|
||||
}
|
||||
|
||||
func testSelectionTextElementExists() {
|
||||
app.launchAndOpenSampleBook()
|
||||
app.waitForReader()
|
||||
|
||||
let selectionText = app.otherElements[IDs.readerSelectionText].firstMatch
|
||||
XCTAssertTrue(selectionText.waitForExistence(timeout: 5), "文本选区元素未出现")
|
||||
}
|
||||
|
||||
func testReaderStateReportsPageInfo() {
|
||||
app.launchAndOpenSampleBook()
|
||||
app.waitForReader()
|
||||
|
||||
let state = app.staticTexts[IDs.demoReaderState]
|
||||
XCTAssertTrue(state.waitForExistence(timeout: 5))
|
||||
XCTAssertTrue(state.label.contains("reader=opened"), "状态未包含 reader=opened")
|
||||
XCTAssertTrue(state.label.contains("page="), "状态未包含 page 信息")
|
||||
XCTAssertTrue(state.label.contains("display="), "状态未包含 display 信息")
|
||||
}
|
||||
|
||||
func testReaderStateReportsHighlightCount() {
|
||||
app.launchAndOpenSampleBook()
|
||||
app.waitForReader()
|
||||
|
||||
let state = app.staticTexts[IDs.demoReaderState]
|
||||
XCTAssertTrue(state.waitForExistence(timeout: 5))
|
||||
XCTAssertTrue(state.label.contains("highlights=0"), "初始高亮数应为 0")
|
||||
}
|
||||
}
|
||||
@@ -10,13 +10,17 @@ final class ReaderAnnotationTests: XCTestCase {
|
||||
func testSelectionMenuCreatesHighlight() {
|
||||
app.launchAndOpenSampleBook(pageNumber: 2)
|
||||
app.waitForReader()
|
||||
app.waitForReaderPage(2)
|
||||
app.hideReaderChromeIfNeeded()
|
||||
|
||||
let content = app.otherElements[IDs.readerSelectionText].firstMatch
|
||||
XCTAssertTrue(content.waitForExistence(timeout: 5), "阅读内容区域未出现")
|
||||
|
||||
let start = content.coordinate(withNormalizedOffset: CGVector(dx: 0.35, dy: 0.42))
|
||||
let end = content.coordinate(withNormalizedOffset: CGVector(dx: 0.68, dy: 0.42))
|
||||
start.press(forDuration: 0.6, thenDragTo: end)
|
||||
app.waitForReaderState(containing: "toolbar=hidden", timeout: 5)
|
||||
|
||||
let start = content.coordinate(withNormalizedOffset: CGVector(dx: 0.35, dy: 0.45))
|
||||
let end = content.coordinate(withNormalizedOffset: CGVector(dx: 0.68, dy: 0.45))
|
||||
start.press(forDuration: 0.8, thenDragTo: end)
|
||||
|
||||
app.waitForReaderState(containing: "selection=1", timeout: 5)
|
||||
|
||||
@@ -36,15 +40,19 @@ final class ReaderAnnotationTests: XCTestCase {
|
||||
func testLongPressSelectionDoesNotShowToolbars() {
|
||||
app.launchAndOpenSampleBook(pageNumber: 2)
|
||||
app.waitForReader()
|
||||
app.waitForReaderPage(2)
|
||||
app.hideReaderChromeIfNeeded()
|
||||
|
||||
let content = app.otherElements[IDs.readerSelectionText].firstMatch
|
||||
XCTAssertTrue(content.waitForExistence(timeout: 5), "阅读内容区域未出现")
|
||||
|
||||
let start = content.coordinate(withNormalizedOffset: CGVector(dx: 0.35, dy: 0.42))
|
||||
let end = content.coordinate(withNormalizedOffset: CGVector(dx: 0.68, dy: 0.42))
|
||||
start.press(forDuration: 0.6, thenDragTo: end)
|
||||
|
||||
app.waitForReaderState(containing: "selection=1", timeout: 5)
|
||||
app.waitForReaderState(containing: "toolbar=hidden", timeout: 5)
|
||||
|
||||
let start = content.coordinate(withNormalizedOffset: CGVector(dx: 0.35, dy: 0.45))
|
||||
let end = content.coordinate(withNormalizedOffset: CGVector(dx: 0.68, dy: 0.45))
|
||||
start.press(forDuration: 0.8, thenDragTo: end)
|
||||
|
||||
app.waitForReaderState(containing: "selection=1", timeout: 8)
|
||||
app.waitForReaderState(containing: "toolbar=hidden", timeout: 3)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import XCTest
|
||||
|
||||
final class SettingsExtendedTests: XCTestCase {
|
||||
private let app = XCUIApplication()
|
||||
|
||||
override func setUpWithError() throws {
|
||||
continueAfterFailure = false
|
||||
}
|
||||
|
||||
private func openSettings() {
|
||||
app.launchAndOpenSampleBook()
|
||||
app.waitForReader()
|
||||
app.showReaderChromeIfNeeded()
|
||||
|
||||
XCTAssertTrue(app.buttons[IDs.readerSettings].waitForExistence(timeout: 5))
|
||||
app.buttons[IDs.readerSettings].tap()
|
||||
XCTAssertTrue(app.scrollViews[IDs.settingsScroll].waitForExistence(timeout: 5))
|
||||
}
|
||||
|
||||
func testBrightnessSliderExists() {
|
||||
openSettings()
|
||||
let slider = app.sliders[IDs.settingsBrightness]
|
||||
XCTAssertTrue(slider.waitForExistence(timeout: 3), "亮度滑块未出现")
|
||||
}
|
||||
|
||||
func testLineHeightControl() {
|
||||
openSettings()
|
||||
let lineHeight = app.segmentedControls[IDs.settingsLineHeight]
|
||||
XCTAssertTrue(lineHeight.waitForExistence(timeout: 3), "行距控件未出现")
|
||||
|
||||
lineHeight.buttons["紧凑"].tap()
|
||||
lineHeight.buttons["标准"].tap()
|
||||
lineHeight.buttons["宽松"].tap()
|
||||
|
||||
app.buttons[IDs.settingsDone].tap()
|
||||
XCTAssertTrue(app.buttons[IDs.readerBack].waitForExistence(timeout: 5))
|
||||
}
|
||||
|
||||
func testColumnCountControl() {
|
||||
openSettings()
|
||||
let columns = app.segmentedControls[IDs.settingsColumns]
|
||||
XCTAssertTrue(columns.waitForExistence(timeout: 3), "分栏控件未出现")
|
||||
|
||||
columns.buttons["单栏"].tap()
|
||||
columns.buttons["双栏"].tap()
|
||||
|
||||
app.buttons[IDs.settingsDone].tap()
|
||||
XCTAssertTrue(app.buttons[IDs.readerBack].waitForExistence(timeout: 5))
|
||||
}
|
||||
|
||||
func testDisplayTypeFromSettings() {
|
||||
openSettings()
|
||||
let displayType = app.segmentedControls[IDs.settingsDisplayType]
|
||||
XCTAssertTrue(displayType.waitForExistence(timeout: 3), "翻页方式控件未出现")
|
||||
|
||||
displayType.buttons["横滑"].tap()
|
||||
app.buttons[IDs.settingsDone].tap()
|
||||
app.waitForReaderState(containing: "display=horizontalScroll", timeout: 5)
|
||||
}
|
||||
|
||||
func testAllThemeButtonsExist() {
|
||||
openSettings()
|
||||
for index in 0...5 {
|
||||
let themeButton = app.buttons[IDs.settingsTheme(index)]
|
||||
XCTAssertTrue(themeButton.waitForExistence(timeout: 3), "主题按钮 \(index) 未出现")
|
||||
}
|
||||
}
|
||||
|
||||
func testScrollSettingsToReachAllControls() {
|
||||
openSettings()
|
||||
let scroll = app.scrollViews[IDs.settingsScroll]
|
||||
XCTAssertTrue(scroll.waitForExistence(timeout: 3))
|
||||
|
||||
XCTAssertTrue(app.sliders[IDs.settingsBrightness].waitForExistence(timeout: 3))
|
||||
XCTAssertTrue(app.segmentedControls[IDs.settingsLineHeight].waitForExistence(timeout: 3))
|
||||
XCTAssertTrue(app.segmentedControls[IDs.settingsColumns].waitForExistence(timeout: 3))
|
||||
XCTAssertTrue(app.segmentedControls[IDs.settingsDisplayType].waitForExistence(timeout: 3))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import XCTest
|
||||
|
||||
final class TableOfContentsTests: XCTestCase {
|
||||
private let app = XCUIApplication()
|
||||
|
||||
override func setUpWithError() throws {
|
||||
continueAfterFailure = false
|
||||
}
|
||||
|
||||
func testTocButtonExists() {
|
||||
app.launchAndOpenSampleBook(bookTitleQuery: "宝山辽墓材料与释读")
|
||||
app.waitForReader()
|
||||
app.showReaderChromeIfNeeded()
|
||||
|
||||
let tocButton = app.buttons[IDs.readerToc]
|
||||
XCTAssertTrue(tocButton.waitForExistence(timeout: 5), "目录按钮未出现")
|
||||
}
|
||||
|
||||
func testTocButtonTappable() {
|
||||
app.launchAndOpenSampleBook(bookTitleQuery: "宝山辽墓材料与释读")
|
||||
app.waitForReader()
|
||||
app.showReaderChromeIfNeeded()
|
||||
|
||||
let tocButton = app.buttons[IDs.readerToc]
|
||||
XCTAssertTrue(tocButton.waitForExistence(timeout: 5))
|
||||
XCTAssertTrue(tocButton.isEnabled, "目录按钮不可点击")
|
||||
tocButton.tap()
|
||||
|
||||
let tocPanel = app.tables[IDs.readerTocTable]
|
||||
XCTAssertTrue(tocPanel.waitForExistence(timeout: 5), "目录面板未出现")
|
||||
XCTAssertTrue(app.navigationBars[IDs.readerTocNavBar].waitForExistence(timeout: 2), "目录导航栏未暴露")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user