Skip to content

Commit 0dc2467

Browse files
authored
test(e2e): add Tier 1 plan — copy file / relative path (#1032)
Adds an E2E plan covering the two clipboard commands contributed against the Java Projects view: - java.view.package.copyFilePath (Copy Path) - java.view.package.copyRelativeFilePath (Copy Relative Path) Both handlers (dependencyExplorer.ts:159 and :165) are thin wrappers that forward the selected DataNode's URI to VS Code's built-in copyFilePath / copyRelativeFilePath. They have no on-screen side effect whatsoever — the only observable consequence is what lands on the OS clipboard. Verifying them therefore requires the new clipboard primitives (writeClipboard / verifyClipboard) added in autotest 0.7.16. Plan shape - Setup: wait for LS, free sidebar space, collapse workspace root, focus Java Projects. - Reveal App.java via Quick Open (link-with-editor auto-expands the tree path), then click the tree row with the new `exact` modifier to disambiguate the leaf label "App" from the project node "my-app" (which would otherwise be matched first by case-insensitive substring and silently selected, producing the workspace folder URI instead of the file URI). - For each command: seed the clipboard with a sentinel, invoke the command by id, assert the clipboard contains "App.java", matches the expected path-suffix shape (cross-OS regex tolerating both `\` and `/` separators), and no longer equals the sentinel. Cross-OS note - VS Code's built-in `copyRelativeFilePath` computes `path.relative(workspaceFolderUri, fileUri)` and falls back to the absolute path when membership fails. On Windows the URI we pass (`Uri.parse(cmdNode.uri)` from JDT.LS) can differ in drive-letter case or percent-encoding from VS Code's registered workspace folder URI, so the membership test fails and the absolute path comes back. On POSIX the URIs match and the relative form is produced. The assertions tolerate both — they prove the command fired and overwrote the sentinel with a well-formed path ending in the expected layout, but do not require the leading-`src` shape that only POSIX produces. Coverage moves from ~33 → 35 of the ~39 user-facing Java Manager commands. Tier 2 (file-menu / file-explorer wrappers) and Tier 3 (gradle lifecycle, multi-module navigation) remain deferred.
1 parent 3858fdd commit 0dc2467

1 file changed

Lines changed: 195 additions & 0 deletions

File tree

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
# Test Plan: Java Dependency — Copy File / Relative Paths
2+
#
3+
# Covers two clipboard commands contributed against the Java Projects view:
4+
# - java.view.package.copyFilePath (Copy Path)
5+
# - java.view.package.copyRelativeFilePath (Copy Relative Path)
6+
#
7+
# Why a dedicated plan
8+
# ────────────────────
9+
# These two commands have **no on-screen side effect at all** — they don't
10+
# open a dialog, write a file, change the tree, or post a notification.
11+
# The only observable consequence is what ends up on the OS clipboard.
12+
# Verifying them therefore requires an autotest clipboard primitive
13+
# (writeClipboard / readClipboard / verifyClipboard) added in 0.7.15.
14+
#
15+
# Both handlers (dependencyExplorer.ts:159 and :165) are thin wrappers
16+
# around VS Code's built-in `copyFilePath` / `copyRelativeFilePath`:
17+
#
18+
# instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_COPY_FILE_PATH,
19+
# (node?: DataNode) => {
20+
# const cmdNode = getCmdNode(this._dependencyViewer.selection, node);
21+
# if (cmdNode?.uri) {
22+
# commands.executeCommand("copyFilePath", Uri.parse(cmdNode.uri));
23+
# }
24+
# })
25+
#
26+
# So the values landing on the clipboard are whatever VS Code's built-ins
27+
# write — i.e. the URI's fsPath (absolute, OS-native separators) and the
28+
# workspace-relative path (no leading slash).
29+
#
30+
# Invocation pattern (same as delete-permanent.yaml)
31+
# ──────────────────────────────────────────────────
32+
# Both commands accept a `node?: DataNode` parameter and fall back to
33+
# the current tree selection via getCmdNode (explorerCommands/utility.ts:38).
34+
# DataNode is a class instance, not a POJO, so passing a synthetic node
35+
# from YAML would crash. Selection fallback is the only viable smoke-test
36+
# path: open a file via link-with-editor (auto-selects in the tree) →
37+
# click the tree row to re-assert selection after focus changes →
38+
# invoke the command by id.
39+
#
40+
# Cross-OS path separator handling
41+
# ────────────────────────────────
42+
# Windows fsPaths use `\` and POSIX uses `/`. The assertions therefore
43+
# combine three orthogonal checks per command:
44+
# - `contains: "App.java"` — leaf filename, identical on every OS
45+
# - `matches: regex` — accepts both separators between segments
46+
# - `notContains: <sentinel>` — proves the clipboard was overwritten
47+
# (we seed a sentinel before each command)
48+
#
49+
# A pure `exact:` match would force a per-OS conditional plan; the regex
50+
# approach keeps a single plan that's portable Linux ↔ Windows ↔ macOS.
51+
#
52+
# Usage:
53+
# npx autotest run test/e2e-plans/java-dep-copy-paths.yaml --vsix <path-to-vsix>
54+
55+
name: "Java Dependency — Copy File / Relative Paths"
56+
description: |
57+
Exercises java.view.package.copyFilePath and java.view.package.copyRelativeFilePath
58+
on a Maven-project source file. Seeds a clipboard sentinel before each command,
59+
invokes the command by id (using the current tree selection), and verifies the
60+
resulting clipboard text via path-shape regex + filename containment +
61+
sentinel-overwritten check.
62+
63+
setup:
64+
extension: "redhat.java"
65+
vscodeVersion: "stable"
66+
workspace: "../maven"
67+
timeout: 180
68+
settings:
69+
java.configuration.checkProjectSettingsExclusions: false
70+
workbench.startupEditor: "none"
71+
72+
steps:
73+
# ── Setup: wait for LS, free sidebar space, focus Java Projects ──
74+
- id: "ls-ready"
75+
action: "waitForLanguageServer"
76+
# No `verify:` — `waitForLanguageServer` is itself the deterministic
77+
# readiness check. The AFTER screenshot may transiently show
78+
# "Java: Building - 0%" which a strict LLM mis-reads as a failure.
79+
timeout: 180
80+
81+
- id: "close-aux-bar"
82+
action: "executeVSCodeCommand workbench.action.closeAuxiliaryBar"
83+
84+
- id: "collapse-outline"
85+
action: "collapseSidebarSection OUTLINE"
86+
87+
- id: "collapse-timeline"
88+
action: "collapseSidebarSection TIMELINE"
89+
90+
- id: "collapse-workspace-root"
91+
action: "collapseWorkspaceRoot"
92+
93+
- id: "focus-java-projects"
94+
action: "executeVSCodeCommand javaProjectExplorer.focus"
95+
96+
- id: "wait-tree-load"
97+
action: "wait 3 seconds"
98+
99+
# ── Reveal & select App.java via link-with-editor ──
100+
# Same pattern as java-dep-delete-permanent.yaml: opening the file
101+
# makes link-with-editor reveal+select the tree node deterministically,
102+
# which is more reliable than chained expandTreeItem on the virtualised
103+
# tree on 1024x768 CI displays.
104+
- id: "open-target-file"
105+
action: "open file App.java"
106+
waitBefore: 2
107+
108+
- id: "collapse-workspace-root-2"
109+
action: "collapseWorkspaceRoot"
110+
111+
- id: "focus-java-projects-2"
112+
action: "executeVSCodeCommand javaProjectExplorer.focus"
113+
waitBefore: 2
114+
115+
# Click the App tree row to assert it as the active selection. The Java
116+
# Projects view labels source files by class name (no `.java` suffix —
117+
# the leaf row reads "App"), and a default substring `click App tree
118+
# item` would also match the project node "my-app" first (case-insensitive
119+
# substring), silently selecting the project — whose URI is the workspace
120+
# root, not the file. We use the `exact` modifier (autotest ≥ 0.7.16) so
121+
# only the leaf row labeled exactly "App" matches.
122+
- id: "select-app"
123+
action: "click App tree item exact"
124+
waitBefore: 1
125+
126+
# ── Cycle 1: java.view.package.copyFilePath (absolute path) ──
127+
# Sentinel proves the clipboard was actually written — without it, a
128+
# silently-no-op command would pass if the OS clipboard happened to
129+
# already contain "App.java" from any earlier action on the host.
130+
- id: "seed-clipboard-absolute"
131+
action: "writeClipboard __SENTINEL_BEFORE_COPY_FILE_PATH__"
132+
133+
- id: "invoke-copy-file-path"
134+
action: "executeVSCodeCommand java.view.package.copyFilePath"
135+
waitBefore: 1
136+
137+
# Verify the clipboard contents post-action.
138+
#
139+
# • `contains: "App.java"` — the leaf filename is identical on every OS
140+
# • `matches: ...` — accepts either `\` (Windows) or `/` (POSIX) between
141+
# path segments, and asserts the URL-decoded fsPath structure
142+
# `maven/src/main/java/com/mycompany/app/App.java`. The `[\\\\/]`
143+
# escapes to a literal `[\/]` character class in the compiled regex.
144+
# • `notContains: <sentinel>` — proves the seed was overwritten and the
145+
# command isn't silently no-op'ing into a stale clipboard.
146+
- id: "verify-absolute-path"
147+
action: "wait 1 seconds"
148+
verifyClipboard:
149+
contains: "App.java"
150+
matches: "maven[\\\\/]src[\\\\/]main[\\\\/]java[\\\\/]com[\\\\/]mycompany[\\\\/]app[\\\\/]App\\.java$"
151+
notContains: "__SENTINEL_BEFORE_COPY_FILE_PATH__"
152+
timeout: 10
153+
154+
# ── Cycle 2: java.view.package.copyRelativeFilePath ──
155+
# The selection persists across the previous command, so no re-click.
156+
# A fresh sentinel is still needed — the cycle-1 clipboard now contains
157+
# the absolute path, which would trivially satisfy any leaf-only check.
158+
#
159+
# Cross-platform note: VS Code's built-in `copyRelativeFilePath` computes
160+
# `path.relative(workspaceFolderUri, fileUri)` and falls back to the
161+
# absolute fsPath when the file URI isn't a member of any workspace
162+
# folder. On Windows the URI we pass — `Uri.parse(cmdNode.uri)` from
163+
# JDT.LS — can differ from VS Code's registered workspace folder URI
164+
# in drive-letter case or percent-encoding, so the membership test
165+
# fails and we get the absolute path back. On POSIX the URIs match and
166+
# the relative form is produced. The assertions below tolerate both:
167+
# they prove the command fired and overwrote the sentinel with a
168+
# well-formed path ending in the expected package + class layout, but
169+
# do not require the leading-`src` shape that only POSIX produces.
170+
- id: "seed-clipboard-relative"
171+
action: "writeClipboard __SENTINEL_BEFORE_COPY_RELATIVE_FILE_PATH__"
172+
173+
- id: "invoke-copy-relative-file-path"
174+
action: "executeVSCodeCommand java.view.package.copyRelativeFilePath"
175+
waitBefore: 1
176+
177+
# Verify the clipboard after copyRelativeFilePath.
178+
#
179+
# • `contains: "App.java"` — leaf filename appears (OS-independent)
180+
# • `matches: ...` — same path-suffix shape as the absolute assertion
181+
# above. Anchored to `$` so it matches whether the path is the
182+
# POSIX relative form `src/main/java/.../App.java` (single match
183+
# of the suffix) or the Windows absolute fallback
184+
# `C:\...\maven\src\main\java\.../App.java` (suffix at end).
185+
# • `notContains: <sentinel>` — proves the seed was overwritten,
186+
# which is the strongest signal that the wrapper command actually
187+
# forwarded to the built-in (rather than silently no-op'ing on a
188+
# missing selection).
189+
- id: "verify-relative-path"
190+
action: "wait 1 seconds"
191+
verifyClipboard:
192+
contains: "App.java"
193+
matches: "src[\\\\/]main[\\\\/]java[\\\\/]com[\\\\/]mycompany[\\\\/]app[\\\\/]App\\.java$"
194+
notContains: "__SENTINEL_BEFORE_COPY_RELATIVE_FILE_PATH__"
195+
timeout: 10

0 commit comments

Comments
 (0)