Skip to content

Commit c4e2013

Browse files
committed
Add navigator title tests for external links in the navigator
Now that the navigator title is supported in external references, we can add some tests which verify this logic is working as expected. Added some tests which verify that the navigator title is used as expected for both Swift and Objective C symbols.
1 parent 9ae016c commit c4e2013

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed

Tests/SwiftDocCTests/Indexing/ExternalRenderNodeTests.swift

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,42 @@ class ExternalRenderNodeTests: XCTestCase {
6565
platforms: [.init(name: "macOS", introduced: nil, isBeta: false)]
6666
)
6767
)
68+
externalResolver.entitiesToReturn["/path/to/external/navigatorTitleSwiftSymbol"] = .success(
69+
.init(
70+
referencePath: "/path/to/external/navigatorTitleSwiftSymbol",
71+
title: "NavigatorTitleSwiftSymbol (title)",
72+
kind: .class,
73+
language: .swift,
74+
declarationFragments: .init(declarationFragments: [
75+
.init(kind: .keyword, spelling: "class", preciseIdentifier: nil),
76+
.init(kind: .text, spelling: " ", preciseIdentifier: nil),
77+
.init(kind: .identifier, spelling: "NavigatorTitleSwiftSymbol", preciseIdentifier: nil)
78+
]),
79+
navigatorTitle: .init(declarationFragments: [
80+
.init(kind: .identifier, spelling: "NavigatorTitleSwiftSymbol (navigator title)", preciseIdentifier: nil)
81+
]),
82+
platforms: [.init(name: "iOS", introduced: nil, isBeta: true)]
83+
)
84+
)
85+
externalResolver.entitiesToReturn["/path/to/external/navigatorTitleObjCSymbol"] = .success(
86+
.init(
87+
referencePath: "/path/to/external/navigatorTitleObjCSymbol",
88+
title: "NavigatorTitleObjCSymbol (title)",
89+
kind: .function,
90+
language: .objectiveC,
91+
declarationFragments: .init(declarationFragments: [
92+
.init(kind: .text, spelling: "- ", preciseIdentifier: nil),
93+
.init(kind: .text, spelling: "(", preciseIdentifier: nil),
94+
.init(kind: .typeIdentifier, spelling: "void", preciseIdentifier: nil),
95+
.init(kind: .text, spelling: ") ", preciseIdentifier: nil),
96+
.init(kind: .identifier, spelling: "ObjCSymbol", preciseIdentifier: nil)
97+
]),
98+
navigatorTitle: .init(declarationFragments: [
99+
.init(kind: .identifier, spelling: "NavigatorTitleObjCSymbol (navigator title)", preciseIdentifier: nil)
100+
]),
101+
platforms: [.init(name: "macOS", introduced: nil, isBeta: false)]
102+
)
103+
)
68104
return externalResolver
69105
}
70106

@@ -266,6 +302,80 @@ class ExternalRenderNodeTests: XCTestCase {
266302
XCTAssertEqual(objcSymbolExternalNode.type, "func")
267303
}
268304

