Dactyloidae iOS initial commit

This commit is contained in:
wuggy 2026-06-26 21:04:09 -07:00
commit 7154a0497e
2123 changed files with 197052 additions and 0 deletions

View file

@ -0,0 +1,378 @@
/* 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
let defaultTopSite = ["topSiteLabel": "wikipedia", "bookmarkLabel": "Wikipedia"]
let newTopSite = ["url": "www.mozilla.org", "topSiteLabel": "mozilla", "bookmarkLabel": "Internet for people, not profit — Mozilla"]
let allDefaultTopSites = ["facebook", "youtube", "amazon", "wikipedia", "twitter"]
class ActivityStreamTest: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
let TopSiteCellgroup = XCUIApplication().collectionViews.cells["TopSitesCell"]
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
dismissFirstRunUI()
}
override func tearDown() {
super.tearDown()
}
func testDefaultSites() {
// There should be 5 top sites by default
checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 5)
}
func testTopSitesAdd() {
checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 5)
loadWebPage("http://example.com")
if iPad() {
app.buttons["URLBarView.backButton"].tap()
} else {
app.buttons["TabToolbar.backButton"].tap()
}
navigator.goto(URLBarOpen)
checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 6)
}
func testTopSitesRemove() {
loadWebPage("http://example.com")
if iPad() {
app.buttons["URLBarView.backButton"].tap()
} else {
app.buttons["TabToolbar.backButton"].tap()
}
navigator.goto(URLBarOpen)
// A new site has been added to the top sites
checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 6)
TopSiteCellgroup.cells["example"].press(forDuration: 1) //example is the name of the domain. (example.com)
app.tables["Context Menu"].cells["Remove"].tap()
// A top site has been removed
checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 5)
}
func testTopSitesRemoveDefaultTopSite() {
TopSiteCellgroup.cells[defaultTopSite["topSiteLabel"]!].press(forDuration: 1)
// Tap on Remove and check that now there should be only 4 default top sites
selectOptionFromContextMenu(option: "Remove")
checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 4)
}
func testTopSitesRemoveAllDefaultTopSitesAddNewOne() {
// Remove all default Top Sites
for i in allDefaultTopSites {
TopSiteCellgroup.cells[i].press(forDuration: 1)
selectOptionFromContextMenu(option: "Remove")
}
let numberOfTopSites = TopSiteCellgroup.cells.matching(identifier: "TopSite").count
XCTAssertEqual(numberOfTopSites, 0, "All top sites should have been removed")
// Open a new page and wait for the completion
navigator.nowAt(HomePanelsScreen)
navigator.goto(URLBarOpen)
app.textFields["address"].typeText(newTopSite["url"]!)
app.textFields["address"].typeText("\r")
waitUntilPageLoad()
if iPad() {
app.buttons["URLBarView.backButton"].tap()
} else {
app.buttons["TabToolbar.backButton"].tap()
}
waitforExistence(TopSiteCellgroup.cells[newTopSite["topSiteLabel"]!])
checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 1)
}
func testTopSitesShiftAfterRemovingOne() {
// Check top site in first and second cell
let topSiteFirstCell = app.collectionViews.cells.collectionViews.cells.element(boundBy: 0).label
let topSiteSecondCell = app.collectionViews.cells.collectionViews.cells.element(boundBy: 1).label
XCTAssertTrue(topSiteFirstCell == allDefaultTopSites[0])
XCTAssertTrue(topSiteSecondCell == allDefaultTopSites[1])
// Remove it
let topSiteCells = TopSiteCellgroup.cells
topSiteCells[allDefaultTopSites[0]].press(forDuration: 1)
selectOptionFromContextMenu(option: "Remove")
// Check top site in first cell now
let topSiteFirstCellAfter = app.collectionViews.cells.collectionViews.cells.element(boundBy: 0).label
XCTAssertTrue(topSiteFirstCellAfter == allDefaultTopSites[1])
}
func testTopSitesOpenInNewTab() {
loadWebPage("http://example.com")
if iPad() {
app.buttons["URLBarView.backButton"].tap()
} else {
app.buttons["TabToolbar.backButton"].tap()
}
navigator.goto(URLBarOpen)
TopSiteCellgroup.cells["example"].press(forDuration: 1)
app.tables["Context Menu"].cells["Open in New Tab"].tap()
XCTAssert(TopSiteCellgroup.exists)
XCTAssertFalse(app.staticTexts["example"].exists)
//URLBarview goBack button
let goBackButton = app.children(matching: .window).element(boundBy: 0).children(matching: .other).element.children(matching: .other).element.children(matching: .other).element.children(matching: .other).element.children(matching: .other).element(boundBy: 1).children(matching: .other).element.children(matching: .button).element(boundBy: 0)
goBackButton.tap()
if iPad() {
app.buttons["TopTabsViewController.tabsButton"].tap()
} else {
app.buttons["TabToolbar.tabsButton"].tap()
}
app.cells.element(boundBy: 0).tap() //"Example Domain"
XCTAssertFalse(app.tables["Top sites"].exists)
let staticTextsQuery = self.app.staticTexts.matching(identifier: "Example Domain")
if staticTextsQuery.count > 0 {
let firstText = staticTextsQuery.element(boundBy: 0)
XCTAssert(firstText.exists)
}
}
func testTopSitesOpenInNewTabDefaultTopSite() {
// Open one of the sites from Topsites and wait until page is loaded
TopSiteCellgroup.cells[defaultTopSite["topSiteLabel"]!]
.press(forDuration: 1)
selectOptionFromContextMenu(option: "Open in New Tab")
waitUntilPageLoad()
// Check that two tabs are open and one of them is the default top site one
navigator.goto(TabTray)
waitforExistence(app.collectionViews.cells[defaultTopSite["bookmarkLabel"]!])
let numTabsOpen = app.collectionViews.cells.count
XCTAssertEqual(numTabsOpen, 2, "New tab not open")
}
func testTopSitesOpenInNewPrivateTab() {
loadWebPage("http://example.com")
if iPad() {
app.buttons["URLBarView.backButton"].tap()
} else {
app.buttons["TabToolbar.backButton"].tap()
}
navigator.goto(URLBarOpen)
app.collectionViews.cells["TopSitesCell"].cells["example"].press(forDuration: 1)
app.tables["Context Menu"].cells["Open in New Private Tab"].tap()
XCTAssert(TopSiteCellgroup.exists)
XCTAssertFalse(app.staticTexts["example"].exists)
//URLBarview goBack button
let goBackButton = app.children(matching: .window).element(boundBy: 0).children(matching: .other).element.children(matching: .other).element.children(matching: .other).element.children(matching: .other).element.children(matching: .other).element(boundBy: 1).children(matching: .other).element.children(matching: .button).element(boundBy: 0)
goBackButton.tap()
if iPad() {
app.buttons["TopTabsViewController.tabsButton"].tap()
} else {
app.buttons["TabToolbar.tabsButton"].tap()
}
app.buttons["TabTrayController.maskButton"].tap()
app.cells["Example Domain"].tap()
XCTAssertFalse(TopSiteCellgroup.exists)
XCTAssert(app.staticTexts["Example Domain"].exists)
}
func testTopSitesOpenInNewPrivateTabDefaultTopSite() {
// Open one of the sites from Topsites and wait until page is loaded
TopSiteCellgroup.cells[defaultTopSite["topSiteLabel"]!]
.press(forDuration: 1)
selectOptionFromContextMenu(option: "Open in New Private Tab")
// Check that two tabs are open and one of them is the default top site one
navigator.goto(PrivateTabTray)
waitforExistence(app.collectionViews.cells[defaultTopSite["bookmarkLabel"]!])
let numTabsOpen = app.collectionViews.cells.count
XCTAssertEqual(numTabsOpen, 1, "New tab not open")
}
func testTopSitesBookmarkDefaultTopSite() {
// Bookmark a default TopSite
TopSiteCellgroup.cells[defaultTopSite["topSiteLabel"]!]
.press(forDuration: 1)
selectOptionFromContextMenu(option: "Bookmark")
// Check that it appears under Bookmarks menu
navigator.goto(HomePanel_Bookmarks)
XCTAssertTrue(app.tables["Bookmarks List"].staticTexts[defaultTopSite["bookmarkLabel"]!].exists)
// Check that longtapping on the TopSite gives the option to remove it
navigator.goto(HomePanel_TopSites)
TopSiteCellgroup.cells[defaultTopSite["topSiteLabel"]!]
.press(forDuration: 2)
XCTAssertTrue(app.tables["Context Menu"].cells["Remove Bookmark"].exists)
// Unbookmark it
selectOptionFromContextMenu(option: "Remove Bookmark")
navigator.goto(HomePanel_Bookmarks)
XCTAssertFalse(app.tables["Bookmarks List"].staticTexts[defaultTopSite["bookmarkLabel"]!].exists)
}
func testTopSitesBookmarkNewTopSite () {
// Bookmark a new TopSite
navigator.openURL(urlString: newTopSite["url"]!)
waitUntilPageLoad()
if iPad() {
app.buttons["URLBarView.backButton"].tap()
} else {
app.buttons["TabToolbar.backButton"].tap()
}
let topSiteCells = TopSiteCellgroup.cells
waitforExistence(topSiteCells[newTopSite["topSiteLabel"]!])
topSiteCells[newTopSite["topSiteLabel"]!].press(forDuration: 1)
selectOptionFromContextMenu(option: "Bookmark")
// Check that it appears under Bookmarks menu
navigator.nowAt(HomePanelsScreen)
navigator.goto(HomePanel_Bookmarks)
XCTAssertTrue(app.tables["Bookmarks List"].staticTexts[newTopSite["bookmarkLabel"]!].exists)
// Check that longtapping on the TopSite gives the option to remove it
navigator.goto(HomePanel_TopSites)
TopSiteCellgroup.cells[newTopSite["topSiteLabel"]!].press(forDuration: 1)
// Unbookmark it
selectOptionFromContextMenu(option: "Remove Bookmark")
navigator.goto(HomePanel_Bookmarks)
XCTAssertFalse(app.tables["Bookmarks List"].staticTexts[newTopSite["bookmarkLabel"]!].exists)
}
func testTopSitesShareDefaultTopSite () {
TopSiteCellgroup.cells[defaultTopSite["topSiteLabel"]!]
.press(forDuration: 1)
// Tap on Share option and verify that the menu is shown and it is possible to cancel it
selectOptionFromContextMenu(option: "Share")
if !iPad() {
app.buttons["Cancel"].tap()
}
}
func testTopSitesShareNewTopSite () {
navigator.openURL(urlString: newTopSite["url"]!)
waitUntilPageLoad()
navigator.goto(TabTray)
navigator.goto(HomePanelsScreen)
let topSiteCells = TopSiteCellgroup.cells
waitforExistence(topSiteCells[newTopSite["topSiteLabel"]!])
topSiteCells[newTopSite["topSiteLabel"]!].press(forDuration: 1)
// Tap on Share option and verify that the menu is shown and it is possible to cancel it....
selectOptionFromContextMenu(option: "Share")
if !iPad() {
app.buttons["Cancel"].tap()
}
}
private func selectOptionFromContextMenu(option: String) {
XCTAssertTrue(app.tables["Context Menu"].cells[option].exists)
app.tables["Context Menu"].cells[option].tap()
}
private func checkNumberOfExpectedTopSites(numberOfExpectedTopSites: Int) {
waitforExistence(app.cells["TopSitesCell"])
XCTAssertTrue(app.cells["TopSitesCell"].exists)
let numberOfTopSites = TopSiteCellgroup.cells.matching(identifier: "TopSite").count
XCTAssertEqual(numberOfTopSites, UInt(numberOfExpectedTopSites), "The number of Top Sites is not correct")
}
func testOpenTopSitesFromContextMenu () {
// Top Sites is shown by default
waitforExistence(app.cells["TopSitesCell"])
checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 5)
// Go to a website
navigator.openURL(urlString: newTopSite["url"]!)
waitUntilPageLoad()
// Go back to Top Sites from context menu
navigator.browserPerformAction(.openTopSitesOption)
checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 6)
}
func testActivityStreamPages() {
let pagecontrolButton = TopSiteCellgroup.buttons["Next Page"]
XCTAssertFalse(pagecontrolButton.exists, "The Page Control button must not exist. Only 5 elements should be on the page")
navigator.openURL(urlString: "http://example.com")
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: "example.com")
navigator.openURL(urlString: "http://mozilla.org")
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: "mozilla.org")
navigator.openURL(urlString: "http://apple.com")
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: "apple.com")
navigator.openURL(urlString: "http://slack.com")
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: "slack.com")
if iPad() {
// Test timeout on BB when loading these pages
navigator.openURL(urlString: "http://cvs.com")
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: "cvs.com")
navigator.openURL(urlString: "http://linkedin.com")
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: "linkedin.com")
navigator.openURL(urlString: "http://zara.com")
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: "zara.com")
navigator.openURL(urlString: "http://twitter.com")
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: "twitter.com")
navigator.openURL(urlString: "http://instagram.com")
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: "instagram.com")
}
navigator.goto(URLBarOpen)
waitforExistence(pagecontrolButton)
XCTAssert(pagecontrolButton.exists, "The Page Control button must exist")
pagecontrolButton.tap()
pagecontrolButton.tap()
let topSiteCells = TopSiteCellgroup.cells
waitforExistence(topSiteCells["example"])
topSiteCells["example"].press(forDuration: 1)
app.tables["Context Menu"].cells["Remove"].tap()
waitforNoExistence(pagecontrolButton)
XCTAssertFalse(pagecontrolButton.exists, "The Page Control button should disappear after an item is deleted.")
}
func testContextMenuInLandscape() {
XCUIDevice.shared().orientation = .landscapeLeft
navigator.openURL(urlString: "http://example.com")
waitUntilPageLoad()
if app.buttons["URLBarView.backButton"].isEnabled {
app.buttons["URLBarView.backButton"].tap()
} else {
app.textFields["url"].tap()
}
TopSiteCellgroup.cells["example"].press(forDuration: 1)
let contextMenuHeight = app.tables["Context Menu"].frame.size.height
let parentViewHeight = app.otherElements["Action Sheet"].frame.size.height
XCTAssertLessThanOrEqual(contextMenuHeight, parentViewHeight)
// Go back to portrait mode
XCUIDevice.shared().orientation = .portrait
}
}

View file

@ -0,0 +1,347 @@
/* 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
extension String {
subscript (i: Int) -> Character {
return self[self.characters.index(self.startIndex, offsetBy: i)]
}
subscript (i: Int) -> String {
return String(self[i] as Character)
}
subscript (r: Range<Int>) -> String {
let start = characters.index(startIndex, offsetBy: r.lowerBound)
let end = self.index(start, offsetBy: r.upperBound - r.lowerBound)
return self[Range(start ..< end)]
}
}
class AuthenticationTest: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
continueAfterFailure = false
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
closeAuthenticationManager()
super.tearDown()
}
fileprivate func typePasscode(_ passCode: String) {
app.keys[passCode[0]].tap()
app.keys[passCode[1]].tap()
app.keys[passCode[2]].tap()
app.keys[passCode[3]].tap()
app.keys[passCode[4]].tap()
app.keys[passCode[5]].tap()
}
fileprivate func closeAuthenticationManager() {
navigator.goto(BrowserTab)
}
fileprivate func disablePasscode(_ passCode: String) {
navigator.goto(PasscodeSettings)
app.tables["AuthenticationManager.settingsTableView"].staticTexts["Turn Passcode Off"].tap()
waitforExistence(app.staticTexts["Enter passcode"])
typePasscode(passCode)
waitforExistence(app.tables["AuthenticationManager.settingsTableView"].staticTexts["Turn Passcode On"])
}
fileprivate func enablePasscode(_ passCode: String, interval: String = "Immediately") {
let authenticationmanagerSettingstableviewTable = app.tables["AuthenticationManager.settingsTableView"]
navigator.goto(PasscodeSettings)
app.tables["AuthenticationManager.settingsTableView"].staticTexts["Turn Passcode On"].tap()
waitforExistence(app.staticTexts["Enter a passcode"])
typePasscode(passCode)
waitforExistence(app.staticTexts["Re-enter passcode"])
typePasscode(passCode)
waitforExistence(app.tables["AuthenticationManager.settingsTableView"].staticTexts["Turn Passcode Off"])
navigator.goto(PasscodeIntervalSettings)
typePasscode(passCode)
app.staticTexts[interval].tap()
navigator.goto(PasscodeSettings)
waitforExistence(authenticationmanagerSettingstableviewTable.staticTexts[interval])
}
// Sets the passcode and interval (set to immediately)
func testTurnOnOff() {
enablePasscode("133777")
XCTAssertTrue(app.staticTexts["Immediately"].exists)
disablePasscode("133777")
}
func testChangePassCode() {
enablePasscode("133777")
app.staticTexts["Change Passcode"].tap()
waitforExistence(app.staticTexts["Enter passcode"])
typePasscode("133777")
waitforExistence(app.staticTexts["Enter a new passcode"])
typePasscode("233777")
waitforExistence(app.staticTexts["Re-enter passcode"])
typePasscode("233777")
waitforExistence(app.tables["AuthenticationManager.settingsTableView"].staticTexts["Turn Passcode Off"])
disablePasscode("233777")
}
func testPromptPassCodeUponReentry() {
enablePasscode("133777")
navigator.goto(LoginsSettings)
waitforExistence(app.navigationBars["Enter Passcode"])
typePasscode("133777")
waitforExistence(app.tables["Login List"])
//send app to background, and re-enter
XCUIDevice.shared().press(.home)
app.activate()
let contentView = app.navigationBars["Client.FxAContentView"]
if contentView.exists {
app.navigationBars["Client.FxAContentView"].buttons["Settings"].tap()
}
navigator.nowAt("SettingsScreen")
navigator.goto(LoginsSettings)
waitforExistence(app.navigationBars["Enter Passcode"])
}
func testPromptPassCodeUponReentryWithDelay() {
enablePasscode("133777", interval: "After 5 minutes")
navigator.goto(LoginsSettings)
waitforExistence(app.navigationBars["Enter Passcode"])
typePasscode("133777")
waitforExistence(app.tables["Login List"])
//send app to background, and re-enter
XCUIDevice.shared().press(.home)
app.activate()
let contentView = app.navigationBars["Client.FxAContentView"]
if contentView.exists {
app.navigationBars["Client.FxAContentView"].buttons["Settings"].tap()
}
navigator.nowAt("SettingsScreen")
navigator.goto(LoginsSettings)
waitforExistence(app.tables["Login List"])
}
func testChangePasscodeShowsErrorStates() {
enablePasscode("133777")
app.staticTexts["Change Passcode"].tap()
waitforExistence(app.staticTexts["Enter passcode"])
typePasscode("233777")
waitforExistence(app.staticTexts["Incorrect passcode. Try again (Attempts remaining: 2)."])
typePasscode("333777")
waitforExistence(app.staticTexts["Incorrect passcode. Try again (Attempts remaining: 1)."])
typePasscode("133777")
waitforExistence(app.staticTexts["Enter a new passcode"])
// Enter same passcode as new one
typePasscode("133777")
waitforExistence(app.staticTexts["New passcode must be different than existing code."])
// Enter mismatched passcode
typePasscode("233777")
waitforExistence(app.staticTexts["Re-enter passcode"])
typePasscode("333777")
waitforExistence(app.staticTexts["Passcodes didnt match. Try again."])
// Put proper password
XCTAssertTrue(app.staticTexts["Enter a new passcode"].exists)
typePasscode("233777")
waitforExistence(app.staticTexts["Re-enter passcode"])
typePasscode("233777")
waitforExistence(app.tables["AuthenticationManager.settingsTableView"].staticTexts["Turn Passcode Off"])
disablePasscode("233777")
}
func testChangeRequirePasscodeInterval() {
enablePasscode("133777")
let authenticationmanagerSettingstableviewTable = app.tables["AuthenticationManager.settingsTableView"]
navigator.goto(PasscodeIntervalSettings)
waitforExistence(app.navigationBars["Enter Passcode"])
typePasscode("133777")
waitforExistence(app.staticTexts["Immediately"])
XCTAssertTrue(app.staticTexts["After 1 minute"].exists)
XCTAssertTrue(app.staticTexts["After 5 minutes"].exists)
XCTAssertTrue(app.staticTexts["After 10 minutes"].exists)
XCTAssertTrue(app.staticTexts["After 15 minutes"].exists)
XCTAssertTrue(app.staticTexts["After 1 hour"].exists)
app.staticTexts["After 15 minutes"].tap()
navigator.goto(PasscodeSettings)
waitforExistence(authenticationmanagerSettingstableviewTable.staticTexts["After 15 minutes"])
// Since we set to 15 min, it shouldn't ask for password again, but it skips verification
// only when timing isn't changed. (could be due to timer reset?)
// For clarification, raised Bug 1325439
navigator.goto(PasscodeIntervalSettings)
waitforExistence(app.navigationBars["Enter Passcode"])
typePasscode("133777")
navigator.goto(PasscodeSettings)
waitforExistence(authenticationmanagerSettingstableviewTable.staticTexts["After 15 minutes"])
disablePasscode("133777")
}
func testEnteringLoginsUsingPasscode() {
enablePasscode("133777")
// Enter login
navigator.goto(LoginsSettings)
waitforExistence(app.navigationBars["Enter Passcode"])
typePasscode("133777")
waitforExistence(app.tables["Login List"])
navigator.goto(SettingsScreen)
// Trying again should display passcode screen since we've set the interval to be immediately.
navigator.goto(LoginsSettings)
waitforExistence(app.navigationBars["Enter Passcode"])
typePasscode("133777")
waitforExistence(app.tables["Login List"])
disablePasscode("133777")
}
func testEnteringLoginsUsingPasscodeWithFiveMinutesInterval() {
enablePasscode("133777", interval: "After 5 minutes")
// now we've changed the timeout, we should prompt next time for passcode.
navigator.goto(LoginsSettings)
waitforExistence(app.navigationBars["Enter Passcode"])
typePasscode("133777")
waitforExistence(app.tables["Login List"])
// Trying again should not display the passcode screen since the interval is 5 minutes
navigator.goto(SettingsScreen)
navigator.goto(LoginsSettings)
waitforExistence(app.tables["Login List"])
navigator.goto(PasscodeIntervalSettings)
waitforExistence(app.staticTexts["After 5 minutes"])
disablePasscode("133777")
}
func testEnteringLoginsWithNoPasscode() {
// it is disabled
navigator.goto(PasscodeSettings)
waitforExistence(app.tables["AuthenticationManager.settingsTableView"].staticTexts["Turn Passcode On"])
navigator.goto(LoginsSettings)
waitforExistence(app.tables["Login List"])
}
func testWrongPasscodeDisplaysAttemptsAndMaxError() {
enablePasscode("133777")
navigator.goto(PasscodeIntervalSettings)
waitforExistence(app.navigationBars["Enter Passcode"])
typePasscode("133777")
waitforExistence(app.staticTexts["After 5 minutes"])
app.staticTexts["After 5 minutes"].tap()
navigator.goto(PasscodeSettings)
waitforExistence(app.tables["AuthenticationManager.settingsTableView"].staticTexts["After 5 minutes"])
// Enter wrong passcode
navigator.goto(LoginsSettings)
waitforExistence(app.navigationBars["Enter Passcode"])
typePasscode("233777")
waitforExistence(app.staticTexts["Incorrect passcode. Try again (Attempts remaining: 2)."])
typePasscode("333777")
waitforExistence(app.staticTexts["Incorrect passcode. Try again (Attempts remaining: 1)."])
typePasscode("333777")
waitforExistence(app.staticTexts["Maximum attempts reached. Please try again later."])
}
func testWrongPasscodeAttemptsPersistAcrossEntryAndConfirmation() {
enablePasscode("133777")
// Enter wrong passcode on Logins
navigator.goto(LoginsSettings)
waitforExistence(app.navigationBars["Enter Passcode"])
typePasscode("233777")
waitforExistence(app.staticTexts["Incorrect passcode. Try again (Attempts remaining: 2)."])
// Go back to Passcode, and enter a wrong passcode, notice the error count
navigator.goto(PasscodeSettings)
app.staticTexts["Change Passcode"].tap()
waitforExistence(app.staticTexts["Enter passcode"])
typePasscode("233777")
waitforExistence(app.staticTexts["Incorrect passcode. Try again (Attempts remaining: 1)."])
app.buttons["Cancel"].tap()
disablePasscode("133777")
}
func testChangedPasswordMustBeNew() {
enablePasscode("133777")
app.staticTexts["Change Passcode"].tap()
waitforExistence(app.staticTexts["Enter passcode"])
typePasscode("133777")
waitforExistence(app.staticTexts["Enter a new passcode"])
typePasscode("133777")
waitforExistence(app.staticTexts["New passcode must be different than existing code."])
app.navigationBars["Change Passcode"].buttons["Cancel"].tap()
disablePasscode("133777")
}
func testPasscodesMustMatchWhenCreating() {
navigator.goto(PasscodeSettings)
app.tables["AuthenticationManager.settingsTableView"].staticTexts["Turn Passcode On"].tap()
waitforExistence(app.staticTexts["Enter a passcode"])
typePasscode("133777")
waitforExistence(app.staticTexts["Re-enter passcode"])
typePasscode("233777")
waitforExistence(app.staticTexts["Passcodes didnt match. Try again."])
waitforExistence(app.staticTexts["Enter a passcode"])
app.buttons["Cancel"].tap()
}
func testPasscodeMustBeCorrectWhenRemoving() {
enablePasscode("133777")
XCTAssertTrue(app.staticTexts["Immediately"].exists)
app.tables["AuthenticationManager.settingsTableView"].staticTexts["Turn Passcode Off"].tap()
waitforExistence(app.staticTexts["Enter passcode"])
typePasscode("233777")
waitforExistence(app.staticTexts["Incorrect passcode. Try again (Attempts remaining: 2)."])
typePasscode("133777")
waitforExistence(app.tables["AuthenticationManager.settingsTableView"].staticTexts["Turn Passcode On"])
}
func testChangingIntervalResetsValidationTimer() {
enablePasscode("133777")
// Enter login, since the default is 'set immediately,' it will ask for passcode
navigator.goto(LoginsSettings)
waitforExistence(app.navigationBars["Enter Passcode"])
typePasscode("133777")
waitforExistence(app.tables["Login List"])
navigator.goto(PasscodeIntervalSettings)
waitforExistence(app.navigationBars["Enter Passcode"])
typePasscode("133777")
waitforExistence(app.staticTexts["Immediately"])
app.staticTexts["After 15 minutes"].tap()
navigator.goto(PasscodeSettings)
waitforExistence(app.tables["AuthenticationManager.settingsTableView"].staticTexts["After 15 minutes"])
// Enter login, since the interval is reset, it will ask for password again
navigator.goto(LoginsSettings)
waitforExistence(app.navigationBars["Enter Passcode"])
disablePasscode("133777")
}
}

View file

@ -0,0 +1,112 @@
/* 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()
}
}
}

View file

@ -0,0 +1,112 @@
/* 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
let url_1 = "www.google.com"
let url_2 = ["url": "www.mozilla.org", "bookmarkLabel": "Internet for people, not profit — Mozilla"]
class BookmarkingTests: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
super.tearDown()
}
private func bookmark() {
navigator.goto(PageOptionsMenu)
waitforExistence(app.tables.cells["Bookmark This Page"])
app.tables.cells["Bookmark This Page"].tap()
navigator.nowAt(BrowserTab)
}
private func unbookmark() {
navigator.goto(PageOptionsMenu)
waitforExistence(app.tables.cells["Remove Bookmark"])
app.cells["Remove Bookmark"].tap()
navigator.nowAt(BrowserTab)
}
private func checkBookmarked() {
navigator.goto(PageOptionsMenu)
waitforExistence(app.tables.cells["Remove Bookmark"])
if iPad() {
app.otherElements["PopoverDismissRegion"].tap()
navigator.nowAt(BrowserTab)
} else {
navigator.goto(BrowserTab)
}
}
private func checkUnbookmarked() {
navigator.goto(PageOptionsMenu)
waitforExistence(app.tables.cells["Bookmark This Page"])
if iPad() {
app.otherElements["PopoverDismissRegion"].tap()
navigator.nowAt(BrowserTab)
} else {
navigator.goto(BrowserTab)
}
}
func testBookmarkingUI() {
// Go to a webpage, and add to bookmarks, check it's added
navigator.createNewTab()
loadWebPage(url_1)
navigator.nowAt(BrowserTab)
bookmark()
checkBookmarked()
// Load a different page on a new tab, check it's not bookmarked
navigator.createNewTab()
loadWebPage(url_2["url"]!)
navigator.nowAt(BrowserTab)
checkUnbookmarked()
// Go back, check it's still bookmarked, check it's on bookmarks home panel
navigator.goto(TabTray)
app.collectionViews.cells["Google"].tap()
navigator.nowAt(BrowserTab)
checkBookmarked()
// Open it, then unbookmark it, and check it's no longer on bookmarks home panel
unbookmark()
checkUnbookmarked()
}
private func checkEmptyBookmarkList() {
let list = app.tables["Bookmarks List"].cells.count
XCTAssertEqual(list, 0, "There should not be any entry in the bookmarks list")
}
private func checkItemInBookmarkList() {
let list = app.tables["Bookmarks List"].cells.count
XCTAssertEqual(list, 1, "There should be an entry in the bookmarks list")
XCTAssertTrue(app.tables["Bookmarks List"].staticTexts[url_2["bookmarkLabel"]!].exists)
}
func testAccessBookmarksFromContextMenu() {
//First time there is not any bookmark
navigator.browserPerformAction(.openBookMarksOption)
checkEmptyBookmarkList()
navigator.nowAt(BrowserTab)
//Add a bookmark
navigator.createNewTab()
loadWebPage(url_2["url"]!)
navigator.nowAt(BrowserTab)
bookmark()
//There should be a bookmark
navigator.browserPerformAction(.openBookMarksOption)
checkItemInBookmarkList()
}
}

View file

@ -0,0 +1,68 @@
/* 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 ClipBoardTests: BaseTestCase {
let url = "www.example.com"
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
navigator = nil
app = nil
super.tearDown()
}
//Check for test url in the browser
func checkUrl() {
let urlTextField = app.textFields["url"]
waitForValueContains(urlTextField, value: "www.example")
}
//Copy url from the browser
func copyUrl() {
navigator.goto(URLBarOpen)
app.textFields["address"].press(forDuration: 3)
waitforExistence(app.menuItems["Select All"])
app.menuItems["Select All"].tap()
waitforExistence(app.menuItems["Copy"])
app.menuItems["Copy"].tap()
app.typeText("\r")
navigator.nowAt(BrowserTab)
}
//Check copied url is same as in browser
func checkCopiedUrl() {
if let myString = UIPasteboard.general.string {
var value = app.textFields["url"].value as! String
if value.hasPrefix("http") == false {
value = "http://\(value)"
}
XCTAssertNotNil(myString)
XCTAssertEqual(myString, value, "Url matches with the UIPasteboard")
}
}
// This test is disabled in release, but can still run on master
func testClipboard() {
navigator.openURL(urlString: url)
waitUntilPageLoad()
checkUrl()
copyUrl()
checkCopiedUrl()
navigator.createNewTab()
navigator.goto(URLBarOpen)
app.textFields["address"].press(forDuration: 3)
app.menuItems["Paste"].tap()
waitForValueContains(app.textFields["address"], value: "www.example.com")
}
}

View file

@ -0,0 +1,48 @@
/* 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 CopiedLinksTests: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
navigator = nil
app = nil
super.tearDown()
}
// This test is enable Offer to open copied links, when opening firefox
func testCopiedLinks() {
navigator.goto(SettingsScreen)
//Check Offer to open copied links, when opening firefox is off
let value = app.tables.cells.switches["Offer to Open Copied Links, When Opening Firefox"].value
XCTAssertEqual(value as? String, "0")
//Switch on, Offer to open copied links, when opening firefox
app.tables.cells.switches["Offer to Open Copied Links, When Opening Firefox"].tap()
//Check Offer to open copied links, when opening firefox is on
let value2 = app.tables.cells.switches["Offer to Open Copied Links, When Opening Firefox"].value
XCTAssertEqual(value2 as? String, "1")
app.navigationBars["Settings"]/*@START_MENU_TOKEN@*/.buttons["Done"]/*[[".buttons[\"Done\"]",".buttons[\"AppSettingsTableViewController.navigationItem.leftBarButtonItem\"]"],[[[-1,1],[-1,0]]],[1]]@END_MENU_TOKEN@*/.tap()
app/*@START_MENU_TOKEN@*/.buttons["TabToolbar.menuButton"]/*[[".buttons[\"Menu\"]",".buttons[\"TabToolbar.menuButton\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.tap()
let settingsmenuitemCell = app.tables.cells["Settings"]
settingsmenuitemCell.tap()
//Check Offer to open copied links, when opening firefox is on
let value3 = app.tables.cells.switches["Offer to Open Copied Links, When Opening Firefox"].value
XCTAssertEqual(value3 as? String, "1")
}
}

View file

@ -0,0 +1,174 @@
/* 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
let website = ["url": "www.mozilla.org", "value": "www.mozilla.org", "subDomain": "https://www.mozilla.org/en-US/firefox/products"]
class DomainAutocompleteTest: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
super.tearDown()
}
func testAutocomplete() {
navigator.openURL(urlString: website["url"]!)
// Basic autocompletion cases
navigator.goto(URLBarOpen)
app.textFields["address"].typeText("w")
waitForValueContains(app.textFields["address"], value: website["value"]!)
let value = app.textFields["address"].value
XCTAssertEqual(value as? String, website["value"]!, "Wrong autocompletion")
// Enter the complete website and check that there is not more text added, just what user typed
app.buttons["Clear text"].tap()
app.textFields["address"].typeText(website["value"]!)
waitForValueContains(app.textFields["address"], value: website["value"]!)
let value2 = app.textFields["address"].value
XCTAssertEqual(value2 as? String, website["value"]!, "Wrong autocompletion")
}
// Test that deleting characters works correctly with autocomplete
func testAutocompleteDeletingChars() {
navigator.openURL(urlString: website["url"]!)
navigator.goto(URLBarOpen)
app.textFields["address"].typeText("www.moz")
// First delete the autocompleted part
app.textFields["address"].typeText("\u{0008}")
// Then remove an extra char and check that the autocompletion stops working
app.textFields["address"].typeText("\u{0008}")
waitForValueContains(app.textFields["address"], value: "mo")
// Then write another letter and the autocompletion works again
app.textFields["address"].typeText("z")
waitForValueContains(app.textFields["address"], value: "moz")
let value = app.textFields["address"].value
XCTAssertEqual(value as? String, website["value"]!, "Wrong autocompletion")
}
// Delete the entire string and verify that the home panels are shown again.
func testDeleteEntireString() {
navigator.openURL(urlString: website["url"]!)
navigator.goto(URLBarOpen)
app.textFields["address"].typeText("www.moz")
waitforExistence(app.buttons["Clear text"])
app.buttons["Clear text"].tap()
// Check that the address field is empty and that the home panels are shown
let value = app.textFields["address"].value
XCTAssertEqual(value as? String, "", "The url has not been removed correctly")
waitforExistence(app.buttons["HomePanels.TopSites"])
XCTAssertFalse(app.buttons["HomePanels.TopSites"].isEnabled)
XCTAssertTrue(app.buttons["HomePanels.Bookmarks"].isEnabled)
}
// Ensure that the scheme is included in the autocompletion.
func testEnsureSchemeIncludedAutocompletion() {
navigator.openURL(urlString: website["url"]!)
waitUntilPageLoad()
navigator.goto(URLBarOpen)
app.textFields["address"].typeText("https")
waitForValueContains(app.textFields["address"], value: "mozilla")
let value = app.textFields["address"].value
XCTAssertEqual(value as? String, "https://www.mozilla.org", "Wrong autocompletion")
}
// Non-matches.
func testNoMatches() {
navigator.openURL(urlString: website["url"]!)
navigator.openURL(urlString: website["subDomain"]!)
navigator.goto(URLBarOpen)
app.textFields["address"].typeText("baz")
let value = app.textFields["address"].value
// Check there is not more text added, just what user typed
XCTAssertEqual(value as? String, "baz", "Wrong autocompletion")
// Ensure we don't match against TLDs.
app.buttons["Clear text"].tap()
app.textFields["address"].typeText("org")
let value2 = app.textFields["address"].value
// Check there is not more text added, just what user typed
XCTAssertEqual(value2 as? String, "org", "Wrong autocompletion")
// Ensure we don't match other characters ie: ., :, /
app.buttons["Clear text"].tap()
app.textFields["address"].typeText(".")
let value3 = app.textFields["address"].value
XCTAssertEqual(value3 as? String, ".", "Wrong autocompletion")
app.buttons["Clear text"].tap()
app.textFields["address"].typeText(":")
let value4 = app.textFields["address"].value
XCTAssertEqual(value4 as? String, ":", "Wrong autocompletion")
app.buttons["Clear text"].tap()
app.textFields["address"].typeText("/")
let value5 = app.textFields["address"].value
XCTAssertEqual(value5 as? String, "/", "Wrong autocompletion")
// Ensure we don't match strings that don't start a word.
app.buttons["Clear text"].tap()
app.textFields["address"].typeText("ozilla")
let value6 = app.textFields["address"].value
XCTAssertEqual(value6 as? String, "ozilla", "Wrong autocompletion")
// Ensure we don't match words outside of the domain
app.buttons["Clear text"].tap()
app.textFields["address"].typeText("products")
let value7 = app.textFields["address"].value
XCTAssertEqual(value7 as? String, "products", "Wrong autocompletion")
}
// Test default domains.
func testDefaultDomains() {
navigator.goto(URLBarOpen)
app.textFields["address"].typeText("a")
waitForValueContains(app.textFields["address"], value: ".com")
let value = app.textFields["address"].value
XCTAssertEqual(value as? String, "amazon.com", "Wrong autocompletion")
app.buttons["Clear text"].tap()
app.textFields["address"].typeText("an")
waitForValueContains(app.textFields["address"], value: ".com")
let value2 = app.textFields["address"].value
XCTAssertEqual(value2 as? String, "answers.com", "Wrong autocompletion")
app.buttons["Clear text"].tap()
app.textFields["address"].typeText("anc")
waitForValueContains(app.textFields["address"], value: ".com")
let value3 = app.textFields["address"].value
XCTAssertEqual(value3 as? String, "ancestry.com", "Wrong autocompletion")
}
// Test mixed case autocompletion.
func testMixedCaseAutocompletion() {
navigator.openURL(urlString: website1["url"]!)
navigator.goto(URLBarOpen)
app.textFields["address"].typeText("MoZ")
waitForValueContains(app.textFields["address"], value: ".org")
let value = app.textFields["address"].value
XCTAssertEqual(value as? String, "MoZilla.org", "Wrong autocompletion")
// Test that leading spaces still show suggestions.
app.buttons["Clear text"].tap()
app.textFields["address"].typeText(" moz")
waitForValueContains(app.textFields["address"], value: ".org")
let value2 = app.textFields["address"].value
XCTAssertEqual(value2 as? String, " mozilla.org", "Wrong autocompletion")
// Test that trailing spaces do *not* show suggestions.
app.buttons["Clear text"].tap()
app.textFields["address"].typeText(" moz ")
waitForValueContains(app.textFields["address"], value: "moz")
let value3 = app.textFields["address"].value
// No autocompletion, just what user typed
XCTAssertEqual(value3 as? String, " moz ", "Wrong autocompletion")
}
}

View file

@ -0,0 +1,123 @@
/* 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 FindInPageTests: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
super.tearDown()
}
private func openFindInPageFromMenu() {
navigator.goto(FindInPage)
waitforExistence(app.buttons["Next in-page result"])
waitforExistence(app.buttons["Previous in-page result"])
XCTAssertTrue(app.textFields[""].exists)
}
func testFindFromMenu() {
openFindInPageFromMenu()
// Enter some text to start finding
app.textFields[""].typeText("Book")
// Once there are matches, test previous/next buttons
waitforExistence(app.staticTexts["1/6"])
XCTAssertTrue(app.staticTexts["1/6"].exists)
let nextInPageResultButton = app.buttons["Next in-page result"]
nextInPageResultButton.tap()
waitforExistence(app.staticTexts["2/6"])
XCTAssertTrue(app.staticTexts["2/6"].exists)
nextInPageResultButton.tap()
waitforExistence(app.staticTexts["3/6"])
XCTAssertTrue(app.staticTexts["3/6"].exists)
let previousInPageResultButton = app.buttons["Previous in-page result"]
previousInPageResultButton.tap()
waitforExistence(app.staticTexts["2/6"])
XCTAssertTrue(app.staticTexts["2/6"].exists)
previousInPageResultButton.tap()
waitforExistence(app.staticTexts["1/6"])
XCTAssertTrue(app.staticTexts["1/6"].exists)
// Tapping on close dismisses the search bar
//app.buttons["Done"].tap()
navigator.goto(BrowserTab)
waitforNoExistence(app.textFields["Book"])
}
func testQueryWithNoMatches() {
openFindInPageFromMenu()
// Try to find text which does not match and check that there are not results
app.textFields["FindInPage.searchField"].typeText("foo")
waitforExistence(app.staticTexts["0/0"])
XCTAssertTrue(app.staticTexts["0/0"].exists, "There should not be any matches")
}
func testBarDissapearsWhenReloading() {
openFindInPageFromMenu()
// Before reloading, it is necessary to hide the keyboard
app.textFields["url"].tap()
app.textFields["address"].typeText("\n")
// Once the page is reloaded the search bar should not appear
waitforNoExistence(app.textFields[""])
XCTAssertFalse(app.textFields[""].exists)
}
func testBarDissapearsWhenOpeningTabsTray() {
openFindInPageFromMenu()
// Dismiss keyboard
app.otherElements["contentView"].tap()
navigator.nowAt(BrowserTab)
// Going to tab tray and back to the website hides the search field.
navigator.goto(TabTray)
waitforExistence(app.collectionViews.cells["The Book of Mozilla"])
app.collectionViews.cells["The Book of Mozilla"].tap()
XCTAssertFalse(app.textFields[""].exists)
XCTAssertFalse(app.buttons["Next in-page result"].exists)
XCTAssertFalse(app.buttons["Previous in-page result"].exists)
}
func testFindFromSelection() {
navigator.goto(BrowserTab)
let textToFind = "from"
// Long press on the word to be found
waitUntilPageLoad()
waitforExistence(app.webViews.staticTexts[textToFind])
let stringToFind = app.webViews.staticTexts.matching(identifier: textToFind)
let firstStringToFind = stringToFind.element(boundBy: 0)
firstStringToFind.press(forDuration: 3)
// Find in page is correctly launched, bar with text pre-filled and
// the buttons to find next and previous
waitforExistence(app.menuItems["Find in Page"])
app.menuItems["Find in Page"].tap()
waitforExistence(app.textFields[textToFind])
XCTAssertTrue(app.textFields[textToFind].exists, "The bar does not appear with the text selected to be found")
XCTAssertTrue(app.buttons["Previous in-page result"].exists, "Find previus button exists")
XCTAssertTrue(app.buttons["Next in-page result"].exists, "Find next button exists")
}
}

View file

@ -0,0 +1,476 @@
/* 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 Foundation
import XCTest
let FirstRun = "OptionalFirstRun"
let TabTray = "TabTray"
let PrivateTabTray = "PrivateTabTray"
let URLBarOpen = "URLBarOpen"
let PrivateURLBarOpen = "PrivateURLBarOpen"
let BrowserTab = "BrowserTab"
let PrivateBrowserTab = "PrivateBrowserTab"
let BrowserTabMenu = "BrowserTabMenu"
let PageOptionsMenu = "PageOptionsMenu"
let FindInPage = "FindInPage"
let SettingsScreen = "SettingsScreen"
let HomePageSettings = "HomePageSettings"
let PasscodeSettings = "PasscodeSettings"
let PasscodeIntervalSettings = "PasscodeIntervalSettings"
let SearchSettings = "SearchSettings"
let NewTabSettings = "NewTabSettings"
let ClearPrivateDataSettings = "ClearPrivateDataSettings"
let LoginsSettings = "LoginsSettings"
let OpenWithSettings = "OpenWithSettings"
let ShowTourInSettings = "ShowTourInSettings"
let Intro_FxASignin = "Intro_FxASignin"
let allSettingsScreens = [
SettingsScreen,
HomePageSettings,
PasscodeSettings,
SearchSettings,
NewTabSettings,
ClearPrivateDataSettings,
LoginsSettings,
OpenWithSettings
]
let Intro_Welcome = "Intro.Welcome"
let Intro_Search = "Intro.Search"
let Intro_Private = "Intro.Private"
let Intro_Mail = "Intro.Mail"
let Intro_Sync = "Intro.Sync"
let allIntroPages = [
Intro_Welcome,
Intro_Search,
Intro_Private,
Intro_Mail,
Intro_Sync
]
let HomePanelsScreen = "HomePanels"
let PrivateHomePanelsScreen = "PrivateHomePanels"
let HomePanel_TopSites = "HomePanel.TopSites.0"
let HomePanel_Bookmarks = "HomePanel.Bookmarks.1"
let HomePanel_History = "HomePanel.History.2"
let HomePanel_ReadingList = "HomePanel.ReadingList.3"
let P_HomePanel_TopSites = "P_HomePanel.TopSites.0"
let P_HomePanel_Bookmarks = "P_HomePanel.Bookmarks.1"
let P_HomePanel_History = "P_HomePanel.History.2"
let P_HomePanel_ReadingList = "P_HomePanel.ReadingList.3"
let allHomePanels = [
HomePanel_Bookmarks,
HomePanel_TopSites,
HomePanel_History,
HomePanel_ReadingList
]
let allPrivateHomePanels = [
P_HomePanel_Bookmarks,
P_HomePanel_TopSites,
P_HomePanel_History,
P_HomePanel_ReadingList
]
let ContextMenu_ReloadButton = "ContextMenu_ReloadButton"
func createScreenGraph(_ app: XCUIApplication, url: String = "https://www.mozilla.org/en-US/book/") -> ScreenGraph {
let map = ScreenGraph()
let startBrowsingButton = app.buttons["IntroViewController.startBrowsingButton"]
let introScrollView = app.scrollViews["IntroViewController.scrollView"]
map.createScene(FirstRun) { scene in
// We don't yet have conditional edges, so we declare an edge from this node
// to BrowserTab, and then just make it work.
if introScrollView.exists {
scene.gesture(to: BrowserTab) {
// go find the startBrowsing button on the second page of the intro.
introScrollView.swipeLeft()
startBrowsingButton.tap()
}
scene.noop(to: allIntroPages[0])
} else {
scene.noop(to: HomePanelsScreen)
}
}
// Add the intro screens.
var i = 0
let introLast = allIntroPages.count - 1
let introPager = app.scrollViews["IntroViewController.scrollView"]
for intro in allIntroPages {
let prev = i == 0 ? nil : allIntroPages[i - 1]
let next = i == introLast ? nil : allIntroPages[i + 1]
map.createScene(intro) { scene in
if let prev = prev {
scene.swipeRight(introPager, to: prev)
}
if let next = next {
scene.swipeLeft(introPager, to: next)
}
if i > 0 {
scene.tap(startBrowsingButton, to: BrowserTab)
}
}
i += 1
}
map.createScene(URLBarOpen) { scene in
// This is used for opening BrowserTab with default mozilla URL
// For custom URL, should use Navigator.openNewURL or Navigator.openURL.
scene.typeText(url + "\r", into: app.textFields["address"], to: BrowserTab)
scene.tap( app.textFields["url"], to: HomePanelsScreen)
/*
scene.backAction = {
app.buttons["goBack"].tap()
}
*/
}
map.createScene(PrivateURLBarOpen) { scene in
// This is used for opening BrowserTab with default mozilla URL
// For custom URL, should use Navigator.openNewURL or Navigator.openURL.
scene.typeText(url + "\r", into: app.textFields["address"], to:PrivateBrowserTab)
scene.tap( app.textFields["address"], to: PrivateHomePanelsScreen)
}
let noopAction = {}
map.createScene(HomePanelsScreen) { scene in
scene.tap(app.buttons["HomePanels.TopSites"], to: HomePanel_TopSites)
scene.tap(app.buttons["HomePanels.Bookmarks"], to: HomePanel_Bookmarks)
scene.tap(app.buttons["HomePanels.History"], to: HomePanel_History)
scene.tap(app.buttons["HomePanels.ReadingList"], to: HomePanel_ReadingList)
scene.tap(app.textFields["url"], to: URLBarOpen)
scene.tap(app.buttons["TabToolbar.menuButton"], to: BrowserTabMenu)
if map.isiPad() {
scene.tap(app.buttons["TopTabsViewController.tabsButton"], to: TabTray)
} else {
scene.gesture(to: TabTray) {
if (app.buttons["TabToolbar.tabsButton"].exists) {
app.buttons["TabToolbar.tabsButton"].tap()
} else {
app.buttons["URLBarView.tabsButton"].tap()
}
}
}
}
map.createScene(PrivateHomePanelsScreen) { scene in
scene.tap(app.buttons["HomePanels.TopSites"], to: P_HomePanel_TopSites)
scene.tap(app.buttons["HomePanels.Bookmarks"], to: P_HomePanel_Bookmarks)
scene.tap(app.buttons["HomePanels.History"], to: P_HomePanel_History)
scene.tap(app.buttons["HomePanels.ReadingList"], to: P_HomePanel_ReadingList)
scene.tap(app.textFields["url"], to: PrivateURLBarOpen)
scene.tap(app.buttons["TabToolbar.menuButton"], to: BrowserTabMenu)
if map.isiPad() {
scene.tap(app.buttons["TopTabsViewController.tabsButton"], to: PrivateTabTray)
} else {
scene.gesture(to: PrivateTabTray) {
if (app.buttons["TabToolbar.tabsButton"].exists) {
app.buttons["TabToolbar.tabsButton"].tap()
} else {
app.buttons["URLBarView.tabsButton"].tap()
}
}
}
}
allHomePanels.forEach { name in
// Tab panel means that all the home panels are available all the time, so we can
// fake this out by a noop back to the HomePanelsScreen which can get to every other panel.
map.createScene(name) { scene in
scene.backAction = noopAction
}
}
allPrivateHomePanels.forEach { name in
// Tab panel means that all the home panels are available all the time, so we can
// fake this out by a noop back to the HomePanelsScreen which can get to every other panel.
map.createScene(name) { scene in
scene.backAction = noopAction
}
}
let closeMenuAction = {
app.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.25)).tap()
}
let navigationControllerBackAction = {
app.navigationBars.element(boundBy: 0).buttons.element(boundBy: 0).tap()
}
let cancelBackAction = {
if map.isiPad() {
// There is not Cancel option in iPad this way it is closed
app/*@START_MENU_TOKEN@*/.otherElements["PopoverDismissRegion"]/*[[".otherElements[\"dismiss popup\"]",".otherElements[\"PopoverDismissRegion\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.tap()
} else {
app.buttons["PhotonMenu.cancel"].tap()
}
}
let backBtnBackAction = {
if map.isiPad() {
app.buttons["URLBarView.backButton"].tap()
}
else {
app.buttons["TabToolbar.backButton"].tap()
}
}
map.createScene(SettingsScreen) { scene in
let table = app.tables["AppSettingsTableViewController.tableView"]
scene.tap(table.cells["Search"], to: SearchSettings)
scene.tap(table.cells["NewTab"], to: NewTabSettings)
scene.tap(table.cells["Homepage"], to: HomePageSettings)
scene.tap(table.cells["TouchIDPasscode"], to: PasscodeSettings)
scene.tap(table.cells["Logins"], to: LoginsSettings)
scene.tap(table.cells["ClearPrivateData"], to: ClearPrivateDataSettings)
scene.tap(table.cells["OpenWith.Setting"], to: OpenWithSettings)
scene.tap(table.cells["ShowTour"], to: ShowTourInSettings)
scene.backAction = navigationControllerBackAction
}
map.createScene(SearchSettings) { scene in
scene.backAction = navigationControllerBackAction
}
map.createScene(NewTabSettings) { scene in
scene.backAction = navigationControllerBackAction
}
map.createScene(HomePageSettings) { scene in
scene.backAction = navigationControllerBackAction
}
map.createScene(PasscodeSettings) { scene in
scene.backAction = navigationControllerBackAction
scene.tap(app.tables["AuthenticationManager.settingsTableView"].staticTexts["Require Passcode"], to: PasscodeIntervalSettings)
}
map.createScene(PasscodeIntervalSettings) { scene in
// The test is likely to know what it needs to do here.
// This screen is protected by a passcode and is essentially modal.
scene.gesture(to: PasscodeSettings) {
if app.navigationBars["Require Passcode"].exists {
// Go back, accepting modifications
app.navigationBars["Require Passcode"].buttons["Passcode For Logins"].tap()
} else {
// Cancel
app.navigationBars["Enter Passcode"].buttons["Cancel"].tap()
}
}
}
map.createScene(LoginsSettings) { scene in
scene.gesture(to: SettingsScreen) {
let loginList = app.tables["Login List"]
if loginList.exists {
app.navigationBars["Logins"].buttons["Settings"].tap()
} else {
app.navigationBars["Enter Passcode"].buttons["Cancel"].tap()
}
}
}
map.createScene(ClearPrivateDataSettings) { scene in
scene.backAction = navigationControllerBackAction
}
map.createScene(OpenWithSettings) { scene in
scene.backAction = navigationControllerBackAction
}
map.createScene(ShowTourInSettings) { scene in
scene.gesture(to: Intro_FxASignin) {
let introScrollView = app.scrollViews["IntroViewController.scrollView"]
for _ in 1...4 {
introScrollView.swipeLeft()
}
app.buttons["Sign in to Firefox"].tap()
}
scene.backAction = {
introScrollView.swipeLeft()
startBrowsingButton.tap()
}
}
map.createScene(Intro_FxASignin) { scene in
scene.tap(app.navigationBars["Client.FxAContentView"].buttons.element(boundBy: 0), to: HomePanelsScreen)
}
map.createScene(PrivateTabTray) { scene in
scene.tap(app.buttons["TabTrayController.addTabButton"], to: PrivateHomePanelsScreen)
scene.tap(app.buttons["TabTrayController.maskButton"], to: TabTray)
}
map.createScene(TabTray) { scene in
scene.tap(app.buttons["TabTrayController.addTabButton"], to: HomePanelsScreen)
scene.tap(app.buttons["TabTrayController.maskButton"], to: PrivateTabTray)
}
map.createScene(BrowserTab) { scene in
scene.tap(app.textFields["url"], to: URLBarOpen)
scene.tap(app.buttons["TabToolbar.menuButton"], to: BrowserTabMenu)
if map.isiPad() {
scene.tap(app.buttons["TopTabsViewController.tabsButton"], to: TabTray)
} else {
scene.gesture(to: TabTray) {
if (app.buttons["TabToolbar.tabsButton"].exists) {
app.buttons["TabToolbar.tabsButton"].tap()
} else {
app.buttons["URLBarView.tabsButton"].tap()
}
}
}
scene.tap(app.buttons["TabLocationView.pageOptionsButton"], to: PageOptionsMenu)
scene.backAction = backBtnBackAction
}
// make sure after the menu action, navigator.nowAt() is used to set the current state
map.createScene(PageOptionsMenu) {scene in
scene.tap(app.tables["Context Menu"].cells["Find in Page"], to: FindInPage)
scene.backAction = cancelBackAction
scene.dismissOnUse = true
}
map.createScene(FindInPage) {scene in
scene.tap(app.buttons["FindInPage.close"], to: BrowserTab)
}
map.createScene(PrivateBrowserTab) { scene in
scene.tap(app.textFields["url"], to: URLBarOpen)
scene.tap(app.buttons["TabToolbar.menuButton"], to: BrowserTabMenu)
if map.isiPad() {
scene.tap(app.buttons["TopTabsViewController.tabsButton"], to: PrivateTabTray)
} else {
scene.gesture(to: PrivateTabTray) {
if (app.buttons["TabToolbar.tabsButton"].exists) {
app.buttons["TabToolbar.tabsButton"].tap()
} else {
app.buttons["URLBarView.tabsButton"].tap()
}
}
}
scene.tap(app.buttons["TabLocationView.pageOptionsButton"], to: PageOptionsMenu)
scene.backAction = backBtnBackAction
}
map.createScene(BrowserTabMenu) { scene in
scene.backAction = cancelBackAction
scene.tap(app.tables.cells["Settings"], to: SettingsScreen)
scene.dismissOnUse = true
}
map.initialSceneName = FirstRun
return map
}
extension ScreenGraph {
// Checks whether the current device is iPad or non-iPad
func isiPad() -> Bool {
if UIDevice.current.userInterfaceIdiom == .pad {
return true
}
return false
}
}
extension Navigator {
// Open a URL. Will use/re-use the first BrowserTab or NewTabScreen it comes to.
func openURL(urlString: String) {
self.goto(URLBarOpen)
let app = XCUIApplication()
app.textFields["address"].typeText(urlString + "\r")
self.nowAt(BrowserTab)
}
// Opens a URL in a new tab.
func openNewURL(urlString: String) {
self.goto(TabTray)
createNewTab()
self.openURL(urlString: urlString)
}
// Closes all Tabs from the option in TabTrayMenu
func closeAllTabs() {
let app = XCUIApplication()
app.buttons["TabTrayController.removeTabsButton"].tap()
app.sheets.buttons["Close All Tabs"].tap()
self.nowAt(HomePanelsScreen)
}
// Add a new Tab from the New Tab option in Browser Tab Menu
func createNewTab() {
let app = XCUIApplication()
self.goto(TabTray)
app.buttons["TabTrayController.addTabButton"].tap()
self.nowAt(HomePanelsScreen)
}
// Add Tab(s) from the Tab Tray
func createSeveralTabsFromTabTray(numberTabs: Int) {
for _ in 1...numberTabs {
self.goto(TabTray)
self.goto(HomePanelsScreen)
}
}
func browserPerformAction(_ view: BrowserPerformAction) {
let PageMenuOptions = [.toggleBookmarkOption, .addReadingListOption, .copyURLOption, .findInPageOption, .toggleDesktopOption, .pinToTopSitesOption, .sendToDeviceOption, BrowserPerformAction.shareOption]
let BrowserMenuOptions = [.openTopSitesOption, .openBookMarksOption, .openHistoryOption, .openReadingListOption, .toggleHideImages, .toggleNightMode, BrowserPerformAction.openSettingsOption]
let app = XCUIApplication()
if PageMenuOptions.contains(view) {
self.goto(PageOptionsMenu)
app.tables["Context Menu"].cells[view.rawValue].tap()
} else if BrowserMenuOptions.contains(view) {
self.goto(BrowserTabMenu)
app.tables["Context Menu"].cells[view.rawValue].tap()
}
}
}
enum BrowserPerformAction: String {
// Page Menu
case toggleBookmarkOption = "menu-Bookmark"
case addReadingListOption = "addToReadingList"
case copyURLOption = "menu-Copy-Link"
case findInPageOption = "menu-FindInPage"
case toggleDesktopOption = "menu-RequestDesktopSite"
case pinToTopSitesOption = "action_pin"
case sendToDeviceOption = "menu-Send-to-Device"
case shareOption = "action_share"
// Tab Menu
case openTopSitesOption = "menu-panel-TopSites"
case openBookMarksOption = "menu-panel-Bookmarks"
case openHistoryOption = "menu-panel-History"
case openReadingListOption = "menu-panel-ReadingList"
case toggleHideImages = "menu-NoImageMode"
case toggleNightMode = "menu-NightMode"
case openSettingsOption = "menu-Settings"
}

View file

@ -0,0 +1,44 @@
/* 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
let webpage = ["url": "www.mozilla.org", "label": "Internet for people, not profit — Mozilla", "value": "mozilla.org"]
class HistoryTests: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
func testEmptyHistoryListFirstTime() {
// Go to History List from Top Sites and check it is empty
navigator.goto(HomePanel_History)
waitforExistence(app.tables.cells["HistoryPanel.recentlyClosedCell"])
XCTAssertTrue(app.tables.cells["HistoryPanel.recentlyClosedCell"].exists)
XCTAssertTrue(app.tables.cells["HistoryPanel.syncedDevicesCell"].exists)
XCTAssertFalse(app.tables.otherElements.staticTexts["Today"].exists)
}
func testOpenHistoryFromBrowserContextMenuOptions() {
navigator.openURL(urlString: webpage["url"]!)
navigator.browserPerformAction(.openHistoryOption)
// Go to History List from Browser context menu and there should be one entry
waitforExistence(app.tables.cells["HistoryPanel.recentlyClosedCell"])
XCTAssertTrue(app.tables.otherElements.staticTexts["Today"].exists)
XCTAssertTrue(app.tables.cells.staticTexts[webpage["label"]!].exists)
}
func testOpenSyncDevices() {
navigator.goto(HomePanel_History)
app.tables.cells["HistoryPanel.syncedDevicesCell"].tap()
waitforExistence(app.tables.cells.staticTexts["Firefox Sync"])
XCTAssertTrue(app.tables/*@START_MENU_TOKEN@*/.buttons["Sign in"]/*[[".cells.buttons[\"Sign in\"]",".buttons[\"Sign in\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.exists)
}
}

View file

@ -0,0 +1,75 @@
/* 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 HomePageSettingsTest: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
super.tearDown()
}
// This test has moved from KIF UITest - accesses google.com instead of local webserver instance
func testCurrentPage() {
navigator.goto(BrowserTab)
// Accessing https means that it is routed
var currentURL = app.textFields["url"].value as! String
// Go via the menu, becuase if we go via the TabTray, then we
// won't have a current tab.
navigator.goto(HomePageSettings)
app.tables.staticTexts["Use Current Page"].tap()
// check the value of the current homepage
let homepageURL = app.tables.textFields["HomePageSettingTextField"].value as? String
if homepageURL?.hasPrefix("https://") == true {
currentURL = "https://\(currentURL)"
}
XCTAssertEqual(currentURL, homepageURL)
app.tables.staticTexts["Clear"].tap()
let urlString = app.tables.textFields["HomePageSettingTextField"].value ?? ""
if iPad() {
XCTAssertEqual("", urlString as! String)
} else {
XCTAssertEqual("Enter a webpage", urlString as! String)
}
}
/* Disabled due to new Photon UI
// Check whether the toolbar/menu shows homepage icon
func testShowHomePageIcon() {
// Check the Homepage icon is present in menu by default
navigator.goto(BrowserTab)
var currentURL = app.textFields["url"].value as! String
navigator.goto(PageOptionsMenu)
waitforExistence(app.tables.staticTexts["Set as Homepage"])
app.tables.staticTexts["Set as Homepage"].tap()
app.buttons["Set Homepage"].tap()
navigator.nowAt(BrowserTab)
navigator.goto(HomePageSettings)
if currentURL.hasPrefix("https://") == false {
currentURL = "https://\(currentURL)"
}
// Go to settings, and check the url are matching or not
let value = app.textFields["HomePageSettingTextField"].value as! String
XCTAssertEqual(value, currentURL,
"The webpage typed does not match with the one saved")
}
*/
}

View file

@ -0,0 +1,107 @@
/* 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
let websiteUrl1 = "www.mozilla.org"
let websiteUrl2 = "developer.mozilla.org"
let invalidUrl = "1-2-3"
class HomePageSettingsUITests: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
super.tearDown()
}
private func enterWebPageAsHomepage(text: String) {
app.textFields["HomePageSettingTextField"].tap()
app.textFields["HomePageSettingTextField"].typeText(text)
let value = app.textFields["HomePageSettingTextField"].value
XCTAssertEqual(value as? String, text, "The webpage typed does not match with the one saved")
}
func testTyping() {
navigator.goto(HomePageSettings)
// Enter a webpage
enterWebPageAsHomepage(text: websiteUrl1)
// Check if it is saved going back and then again to home settings menu
navigator.goto(HomePageSettings)
let valueAfter = app.textFields["HomePageSettingTextField"].value
XCTAssertEqual(valueAfter as? String, websiteUrl1)
// Check that it is actually set by opening a different website and going to Home
navigator.openURL(urlString: websiteUrl2)
navigator.goto(BrowserTabMenu)
//Now check open home page should load the previously saved home page
let homePageMenuItem = app.tables["Context Menu"].cells["Open Homepage"]
waitforExistence(homePageMenuItem)
homePageMenuItem.tap()
waitForValueContains(app.textFields["url"], value: websiteUrl1)
}
func testTypingBadURL() {
navigator.goto(HomePageSettings)
// Enter an invalid Url
enterWebPageAsHomepage(text: invalidUrl)
navigator.goto(SettingsScreen)
// Check that it is not saved
navigator.goto(HomePageSettings)
let valueAfter = app.textFields["HomePageSettingTextField"].value
XCTAssertEqual("Enter a webpage", valueAfter as! String)
// There is no option to go to Home, instead the website open has the option to be set as HomePageSettings
navigator.openURL(urlString: websiteUrl1)
navigator.goto(BrowserTabMenu)
let homePageMenuItem = app.tables["Context Menu"].cells["Open Homepage"]
XCTAssertFalse(homePageMenuItem.exists)
}
func testClipboard() {
// Go to a website and copy the url
navigator.openURL(urlString: websiteUrl1)
app.textFields["url"].press(forDuration: 5)
app.buttons["Copy Address"].tap()
// Go to HomePage settings and paste it using the option Used Copied Link
navigator.goto(HomePageSettings)
XCTAssertTrue(app.cells["Use Copied Link"].isEnabled)
app.cells["Use Copied Link"].tap()
// Check that the webpage has been correclty copied into the correct field
let value = app.textFields["HomePageSettingTextField"].value
XCTAssertEqual(value as? String, "https://\(websiteUrl1)/en-US/",
"The webpage typed does not match with the one saved")
}
func testDisabledClipboard() {
// Type an incorrect URL and copy it
navigator.goto(URLBarOpen)
app.textFields["address"].typeText(invalidUrl)
app.textFields["address"].press(forDuration: 5)
app.menuItems["Select All"].tap()
app.menuItems["Copy"].tap()
app.buttons["goBack"].tap()
// Go to HomePage settings and check that it is not possible to copy it into the set webpage field
navigator.nowAt(BrowserTab)
navigator.goto(HomePageSettings)
waitforExistence(app.staticTexts["Use Copied Link"])
// Check that nothing is copied in the Set webpage field
app.cells["Use Copied Link"].tap()
let value = app.textFields["HomePageSettingTextField"].value
XCTAssertEqual("Enter a webpage", value as! String)
}
}

View file

@ -0,0 +1,31 @@
/* 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 HomePageUITest: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
dismissFirstRunUI()
}
override func tearDown() {
super.tearDown()
}
func testSetInternalURLAsHomepage() {
loadWebPage("http://en.m.wikipedia.org/wiki/Main_Page")
app.buttons["Reader View"].tap()
navigator.goto(PageOptionsMenu)
app.cells["Set as Homepage"].tap()
app.buttons["Set Homepage"].tap()
navigator.nowAt(BrowserTab)
XCTAssertTrue(app.alerts.count == 0)
}
}

View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>10.6</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

View file

@ -0,0 +1,299 @@
/* 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
let website_1 = ["url": "www.mozilla.org", "label": "Internet for people, not profit — Mozilla", "value": "mozilla.org"]
let website_2 = ["url": "www.example.com", "label": "Example", "value": "example"]
let urlAddOns = "addons.mozilla.org"
let requestMobileSiteLabel = "Request Mobile Site"
let requestDesktopSiteLabel = "Request Desktop Site"
class NavigationTest: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
super.tearDown()
}
func testNavigation() {
navigator.goto(URLBarOpen)
let urlPlaceholder = "Search or enter address"
XCTAssert(app.textFields["url"].exists)
let defaultValuePlaceholder = app.textFields["url"].placeholderValue!
// Check the url placeholder text and that the back and forward buttons are disabled
XCTAssert(urlPlaceholder == defaultValuePlaceholder)
if iPad() {
app.buttons["goBack"].tap()
XCTAssertFalse(app.buttons["URLBarView.backButton"].isEnabled)
XCTAssertFalse(app.buttons["Forward"].isEnabled)
app.textFields["url"].tap()
} else {
XCTAssertFalse(app.buttons["TabToolbar.backButton"].isEnabled)
XCTAssertFalse(app.buttons["TabToolbar.forwardButton"].isEnabled)
}
// Once an url has been open, the back button is enabled but not the forward button
navigator.openURL(urlString: website_1["url"]!)
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: website_1["value"]!)
if iPad() {
XCTAssertTrue(app.buttons["URLBarView.backButton"].isEnabled)
XCTAssertFalse(app.buttons["Forward"].isEnabled)
} else {
XCTAssertTrue(app.buttons["TabToolbar.backButton"].isEnabled)
XCTAssertFalse(app.buttons["TabToolbar.forwardButton"].isEnabled)
}
// Once a second url is open, back button is enabled but not the forward one till we go back to url_1
navigator.openURL(urlString: website_2["url"]!)
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: website_2["value"]!)
if iPad() {
XCTAssertTrue(app.buttons["URLBarView.backButton"].isEnabled)
XCTAssertFalse(app.buttons["Forward"].isEnabled)
// Go back to previous visited web site
app.buttons["URLBarView.backButton"].tap()
} else {
XCTAssertTrue(app.buttons["TabToolbar.backButton"].isEnabled)
XCTAssertFalse(app.buttons["TabToolbar.forwardButton"].isEnabled)
// Go back to previous visited web site
app.buttons["TabToolbar.backButton"].tap()
}
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: website_1["value"]!)
if iPad() {
app.buttons["Forward"].tap()
} else {
// Go forward to next visited web site
app.buttons["TabToolbar.forwardButton"].tap()
}
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: website_2["value"]!)
}
func testTapSignInShowsFxAFromTour() {
// Open FxAccount from tour option in settings menu and go throughout all the screens there
navigator.goto(Intro_FxASignin)
checkFirefoxSyncScreenShown()
// Go back to NewTabScreen
navigator.goto(HomePanelsScreen)
waitforExistence(app.buttons["HomePanels.TopSites"])
}
func testTapSigninShowsFxAFromSettings() {
navigator.goto(SettingsScreen)
// Open FxAccount from settings menu and check the Sign in to Firefox scren
let signInToFirefoxStaticText = app.tables["AppSettingsTableViewController.tableView"].staticTexts["Sign in to Sync"]
signInToFirefoxStaticText.tap()
checkFirefoxSyncScreenShown()
// After that it is possible to go back to Settings
let settingsButton = app.navigationBars["Client.FxAContentView"].buttons["Settings"]
settingsButton.tap()
}
func testTapSignInShowsFxAFromRemoteTabPanel() {
navigator.goto(HomePanel_TopSites)
// Open FxAccount from remote tab panel and check the Sign in to Firefox scren
navigator.goto(HomePanel_History)
XCTAssertTrue(app.tables["History List"].staticTexts["Synced Devices"].isEnabled)
app.tables["History List"].staticTexts["Synced Devices"].tap()
app.tables.buttons["Sign in"].tap()
checkFirefoxSyncScreenShown()
app.navigationBars["Client.FxAContentView"].buttons["Done"].tap()
navigator.nowAt(HomePanel_History)
}
private func checkFirefoxSyncScreenShown() {
waitforExistence(app.webViews.staticTexts["Sign in"])
XCTAssertTrue(app.webViews.textFields["Email"].exists)
XCTAssertTrue(app.webViews.secureTextFields["Password"].exists)
XCTAssertTrue(app.webViews.buttons["Sign in"].exists)
}
func testScrollsToTopWithMultipleTabs() {
navigator.goto(TabTray)
navigator.openURL(urlString: website_1["url"]!)
waitForValueContains(app.textFields["url"], value: website_1["value"]!)
// Element at the TOP. TBChanged once the web page is correclty shown
let topElement = app.webViews.staticTexts["Internet for people, "]
// Element at the BOTTOM
let bottomElement = app.webViews.links.staticTexts["Contact Us"]
// Scroll to bottom
bottomElement.tap()
waitUntilPageLoad()
if iPad() {
app.buttons["URLBarView.backButton"].tap()
} else {
app.buttons["TabToolbar.backButton"].tap()
}
waitUntilPageLoad()
// Scroll to top
topElement.tap()
waitforExistence(topElement)
}
private func checkMobileView() {
let mobileViewElement = app.webViews.links.staticTexts["View classic desktop site"]
waitforExistence(mobileViewElement)
XCTAssertTrue (mobileViewElement.exists, "Mobile view is not available")
}
private func checkDesktopView() {
let desktopViewElement = app.webViews.links.staticTexts["View Mobile Site"]
waitforExistence(desktopViewElement)
XCTAssertTrue (desktopViewElement.exists, "Desktop view is not available")
}
private func clearData() {
navigator.goto(ClearPrivateDataSettings)
app.tables.staticTexts["Clear Private Data"].tap()
app.alerts.buttons["OK"].tap()
navigator.goto(HomePanel_TopSites)
}
func testToggleBetweenMobileAndDesktopSiteFromSite() {
clearData()
let goToDesktopFromMobile = app.webViews.links.staticTexts["View classic desktop site"]
// Open URL by default in mobile view
navigator.openURL(urlString: urlAddOns)
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: urlAddOns)
waitforExistence(goToDesktopFromMobile)
// From the website go to Desktop view
goToDesktopFromMobile.tap()
waitUntilPageLoad()
checkDesktopView()
// From the website go back to Mobile view
app.webViews.links.staticTexts["View Mobile Site"].tap()
waitUntilPageLoad()
checkMobileView()
}
func testToggleBetweenMobileAndDesktopSiteFromMenu() {
clearData()
navigator.openURL(urlString: urlAddOns)
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: urlAddOns)
// Mobile view by default, desktop view should be available
navigator.browserPerformAction(.toggleDesktopOption)
checkDesktopSite()
// From desktop view it is posible to change to mobile view again
navigator.nowAt(BrowserTab)
navigator.browserPerformAction(.toggleDesktopOption)
checkMobileSite()
}
private func checkMobileSite() {
app.buttons["TabLocationView.pageOptionsButton"].tap()
waitforExistence(app.tables.cells["menu-RequestDesktopSite"].staticTexts[requestDesktopSiteLabel])
navigator.goto(BrowserTab)
}
private func checkDesktopSite() {
app.buttons["TabLocationView.pageOptionsButton"].tap()
waitforExistence(app.tables.cells["menu-RequestDesktopSite"].staticTexts[requestMobileSiteLabel])
navigator.goto(BrowserTab)
}
func testNavigationPreservesDesktopSiteOnSameHost() {
clearData()
navigator.openURL(urlString: urlAddOns)
waitUntilPageLoad()
// Mobile view by default, desktop view should be available
navigator.browserPerformAction(.toggleDesktopOption)
waitforNoExistence(app.tables["Context Menu"])
checkDesktopView()
// Select any link to navigate to another site and check if the view is kept in desktop view
waitforExistence(app.webViews.links["Featured "])
app.webViews.links["Featured "].tap()
waitUntilPageLoad()
checkDesktopView()
}
func testReloadPreservesMobileOrDesktopSite() {
clearData()
navigator.openURL(urlString: urlAddOns)
waitUntilPageLoad()
// Mobile view by default, desktop view should be available
navigator.browserPerformAction(.toggleDesktopOption)
// After reloading a website the desktop view should be kept
if iPad() {
app.buttons["Reload"].tap()
} else {
app.buttons["TabToolbar.stopReloadButton"].tap()
}
waitForValueContains(app.textFields["url"], value: urlAddOns)
checkDesktopView()
// From desktop view it is posible to change to mobile view again
navigator.nowAt(BrowserTab)
navigator.browserPerformAction(.toggleDesktopOption)
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: urlAddOns)
// After reloading a website the mobile view should be kept
if iPad() {
app.buttons["Reload"].tap()
} else {
app.buttons["TabToolbar.stopReloadButton"].tap()
}
checkMobileView()
}
/* Disable test due to bug 1346157, the desktop view is not kept after going back and forward
func testBackForwardNavigationRestoresMobileOrDesktopSite() {
clearData()
let desktopViewElement = app.webViews.links.staticTexts["Mobile"]
// Open first url and keep it in mobile view
navigator.openURL(urlString: urlAddOns)
waitForValueContains(app.textFields["url"], value: urlAddOns)
checkMobileView()
// Open a second url and change it to desktop view
navigator.openURL(urlString: "www.linkedin.com")
navigator.goto(PageOptionsMenu)
waitforExistence(app.tables.cells["menu-RequestDesktopSite"].staticTexts[requestDesktopSiteLabel])
app.tables.cells["menu-RequestDesktopSite"].tap()
waitforExistence(desktopViewElement)
XCTAssertTrue (desktopViewElement.exists, "Desktop view is not available")
// Go back to first url and check that the view is still mobile view
app.buttons["TabToolbar.backButton"].tap()
waitForValueContains(app.textFields["url"], value: urlAddOns)
checkMobileView()
// Go forward to second url and check that the view is still desktop view
app.buttons["TabToolbar.forwardButton"].tap()
waitForValueContains(app.textFields["url"], value: "www.linkedin.com")
waitforExistence(desktopViewElement)
XCTAssertTrue (desktopViewElement.exists, "Desktop view is not available after coming from another site in mobile view")
}
*/
}

