Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.

Commit 49ce9c6

Browse files
authored
Merge branch 'master' into extension-exposing-bug
2 parents 9a8ee7b + 006dddc commit 49ce9c6

File tree

14 files changed

+243
-29
lines changed

14 files changed

+243
-29
lines changed

.github/workflows/ci.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,12 @@ jobs:
2525
key: ${{ runner.os }}-spm-xcode-${{ matrix.xcode }}-${{ hashFiles('**/Package.resolved') }}
2626
restore-keys: |
2727
${{ runner.os }}-spm-xcode-${{ matrix.xcode }}-
28+
- name: Install System Dependencies
29+
run: |
30+
brew install graphviz
2831
- name: Build and Test
29-
run: swift test -c release
32+
run: |
33+
swift test -c release
3034
env:
3135
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer
3236

@@ -52,6 +56,6 @@ jobs:
5256
- name: Install System Dependencies
5357
run: |
5458
apt-get update
55-
apt-get install -y libxml2-dev
59+
apt-get install -y libxml2-dev graphviz
5660
- name: Build and Test
5761
run: swift test -c release --enable-test-discovery

.node/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"not dead"
66
],
77
"scripts": {
8-
"watch": "postcss -w ../Assets/**/*.css -o ../Sources/swift-doc/Resources/all.min.css --config ./postcss.config.js"
8+
"watch": "postcss -w ../Assets/**/*.css -o ../Resources/all.min.css --config ./postcss.config.js"
99
},
1010
"dependencies": {
1111
"cssnano": "^4.1.10",

Changelog.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Added end-to-end tests for command-line interface.
13+
#199 by @MaxDesiatov and @mattt.
14+
1015
### Fixed
1116

1217
- Fixed public extensions exposing nested code of all access levels.
@@ -36,8 +41,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3641

3742
- Changed GitHub Action to use prebuilt Docker image.
3843
#185 by @mattt and @MaxDesiatov.
39-
- Changed build command to load CSS from package resource when available.
40-
#192 by @mattt.
4144

4245
## [1.0.0-beta.4] - 2020-07-31
4346

Package.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import PackageDescription
55

66
let package = Package(
77
name: "swift-doc",
8+
platforms: [
9+
.macOS(.v10_13)
10+
],
811
products: [
912
.executable(name: "swift-doc", targets: ["swift-doc"]),
1013
.library(name: "SwiftDoc", targets: ["SwiftDoc"])
@@ -40,9 +43,6 @@ let package = Package(
4043
.product(name: "SwiftSyntaxHighlighter", package: "SwiftSyntaxHighlighter"),
4144
.product(name: "Logging", package: "swift-log"),
4245
.product(name: "LoggingGitHubActions", package: "LoggingGitHubActions")
43-
],
44-
resources: [
45-
.copy("Resources")
4646
]
4747
),
4848
.target(
@@ -66,5 +66,11 @@ let package = Package(
6666
.product(name: "SwiftMarkup", package: "SwiftMarkup")
6767
]
6868
),
69+
.testTarget(
70+
name: "EndToEndTests",
71+
dependencies: [
72+
.target(name: "swift-doc"),
73+
]
74+
),
6975
]
7076
)

Package@swift-5.2.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,11 @@ let package = Package(
4141
name: "SwiftDocTests",
4242
dependencies: ["SwiftDoc", "SwiftSyntax", "SwiftSemantics", "SwiftMarkup"]
4343
),
44+
.testTarget(
45+
name: "EndToEndTests",
46+
dependencies: [
47+
.target(name: "swift-doc"),
48+
]
49+
),
4450
]
4551
)
File renamed without changes.

Sources/SwiftDoc/SourceFile.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public struct SourceFile: Hashable, Codable {
4545
sourceLocationConverter = SourceLocationConverter(file: url.path(relativeTo: directory), tree: tree)
4646
super.init()
4747

48-
walk(tree)
48+
_ = walk(tree)
4949

5050
assert(context.isEmpty)
5151
}

Sources/swift-doc/Subcommands/Generate.swift

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -120,26 +120,9 @@ extension SwiftDoc {
120120
}
121121

