Reputation: 4502
I am trying to add UI tests to a SwiftUI project.
I have a list, which contains views - those then contain a number of views.
I cannot seem to access the furthest most view in my UI test.
I thought I could add an accessibility identifier to each element but I cannot make my test pass still.
A very simple example;
ContentView
struct ListModel: Identifiable {
let id: String
let text: String
}
struct ContentView: View {
private var state = (0..<50).map { ListModel(id: "\($0)", text: "Row \($0)") }
var body: some View {
List(state, id: \.id) { item in
ContentViewRow(text: item.text)
.accessibility(identifier: "FEED_ITEM")
}
.accessibility(identifier: "FEED")
}
}
struct ContentViewRow: View {
let text: String
var body: some View {
Text(text)
.accessibility(identifier: "CONTENT_ROW_TEXT")
}
}
Tests
class TestingSwiftUIUITests: XCTestCase {
func testExample() throws {
// UI tests must launch the application that they test.
let app = XCUIApplication()
app.launch()
let feed = app.tables["FEED"]
XCTAssert(feed.waitForExistence(timeout: 0.5))
let row0 = feed.staticTexts["FEED_ITEM"].firstMatch
XCTAssert(row0.waitForExistence(timeout: 0.5))
let textView = row0.staticTexts["CONTENT_ROW_TEXT"].firstMatch
XCTAssert(textView.waitForExistence(timeout: 0.5)) // <-- This fails.
}
}
How can I access a view inside ContentViewRow
- thank you.
Upvotes: 2
Views: 906
Reputation: 250
identifier: CONTENT_ROW_TEXT
seems to be overriden by identifier: FEED_ITEM
Perhaps you can leave just FEED_ITEM
and check for the label text if needed.
let row0 = feed.staticTexts["FEED_ITEM"].firstMatch
XCTAssert(row0.waitForExistence(timeout: 0.5))
XCTAssert(row0.label == "Row 0")
Upvotes: 2
Reputation: 161
List UITestCase in SwiftUI
Swift UI View Code
struct ContentView: View {
@StateObject var viewModel = ContentViewModel()
var body: some View {
NavigationView {
List(viewModel.list, id: \.id) { item in
NavigationLink(destination: self.detailsView(content: item)) {
ContentViewRow(text: item.text)
.accessibility(identifier: "FEED_ITEM_\(item.id)")
}
}
.listStyle(.plain)
.padding(.all, 20)
.accessibility(identifier: "FEED")
.onAppear {
self.viewModel.publishListModel()
}
.navigationTitle("List")
}
}
func detailsView(content: ListModel) -> some View {
return ContestDetailsView(content: content)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct ContentViewRow: View {
let text: String
var body: some View {
Text(text)
.accessibility(identifier: "CONTENT_ROW_TEXT")
}
}
struct ContestDetailsView: View {
var content: ListModel
var body: some View {
Text(content.text)
.navigationTitle("Details")
.accessibility(identifier: "FEED_Details")
}
}
UI Test Case
func testTableList() throws {
// UI tests must launch the application that they test.
let app = XCUIApplication()
app.launch()
let pred = NSPredicate(format: "identifier == 'FEED'")
let tableView = app.descendants(matching: .any).matching(pred).firstMatch
let arrOfTexts = tableView.staticTexts
XCTAssertGreaterThan(arrOfTexts.count, 10)
// let feed = app.tables["FEED"]
XCTAssert(tableView.waitForExistence(timeout: 0.5))
let row7 = tableView.staticTexts["FEED_ITEM_7"].firstMatch
XCTAssert(row7.waitForExistence(timeout: 0.5))
//let textView = row7.staticTexts["Row 7"].firstMatch
//XCTAssert(textView.waitForExistence(timeout: 0.5)) // <-- This fails.
row7.tap()
let textView = app.staticTexts["Row 7"]
// If the text ran successfully, the the above textView will be != Nil
XCTAssertEqual(textView.exists, true)
}
Upvotes: 0