Файли
openidea/src/features/project-tree/roots.test.ts
T
l0ng-ai 046fd37064 fix(ui): Match PyCharm project view, matched tags and text weight
- Project widget initials follow IDEA's AvatarUtils.initials ("idea" → "I").
- "Show directories with changed descendants" is off by default, as in IDEA.
- FileEntry gains `excluded`: only excluded folders get the excluded icon and
  dimming; git-ignored ones keep the plain icon and the ignored colour.
- `.github` folders get IDEA's GitHub folder icon.
- Matched tag names are never bold and use their own background
  (MATCHED_TAG_NAME); matched braces are bold in dark schemes only.
- Revert Greyscale antialiasing to `antialiased` for UI and editor; `auto`
  rendered text heavier than PyCharm.

Claude-Session: https://claude.ai/code/session_01SaPPsVPuk6ZTNsoUCNCbMv
2026-10-24 22:56:48 +08:00

103 рядки
4.6 KiB
TypeScript
Неформатований Анотація Історія

Цей файл містить неоднозначні символи Юнікоду
Цей файл містить символи Юнікоду, які можна сплутати з іншими символами. Якщо ви вважаєте, що це зроблено навмисно, можете сміливо ігнорувати це попередження. Щоб показати їх, скористайтеся кнопкою Escape.
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import type { RootFolder } from "@/platform/languageSettings";
import { useProject } from "@/platform/project";
import { useProjectRoots } from "@/platform/projectRoots";
import type { MenuItem } from "@/ui";
import { newMenuItems } from "./contextMenu";
import { folderKind } from "./folderKind";
import { MemoryFs, setProjectFsForTests } from "./fs";
import { beginNewPackage, checkEditingName, commitEditing } from "./operations";
import { packageKindAt } from "./packages";
import { packageSegments } from "./paths";
import { initProjectTree, loadDir } from "./store";
const root = (path: string, kind: RootFolder["kind"], detectedFrom: string | null): RootFolder => ({
path,
kind,
detectedFrom,
});
const MAVEN: RootFolder[] = [
root("src/main/java", "source", "pom.xml"),
root("src/test/java", "test", "pom.xml"),
root("src/test/resources", "testResources", "pom.xml"),
root("target", "excluded", "pom.xml"),
];
describe("folder icons", () => {
it("follow detected and marked roots", () => {
const kind = (rel: string, excluded = false) => folderKind({ path: `/p/${rel}`, excluded }, MAVEN, "/p");
expect(kind("src/main/java")).toBe("source");
expect(kind("src/test/java")).toBe("test");
expect(kind("src/test/resources")).toBe("testResources");
expect(kind("target")).toBe("excluded");
expect(kind("src")).toBe("plain");
expect(kind("docs", true)).toBe("excluded");
expect(kind(".github")).toBe("github");
});
});
describe("New › Package", () => {
it("is offered inside JVM source roots and Python modules", () => {
const py = [root("py/src", "source", "py/pyproject.toml")];
expect(packageKindAt("src/main/java/com", MAVEN)).toBe("jvm");
expect(packageKindAt("src/test/java", MAVEN)).toBe("jvm");
expect(packageKindAt("src/test/resources", MAVEN)).toBeNull();
expect(packageKindAt("target", MAVEN)).toBeNull();
expect(packageKindAt("gen/kotlin/x", [root("gen/kotlin", "source", null)])).toBe("jvm");
expect(packageKindAt("py/src/app", py)).toBe("python");
expect(packageKindAt("py", py)).toBe("python");
expect(packageKindAt("web", py)).toBeNull();
// An unmarked Python root still leaves the module a Python module.
expect(packageKindAt("py/src", [], py)).toBe("python");
});
it("validates dotted package names", () => {
expect(packageSegments("com.acme.util", "jvm")).toEqual({ segments: ["com", "acme", "util"], error: null });
expect(packageSegments("com..x", "jvm").error).toMatch(/Not a valid package name/);
expect(packageSegments("com.class", "jvm").error).toMatch(/Not a valid package name/);
expect(packageSegments("my-app", "python").error).toMatch(/Not a valid package name/);
expect(packageSegments("lambda", "python").error).toMatch(/Not a valid package name/);
expect(packageSegments(" ", "python").error).toBe("Name cannot be empty");
});
});
describe("creating packages", () => {
let fs: MemoryFs;
beforeEach(() => {
fs = new MemoryFs({ "/p/src/main/java/App.java": "x", "/p/pkg/__init__.py": "" }, "/p");
setProjectFsForTests(fs, "/p");
initProjectTree("/p", "p");
useProject.setState({ project: { name: "p", root: "/p", isGit: false, settings: {} } as never, settings: {} as never });
useProjectRoots.setState({ root: "/p", detected: MAVEN });
});
afterEach(() => {
setProjectFsForTests(null);
initProjectTree(null);
useProject.setState({ project: null, settings: null });
useProjectRoots.setState({ root: null, detected: [] });
});
it("New menu shows Package instead of Directory in a Java source root", () => {
const labels = (items: MenuItem[]) => items.map((i) => ("label" in i ? i.label : "-"));
expect(labels(newMenuItems("/p/src/main/java")).slice(0, 2)).toEqual(["File", "Package"]);
expect(labels(newMenuItems("/p")).slice(0, 2)).toEqual(["File", "Directory"]);
});
it("a dotted JVM package creates nested folders", async () => {
await loadDir("/p/src/main/java");
await beginNewPackage("jvm", "/p/src/main/java");
expect(checkEditingName("com.class").error).toMatch(/Not a valid package name/);
expect(await commitEditing("com.acme")).toBe(true);
expect(fs.nodes.get("/p/src/main/java/com/acme")?.kind).toBe("dir");
});
it("a Python package gets an __init__.py in every new folder", async () => {
await loadDir("/p/pkg");
await beginNewPackage("python", "/p/pkg");
expect(await commitEditing("api.v1")).toBe(true);
expect(fs.nodes.has("/p/pkg/api/__init__.py")).toBe(true);
expect(fs.nodes.has("/p/pkg/api/v1/__init__.py")).toBe(true);
});
});