mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-20 15:27:32 +09:00
Dactyloidae iOS initial commit
This commit is contained in:
parent
daa6179d22
commit
7154a0497e
2123 changed files with 197052 additions and 0 deletions
378
mobile/ios/XCUITests/ActivityStreamTest.swift
Normal file
378
mobile/ios/XCUITests/ActivityStreamTest.swift
Normal 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
|
||||
}
|
||||
}
|
||||
347
mobile/ios/XCUITests/AuthenticationTest.swift
Normal file
347
mobile/ios/XCUITests/AuthenticationTest.swift
Normal 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 didn’t 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 didn’t 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")
|
||||
}
|
||||
}
|
||||
112
mobile/ios/XCUITests/BaseTestCase.swift
Normal file
112
mobile/ios/XCUITests/BaseTestCase.swift
Normal 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
112
mobile/ios/XCUITests/BookmarkingTests.swift
Normal file
112
mobile/ios/XCUITests/BookmarkingTests.swift
Normal 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()
|
||||
}
|
||||
}
|
||||
68
mobile/ios/XCUITests/ClipBoardTests.swift
Normal file
68
mobile/ios/XCUITests/ClipBoardTests.swift
Normal 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")
|
||||
}
|
||||
}
|
||||
48
mobile/ios/XCUITests/CopiedLinksTests.swift
Normal file
48
mobile/ios/XCUITests/CopiedLinksTests.swift
Normal 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")
|
||||
}
|
||||
}
|
||||
174
mobile/ios/XCUITests/DomainAutocompleteTest.swift
Normal file
174
mobile/ios/XCUITests/DomainAutocompleteTest.swift
Normal 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")
|
||||
}
|
||||
}
|
||||
123
mobile/ios/XCUITests/FindInPageTest.swift
Normal file
123
mobile/ios/XCUITests/FindInPageTest.swift
Normal 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")
|
||||
}
|
||||
}
|
||||
476
mobile/ios/XCUITests/FxScreenGraph.swift
Normal file
476
mobile/ios/XCUITests/FxScreenGraph.swift
Normal 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"
|
||||
}
|
||||
44
mobile/ios/XCUITests/HistoryTests.swift
Normal file
44
mobile/ios/XCUITests/HistoryTests.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
75
mobile/ios/XCUITests/HomePageSettingsTest.swift
Normal file
75
mobile/ios/XCUITests/HomePageSettingsTest.swift
Normal 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")
|
||||
}
|
||||
*/
|
||||
}
|
||||
107
mobile/ios/XCUITests/HomePageSettingsUITest.swift
Normal file
107
mobile/ios/XCUITests/HomePageSettingsUITest.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
31
mobile/ios/XCUITests/HomePageUITest.swift
Normal file
31
mobile/ios/XCUITests/HomePageUITest.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
24
mobile/ios/XCUITests/Info.plist
Normal file
24
mobile/ios/XCUITests/Info.plist
Normal 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>
|
||||
299
mobile/ios/XCUITests/NavigationTest.swift
Normal file
299
mobile/ios/XCUITests/NavigationTest.swift
Normal 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")
|
||||
}
|
||||
*/
|
||||
}
|
||||
65
mobile/ios/XCUITests/NightModeTests.swift
Normal file
65
mobile/ios/XCUITests/NightModeTests.swift
Normal 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()
|
||||
}
|
||||
}
|
||||
65
mobile/ios/XCUITests/NoImageTests.swift
Normal file
65
mobile/ios/XCUITests/NoImageTests.swift
Normal 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()
|
||||
}
|
||||
}
|
||||
87
mobile/ios/XCUITests/PhotonActionSheetTest.swift
Normal file
87
mobile/ios/XCUITests/PhotonActionSheetTest.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
166
mobile/ios/XCUITests/PrivateBrowsingTest.swift
Normal file
166
mobile/ios/XCUITests/PrivateBrowsingTest.swift
Normal 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")
|
||||
}
|
||||
}
|
||||
143
mobile/ios/XCUITests/ReaderViewUITest.swift
Normal file
143
mobile/ios/XCUITests/ReaderViewUITest.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
388
mobile/ios/XCUITests/ScreenGraph.swift
Normal file
388
mobile/ios/XCUITests/ScreenGraph.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
123
mobile/ios/XCUITests/SearchSettingsUITest.swift
Normal file
123
mobile/ios/XCUITests/SearchSettingsUITest.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
178
mobile/ios/XCUITests/SearchTest.swift
Normal file
178
mobile/ios/XCUITests/SearchTest.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
39
mobile/ios/XCUITests/SettingsTest.swift
Normal file
39
mobile/ios/XCUITests/SettingsTest.swift
Normal 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")
|
||||
}
|
||||
}
|
||||
52
mobile/ios/XCUITests/SiteLoadTest.swift
Normal file
52
mobile/ios/XCUITests/SiteLoadTest.swift
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
178
mobile/ios/XCUITests/ThirdPartySearchTest.swift
Normal file
178
mobile/ios/XCUITests/ThirdPartySearchTest.swift
Normal 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")
|
||||
}
|
||||
}
|
||||
94
mobile/ios/XCUITests/ToolbarTest.swift
Normal file
94
mobile/ios/XCUITests/ToolbarTest.swift
Normal 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")
|
||||
}
|
||||
}
|
||||
178
mobile/ios/XCUITests/TopTabsTest.swift
Normal file
178
mobile/ios/XCUITests/TopTabsTest.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
65
mobile/ios/XCUITests/TrackingProtectionTests.swift
Normal file
65
mobile/ios/XCUITests/TrackingProtectionTests.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
14
mobile/ios/XCUITests/XCUITests-Bridging-Header.h
Normal file
14
mobile/ios/XCUITests/XCUITests-Bridging-Header.h
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue