140 lines
5.8 KiB
Swift
140 lines
5.8 KiB
Swift
import Foundation
|
|
import SaplingCore
|
|
import SaplingWorkspace
|
|
import XCTest
|
|
|
|
final class WorkspaceManagerTests: XCTestCase {
|
|
private var temporaryRoots: [URL] = []
|
|
|
|
override func tearDownWithError() throws {
|
|
for url in temporaryRoots {
|
|
try? FileManager.default.removeItem(at: url)
|
|
}
|
|
temporaryRoots = []
|
|
}
|
|
|
|
func testOpenWorkspaceBuildsFilesystemTree() async throws {
|
|
let rootURL = try makeTemporaryWorkspace()
|
|
try createDirectory("Notes", in: rootURL)
|
|
try writeFile("Notes/Index.md", in: rootURL, contents: "# Notes")
|
|
try writeFile("Notes/todo.txt", in: rootURL, contents: "todo")
|
|
try createDirectory("Research/Archive", in: rootURL)
|
|
try writeFile("Research/Archive/Paper.markdown", in: rootURL, contents: "# Paper")
|
|
|
|
let workspace = try await LocalWorkspaceManager().openWorkspace(at: rootURL)
|
|
|
|
XCTAssertEqual(workspace.rootURL, rootURL)
|
|
XCTAssertEqual(workspace.items.map(\.displayName), ["Notes", "Research"])
|
|
|
|
let notes = try XCTUnwrap(workspace.folder(named: "Notes"))
|
|
XCTAssertEqual(notes.children.map(\.displayName), ["Index.md", "todo.txt"])
|
|
XCTAssertEqual(try XCTUnwrap(notes.file(named: "Index.md")).kind, .markdown)
|
|
XCTAssertEqual(try XCTUnwrap(notes.file(named: "todo.txt")).kind, .other)
|
|
|
|
let archive = try XCTUnwrap(workspace.folder(named: "Research")?.folder(named: "Archive"))
|
|
XCTAssertEqual(try XCTUnwrap(archive.file(named: "Paper.markdown")).kind, .markdown)
|
|
}
|
|
|
|
func testGitRepositoriesAreDetectedAsProjectsWithChildren() async throws {
|
|
let rootURL = try makeTemporaryWorkspace()
|
|
try createGitRepository("Sapling", in: rootURL)
|
|
try writeFile("Sapling/README.md", in: rootURL, contents: "# Sapling")
|
|
try createGitRepository("Research", in: rootURL)
|
|
try writeFile("Research/Notes.md", in: rootURL, contents: "# Research")
|
|
try createDirectory("Ordinary", in: rootURL)
|
|
|
|
let workspace = try await LocalWorkspaceManager().openWorkspace(at: rootURL)
|
|
|
|
XCTAssertEqual(workspace.items.map(\.displayName), ["Ordinary", "Research", "Sapling"])
|
|
let research = try XCTUnwrap(workspace.project(named: "Research"))
|
|
let sapling = try XCTUnwrap(workspace.project(named: "Sapling"))
|
|
XCTAssertEqual(research.gitRepository.statusSummary, .unknown)
|
|
XCTAssertEqual(sapling.gitRepository.rootURL.lastPathComponent, "Sapling")
|
|
XCTAssertEqual(research.children.map(\.displayName), ["Notes.md"])
|
|
XCTAssertNil(research.folder(named: ".git"))
|
|
}
|
|
|
|
func testHiddenFilesAndGitInternalsAreExcluded() async throws {
|
|
let rootURL = try makeTemporaryWorkspace()
|
|
try writeFile(".hidden.md", in: rootURL, contents: "# Hidden")
|
|
try createGitRepository("Project", in: rootURL)
|
|
try writeFile("Project/.git/config", in: rootURL, contents: "[core]")
|
|
try writeFile("Project/Visible.md", in: rootURL, contents: "# Visible")
|
|
|
|
let workspace = try await LocalWorkspaceManager().openWorkspace(at: rootURL)
|
|
|
|
XCTAssertEqual(workspace.items.map(\.displayName), ["Project"])
|
|
let project = try XCTUnwrap(workspace.project(named: "Project"))
|
|
XCTAssertEqual(project.children.map(\.displayName), ["Visible.md"])
|
|
}
|
|
|
|
private func makeTemporaryWorkspace() throws -> URL {
|
|
let url = FileManager.default.temporaryDirectory
|
|
.appendingPathComponent("SaplingWorkspaceTests-\(UUID().uuidString)", isDirectory: true)
|
|
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true)
|
|
temporaryRoots.append(url)
|
|
return url
|
|
}
|
|
|
|
private func createDirectory(_ path: String, in rootURL: URL) throws {
|
|
try FileManager.default.createDirectory(
|
|
at: rootURL.appendingPathComponent(path, isDirectory: true),
|
|
withIntermediateDirectories: true
|
|
)
|
|
}
|
|
|
|
private func createGitRepository(_ path: String, in rootURL: URL) throws {
|
|
try createDirectory(path, in: rootURL)
|
|
try createDirectory("\(path)/.git", in: rootURL)
|
|
}
|
|
|
|
private func writeFile(_ path: String, in rootURL: URL, contents: String) throws {
|
|
let url = rootURL.appendingPathComponent(path)
|
|
try FileManager.default.createDirectory(
|
|
at: url.deletingLastPathComponent(),
|
|
withIntermediateDirectories: true
|
|
)
|
|
try contents.write(to: url, atomically: true, encoding: .utf8)
|
|
}
|
|
}
|
|
|
|
private extension Workspace {
|
|
func folder(named name: String) -> WorkspaceFolder? {
|
|
items.compactMap { item -> WorkspaceFolder? in
|
|
guard case .folder(let folder) = item, folder.name == name else { return nil }
|
|
return folder
|
|
}.first
|
|
}
|
|
|
|
func project(named name: String) -> Project? {
|
|
items.compactMap { item -> Project? in
|
|
guard case .project(let project) = item, project.name == name else { return nil }
|
|
return project
|
|
}.first
|
|
}
|
|
}
|
|
|
|
private extension WorkspaceFolder {
|
|
func folder(named name: String) -> WorkspaceFolder? {
|
|
children.compactMap { item -> WorkspaceFolder? in
|
|
guard case .folder(let folder) = item, folder.name == name else { return nil }
|
|
return folder
|
|
}.first
|
|
}
|
|
|
|
func file(named name: String) -> WorkspaceFile? {
|
|
children.compactMap { item -> WorkspaceFile? in
|
|
guard case .file(let file) = item, file.name == name else { return nil }
|
|
return file
|
|
}.first
|
|
}
|
|
}
|
|
|
|
private extension Project {
|
|
func folder(named name: String) -> WorkspaceFolder? {
|
|
children.compactMap { item -> WorkspaceFolder? in
|
|
guard case .folder(let folder) = item, folder.name == name else { return nil }
|
|
return folder
|
|
}.first
|
|
}
|
|
}
|