feat(intents): onscreen entity annotations + App Intents tests
All checks were successful
CI / build-and-deploy (push) Successful in 28s

- bookmarkOnscreen(_:) publishes the viewed bookmark as the on-screen
  entity (NSUserActivity.appEntityIdentifier) so Siri can resolve "this"
  / "summarize this one"; applied to the BrowserView sheets in
  BookmarksView and SearchView
- Add MarksTests (XCTest) covering entity mapping, EntityIdentifier,
  IntentRouter, and the real perform() of SearchMarksIntent and
  OpenBookmarkIntent; wired into the Marks scheme test phase

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Krishna Kumar
2026-06-17 00:16:46 -05:00
parent 389d615c8b
commit a3059f25fc
7 changed files with 256 additions and 0 deletions

View File

@@ -0,0 +1,107 @@
import XCTest
import AppIntents
@testable import Marks
/// Tests for the App Intents layer.
///
/// Note: WWDC26's dedicated `AppIntentsTesting` framework (out-of-process
/// `IntentDefinitions(bundleIdentifier:)` / `.run()`) is not present in this
/// Xcode, so these are standard XCTest cases. They work because Marks has no
/// AppIntents extension intents run in the app process, so `perform()` can be
/// called directly and asserted against `IntentRouter`.
final class AppIntentsTests: XCTestCase {
private func sampleBookmark(
id: Int = 42,
url: String = "https://example.com/article",
title: String = "Concurrency in Swift",
tags: [String] = ["swift", "concurrency"],
unread: Bool = true,
aiSummary: String? = "A short summary."
) -> Bookmark {
Bookmark(
id: id, url: url, title: title, description: "desc",
tagNames: tags, dateAdded: Date(), dateModified: Date(),
isArchived: false, unread: unread, shared: false,
websiteTitle: nil, websiteDescription: nil,
faviconUrl: nil, previewImageUrl: nil,
aiSummary: aiSummary, aiTags: nil
)
}
// MARK: - Entity mapping
func testEntityMapsFromBookmark() {
let entity = BookmarkEntity(from: sampleBookmark())
XCTAssertEqual(entity.id, 42)
XCTAssertEqual(entity.title, "Concurrency in Swift")
XCTAssertEqual(entity.url, URL(string: "https://example.com/article"))
XCTAssertEqual(entity.host, "example.com")
XCTAssertEqual(entity.tags, ["swift", "concurrency"])
XCTAssertTrue(entity.unread)
XCTAssertEqual(entity.summary, "A short summary.")
}
func testEntityUsesDisplayTitleFallback() {
// empty title falls back to url (Bookmark.displayTitle)
let entity = BookmarkEntity(from: sampleBookmark(title: ""))
XCTAssertFalse(entity.title.isEmpty)
}
func testMakeBookmarkRoundTripsCoreFields() {
let entity = BookmarkEntity(from: sampleBookmark())
let back = entity.makeBookmark()
XCTAssertEqual(back.id, 42)
XCTAssertEqual(back.url, "https://example.com/article")
XCTAssertEqual(back.tagNames, ["swift", "concurrency"])
}
func testEntityIdentifierEncodesServerId() {
let entity = BookmarkEntity(from: sampleBookmark(id: 7))
let eid = EntityIdentifier(for: entity)
XCTAssertEqual(eid.identifier, "7")
XCTAssertTrue(eid.entityType == BookmarkEntity.self)
}
// MARK: - Router
@MainActor
func testRouterSearch() {
IntentRouter.shared.searchRequest = nil
IntentRouter.shared.search("hello")
XCTAssertEqual(IntentRouter.shared.searchRequest, "hello")
}
@MainActor
func testRouterOpenBookmark() {
IntentRouter.shared.openBookmarkURL = nil
IntentRouter.shared.openBookmark(url: "https://example.com")
XCTAssertEqual(IntentRouter.shared.openBookmarkURL, "https://example.com")
}
// MARK: - Intent perform() wiring (no network)
@MainActor
func testSearchIntentRoutesCriteriaTerm() async throws {
IntentRouter.shared.searchRequest = nil
let intent = SearchMarksIntent()
intent.criteria = StringSearchCriteria(term: "graphql")
_ = try await intent.perform()
XCTAssertEqual(IntentRouter.shared.searchRequest, "graphql")
}
@MainActor
func testOpenIntentRoutesURL() async throws {
IntentRouter.shared.openBookmarkURL = nil
let intent = OpenBookmarkIntent()
intent.target = BookmarkEntity(from: sampleBookmark())
_ = try await intent.perform()
XCTAssertEqual(IntentRouter.shared.openBookmarkURL, "https://example.com/article")
}
// MARK: - App Shortcuts
func testAppShortcutsAreRegistered() {
XCTAssertGreaterThanOrEqual(MarksShortcuts.appShortcuts.count, 4)
}
}