Skip to content

Commit 1c54e10

Browse files
Support beta status in navigator (#1249)
* Propagate beta attribute for external entities to the navigator The `isBeta` attribute is part of `TopicRenderReference` [1], and is already computed based on the platforms [2][3] (though the platform information itself is dropped). This changes propagates the property to `ExternalRenderNode` and `ExternalRenderNodeMetadataRepresentation` so that we can ultimately store it as part of the navigator `RenderIndex`. [4] Fixes rdar://155521394. [1]: https://github.com/swiftlang/swift-docc/blob/f968935b770b0011d7aa28f59eda22a8407282b7/Sources/SwiftDocC/Model/Rendering/References/TopicRenderReference.swift#L82-L85 [2]: https://github.com/swiftlang/swift-docc/blob/f968935b770b0011d7aa28f59eda22a8407282b7/Sources/SwiftDocC/Infrastructure/External%20Data/OutOfProcessReferenceResolver.swift#L158 [3]: https://github.com/swiftlang/swift-docc/blob/f968935b770b0011d7aa28f59eda22a8407282b7/Sources/SwiftDocC/Infrastructure/External%20Data/OutOfProcessReferenceResolver.swift#L592-L598 [4]: https://github.com/swiftlang/swift-docc/blob/f968935b770b0011d7aa28f59eda22a8407282b7/Sources/SwiftDocC/Indexing/RenderIndexJSON/RenderIndex.swift#L251 * Add beta attribute to NavigatorIndexableRenderMetadataRepresentation Adds a computed property to `NavigatorIndexableRenderMetadataRepresentation` which derives whether the navigator item `isBeta` or not. This uses the same logic used in other places in the codebase [1]. Fixes rdar://155521394. [1]: https://github.com/swiftlang/swift-docc/blob/f968935b770b0011d7aa28f59eda22a8407282b7/Sources/SwiftDocC/Infrastructure/External%20Data/OutOfProcessReferenceResolver.swift#L592-L598 * Capture whether an item `isBeta` in the navigator item Propagates the `isBeta` property to the `NavigatorItem` type from `NavigatorIndexableRenderMetadataRepresentation`. When we index a new node, whether the item is beta or not will now be captured as part of the navigator This is preparatory work before this property is propagated to the `RenderIndex` [1]. Fixes rdar://155521394. [1]: https://github.com/swiftlang/swift-docc/blob/65aaf926ec079ddbd40f29540d4180a70af99e5e/Sources/SwiftDocC/Indexing/RenderIndexJSON/RenderIndex.swift#L257-L259 * Fix serialisation of isBeta and isExternal properties The isBeta and isExternal properties weren't being serialised as part of `NavigatorItem`. These properties are used to initialise to `RenderIndex.Node` during the conversion to `index.json` [1] and must be preserved when navigator indexes are written to disk [2] so that when they are read [3], we don't drop beta and external information. This serialisation happens during the `finalize` step [4] and the deserialisation can be invoked via `NavigatorIndex.readNavigatorIndex` [5]. Otherwise, the values can be lost on serialisation roundtrip. [1]: https://github.com/swiftlang/swift-docc/blob/65aaf926ec079ddbd40f29540d4180a70af99e5e/Sources/SwiftDocC/Indexing/RenderIndexJSON/RenderIndex.swift#L329 [2]: https://github.com/swiftlang/swift-docc/blob/65aaf926ec079ddbd40f29540d4180a70af99e5e/Sources/SwiftDocC/Indexing/Navigator/NavigatorTree.swift#L195 [3]: https://github.com/swiftlang/swift-docc/blob/65aaf926ec079ddbd40f29540d4180a70af99e5e/Sources/SwiftDocC/Indexing/Navigator/NavigatorTree.swift#L266 [4]: https://github.com/swiftlang/swift-docc/blob/65aaf926ec079ddbd40f29540d4180a70af99e5e/Sources/SwiftDocC/Indexing/Navigator/NavigatorIndex.swift#L1193 [5]: https://github.com/swiftlang/swift-docc/blob/65aaf926ec079ddbd40f29540d4180a70af99e5e/Sources/SwiftDocC/Indexing/Navigator/NavigatorIndex.swift#L157 * Propagates `isBeta` property to RenderIndex All that was left was that on initialisation of a `RenderIndex.Node`, we propagate the `isBeta` value from the `NavigatorItem`. With this change, beta information is now available in the navigator, encoded as `"beta": true` in the resulting `index.json` file. Fixes rdar://155521394. * Check that we don't cause an out of bounds crash when accessing the new values. Added an assertion that checks that the cursor plus the lenght of the memory to be decoded is less or equal than the length of the entire memory for the raw value that has been passed, avoiding a runtime crash. Also both if statements were combined into a signgle one since, as pointed out in [1], `isBeta` and `isExternal` have to either both exists or not. --- [1] #1249 (comment) * Update license year in the header of the modified files. --------- Co-authored-by: Sofia Rodriguez Morales <[email protected]>
1 parent 0238525 commit 1c54e10

File tree

9 files changed

+389
-21
lines changed

9 files changed

+389
-21
lines changed

Sources/SwiftDocC/Indexing/Navigator/NavigatorIndex.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,8 @@ extension NavigatorIndex {
771771
platformMask: platformID,
772772
availabilityID: UInt64(availabilityID),
773773
icon: renderNode.icon,
774-
isExternal: external
774+
isExternal: external,
775+
isBeta: renderNode.metadata.isBeta
775776
)
776777
navigationItem.path = identifierPath
777778

Sources/SwiftDocC/Indexing/Navigator/NavigatorItem.swift

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This source file is part of the Swift.org open source project
33

4-
Copyright (c) 2021-2024 Apple Inc. and the Swift project authors
4+
Copyright (c) 2021-2025 Apple Inc. and the Swift project authors
55
Licensed under Apache License v2.0 with Runtime Library Exception
66

77
See https://swift.org/LICENSE.txt for license information
@@ -49,6 +49,11 @@ public final class NavigatorItem: Serializable, Codable, Equatable, CustomString
4949

5050
var icon: RenderReferenceIdentifier? = nil
5151

52+
/// A value that indicates whether this item is built for a beta platform.
53+
///
54+
/// This value is `false` if the referenced item is not a symbol.
55+
var isBeta: Bool = false
56+
5257
/// Whether the item has originated from an external reference.
5358
///
5459
/// Used for determining whether stray navigation items should remain part of the final navigator.
@@ -66,7 +71,7 @@ public final class NavigatorItem: Serializable, Codable, Equatable, CustomString
6671
- path: The path to load the content.
6772
- icon: A reference to a custom image for this navigator item.
6873
*/
69-
init(pageType: UInt8, languageID: UInt8, title: String, platformMask: UInt64, availabilityID: UInt64, path: String, icon: RenderReferenceIdentifier? = nil, isExternal: Bool = false) {
74+
init(pageType: UInt8, languageID: UInt8, title: String, platformMask: UInt64, availabilityID: UInt64, path: String, icon: RenderReferenceIdentifier? = nil, isExternal: Bool = false, isBeta: Bool = false) {
7075
self.pageType = pageType
7176
self.languageID = languageID
7277
self.title = title
@@ -75,6 +80,7 @@ public final class NavigatorItem: Serializable, Codable, Equatable, CustomString
7580
self.path = path
7681
self.icon = icon
7782
self.isExternal = isExternal
83+
self.isBeta = isBeta
7884
}
7985

8086
/**
@@ -87,15 +93,18 @@ public final class NavigatorItem: Serializable, Codable, Equatable, CustomString
8793
- platformMask: The mask indicating for which platform the page is available.
8894
- availabilityID: The identifier of the availability information of the page.
8995
- icon: A reference to a custom image for this navigator item.
96+
- isExternal: A flag indicating whether the navigator item belongs to an external documentation archive.
97+
- isBeta: A flag indicating whether the navigator item is in beta.
9098
*/
91-
public init(pageType: UInt8, languageID: UInt8, title: String, platformMask: UInt64, availabilityID: UInt64, icon: RenderReferenceIdentifier? = nil, isExternal: Bool = false) {
99+
public init(pageType: UInt8, languageID: UInt8, title: String, platformMask: UInt64, availabilityID: UInt64, icon: RenderReferenceIdentifier? = nil, isExternal: Bool = false, isBeta: Bool = false) {
92100
self.pageType = pageType
93101
self.languageID = languageID
94102
self.title = title
95103
self.platformMask = platformMask
96104
self.availabilityID = availabilityID
97105
self.icon = icon
98106
self.isExternal = isExternal
107+
self.isBeta = isBeta
99108
}
100109

101110
// MARK: - Serialization and Deserialization
@@ -137,8 +146,27 @@ public final class NavigatorItem: Serializable, Codable, Equatable, CustomString
137146

138147
let pathData = data[cursor..<cursor + Int(pathLength)]
139148
self.path = String(data: pathData, encoding: .utf8)!
149+
cursor += Int(pathLength)
140150

141-
assert(cursor+Int(pathLength) == data.count)
151+
// isBeta and isExternal should be encoded because they are relevant when creating a RenderIndex node.
152+
// Without proper serialization, these indicators would be lost when navigator indexes are loaded from disk.
153+
154+
length = MemoryLayout<UInt8>.stride
155+
// To ensure backwards compatibility, handle both when `isBeta` and `isExternal` has been encoded and when it hasn't
156+
if cursor < data.count {
157+
// Encoded `isBeta`
158+
assert(cursor + length <= data.count, "The serialized data is malformed: `isBeta` value should not extend past the end of the data")
159+
let betaValue: UInt8 = unpackedValueFromData(data[cursor..<cursor + length])
160+
cursor += length
161+
self.isBeta = betaValue != 0
162+
// Encoded `isExternal`
163+
assert(cursor + length <= data.count, "The serialized data is malformed: `isExternal` value should not extend past the end of the data")
164+
let externalValue: UInt8 = unpackedValueFromData(data[cursor..<cursor + length])
165+
cursor += length
166+
self.isExternal = externalValue != 0
167+
}
168+
169+
assert(cursor == data.count)
142170
}
143171

144172
/// Returns the `Data` representation of the current `NavigatorItem` instance.
@@ -155,6 +183,9 @@ public final class NavigatorItem: Serializable, Codable, Equatable, CustomString
155183
data.append(Data(title.utf8))
156184
data.append(Data(path.utf8))
157185

186+
data.append(packedDataFromValue(isBeta ? UInt8(1) : UInt8(0)))
187+
data.append(packedDataFromValue(isExternal ? UInt8(1) : UInt8(0)))
188+
158189
return data
159190
}
160191

@@ -167,7 +198,9 @@ public final class NavigatorItem: Serializable, Codable, Equatable, CustomString
167198
languageID: \(languageID),
168199
title: \(title),
169200
platformMask: \(platformMask),
170-
availabilityID: \(availabilityID)
201+
availabilityID: \(availabilityID),
202+
isBeta: \(isBeta),
203+
isExternal: \(isExternal)
171204
}
172205
"""
173206
}

Sources/SwiftDocC/Indexing/Navigator/RenderNode+NavigatorIndex.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This source file is part of the Swift.org open source project
33

4-
Copyright (c) 2024 Apple Inc. and the Swift project authors
4+
Copyright (c) 2024-2025 Apple Inc. and the Swift project authors
55
Licensed under Apache License v2.0 with Runtime Library Exception
66

77
See https://swift.org/LICENSE.txt for license information
@@ -40,6 +40,7 @@ protocol NavigatorIndexableRenderMetadataRepresentation {
4040
var roleHeading: String? { get }
4141
var symbolKind: String? { get }
4242
var platforms: [AvailabilityRenderItem]? { get }
43+
var isBeta: Bool { get }
4344
}
4445

4546
extension NavigatorIndexableRenderNodeRepresentation {
@@ -122,6 +123,16 @@ struct RenderNodeVariantView: NavigatorIndexableRenderNodeRepresentation {
122123
}
123124
}
124125

126+
extension NavigatorIndexableRenderMetadataRepresentation {
127+
var isBeta: Bool {
128+
guard let platforms, !platforms.isEmpty else {
129+
return false
130+
}
131+
132+
return platforms.allSatisfy { $0.isBeta == true }
133+
}
134+
}
135+
125136
private let typesThatShouldNotUseNavigatorTitle: Set<NavigatorIndex.PageType> = [
126137
.framework, .class, .structure, .enumeration, .protocol, .typeAlias, .associatedType, .extension
127138
]

Sources/SwiftDocC/Indexing/RenderIndexJSON/RenderIndex.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This source file is part of the Swift.org open source project
33

4-
Copyright (c) 2022-2024 Apple Inc. and the Swift project authors
4+
Copyright (c) 2022-2025 Apple Inc. and the Swift project authors
55
Licensed under Apache License v2.0 with Runtime Library Exception
66

77
See https://swift.org/LICENSE.txt for license information
@@ -92,6 +92,7 @@ public struct RenderIndex: Codable, Equatable {
9292
pageType: .framework,
9393
isDeprecated: false,
9494
isExternal: false,
95+
isBeta: false,
9596
children: nodes,
9697
icon: nil
9798
)
@@ -245,6 +246,7 @@ extension RenderIndex {
245246
pageType: NavigatorIndex.PageType?,
246247
isDeprecated: Bool,
247248
isExternal: Bool,
249+
isBeta: Bool,
248250
children: [Node],
249251
icon: RenderReferenceIdentifier?
250252
) {
@@ -253,10 +255,8 @@ extension RenderIndex {
253255

254256
self.isDeprecated = isDeprecated
255257
self.isExternal = isExternal
256-
257-
// Currently Swift-DocC doesn't support marking a node as beta in the navigation index
258-
// so we default to `false` here.
259-
self.isBeta = false
258+
self.isBeta = isBeta
259+
260260
self.icon = icon
261261

262262
guard let pageType else {
@@ -327,6 +327,7 @@ extension RenderIndex.Node {
327327
pageType: NavigatorIndex.PageType(rawValue: node.item.pageType),
328328
isDeprecated: isDeprecated,
329329
isExternal: node.item.isExternal,
330+
isBeta: node.item.isBeta,
330331
children: node.children.map {
331332
RenderIndex.Node.fromNavigatorTreeNode($0, in: navigatorIndex, with: builder)
332333
},

Sources/SwiftDocC/Infrastructure/Link Resolution/LinkResolver+NavigatorIndex.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ package struct ExternalRenderNode {
7777
RenderNode.Variant(traits: [.interfaceLanguage($0.id)], paths: [externalEntity.topicRenderReference.url])
7878
}
7979
}
80+
81+
/// A value that indicates whether this symbol is built for a beta platform
82+
///
83+
/// This value is `false` if the referenced page is not a symbol.
84+
var isBeta: Bool {
85+
externalEntity.topicRenderReference.isBeta
86+
}
8087
}
8188

8289
/// A language specific representation of an external render node value for building a navigator index.
@@ -110,7 +117,8 @@ struct NavigatorExternalRenderNode: NavigatorIndexableRenderNodeRepresentation {
110117
externalID: renderNode.externalIdentifier.identifier,
111118
role: renderNode.role,
112119
symbolKind: renderNode.symbolKind?.identifier,
113-
images: renderNode.images
120+
images: renderNode.images,
121+
isBeta: renderNode.isBeta
114122
)
115123
}
116124
}
@@ -123,6 +131,7 @@ struct ExternalRenderNodeMetadataRepresentation: NavigatorIndexableRenderMetadat
123131
var role: String?
124132
var symbolKind: String?
125133
var images: [TopicImage]
134+
var isBeta: Bool
126135

127136
// Values that we have insufficient information to derive.
128137
// These are needed to conform to the navigator indexable metadata protocol.

Tests/SwiftDocCTests/Indexing/ExternalRenderNodeTests.swift

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,31 +21,35 @@ class ExternalRenderNodeTests: XCTestCase {
2121
referencePath: "/path/to/external/swiftArticle",
2222
title: "SwiftArticle",
2323
kind: .article,
24-
language: .swift
24+
language: .swift,
25+
platforms: [.init(name: "iOS", introduced: nil, isBeta: false)]
2526
)
2627
)
2728
externalResolver.entitiesToReturn["/path/to/external/objCArticle"] = .success(
2829
.init(
2930
referencePath: "/path/to/external/objCArticle",
3031
title: "ObjCArticle",
3132
kind: .article,
32-
language: .objectiveC
33+
language: .objectiveC,
34+
platforms: [.init(name: "macOS", introduced: nil, isBeta: true)]
3335
)
3436
)
3537
externalResolver.entitiesToReturn["/path/to/external/swiftSymbol"] = .success(
3638
.init(
3739
referencePath: "/path/to/external/swiftSymbol",
3840
title: "SwiftSymbol",
3941
kind: .class,
40-
language: .swift
42+
language: .swift,
43+
platforms: [.init(name: "iOS", introduced: nil, isBeta: true)]
4144
)
4245
)
4346
externalResolver.entitiesToReturn["/path/to/external/objCSymbol"] = .success(
4447
.init(
4548
referencePath: "/path/to/external/objCSymbol",
4649
title: "ObjCSymbol",
4750
kind: .function,
48-
language: .objectiveC
51+
language: .objectiveC,
52+
platforms: [.init(name: "macOS", introduced: nil, isBeta: false)]
4953
)
5054
)
5155
return externalResolver
@@ -89,24 +93,28 @@ class ExternalRenderNodeTests: XCTestCase {
8993
XCTAssertEqual(externalRenderNodes[0].symbolKind, nil)
9094
XCTAssertEqual(externalRenderNodes[0].role, "article")
9195
XCTAssertEqual(externalRenderNodes[0].externalIdentifier.identifier, "doc://com.test.external/path/to/external/objCArticle")
92-
96+
XCTAssertTrue(externalRenderNodes[0].isBeta)
97+
9398
XCTAssertEqual(externalRenderNodes[1].identifier.absoluteString, "doc://org.swift.MixedLanguageFramework/example/path/to/external/objCSymbol")
9499
XCTAssertEqual(externalRenderNodes[1].kind, .symbol)
95100
XCTAssertEqual(externalRenderNodes[1].symbolKind, nil)
96101
XCTAssertEqual(externalRenderNodes[1].role, "symbol")
97102
XCTAssertEqual(externalRenderNodes[1].externalIdentifier.identifier, "doc://com.test.external/path/to/external/objCSymbol")
103+
XCTAssertFalse(externalRenderNodes[1].isBeta)
98104

99105
XCTAssertEqual(externalRenderNodes[2].identifier.absoluteString, "doc://org.swift.MixedLanguageFramework/example/path/to/external/swiftArticle")
100106
XCTAssertEqual(externalRenderNodes[2].kind, .article)
101107
XCTAssertEqual(externalRenderNodes[2].symbolKind, nil)
102108
XCTAssertEqual(externalRenderNodes[2].role, "article")
103109
XCTAssertEqual(externalRenderNodes[2].externalIdentifier.identifier, "doc://com.test.external/path/to/external/swiftArticle")
110+
XCTAssertFalse(externalRenderNodes[2].isBeta)
104111

105112
XCTAssertEqual(externalRenderNodes[3].identifier.absoluteString, "doc://org.swift.MixedLanguageFramework/example/path/to/external/swiftSymbol")
106113
XCTAssertEqual(externalRenderNodes[3].kind, .symbol)
107114
XCTAssertEqual(externalRenderNodes[3].symbolKind, nil)
108115
XCTAssertEqual(externalRenderNodes[3].role, "symbol")
109116
XCTAssertEqual(externalRenderNodes[3].externalIdentifier.identifier, "doc://com.test.external/path/to/external/swiftSymbol")
117+
XCTAssertTrue(externalRenderNodes[3].isBeta)
110118
}
111119

112120
func testExternalRenderNodeVariantRepresentation() throws {
@@ -146,14 +154,16 @@ class ExternalRenderNodeTests: XCTestCase {
146154
)
147155
XCTAssertEqual(swiftNavigatorExternalRenderNode.metadata.title, swiftTitle)
148156
XCTAssertEqual(swiftNavigatorExternalRenderNode.metadata.navigatorTitle, navigatorTitle)
149-
157+
XCTAssertFalse(swiftNavigatorExternalRenderNode.metadata.isBeta)
158+
150159
let objcNavigatorExternalRenderNode = try XCTUnwrap(
151160
NavigatorExternalRenderNode(renderNode: externalRenderNode, trait: .interfaceLanguage("objc"))
152161
)
153162
XCTAssertEqual(objcNavigatorExternalRenderNode.metadata.title, occTitle)
154163
XCTAssertEqual(objcNavigatorExternalRenderNode.metadata.navigatorTitle, occNavigatorTitle)
164+
XCTAssertFalse(objcNavigatorExternalRenderNode.metadata.isBeta)
155165
}
156-
166+
157167
func testNavigatorWithExternalNodes() async throws {
158168
let externalResolver = generateExternalResolver()
159169
let (_, bundle, context) = try await testBundleAndContext(
@@ -208,6 +218,10 @@ class ExternalRenderNodeTests: XCTestCase {
208218
XCTAssertEqual(occExternalNodes.map(\.title), ["ObjCArticle", "ObjCSymbol"])
209219
XCTAssert(swiftExternalNodes.allSatisfy(\.isExternal))
210220
XCTAssert(occExternalNodes.allSatisfy(\.isExternal))
221+
XCTAssert(swiftExternalNodes.first { $0.title == "SwiftArticle" }?.isBeta == false)
222+
XCTAssert(swiftExternalNodes.first { $0.title == "SwiftSymbol" }?.isBeta == true)
223+
XCTAssert(occExternalNodes.first { $0.title == "ObjCArticle" }?.isBeta == true)
224+
XCTAssert(occExternalNodes.first { $0.title == "ObjCSymbol" }?.isBeta == false)
211225
}
212226

213227
func testNavigatorWithExternalNodesOnlyAddsCuratedNodesToNavigator() async throws {
@@ -269,4 +283,52 @@ class ExternalRenderNodeTests: XCTestCase {
269283
XCTAssert(swiftExternalNodes.allSatisfy(\.isExternal))
270284
XCTAssert(occExternalNodes.allSatisfy(\.isExternal))
271285
}
286+
287+
func testExternalRenderNodeVariantRepresentationWhenIsBeta() throws {
288+
let renderReferenceIdentifier = RenderReferenceIdentifier(forExternalLink: "doc://com.test.external/path/to/external/symbol")
289+
290+
// Variants for the title
291+
let swiftTitle = "Swift Symbol"
292+
let occTitle = "Occ Symbol"
293+
294+
// Variants for the navigator title
295+
let navigatorTitle: [DeclarationRenderSection.Token] = [.init(text: "symbol", kind: .identifier)]
296+
let occNavigatorTitle: [DeclarationRenderSection.Token] = [.init(text: "occ_symbol", kind: .identifier)]
297+
298+
// Variants for the fragments
299+
let fragments: [DeclarationRenderSection.Token] = [.init(text: "func", kind: .keyword), .init(text: "symbol", kind: .identifier)]
300+
let occFragments: [DeclarationRenderSection.Token] = [.init(text: "func", kind: .keyword), .init(text: "occ_symbol", kind: .identifier)]
301+
302+
let externalEntity = LinkResolver.ExternalEntity(
303+
topicRenderReference: .init(
304+
identifier: renderReferenceIdentifier,
305+
titleVariants: .init(defaultValue: swiftTitle, objectiveCValue: occTitle),
306+
abstractVariants: .init(defaultValue: []),
307+
url: "/example/path/to/external/symbol",
308+
kind: .symbol,
309+
fragmentsVariants: .init(defaultValue: fragments, objectiveCValue: occFragments),
310+
navigatorTitleVariants: .init(defaultValue: navigatorTitle, objectiveCValue: occNavigatorTitle),
311+
isBeta: true
312+
),
313+
renderReferenceDependencies: .init(),
314+
sourceLanguages: [SourceLanguage(name: "swift"), SourceLanguage(name: "objc")])
315+
let externalRenderNode = ExternalRenderNode(
316+
externalEntity: externalEntity,
317+
bundleIdentifier: "com.test.external"
318+
)
319+
320+
let swiftNavigatorExternalRenderNode = try XCTUnwrap(
321+
NavigatorExternalRenderNode(renderNode: externalRenderNode)
322+
)
323+
XCTAssertEqual(swiftNavigatorExternalRenderNode.metadata.title, swiftTitle)
324+
XCTAssertEqual(swiftNavigatorExternalRenderNode.metadata.navigatorTitle, navigatorTitle)
325+
XCTAssertTrue(swiftNavigatorExternalRenderNode.metadata.isBeta)
326+
327+
let objcNavigatorExternalRenderNode = try XCTUnwrap(
328+
NavigatorExternalRenderNode(renderNode: externalRenderNode, trait: .interfaceLanguage("objc"))
329+
)
330+
XCTAssertEqual(objcNavigatorExternalRenderNode.metadata.title, occTitle)
331+
XCTAssertEqual(objcNavigatorExternalRenderNode.metadata.navigatorTitle, occNavigatorTitle)
332+
XCTAssertTrue(objcNavigatorExternalRenderNode.metadata.isBeta)
333+
}
272334
}

0 commit comments

Comments
 (0)