aboutsummaryrefslogtreecommitdiff
path: root/MapUITests/SearchUITests.swift
diff options
context:
space:
mode:
authorRuben Beltran del Rio <git@r.bdr.sh>2025-07-04 17:06:28 +0200
committerRuben Beltran del Rio <git@r.bdr.sh>2025-07-04 17:06:28 +0200
commitc843d34f56c207abcf4b93e424125eea2dc601e0 (patch)
tree415dc2d9be4be31e290e1dd1dedb0b630c5e8fc6 /MapUITests/SearchUITests.swift
parented10ac191df473c92c4fec495aafa7f569d108c8 (diff)
Upgrade to Swift 6
Diffstat (limited to 'MapUITests/SearchUITests.swift')
-rw-r--r--MapUITests/SearchUITests.swift226
1 files changed, 226 insertions, 0 deletions
diff --git a/MapUITests/SearchUITests.swift b/MapUITests/SearchUITests.swift
new file mode 100644
index 0000000..1891678
--- /dev/null
+++ b/MapUITests/SearchUITests.swift
@@ -0,0 +1,226 @@
+// Copyright (C) 2024 Rubén Beltrán del Río
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see https://map.tranquil.systems.
+import XCTest
+
+final class SearchUITests: XCTestCase {
+
+ override func setUpWithError() throws {
+ continueAfterFailure = false
+ }
+
+ override func tearDownWithError() throws {
+ Task { @MainActor in
+ // Close any test documents we may have created to avoid leaving them open
+ let app = XCUIApplication()
+ if app.state == .runningForeground {
+ // Close all windows except the first one (if any existed before tests)
+ let windowCount = app.windows.count
+ if windowCount > 1 {
+ for _ in 1..<windowCount {
+ app.typeKey("w", modifierFlags: .command)
+ }
+ }
+ }
+ }
+ }
+
+ @MainActor
+ private func createNewDocument(app: XCUIApplication) {
+ // Create a new document to ensure we start with a clean slate
+ app.typeKey("n", modifierFlags: .command)
+
+ // Wait for the new document window to appear
+ let newWindow = app.windows.element(boundBy: app.windows.count - 1)
+ XCTAssertTrue(newWindow.waitForExistence(timeout: 3.0))
+ }
+
+ @MainActor
+ func testSearchBarAppearance() throws {
+ let app = XCUIApplication()
+ app.launch()
+
+ // Create new document to avoid interfering with existing files
+ createNewDocument(app: app)
+
+ let window = app.windows.firstMatch
+ XCTAssertTrue(window.waitForExistence(timeout: 5.0))
+
+ // Trigger search with Cmd+F
+ window.typeKey("f", modifierFlags: .command)
+
+ // Verify search bar appears (SearchBar uses a TextField with placeholder "Search")
+ let searchField = app.textFields["Search"]
+ XCTAssertTrue(searchField.waitForExistence(timeout: 2.0))
+
+ // Verify search navigation buttons appear - the search bar should contain multiple buttons
+ // We'll check for the Done button which should be most reliable
+ let doneButton = app.buttons["Done"]
+ XCTAssertTrue(doneButton.waitForExistence(timeout: 2.0))
+ }
+
+ @MainActor
+ func testSearchFunctionality() throws {
+ let app = XCUIApplication()
+ app.launch()
+
+ // Create new document to avoid interfering with existing files
+ createNewDocument(app: app)
+
+ // Add test content with searchable terms
+ let textView = app.textViews.firstMatch
+ XCTAssertTrue(textView.waitForExistence(timeout: 5.0))
+
+ textView.click()
+ textView.typeKey("a", modifierFlags: .command)
+ textView.typeText("Node A (10, 20)\nNode B (30, 40)\nNode C (50, 60)\nNode A -> Node B")
+
+ // Open search
+ app.typeKey("f", modifierFlags: .command)
+
+ let searchField = app.textFields["Search"]
+ XCTAssertTrue(searchField.waitForExistence(timeout: 2.0))
+
+ // Search for "Node"
+ searchField.typeText("Node")
+
+ // Verify search results are highlighted (this is visual, hard to test directly)
+ // We can at least verify the search field contains our text
+ XCTAssertEqual(searchField.value as? String, "Node")
+ }
+
+ @MainActor
+ func testSearchNavigation() throws {
+ let app = XCUIApplication()
+ app.launch()
+
+ // Create new document to avoid interfering with existing files
+ createNewDocument(app: app)
+
+ // Add test content with multiple instances of search term
+ let textView = app.textViews.firstMatch
+ XCTAssertTrue(textView.waitForExistence(timeout: 5.0))
+
+ textView.click()
+ textView.typeKey("a", modifierFlags: .command)
+ textView.typeText("Test Test Test\nAnother Test line\nFinal Test here")
+
+ // Open search
+ app.typeKey("f", modifierFlags: .command)
+
+ let searchField = app.textFields["Search"]
+ XCTAssertTrue(searchField.waitForExistence(timeout: 2.0))
+
+ // Search for "Test"
+ searchField.typeText("Test")
+
+ // Try navigation with chevron buttons
+ let nextButton = app.buttons.containing(.image, identifier: "chevron.right").firstMatch
+ let previousButton = app.buttons.containing(.image, identifier: "chevron.left").firstMatch
+
+ if nextButton.waitForExistence(timeout: 2.0) {
+ nextButton.click()
+ }
+
+ if previousButton.waitForExistence(timeout: 2.0) {
+ previousButton.click()
+ }
+ }
+
+ @MainActor
+ func testSearchDismissal() throws {
+ let app = XCUIApplication()
+ app.launch()
+
+ // Create new document to avoid interfering with existing files
+ createNewDocument(app: app)
+
+ let window = app.windows.firstMatch
+ XCTAssertTrue(window.waitForExistence(timeout: 5.0))
+
+ // Open search
+ window.typeKey("f", modifierFlags: .command)
+
+ let searchField = app.textFields["Search"]
+ XCTAssertTrue(searchField.waitForExistence(timeout: 2.0))
+
+ // Type something
+ searchField.typeText("test")
+
+ // Dismiss with Escape
+ searchField.typeKey(XCUIKeyboardKey.escape, modifierFlags: [])
+
+ // Verify search bar is dismissed
+ XCTAssertFalse(searchField.waitForExistence(timeout: 1.0))
+ }
+
+ @MainActor
+ func testSearchWithEmptyResults() throws {
+ let app = XCUIApplication()
+ app.launch()
+
+ // Create new document to avoid interfering with existing files
+ createNewDocument(app: app)
+
+ // Add test content
+ let textView = app.textViews.firstMatch
+ XCTAssertTrue(textView.waitForExistence(timeout: 5.0))
+
+ textView.click()
+ textView.typeKey("a", modifierFlags: .command)
+ textView.typeText("Node A (10, 20)\nNode B (30, 40)")
+
+ // Open search
+ app.typeKey("f", modifierFlags: .command)
+
+ let searchField = app.textFields["Search"]
+ XCTAssertTrue(searchField.waitForExistence(timeout: 2.0))
+
+ // Search for something that doesn't exist
+ searchField.typeText("XYZ123")
+
+ // Verify search field still exists and contains our search term
+ XCTAssertEqual(searchField.value as? String, "XYZ123")
+ }
+
+ @MainActor
+ func testSearchCaseSensitivity() throws {
+ let app = XCUIApplication()
+ app.launch()
+
+ // Create new document to avoid interfering with existing files
+ createNewDocument(app: app)
+
+ // Add test content with mixed case
+ let textView = app.textViews.firstMatch
+ XCTAssertTrue(textView.waitForExistence(timeout: 5.0))
+
+ textView.click()
+ textView.typeKey("a", modifierFlags: .command)
+ textView.typeText("Node A (10, 20)\nnode B (30, 40)\nNODE C (50, 60)")
+
+ // Open search
+ app.typeKey("f", modifierFlags: .command)
+
+ let searchField = app.textFields["Search"]
+ XCTAssertTrue(searchField.waitForExistence(timeout: 2.0))
+
+ // Search for "node" (lowercase)
+ searchField.typeText("node")
+
+ // The search should be case-insensitive based on the implementation
+ XCTAssertEqual(searchField.value as? String, "node")
+ }
+
+}