@@ -31,6 +31,10 @@ class ConvertActionTests: XCTestCase {
31
31
withExtension: " symbols.json " ,
32
32
subdirectory: " Test Resources "
33
33
) !
34
+
35
+ let projectZipFile = Bundle . module. url (
36
+ forResource: " TestBundle " , withExtension: " docc " , subdirectory: " Test Bundles " ) !
37
+ . appendingPathComponent ( " project.zip " )
34
38
35
39
/// A symbol graph file that has missing symbols.
36
40
let incompleteSymbolGraphFile = TextFile ( name: " TechnologyX.symbols.json " , utf8Content: """
@@ -1159,6 +1163,132 @@ class ConvertActionTests: XCTestCase {
1159
1163
XCTAssertEqual ( resultAssets. images. map ( { $0. identifier. identifier } ) . sorted ( ) , images. map ( { $0. identifier. identifier } ) . sorted ( ) )
1160
1164
}
1161
1165
1166
+ func testDownloadMetadataIsWritenToOutputFolder( ) throws {
1167
+ let bundle = Folder ( name: " unit-test.docc " , content: [
1168
+ CopyOfFile ( original: projectZipFile) ,
1169
+ CopyOfFile ( original: imageFile, newName: " referenced-tutorials-image.png " ) ,
1170
+
1171
+ TextFile ( name: " MyTechnology.tutorial " , utf8Content: """
1172
+ @Tutorial(time: 10, projectFiles: project.zip) {
1173
+ @Intro(title: " TechologyX " ) {}
1174
+
1175
+ @Section(title: " Section " ) {
1176
+ @Steps {}
1177
+ }
1178
+
1179
+ @Assessments {
1180
+ @MultipleChoice {
1181
+ text
1182
+ @Choice(isCorrect: true) {
1183
+ text
1184
+ @Justification(reaction: " reaction text " ) {}
1185
+ }
1186
+
1187
+ @Choice(isCorrect: false) {
1188
+ text
1189
+ @Justification(reaction: " reaction text " ) {}
1190
+ }
1191
+ }
1192
+ }
1193
+ }
1194
+ """ ) ,
1195
+
1196
+ TextFile ( name: " TechnologyX.tutorial " , utf8Content: """
1197
+ @Tutorials(name: TechnologyX) {
1198
+ @Intro(title: " Technology X " ) {
1199
+ Learn about some stuff in Technology X.
1200
+ }
1201
+
1202
+ @Volume(name: " Volume 1 " ) {
1203
+ This volume contains Chapter 1.
1204
+
1205
+ @Image(source: referenced-tutorials-image.png, alt: " Some alt text " )
1206
+
1207
+ @Chapter(name: " Chapter 1 " ) {
1208
+ In this chapter, you'll learn about Tutorial 1.
1209
+
1210
+ @Image(source: referenced-tutorials-image.png, alt: " Some alt text " )
1211
+ @TutorialReference(tutorial: " doc:MyTechnology " )
1212
+ }
1213
+ }
1214
+ }
1215
+ """ ) ,
1216
+
1217
+ TextFile ( name: " MySample.md " , utf8Content: """
1218
+ # My Sample
1219
+
1220
+ @Metadata {
1221
+ @CallToAction(url: " https://example.com/sample.zip " , purpose: download)
1222
+ }
1223
+
1224
+ This is a page with a download button.
1225
+ """ ) ,
1226
+
1227
+ TextFile ( name: " TestBundle.md " , utf8Content: """
1228
+ # ``TestBundle``
1229
+
1230
+ This is a test.
1231
+
1232
+ ## Topics
1233
+
1234
+ ### Pages
1235
+
1236
+ - <doc:TechnologyX>
1237
+ - <doc:MySample>
1238
+ """ ) ,
1239
+
1240
+ // A symbol graph
1241
+ CopyOfFile ( original: Bundle . module. url ( forResource: " TopLevelCuration.symbols " , withExtension: " json " , subdirectory: " Test Resources " ) !) ,
1242
+
1243
+ InfoPlist ( displayName: " TestBundle " , identifier: " com.test.example " ) ,
1244
+ ] )
1245
+
1246
+ let testDataProvider = try TestFileSystem ( folders: [ bundle, Folder . emptyHTMLTemplateDirectory] )
1247
+ let targetDirectory = URL ( fileURLWithPath: testDataProvider. currentDirectoryPath)
1248
+ . appendingPathComponent ( " target " , isDirectory: true )
1249
+
1250
+ var action = try ConvertAction (
1251
+ documentationBundleURL: bundle. absoluteURL,
1252
+ outOfProcessResolver: nil ,
1253
+ analyze: false ,
1254
+ targetDirectory: targetDirectory,
1255
+ htmlTemplateDirectory: Folder . emptyHTMLTemplateDirectory. absoluteURL,
1256
+ emitDigest: true ,
1257
+ currentPlatforms: nil ,
1258
+ dataProvider: testDataProvider,
1259
+ fileManager: testDataProvider,
1260
+ temporaryDirectory: createTemporaryDirectory ( ) )
1261
+ let result = try action. perform ( logHandle: . standardOutput)
1262
+
1263
+ func contentsOfJSONFile< Result: Decodable > ( url: URL ) -> Result ? {
1264
+ guard let data = testDataProvider. contents ( atPath: url. path) else {
1265
+ return nil
1266
+ }
1267
+ return try ? JSONDecoder ( ) . decode ( Result . self, from: data)
1268
+ }
1269
+
1270
+ // Verify downloads
1271
+ guard let resultAssets: Digest . Assets = contentsOfJSONFile ( url: result. outputs [ 0 ] . appendingPathComponent ( " assets.json " ) ) else {
1272
+ XCTFail ( " Can't find assets.json in output " )
1273
+ return
1274
+ }
1275
+ XCTAssertEqual ( resultAssets. downloads. count, 1 )
1276
+
1277
+ XCTAssert ( resultAssets. downloads. contains ( where: {
1278
+ $0. identifier. identifier == " project.zip "
1279
+ } ) )
1280
+
1281
+ guard let externalAssets: Digest . ExternalAssets = contentsOfJSONFile ( url: result. outputs [ 0 ] . appendingPathComponent ( " external-assets.json " ) ) else {
1282
+ XCTFail ( " Can't find external-assets.json in output " )
1283
+ return
1284
+ }
1285
+ XCTAssertEqual ( externalAssets. externalLocations. count, 1 )
1286
+
1287
+ XCTAssert ( externalAssets. externalLocations. contains ( where: {
1288
+ $0. identifier. identifier == " https://example.com/sample.zip "
1289
+ } ) )
1290
+ }
1291
+
1162
1292
func testMetadataIsWrittenToOutputFolder( ) throws {
1163
1293
// Example documentation bundle that contains an image
1164
1294
let bundle = Folder ( name: " unit-test.docc " , content: [
0 commit comments