| @@ -10,8 +10,10 @@ import XCTest |
| 10 | 10 | /// TEST_RUNNER_GITBAY_UITEST_LIVE=1 xcodebuild test \ |
| 11 | 11 | /// -only-testing:gitbayUITests ... |
| 12 | 12 | /// |
| 13 | | /// They assume the simulator is already signed in as an account that can |
| 14 | | /// write to krz/gitbay-ios, and that branch `ui-smoke` exists. |
| 13 | /// They run as the `ios-smoke` account, a krz admin that owns the |
| 14 | /// scratch and fixture repositories (smoke-account.sh provisions it), and |
| 15 | /// assume branch `ui-smoke` exists on krz/gitbay-ios. A signed-out device |
| 16 | /// is signed in at setUp from TEST_RUNNER_GITBAY_UITEST_TOKEN. |
| 15 | 17 | final class LiveSmokeUITests: XCTestCase { |
| 16 | 18 | |
| 17 | 19 | private var app: XCUIApplication! |
| @@ -22,7 +24,15 @@ final class LiveSmokeUITests: XCTestCase { |
| 22 | 24 | /// because the name is taken, which reads like a UI bug and is not. |
| 23 | 25 | /// Removed before and after, so neither a crashed run nor this one |
| 24 | 26 | /// can strand it. |
| 25 | | private static let scratchRepo = "cmc/ui-smoke" |
| 27 | private static let scratchRepo = "\(smokeUser)/ui-smoke" |
| 28 | |
| 29 | /// The account the suite runs as. smoke-account.sh creates it with |
| 30 | /// the profile description, PGP key and fixture repository the |
| 31 | /// assertions below read back. |
| 32 | static let smokeUser = "ios-smoke" |
| 33 | static let smokeProfileDescription = "Live UI smoke account for gitbay-ios" |
| 34 | static let smokePGPEmail = "ios-smoke+pgp@gitbay.org" |
| 35 | static let editRepo = "\(smokeUser)/ui-smoke-edit" |
| 26 | 36 | |
| 27 | 37 | override func setUpWithError() throws { |
| 28 | 38 | try XCTSkipUnless( |
| @@ -408,15 +418,15 @@ final class LiveSmokeUITests: XCTestCase { |
| 408 | 418 | /// The edit flow saves a change to a real file. Seeding a |
| 409 | 419 | /// repository's first commit is a push, which no test can make, so |
| 410 | 420 | /// this only checks — and says why, rather than failing later at |
| 411 | | /// "cmc/ui-smoke-edit not in the repo list". |
| 421 | /// "ios-smoke/ui-smoke-edit not in the repo list". |
| 412 | 422 | private func requireFixtureRepo() throws { |
| 413 | | guard let data = readCommand(["repo", "show", "cmc/ui-smoke-edit"]), |
| 423 | guard let data = readCommand(["repo", "show", Self.editRepo]), |
| 414 | 424 | let envelope = try? JSONSerialization.jsonObject(with: data) as? [String: Any] |
| 415 | 425 | else { return } // no token, or the instance is unreachable |
| 416 | 426 | try XCTSkipUnless(envelope["data"] != nil, """ |
| 417 | | cmc/ui-smoke-edit is missing. The edit flow saves a change to \ |
| 418 | | notes.txt in it; recreate the repo with that file (see its \ |
| 419 | | README) and run again. |
| 427 | \(Self.editRepo) is missing. The edit flow saves a change to \ |
| 428 | notes.txt in it; gitbayUITests/smoke-account.sh seeds it (or \ |
| 429 | push it by hand, see that script) and run again. |
| 420 | 430 | """) |
| 421 | 431 | } |
| 422 | 432 | |
| @@ -533,11 +543,11 @@ extension LiveSmokeUITests { |
| 533 | 543 | let createSearch = app.searchFields.firstMatch |
| 534 | 544 | XCTAssertTrue(createSearch.waitForExistence(timeout: 10)) |
| 535 | 545 | focusAndType(createSearch, "ui-smoke") |
| 536 | | XCTAssertTrue(app.staticTexts["cmc/ui-smoke"].firstMatch |
| 546 | XCTAssertTrue(app.staticTexts[Self.scratchRepo].firstMatch |
| 537 | 547 | .waitForExistence(timeout: 15), "created repo not in the list") |
| 538 | 548 | |
| 539 | 549 | // --- access: grant a user on the scratch repo, then revoke --- |
| 540 | | app.staticTexts["cmc/ui-smoke"].firstMatch.tap() |
| 550 | app.staticTexts[Self.scratchRepo].firstMatch.tap() |
| 541 | 551 | XCTAssertTrue(app.staticTexts["Files"].firstMatch.waitForExistence(timeout: 10)) |
| 542 | 552 | app.staticTexts["Settings"].firstMatch.tap() |
| 543 | 553 | let grantUser = app.descendants(matching: .any) |
| @@ -582,7 +592,7 @@ extension LiveSmokeUITests { |
| 582 | 592 | |
| 583 | 593 | // --- rename the scratch repo there and back --- |
| 584 | 594 | // Each rename pushes the renamed repository; the round-trip ends |
| 585 | | // on cmc/ui-smoke again, several screens deep. |
| 595 | // on the scratch repo again, several screens deep. |
| 586 | 596 | var firstRename = true |
| 587 | 597 | let rename: (String, String) -> Void = { newName, expectedPath in |
| 588 | 598 | if firstRename { |
| @@ -616,8 +626,8 @@ extension LiveSmokeUITests { |
| 616 | 626 | XCTAssertTrue(self.app.staticTexts[expectedPath].firstMatch.waitForExistence(timeout: 15), |
| 617 | 627 | "renamed repo did not open as \(expectedPath)") |
| 618 | 628 | } |
| 619 | | rename("ui-smoke-2", "cmc/ui-smoke-2") |
| 620 | | rename("ui-smoke", "cmc/ui-smoke") |
| 629 | rename("ui-smoke-2", Self.scratchRepo + "-2") |
| 630 | rename("ui-smoke", Self.scratchRepo) |
| 621 | 631 | |
| 622 | 632 | // --- pin / unpin round-trip on krz/gitbay-ios --- |
| 623 | 633 | // Start the list fresh; the rename left the stack several deep. |
| @@ -939,7 +949,7 @@ extension LiveSmokeUITests { |
| 939 | 949 | |
| 940 | 950 | // The PGP key's UID email, below the keys on a List that does not |
| 941 | 951 | // build rows it has not shown. |
| 942 | | XCTAssertTrue(scrollTo(app.staticTexts["hello@cleberg.net"].firstMatch), |
| 952 | XCTAssertTrue(scrollTo(app.staticTexts[Self.smokePGPEmail].firstMatch), |
| 943 | 953 | "PGP key UID missing") |
| 944 | 954 | |
| 945 | 955 | // Activity mail flips off and back on; the value comes back from |
| @@ -1010,7 +1020,7 @@ extension LiveSmokeUITests { |
| 1010 | 1020 | orgRow.tap() |
| 1011 | 1021 | |
| 1012 | 1022 | // Members render with roles. |
| 1013 | | XCTAssertTrue(app.staticTexts["cmc"].firstMatch |
| 1023 | XCTAssertTrue(app.staticTexts[Self.smokeUser].firstMatch |
| 1014 | 1024 | .waitForExistence(timeout: 15), "org members missing") |
| 1015 | 1025 | |
| 1016 | 1026 | // Create a team. |
| @@ -1176,7 +1186,7 @@ extension LiveSmokeUITests { |
| 1176 | 1186 | // previous query, and clearing it from the harness is unreliable. |
| 1177 | 1187 | app.terminate() |
| 1178 | 1188 | app.launch() |
| 1179 | | openRepo("cmc/ui-smoke-edit") |
| 1189 | openRepo(Self.editRepo) |
| 1180 | 1190 | app.staticTexts["Files"].firstMatch.tap() |
| 1181 | 1191 | let notes = app.staticTexts["notes.txt"].firstMatch |
| 1182 | 1192 | XCTAssertTrue(notes.waitForExistence(timeout: 15), "notes.txt not in the tree") |
| @@ -1242,7 +1252,7 @@ extension LiveSmokeUITests { |
| 1242 | 1252 | |
| 1243 | 1253 | // --- a profile is a profile: description, links, orgs, graph, repos --- |
| 1244 | 1254 | XCTAssertTrue(app.staticTexts |
| 1245 | | .containing(NSPredicate(format: "label CONTAINS 'Self-Hosting'")).firstMatch |
| 1255 | .containing(NSPredicate(format: "label CONTAINS %@", Self.smokeProfileDescription)).firstMatch |
| 1246 | 1256 | .waitForExistence(timeout: 20), "profile description missing") |
| 1247 | 1257 | XCTAssertTrue(header("Organizations").exists, |
| 1248 | 1258 | "org memberships missing") |
| @@ -1467,8 +1477,10 @@ extension LiveSmokeUITests { |
| 1467 | 1477 | snap("feed") |
| 1468 | 1478 | |
| 1469 | 1479 | selectTab("My Profile") |
| 1470 | | XCTAssertTrue(app.staticTexts |
| 1471 | | .containing(NSPredicate(format: "label CONTAINS 'Self-Hosting'")).firstMatch |
| 1480 | // Any signed-in account can edit its own profile, so this holds |
| 1481 | // for store screenshots taken as a real user too. |
| 1482 | XCTAssertTrue(app.descendants(matching: .any) |
| 1483 | .matching(identifier: "profile-edit-button").firstMatch |
| 1472 | 1484 | .waitForExistence(timeout: 20), "profile did not load") |
| 1473 | 1485 | snap("profile") |
| 1474 | 1486 | } |
| @@ -1631,7 +1643,7 @@ extension LiveSmokeUITests { |
| 1631 | 1643 | let orgRow = app.staticTexts[Self.smokeOrg].firstMatch |
| 1632 | 1644 | XCTAssertTrue(orgRow.waitForExistence(timeout: 15), "org list missing") |
| 1633 | 1645 | orgRow.tap() |
| 1634 | | XCTAssertTrue(app.staticTexts["cmc"].firstMatch.waitForExistence(timeout: 15), |
| 1646 | XCTAssertTrue(app.staticTexts[Self.smokeUser].firstMatch.waitForExistence(timeout: 15), |
| 1635 | 1647 | "org members missing") |
| 1636 | 1648 | |
| 1637 | 1649 | // --- labels --- |