View file

@ -0,0 +1,65 @@
/* 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 NightModeTests: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
navigator = nil
app = nil
super.tearDown()
}
private func nightModeOff() {
navigator.goto(BrowserTabMenu)
app.tables.cells["Disable Night Mode"].tap()
navigator.nowAt(BrowserTab)
}
private func nightModeOn() {
navigator.goto(BrowserTabMenu)
app.tables.cells["Enable Night Mode"].tap()
navigator.nowAt(BrowserTab)
}
private func checkNightModeOn() {
navigator.goto(BrowserTabMenu)
waitforExistence(app.tables.cells["Disable Night Mode"])
navigator.goto(BrowserTab)
}
private func checkNightModeOff() {
navigator.goto(BrowserTabMenu)
waitforExistence(app.tables.cells["Enable Night Mode"])
navigator.goto(BrowserTab)
}
func testNightModeUI() {
let url1 = "www.google.com"
// Go to a webpage, and select night mode on and off, check it's applied or not
navigator.openNewURL(urlString: url1)
//turn on the night mode
nightModeOn()
//checking night mode on or off
checkNightModeOn()
//turn off the night mode
nightModeOff()
//checking night mode on or off
checkNightModeOff()
}
}

View file

@ -0,0 +1,65 @@
/* 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 NoImageTests: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
static let NoImageButtonIdentifier = "menu-NoImageMode"
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
navigator = nil
app = nil
super.tearDown()
}
private func showImages() {
navigator.goto(BrowserTabMenu)
app.tables["Context Menu"].cells["menu-NoImageMode"].tap()
navigator.nowAt(BrowserTab)
}
private func hideImages() {
navigator.goto(BrowserTabMenu)
app.tables["Context Menu"].cells["menu-NoImageMode"].tap()
navigator.nowAt(BrowserTab)
}
private func checkShowImages() {
navigator.goto(BrowserTabMenu)
waitforExistence(app.tables["Context Menu"].cells["menu-NoImageMode"])
XCTAssertTrue(app.tables["Context Menu"].cells["menu-NoImageMode"].staticTexts["Show Images"].exists)
navigator.goto(BrowserTab)
}
private func checkHideImages() {
navigator.goto(BrowserTabMenu)
waitforExistence(app.tables["Context Menu"].cells["menu-NoImageMode"])
XCTAssertTrue(app.tables["Context Menu"].cells["menu-NoImageMode"].staticTexts["Hide Images"].exists)
navigator.goto(BrowserTab)
}
// Functionality is tested by UITests/NoImageModeTests, here only the UI is updated properly
func testImageOnOff() {
// Go to a webpage, and select no images or hide images, check it's hidden or not
navigator.openNewURL(urlString: "www.google.com")
waitUntilPageLoad()
// Select hide images, and check the UI is updated
hideImages()
checkShowImages()
// Select show images, and check the UI is updated
showImages()
checkHideImages()
}
}

View file

@ -0,0 +1,87 @@
/* 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 PhotonActionSheetTest: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
func testPinToTop() {
navigator.openURL(urlString: "http://example.com")
waitUntilPageLoad()
// Open Action Sheet
app.buttons["TabLocationView.pageOptionsButton"].tap()
// Pin the site
app.cells["Pin to Top Sites"].tap()
// Verify that the site has been pinned
// Open menu
app.buttons["Menu"].tap()
// Navigate to top sites
app.cells["Top Sites"].tap()
waitforExistence(app.cells["TopSite"].firstMatch)
// Verify that the site is pinned to top
let cell = app.cells["TopSite"].firstMatch
XCTAssertEqual(cell.label, "example")
// Remove pin
cell.press(forDuration: 2)
app.cells["Remove"].tap()
}
func testShareOptionIsShown() {
navigator.browserPerformAction(.shareOption)
// Wait to see the Share options sheet
waitforExistence(app.buttons["Copy"])
}
func testShareOptionIsShownFromShortCut() {
navigator.goto(BrowserTab)
waitUntilPageLoad()
app.buttons["TabLocationView.pageOptionsButton"].press(forDuration: 1)
// Wait to see the Share options sheet
waitforExistence(app.buttons["Copy"])
}
func testSendToDeviceFromPageOptionsMenu() {
// User not logged in
navigator.browserPerformAction(.sendToDeviceOption)
waitforExistence(app.images["emptySync"])
XCTAssertTrue(app.staticTexts["You are not signed in to your Firefox Account."].exists)
}
func testSendToDeviceFromShareOption() {
// Open and Wait to see the Share options sheet
navigator.browserPerformAction(.shareOption)
waitforExistence(app.buttons["More"])
waitforNoExistence(app.buttons["Send Tab"])
app.collectionViews.cells/*@START_MENU_TOKEN@*/.collectionViews.containing(.button, identifier:"Copy")/*[[".collectionViews.containing(.button, identifier:\"Create PDF\")",".collectionViews.containing(.button, identifier:\"Print\")",".collectionViews.containing(.button, identifier:\"Copy\")"],[[[-1,2],[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.buttons["More"].tap()
// Enable Send Tab
let sendTabButton = app.tables.cells.switches["Send Tab"]
sendTabButton.tap()
app.navigationBars["Activities"].buttons["Done"].tap()
// Send Tab option appears on the Share options sheet
waitforExistence(app.buttons["Send Tab"])
app.buttons["Send Tab"].tap()
// User not logged in
waitforExistence(app.images["emptySync"])
XCTAssertTrue(app.staticTexts["You are not signed in to your Firefox Account."].exists)
}
}

View file

@ -0,0 +1,166 @@
/* 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
let url1 = "www.mozilla.org"
let url2 = "www.facebook.com"
let url1Label = "Internet for people, not profit — Mozilla"
let url2Label = "Facebook - Log In or Sign Up"
class PrivateBrowsingTest: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
super.tearDown()
}
func testPrivateTabDoesNotTrackHistory() {
navigator.openURL(urlString: url1)
navigator.goto(BrowserTabMenu)
// Go to History screen
waitforExistence(app.tables.cells["History"])
app.tables.cells["History"].tap()
navigator.nowAt(BrowserTab)
waitforExistence(app.tables["History List"])
XCTAssertTrue(app.tables["History List"].staticTexts[url1Label].exists)
// History without counting Recently Closed and Synced devices
let history = app.tables["History List"].cells.count - 2
XCTAssertEqual(history, 1, "History entries in regular browsing do not match")
// Go to Private browsing to open a website and check if it appears on History
navigator.goto(PrivateTabTray)
navigator.openURL(urlString: url2)
navigator.nowAt(PrivateBrowserTab)
waitForValueContains(app.textFields["url"], value: "facebook")
navigator.goto(BrowserTabMenu)
waitforExistence(app.tables.cells["History"])
app.tables.cells["History"].tap()
waitforExistence(app.tables["History List"])
XCTAssertTrue(app.tables["History List"].staticTexts[url1Label].exists)
XCTAssertFalse(app.tables["History List"].staticTexts[url2Label].exists)
// Open one tab in private browsing and check the total number of tabs
let privateHistory = app.tables["History List"].cells.count - 2
XCTAssertEqual(privateHistory, 1, "History entries in private browsing do not match")
}
func testTabCountShowsOnlyNormalOrPrivateTabCount() {
// Open two tabs in normal browsing and check the number of tabs open
navigator.openNewURL(urlString: url1)
waitUntilPageLoad()
navigator.goto(TabTray)
navigator.goto(BrowserTab)
navigator.goto(TabTray)
waitforExistence(app.collectionViews.cells[url1Label])
let numTabs = app.collectionViews.cells.count
XCTAssertEqual(numTabs, 3, "The number of regular tabs is not correct")
// Open one tab in private browsing and check the total number of tabs
navigator.goto(PrivateTabTray)
navigator.goto(URLBarOpen)
waitUntilPageLoad()
navigator.openURL(urlString: url2)
waitUntilPageLoad()
navigator.nowAt(PrivateBrowserTab)
waitForValueContains(app.textFields["url"], value: "facebook")
navigator.goto(PrivateTabTray)
waitforExistence(app.collectionViews.cells[url2Label])
let numPrivTabs = app.collectionViews.cells.count
XCTAssertEqual(numPrivTabs, 1, "The number of private tabs is not correct")
// Go back to regular mode and check the total number of tabs
navigator.goto(TabTray)
waitforExistence(app.collectionViews.cells[url1Label])
waitforNoExistence(app.collectionViews.cells[url2Label])
let numRegularTabs = app.collectionViews.cells.count
XCTAssertEqual(numRegularTabs, 3, "The number of regular tabs is not correct")
}
func testClosePrivateTabsOptionClosesPrivateTabs() {
// Check that Close Private Tabs when closing the Private Browsing Button is off by default
navigator.goto(SettingsScreen)
let settingsTableView = app.tables["AppSettingsTableViewController.tableView"]
while settingsTableView.staticTexts["Close Private Tabs"].exists == false {
settingsTableView.swipeUp()
}
let closePrivateTabsSwitch = settingsTableView.switches["Close Private Tabs, When Leaving Private Browsing"]
XCTAssertFalse(closePrivateTabsSwitch.isSelected)
// Open a Private tab
navigator.goto(PrivateTabTray)
navigator.openURL(urlString: url1)
//Wait until the page loads
waitUntilPageLoad()
navigator.nowAt(PrivateBrowserTab)
navigator.goto(PrivateTabTray)
// Go back to regular browser
navigator.goto(TabTray)
// Go back to private browsing and check that the tab has not been closed
navigator.goto(PrivateTabTray)
waitforExistence(app.collectionViews.cells[url1Label])
let numPrivTabs = app.collectionViews.cells.count
XCTAssertEqual(numPrivTabs, 1, "The number of tabs is not correct, the private tab should not have been closed")
app.collectionViews.cells[url1Label].tap()
navigator.nowAt(PrivateBrowserTab)
// Now the enable the Close Private Tabs when closing the Private Browsing Button
navigator.goto(SettingsScreen)
closePrivateTabsSwitch.tap()
navigator.goto(PrivateBrowserTab)
// Go back to regular browsing and check that the private tab has been closed and that the initial Private Browsing message appears when going back to Private Browsing
navigator.goto(PrivateTabTray)
navigator.goto(TabTray)
navigator.goto(PrivateTabTray)
waitforNoExistence(app.collectionViews.cells[url1Label])
let numPrivTabsAfterClosing = app.collectionViews.cells.count
XCTAssertEqual(numPrivTabsAfterClosing, 0, "The number of tabs is not correct, the private tab should have been closed")
XCTAssertTrue(app.staticTexts["Private Browsing"].exists, "Private Browsing screen is not shown")
}
func testPrivateBrowserPanelView() {
// If no private tabs are open, there should be a initial screen with label Private Browsing
navigator.goto(PrivateTabTray)
XCTAssertTrue(app.staticTexts["Private Browsing"].exists, "Private Browsing screen is not shown")
let numPrivTabsFirstTime = app.collectionViews.cells.count
XCTAssertEqual(numPrivTabsFirstTime, 0, "The number of tabs is not correct, there should not be any private tab yet")
// If a private tab is open Private Browsing screen is not shown anymore
navigator.goto(PrivateBrowserTab)
//Wait until the page loads
waitUntilPageLoad()
navigator.goto(PrivateTabTray)
// Go to regular browsing
navigator.goto(TabTray)
// Go back to private brosing
navigator.goto(PrivateTabTray)
waitforNoExistence(app.staticTexts["Private Browsing"])
XCTAssertFalse(app.staticTexts["Private Browsing"].exists, "Private Browsing screen is shown")
let numPrivTabsOpen = app.collectionViews.cells.count
XCTAssertEqual(numPrivTabsOpen, 1, "The number of tabs is not correct, there should be one private tab")
}
}

View file

@ -0,0 +1,143 @@
/* 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 ReaderViewTest: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
super.tearDown()
}
func testLoadReaderContent() {
navigator.goto(BrowserTab)
app.buttons["Reader View"].tap()
// The settings of reader view are shown as well as the content of the web site
waitforExistence(app.buttons["Display Settings"])
XCTAssertTrue(app.webViews.staticTexts["The Book of Mozilla"].exists)
}
private func addContentToReaderView() {
navigator.goto(BrowserTab)
waitUntilPageLoad()
app.buttons["Reader View"].tap()
waitforExistence(app.buttons["Add to Reading List"])
app.buttons["Add to Reading List"].tap()
}
private func checkReadingListNumberOfItems(items: Int) {
waitforExistence(app.tables["ReadingTable"])
let list = app.tables["ReadingTable"].cells.count
XCTAssertEqual(list, UInt(items), "The number of items in the reading table is not correct")
}
func testAddToReadingList() {
// Initially reading list is empty
navigator.goto(HomePanel_ReadingList)
// Check the button is selected (is disabled and the rest bookmarks and so are enabled)
XCTAssertFalse(app.buttons["HomePanels.ReadingList"].isEnabled)
XCTAssertTrue(app.buttons["HomePanels.Bookmarks"].isEnabled)
checkReadingListNumberOfItems(items: 0)
// Add item to reading list and check that it appears
addContentToReaderView()
navigator.goto(HomePanel_ReadingList)
waitforExistence(app.buttons["HomePanels.ReadingList"])
// Check that there is one item
let savedToReadingList = app.tables["ReadingTable"].cells.staticTexts["The Book of Mozilla"]
XCTAssertTrue(savedToReadingList.exists)
checkReadingListNumberOfItems(items: 1)
}
func testMarkAsReadAndUreadFromReaderView() {
addContentToReaderView()
// Mark the content as read, so the mark as unread buttons appear
app.buttons["Mark as Read"].tap()
waitforExistence(app.buttons["Mark as Unread"])
// Mark the content as unread, so the mark as read button appear
app.buttons["Mark as Unread"].tap()
waitforExistence(app.buttons["Mark as Read"])
}
func testRemoveFromReadingView() {
addContentToReaderView()
// Once the content has been added, remove it
waitforExistence(app.buttons["Remove from Reading List"])
app.buttons["Remove from Reading List"].tap()
// Check that instead of the remove icon now it is shown the add to read list
waitforExistence(app.buttons["Add to Reading List"])
// Go to reader list view to check that there is not any item there
navigator.goto(HomePanel_ReadingList)
waitforExistence(app.buttons["HomePanels.ReadingList"])
navigator.goto(HomePanel_ReadingList)
checkReadingListNumberOfItems(items: 0)
}
func testMarkAsReadAndUnreadFromReadingList() {
addContentToReaderView()
navigator.goto(HomePanel_ReadingList)
waitforExistence(app.buttons["HomePanels.ReadingList"])
navigator.goto(HomePanel_ReadingList)
// Check that there is one item
let savedToReadingList = app.tables["ReadingTable"].cells.staticTexts["The Book of Mozilla"]
XCTAssertTrue(savedToReadingList.exists)
// Mark it as read/unread
savedToReadingList.swipeLeft()
waitforExistence(app.buttons["Mark as Read"])
app.buttons["Mark as Read"].tap()
savedToReadingList.swipeLeft()
waitforExistence(app.buttons["Mark as Unread"])
}
func testRemoveFromReadingList() {
addContentToReaderView()
navigator.goto(HomePanel_ReadingList)
waitforExistence(app.buttons["HomePanels.ReadingList"])
navigator.goto(HomePanel_ReadingList)
let savedToReadingList = app.tables["ReadingTable"].cells.staticTexts["The Book of Mozilla"]
savedToReadingList.swipeLeft()
waitforExistence(app.buttons["Remove"])
// Remove the item from reading list
app.buttons["Remove"].tap()
XCTAssertFalse(savedToReadingList.exists)
// Reader list view should be empty
checkReadingListNumberOfItems(items: 0)
}
func testAddToReadingListFromPageOptionsMenu() {
// First time Reading list is empty
navigator.goto(HomePanel_ReadingList)
checkReadingListNumberOfItems(items: 0)
// Add item to Reading List from Page Options Menu
navigator.goto(BrowserTab)
waitUntilPageLoad()
navigator.browserPerformAction(.addReadingListOption)
// Now there should be an item on the list
navigator.nowAt(BrowserTab)
navigator.browserPerformAction(.openReadingListOption)
checkReadingListNumberOfItems(items: 1)
}
}

View file

@ -0,0 +1,388 @@
/* 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/. */
/**
* ScreenGraph helps you get rid of the navigation boiler plate found in a lot of whole-application UI testing.
*
* You create a shared graph of UI 'screens' or 'scenes' for your app, and use it for every test.
*
* In your tests, you use a navigator which does the job of getting your tests from place to place in your application,
* leaving you to concentrate on testing, rather than maintaining brittle and duplicated navigation code.
*
* The shared graph may also have other uses, such as generating screen shots for the App Store or L10n translators.
*
* Under the hood, the ScreenGraph is using GameplayKit's path finding to do the heavy lifting.
*/
import Foundation
import GameplayKit
import XCTest
typealias Edge = (XCTestCase, String, UInt) -> Void
typealias SceneBuilder = (ScreenGraphNode) -> Void
typealias NodeVisitor = (String) -> Void
/**
* ScreenGraph
* This is the main interface to building a graph of screens/app states and how to navigate between them.
* The ScreenGraph will be used as a map to navigate the test agent around the app.
*/
open class ScreenGraph {
var initialSceneName: String?
var namedScenes: [String: ScreenGraphNode] = [:]
var nodedScenes: [GKGraphNode: ScreenGraphNode] = [:]
var isReady: Bool = false
let gkGraph: GKGraph
init() {
self.gkGraph = GKGraph()
}
}
extension ScreenGraph {
/**
* Method for creating a ScreenGraphNode in the graph. The node should be accompanied by a closure
* used to document the exits out of this node to other nodes.
*/
func createScene(_ name: String, file: String = #file, line: UInt = #line, builder: @escaping (ScreenGraphNode) -> Void) {
let scene = ScreenGraphNode(map: self, name: name, builder: builder)
scene.file = file
scene.line = line
namedScenes[name] = scene
nodedScenes[scene.gkNode] = scene
}
}
extension ScreenGraph {
/**
* Create a new navigator object. Navigator objects are the main way of getting around the app.
* Typically, you'll do this in `TestCase.setUp()`
*/
func navigator(_ xcTest: XCTestCase, startingAt: String? = nil, file: String = #file, line: UInt = #line) -> Navigator {
buildGkGraph()
var current: ScreenGraphNode?
if let name = startingAt ?? initialSceneName {
current = namedScenes[name]
}
if current == nil {
xcTest.recordFailure(withDescription: "The app's initial state couldn't be established.",
inFile: file, atLine: line, expected: false)
}
return Navigator(self, xcTest: xcTest, initialScene: current!)
}
fileprivate func buildGkGraph() {
if isReady {
return
}
isReady = true
// Construct all the GKGraphNodes, and add them to the GKGraph.
let scenes = namedScenes.values
gkGraph.add(scenes.map { $0.gkNode })
// Now, use the scene builders to collect edge actions and destinations.
scenes.forEach { scene in
scene.builder(scene)
}
scenes.forEach { scene in
let gkNodes = scene.edges.keys.flatMap { self.namedScenes[$0]?.gkNode } as [GKGraphNode]
scene.gkNode.addConnections(to: gkNodes, bidirectional: false)
}
}
}
typealias Gesture = () -> Void
/**
* The ScreenGraph is made up of nodes. It is not possible to init these directly, only by creating
* screen nodes from the ScreenGraph object.
*
* The ScreenGraphNode has all the methods needed to define edges from this node to another node, using the usual
* XCUIElement method of moving about.
*/
class ScreenGraphNode {
let name: String
fileprivate let builder: SceneBuilder
fileprivate let gkNode: GKGraphNode
fileprivate var edges: [String: Edge] = [:]
fileprivate weak var map: ScreenGraph?
// Iff this node has a backAction, this store temporarily stores
// the node we were at before we got to this one. This becomes the node we return to when the backAction is
// invoked.
fileprivate weak var returnNode: ScreenGraphNode?
fileprivate var hasBack: Bool {
return backAction != nil
}
/**
* This is an action that will cause us to go back from where we came from.
* This is most useful when the same screen is accessible from multiple places,
* and we have a back button to return to where we came from.
*/
var backAction: Gesture?
/**
* This flag indicates that once we've moved on from this node, we can't come back to
* it via `backAction`. This is especially useful for Menus, and dialogs.
*/
var dismissOnUse: Bool = false
var existsWhen: XCUIElement?
fileprivate var line: UInt!
fileprivate var file: String!
fileprivate init(map: ScreenGraph, name: String, builder: @escaping SceneBuilder) {
self.map = map
self.name = name
self.gkNode = GKGraphNode()
self.builder = builder
}
fileprivate func addEdge(_ dest: String, by edge: @escaping Edge) {
edges[dest] = edge
// by this time, we should've added all nodes in to the gkGraph.
assert(map?.namedScenes[dest] != nil, "Destination scene '\(dest)' has not been created anywhere")
}
}
private let existsPredicate = NSPredicate(format: "exists == true")
private let enabledPredicate = NSPredicate(format: "enabled == true")
private let hittablePredicate = NSPredicate(format: "hittable == true")
private let noopNodeVisitor: NodeVisitor = { _ in }
extension ScreenGraphNode {
fileprivate func waitForElement(_ element: XCUIElement, withTest xcTest: XCTestCase, notFoundHandler: () -> Void) {
// Wait for 5 seconds for the element to exist.
let expectation = XCTNSPredicateExpectation(predicate: existsPredicate, object: element)
let result = XCTWaiter().wait(for: [expectation], timeout: 5)
if result != .completed {
notFoundHandler()
}
}
}
// Public methods for defining edges out of this node.
extension ScreenGraphNode {
/**
* Declare that by performing the given action/gesture, then we can navigate from this node to the next.
*
* @param withElement optional, but if provided will attempt to verify it is there before performing the action.
* @param to the destination node.
*/
func gesture(withElement element: XCUIElement? = nil, to nodeName: String, file declFile: String = #file, line declLine: UInt = #line, g: @escaping () -> Void) {
addEdge(nodeName) { xcTest, file, line in
if let el = element {
self.waitForElement(el, withTest: xcTest) { _ in
xcTest.recordFailure(withDescription: "Cannot find \(el)", inFile: declFile, atLine: declLine, expected: false)
xcTest.recordFailure(withDescription: "Cannot get from \(self.name) to \(nodeName). See \(declFile)", inFile: file, atLine: line, expected: false)
}
}
g()
}
}
func noop(to nodeName: String, file: String = #file, line: UInt = #line) {
self.gesture(to: nodeName, file: file, line: line) {
// NOOP.
}
}
/**
* Declare that by tapping a given element, we should be able to navigate from this node to another.
*
* @param element - the element to tap
* @param to the destination node.
*/
func tap(_ element: XCUIElement, to nodeName: String, file: String = #file, line: UInt = #line) {
self.gesture(withElement: element, to: nodeName, file: file, line: line) {
element.tap()
}
}
func doubleTap(_ element: XCUIElement, to nodeName: String, file: String = #file, line: UInt = #line) {
self.gesture(withElement: element, to: nodeName, file: file, line: line) {
element.doubleTap()
}
}
func typeText(_ text: String, into element: XCUIElement, to nodeName: String, file: String = #file, line: UInt = #line) {
self.gesture(withElement: element, to: nodeName, file: file, line: line) {
element.typeText(text)
}
}
func swipeLeft(_ element: XCUIElement, to nodeName: String, file: String = #file, line: UInt = #line) {
self.gesture(withElement: element, to: nodeName, file: file, line: line) {
element.swipeLeft()
}
}
func swipeRight(_ element: XCUIElement, to nodeName: String, file: String = #file, line: UInt = #line) {
self.gesture(withElement: element, to: nodeName, file: file, line: line) {
element.swipeRight()
}
}
func swipeUp(_ element: XCUIElement, to nodeName: String, file: String = #file, line: UInt = #line) {
self.gesture(withElement: element, to: nodeName, file: file, line: line) {
element.swipeUp()
}
}
func swipeDown(_ element: XCUIElement, to nodeName: String, file: String = #file, line: UInt = #line) {
self.gesture(withElement: element, to: nodeName, file: file, line: line) {
element.swipeDown()
}
}
}
/**
* The Navigator provides a set of methods to navigate around the app. You can `goto` nodes, `visit` multiple nodes,
* or visit all nodes, but mostly you just goto. If you take actions that move around the app outside of the
* navigator, you can re-sync app with navigator my telling it which node it is now at, using the `nowAt` method.
*/
class Navigator {
fileprivate let map: ScreenGraph
fileprivate var currentScene: ScreenGraphNode
fileprivate var returnToRecentScene: ScreenGraphNode
fileprivate let xcTest: XCTestCase
fileprivate init(_ map: ScreenGraph, xcTest: XCTestCase, initialScene: ScreenGraphNode) {
self.map = map
self.xcTest = xcTest
self.currentScene = initialScene
self.returnToRecentScene = initialScene
}
/**
* Move the application to the named node.
*/
func goto(_ nodeName: String, file: String = #file, line: UInt = #line) {
goto(nodeName, file: file, line: line, visitWith: noopNodeVisitor)
}
/**
* Move the application to the named node, wth an optional node visitor closure, which is called each time the
* node changes.
*/
func goto(_ nodeName: String, file: String = #file, line: UInt = #line, visitWith nodeVisitor: NodeVisitor) {
let gkSrc = currentScene.gkNode
guard let gkDest = map.namedScenes[nodeName]?.gkNode else {
xcTest.recordFailure(withDescription: "Cannot route to \(nodeName), because it doesn't exist", inFile: file, atLine: line, expected: false)
return
}
var gkPath = map.gkGraph.findPath(from: gkSrc, to: gkDest)
guard gkPath.count > 0 else {
xcTest.recordFailure(withDescription: "Cannot route from \(currentScene.name) to \(nodeName)", inFile: file, atLine: line, expected: false)
return
}
gkPath.removeFirst()
gkPath.forEach { gkNext in
if !currentScene.dismissOnUse {
returnToRecentScene = currentScene
}
let nextScene = map.nodedScenes[gkNext]!
let action = currentScene.edges[nextScene.name]!
// We definitely have an action, so it's save to unbox.
action(xcTest, file, line)
if let testElement = nextScene.existsWhen {
nextScene.waitForElement(testElement, withTest: xcTest) { _ in
// TODO report error in the correct place in the graph.
self.xcTest.recordFailure(withDescription: "Cannot find \(testElement) in \(nextScene.name)",
inFile: nextScene.file,
atLine: nextScene.line,
expected: false)
}
}
if nextScene.hasBack {
if nextScene.returnNode == nil {
nextScene.returnNode = returnToRecentScene
nextScene.gkNode.addConnections(to: [ returnToRecentScene.gkNode ], bidirectional: false)
nextScene.gesture(to: returnToRecentScene.name, g: nextScene.backAction!)
}
}
if currentScene.hasBack {
if nextScene.name == currentScene.returnNode?.name {
currentScene.returnNode = nil
currentScene.gkNode.removeConnections(to: [ nextScene.gkNode ], bidirectional: false)
}
}
nodeVisitor(currentScene.name)
currentScene = nextScene
}
}
/**
* Helper method when the navigator gets out of sync with the actual app.
* This should not be used too often, as it indicates you should probably have another node in your graph,
* or you should be using `scene.dismissOnUse = true`.
* Also useful if you're using XCUIElement taps directly to navigate from one node to another.
*/
func nowAt(_ nodeName: String, file: String = #file, line: UInt = #line) {
guard let newScene = map.namedScenes[nodeName] else {
xcTest.recordFailure(withDescription: "Cannot force to unknown \(nodeName). Currently at \(currentScene.name)", inFile: file, atLine: line, expected: false)
return
}
currentScene = newScene
}
/**
* Visit the named nodes, calling the NodeVisitor the first time it is encountered.
*/
func visitNodes(_ nodes: [String], file: String = #file, line: UInt = #line, f: NodeVisitor) {
var visitedNodes = Set<String>()
let desiredNodes = Set<String>(nodes)
nodes.forEach { node in
if visitedNodes.contains(node) {
return
}
self.goto(node, file: file, line: line) { visitedNode in
if desiredNodes.contains(visitedNode) && !visitedNodes.contains(visitedNode) {
f(visitedNode)
}
visitedNodes.insert(visitedNode)
}
}
}
/**
* Visit all nodes, calling the NodeVisitor the first time it is encountered.
*
* Some nodes may not be immediately available, depending on the state of the app.
*/
func visitAll(_ file: String = #file, line: UInt = #line, f: NodeVisitor) {
let nodes: [String] = self.map.namedScenes.keys.map { $0 } // keys can't be coerced into a [String]
self.visitNodes(nodes, file: file, line: line, f: f)
}
/**
* Move the app back to its initial state.
* This may not be possible.
*/
func revert(_ file: String = #file, line: UInt = #line) {
if let initial = self.map.initialSceneName {
self.goto(initial, file: file, line: line)
}
}
}

