| 1 | "use strict"; |
| 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { |
| 3 | if (k2 === undefined) k2 = k; |
| 4 | var desc = Object.getOwnPropertyDescriptor(m, k); |
| 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { |
| 6 | desc = { enumerable: true, get: function() { return m[k]; } }; |
| 7 | } |
| 8 | Object.defineProperty(o, k2, desc); |
| 9 | }) : (function(o, m, k, k2) { |
| 10 | if (k2 === undefined) k2 = k; |
| 11 | o[k2] = m[k]; |
| 12 | })); |
| 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { |
| 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); |
| 15 | }) : function(o, v) { |
| 16 | o["default"] = v; |
| 17 | }); |
| 18 | var __importStar = (this && this.__importStar) || (function () { |
| 19 | var ownKeys = function(o) { |
| 20 | ownKeys = Object.getOwnPropertyNames || function (o) { |
| 21 | var ar = []; |
| 22 | for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; |
| 23 | return ar; |
| 24 | }; |
| 25 | return ownKeys(o); |
| 26 | }; |
| 27 | return function (mod) { |
| 28 | if (mod && mod.__esModule) return mod; |
| 29 | var result = {}; |
| 30 | if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); |
| 31 | __setModuleDefault(result, mod); |
| 32 | return result; |
| 33 | }; |
| 34 | })(); |
| 35 | Object.defineProperty(exports, "__esModule", { value: true }); |
| 36 | const assert = __importStar(require("assert")); |
| 37 | const vscode = __importStar(require("vscode")); |
| 38 | const path = __importStar(require("path")); |
| 39 | const FIXTURE_DIR = path.resolve(__dirname, "../../test/fixtures"); |
| 40 | const SAMPLE_DLM = path.join(FIXTURE_DIR, "sample.dlm"); |
| 41 | suite("Extension Activation", () => { |
| 42 | test("extension is present in the registry", () => { |
| 43 | const ext = vscode.extensions.getExtension("tenseleyFlow.dlm-vsc"); |
| 44 | // In dev mode the publisher may not match; check by scanning all extensions |
| 45 | const all = vscode.extensions.all.map((e) => e.id); |
| 46 | // The extension ID in dev is just the package name without publisher |
| 47 | assert.ok(all.some((id) => id.includes("dlm-vsc")), `dlm-vsc not found in extensions: ${all.join(", ")}`); |
| 48 | }); |
| 49 | test("dlm language is registered", () => { |
| 50 | // Opening a .dlm file should associate with our language |
| 51 | const langs = vscode.extensions.all |
| 52 | .flatMap((e) => { |
| 53 | const langs = e.packageJSON?.contributes?.languages; |
| 54 | return Array.isArray(langs) ? langs : []; |
| 55 | }) |
| 56 | .filter((l) => l.id === "dlm"); |
| 57 | assert.ok(langs.length > 0, "dlm language not registered by any extension"); |
| 58 | }); |
| 59 | test("extension activates when opening a .dlm file", async () => { |
| 60 | const doc = await vscode.workspace.openTextDocument(SAMPLE_DLM); |
| 61 | await vscode.window.showTextDocument(doc); |
| 62 | // Give the extension a moment to activate |
| 63 | await sleep(2000); |
| 64 | const editor = vscode.window.activeTextEditor; |
| 65 | assert.ok(editor, "no active editor after opening .dlm file"); |
| 66 | assert.strictEqual(editor.document.languageId, "dlm"); |
| 67 | }); |
| 68 | }); |
| 69 | suite("Command Registration", () => { |
| 70 | const EXPECTED_COMMANDS = [ |
| 71 | "dlm.train", |
| 72 | "dlm.export", |
| 73 | "dlm.synth", |
| 74 | "dlm.showHistory", |
| 75 | "dlm.openStore", |
| 76 | "dlm.insertInstruction", |
| 77 | "dlm.insertPreference", |
| 78 | ]; |
| 79 | test("all 7 DLM commands are registered", async () => { |
| 80 | const allCommands = await vscode.commands.getCommands(true); |
| 81 | for (const cmd of EXPECTED_COMMANDS) { |
| 82 | assert.ok(allCommands.includes(cmd), `command ${cmd} not registered`); |
| 83 | } |
| 84 | }); |
| 85 | }); |
| 86 | suite("Language Configuration", () => { |
| 87 | test(".dlm files get dlm languageId", async () => { |
| 88 | const doc = await vscode.workspace.openTextDocument(SAMPLE_DLM); |
| 89 | assert.strictEqual(doc.languageId, "dlm"); |
| 90 | }); |
| 91 | test("non-.dlm files do not get dlm languageId", async () => { |
| 92 | const doc = await vscode.workspace.openTextDocument({ |
| 93 | content: "hello world", |
| 94 | language: "plaintext", |
| 95 | }); |
| 96 | assert.notStrictEqual(doc.languageId, "dlm"); |
| 97 | }); |
| 98 | }); |
| 99 | suite("Document Content", () => { |
| 100 | test("sample fixture has valid frontmatter", async () => { |
| 101 | const doc = await vscode.workspace.openTextDocument(SAMPLE_DLM); |
| 102 | const text = doc.getText(); |
| 103 | assert.ok(text.startsWith("---"), "file does not start with ---"); |
| 104 | assert.ok(text.includes("dlm_id:"), "missing dlm_id"); |
| 105 | assert.ok(text.includes("base_model:"), "missing base_model"); |
| 106 | assert.ok(text.includes("dlm_version:"), "missing dlm_version"); |
| 107 | // Count frontmatter delimiters |
| 108 | const lines = text.split("\n"); |
| 109 | const delimCount = lines.filter((l) => l.trim() === "---").length; |
| 110 | assert.ok(delimCount >= 2, `expected at least 2 --- delimiters, got ${delimCount}`); |
| 111 | }); |
| 112 | test("sample fixture has instruction sections", async () => { |
| 113 | const doc = await vscode.workspace.openTextDocument(SAMPLE_DLM); |
| 114 | const text = doc.getText(); |
| 115 | const fences = text.split("\n").filter((l) => l.trim().startsWith("::instruction::")); |
| 116 | assert.ok(fences.length >= 2, `expected at least 2 instruction fences, got ${fences.length}`); |
| 117 | }); |
| 118 | }); |
| 119 | suite("Edge Cases", () => { |
| 120 | test("commands warn when no .dlm file is open", async () => { |
| 121 | // Open a non-.dlm file |
| 122 | const doc = await vscode.workspace.openTextDocument({ |
| 123 | content: "not a dlm file", |
| 124 | language: "plaintext", |
| 125 | }); |
| 126 | await vscode.window.showTextDocument(doc); |
| 127 | // These should not throw — they show a warning message instead |
| 128 | await vscode.commands.executeCommand("dlm.train"); |
| 129 | await vscode.commands.executeCommand("dlm.export"); |
| 130 | await vscode.commands.executeCommand("dlm.synth"); |
| 131 | await vscode.commands.executeCommand("dlm.insertInstruction"); |
| 132 | }); |
| 133 | test("commands handle no active editor gracefully", async () => { |
| 134 | // Close all editors |
| 135 | await vscode.commands.executeCommand("workbench.action.closeAllEditors"); |
| 136 | // These should not throw |
| 137 | await vscode.commands.executeCommand("dlm.train"); |
| 138 | await vscode.commands.executeCommand("dlm.insertInstruction"); |
| 139 | }); |
| 140 | test("opening an empty file with .dlm extension", async () => { |
| 141 | const emptyUri = vscode.Uri.file(path.join(FIXTURE_DIR, "empty.dlm")); |
| 142 | try { |
| 143 | // Create a temporary empty .dlm |
| 144 | await vscode.workspace.fs.writeFile(emptyUri, Buffer.from("")); |
| 145 | const doc = await vscode.workspace.openTextDocument(emptyUri); |
| 146 | assert.strictEqual(doc.languageId, "dlm"); |
| 147 | assert.strictEqual(doc.getText(), ""); |
| 148 | } |
| 149 | finally { |
| 150 | try { |
| 151 | await vscode.workspace.fs.delete(emptyUri); |
| 152 | } |
| 153 | catch { |
| 154 | /* cleanup best-effort */ |
| 155 | } |
| 156 | } |
| 157 | }); |
| 158 | test("opening a .dlm with invalid frontmatter does not crash", async () => { |
| 159 | const badUri = vscode.Uri.file(path.join(FIXTURE_DIR, "bad.dlm")); |
| 160 | try { |
| 161 | await vscode.workspace.fs.writeFile(badUri, Buffer.from("not valid frontmatter\njust plain text\n")); |
| 162 | const doc = await vscode.workspace.openTextDocument(badUri); |
| 163 | await vscode.window.showTextDocument(doc); |
| 164 | assert.strictEqual(doc.languageId, "dlm"); |
| 165 | // Extension should still be alive — commands should still be registered |
| 166 | const cmds = await vscode.commands.getCommands(true); |
| 167 | assert.ok(cmds.includes("dlm.train")); |
| 168 | } |
| 169 | finally { |
| 170 | try { |
| 171 | await vscode.workspace.fs.delete(badUri); |
| 172 | } |
| 173 | catch { |
| 174 | /* cleanup best-effort */ |
| 175 | } |
| 176 | } |
| 177 | }); |
| 178 | }); |
| 179 | suite("Configuration", () => { |
| 180 | test("dlm.command setting exists with default", () => { |
| 181 | const config = vscode.workspace.getConfiguration("dlm"); |
| 182 | const cmd = config.get("command"); |
| 183 | assert.strictEqual(cmd, "uv run dlm"); |
| 184 | }); |
| 185 | test("dlm.lspPath setting exists with default", () => { |
| 186 | const config = vscode.workspace.getConfiguration("dlm"); |
| 187 | const lsp = config.get("lspPath"); |
| 188 | assert.strictEqual(lsp, "dlm-lsp"); |
| 189 | }); |
| 190 | test("dlm.home setting exists and defaults to empty", () => { |
| 191 | const config = vscode.workspace.getConfiguration("dlm"); |
| 192 | const home = config.get("home"); |
| 193 | assert.strictEqual(home, ""); |
| 194 | }); |
| 195 | test("dlm.watchOnSave setting exists and defaults to false", () => { |
| 196 | const config = vscode.workspace.getConfiguration("dlm"); |
| 197 | const watch = config.get("watchOnSave"); |
| 198 | assert.strictEqual(watch, false); |
| 199 | }); |
| 200 | }); |
| 201 | suite("Webview Provider", () => { |
| 202 | test("DLM side panel view is registered", () => { |
| 203 | // The view should be declared in the extension's contributes |
| 204 | const ext = vscode.extensions.all.find((e) => e.id.includes("dlm-vsc")); |
| 205 | if (ext) { |
| 206 | const views = ext.packageJSON?.contributes?.views?.["dlm-panel"]; |
| 207 | assert.ok(Array.isArray(views), "dlm-panel views not declared"); |
| 208 | const panel = views.find((v) => v.id === "dlm.sidePanel"); |
| 209 | assert.ok(panel, "dlm.sidePanel view not found"); |
| 210 | assert.strictEqual(panel.type, "webview"); |
| 211 | } |
| 212 | }); |
| 213 | }); |
| 214 | function sleep(ms) { |
| 215 | return new Promise((resolve) => setTimeout(resolve, ms)); |
| 216 | } |
| 217 | //# sourceMappingURL=extension.test.js.map |
| 218 |