Update UI tests

This commit is contained in:
Balazs Perlaki-Horvath 2025-06-14 14:46:32 +02:00 committed by BPH
parent 9b0dab3faf
commit b19028f19c
9 changed files with 84 additions and 28 deletions

View File

@ -64,7 +64,7 @@ jobs:
- name: Run Unit Tests on iOS
if: matrix.platform == 'iOS'
run: xcodebuild test -scheme Kiwix -destination 'platform=iOS Simulator,name=iPhone 16 Pro'
run: xcodebuild clean test -scheme Kiwix -destination 'platform=iOS Simulator,name=iPhone 16 Pro'
- name: Run Unit Tests on macOS
if: matrix.platform == 'macOS'
@ -75,13 +75,17 @@ jobs:
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- name: Run UI Tests on iPhone
if: matrix.platform == 'iOS'
run: xcodebuild test -scheme UITests_iPhone -destination 'platform=iOS Simulator,name=iPhone 16 Pro'
# - name: Run UI Tests on iPhone
# if: matrix.platform == 'iOS'
# env:
# DEVICE_NAME: "iPhone 16 Pro Max"
# run: xcodebuild test -scheme UITests_iPhone -destination "platform=iOS Simulator,name=$DEVICE_NAME"
- name: Run UI Tests on iPad
if: matrix.platform == 'iOS'
run: xcodebuild test -scheme UITests_iPad -destination 'platform=iOS Simulator,name=iPad Pro 13-inch (M4)'
# - name: Run UI Tests on iPad
# if: matrix.platform == 'iOS'
# env:
# DEVICE_NAME: "iPad Pro 13-inch (M4)"
# run: xcodebuild test -scheme UITests_iPad -destination "platform=iOS Simulator,name=$DEVICE_NAME"
- name: Run UI Tests on macOS
if: matrix.platform == 'macOS'

View File

@ -15,6 +15,7 @@
protocol Parser {
var zimFileIDs: Set<UUID> { get }
@ZimActor
func parse(data: Data, urlHost: String) throws
func getMetaData(id: UUID) -> ZimFileMetaData?
}
@ -24,6 +25,7 @@ extension OPDSParser: Parser {
__getZimFileIDs() as? Set<UUID> ?? Set<UUID>()
}
@ZimActor
func parse(data: Data, urlHost: String) throws {
if !self.__parseData(data, using: urlHost.removingSuffix("/")) {
throw LibraryRefreshError.parse

View File

@ -240,13 +240,21 @@ final class LibraryRefreshViewModelTest: XCTestCase {
func testZimFileDeprecation() async throws {
let testDefaults = TestDefaults()
testDefaults.setup()
let context = Database.shared.viewContext
let oldZimFiles = try? context.fetch(ZimFile.fetchRequest())
oldZimFiles?.forEach { zimFile in
context.delete(zimFile)
}
if context.hasChanges {
try? context.save()
}
// refresh library for the first time, which should create one zim file
let viewModel = LibraryViewModel(urlSession: urlSession,
processFactory: { LibraryProcess(defaultState: .initial) },
defaults: testDefaults,
categories: CategoriesToLanguages(withDefaults: testDefaults))
await viewModel.start(isUserInitiated: true)
let context = Database.shared.viewContext
let zimFile1 = try XCTUnwrap(try context.fetch(ZimFile.fetchRequest()).first)
// refresh library for the second time, which should replace the old zim file with a new one
@ -271,6 +279,8 @@ final class LibraryRefreshViewModelTest: XCTestCase {
// clean up
context.delete(zimFile1)
context.delete(zimFile2)
try? context.save()
}
}

View File

@ -18,6 +18,7 @@ import XCTest
final class OPDSParserTests: XCTestCase {
/// Test OPDSParser.parse throws error when OPDS data is invalid.
@ZimActor
func testInvalidOPDSData() {
XCTExpectFailure("Requires work in dependency to resolve the issue.")
let content = "Invalid OPDS Data"
@ -26,6 +27,7 @@ final class OPDSParserTests: XCTestCase {
)
}
@ZimActor
func testNonCompatibleDataWithUT8() throws {
let content = "any data"
let incompatibleEncodings: [String.Encoding] = [.unicode, .utf16, .utf32]
@ -44,6 +46,7 @@ final class OPDSParserTests: XCTestCase {
}
/// Test OPDSParser can parse and extract zim file metadata.
@ZimActor
func test() throws {
let content = """
<feed xmlns="http://www.w3.org/2005/Atom"

View File

@ -19,19 +19,59 @@ final class LoadingUI_iPad_Test: XCTestCase {
@MainActor
func testLaunchingApp_on_iPad() throws {
let app = XCUIApplication()
app.activate()
if !XCUIDevice.shared.orientation.isLandscape {
XCUIDevice.shared.orientation = .landscapeLeft
}
let app = XCUIApplication()
app.activate()
app.buttons.matching(identifier: "ToggleSidebar").element.tap()
if !app.collectionViews["sidebar_collection_view"].exists {
app.buttons.matching(identifier: "ToggleSidebar").element.tap()
}
let sidebar = app.collectionViews["sidebar_collection_view"]
sidebar.cells["categories"].tap()
app.buttons["Category, Wikipedia"].tap()
app.buttons["Other"].tap()
XCTAssert(sidebar.cells["New Tab"].isSelected)
let zimMini = app.buttons["Apache Pig Docs"].firstMatch
Wait.inApp(app, forElement: zimMini)
zimMini.tap()
let downloadButton = app.buttons["Download"].firstMatch
Wait.inApp(app, forElement: downloadButton)
downloadButton.tap()
addUIInterruptionMonitor(withDescription: "\"Kiwix\" Would Like To Send You Notifications") { (alert) -> Bool in
let alertButton = alert.buttons["Allow"]
if alertButton.exists {
alertButton.tap()
return true
}
return false
}
let openMainPageButton = app.buttons["Open Main Page"]
Wait.inApp(app, forElement: openMainPageButton)
openMainPageButton.tap()
usleep(1)
// RESTART THE APP
app.terminate()
usleep(1)
app.activate()
testAfterRelaunch(app)
app.terminate()
}
private func testAfterRelaunch(_ app: XCUIApplication) {
let sidebar = app.collectionViews["sidebar_collection_view"]
let zimFileTab = sidebar.cells["Apache Pig Documentation"].firstMatch
Wait.inApp(app, forElement: zimFileTab)
XCTAssert(sidebar.cells["Apache Pig Documentation"].firstMatch.isSelected)
sidebar.cells["bookmarks"].tap()
sidebar.cells["opened"].tap()
@ -40,5 +80,6 @@ final class LoadingUI_iPad_Test: XCTestCase {
sidebar.cells["new"].tap()
sidebar.cells["settings"].tap()
sidebar.cells["donation"].tap()
app.buttons["close_payment_button"].tap()
}
}

View File

@ -131,7 +131,7 @@ final class LibraryViewModel: ObservableObject {
process.state = .inProgress
// refresh library
guard case (var data, let responseURL)? = try await fetchData() else {
guard case (let data, let responseURL)? = try await fetchData() else {
// this is the case when we have no new data (304 http)
// but we still need to refresh the memory only stored
// zimfile categories to languages dictionary
@ -283,19 +283,13 @@ final class LibraryViewModel: ObservableObject {
}
private func parse(data: Data, urlHost: URL) async throws -> OPDSParser {
try await withCheckedThrowingContinuation { continuation in
let parser = OPDSParser()
do {
let urlHostString = urlHost
.withoutQueryParams()
.trim(pathComponents: ["catalog", "v2", "entries"])
.absoluteString
try parser.parse(data: data, urlHost: urlHostString)
continuation.resume(returning: parser)
} catch {
continuation.resume(throwing: error)
}
}
let parser = OPDSParser()
let urlHostString = urlHost
.withoutQueryParams()
.trim(pathComponents: ["catalog", "v2", "entries"])
.absoluteString
try await parser.parse(data: data, urlHost: urlHostString)
return parser
}
private func process(parser: Parser) async throws {

View File

@ -228,7 +228,7 @@ struct LibraryZimFileContext<Content: View>: View {
ZimFileDetail(zimFile: zimFile, dismissParent: dismiss)
} label: {
content
}
} .accessibilityIdentifier(zimFile.name)
#endif
}.contextMenu {
ZimFileContextMenu(zimFile: zimFile)

View File

@ -45,6 +45,7 @@ struct PaymentForm: View {
Button("", systemImage: "x.circle.fill") {
dismiss()
}
.accessibilityIdentifier("close_payment_button")
.font(.title)
.foregroundStyle(.tertiary)
.padding()

View File

@ -65,6 +65,7 @@ struct PaymentResultPopUp: View {
Button("", systemImage: "x.circle.fill") {
dismiss()
}
.accessibilityIdentifier("close_payment_button")
.font(.title2)
.foregroundStyle(.secondary)
.padding()