122122
if case .html = format {
123-
let destinationURL = outputDirectoryURL.appendingPathComponent("all.css")
124-
125-
func fetchRemoteCSS() throws -> Data {
126-
let url = URL(string: "https://raw.githubusercontent.com/SwiftDocOrg/swift-doc/master/Resources/all.min.css")!
127-
return try Data(contentsOf: url)
128-
}
129-
130-
#if swift(>=5.3)
131-
if let resourceURL = Bundle.module.url(forResource: "all.min", withExtension: "css") {
132-
if !fileManager.fileExists(atPath: destinationURL.path) {
133-
try fileManager.copyItem(at: resourceURL, to: destinationURL)
134-
}
135-
} else {
136-
let cssData = try fetchRemoteCSS()
137-
try writeFile(cssData, to: destinationURL)
138-
}
139-
#else
140-
let cssData = try fetchRemoteCSS()
141-
try writeFile(cssData, to: destinationURL)
142-
#endif
123+
let cssData = try fetchRemoteCSS()
124+
let cssURL = outputDirectoryURL.appendingPathComponent("all.css")
125+
try writeFile(cssData, to: cssURL)
143126
}
144127

145128
} catch {
@@ -148,3 +131,8 @@ extension SwiftDoc {
148131
}
149132
}
150133
}
134+
135+
func fetchRemoteCSS() throws -> Data {
136+
let url = URL(string: "https://raw.githubusercontent.com/SwiftDocOrg/swift-doc/master/Resources/all.min.css")!
137+
return try Data(contentsOf: url)
138+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import XCTest
2+
3+
final class CoverageSubcommandTests: XCTestCase {
4+
func testStandardOutput() throws {
5+
let command = Bundle.productsDirectory.appendingPathComponent("swift-doc")
6+
7+
let outputDirectory = try temporaryDirectory()
8+
defer { try? FileManager.default.removeItem(at: outputDirectory) }
9+
10+
try Process.run(command: command,
11+
arguments: [
12+
"coverage",
13+
"Sources"
14+
]
15+
) { result in
16+
XCTAssertEqual(result.terminationStatus, EXIT_SUCCESS)
17+
XCTAssertEqual(result.output?.starts(with: "Total"), true)
18+
XCTAssertEqual(result.error, "")
19+
}
20+
}
21+
22+
func testFileOutput() throws {
23+
let command = Bundle.productsDirectory.appendingPathComponent("swift-doc")
24+
25+
let outputDirectory = try temporaryDirectory()
26+
let outputFile = outputDirectory.appendingPathComponent("report.json")
27+
defer { try? FileManager.default.removeItem(at: outputDirectory) }
28+
29+
try Process.run(command: command,
30+
arguments: [
31+
"coverage",
32+
"--output", outputFile.path,
33+
"Sources"
34+
]
35+
) { result in
36+
XCTAssertEqual(result.terminationStatus, EXIT_SUCCESS)
37+
XCTAssertEqual(result.output, "")
38+
XCTAssertEqual(result.error, "")
39+
40+
do {
41+
let data = try Data(contentsOf: outputFile)
42+
let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
43+
XCTAssertEqual(json?["type"] as? String, "org.dcov.report.json.export")
44+
}
45+
}
46+
}
47+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import XCTest
2+
3+
final class DiagramSubcommandTests: XCTestCase {
4+
func testStandardOutput() throws {
5+
let command = Bundle.productsDirectory.appendingPathComponent("swift-doc")
6+
7+
let outputDirectory = try temporaryDirectory()
8+
defer { try? FileManager.default.removeItem(at: outputDirectory) }
9+
10+
try Process.run(command: command,
11+
arguments: [
12+
"diagram",
13+
"Sources"
14+
]
15+
) { result in
16+
XCTAssertEqual(result.terminationStatus, EXIT_SUCCESS)
17+
XCTAssertEqual(result.output?.starts(with: "digraph {"), true)
18+
XCTAssertEqual(result.error, "")
19+
}
20+
}
21+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import XCTest
2+
3+
final class GenerateSubcommandTests: XCTestCase {
4+
func testCommonMark() throws {
5+
let command = Bundle.productsDirectory.appendingPathComponent("swift-doc")
6+
7+
let outputDirectory = try temporaryDirectory()
8+
defer { try? FileManager.default.removeItem(at: outputDirectory) }
9+
10+
try Process.run(command: command,
11+
arguments: [
12+
"generate",
13+
"--module-name", "SwiftDoc",
14+
"--format", "commonmark",
15+
"--output", outputDirectory.path,
16+
"Sources"
17+
]
18+
) { result in
19+
XCTAssertEqual(result.terminationStatus, EXIT_SUCCESS)
20+
XCTAssertEqual(result.output, "")
21+
XCTAssertEqual(result.error, "")
22+
23+
do {
24+
let commonmark = try String(contentsOf: outputDirectory.appendingPathComponent("Home.md"))
25+
XCTAssertTrue(commonmark.contains("# Types"))
26+
}
27+
28+
do {
29+
let commonmark = try String(contentsOf: outputDirectory.appendingPathComponent("_Sidebar.md"))
30+
XCTAssertTrue(commonmark.contains("<summary>Types</summary>"))
31+
}
32+
33+
do {
34+
let commonmark = try String(contentsOf: outputDirectory.appendingPathComponent("_Footer.md"))
35+
XCTAssertTrue(commonmark.contains("[swift-doc](https://github.com/SwiftDocOrg/swift-doc)"))
36+
}
37+
38+
do {
39+
let contents = try FileManager.default.contentsOfDirectory(at: outputDirectory, includingPropertiesForKeys: [.isDirectoryKey], options: [.skipsHiddenFiles])
40+
let subdirectories = try contents.filter { try $0.resourceValues(forKeys: [.isDirectoryKey]).isDirectory == true }
41+
XCTAssertEqual(subdirectories.count, 0, "output should not contain any subdirectories")
42+
}
43+
}
44+
}
45+
46+
func testHTML() throws {
47+
let command = Bundle.productsDirectory.appendingPathComponent("swift-doc")
48+
let outputDirectory = try temporaryDirectory()
49+
50+
defer { try? FileManager.default.removeItem(at: outputDirectory) }
51+
try Process.run(command: command,
52+
arguments: [
53+
"generate",
54+
"--module-name", "SwiftDoc",
55+
"--format", "html",
56+
"--output", outputDirectory.path,
57+
"Sources"
58+
]
59+
) { result in
60+
XCTAssertEqual(result.terminationStatus, EXIT_SUCCESS)
61+
XCTAssertEqual(result.output, "")
62+
XCTAssertEqual(result.error, "")
63+
64+
do {
65+
let html = try String(contentsOf: outputDirectory.appendingPathComponent("index.html"))
66+
XCTAssertTrue(html.contains("<!DOCTYPE html>"))
67+
}
68+
69+
do {
70+
let css = try String(contentsOf: outputDirectory.appendingPathComponent("all.css"))
71+
XCTAssertTrue(css.contains(":root"))
72+
}
73+
74+
do {
75+
let contents = try FileManager.default.contentsOfDirectory(at: outputDirectory, includingPropertiesForKeys: [.isDirectoryKey], options: [.skipsHiddenFiles])
76+
let subdirectories = try contents.filter { try $0.resourceValues(forKeys: [.isDirectoryKey]).isDirectory == true }
77+
.filter { FileManager.default.fileExists(atPath: $0.appendingPathComponent("index.html").path) }
78+
XCTAssertGreaterThanOrEqual(subdirectories.count, 1, "output should contain one or more subdirectories containing index.html")
79+
}
80+
}
81+
}
82+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import Foundation
2+
3+
extension Bundle {
4+
static var productsDirectory: URL = {
5+
#if os(macOS)
6+
for bundle in Bundle.allBundles where bundle.bundlePath.hasSuffix(".xctest") {
7+
return bundle.bundleURL.deletingLastPathComponent()
8+
}
9+
fatalError("couldn't find the products directory")
10+
#else
11+
return Bundle.main.bundleURL
12+
#endif
13+
}()
14+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import Foundation
2+
3+
extension Process {
4+
typealias Result = (terminationStatus: Int32, output: String?, error: String?)
5+
6+
static func run(command executableURL: URL, arguments: [String] = [], completion: (Result) throws -> Void) throws {
7+
let process = Process()
8+
if #available(OSX 10.13, *) {
9+
process.executableURL = executableURL
10+
} else {
11+
process.launchPath = executableURL.path
12+
}
13+
process.arguments = arguments
14+
15+
let standardOutput = Pipe()
16+
process.standardOutput = standardOutput
17+
18+
let standardError = Pipe()
19+
process.standardError = standardError
20+
21+
if #available(OSX 10.13, *) {
22+
try process.run()
23+
} else {
24+
process.launch()
25+
}
26+
process.waitUntilExit()
27+
28+
let output = String(data: standardOutput.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8)
29+
let error = String(data: standardError.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8)
30+
31+
try completion((numericCast(process.terminationStatus), output, error))
32+
}
33+
34+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import Foundation
2+
3+
func temporaryDirectory() throws -> URL {
4+
let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString)
5+
try FileManager.default.createDirectory(at: temporaryDirectoryURL, withIntermediateDirectories: true)
6+
7+
return temporaryDirectoryURL
8+
}
9+

0 commit comments

Comments
 (0)