View file

@ -0,0 +1,123 @@
/* 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
let defaultSearchEngine1 = "Google"
let defaultSearchEngine2 = "Amazon.com"
let customSearchEngine = ["name": "youtube", "url": "http://youtube.com/search?q=%s"]
class SearchSettingsUITests: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
super.tearDown()
}
func testDefaultSearchEngine() {
navigator.goto(SearchSettings)
// Check the default browser
let defaultSearchEngine = app.tables.cells.element(boundBy: 0)
waitforExistence(app.tables.cells.staticTexts[defaultSearchEngine1])
// Change to another browser and check it is set as default
defaultSearchEngine.tap()
let listOfEngines = app.tables
listOfEngines.staticTexts[defaultSearchEngine2].tap()
waitforExistence(app.tables.cells.staticTexts[defaultSearchEngine2])
}
func testCustomSearchEngineIsEditable() {
navigator.goto(SearchSettings)
// Add a custom search engine
addCustomSearchEngine()
// Check that the custom search appears on the list
waitforExistence(app.tables.cells.staticTexts[customSearchEngine["name"]!])
// Check that it can be edited
XCTAssertTrue(app.buttons["Edit"].isEnabled)
app.buttons["Edit"].tap()
waitforExistence(app.tables.buttons["Delete \(customSearchEngine["name"]!)"])
}
private func addCustomSearchEngine() {
waitforExistence(app.tables.cells["customEngineViewButton"])
app.tables.cells["customEngineViewButton"].tap()
waitforExistence(app.tables.cells.staticTexts["Search Engine"])
app.tables.cells.textViews["customEngineTitle"].tap()
app.tables.cells.textViews["customEngineTitle"].typeText(customSearchEngine["name"]!)
app.tables.cells.textViews["customEngineUrl"].tap()
app.tables.cells.textViews["customEngineUrl"].typeText(customSearchEngine["url"]!)
app.buttons["Save"].tap()
// Check that custom engine has been added successfully
waitforExistence(app.tables.cells.staticTexts[customSearchEngine["name"]!])
}
func testCustomSearchEngineAsDefaultIsNotEditable() {
navigator.goto(SearchSettings)
// Edit is disabled
XCTAssertFalse(app.buttons["Edit"].isEnabled)
addCustomSearchEngine()
// Edit is enabled
XCTAssertTrue(app.buttons["Edit"].isEnabled)
// Select the custom engine as the default one
let defaultSearchEngine = app.tables.cells.element(boundBy: 0)
defaultSearchEngine.tap()
let listOfEngines = app.tables
listOfEngines.staticTexts[customSearchEngine["name"]!].tap()
// Edit is disabled
XCTAssertFalse(app.buttons["Edit"].isEnabled)
}
func testNavigateToSearchPickerTurnsOffEditing() {
navigator.goto(SearchSettings)
// Edit is disabled
XCTAssertFalse(app.buttons["Edit"].isEnabled)
addCustomSearchEngine()
// Edit is enabled
XCTAssertTrue(app.buttons["Edit"].isEnabled)
app.buttons["Edit"].tap()
XCTAssertTrue(app.buttons["Done"].isEnabled)
// Navigate to the search engine picker and back
let defaultSearchEngine = app.tables.cells.element(boundBy: 0)
defaultSearchEngine.tap()
app.buttons["Cancel"].tap()
// Check to see we're not in editing state, edit is enable and done does not appear
XCTAssertTrue(app.buttons["Edit"].isEnabled)
waitforNoExistence(app.buttons["Done"])
}
func testDeletingLastCustomEngineExitsEditing() {
navigator.goto(SearchSettings)
// Edit is disabled
XCTAssertFalse(app.buttons["Edit"].isEnabled)
// Add a custom search engine
addCustomSearchEngine()
XCTAssertTrue(app.buttons["Edit"].isEnabled)
app.buttons["Edit"].tap()
XCTAssertTrue(app.buttons["Done"].isEnabled)
// Remove the custom search engine and check that edit is disabled
let tablesQuery = app.tables
tablesQuery.buttons["Delete \(customSearchEngine["name"]!)"].tap()
tablesQuery.buttons["Delete"].tap()
XCTAssertFalse(app.buttons["Edit"].isEnabled)
}
}

View file

@ -0,0 +1,178 @@
/* 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
private let LabelPrompt: String = "Turn on search suggestions?"
private let SuggestedSite: String = "foobar meaning"
class SearchTests: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
super.tearDown()
}
private func typeOnSearchBar(text: String) {
waitforExistence(app.textFields["address"])
app.textFields["address"].typeText(text)
}
private func suggestionsOnOff() {
navigator.goto(SearchSettings)
app.tables.switches["Show Search Suggestions"].tap()
app.navigationBars["Search"].buttons["Settings"].tap()
app.navigationBars["Settings"].buttons["AppSettingsTableViewController.navigationItem.leftBarButtonItem"].tap()
}
func testPromptPresence() {
// Suggestion is on by default (starting on Oct 24th 2017), so the prompt should not appear
navigator.goto(URLBarOpen)
typeOnSearchBar(text: "foobar")
waitforNoExistence(app.staticTexts[LabelPrompt])
// Suggestions should be shown
waitforExistence(app.tables["SiteTable"].buttons[SuggestedSite])
// Disable Search suggestion
app.buttons["goBack"].tap()
navigator.nowAt(HomePanelsScreen)
suggestionsOnOff()
// Suggestions should not be shown
waitforNoExistence(app.tables["SiteTable"].buttons[SuggestedSite])
navigator.nowAt(BrowserTab)
navigator.goto(URLBarOpen)
typeOnSearchBar(text: "foobar")
waitforNoExistence(app.tables["SiteTable"].buttons[SuggestedSite])
// Verify that previous choice is remembered
app.buttons["goBack"].tap()
navigator.nowAt(HomePanelsScreen)
navigator.goto(URLBarOpen)
typeOnSearchBar(text: "foobar")
waitforNoExistence(app.tables["SiteTable"].buttons[SuggestedSite])
app.buttons["goBack"].tap()
navigator.nowAt(HomePanelsScreen)
// Reset suggestion button, set it to on
suggestionsOnOff()
navigator.nowAt(HomePanelsScreen)
navigator.goto(URLBarOpen)
// Suggestions prompt should appear
typeOnSearchBar(text: "foobar")
waitforExistence(app.tables["SiteTable"].buttons[SuggestedSite])
}
// Promt does not appear once Search has been enabled by default, see bug: 1411184
func testDismissPromptPresence() {
navigator.goto(URLBarOpen)
typeOnSearchBar(text: "foobar")
waitforExistence(app.staticTexts[LabelPrompt])
app.buttons["No"].tap()
waitforNoExistence(app.tables["SiteTable"].buttons[SuggestedSite])
app.buttons["Go"].tap()
navigator.nowAt(BrowserTab)
// Verify that it is possible to enable suggestions after selecting No
suggestionsOnOff()
navigator.nowAt(BrowserTab)
navigator.goto(URLBarOpen)
typeOnSearchBar(text: "foobar")
waitforExistence(app.tables["SiteTable"].buttons[SuggestedSite])
}
func testDoNotShowSuggestionsWhenEnteringURL() {
// According to bug 1192155 if a string contains /, do not show suggestions, if there a space an a string,
// the suggestions are shown again
navigator.goto(URLBarOpen)
typeOnSearchBar(text: "foobar")
waitforNoExistence(app.staticTexts[LabelPrompt])
// Suggestions should be shown
waitforExistence(app.tables["SiteTable"].buttons[SuggestedSite])
// Typing / should stop showing suggestions
app.textFields["address"].typeText("/")
waitforNoExistence(app.tables["SiteTable"].buttons[SuggestedSite])
// Typing space and char after / should show suggestions again
app.textFields["address"].typeText(" b")
waitforExistence(app.tables["SiteTable"].buttons["foobar burn cd"])
}
func testCopyPasteComplete() {
// Copy, Paste and Go to url
navigator.goto(URLBarOpen)
typeOnSearchBar(text: "www.mozilla.org")
app.textFields["address"].press(forDuration: 5)
app.menuItems["Select All"].tap()
app.menuItems["Copy"].tap()
app.buttons["goBack"].tap()
navigator.nowAt(HomePanelsScreen)
navigator.goto(URLBarOpen)
app.textFields["address"].tap()
waitforExistence(app.menuItems["Paste"])
app.menuItems["Paste"].tap()
// Verify that the Paste shows the search controller with prompt
waitforNoExistence(app.staticTexts[LabelPrompt])
app.typeText("\r")
// Check that the website is loaded
waitForValueContains(app.textFields["url"], value: "www.mozilla.org")
// Go back, write part of moz, check the autocompletion
if iPad() {
app.buttons["URLBarView.backButton"].tap()
} else {
app.buttons["TabToolbar.backButton"].tap()
}
navigator.nowAt(HomePanelsScreen)
navigator.goto(URLBarOpen)
typeOnSearchBar(text: "moz")
waitForValueContains(app.textFields["address"], value: "mozilla.org")
let value = app.textFields["address"].value
XCTAssertEqual(value as? String, "mozilla.org")
}
private func changeSearchEngine(searchEngine: String) {
navigator.goto(SearchSettings)
// Open the list of default search engines and select the desired
app.tables.cells.element(boundBy: 0).tap()
let tablesQuery2 = app.tables
tablesQuery2.staticTexts[searchEngine].tap()
navigator.openURL(urlString: "foo")
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: searchEngine.lowercased())
// Go here so that next time it is possible to access settings
navigator.goto(BrowserTabMenu)
}
func testSearchEngine() {
// Change to the each search engine and verify the search uses it
changeSearchEngine(searchEngine: "Bing")
changeSearchEngine(searchEngine: "DuckDuckGo")
changeSearchEngine(searchEngine: "Google")
changeSearchEngine(searchEngine: "Twitter")
changeSearchEngine(searchEngine: "Wikipedia")
changeSearchEngine(searchEngine: "Amazon.com")
changeSearchEngine(searchEngine: "Yahoo")
}
func testDefaultSearchEngine() {
navigator.goto(SearchSettings)
XCTAssert(app.tables.staticTexts["Google"].exists)
}
}

View file

@ -0,0 +1,39 @@
/* 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 SettingsTest: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
super.tearDown()
}
func testHelpOpensSUMOInTab() {
navigator.goto(SettingsScreen)
let settingsTableView = app.tables["AppSettingsTableViewController.tableView"]
while settingsTableView.staticTexts["Help"].exists == false {
settingsTableView.swipeUp()
}
let helpMenu = settingsTableView.cells["Help"]
XCTAssertTrue(helpMenu.isEnabled)
helpMenu.tap()
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: "support.mozilla.org")
waitforExistence(app.webViews.staticTexts["Firefox for iOS"])
XCTAssertTrue(app.webViews.staticTexts["Firefox for iOS"].exists)
let numTabs = app.buttons["Show Tabs"].value
XCTAssertEqual("2", numTabs as? String, "Sume should be open in a different tab")
}
}

View file

@ -0,0 +1,52 @@
/* 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
// NOTE: This test should be DISABLED on XCUITEST/UITEST scheme. This test should be run in conjunction with
// XCode Profiler to measure the memory/CPU load
class SiteLoadTest: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
super.tearDown()
}
func testLoadSite() {
let site = ["http://www.forbes.com", "http://www.amazon.com", "http://theguardian.com", "http://www.reddit.com", "http://cnn.com"]
let durationInHrs = 1
let futureDate = Date().addingTimeInterval(TimeInterval(60 * 60 * durationInHrs))
var counter = 0
while Date() < futureDate {
navigator.goto(URLBarOpen)
navigator.openURL(urlString: site[counter % 5])
sleep(5)
navigator.nowAt(BrowserTab)
navigator.goto(TabTray)
navigator.closeAllTabs()
navigator.goto(BrowserTab)
waitforNoExistence(app.staticTexts["1 tab(s) closed"])
// clear the cache
navigator.goto(ClearPrivateDataSettings)
app.tables.staticTexts["Clear Private Data"].tap()
waitforExistence(app.alerts.buttons["OK"])
app.alerts.buttons["OK"].tap()
navigator.goto(BrowserTab)
waitforExistence(app.textFields["url"])
counter += 1
}
}
}

View file

@ -0,0 +1,178 @@
/* 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 ThirdPartySearchTest: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
dismissFirstRunUI()
}
override func tearDown() {
super.tearDown()
}
fileprivate func dismissKeyboardAssistant(forApp app: XCUIApplication) {
if iPad() {
let searchTheDocsSearchField = app.webViews.searchFields["Search the docs"]
searchTheDocsSearchField.typeText("\r")
} else {
app.buttons["Done"].tap()
}
}
func testCustomSearchEngines() {
// Visit MDN to add a custom search engine
loadWebPage("https://developer.mozilla.org/en-US/search", waitForLoadToFinish: true)
if iPad() {
let searchTheDocsSearchField = app.webViews.searchFields["Search the docs"]
searchTheDocsSearchField.tap()
app.keyboards.buttons["Search"].tap()
searchTheDocsSearchField.tap()
} else {
app.webViews.searchFields.element(boundBy: 0).tap()
}
app.buttons["AddSearch"].tap()
app.alerts["Add Search Provider?"].buttons["OK"].tap()
XCTAssertFalse(app.buttons["AddSearch"].isEnabled)
dismissKeyboardAssistant(forApp: app)
// Perform a search using a custom search engine
tabTrayButton(forApp: app).tap()
app.buttons["TabTrayController.addTabButton"].tap()
app.textFields["url"].tap()
app.typeText("window")
app.scrollViews.otherElements.buttons["developer.mozilla.org search"].tap()
var url = app.textFields["url"].value as! String
if url.hasPrefix("https://") == false {
url = "https://\(url)"
}
XCTAssert(url.hasPrefix("https://developer.mozilla.org/en-US/search"), "The URL should indicate that the search was performed on MDN and not the default")
}
func testCustomSearchEngineAsDefault() {
// Visit MDN to add a custom search engine
loadWebPage("https://developer.mozilla.org/en-US/search", waitForLoadToFinish: true)
if iPad() {
let searchTheDocsSearchField = app.webViews.searchFields["Search the docs"]
searchTheDocsSearchField.tap()
app.keyboards.buttons["Search"].tap()
searchTheDocsSearchField.tap()
} else {
app.webViews.searchFields.element(boundBy: 0).tap()
}
app.buttons["AddSearch"].tap()
app.alerts["Add Search Provider?"].buttons["OK"].tap()
XCTAssertFalse(app.buttons["AddSearch"].isEnabled)
dismissKeyboardAssistant(forApp: app)
// Go to settings and set MDN as the default
navigator.goto(SearchSettings)
app.tables.cells.element(boundBy: 0).tap()
app.tables.staticTexts["developer.mozilla.org"].tap()
navigator.goto(BrowserTab)
// Perform a search to check
navigator.openNewURL(urlString:"window")
// Ensure that the default search is MDN
var url = app.textFields["url"].value as! String
if url.hasPrefix("https://") == false {
url = "https://\(url)"
}
XCTAssert(url.hasPrefix("https://developer.mozilla.org/en-US/search"), "The URL should indicate that the search was performed on MDN and not the default")
}
func testCustomSearchEngineDeletion() {
// Visit MDN to add a custom search engine
loadWebPage("https://developer.mozilla.org/en-US/search", waitForLoadToFinish: true)
if iPad() {
let searchTheDocsSearchField = app.webViews.searchFields["Search the docs"]
searchTheDocsSearchField.tap()
app.keyboards.buttons["Search"].tap()
searchTheDocsSearchField.tap()
} else {
app.webViews.searchFields.element(boundBy: 0).tap()
}
app.buttons["AddSearch"].tap()
app.alerts["Add Search Provider?"].buttons["OK"].tap()
XCTAssertFalse(app.buttons["AddSearch"].isEnabled)
dismissKeyboardAssistant(forApp: app)
let tabTrayButton = self.tabTrayButton(forApp: app)
tabTrayButton.tap()
app.buttons["TabTrayController.addTabButton"].tap()
app.textFields["url"].tap()
app.typeText("window")
// For timing issue, we need a wait statement
waitforExistence(app.scrollViews.otherElements.buttons["developer.mozilla.org search"])
XCTAssert(app.scrollViews.otherElements.buttons["developer.mozilla.org search"].exists)
app.typeText("\r")
// Go to settings and set MDN as the default
navigator.goto(SearchSettings)
app.navigationBars["Search"].buttons["Edit"].tap()
app.tables.buttons["Delete developer.mozilla.org"].tap()
app.tables.buttons["Delete"].tap()
navigator.goto(BrowserTab)
// Perform a search to check
tabTrayButton.tap(force: true)
app.buttons["TabTrayController.addTabButton"].tap()
app.textFields["url"].tap()
app.typeText("window")
waitforNoExistence(app.scrollViews.otherElements.buttons["developer.mozilla.org search"])
XCTAssertFalse(app.scrollViews.otherElements.buttons["developer.mozilla.org search"].exists)
}
func testCustomEngineFromCorrectTemplate() {
navigator.goto(SearchSettings)
app.tables.cells["customEngineViewButton"].tap()
app.textViews["customEngineTitle"].tap()
app.typeText("Feeling Lucky")
app.textViews["customEngineUrl"].tap()
app.typeText("http://www.google.com/search?q=%s&btnI")
app.navigationBars.buttons["customEngineSaveButton"].tap()
// Perform a search using a custom search engine
navigator.goto(HomePanelsScreen)
app.textFields["url"].tap()
app.typeText("strange charm")
app.scrollViews.otherElements.buttons["Feeling Lucky search"].tap()
// Ensure that correct search is done
let url = app.textFields["url"].value as! String
XCTAssert(url.hasSuffix("&btnI"), "The URL should indicate that the search was performed using IFL")
}
func testCustomEngineFromIncorrectTemplate() {
navigator.goto(SearchSettings)
app.tables.cells["customEngineViewButton"].tap()
app.textViews["customEngineTitle"].tap()
app.typeText("Feeling Lucky")
app.textViews["customEngineUrl"].tap()
app.typeText("http://www.google.com/search?q=&btnI") //Occurunces of %s != 1
app.navigationBars.buttons["customEngineSaveButton"].tap()
waitforExistence(app.alerts.element(boundBy: 0))
XCTAssert(app.alerts.element(boundBy: 0).label == "Failed")
}
}

View file

@ -0,0 +1,94 @@
/* 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
let website1: [String: String] = ["url": "www.mozilla.org", "label": "Internet for people, not profit — Mozilla", "value": "mozilla.org"]
let website2 = "yahoo.com"
class ToolbarTests: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
XCUIDevice.shared().orientation = UIDeviceOrientation.landscapeLeft
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
XCUIDevice.shared().orientation = UIDeviceOrientation.portrait
super.tearDown()
}
/**
* Tests landscape page navigation enablement with the URL bar with tab switching.
*/
func testLandscapeNavigationWithTabSwitch() {
let urlPlaceholder = "Search or enter address"
XCTAssert(app.textFields["url"].exists)
let defaultValuePlaceholder = app.textFields["url"].placeholderValue!
// Check the url placeholder text and that the back and forward buttons are disabled
XCTAssertTrue(urlPlaceholder == defaultValuePlaceholder, "The placeholder does not show the correct value")
XCTAssertFalse(app.buttons["URLBarView.backButton"].isEnabled)
XCTAssertFalse(app.buttons["Forward"].isEnabled)
XCTAssertFalse(app.buttons["Reload"].isEnabled)
// Navigate to two pages and press back once so that all buttons are enabled in landscape mode.
navigator.openURL(urlString: website1["url"]!)
waitForValueContains(app.textFields["url"], value: website1["value"]!)
XCTAssertTrue(app.buttons["URLBarView.backButton"].isEnabled)
XCTAssertFalse(app.buttons["Forward"].isEnabled)
XCTAssertTrue(app.buttons["Reload"].isEnabled)
navigator.openURL(urlString: website2)
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: website2)
XCTAssertTrue(app.buttons["URLBarView.backButton"].isEnabled)
XCTAssertFalse(app.buttons["Forward"].isEnabled)
app.buttons["URLBarView.backButton"].tap()
waitForValueContains(app.textFields["url"], value: website1["value"]!)
waitUntilPageLoad()
XCTAssertTrue(app.buttons["URLBarView.backButton"].isEnabled)
XCTAssertTrue(app.buttons["Forward"].isEnabled)
// Open new tab and then go back to previous tab to test navigation buttons.
navigator.goto(TabTray)
waitforExistence(app.collectionViews.cells[website1["label"]!])
app.collectionViews.cells[website1["label"]!].tap()
waitForValueContains(app.textFields["url"], value: website1["value"]!)
// Test to see if all the buttons are enabled then close tab.
waitUntilPageLoad()
XCTAssertTrue(app.buttons["URLBarView.backButton"].isEnabled)
XCTAssertTrue(app.buttons["Forward"].isEnabled)
navigator.nowAt(BrowserTab)
navigator.goto(TabTray)
waitforExistence(app.collectionViews.cells[website1["label"]!])
app.collectionViews.cells[website1["label"]!].swipeRight()
// Go Back to other tab to see if all buttons are disabled.
navigator.nowAt(BrowserTab)
XCTAssertFalse(app.buttons["URLBarView.backButton"].isEnabled)
XCTAssertFalse(app.buttons["Forward"].isEnabled)
}
func testClearURLTextUsingBackspace() {
navigator.openURL(urlString: website1["url"]!)
waitForValueContains(app.textFields["url"], value: website1["value"]!)
// Simulate pressing on backspace key should remove the text
app.textFields["url"].tap()
app.textFields["address"].typeText("\u{8}")
let value = app.textFields["address"].value
XCTAssertEqual(value as? String, "", "The url has not been removed correctly")
}
}

