/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import XCTest class BaseTestCase: XCTestCase { override func setUp() { super.setUp() continueAfterFailure = false let app = XCUIApplication() app.terminate() restart(app, args: [LaunchArguments.ClearProfile, LaunchArguments.SkipIntro, LaunchArguments.SkipWhatsNew]) } override func tearDown() { XCUIApplication().terminate() super.tearDown() } func restart(_ app: XCUIApplication, args: [String] = []) { XCUIDevice.shared().press(.home) var launchArguments = [LaunchArguments.Test] args.forEach { arg in launchArguments.append(arg) } app.launchArguments = launchArguments app.activate() } //If it is a first run, first run window should be gone func dismissFirstRunUI() { let firstRunUI = XCUIApplication().scrollViews["IntroViewController.scrollView"] if firstRunUI.exists { firstRunUI.swipeLeft() XCUIApplication().buttons["Start Browsing"].tap() } } func waitforExistence(_ element: XCUIElement, file: String = #file, line: UInt = #line) { waitFor(element, with: "exists == true", file: file, line: line) } func waitforNoExistence(_ element: XCUIElement, timeoutValue: TimeInterval = 5.0, file: String = #file, line: UInt = #line) { waitFor(element, with: "exists != true", timeout: timeoutValue, file: file, line: line) } func waitForValueContains(_ element: XCUIElement, value: String, file: String = #file, line: UInt = #line) { waitFor(element, with: "value CONTAINS '\(value)'", file: file, line: line) } private func waitFor(_ element: XCUIElement, with predicateString: String, description: String? = nil, timeout: TimeInterval = 5.0, file: String, line: UInt) { let predicate = NSPredicate(format: predicateString) let expectation = XCTNSPredicateExpectation(predicate: predicate, object: element) let result = XCTWaiter().wait(for: [expectation], timeout: timeout) if result != .completed { let message = description ?? "Expect predicate \(predicateString) for \(element.description)" self.recordFailure(withDescription: message, inFile: file, atLine: line, expected: false) } } func loadWebPage(_ url: String, waitForLoadToFinish: Bool = true, file: String = #file, line: UInt = #line) { let app = XCUIApplication() UIPasteboard.general.string = url app.textFields["url"].press(forDuration: 2.0) app.sheets.element(boundBy: 0).buttons.element(boundBy: 0).tap() if waitForLoadToFinish { let finishLoadingTimeout: TimeInterval = 30 let progressIndicator = app.progressIndicators.element(boundBy: 0) waitFor(progressIndicator, with: "exists != true", description: "Problem loading \(url)", timeout: finishLoadingTimeout, file: file, line: line) } } func iPad() -> Bool { if UIDevice.current.userInterfaceIdiom == .pad { return true } return false } func waitUntilPageLoad() { let app = XCUIApplication() let progressIndicator = app.progressIndicators.element(boundBy: 0) waitforNoExistence(progressIndicator, timeoutValue: 20.0) } } extension BaseTestCase { func tabTrayButton(forApp app: XCUIApplication) -> XCUIElement { return app.buttons["TopTabsViewController.tabsButton"].exists ? app.buttons["TopTabsViewController.tabsButton"] : app.buttons["TabToolbar.tabsButton"] } } extension XCUIElement { func tap(force: Bool) { // There appears to be a bug with tapping elements sometimes, despite them being on-screen and tappable, due to hittable being false. // See: http://stackoverflow.com/a/33534187/1248491 if isHittable { tap() } else if force { coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap() } } }