305+
func testNavigatorWithExternalNodesWithNavigatorTitle() async throws {
306+
let catalog = Folder(name: "ModuleName.docc", content: [
307+
Folder(name: "swift", content: [
308+
JSONFile(name: "ModuleName.symbols.json", content: makeSymbolGraph(moduleName: "ModuleName", symbols: [
309+
makeSymbol(id: "some-symbol-id", language: .swift, kind: .class, pathComponents: ["SomeClass"])
310+
]))
311+
]),
312+
Folder(name: "clang", content: [
313+
JSONFile(name: "ModuleName.symbols.json", content: makeSymbolGraph(moduleName: "ModuleName", symbols: [
314+
makeSymbol(id: "some-symbol-id", language: .objectiveC, kind: .class, pathComponents: ["TLASomeClass"])
315+
]))
316+
]),
317+
318+
InfoPlist(identifier: "some.custom.identifier"),
319+
320+
TextFile(name: "ModuleName.md", utf8Content: """
321+
# ``ModuleName``
322+
323+
Curate a few external language-specific symbols and articles
324+
325+
## Topics
326+
327+
### External Reference
328+
329+
- <doc://com.test.external/path/to/external/navigatorTitleSwiftSymbol>
330+
- <doc://com.test.external/path/to/external/navigatorTitleObjCSymbol>
331+
"""),
332+
])
333+
334+
var configuration = DocumentationContext.Configuration()
335+
let externalResolver = generateExternalResolver()
336+
configuration.externalDocumentationConfiguration.sources[externalResolver.bundleID] = externalResolver
337+
let (bundle, context) = try await loadBundle(catalog: catalog, configuration: configuration)
338+
XCTAssert(context.problems.isEmpty, "Encountered unexpected problems: \(context.problems.map(\.diagnostic.summary))")
339+
340+
let renderContext = RenderContext(documentationContext: context, bundle: bundle)
341+
let converter = DocumentationContextConverter(bundle: bundle, context: context, renderContext: renderContext)
342+
let targetURL = try createTemporaryDirectory()
343+
let builder = NavigatorIndex.Builder(outputURL: targetURL, bundleIdentifier: bundle.id.rawValue, sortRootChildrenByName: true, groupByLanguage: true)
344+
builder.setup()
345+
for externalLink in context.externalCache {
346+
let externalRenderNode = ExternalRenderNode(externalEntity: externalLink.value, bundleIdentifier: bundle.id)
347+
try builder.index(renderNode: externalRenderNode)
348+
}
349+
for identifier in context.knownPages {
350+
let entity = try context.entity(with: identifier)
351+
let renderNode = try XCTUnwrap(converter.renderNode(for: entity))
352+
try builder.index(renderNode: renderNode)
353+
}
354+
builder.finalize()
355+
let renderIndex = try RenderIndex.fromURL(targetURL.appendingPathComponent("index.json"))
356+
357+
// Verify that there are no uncurated external links at the top level
358+
XCTAssertEqual(renderIndex.interfaceLanguages[SourceLanguage.swift.id]?.count(where: \.isExternal), 0)
359+
XCTAssertEqual(renderIndex.interfaceLanguages[SourceLanguage.objectiveC.id]?.count(where: \.isExternal), 0)
360+
361+
func externalNodes(by language: SourceLanguage) -> [RenderIndex.Node]? {
362+
renderIndex.interfaceLanguages[language.id]?.first?.children?.filter(\.isExternal)
363+
}
364+
365+
// Verify that the curated external links are part of the index.
366+
let swiftExternalNodes = try XCTUnwrap(externalNodes(by: .swift))
367+
let objcExternalNodes = try XCTUnwrap(externalNodes(by: .objectiveC))
368+
369+
XCTAssertEqual(swiftExternalNodes.count, 1)
370+
XCTAssertEqual(objcExternalNodes.count, 1)
371+
372+
let swiftSymbolExternalNode = try XCTUnwrap(swiftExternalNodes.first)
373+
let objcSymbolExternalNode = try XCTUnwrap(objcExternalNodes.first)
374+
375+
XCTAssertEqual(swiftSymbolExternalNode.title, "NavigatorTitleSwiftSymbol (title)") // Swift types prefer not using the navigator title where possible
376+
XCTAssertEqual(objcSymbolExternalNode.title, "NavigatorTitleObjCSymbol (navigator title)") // Objective C types prefer using the navigator title where possible
377+
}
378+
269379
func testNavigatorWithExternalNodesOnlyAddsCuratedNodesToNavigator() async throws {
270380
let catalog = Folder(name: "ModuleName.docc", content: [
271381
Folder(name: "swift", content: [

Tests/SwiftDocCTests/Infrastructure/TestExternalReferenceResolvers.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class TestMultiResultExternalReferenceResolver: ExternalDocumentationSource {
2828
var kind = DocumentationNode.Kind.article
2929
var language = SourceLanguage.swift
3030
var declarationFragments: SymbolGraph.Symbol.DeclarationFragments? = nil
31+
var navigatorTitle: SymbolGraph.Symbol.DeclarationFragments? = nil
3132
var topicImages: [(TopicImage, alt: String)]? = nil
3233
var platforms: [AvailabilityRenderItem]? = nil
3334
}
@@ -93,6 +94,7 @@ class TestMultiResultExternalReferenceResolver: ExternalDocumentationSource {
9394
availableLanguages: [entityInfo.language],
9495
platforms: entityInfo.platforms,
9596
declarationFragments: entityInfo.declarationFragments?.declarationFragments.map { .init(fragment: $0, identifier: nil) },
97+
navigatorTitle: entityInfo.navigatorTitle?.declarationFragments.map { .init(fragment: $0, identifier: nil) },
9698
topicImages: entityInfo.topicImages?.map(\.0),
9799
references: entityInfo.topicImages?.map { topicImage, altText in
98100
ImageReference(identifier: topicImage.identifier, altText: altText, imageAsset: assetsToReturn[topicImage.identifier.identifier] ?? .init())

0 commit comments

Comments
 (0)