ListlessiOSScreenshots.swift (3663B)
1 import XCTest 2 3 final class ListlessiOSScreenshots: XCTestCase { 4 var app: XCUIApplication! 5 6 static let screenshotDir = "/tmp/listless-screenshots" 7 8 override class func setUp() { 9 super.setUp() 10 try? FileManager.default.createDirectory( 11 atPath: screenshotDir, 12 withIntermediateDirectories: true 13 ) 14 } 15 16 override func tearDownWithError() throws { 17 app.terminate() 18 } 19 20 // MARK: - Helpers 21 22 private func launchApp(_ additionalArgs: [String] = []) { 23 app = XCUIApplication() 24 app.launchArguments = ["UI_TESTING"] + additionalArgs 25 app.launch() 26 } 27 28 var draftTextField: XCUIElement { 29 app.textViews.matching(identifier: "draft-row-append").firstMatch 30 } 31 32 var itemListScrollView: XCUIElement { 33 app.scrollViews["item-list-scrollview"] 34 } 35 36 func createItem(_ title: String) { 37 let textView = draftTextField 38 if !textView.exists { 39 itemListScrollView.tap() 40 _ = textView.waitForExistence(timeout: 2) 41 } 42 textView.tap() 43 textView.typeText(title + "\n") 44 } 45 46 func itemCheckbox(at index: Int) -> XCUIElement { 47 app.buttons.matching(identifier: "item-checkbox").element(boundBy: index) 48 } 49 50 func exitEditingMode() { 51 let draft = draftTextField 52 if draft.exists { 53 draft.typeText("\n") 54 } 55 } 56 57 func saveScreenshot(name: String) { 58 let screenshot = XCUIScreen.main.screenshot() 59 let attachment = XCTAttachment(screenshot: screenshot) 60 attachment.name = name 61 attachment.lifetime = .keepAlways 62 add(attachment) 63 64 let data = screenshot.pngRepresentation 65 let path = "\(Self.screenshotDir)/\(name).png" 66 try? data.write(to: URL(fileURLWithPath: path)) 67 } 68 69 // MARK: - Screenshots 70 71 /// Five items with keyboard up: three active, one empty draft row focused, 72 /// one completed at the bottom. 73 func testScreenshot01_ItemsWithKeyboard() throws { 74 launchApp() 75 76 createItem("Add items on your iPhone") 77 createItem("Edit items on your iPad") 78 createItem("Reorder items on your Mac") 79 createItem("Complete items on your Watch") 80 exitEditingMode() 81 82 usleep(500_000) 83 84 // Complete the last item 85 let checkbox = itemCheckbox(at: 3) 86 XCTAssertTrue(checkbox.waitForExistence(timeout: 2)) 87 checkbox.tap() 88 89 usleep(500_000) 90 91 // Tap below items to create an empty focused draft row 92 let bottomArea = itemListScrollView.coordinate( 93 withNormalizedOffset: CGVector(dx: 0.5, dy: 0.9) 94 ) 95 bottomArea.tap() 96 XCTAssertTrue(draftTextField.waitForExistence(timeout: 2)) 97 usleep(300_000) 98 99 saveScreenshot(name: "01-items") 100 } 101 102 /// Empty list showing the "Pull down to create" hint. 103 func testScreenshot02_EmptyState() throws { 104 launchApp() 105 106 usleep(500_000) 107 108 saveScreenshot(name: "02-empty-state") 109 } 110 111 /// Two items with the first row swiped right past the complete threshold. 112 /// Collaroy colour theme. 113 func testScreenshot03_SwipeComplete() throws { 114 launchApp(["THEME_COLLAROY", "SCREENSHOT_SWIPE"]) 115 116 createItem("Slide left to complete") 117 createItem("Slide right to delete") 118 exitEditingMode() 119 120 usleep(500_000) 121 122 saveScreenshot(name: "03-swipe") 123 } 124 125 /// Settings sheet. 126 func testScreenshot04_Settings() throws { 127 launchApp(["SCREENSHOT_SHOW_SETTINGS"]) 128 129 usleep(500_000) 130 131 saveScreenshot(name: "04-settings") 132 } 133 }