obsidian-e2e 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -18
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/matchers.d.mts +1 -1
- package/dist/matchers.mjs +5 -1
- package/dist/matchers.mjs.map +1 -1
- package/dist/{test-context-BprSx6U1.mjs → test-context-Bl-e-83H.mjs} +150 -355
- package/dist/test-context-Bl-e-83H.mjs.map +1 -0
- package/dist/{types-C4cj443K.d.mts → types-BUXaueDI.d.mts} +2 -4
- package/dist/{vault-lock-CYyOdRP1.d.mts → vault-lock-XcBHtwm9.d.mts} +2 -2
- package/dist/vitest.d.mts +1 -1
- package/dist/vitest.mjs +1 -1
- package/package.json +1 -1
- package/dist/test-context-BprSx6U1.mjs.map +0 -1
|
@@ -18,303 +18,6 @@ function buildCommandArgv(vaultName, command, args = {}) {
|
|
|
18
18
|
return argv;
|
|
19
19
|
}
|
|
20
20
|
//#endregion
|
|
21
|
-
//#region src/dev/harness.ts
|
|
22
|
-
const HARNESS_NAMESPACE = "__obsidianE2E";
|
|
23
|
-
const HARNESS_VERSION = 1;
|
|
24
|
-
function buildHarnessCallCode(method, ...args) {
|
|
25
|
-
return `(() => {
|
|
26
|
-
const __obsidianE2EMethod = ${JSON.stringify(method)};
|
|
27
|
-
const __obsidianE2EArgs = ${JSON.stringify(args)};
|
|
28
|
-
const __obsidianE2ENamespace = ${JSON.stringify(HARNESS_NAMESPACE)};
|
|
29
|
-
const __obsidianE2EVersion = ${HARNESS_VERSION};
|
|
30
|
-
${HARNESS_RUNTIME}
|
|
31
|
-
})()`;
|
|
32
|
-
}
|
|
33
|
-
function parseHarnessEnvelope(raw) {
|
|
34
|
-
const envelope = JSON.parse(raw.startsWith("=> ") ? raw.slice(3) : raw);
|
|
35
|
-
if (!envelope.ok) throw envelope.error;
|
|
36
|
-
return decodeHarnessValue(envelope.value);
|
|
37
|
-
}
|
|
38
|
-
function decodeHarnessValue(value) {
|
|
39
|
-
if (Array.isArray(value)) return value.map((entry) => decodeHarnessValue(entry));
|
|
40
|
-
if (!value || typeof value !== "object") return value;
|
|
41
|
-
if ("__obsidianE2EType" in value && value.__obsidianE2EType === "undefined") return;
|
|
42
|
-
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, decodeHarnessValue(entry)]));
|
|
43
|
-
}
|
|
44
|
-
function createDevDiagnostics(value) {
|
|
45
|
-
return {
|
|
46
|
-
consoleMessages: value?.consoleMessages ?? [],
|
|
47
|
-
notices: value?.notices ?? [],
|
|
48
|
-
runtimeErrors: value?.runtimeErrors ?? []
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
const HARNESS_RUNTIME = String.raw`
|
|
52
|
-
const __obsidianE2EMaxEntries = 100;
|
|
53
|
-
|
|
54
|
-
const __obsidianE2EPush = (entries, value) => {
|
|
55
|
-
if (entries.length >= __obsidianE2EMaxEntries) {
|
|
56
|
-
entries.shift();
|
|
57
|
-
}
|
|
58
|
-
entries.push(value);
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const __obsidianE2EFormat = (value) => {
|
|
62
|
-
if (typeof value === "string") {
|
|
63
|
-
return value;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
try {
|
|
67
|
-
return JSON.stringify(value);
|
|
68
|
-
} catch {
|
|
69
|
-
return String(value);
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const __obsidianE2ESerialize = (value, path = "$") => {
|
|
74
|
-
if (value === null) {
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (value === undefined) {
|
|
79
|
-
return { __obsidianE2EType: "undefined" };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const valueType = typeof value;
|
|
83
|
-
|
|
84
|
-
if (valueType === "string" || valueType === "boolean") {
|
|
85
|
-
return value;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (valueType === "number") {
|
|
89
|
-
if (!Number.isFinite(value)) {
|
|
90
|
-
throw new Error(\`Cannot serialize non-finite number at \${path}.\`);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return value;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (valueType === "bigint" || valueType === "function" || valueType === "symbol") {
|
|
97
|
-
throw new Error(\`Cannot serialize \${valueType} at \${path}.\`);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (Array.isArray(value)) {
|
|
101
|
-
return value.map((item, index) => __obsidianE2ESerialize(item, \`\${path}[\${index}]\`));
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const prototype = Object.getPrototypeOf(value);
|
|
105
|
-
|
|
106
|
-
if (prototype !== Object.prototype && prototype !== null) {
|
|
107
|
-
throw new Error(\`Cannot serialize non-plain object at \${path}.\`);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const next = {};
|
|
111
|
-
|
|
112
|
-
for (const [key, entry] of Object.entries(value)) {
|
|
113
|
-
next[key] = __obsidianE2ESerialize(entry, \`\${path}.\${key}\`);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return next;
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
const __obsidianE2EClone = (value) => JSON.parse(JSON.stringify(__obsidianE2ESerialize(value)));
|
|
120
|
-
|
|
121
|
-
const __obsidianE2ECreateHarness = () => {
|
|
122
|
-
const state = {
|
|
123
|
-
consoleMessages: [],
|
|
124
|
-
notices: [],
|
|
125
|
-
runtimeErrors: [],
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
const pushConsoleMessage = (level, args) => {
|
|
129
|
-
__obsidianE2EPush(state.consoleMessages, {
|
|
130
|
-
args: args.map((entry) => {
|
|
131
|
-
try {
|
|
132
|
-
return __obsidianE2EClone(entry);
|
|
133
|
-
} catch {
|
|
134
|
-
return __obsidianE2EFormat(entry);
|
|
135
|
-
}
|
|
136
|
-
}),
|
|
137
|
-
at: Date.now(),
|
|
138
|
-
level,
|
|
139
|
-
text: args.map(__obsidianE2EFormat).join(" "),
|
|
140
|
-
});
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
const pushRuntimeError = (source, errorLike) => {
|
|
144
|
-
const message =
|
|
145
|
-
errorLike && typeof errorLike === "object" && "message" in errorLike
|
|
146
|
-
? String(errorLike.message)
|
|
147
|
-
: String(errorLike);
|
|
148
|
-
const stack =
|
|
149
|
-
errorLike && typeof errorLike === "object" && "stack" in errorLike
|
|
150
|
-
? String(errorLike.stack)
|
|
151
|
-
: undefined;
|
|
152
|
-
|
|
153
|
-
__obsidianE2EPush(state.runtimeErrors, {
|
|
154
|
-
at: Date.now(),
|
|
155
|
-
message,
|
|
156
|
-
source,
|
|
157
|
-
stack,
|
|
158
|
-
});
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
const installConsolePatch = (root) => {
|
|
162
|
-
if (root.__obsidianE2EConsolePatched) {
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
for (const level of ["debug", "error", "info", "log", "warn"]) {
|
|
167
|
-
const original = root.console?.[level];
|
|
168
|
-
|
|
169
|
-
if (typeof original !== "function") {
|
|
170
|
-
continue;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
root.console[level] = (...args) => {
|
|
174
|
-
pushConsoleMessage(level, args);
|
|
175
|
-
return original.apply(root.console, args);
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
root.__obsidianE2EConsolePatched = true;
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
const installRuntimePatch = (root) => {
|
|
183
|
-
if (root.__obsidianE2ERuntimePatched || typeof root.addEventListener !== "function") {
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
root.addEventListener("error", (event) => {
|
|
188
|
-
pushRuntimeError("error", event?.error ?? event?.message ?? "Unknown error");
|
|
189
|
-
});
|
|
190
|
-
root.addEventListener("unhandledrejection", (event) => {
|
|
191
|
-
pushRuntimeError("unhandledrejection", event?.reason ?? "Unhandled rejection");
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
root.__obsidianE2ERuntimePatched = true;
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
const installNoticePatch = (root) => {
|
|
198
|
-
if (root.__obsidianE2ENoticePatched || typeof root.Notice !== "function") {
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const OriginalNotice = root.Notice;
|
|
203
|
-
root.Notice = new Proxy(OriginalNotice, {
|
|
204
|
-
construct(target, ctorArgs, newTarget) {
|
|
205
|
-
__obsidianE2EPush(state.notices, {
|
|
206
|
-
at: Date.now(),
|
|
207
|
-
message: __obsidianE2EFormat(ctorArgs[0] ?? ""),
|
|
208
|
-
timeout:
|
|
209
|
-
typeof ctorArgs[1] === "number" && Number.isFinite(ctorArgs[1])
|
|
210
|
-
? ctorArgs[1]
|
|
211
|
-
: undefined,
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
return Reflect.construct(target, ctorArgs, newTarget);
|
|
215
|
-
},
|
|
216
|
-
});
|
|
217
|
-
root.__obsidianE2ENoticePatched = true;
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
const ensureInstalled = () => {
|
|
221
|
-
const root = globalThis;
|
|
222
|
-
installConsolePatch(root);
|
|
223
|
-
installRuntimePatch(root);
|
|
224
|
-
installNoticePatch(root);
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
const getFileCache = (vaultPath) => {
|
|
228
|
-
const file = app?.vault?.getAbstractFileByPath?.(vaultPath);
|
|
229
|
-
if (!file) {
|
|
230
|
-
return null;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
return app?.metadataCache?.getFileCache?.(file) ?? null;
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
return {
|
|
237
|
-
activeFilePath() {
|
|
238
|
-
ensureInstalled();
|
|
239
|
-
return app?.workspace?.getActiveFile?.()?.path ?? null;
|
|
240
|
-
},
|
|
241
|
-
consoleMessages() {
|
|
242
|
-
ensureInstalled();
|
|
243
|
-
return state.consoleMessages;
|
|
244
|
-
},
|
|
245
|
-
diagnostics() {
|
|
246
|
-
ensureInstalled();
|
|
247
|
-
return state;
|
|
248
|
-
},
|
|
249
|
-
editorText() {
|
|
250
|
-
ensureInstalled();
|
|
251
|
-
return app?.workspace?.activeLeaf?.view?.editor?.getValue?.() ?? null;
|
|
252
|
-
},
|
|
253
|
-
eval(code) {
|
|
254
|
-
ensureInstalled();
|
|
255
|
-
return (0, eval)(code);
|
|
256
|
-
},
|
|
257
|
-
frontmatter(vaultPath) {
|
|
258
|
-
ensureInstalled();
|
|
259
|
-
return getFileCache(vaultPath)?.frontmatter ?? null;
|
|
260
|
-
},
|
|
261
|
-
metadata(vaultPath) {
|
|
262
|
-
ensureInstalled();
|
|
263
|
-
return getFileCache(vaultPath);
|
|
264
|
-
},
|
|
265
|
-
notices() {
|
|
266
|
-
ensureInstalled();
|
|
267
|
-
return state.notices;
|
|
268
|
-
},
|
|
269
|
-
pluginLoaded(pluginId) {
|
|
270
|
-
ensureInstalled();
|
|
271
|
-
const plugins = app?.plugins;
|
|
272
|
-
return Boolean(
|
|
273
|
-
plugins?.enabledPlugins?.has?.(pluginId) &&
|
|
274
|
-
plugins?.plugins?.[pluginId],
|
|
275
|
-
);
|
|
276
|
-
},
|
|
277
|
-
resetDiagnostics() {
|
|
278
|
-
state.consoleMessages.splice(0);
|
|
279
|
-
state.notices.splice(0);
|
|
280
|
-
state.runtimeErrors.splice(0);
|
|
281
|
-
ensureInstalled();
|
|
282
|
-
return true;
|
|
283
|
-
},
|
|
284
|
-
runtimeErrors() {
|
|
285
|
-
ensureInstalled();
|
|
286
|
-
return state.runtimeErrors;
|
|
287
|
-
},
|
|
288
|
-
};
|
|
289
|
-
};
|
|
290
|
-
|
|
291
|
-
const root = globalThis;
|
|
292
|
-
const current = root[__obsidianE2ENamespace];
|
|
293
|
-
const harness =
|
|
294
|
-
current && current.version === __obsidianE2EVersion
|
|
295
|
-
? current
|
|
296
|
-
: (root[__obsidianE2ENamespace] = {
|
|
297
|
-
api: __obsidianE2ECreateHarness(),
|
|
298
|
-
version: __obsidianE2EVersion,
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
try {
|
|
302
|
-
const result = harness.api[__obsidianE2EMethod](...__obsidianE2EArgs);
|
|
303
|
-
return JSON.stringify({
|
|
304
|
-
ok: true,
|
|
305
|
-
value: __obsidianE2ESerialize(result),
|
|
306
|
-
});
|
|
307
|
-
} catch (error) {
|
|
308
|
-
return JSON.stringify({
|
|
309
|
-
error: {
|
|
310
|
-
message: error instanceof Error ? error.message : String(error),
|
|
311
|
-
name: error instanceof Error ? error.name : "Error",
|
|
312
|
-
stack: error instanceof Error ? error.stack : undefined,
|
|
313
|
-
},
|
|
314
|
-
ok: false,
|
|
315
|
-
});
|
|
316
|
-
}`;
|
|
317
|
-
//#endregion
|
|
318
21
|
//#region src/core/exec-options.ts
|
|
319
22
|
function mergeExecOptions(defaults, overrides) {
|
|
320
23
|
if (!defaults) return overrides ? { ...overrides } : {};
|
|
@@ -392,6 +95,89 @@ function isMissingFileError(error) {
|
|
|
392
95
|
return Boolean(error && typeof error === "object" && "code" in error && error.code === "ENOENT");
|
|
393
96
|
}
|
|
394
97
|
//#endregion
|
|
98
|
+
//#region src/core/errors.ts
|
|
99
|
+
var ObsidianCommandError = class extends Error {
|
|
100
|
+
result;
|
|
101
|
+
constructor(message, result) {
|
|
102
|
+
super(message);
|
|
103
|
+
this.name = "ObsidianCommandError";
|
|
104
|
+
this.result = result;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
var WaitForTimeoutError = class extends Error {
|
|
108
|
+
causeError;
|
|
109
|
+
constructor(message, causeError) {
|
|
110
|
+
super(message);
|
|
111
|
+
this.name = "WaitForTimeoutError";
|
|
112
|
+
this.causeError = causeError;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
var DevEvalError = class extends Error {
|
|
116
|
+
remote;
|
|
117
|
+
constructor(message, remote) {
|
|
118
|
+
super(message);
|
|
119
|
+
this.name = "DevEvalError";
|
|
120
|
+
this.remote = remote;
|
|
121
|
+
if (remote.stack) this.stack = `${this.name}: ${message}\nRemote stack:\n${remote.stack}`;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
//#endregion
|
|
125
|
+
//#region src/dev/eval-json.ts
|
|
126
|
+
async function runEvalJson(dev, code, execOptions = {}) {
|
|
127
|
+
return parseEvalJsonEnvelope(await dev.evalRaw(buildEvalJsonCode(code), execOptions));
|
|
128
|
+
}
|
|
129
|
+
function buildEvalJsonCode(code) {
|
|
130
|
+
return [
|
|
131
|
+
"(()=>{",
|
|
132
|
+
`const __obsidianE2ECode=${JSON.stringify(code)};`,
|
|
133
|
+
"const __obsidianE2ESerialize=(value,path='$')=>{",
|
|
134
|
+
"if(value===null){return null;}",
|
|
135
|
+
"if(value===undefined){return {__obsidianE2EType:'undefined'};}",
|
|
136
|
+
"const valueType=typeof value;",
|
|
137
|
+
"if(valueType==='string'||valueType==='boolean'){return value;}",
|
|
138
|
+
"if(valueType==='number'){if(!Number.isFinite(value)){throw new Error(`Cannot serialize non-finite number at ${path}.`);}return value;}",
|
|
139
|
+
"if(valueType==='bigint'||valueType==='function'||valueType==='symbol'){throw new Error(`Cannot serialize ${valueType} at ${path}.`);}",
|
|
140
|
+
"if(Array.isArray(value)){return value.map((item,index)=>__obsidianE2ESerialize(item,`${path}[${index}]`));}",
|
|
141
|
+
"const prototype=Object.getPrototypeOf(value);",
|
|
142
|
+
"if(prototype!==Object.prototype&&prototype!==null){throw new Error(`Cannot serialize non-plain object at ${path}.`);}",
|
|
143
|
+
"const next={};",
|
|
144
|
+
"for(const [key,entry] of Object.entries(value)){next[key]=__obsidianE2ESerialize(entry,`${path}.${key}`);}",
|
|
145
|
+
"return next;",
|
|
146
|
+
"};",
|
|
147
|
+
"try{",
|
|
148
|
+
"return JSON.stringify({ok:true,value:__obsidianE2ESerialize((0,eval)(__obsidianE2ECode))});",
|
|
149
|
+
"}catch(error){",
|
|
150
|
+
"return JSON.stringify({ok:false,error:{message:error instanceof Error?error.message:String(error),name:error instanceof Error?error.name:'Error',stack:error instanceof Error?error.stack:undefined}});",
|
|
151
|
+
"}",
|
|
152
|
+
"})()"
|
|
153
|
+
].join("");
|
|
154
|
+
}
|
|
155
|
+
function parseDevEvalOutput(raw) {
|
|
156
|
+
const normalized = normalizeEvalOutput(raw);
|
|
157
|
+
try {
|
|
158
|
+
return JSON.parse(normalized);
|
|
159
|
+
} catch {
|
|
160
|
+
return normalized;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function parseEvalJsonEnvelope(raw) {
|
|
164
|
+
const envelope = JSON.parse(normalizeEvalOutput(raw));
|
|
165
|
+
if (!envelope.ok) throw new DevEvalError(`Failed to evaluate Obsidian code: ${envelope.error.message}`, { ...envelope.error });
|
|
166
|
+
return decodeEvalJsonValue(envelope.value);
|
|
167
|
+
}
|
|
168
|
+
function normalizeEvalOutput(raw) {
|
|
169
|
+
return raw.startsWith("=> ") ? raw.slice(3) : raw;
|
|
170
|
+
}
|
|
171
|
+
function decodeEvalJsonValue(value) {
|
|
172
|
+
if (Array.isArray(value)) return value.map((entry) => decodeEvalJsonValue(entry));
|
|
173
|
+
if (!value || typeof value !== "object") return value;
|
|
174
|
+
if (isUndefinedSentinel(value)) return;
|
|
175
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, decodeEvalJsonValue(entry)]));
|
|
176
|
+
}
|
|
177
|
+
function isUndefinedSentinel(value) {
|
|
178
|
+
return "__obsidianE2EType" in value && value.__obsidianE2EType === "undefined";
|
|
179
|
+
}
|
|
180
|
+
//#endregion
|
|
395
181
|
//#region src/metadata/metadata.ts
|
|
396
182
|
function createObsidianMetadataHandle(client) {
|
|
397
183
|
return {
|
|
@@ -413,7 +199,17 @@ function createObsidianMetadataHandle(client) {
|
|
|
413
199
|
};
|
|
414
200
|
}
|
|
415
201
|
async function readMetadata(client, method, path, execOptions) {
|
|
416
|
-
return
|
|
202
|
+
return runEvalJson(client.dev, buildMetadataReadCode(method, path), execOptions);
|
|
203
|
+
}
|
|
204
|
+
function buildMetadataReadCode(method, path) {
|
|
205
|
+
return [
|
|
206
|
+
"(()=>{",
|
|
207
|
+
`const __obsidianE2EPath=${JSON.stringify(path)};`,
|
|
208
|
+
"const __obsidianE2EFile=app?.vault?.getAbstractFileByPath?.(__obsidianE2EPath);",
|
|
209
|
+
"if(!__obsidianE2EFile){return null;}",
|
|
210
|
+
method === "frontmatter" ? "return app?.metadataCache?.getFileCache?.(__obsidianE2EFile)?.frontmatter ?? null;" : "return app?.metadataCache?.getFileCache?.(__obsidianE2EFile) ?? null;",
|
|
211
|
+
"})()"
|
|
212
|
+
].join("");
|
|
417
213
|
}
|
|
418
214
|
async function waitForPresentValue(client, path, readValue, predicate, label, options = {}) {
|
|
419
215
|
return client.waitFor(async () => {
|
|
@@ -457,7 +253,7 @@ function createPluginHandle(client, id) {
|
|
|
457
253
|
}
|
|
458
254
|
async function isLoadedInApp() {
|
|
459
255
|
try {
|
|
460
|
-
return
|
|
256
|
+
return await runEvalJson(client.dev, buildPluginLoadedCode(id));
|
|
461
257
|
} catch {
|
|
462
258
|
return false;
|
|
463
259
|
}
|
|
@@ -565,33 +361,14 @@ function createPluginHandle(client, id) {
|
|
|
565
361
|
}
|
|
566
362
|
};
|
|
567
363
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
}
|
|
577
|
-
};
|
|
578
|
-
var WaitForTimeoutError = class extends Error {
|
|
579
|
-
causeError;
|
|
580
|
-
constructor(message, causeError) {
|
|
581
|
-
super(message);
|
|
582
|
-
this.name = "WaitForTimeoutError";
|
|
583
|
-
this.causeError = causeError;
|
|
584
|
-
}
|
|
585
|
-
};
|
|
586
|
-
var DevEvalError = class extends Error {
|
|
587
|
-
remote;
|
|
588
|
-
constructor(message, remote) {
|
|
589
|
-
super(message);
|
|
590
|
-
this.name = "DevEvalError";
|
|
591
|
-
this.remote = remote;
|
|
592
|
-
if (remote.stack) this.stack = `${this.name}: ${message}\nRemote stack:\n${remote.stack}`;
|
|
593
|
-
}
|
|
594
|
-
};
|
|
364
|
+
function buildPluginLoadedCode(id) {
|
|
365
|
+
return [
|
|
366
|
+
"(()=>{",
|
|
367
|
+
"const __obsidianE2EPlugins=app?.plugins;",
|
|
368
|
+
`return Boolean(__obsidianE2EPlugins?.enabledPlugins?.has?.(${JSON.stringify(id)})&&__obsidianE2EPlugins?.plugins?.[${JSON.stringify(id)}]);`,
|
|
369
|
+
"})()"
|
|
370
|
+
].join("");
|
|
371
|
+
}
|
|
595
372
|
//#endregion
|
|
596
373
|
//#region src/core/transport.ts
|
|
597
374
|
const DEFAULT_TIMEOUT_MS$2 = 3e4;
|
|
@@ -638,6 +415,39 @@ const executeCommand = async ({ allowNonZeroExit = false, argv, bin, cwd, env, t
|
|
|
638
415
|
return result;
|
|
639
416
|
};
|
|
640
417
|
//#endregion
|
|
418
|
+
//#region src/dev/diagnostics.ts
|
|
419
|
+
const DIAGNOSTICS_NAMESPACE = "__obsidianE2EDiagnostics";
|
|
420
|
+
function buildDiagnosticsCode(method) {
|
|
421
|
+
return [
|
|
422
|
+
"(()=>{",
|
|
423
|
+
`const __obsidianE2EMethod=${JSON.stringify(method)};`,
|
|
424
|
+
`const __obsidianE2ENamespace=${JSON.stringify(DIAGNOSTICS_NAMESPACE)};`,
|
|
425
|
+
"const __obsidianE2EMaxEntries=100;",
|
|
426
|
+
"const __obsidianE2EPush=(entries,value)=>{if(entries.length>=__obsidianE2EMaxEntries){entries.shift();}entries.push(value);};",
|
|
427
|
+
"const __obsidianE2EFormat=(value)=>{if(typeof value==='string'){return value;}try{return JSON.stringify(value);}catch{return String(value);}};",
|
|
428
|
+
"const __obsidianE2EClone=(value)=>{try{return JSON.parse(JSON.stringify(value));}catch{return __obsidianE2EFormat(value);}};",
|
|
429
|
+
"const __obsidianE2EPushRuntimeError=(source,errorLike,state)=>{const message=errorLike&&typeof errorLike==='object'&&'message' in errorLike?String(errorLike.message):String(errorLike);const stack=errorLike&&typeof errorLike==='object'&&'stack' in errorLike?String(errorLike.stack):undefined;__obsidianE2EPush(state.runtimeErrors,{at:Date.now(),message,source,stack});};",
|
|
430
|
+
"const root=globalThis;",
|
|
431
|
+
"const state=root[__obsidianE2ENamespace]??(root[__obsidianE2ENamespace]={consoleMessages:[],notices:[],runtimeErrors:[],consolePatched:false,noticePatched:false,runtimePatched:false});",
|
|
432
|
+
"if(!state.consolePatched&&root.console){for(const level of ['debug','error','info','log','warn']){const original=root.console?.[level];if(typeof original!=='function'){continue;}root.console[level]=(...args)=>{__obsidianE2EPush(state.consoleMessages,{args:args.map(__obsidianE2EClone),at:Date.now(),level,text:args.map(__obsidianE2EFormat).join(' ')});return original.apply(root.console,args);};}state.consolePatched=true;}",
|
|
433
|
+
"if(!state.runtimePatched&&typeof root.addEventListener==='function'){root.addEventListener('error',(event)=>{__obsidianE2EPushRuntimeError('error',event?.error??event?.message??'Unknown error',state);});root.addEventListener('unhandledrejection',(event)=>{__obsidianE2EPushRuntimeError('unhandledrejection',event?.reason??'Unhandled rejection',state);});state.runtimePatched=true;}",
|
|
434
|
+
"if(!state.noticePatched&&typeof root.Notice==='function'){const OriginalNotice=root.Notice;root.Notice=new Proxy(OriginalNotice,{construct(target,ctorArgs,newTarget){__obsidianE2EPush(state.notices,{at:Date.now(),message:__obsidianE2EFormat(ctorArgs[0]??''),timeout:typeof ctorArgs[1]==='number'&&Number.isFinite(ctorArgs[1])?ctorArgs[1]:undefined});return Reflect.construct(target,ctorArgs,newTarget);}});state.noticePatched=true;}",
|
|
435
|
+
"if(__obsidianE2EMethod==='reset'){state.consoleMessages.splice(0);state.notices.splice(0);state.runtimeErrors.splice(0);return true;}",
|
|
436
|
+
"if(__obsidianE2EMethod==='consoleMessages'){return state.consoleMessages;}",
|
|
437
|
+
"if(__obsidianE2EMethod==='notices'){return state.notices;}",
|
|
438
|
+
"if(__obsidianE2EMethod==='runtimeErrors'){return state.runtimeErrors;}",
|
|
439
|
+
"return {consoleMessages:state.consoleMessages,notices:state.notices,runtimeErrors:state.runtimeErrors};",
|
|
440
|
+
"})()"
|
|
441
|
+
].join("");
|
|
442
|
+
}
|
|
443
|
+
function createDevDiagnostics(value) {
|
|
444
|
+
return {
|
|
445
|
+
consoleMessages: value?.consoleMessages ?? [],
|
|
446
|
+
notices: value?.notices ?? [],
|
|
447
|
+
runtimeErrors: value?.runtimeErrors ?? []
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
//#endregion
|
|
641
451
|
//#region src/core/wait.ts
|
|
642
452
|
const DEFAULT_INTERVAL_MS = 100;
|
|
643
453
|
const DEFAULT_TIMEOUT_MS$1 = 5e3;
|
|
@@ -701,13 +511,13 @@ function createObsidianClient(options) {
|
|
|
701
511
|
};
|
|
702
512
|
const dev = {
|
|
703
513
|
async activeFilePath(execOptions = {}) {
|
|
704
|
-
return
|
|
514
|
+
return this.eval("app.workspace.getActiveFile()?.path ?? null", execOptions);
|
|
705
515
|
},
|
|
706
516
|
async consoleMessages(execOptions = {}) {
|
|
707
|
-
return
|
|
517
|
+
return readDiagnosticsValue(this, "consoleMessages", execOptions);
|
|
708
518
|
},
|
|
709
519
|
async diagnostics(execOptions = {}) {
|
|
710
|
-
return createDevDiagnostics(await
|
|
520
|
+
return createDevDiagnostics(await readDiagnosticsValue(this, "diagnostics", execOptions));
|
|
711
521
|
},
|
|
712
522
|
async dom(options, execOptions = {}) {
|
|
713
523
|
const output = await client.execText("dev:dom", {
|
|
@@ -724,31 +534,25 @@ function createObsidianClient(options) {
|
|
|
724
534
|
return output;
|
|
725
535
|
},
|
|
726
536
|
async eval(code, execOptions = {}) {
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
message: error.message,
|
|
732
|
-
name: error.name,
|
|
733
|
-
stack: "stack" in error && typeof error.stack === "string" ? error.stack : void 0
|
|
734
|
-
});
|
|
735
|
-
throw error;
|
|
736
|
-
}
|
|
537
|
+
return parseDevEvalOutput(await this.evalRaw(code, execOptions));
|
|
538
|
+
},
|
|
539
|
+
async evalJson(code, execOptions = {}) {
|
|
540
|
+
return runEvalJson(this, code, execOptions);
|
|
737
541
|
},
|
|
738
542
|
async evalRaw(code, execOptions = {}) {
|
|
739
543
|
return client.execText("eval", { code }, execOptions);
|
|
740
544
|
},
|
|
741
545
|
async editorText(execOptions = {}) {
|
|
742
|
-
return
|
|
546
|
+
return this.eval("app.workspace.activeLeaf?.view?.editor?.getValue?.() ?? null", execOptions);
|
|
743
547
|
},
|
|
744
548
|
async notices(execOptions = {}) {
|
|
745
|
-
return
|
|
549
|
+
return readDiagnosticsValue(this, "notices", execOptions);
|
|
746
550
|
},
|
|
747
551
|
async resetDiagnostics(execOptions = {}) {
|
|
748
|
-
await
|
|
552
|
+
await readDiagnosticsValue(this, "reset", execOptions);
|
|
749
553
|
},
|
|
750
554
|
async runtimeErrors(execOptions = {}) {
|
|
751
|
-
return
|
|
555
|
+
return readDiagnosticsValue(this, "runtimeErrors", execOptions);
|
|
752
556
|
},
|
|
753
557
|
async screenshot(targetPath, execOptions = {}) {
|
|
754
558
|
await client.exec("dev:screenshot", { path: targetPath }, execOptions);
|
|
@@ -906,8 +710,8 @@ async function waitForDiagnosticEntry(client, readEntries, predicate, label, opt
|
|
|
906
710
|
message: options?.message ?? label
|
|
907
711
|
});
|
|
908
712
|
}
|
|
909
|
-
async function
|
|
910
|
-
return
|
|
713
|
+
async function readDiagnosticsValue(dev, method, execOptions) {
|
|
714
|
+
return runEvalJson(dev, buildDiagnosticsCode(method), execOptions);
|
|
911
715
|
}
|
|
912
716
|
function getWorkspaceDepth(line) {
|
|
913
717
|
let depth = 0;
|
|
@@ -1202,9 +1006,6 @@ async function createSandboxApi(options) {
|
|
|
1202
1006
|
async cleanup() {
|
|
1203
1007
|
await vault.delete(".", { permanent: true });
|
|
1204
1008
|
},
|
|
1205
|
-
async frontmatter(targetPath) {
|
|
1206
|
-
return options.obsidian.metadata.frontmatter(sandboxPath(targetPath));
|
|
1207
|
-
},
|
|
1208
1009
|
path(...segments) {
|
|
1209
1010
|
return sandboxPath(...segments);
|
|
1210
1011
|
},
|
|
@@ -1212,12 +1013,6 @@ async function createSandboxApi(options) {
|
|
|
1212
1013
|
return parseNoteDocument(await vault.read(targetPath));
|
|
1213
1014
|
},
|
|
1214
1015
|
root,
|
|
1215
|
-
async waitForFrontmatter(targetPath, predicate, waitOptions) {
|
|
1216
|
-
return options.obsidian.metadata.waitForFrontmatter(sandboxPath(targetPath), predicate, waitOptions);
|
|
1217
|
-
},
|
|
1218
|
-
async waitForMetadata(targetPath, predicate, waitOptions) {
|
|
1219
|
-
return options.obsidian.metadata.waitForMetadata(sandboxPath(targetPath), predicate, waitOptions);
|
|
1220
|
-
},
|
|
1221
1016
|
async writeNote(writeOptions) {
|
|
1222
1017
|
const { path, waitForMetadata = true, waitOptions, ...noteInput } = writeOptions;
|
|
1223
1018
|
const document = createNoteDocument(noteInput);
|
|
@@ -1555,4 +1350,4 @@ async function maybeAcquireVaultLock(options, obsidian) {
|
|
|
1555
1350
|
//#endregion
|
|
1556
1351
|
export { clearVaultRunLockMarker as a, createSandboxApi as c, createVaultApi as d, resolveFilesystemPath as f, acquireVaultRunLock as i, DEFAULT_FAILURE_ARTIFACTS_DIR as l, getClientInternals as m, withVaultSandbox as n, inspectVaultRunLock as o, createObsidianClient as p, createBaseFixtures as r, readVaultRunLockMarker as s, createTestContext as t, captureFailureArtifacts as u };
|
|
1557
1352
|
|
|
1558
|
-
//# sourceMappingURL=test-context-
|
|
1353
|
+
//# sourceMappingURL=test-context-Bl-e-83H.mjs.map
|