View file

@ -0,0 +1,178 @@
/* 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
let url = "www.mozilla.org"
let urlLabel = "Internet for people, not profit — Mozilla"
let urlValue = "mozilla.org"
let urlYah = "www.yahoo.com"
let urlLabelYah = "Yahoo"
let urlValueYah = "yahoo"
let urlExample = "example.com"
class TopTabsTest: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
super.tearDown()
}
func testAddTabFromSettings() {
navigator.createNewTab()
navigator.openURL(urlString: url)
waitForValueContains(app.textFields["url"], value: urlValue)
waitforExistence(app.buttons["Show Tabs"])
let numTab = app.buttons["Show Tabs"].value as? String
XCTAssertEqual("2", numTab)
}
func testAddTabFromTabTray() {
navigator.goto(TabTray)
navigator.openURL(urlString: url)
waitUntilPageLoad()
waitForValueContains(app.textFields["url"], value: urlValue)
// The tabs counter shows the correct number
let tabsOpen = app.buttons["Show Tabs"].value
XCTAssertEqual("2", tabsOpen as? String)
// The tab tray shows the correct tabs
navigator.goto(TabTray)
waitforExistence(app.collectionViews.cells[urlLabel])
}
private func checkNumberOfTabsExpectedToBeOpen(expectedNumberOfTabsOpen: Int) {
let numTabsOpen = app.collectionViews.cells.count
XCTAssertEqual(numTabsOpen, UInt(expectedNumberOfTabsOpen), "The number of tabs open is not correct")
}
func testAddTabFromContext() {
navigator.openURL(urlString: urlExample)
// Initially there is only one tab open
let tabsOpenInitially = app.buttons["Show Tabs"].value
XCTAssertEqual("1", tabsOpenInitially as? String)
// Open link in a different tab and switch to it
waitforExistence(app.webViews.links.staticTexts["More information..."])
app.webViews.links.staticTexts["More information..."].press(forDuration: 5)
app.buttons["Open in New Tab"].tap()
waitUntilPageLoad()
// Open tab tray to check that both tabs are there
navigator.goto(TabTray)
waitforExistence(app.collectionViews.cells["Example Domain"])
waitforExistence(app.collectionViews.cells["IANA — IANA-managed Reserved Domains"])
checkNumberOfTabsExpectedToBeOpen(expectedNumberOfTabsOpen: 2)
}
// This test only runs for iPhone see bug 1409750
func testAddTabByLongPressTabsButton() {
navigator.goto(BrowserTab)
app.buttons["TabToolbar.tabsButton"].press(forDuration: 1)
waitforExistence(app.buttons["New Tab"])
app.buttons["New Tab"].tap()
navigator.goto(TabTray)
checkNumberOfTabsExpectedToBeOpen(expectedNumberOfTabsOpen: 2)
}
// This test only runs for iPhone see bug 1409750
func testAddPrivateTabByLongPressTabsButton() {
navigator.goto(BrowserTab)
app.buttons["TabToolbar.tabsButton"].press(forDuration: 1)
waitforExistence(app.buttons["New Private Tab"])
app.buttons["New Private Tab"].tap()
navigator.goto(TabTray)
waitforExistence(app.buttons["TabTrayController.maskButton"])
XCTAssertTrue(app.buttons["TabTrayController.maskButton"].isEnabled)
checkNumberOfTabsExpectedToBeOpen(expectedNumberOfTabsOpen: 1)
}
func testSwitchBetweenTabs() {
// Open two urls from tab tray and switch between them
navigator.openURL(urlString: url)
navigator.goto(TabTray)
navigator.openURL(urlString: urlYah)
navigator.goto(TabTray)
waitforExistence(app.collectionViews.cells[urlLabel])
app.collectionViews.cells[urlLabel].tap()
waitForValueContains(app.textFields["url"], value: urlValue)
navigator.nowAt(BrowserTab)
navigator.goto(TabTray)
waitforExistence(app.collectionViews.cells[urlLabelYah])
app.collectionViews.cells[urlLabelYah].tap()
waitForValueContains(app.textFields["url"], value: urlValueYah)
}
func testCloseOneTab() {
navigator.openURL(urlString: url)
waitUntilPageLoad()
navigator.goto(TabTray)
waitforExistence(app.collectionViews.cells[urlLabel])
// 'x' button to close the tab is not visible, so closing by swiping the tab
app.collectionViews.cells[urlLabel].swipeRight()
// After removing only one tab it automatically goes to HomepanelView
waitforExistence(app.collectionViews.cells["TopSitesCell"])
XCTAssert(app.buttons["HomePanels.TopSites"].exists)
}
func testCloseAllTabsUndo() {
// A different tab than home is open to do the proper checks
navigator.openURL(urlString: url)
waitUntilPageLoad()
navigator.createSeveralTabsFromTabTray (numberTabs: 3)
navigator.goto(TabTray)
waitforExistence(app.collectionViews.cells[urlLabel])
checkNumberOfTabsExpectedToBeOpen(expectedNumberOfTabsOpen: 4)
// Close all tabs, undo it and check that the number of tabs is correct
navigator.closeAllTabs()
app.buttons["Undo"].tap()
navigator.nowAt(BrowserTab)
navigator.goto(TabTray)
waitforExistence(app.collectionViews.cells[urlLabel])
checkNumberOfTabsExpectedToBeOpen(expectedNumberOfTabsOpen: 4)
}
func testCloseAllTabs() {
// A different tab than home is open to do the proper checks
navigator.openURL(urlString: url)
waitUntilPageLoad()
// Add several tabs from tab tray menu and check that the number is correct before closing all
navigator.createSeveralTabsFromTabTray (numberTabs: 3)
navigator.goto(TabTray)
waitforExistence(app.collectionViews.cells[urlLabel])
checkNumberOfTabsExpectedToBeOpen(expectedNumberOfTabsOpen: 4)
// Close all tabs and check that the number of tabs is correct
navigator.closeAllTabs()
navigator.goto(TabTray)
waitforNoExistence(app.collectionViews.cells[urlLabel])
checkNumberOfTabsExpectedToBeOpen(expectedNumberOfTabsOpen: 1)
}
}

View file

@ -0,0 +1,65 @@
/* 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 TrackingProtectionTests: BaseTestCase {
var navigator: Navigator!
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
navigator = createScreenGraph(app).navigator(self)
}
override func tearDown() {
navigator = nil
app = nil
super.tearDown()
}
// This test is to change the tracking protection to block known blockers
func testTrackingProtection() {
navigator.goto(SettingsScreen)
let appSettingsTableView = app.tables["AppSettingsTableViewController.tableView"]
//Scroll the table view until Tracking Proection cell is visible
while !app.staticTexts["Tracking Protection"].exists {
appSettingsTableView.swipeUp()
}
appSettingsTableView.staticTexts["Tracking Protection"].tap()
//Check "Private Browsing Mode Only" is selected and other items are not selected
XCTAssertFalse(app.tables.cells["Always On"].isSelected)
XCTAssertTrue(app.tables.cells["Private Browsing Mode Only"].isSelected)
XCTAssertFalse(app.tables.cells["Never"].isSelected)
//Select "Always On"
app.tables.cells["Always On"].tap()
XCTAssertTrue(app.tables.cells["Always On"].isSelected)
app.navigationBars["Tracking Protection"].buttons["Settings"].tap()
waitforExistence(app.navigationBars["Settings"].buttons["Done"])
app.navigationBars["Settings"]/*@START_MENU_TOKEN@*/.buttons["Done"]/*[[".buttons[\"Done\"]",".buttons[\"AppSettingsTableViewController.navigationItem.leftBarButtonItem\"]"],[[[-1,1],[-1,0]]],[1]]@END_MENU_TOKEN@*/.tap()
app/*@START_MENU_TOKEN@*/.buttons["TabToolbar.menuButton"]/*[[".buttons[\"Menu\"]",".buttons[\"TabToolbar.menuButton\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.tap()
let settingsmenuitemCell = app.tables.cells["Settings"]
settingsmenuitemCell.tap()
let appSettingsTableView1 = app.tables["AppSettingsTableViewController.tableView"]
//Scroll the table view until Tracking Proection cell is visible
while !app.staticTexts["Tracking Protection"].exists {
appSettingsTableView1.swipeUp()
}
appSettingsTableView1.staticTexts["Tracking Protection"].tap()
waitforExistence(app.tables.cells["Always On"])
//Check "Always On" is selected and other items are not selected
XCTAssertTrue(app.tables.cells["Always On"].isSelected)
XCTAssertFalse(app.tables.cells["Private Browsing Mode Only"].isSelected)
XCTAssertFalse(app.tables.cells["Never"].isSelected)
}
}

View file

@ -0,0 +1,14 @@
/* 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/. */
#ifndef XCUITests_Bridging_Header_h
#define XCUITests_Bridging_Header_h
#import "XCTest/XCUIApplication.h"
#import "XCTest/XCUIElement.h"
@interface XCUIApplication (Private)
- (id)initPrivateWithPath:(NSString *)path bundleID:(NSString *)bundleID;
@end
#endif