Skip to content
This repository was archived by the owner on Feb 24, 2025. It is now read-only.

Commit 2e1c81b

Browse files
authored
Adds a series of UI tests for Find in Page
Task/Issue URL: https://app.asana.com/0/1199230911884351/1205717021705364/f Tech Design URL: CC: **Description**: Adds a series of UI tests for Find in Page **Steps to test this PR**: 1. Open the scheme UI Tests 2. Navigate to the test pane 3. Run UI Tests
1 parent 9da0cee commit 2e1c81b

11 files changed

+637
-19
lines changed

DuckDuckGo.xcodeproj/project.pbxproj

+20
Original file line numberDiff line numberDiff line change
@@ -3223,6 +3223,7 @@
32233223
EAC80DE0271F6C0100BBF02D /* fb-sdk.js in Resources */ = {isa = PBXBuildFile; fileRef = EAC80DDF271F6C0100BBF02D /* fb-sdk.js */; };
32243224
EAE42800275D47FA00DAC26B /* ClickToLoadModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAE427FF275D47FA00DAC26B /* ClickToLoadModel.swift */; };
32253225
EAFAD6CA2728BD1200F9DF00 /* clickToLoad.js in Resources */ = {isa = PBXBuildFile; fileRef = EAFAD6C92728BD1200F9DF00 /* clickToLoad.js */; };
3226+
EE0429E02BA31D2F009EB20F /* FindInPageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE0429DF2BA31D2F009EB20F /* FindInPageTests.swift */; };
32263227
EE0629722B90EE8C00D868B4 /* AccountManagerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE0629712B90EE8C00D868B4 /* AccountManagerExtension.swift */; };
32273228
EE0629732B90EE8C00D868B4 /* AccountManagerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE0629712B90EE8C00D868B4 /* AccountManagerExtension.swift */; };
32283229
EE0629742B90EE8C00D868B4 /* AccountManagerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE0629712B90EE8C00D868B4 /* AccountManagerExtension.swift */; };
@@ -3245,6 +3246,9 @@
32453246
EEA3EEB12B24EBD000E8333A /* NetworkProtectionVPNCountryLabelsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEA3EEB02B24EBD000E8333A /* NetworkProtectionVPNCountryLabelsModel.swift */; };
32463247
EEA3EEB32B24EC0600E8333A /* VPNLocationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEA3EEB22B24EC0600E8333A /* VPNLocationViewModel.swift */; };
32473248
EEAD7A7C2A1D3E20002A24E7 /* AppLauncher.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEAD7A6E2A1D3E1F002A24E7 /* AppLauncher.swift */; };
3249+
EEBCE6822BA444FA00B9DF00 /* XCUIElementExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEBCE6812BA444FA00B9DF00 /* XCUIElementExtension.swift */; };
3250+
EEBCE6832BA463DD00B9DF00 /* NSImageExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B139AFC26B60BD800894F82 /* NSImageExtensions.swift */; };
3251+
EEBCE6842BA4643200B9DF00 /* NSSizeExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC5E4E325D6BA9C007F5990 /* NSSizeExtension.swift */; };
32483252
EEC111E4294D06020086524F /* JSAlert.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EEC111E3294D06020086524F /* JSAlert.storyboard */; };
32493253
EEC111E6294D06290086524F /* JSAlertViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEC111E5294D06290086524F /* JSAlertViewModel.swift */; };
32503254
EEC4A65E2B277E8D00F7C0AA /* NetworkProtectionVPNCountryLabelsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEA3EEB02B24EBD000E8333A /* NetworkProtectionVPNCountryLabelsModel.swift */; };
@@ -4655,6 +4659,7 @@
46554659
EAC80DDF271F6C0100BBF02D /* fb-sdk.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "fb-sdk.js"; sourceTree = "<group>"; };
46564660
EAE427FF275D47FA00DAC26B /* ClickToLoadModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClickToLoadModel.swift; sourceTree = "<group>"; };
46574661
EAFAD6C92728BD1200F9DF00 /* clickToLoad.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = clickToLoad.js; sourceTree = "<group>"; };
4662+
EE0429DF2BA31D2F009EB20F /* FindInPageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FindInPageTests.swift; sourceTree = "<group>"; };
46584663
EE0629712B90EE8C00D868B4 /* AccountManagerExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountManagerExtension.swift; sourceTree = "<group>"; };
46594664
EE339227291BDEFD009F62C1 /* JSAlertController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSAlertController.swift; sourceTree = "<group>"; };
46604665
EE34245D2BA0853900173B1B /* VPNUninstaller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNUninstaller.swift; sourceTree = "<group>"; };
@@ -4663,6 +4668,7 @@
46634668
EEA3EEB02B24EBD000E8333A /* NetworkProtectionVPNCountryLabelsModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkProtectionVPNCountryLabelsModel.swift; sourceTree = "<group>"; };
46644669
EEA3EEB22B24EC0600E8333A /* VPNLocationViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VPNLocationViewModel.swift; sourceTree = "<group>"; };
46654670
EEAD7A6E2A1D3E1F002A24E7 /* AppLauncher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppLauncher.swift; sourceTree = "<group>"; };
4671+
EEBCE6812BA444FA00B9DF00 /* XCUIElementExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XCUIElementExtension.swift; sourceTree = "<group>"; };
46664672
EEC111E3294D06020086524F /* JSAlert.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = JSAlert.storyboard; sourceTree = "<group>"; };
46674673
EEC111E5294D06290086524F /* JSAlertViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSAlertViewModel.swift; sourceTree = "<group>"; };
46684674
EEC4A6682B2C87D300F7C0AA /* VPNLocationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNLocationView.swift; sourceTree = "<group>"; };
@@ -6417,7 +6423,9 @@
64176423
7B4CE8DB26F02108009134B1 /* UITests */ = {
64186424
isa = PBXGroup;
64196425
children = (
6426+
EEBCE6802BA444FA00B9DF00 /* Common */,
64206427
7B4CE8E626F02134009134B1 /* TabBarTests.swift */,
6428+
EE0429DF2BA31D2F009EB20F /* FindInPageTests.swift */,
64216429
);
64226430
path = UITests;
64236431
sourceTree = "<group>";
@@ -8642,6 +8650,14 @@
86428650
path = JSAlert;
86438651
sourceTree = "<group>";
86448652
};
8653+
EEBCE6802BA444FA00B9DF00 /* Common */ = {
8654+
isa = PBXGroup;
8655+
children = (
8656+
EEBCE6812BA444FA00B9DF00 /* XCUIElementExtension.swift */,
8657+
);
8658+
path = Common;
8659+
sourceTree = "<group>";
8660+
};
86458661
EEC589D62A4F1B1F00BCD60C /* AppAndExtensionAndAgentTargets */ = {
86468662
isa = PBXGroup;
86478663
children = (
@@ -12017,7 +12033,11 @@
1201712033
isa = PBXSourcesBuildPhase;
1201812034
buildActionMask = 2147483647;
1201912035
files = (
12036+
EEBCE6842BA4643200B9DF00 /* NSSizeExtension.swift in Sources */,
12037+
EE0429E02BA31D2F009EB20F /* FindInPageTests.swift in Sources */,
1202012038
7B4CE8E726F02135009134B1 /* TabBarTests.swift in Sources */,
12039+
EEBCE6832BA463DD00B9DF00 /* NSImageExtensions.swift in Sources */,
12040+
EEBCE6822BA444FA00B9DF00 /* XCUIElementExtension.swift in Sources */,
1202112041
);
1202212042
runOnlyForDeploymentPostprocessing = 0;
1202312043
};

DuckDuckGo/Common/Extensions/NSMenuItemExtension.swift

+6
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ extension NSMenuItem {
104104
return self
105105
}
106106

107+
@discardableResult
108+
func withAccessibilityIdentifier(_ accessibilityIdentifier: String) -> NSMenuItem {
109+
self.setAccessibilityIdentifier(accessibilityIdentifier)
110+
return self
111+
}
112+
107113
@discardableResult
108114
func withImage(_ image: NSImage?) -> NSMenuItem {
109115
self.image = image

DuckDuckGo/FindInPage/FindInPageViewController.swift

+8
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ final class FindInPageViewController: NSViewController {
5959
closeButton.toolTip = UserText.findInPageCloseTooltip
6060
nextButton.toolTip = UserText.findInPageNextTooltip
6161
previousButton.toolTip = UserText.findInPagePreviousTooltip
62+
63+
nextButton.setAccessibilityIdentifier("FindInPageController.nextButton")
64+
closeButton.setAccessibilityIdentifier("FindInPageController.closeButton")
65+
previousButton.setAccessibilityIdentifier("FindInPageController.previousButton")
66+
textField.setAccessibilityIdentifier("FindInPageController.textField")
67+
textField.setAccessibilityRole(.textField)
68+
statusField.setAccessibilityIdentifier("FindInPageController.statusField")
69+
statusField.setAccessibilityRole(.textField)
6270
}
6371

6472
@IBAction func findInPageNext(_ sender: Any?) {

DuckDuckGo/Menus/MainMenu.swift

+5-5
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import SubscriptionUI
4343

4444
// MARK: DuckDuckGo
4545
let servicesMenu = NSMenu(title: UserText.mainMenuAppServices)
46-
let preferencesMenuItem = NSMenuItem(title: UserText.mainMenuAppPreferences, action: #selector(AppDelegate.openPreferences), keyEquivalent: ",")
46+
let preferencesMenuItem = NSMenuItem(title: UserText.mainMenuAppPreferences, action: #selector(AppDelegate.openPreferences), keyEquivalent: ",").withAccessibilityIdentifier("MainMenu.preferencesMenuItem")
4747

4848
// MARK: File
4949
let newWindowMenuItem = NSMenuItem(title: UserText.newWindowMenuItem, action: #selector(AppDelegate.newWindow), keyEquivalent: "n")
@@ -207,12 +207,12 @@ import SubscriptionUI
207207
NSMenuItem.separator()
208208

209209
NSMenuItem(title: UserText.mainMenuEditFind) {
210-
NSMenuItem(title: UserText.findInPageMenuItem, action: #selector(MainViewController.findInPage), keyEquivalent: "f")
211-
NSMenuItem(title: UserText.mainMenuEditFindFindNext, action: #selector(MainViewController.findInPageNext), keyEquivalent: "g")
212-
NSMenuItem(title: UserText.mainMenuEditFindFindPrevious, action: #selector(MainViewController.findInPagePrevious), keyEquivalent: "G")
210+
NSMenuItem(title: UserText.findInPageMenuItem, action: #selector(MainViewController.findInPage), keyEquivalent: "f").withAccessibilityIdentifier("MainMenu.findInPage")
211+
NSMenuItem(title: UserText.mainMenuEditFindFindNext, action: #selector(MainViewController.findInPageNext), keyEquivalent: "g").withAccessibilityIdentifier("MainMenu.findNext")
212+
NSMenuItem(title: UserText.mainMenuEditFindFindPrevious, action: #selector(MainViewController.findInPagePrevious), keyEquivalent: "G").withAccessibilityIdentifier("MainMenu.findPrevious")
213213
NSMenuItem.separator()
214214

215-
NSMenuItem(title: UserText.mainMenuEditFindHideFind, action: #selector(MainViewController.findInPageDone), keyEquivalent: "F")
215+
NSMenuItem(title: UserText.mainMenuEditFindHideFind, action: #selector(MainViewController.findInPageDone), keyEquivalent: "F").withAccessibilityIdentifier("MainMenu.findInPageDone")
216216
}
217217

218218
NSMenuItem(title: UserText.mainMenuEditSpellingandGrammar) {

DuckDuckGo/NavigationBar/View/AddressBarViewController.swift

+1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ final class AddressBarViewController: NSViewController {
9999
view.layer?.masksToBounds = false
100100

101101
addressBarTextField.placeholderString = UserText.addressBarPlaceholder
102+
addressBarTextField.setAccessibilityIdentifier("AddressBarViewController.addressBarTextField")
102103

103104
updateView()
104105
// only activate active text field leading constraint on its appearance to avoid constraint conflicts

DuckDuckGo/NavigationBar/View/MoreOptionsMenu.swift

+1
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ final class MoreOptionsMenu: NSMenu {
459459
addItem(withTitle: UserText.findInPageMenuItem, action: #selector(findInPage(_:)), keyEquivalent: "f")
460460
.targetting(self)
461461
.withImage(.findSearch)
462+
.withAccessibilityIdentifier("MoreOptionsMenu.findInPage")
462463

463464
addItem(withTitle: UserText.shareMenuItem, action: nil, keyEquivalent: "")
464465
.targetting(self)

DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ final class NavigationBarViewController: NSViewController {
185185
passwordManagementButton.sendAction(on: .leftMouseDown)
186186

187187
optionsButton.toolTip = UserText.applicationMenuTooltip
188-
optionsButton.setAccessibilityIdentifier("Options Button")
188+
optionsButton.setAccessibilityIdentifier("NavigationBarViewController.optionsButton")
189189

190190
networkProtectionButton.toolTip = UserText.networkProtectionButtonTooltip
191191

SyncE2EUITests/CriticalPathsTests.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ final class CriticalPathsTests: XCTestCase {
296296

297297
private func addLogin() {
298298
let bookmarksWindow = app.windows["Bookmarks"]
299-
bookmarksWindow.buttons["Options Button"].click()
299+
bookmarksWindow.buttons["NavigationBarViewController.optionsButton"].click()
300300
bookmarksWindow.menuItems["Autofill"].click()
301301
bookmarksWindow.popovers.buttons["add item"].click()
302302
bookmarksWindow.popovers.menuItems["createNewLogin"].click()
@@ -361,7 +361,7 @@ final class CriticalPathsTests: XCTestCase {
361361

362362
private func checkLogins() {
363363
let bookmarksWindow = app.windows["Bookmarks"]
364-
bookmarksWindow.buttons["Options Button"].click()
364+
bookmarksWindow.buttons["NavigationBarViewController.optionsButton"].click()
365365
bookmarksWindow.menuItems["Autofill"].click()
366366
let elementsQuery = bookmarksWindow.popovers.scrollViews.otherElements
367367
elementsQuery.buttons["Da, Dax Login, daxthetest"].click()
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// XCUIElementExtension.swift
3+
//
4+
// Copyright © 2024 DuckDuckGo. All rights reserved.
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
19+
import XCTest
20+
21+
extension XCUIElement {
22+
23+
// https://stackoverflow.com/a/63089781/119717
24+
// Licensed under https://creativecommons.org/licenses/by-sa/4.0/
25+
// Credit: Adil Hussain
26+
27+
/**
28+
* Waits the specified amount of time for the element’s `exists` property to become `false`.
29+
*
30+
* - Parameter timeout: The amount of time to wait.
31+
* - Returns: `false` if the timeout expires without the element coming out of existence.
32+
*/
33+
func waitForNonExistence(timeout: TimeInterval) -> Bool {
34+
let timeStart = Date().timeIntervalSince1970
35+
36+
while Date().timeIntervalSince1970 <= (timeStart + timeout) {
37+
if !exists { return true }
38+
}
39+
40+
return false
41+
}
42+
}

0 commit comments

Comments
 (0)