mirror of
https://github.com/kiwix/kiwix-apple.git
synced 2025-09-13 22:26:45 -04:00
Update UI tests
This commit is contained in:
parent
9b0dab3faf
commit
b19028f19c
18
.github/workflows/ci.yml
vendored
18
.github/workflows/ci.yml
vendored
@ -64,7 +64,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Run Unit Tests on iOS
|
- name: Run Unit Tests on iOS
|
||||||
if: matrix.platform == '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
|
- name: Run Unit Tests on macOS
|
||||||
if: matrix.platform == 'macOS'
|
if: matrix.platform == 'macOS'
|
||||||
@ -75,13 +75,17 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
|
||||||
- name: Run UI Tests on iPhone
|
# - name: Run UI Tests on iPhone
|
||||||
if: matrix.platform == 'iOS'
|
# if: matrix.platform == 'iOS'
|
||||||
run: xcodebuild test -scheme UITests_iPhone -destination 'platform=iOS Simulator,name=iPhone 16 Pro'
|
# 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
|
# - name: Run UI Tests on iPad
|
||||||
if: matrix.platform == 'iOS'
|
# if: matrix.platform == 'iOS'
|
||||||
run: xcodebuild test -scheme UITests_iPad -destination 'platform=iOS Simulator,name=iPad Pro 13-inch (M4)'
|
# 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
|
- name: Run UI Tests on macOS
|
||||||
if: matrix.platform == 'macOS'
|
if: matrix.platform == 'macOS'
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
protocol Parser {
|
protocol Parser {
|
||||||
var zimFileIDs: Set<UUID> { get }
|
var zimFileIDs: Set<UUID> { get }
|
||||||
|
@ZimActor
|
||||||
func parse(data: Data, urlHost: String) throws
|
func parse(data: Data, urlHost: String) throws
|
||||||
func getMetaData(id: UUID) -> ZimFileMetaData?
|
func getMetaData(id: UUID) -> ZimFileMetaData?
|
||||||
}
|
}
|
||||||
@ -24,6 +25,7 @@ extension OPDSParser: Parser {
|
|||||||
__getZimFileIDs() as? Set<UUID> ?? Set<UUID>()
|
__getZimFileIDs() as? Set<UUID> ?? Set<UUID>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ZimActor
|
||||||
func parse(data: Data, urlHost: String) throws {
|
func parse(data: Data, urlHost: String) throws {
|
||||||
if !self.__parseData(data, using: urlHost.removingSuffix("/")) {
|
if !self.__parseData(data, using: urlHost.removingSuffix("/")) {
|
||||||
throw LibraryRefreshError.parse
|
throw LibraryRefreshError.parse
|
||||||
|
@ -240,13 +240,21 @@ final class LibraryRefreshViewModelTest: XCTestCase {
|
|||||||
func testZimFileDeprecation() async throws {
|
func testZimFileDeprecation() async throws {
|
||||||
let testDefaults = TestDefaults()
|
let testDefaults = TestDefaults()
|
||||||
testDefaults.setup()
|
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
|
// refresh library for the first time, which should create one zim file
|
||||||
let viewModel = LibraryViewModel(urlSession: urlSession,
|
let viewModel = LibraryViewModel(urlSession: urlSession,
|
||||||
processFactory: { LibraryProcess(defaultState: .initial) },
|
processFactory: { LibraryProcess(defaultState: .initial) },
|
||||||
defaults: testDefaults,
|
defaults: testDefaults,
|
||||||
categories: CategoriesToLanguages(withDefaults: testDefaults))
|
categories: CategoriesToLanguages(withDefaults: testDefaults))
|
||||||
await viewModel.start(isUserInitiated: true)
|
await viewModel.start(isUserInitiated: true)
|
||||||
let context = Database.shared.viewContext
|
|
||||||
let zimFile1 = try XCTUnwrap(try context.fetch(ZimFile.fetchRequest()).first)
|
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
|
// 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
|
// clean up
|
||||||
context.delete(zimFile1)
|
context.delete(zimFile1)
|
||||||
context.delete(zimFile2)
|
context.delete(zimFile2)
|
||||||
|
|
||||||
|
try? context.save()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ import XCTest
|
|||||||
|
|
||||||
final class OPDSParserTests: XCTestCase {
|
final class OPDSParserTests: XCTestCase {
|
||||||
/// Test OPDSParser.parse throws error when OPDS data is invalid.
|
/// Test OPDSParser.parse throws error when OPDS data is invalid.
|
||||||
|
@ZimActor
|
||||||
func testInvalidOPDSData() {
|
func testInvalidOPDSData() {
|
||||||
XCTExpectFailure("Requires work in dependency to resolve the issue.")
|
XCTExpectFailure("Requires work in dependency to resolve the issue.")
|
||||||
let content = "Invalid OPDS Data"
|
let content = "Invalid OPDS Data"
|
||||||
@ -26,6 +27,7 @@ final class OPDSParserTests: XCTestCase {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ZimActor
|
||||||
func testNonCompatibleDataWithUT8() throws {
|
func testNonCompatibleDataWithUT8() throws {
|
||||||
let content = "any data"
|
let content = "any data"
|
||||||
let incompatibleEncodings: [String.Encoding] = [.unicode, .utf16, .utf32]
|
let incompatibleEncodings: [String.Encoding] = [.unicode, .utf16, .utf32]
|
||||||
@ -44,6 +46,7 @@ final class OPDSParserTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Test OPDSParser can parse and extract zim file metadata.
|
/// Test OPDSParser can parse and extract zim file metadata.
|
||||||
|
@ZimActor
|
||||||
func test() throws {
|
func test() throws {
|
||||||
let content = """
|
let content = """
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom"
|
<feed xmlns="http://www.w3.org/2005/Atom"
|
||||||
|
@ -19,19 +19,59 @@ final class LoadingUI_iPad_Test: XCTestCase {
|
|||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
func testLaunchingApp_on_iPad() throws {
|
func testLaunchingApp_on_iPad() throws {
|
||||||
|
let app = XCUIApplication()
|
||||||
|
app.activate()
|
||||||
|
|
||||||
if !XCUIDevice.shared.orientation.isLandscape {
|
if !XCUIDevice.shared.orientation.isLandscape {
|
||||||
XCUIDevice.shared.orientation = .landscapeLeft
|
XCUIDevice.shared.orientation = .landscapeLeft
|
||||||
}
|
}
|
||||||
|
|
||||||
let app = XCUIApplication()
|
if !app.collectionViews["sidebar_collection_view"].exists {
|
||||||
app.activate()
|
app.buttons.matching(identifier: "ToggleSidebar").element.tap()
|
||||||
|
}
|
||||||
app.buttons.matching(identifier: "ToggleSidebar").element.tap()
|
|
||||||
|
|
||||||
let sidebar = app.collectionViews["sidebar_collection_view"]
|
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["bookmarks"].tap()
|
||||||
sidebar.cells["opened"].tap()
|
sidebar.cells["opened"].tap()
|
||||||
@ -40,5 +80,6 @@ final class LoadingUI_iPad_Test: XCTestCase {
|
|||||||
sidebar.cells["new"].tap()
|
sidebar.cells["new"].tap()
|
||||||
sidebar.cells["settings"].tap()
|
sidebar.cells["settings"].tap()
|
||||||
sidebar.cells["donation"].tap()
|
sidebar.cells["donation"].tap()
|
||||||
|
app.buttons["close_payment_button"].tap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ final class LibraryViewModel: ObservableObject {
|
|||||||
process.state = .inProgress
|
process.state = .inProgress
|
||||||
|
|
||||||
// refresh library
|
// 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)
|
// this is the case when we have no new data (304 http)
|
||||||
// but we still need to refresh the memory only stored
|
// but we still need to refresh the memory only stored
|
||||||
// zimfile categories to languages dictionary
|
// zimfile categories to languages dictionary
|
||||||
@ -283,19 +283,13 @@ final class LibraryViewModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func parse(data: Data, urlHost: URL) async throws -> OPDSParser {
|
private func parse(data: Data, urlHost: URL) async throws -> OPDSParser {
|
||||||
try await withCheckedThrowingContinuation { continuation in
|
let parser = OPDSParser()
|
||||||
let parser = OPDSParser()
|
let urlHostString = urlHost
|
||||||
do {
|
.withoutQueryParams()
|
||||||
let urlHostString = urlHost
|
.trim(pathComponents: ["catalog", "v2", "entries"])
|
||||||
.withoutQueryParams()
|
.absoluteString
|
||||||
.trim(pathComponents: ["catalog", "v2", "entries"])
|
try await parser.parse(data: data, urlHost: urlHostString)
|
||||||
.absoluteString
|
return parser
|
||||||
try parser.parse(data: data, urlHost: urlHostString)
|
|
||||||
continuation.resume(returning: parser)
|
|
||||||
} catch {
|
|
||||||
continuation.resume(throwing: error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func process(parser: Parser) async throws {
|
private func process(parser: Parser) async throws {
|
||||||
|
@ -228,7 +228,7 @@ struct LibraryZimFileContext<Content: View>: View {
|
|||||||
ZimFileDetail(zimFile: zimFile, dismissParent: dismiss)
|
ZimFileDetail(zimFile: zimFile, dismissParent: dismiss)
|
||||||
} label: {
|
} label: {
|
||||||
content
|
content
|
||||||
}
|
} .accessibilityIdentifier(zimFile.name)
|
||||||
#endif
|
#endif
|
||||||
}.contextMenu {
|
}.contextMenu {
|
||||||
ZimFileContextMenu(zimFile: zimFile)
|
ZimFileContextMenu(zimFile: zimFile)
|
||||||
|
@ -45,6 +45,7 @@ struct PaymentForm: View {
|
|||||||
Button("", systemImage: "x.circle.fill") {
|
Button("", systemImage: "x.circle.fill") {
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
.accessibilityIdentifier("close_payment_button")
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.foregroundStyle(.tertiary)
|
.foregroundStyle(.tertiary)
|
||||||
.padding()
|
.padding()
|
||||||
|
@ -65,6 +65,7 @@ struct PaymentResultPopUp: View {
|
|||||||
Button("", systemImage: "x.circle.fill") {
|
Button("", systemImage: "x.circle.fill") {
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
.accessibilityIdentifier("close_payment_button")
|
||||||
.font(.title2)
|
.font(.title2)
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
.padding()
|
.padding()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user