test: fix tests

This commit is contained in:
Stefan Hausotte 2026-03-11 19:42:25 +01:00
parent 781826004b
commit eede8a3467
6 changed files with 60 additions and 59 deletions

View file

@ -240,27 +240,38 @@ struct SearchableOverviewView<Row: View, Detail: View, CreateView: View>: View {
}
private func searchIssues(service: IssueService, page: Int, limit: Int) async throws -> [Issue] {
// Forgejo's search (q=) does not work with involvement scope flags
// (assigned, created, mentioned). When a search query is active, search
// globally by type and state only. The scoped view returns when the
// user clears the search.
if !searchText.isEmpty {
return try await service.searchIssues(
type: issueType, state: stateFilter.rawValue, query: searchText,
page: page, limit: limit,
)
}
switch involvementScope {
case .involved:
try await searchInvolved(service: service, page: page, limit: limit)
return try await searchInvolved(service: service, page: page, limit: limit)
case .created:
try await service.searchIssues(
type: issueType, state: stateFilter.rawValue, query: searchText,
return try await service.searchIssues(
type: issueType, state: stateFilter.rawValue,
page: page, limit: limit, created: true,
)
case .assigned:
try await service.searchIssues(
type: issueType, state: stateFilter.rawValue, query: searchText,
return try await service.searchIssues(
type: issueType, state: stateFilter.rawValue,
page: page, limit: limit, assigned: true,
)
case .mentioned:
try await service.searchIssues(
type: issueType, state: stateFilter.rawValue, query: searchText,
return try await service.searchIssues(
type: issueType, state: stateFilter.rawValue,
page: page, limit: limit, mentioned: true,
)
case .reviewRequested:
try await service.searchIssues(
type: issueType, state: stateFilter.rawValue, query: searchText,
return try await service.searchIssues(
type: issueType, state: stateFilter.rawValue,
page: page, limit: limit, reviewRequested: true,
)
}
@ -273,14 +284,13 @@ struct SearchableOverviewView<Row: View, Detail: View, CreateView: View>: View {
private func searchInvolved(service: IssueService, page: Int, limit: Int) async throws -> [Issue] {
let type = issueType
let state = stateFilter.rawValue
let query = searchText
let batches = try await withThrowingTaskGroup(of: [Issue].self) { group in
for flag in involvedFlags {
group.addTask {
try await resilientFetch {
try await service.searchIssues(
type: type, state: state, query: query, page: page, limit: limit,
type: type, state: state, page: page, limit: limit,
assigned: flag == .assigned, created: flag == .created,
mentioned: flag == .mentioned, reviewRequested: flag == .reviewRequested,
)

View file

@ -13,23 +13,16 @@ final class IssueUITests: ForgejoReadOnlyUITestBase {
func testIssuesOverview() throws {
app.tabBars.buttons["Issues"].tap()
// Issues list loads (may show pagination test issues first on page 1)
XCTAssertTrue(app.cells.firstMatch.waitForExistence(timeout: 10), "Issues should load")
// Wait for initial load (default scope: Open + All involvement)
XCTAssertTrue(app.cells.firstMatch.waitForExistence(timeout: 15), "Issues should load")
// Filter All via toolbar menu
let filterMenuButton = app.buttons["filter-menu-button"]
XCTAssertTrue(filterMenuButton.waitForExistence(timeout: 5))
filterMenuButton.tap()
app.buttons["All"].firstMatch.tap()
XCTAssertTrue(app.cells.firstMatch.waitForExistence(timeout: 10), "Issues should load after filter change")
// Search narrows results to specific issue (unique keyword avoids pagination test issues)
// Search narrows results to a specific issue
let searchField = app.searchFields.firstMatch
XCTAssertTrue(searchField.waitForExistence(timeout: 5))
searchField.tap()
searchField.typeText("integration")
searchField.typeText("Pagination test issue 25")
XCTAssertTrue(app.staticTexts["Test issue 1 from integration tests"].waitForExistence(timeout: 10))
XCTAssertTrue(app.staticTexts["Pagination test issue 25"].waitForExistence(timeout: 15))
}
// MARK: - Issues Overview Involvement Filter
@ -44,10 +37,10 @@ final class IssueUITests: ForgejoReadOnlyUITestBase {
// Wait for list to load
XCTAssertTrue(app.cells.firstMatch.waitForExistence(timeout: 10), "Issues should load")
// Default filter summary should show "Open · Created by you"
// Default filter summary should show "Open" (default scope is All involvement)
let filterSummary = app.staticTexts["filter-summary"]
XCTAssertTrue(filterSummary.waitForExistence(timeout: 5))
XCTAssertEqual(filterSummary.label, "Open · Created by you")
XCTAssertEqual(filterSummary.label, "Open")
let filterMenuButton = app.buttons["filter-menu-button"]
@ -63,11 +56,11 @@ final class IssueUITests: ForgejoReadOnlyUITestBase {
sleep(2)
XCTAssertTrue(filterSummary.label.contains("Mentioned"))
// Tap back to "All" scope via filter menu
// Tap "Created by you" via filter menu
filterMenuButton.tap()
// The scope "All" button use firstMatch since "All" also appears in State section
app.buttons["All"].firstMatch.tap()
app.buttons["Created by you"].tap()
sleep(2)
XCTAssertTrue(filterSummary.label.contains("Created by you"))
// "Review requested" should NOT be present for issues
filterMenuButton.tap()
@ -113,7 +106,7 @@ final class IssueUITests: ForgejoReadOnlyUITestBase {
allButtons.element(boundBy: 1).tap()
XCTAssertTrue(filterSummary.waitForExistence(timeout: 5))
XCTAssertEqual(filterSummary.label, "All · All",
XCTAssertEqual(filterSummary.label, "All · All involvement",
"Filter summary should show All state and All scope")
// The key assertion: items must actually load

View file

@ -13,10 +13,7 @@ final class OverviewCreateUITests: ForgejoReadOnlyUITestBase {
func testCreatePRFromOverview() throws {
app.tabBars.buttons["Pull Requests"].tap()
// Test PRs were created by testbot switch scope to "All" to see them
setOverviewScopeAll()
// Wait for the PR list to load
// Default scope is "All involvement" testadmin is assigned to PR #4
XCTAssertTrue(app.staticTexts["Add feature file"].waitForExistence(timeout: 10))
// Tap floating create button

View file

@ -90,16 +90,8 @@ final class PullRequestUITests: ForgejoReadOnlyUITestBase {
func testPullRequestsOverview() throws {
app.tabBars.buttons["Pull Requests"].tap()
// Test PRs were created by testbot switch scope to "All" to see them
setOverviewScopeAll()
XCTAssertTrue(app.staticTexts["Add feature file"].waitForExistence(timeout: 10))
// Filter state to All via toolbar menu
let filterMenuButton = app.buttons["filter-menu-button"]
XCTAssertTrue(filterMenuButton.waitForExistence(timeout: 5))
filterMenuButton.tap()
app.buttons["All"].firstMatch.tap()
// Wait for initial load to complete (testadmin is assigned to PR #4)
XCTAssertTrue(app.staticTexts["Add feature file"].waitForExistence(timeout: 15))
// Search
let searchField = app.searchFields.firstMatch
@ -107,7 +99,7 @@ final class PullRequestUITests: ForgejoReadOnlyUITestBase {
searchField.tap()
searchField.typeText("feature")
XCTAssertTrue(app.staticTexts["Add feature file"].waitForExistence(timeout: 10))
XCTAssertTrue(app.staticTexts["Add feature file"].waitForExistence(timeout: 15))
}
// MARK: - Pull Requests Overview Involvement Filter
@ -119,10 +111,10 @@ final class PullRequestUITests: ForgejoReadOnlyUITestBase {
// Reset filters to defaults (previous test may have changed them)
resetOverviewFilters()
// Default filter summary should show "Open · Created by you"
// Default filter summary should show "Open" (default scope is All involvement)
let filterSummary = app.staticTexts["filter-summary"]
XCTAssertTrue(filterSummary.waitForExistence(timeout: 5))
XCTAssertEqual(filterSummary.label, "Open · Created by you")
XCTAssertEqual(filterSummary.label, "Open")
let filterMenuButton = app.buttons["filter-menu-button"]
@ -138,10 +130,11 @@ final class PullRequestUITests: ForgejoReadOnlyUITestBase {
sleep(2)
XCTAssertTrue(filterSummary.label.contains("Mentioned"))
// Tap back to "All" scope via filter menu
// Tap "Created by you" via filter menu
filterMenuButton.tap()
app.buttons["All"].firstMatch.tap()
app.buttons["Created by you"].tap()
sleep(2)
XCTAssertTrue(filterSummary.label.contains("Created by you"))
// "Review requested" SHOULD be present for PRs
filterMenuButton.tap()

View file

@ -28,16 +28,14 @@ extension UITestNavigating {
picker.buttons["Pull Requests"].tap()
}
/// Resets the overview filter to Open + Created by you (the app defaults).
/// Resets the overview filter to Open + All involvement (the app defaults).
func resetOverviewFilters() {
let filterMenuButton = app.buttons["filter-menu-button"]
guard filterMenuButton.waitForExistence(timeout: 5) else { return }
filterMenuButton.tap()
app.buttons["Open"].tap()
sleep(1)
filterMenuButton.tap()
app.buttons["Created by you"].tap()
sleep(1)
setOverviewScopeAll()
}
/// Switches the overview scope to "All" to show items from all users.

View file

@ -60,17 +60,27 @@ curl -sf -X POST "$BASE_URL/api/v1/user/repos" \
wait
echo "Repositories created."
# Archive the archived-repo
# Archive the archived-repo (retry — the repo may not be ready immediately after creation)
echo "Archiving archived-repo..."
curl -sf -X PATCH "$BASE_URL/api/v1/repos/$ADMIN_USER/archived-repo" \
-u "$ADMIN_AUTH" \
-H "Content-Type: application/json" \
-d '{"archived": true}'
for attempt in 1 2 3; do
if curl -sf -X PATCH "$BASE_URL/api/v1/repos/$ADMIN_USER/archived-repo" \
-u "$ADMIN_AUTH" \
-H "Content-Type: application/json" \
-d '{"archived": true}'; then
break
fi
echo " Archive attempt $attempt failed, retrying..."
sleep 1
done
# Update html-readme-repo README with HTML content
echo "Updating html-readme-repo README..."
README_SHA=$(curl -sf "$BASE_URL/api/v1/repos/$ADMIN_USER/html-readme-repo/contents/README.md" \
-u "$ADMIN_AUTH" | python3 -c "import sys,json; print(json.load(sys.stdin)['sha'])")
for attempt in 1 2 3; do
README_SHA=$(curl -sf "$BASE_URL/api/v1/repos/$ADMIN_USER/html-readme-repo/contents/README.md" \
-u "$ADMIN_AUTH" | python3 -c "import sys,json; print(json.load(sys.stdin)['sha'])" 2>/dev/null) && break
echo " README fetch attempt $attempt failed, retrying..."
sleep 1
done
README_PAYLOAD=$(python3 -c "
import base64, json
content = '''# HTML Readme Test