Skip to content

Commit f4d6bb0

Browse files
authored
Package dependency view tests (#1117)
* Remove some ununused private functions * Integration tests for package dependencies view Issue: #1113 * Unit tests for converting FileNode and PackageNode to tree items * Don't run integration tests against 5.6 * Confirmed in swift repo that workspace-state.json was not introduced until 5.7 * Address review comments
1 parent 862c67f commit f4d6bb0

File tree

5 files changed

+203
-73
lines changed

5 files changed

+203
-73
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// swift-tools-version:5.6
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "dependencies",
8+
dependencies: [
9+
.package(url: "https://github.com/swiftlang/swift-markdown.git", branch: "main"),
10+
.package(path: "../defaultPackage"),
11+
],
12+
targets: [
13+
.executableTarget(
14+
name: "dependencies",
15+
dependencies: [],
16+
path: "Sources"),
17+
]
18+
)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
print("dependencies")

src/ui/PackageDependencyProvider.ts

Lines changed: 2 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export class PackageNode {
6969
/**
7070
* A file or directory in the Package Dependencies {@link vscode.TreeView TreeView}.
7171
*/
72-
class FileNode {
72+
export class FileNode {
7373
constructor(
7474
public name: string,
7575
public path: string,
@@ -257,7 +257,7 @@ export class PackageDependenciesProvider implements vscode.TreeDataProvider<Tree
257257
const workspacePath = folderContext.folder.fsPath;
258258

259259
const showingDependencies: Set<string> = new Set<string>();
260-
const stack: Dependency[] = rootDependencies;
260+
const stack: Dependency[] = rootDependencies.slice();
261261

262262
while (stack.length > 0) {
263263
const top = stack.pop();
@@ -293,77 +293,6 @@ export class PackageDependenciesProvider implements vscode.TreeDataProvider<Tree
293293
return showingDependencies;
294294
}
295295

296-
/**
297-
* Returns a {@link PackageNode} for every local dependency
298-
* declared in **Package.swift**.
299-
*/
300-
private getLocalDependencies(workspaceState: WorkspaceState | undefined): PackageNode[] {
301-
return (
302-
workspaceState?.object.dependencies
303-
.filter(item => {
304-
// need to check for both "local" and "fileSystem" as swift 5.5 and earlier
305-
// use "local" while 5.6 and later use "fileSystem"
306-
return (
307-
(item.packageRef.kind === "local" ||
308-
item.packageRef.kind === "fileSystem") &&
309-
item.packageRef.location
310-
);
311-
})
312-
.map(
313-
dependency =>
314-
new PackageNode(
315-
dependency.packageRef.identity,
316-
dependency.packageRef.location,
317-
dependency.packageRef.location,
318-
"local",
319-
"local"
320-
)
321-
) ?? []
322-
);
323-
}
324-
325-
/**
326-
* Returns a {@link PackageNode} for every remote dependency.
327-
*/
328-
private getRemoteDependencies(folderContext: FolderContext): PackageNode[] {
329-
return (
330-
folderContext.swiftPackage.resolved?.pins.map(
331-
pin =>
332-
new PackageNode(
333-
pin.identity,
334-
pin.location,
335-
pin.location,
336-
pin.state.version ?? pin.state.branch ?? pin.state.revision.substring(0, 7),
337-
"remote"
338-
)
339-
) ?? []
340-
);
341-
}
342-
343-
/**
344-
* Return list of package dependencies in edit mode
345-
* @param folderContext Folder to get edited dependencies for
346-
* @returns Array of packages
347-
*/
348-
private getEditedDependencies(workspaceState: WorkspaceState | undefined): PackageNode[] {
349-
return (
350-
workspaceState?.object.dependencies
351-
.filter(item => {
352-
return item.state.name === "edited" && item.state.path;
353-
})
354-
.map(
355-
item =>
356-
new PackageNode(
357-
item.packageRef.identity,
358-
item.state.path!,
359-
item.state.path!,
360-
"local",
361-
"editing"
362-
)
363-
) ?? []
364-
);
365-
}
366-
367296
/**
368297
* Returns a {@link FileNode} for every file or subdirectory
369298
* in the given directory.
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the VS Code Swift open source project
4+
//
5+
// Copyright (c) 2024 the VS Code Swift project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of VS Code Swift project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import { expect } from "chai";
16+
import {
17+
PackageDependenciesProvider,
18+
PackageNode,
19+
} from "../../../src/ui/PackageDependencyProvider";
20+
import { folderContextPromise, globalWorkspaceContextPromise } from "../extension.test";
21+
import { executeTaskAndWaitForResult, waitForNoRunningTasks } from "../../utilities";
22+
import { getBuildAllTask, SwiftTask } from "../../../src/tasks/SwiftTaskProvider";
23+
import { testAssetPath } from "../../fixtures";
24+
import { Version } from "../../../src/utilities/version";
25+
26+
suite("PackageDependencyProvider Test Suite", function () {
27+
let treeProvider: PackageDependenciesProvider;
28+
this.timeout(2 * 60 * 1000); // Allow up to 2 minutes to build
29+
30+
suiteSetup(async function () {
31+
const workspaceContext = await globalWorkspaceContextPromise;
32+
// workspace-state.json was not introduced until swift 5.7
33+
if (workspaceContext.toolchain.swiftVersion.isLessThan(new Version(5, 7, 0))) {
34+
this.skip();
35+
}
36+
await waitForNoRunningTasks();
37+
const folderContext = await folderContextPromise("dependencies");
38+
await executeTaskAndWaitForResult((await getBuildAllTask(folderContext)) as SwiftTask);
39+
await workspaceContext.focusFolder(folderContext);
40+
treeProvider = new PackageDependenciesProvider(workspaceContext);
41+
});
42+
43+
suiteTeardown(() => {
44+
treeProvider?.dispose();
45+
});
46+
47+
test("Includes remote dependency", async () => {
48+
const items = await treeProvider.getChildren();
49+
50+
const dep = items.find(n => n.name === "swift-markdown") as PackageNode;
51+
expect(dep).to.not.be.undefined;
52+
expect(dep?.location).to.equal("https://github.com/swiftlang/swift-markdown.git");
53+
expect(dep?.path).to.equal(
54+
`${testAssetPath("dependencies")}/.build/checkouts/swift-markdown`
55+
);
56+
});
57+
58+
test("Includes local dependency", async () => {
59+
const items = await treeProvider.getChildren();
60+
61+
const dep = items.find(n => n.name === "defaultpackage") as PackageNode;
62+
expect(dep).to.not.be.undefined;
63+
expect(dep?.location).to.equal(testAssetPath("defaultPackage"));
64+
expect(dep?.path).to.equal(testAssetPath("defaultPackage"));
65+
});
66+
67+
test("Lists local dependency file structure", async () => {
68+
const items = await treeProvider.getChildren();
69+
70+
const dep = items.find(n => n.name === "defaultpackage") as PackageNode;
71+
expect(dep).to.not.be.undefined;
72+
73+
const folders = await treeProvider.getChildren(dep);
74+
const folder = folders.find(n => n.name === "Sources");
75+
expect(folder).to.not.be.undefined;
76+
77+
expect(folder?.path).to.equal(`${testAssetPath("defaultPackage")}/Sources`);
78+
79+
const childFolders = await treeProvider.getChildren(folder);
80+
const childFolder = childFolders.find(n => n.name === "PackageExe");
81+
expect(childFolder).to.not.be.undefined;
82+
83+
expect(childFolder?.path).to.equal(`${testAssetPath("defaultPackage")}/Sources/PackageExe`);
84+
85+
const files = await treeProvider.getChildren(childFolder);
86+
const file = files.find(n => n.name === "main.swift");
87+
expect(file).to.not.be.undefined;
88+
89+
expect(file?.path).to.equal(
90+
`${testAssetPath("defaultPackage")}/Sources/PackageExe/main.swift`
91+
);
92+
});
93+
94+
test("Lists remote dependency file structure", async () => {
95+
const items = await treeProvider.getChildren();
96+
97+
const dep = items.find(n => n.name === "swift-markdown") as PackageNode;
98+
expect(dep).to.not.be.undefined;
99+
100+
const folders = await treeProvider.getChildren(dep);
101+
const folder = folders.find(n => n.name === "Sources");
102+
expect(folder).to.not.be.undefined;
103+
104+
const path = `${testAssetPath("dependencies")}/.build/checkouts/swift-markdown`;
105+
expect(folder?.path).to.equal(`${path}/Sources`);
106+
107+
const childFolders = await treeProvider.getChildren(folder);
108+
const childFolder = childFolders.find(n => n.name === "CAtomic");
109+
expect(childFolder).to.not.be.undefined;
110+
111+
expect(childFolder?.path).to.equal(`${path}/Sources/CAtomic`);
112+
113+
const files = await treeProvider.getChildren(childFolder);
114+
const file = files.find(n => n.name === "CAtomic.c");
115+
expect(file).to.not.be.undefined;
116+
117+
expect(file?.path).to.equal(`${path}/Sources/CAtomic/CAtomic.c`);
118+
});
119+
});
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the VS Code Swift open source project
4+
//
5+
// Copyright (c) 2024 the VS Code Swift project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of VS Code Swift project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import { expect } from "chai";
16+
import * as vscode from "vscode";
17+
import { FileNode, PackageNode } from "../../../src/ui/PackageDependencyProvider";
18+
19+
suite("PackageDependencyProvider Unit Test Suite", function () {
20+
suite("FileNode", () => {
21+
test("can create a VSCode TreeItem that opens a file", () => {
22+
const node = new FileNode("Foo", "/path/to/Foo", false);
23+
const item = node.toTreeItem();
24+
25+
const expectedUri = vscode.Uri.file("/path/to/Foo");
26+
expect(item.label).to.equal("Foo");
27+
expect(item.resourceUri).to.deep.equal(expectedUri);
28+
expect(item.command).to.deep.equal({
29+
command: "vscode.open",
30+
arguments: [expectedUri],
31+
title: "Open File",
32+
});
33+
});
34+
35+
test("can create a VSCode TreeItem that represents a directory", () => {
36+
const node = new FileNode("Foo", "/path/to/Foo", true);
37+
const item = node.toTreeItem();
38+
39+
const expectedUri = vscode.Uri.file("/path/to/Foo");
40+
expect(item.label).to.equal("Foo");
41+
expect(item.resourceUri).to.deep.equal(expectedUri);
42+
expect(item.command).to.be.undefined;
43+
});
44+
});
45+
46+
suite("PackageNode", () => {
47+
test("can create a VSCode TreeItem that represents a Swift package", () => {
48+
const node = new PackageNode(
49+
"SwiftMarkdown",
50+
"/path/to/.build/swift-markdown",
51+
"https://github.com/swiftlang/swift-markdown.git",
52+
"1.2.3",
53+
"remote"
54+
);
55+
const item = node.toTreeItem();
56+
57+
expect(item.label).to.equal("SwiftMarkdown");
58+
expect(item.description).to.deep.equal("1.2.3");
59+
expect(item.command).to.be.undefined;
60+
});
61+
});
62+
});

0 commit comments

Comments
 (0)