@@ -12,6 +12,7 @@ import XCTest
1212import Foundation
1313@testable import SwiftDocC
1414import SymbolKit
15+ import SwiftDocCTestUtilities
1516
1617class ConvertServiceTests : XCTestCase {
1718 private let testBundleInfo = DocumentationBundle . Info (
@@ -835,6 +836,177 @@ class ConvertServiceTests: XCTestCase {
835836 }
836837 }
837838
839+ func testConvertTutorialWithCode( ) throws {
840+ let tutorialContent = """
841+ @Tutorial(time: 99) {
842+ @Intro(title: " Tutorial Title " ) {
843+ Tutorial intro.
844+ }
845+ @Section(title: " Section title " ) {
846+ This section has one step with a code file reference.
847+
848+ @Steps {
849+ @Step {
850+ Start with this
851+
852+ @Code(name: " Something.swift " , file: before.swift)
853+ }
854+
855+ @Step {
856+ Add this
857+
858+ @Code(name: " Something.swift " , file: after.swift)
859+ }
860+ }
861+ }
862+ }
863+ """
864+
865+ let tempURL = try createTempFolder ( content: [
866+ Folder ( name: " TutorialWithCodeTest.docc " , content: [
867+ TextFile ( name: " Something.tutorial " , utf8Content: tutorialContent) ,
868+
869+ TextFile ( name: " before.swift " , utf8Content: """
870+ // This is an example swift file
871+ """ ) ,
872+ TextFile ( name: " after.swift " , utf8Content: """
873+ // This is an example swift file
874+ let something = 0
875+ """ ) ,
876+ ] )
877+ ] )
878+ let catalog = tempURL. appendingPathComponent ( " TutorialWithCodeTest.docc " )
879+
880+ let request = ConvertRequest (
881+ bundleInfo: testBundleInfo,
882+ externalIDsToConvert: nil ,
883+ documentPathsToConvert: nil ,
884+ bundleLocation: nil ,
885+ symbolGraphs: [ ] ,
886+ knownDisambiguatedSymbolPathComponents: nil ,
887+ markupFiles: [ ] ,
888+ tutorialFiles: [ tutorialContent. data ( using: . utf8) !] ,
889+ miscResourceURLs: [ ]
890+ )
891+
892+ let server = DocumentationServer ( )
893+
894+ let mockLinkResolvingService = LinkResolvingService { message in
895+ XCTAssertEqual ( message. type, " resolve-reference " )
896+ XCTAssert ( message. identifier. hasPrefix ( " SwiftDocC " ) )
897+ do {
898+ let payload = try XCTUnwrap ( message. payload)
899+ let request = try JSONDecoder ( )
900+ . decode (
901+ ConvertRequestContextWrapper< OutOfProcessReferenceResolver . Request> . self ,
902+ from: payload
903+ )
904+
905+ XCTAssertEqual ( request. convertRequestIdentifier, " test-identifier " )
906+
907+ switch request. payload {
908+ case . topic( let url) :
909+ XCTFail ( " Unexpected topic request: \( url. absoluteString. singleQuoted) " )
910+ // Fail to resolve every topic
911+ return DocumentationServer . Message (
912+ type: " resolve-reference-response " ,
913+ payload: try JSONEncoder ( ) . encode (
914+ OutOfProcessReferenceResolver . Response. errorMessage ( " Unexpected topic request " )
915+ )
916+ )
917+
918+ case . symbol( let preciseIdentifier) :
919+ XCTFail ( " Unexpected symbol request: \( preciseIdentifier) " )
920+ // Fail to resolve every symbol
921+ return DocumentationServer . Message (
922+ type: " resolve-reference-response " ,
923+ payload: try JSONEncoder ( ) . encode (
924+ OutOfProcessReferenceResolver . Response. errorMessage ( " Unexpected symbol request " )
925+ )
926+ )
927+
928+ case . asset( let assetReference) :
929+ print ( assetReference)
930+ switch ( assetReference. assetName, assetReference. bundleIdentifier) {
931+ case ( let assetName, " identifier " ) where [ " before.swift " , " after.swift " ] . contains ( assetName) :
932+ var asset = DataAsset ( )
933+ asset. register (
934+ catalog. appendingPathComponent ( assetName) ,
935+ with: DataTraitCollection ( )
936+ )
937+
938+ return DocumentationServer . Message (
939+ type: " resolve-reference-response " ,
940+ payload: try JSONEncoder ( ) . encode (
941+ OutOfProcessReferenceResolver . Response
942+ . asset ( asset)
943+ )
944+ )
945+
946+ default :
947+ XCTFail ( " Unexpected asset request: \( assetReference. assetName) " )
948+ // Fail to resolve all other assets
949+ return DocumentationServer . Message (
950+ type: " resolve-reference-response " ,
951+ payload: try JSONEncoder ( ) . encode (
952+ OutOfProcessReferenceResolver . Response. errorMessage ( " Unexpected topic request " )
953+ )
954+ )
955+ }
956+ }
957+ } catch {
958+ XCTFail ( error. localizedDescription)
959+ return nil
960+ }
961+ }
962+
963+ server. register ( service: mockLinkResolvingService)
964+
965+ try processAndAssert ( request: request, linkResolvingServer: server) { message in
966+ XCTAssertEqual ( message. type, " convert-response " )
967+ XCTAssertEqual ( message. identifier, " test-identifier-response " )
968+
969+ let response = try JSONDecoder ( ) . decode (
970+ ConvertResponse . self, from: XCTUnwrap ( message. payload)
971+ )
972+
973+ XCTAssertEqual ( response. renderNodes. count, 1 )
974+ let data = try XCTUnwrap ( response. renderNodes. first)
975+ let renderNode = try JSONDecoder ( ) . decode ( RenderNode . self, from: data)
976+
977+ let beforeIdentifier = RenderReferenceIdentifier ( " before.swift " )
978+ let afterIdentifier = RenderReferenceIdentifier ( " after.swift " )
979+
980+ XCTAssertEqual (
981+ renderNode. references [ " before.swift " ] as? FileReference ,
982+ FileReference ( identifier: beforeIdentifier, fileName: " Something.swift " , fileType: " swift " , syntax: " swift " , content: [
983+ " // This is an example swift file " ,
984+ ] , highlights: [ ] )
985+ )
986+ XCTAssertEqual (
987+ renderNode. references [ " after.swift " ] as? FileReference ,
988+ FileReference ( identifier: afterIdentifier, fileName: " Something.swift " , fileType: " swift " , syntax: " swift " , content: [
989+ " // This is an example swift file " ,
990+ " let something = 0 " ,
991+ ] , highlights: [ . init( line: 2 ) ] )
992+ )
993+
994+ let stepsSection = try XCTUnwrap ( renderNode. sections. compactMap { $0 as? TutorialSectionsRenderSection } . first? . tasks. first? . stepsSection)
995+ XCTAssertEqual ( stepsSection. count, 2 )
996+ if case . step( let step) = stepsSection. first {
997+ XCTAssertEqual ( step. code, beforeIdentifier)
998+ } else {
999+ XCTFail ( " Unexpected kind of step " )
1000+ }
1001+
1002+ if case . step( let step) = stepsSection. last {
1003+ XCTAssertEqual ( step. code, afterIdentifier)
1004+ } else {
1005+ XCTFail ( " Unexpected kind of step " )
1006+ }
1007+ }
1008+ }
1009+
8381010 func testConvertArticleWithImageReferencesAndDetailedGridLinks( ) throws {
8391011 let articleData = try XCTUnwrap ( """
8401012 # First article
0 commit comments