|
| 1 | +# Test Plan: Java Dependency — Export Jar |
| 2 | +# |
| 3 | +# Covers java.view.package.exportJar — the multi-step wizard that builds a |
| 4 | +# runnable jar from a Java project. The command is contributed both as the |
| 5 | +# title-bar `$(export)` icon on the JAVA PROJECTS workspace-root node |
| 6 | +# (package.json:858-861, group=inline) and as a context-menu entry, but we |
| 7 | +# invoke it directly by id: the inline icon is rendered against the |
| 8 | +# `java:workspace` viewItem (not the Maven project node `my-app`), which |
| 9 | +# is fragile to locate by name, and ResolveJavaProject auto-resolves when |
| 10 | +# there's exactly one project in the workspace — so direct invocation |
| 11 | +# bypasses one wizard step that's not the command's responsibility. |
| 12 | +# |
| 13 | +# Wizard step machine (BuildArtifactTaskProvider.ts:284 `createJarFile`): |
| 14 | +# 1. ResolveJavaProject → auto when single-project; quick-pick otherwise |
| 15 | +# 2. ResolveMainClass → quick-pick of main classes + "<without main class>" |
| 16 | +# 3. GenerateJar |
| 17 | +# a. generateClasspaths → multi-select quick-pick if >1 dependency item |
| 18 | +# b. showSaveDialog → only if outputPath === "" (skipped when |
| 19 | +# java.project.exportJar.targetPath is set |
| 20 | +# to a non-empty value; we set it via a |
| 21 | +# user-level `settings:` block to keep the |
| 22 | +# output filename deterministic — see the |
| 23 | +# setup section below for why user-level |
| 24 | +# and not workspaceSettings) |
| 25 | +# c. Jdtls.exportJar → writes the jar file |
| 26 | +# |
| 27 | +# Verification strategy |
| 28 | +# ───────────────────── |
| 29 | +# The jar is written to a known absolute path inside the workspace |
| 30 | +# (`output.jar`). We assert with `verifyFile exists: true` — the strongest |
| 31 | +# possible signal that the full wizard completed end-to-end, not just that |
| 32 | +# the command was dispatched. The Jdtls export runs in a hidden Pseudoterminal |
| 33 | +# (BuildArtifactTaskProvider line 91: `presentationOptions.reveal = Never`), |
| 34 | +# so there is no terminal text to inspect; the file on disk is the only |
| 35 | +# unambiguous post-condition. |
| 36 | +# |
| 37 | +# Usage: |
| 38 | +# npx autotest run test/e2e-plans/java-dep-export-jar.yaml --vsix <path-to-vsix> |
| 39 | + |
| 40 | +name: "Java Dependency — Export Jar" |
| 41 | +description: | |
| 42 | + Exercises the multi-step Export Jar wizard end-to-end on the maven |
| 43 | + fixture: triggers the command, picks the main class, accepts the default |
| 44 | + classpath element selection, and verifies that the resulting jar file |
| 45 | + exists at the configured target path. |
| 46 | +
|
| 47 | +setup: |
| 48 | + extension: "redhat.java" |
| 49 | + vscodeVersion: "stable" |
| 50 | + workspace: "../maven" |
| 51 | + # Bumped above the standard 180s — the wizard runs a full workspace build |
| 52 | + # (await buildWorkspace() in executeExportJarTask) before the first |
| 53 | + # quick-pick appears, which on a cold JDT-LS warmup commonly takes 60-90s. |
| 54 | + timeout: 360 |
| 55 | + settings: |
| 56 | + java.configuration.checkProjectSettingsExclusions: false |
| 57 | + workbench.startupEditor: "none" |
| 58 | + # Pinning java.project.exportJar.targetPath to an absolute deterministic |
| 59 | + # path bypasses the showSaveDialog branch in GenerateJarExecutor |
| 60 | + # (BuildArtifactTaskProvider lines 240-244 short-circuit only when |
| 61 | + # outputPath === ""), and lets the verifyFile assertion target a stable |
| 62 | + # location regardless of how the fixture's worktree is named. |
| 63 | + # |
| 64 | + # We use user-level `settings:` (not `workspaceSettings:`) because |
| 65 | + # autotest's workspaceSettings merge uses JSON.parse on the existing |
| 66 | + # `.vscode/settings.json`, and the maven fixture's settings.json |
| 67 | + # contains JSONC `//` comments which fail JSON.parse. User settings |
| 68 | + # are written fresh each run (user-data-dir is wiped on launch) so |
| 69 | + # there is no JSONC merge hazard. The Settings.getExportJarTargetPath |
| 70 | + # config read is unscoped, so user-level setting takes effect identically. |
| 71 | + java.project.exportJar.targetPath: "${workspaceFolder}/output.jar" |
| 72 | + |
| 73 | +steps: |
| 74 | + # ── Setup: wait for LS, free sidebar space, focus Java Projects ── |
| 75 | + - id: "ls-ready" |
| 76 | + action: "waitForLanguageServer" |
| 77 | + # No `verify:` — `waitForLanguageServer` is itself the deterministic |
| 78 | + # readiness check. The AFTER screenshot may transiently show |
| 79 | + # "Java: Building - 0%" which a strict LLM mis-reads as a failure. |
| 80 | + timeout: 180 |
| 81 | + |
| 82 | + - id: "close-aux-bar" |
| 83 | + action: "executeVSCodeCommand workbench.action.closeAuxiliaryBar" |
| 84 | + verify: "Auxiliary bar (Chat) closed" |
| 85 | + |
| 86 | + - id: "collapse-outline" |
| 87 | + action: "collapseSidebarSection OUTLINE" |
| 88 | + |
| 89 | + - id: "collapse-timeline" |
| 90 | + action: "collapseSidebarSection TIMELINE" |
| 91 | + |
| 92 | + - id: "collapse-workspace-root" |
| 93 | + action: "collapseWorkspaceRoot" |
| 94 | + |
| 95 | + - id: "focus-java-projects" |
| 96 | + action: "executeVSCodeCommand javaProjectExplorer.focus" |
| 97 | + verify: "Java Projects view is focused" |
| 98 | + |
| 99 | + - id: "wait-tree-load" |
| 100 | + action: "wait 3 seconds" |
| 101 | + |
| 102 | + # ── Trigger the Export Jar wizard ── |
| 103 | + # Direct command invocation avoids the brittle inline-icon-on-workspace- |
| 104 | + # node click path (the `$(export)` icon is contributed against viewItem |
| 105 | + # `java:workspace`, not against the Maven project node `my-app`, and |
| 106 | + # locating workspace-level inline icons in autotest is fragile). |
| 107 | + # ResolveJavaProject auto-resolves for single-project workspaces. |
| 108 | + - id: "invoke-export-jar" |
| 109 | + action: "executeVSCodeCommand java.view.package.exportJar" |
| 110 | + |
| 111 | + # The wizard first triggers a full workspace build (await buildWorkspace() |
| 112 | + # in executeExportJarTask) before any UI appears. On a cold JDT-LS this |
| 113 | + # typically takes 30-60s; the Jdtls.getMainClasses fetch then needs |
| 114 | + # another 2-5s before the first quick-pick is shown. Wait generously. |
| 115 | + - id: "wait-build-complete" |
| 116 | + action: "wait 60 seconds" |
| 117 | + |
| 118 | + # ── Step 2: pick the main class ── |
| 119 | + # The maven fixture has a single class with a `public static void main` |
| 120 | + # entry point: com.mycompany.app.App. App1 has no main, so the only |
| 121 | + # quick-pick options are "App" and "<without main class>". We pick "App" |
| 122 | + # explicitly so the resulting jar is runnable. |
| 123 | + - id: "pick-main-class" |
| 124 | + action: "select App option" |
| 125 | + # No `verify:` — selectPaletteOption is the action and verification in |
| 126 | + # one. The quick-pick closes on selection; the AFTER screenshot may |
| 127 | + # already show the next quick-pick (classpath elements), which a |
| 128 | + # strict LLM could mis-read as "App selection was lost". |
| 129 | + |
| 130 | + - id: "wait-after-main-class" |
| 131 | + action: "wait 5 seconds" |
| 132 | + |
| 133 | + # ── Step 3a: accept the pre-selected classpath elements ── |
| 134 | + # GenerateJarExecutor.generateClasspaths builds a list of runtime / test |
| 135 | + # output folders + dependency artifacts, pre-selects everything tagged |
| 136 | + # `runtime`, and shows a multi-select QuickPick. For the maven fixture |
| 137 | + # this includes target/classes plus any resolved JUnit jars under test |
| 138 | + # scope. The pre-selection is the sane default — accepting it gives a |
| 139 | + # runnable jar without needing to compute which items to check. |
| 140 | + # |
| 141 | + # `confirmQuickInput` presses Enter on the open quick-pick widget without |
| 142 | + # typing anything, which leaves selections untouched and submits. |
| 143 | + - id: "accept-classpath-elements" |
| 144 | + action: "confirmQuickInput" |
| 145 | + |
| 146 | + # ── Step 3c: wait for Jdtls to generate the jar ── |
| 147 | + # Jdtls.exportJar writes the jar via a JDT LSP request. The custom |
| 148 | + # pseudoterminal stays hidden (presentationOptions.reveal=Never), so |
| 149 | + # there is no terminal-text signal — we just wait long enough for the |
| 150 | + # filesystem write to settle. |
| 151 | + - id: "wait-jar-generated" |
| 152 | + action: "wait 30 seconds" |
| 153 | + |
| 154 | + # ── Verification: jar file exists at the configured target path ── |
| 155 | + # This is the strongest possible end-to-end check: the file appearing |
| 156 | + # on disk proves ResolveJavaProject + ResolveMainClass + generateClasspaths |
| 157 | + # + Jdtls.exportJar all completed in order. A failure here pinpoints |
| 158 | + # the wizard breaking; a pass means the full happy path worked. |
| 159 | + - id: "verify-jar-created" |
| 160 | + action: "wait 1 seconds" |
| 161 | + verifyFile: |
| 162 | + path: "${workspaceFolder}/output.jar" |
| 163 | + exists: true |
| 164 | + timeout: 60 |
0 commit comments