wdio-obsidian-service 0.1.8 → 0.2.1
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/dist/index.cjs +141 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -13
- package/dist/index.d.ts +61 -13
- package/dist/index.js +145 -46
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.cjs
CHANGED
|
@@ -30,9 +30,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
ObsidianReporter: () => obsidianReporter_default,
|
|
33
34
|
default: () => index_default,
|
|
34
35
|
launcher: () => launcher,
|
|
35
|
-
obsidianBetaAvailable: () => obsidianBetaAvailable
|
|
36
|
+
obsidianBetaAvailable: () => obsidianBetaAvailable,
|
|
37
|
+
obsidianPage: () => obsidianPage_default
|
|
36
38
|
});
|
|
37
39
|
module.exports = __toCommonJS(index_exports);
|
|
38
40
|
|
|
@@ -54,6 +56,68 @@ var import_obsidian_launcher = __toESM(require("obsidian-launcher"), 1);
|
|
|
54
56
|
// src/types.ts
|
|
55
57
|
var OBSIDIAN_CAPABILITY_KEY = "wdio:obsidianOptions";
|
|
56
58
|
|
|
59
|
+
// src/pageobjects/obsidianPage.ts
|
|
60
|
+
var path = __toESM(require("path"), 1);
|
|
61
|
+
var fsAsync = __toESM(require("fs/promises"), 1);
|
|
62
|
+
var ObsidianPage = class {
|
|
63
|
+
/** Enables a plugin */
|
|
64
|
+
async enablePlugin(pluginId) {
|
|
65
|
+
await browser.executeObsidian(
|
|
66
|
+
async ({ app }, pluginId2) => await app.plugins.enablePluginAndSave(pluginId2),
|
|
67
|
+
pluginId
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
/** Disables a plugin */
|
|
71
|
+
async disablePlugin(pluginId) {
|
|
72
|
+
await browser.executeObsidian(
|
|
73
|
+
async ({ app }, pluginId2) => await app.plugins.disablePluginAndSave(pluginId2),
|
|
74
|
+
pluginId
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
/** Sets the theme. Pass "default" to reset to the Obsidian theme. */
|
|
78
|
+
async setTheme(themeName) {
|
|
79
|
+
themeName = themeName == "default" ? "" : themeName;
|
|
80
|
+
await browser.executeObsidian(
|
|
81
|
+
async ({ app }, themeName2) => await app.customCss.setTheme(themeName2),
|
|
82
|
+
themeName
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Opens a file in a new tab.
|
|
87
|
+
*/
|
|
88
|
+
async openFile(path3) {
|
|
89
|
+
await browser.executeObsidian(async ({ app, obsidian }, path4) => {
|
|
90
|
+
const file = app.vault.getAbstractFileByPath(path4);
|
|
91
|
+
if (file instanceof obsidian.TFile) {
|
|
92
|
+
await app.workspace.getLeaf("tab").openFile(file);
|
|
93
|
+
} else {
|
|
94
|
+
throw Error(`No file ${path4} exists`);
|
|
95
|
+
}
|
|
96
|
+
}, path3);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Loads a saved workspace from `workspaces.json` by name. You can use the core "Workspaces" plugin to create the
|
|
100
|
+
* layouts.
|
|
101
|
+
*/
|
|
102
|
+
async loadWorkspaceLayout(layoutName) {
|
|
103
|
+
const vaultPath = await browser.getVaultPath();
|
|
104
|
+
const workspacesPath = path.join(vaultPath, ".obsidian/workspaces.json");
|
|
105
|
+
let layout = void 0;
|
|
106
|
+
try {
|
|
107
|
+
layout = await fsAsync.readFile(workspacesPath, "utf-8");
|
|
108
|
+
} catch {
|
|
109
|
+
throw new Error(`No workspace ${layout} found in .obsidian/workspaces.json`);
|
|
110
|
+
}
|
|
111
|
+
layout = JSON.parse(layout).workspaces?.[layoutName];
|
|
112
|
+
await $(".status-bar").click();
|
|
113
|
+
await browser.executeObsidian(async ({ app }, layout2) => {
|
|
114
|
+
await app.workspace.changeLayout(layout2);
|
|
115
|
+
}, layout);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
var obsidianPage = new ObsidianPage();
|
|
119
|
+
var obsidianPage_default = obsidianPage;
|
|
120
|
+
|
|
57
121
|
// src/browserCommands.ts
|
|
58
122
|
var browserCommands = {
|
|
59
123
|
/** Returns the Obsidian version this test is running under. */
|
|
@@ -65,8 +129,8 @@ var browserCommands = {
|
|
|
65
129
|
return this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].installerVersion;
|
|
66
130
|
},
|
|
67
131
|
/**
|
|
68
|
-
* Wrapper around browser.execute that passes the Obsidian API to the function. The
|
|
69
|
-
*
|
|
132
|
+
* Wrapper around browser.execute that passes the Obsidian API to the function. The first argument to the function
|
|
133
|
+
* is an object containing keys:
|
|
70
134
|
* - app: Obsidian app instance
|
|
71
135
|
* - obsidian: Full Obsidian API
|
|
72
136
|
* See also: https://webdriver.io/docs/api/browser/execute
|
|
@@ -77,6 +141,27 @@ var browserCommands = {
|
|
|
77
141
|
* return app.vault.getMarkdownFiles().find(f => f.path == path)
|
|
78
142
|
* })
|
|
79
143
|
* ```
|
|
144
|
+
*
|
|
145
|
+
* Note: The same caveats as `browser.execute` apply. The function will be stringified and then run inside Obsidian,
|
|
146
|
+
* so you can't capture any local variables. E.g.
|
|
147
|
+
*
|
|
148
|
+
* This *won't* work:
|
|
149
|
+
* ```ts
|
|
150
|
+
* import { FileView } from Obsidian
|
|
151
|
+
* browser.executeObsidian(({app, obsidian}) => {
|
|
152
|
+
* if (leaf.view instanceof FileView) {
|
|
153
|
+
* ...
|
|
154
|
+
* }
|
|
155
|
+
* })
|
|
156
|
+
* ```
|
|
157
|
+
* do this instead:
|
|
158
|
+
* ```ts
|
|
159
|
+
* browser.executeObsidian(({app, obsidian}) => {
|
|
160
|
+
* if (leaf.view instanceof obsidian.FileView) {
|
|
161
|
+
* ...
|
|
162
|
+
* }
|
|
163
|
+
* })
|
|
164
|
+
* ```
|
|
80
165
|
*/
|
|
81
166
|
async executeObsidian(func, ...params) {
|
|
82
167
|
return await browser.execute(
|
|
@@ -84,6 +169,16 @@ var browserCommands = {
|
|
|
84
169
|
...params
|
|
85
170
|
);
|
|
86
171
|
},
|
|
172
|
+
/**
|
|
173
|
+
* Executes an Obsidian command by id.
|
|
174
|
+
* @param id Id of the command to run.
|
|
175
|
+
*/
|
|
176
|
+
async executeObsidianCommand(id) {
|
|
177
|
+
const result = await this.executeObsidian(({ app }, id2) => app.commands.executeCommandById(id2), id);
|
|
178
|
+
if (!result) {
|
|
179
|
+
throw Error(`Obsidian command ${id} not found or failed.`);
|
|
180
|
+
}
|
|
181
|
+
},
|
|
87
182
|
/** Returns the path to the vault opened in Obsidian */
|
|
88
183
|
async getVaultPath() {
|
|
89
184
|
if (this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].vault == void 0) {
|
|
@@ -99,37 +194,15 @@ var browserCommands = {
|
|
|
99
194
|
});
|
|
100
195
|
}
|
|
101
196
|
},
|
|
102
|
-
/** Enables a plugin */
|
|
103
|
-
async enablePlugin(pluginId) {
|
|
104
|
-
await this.executeObsidian(
|
|
105
|
-
async ({ app }, pluginId2) => await app.plugins.enablePluginAndSave(pluginId2),
|
|
106
|
-
pluginId
|
|
107
|
-
);
|
|
108
|
-
},
|
|
109
|
-
/** Disables a plugin */
|
|
110
|
-
async disablePlugin(pluginId) {
|
|
111
|
-
await this.executeObsidian(
|
|
112
|
-
async ({ app }, pluginId2) => await app.plugins.disablePluginAndSave(pluginId2),
|
|
113
|
-
pluginId
|
|
114
|
-
);
|
|
115
|
-
},
|
|
116
|
-
/** Sets the theme. Pass "default" to reset to the Obsidian theme. */
|
|
117
|
-
async setTheme(themeName) {
|
|
118
|
-
themeName = themeName == "default" ? "" : themeName;
|
|
119
|
-
await this.executeObsidian(
|
|
120
|
-
async ({ app }, themeName2) => await app.customCss.setTheme(themeName2),
|
|
121
|
-
themeName
|
|
122
|
-
);
|
|
123
|
-
},
|
|
124
197
|
/**
|
|
125
|
-
*
|
|
126
|
-
*
|
|
198
|
+
* Returns the Workspace page object with convenience helper functions.
|
|
199
|
+
* You can also import the page object directly with
|
|
200
|
+
* ```ts
|
|
201
|
+
* import { obsidianPage } from "wdio-obsidian-service"
|
|
202
|
+
* ```
|
|
127
203
|
*/
|
|
128
|
-
async
|
|
129
|
-
|
|
130
|
-
if (!result) {
|
|
131
|
-
throw Error(`Obsidian command ${id} not found or failed.`);
|
|
132
|
-
}
|
|
204
|
+
async getObsidianPage() {
|
|
205
|
+
return obsidianPage_default;
|
|
133
206
|
}
|
|
134
207
|
};
|
|
135
208
|
var browserCommands_default = browserCommands;
|
|
@@ -140,11 +213,13 @@ async function sleep(ms) {
|
|
|
140
213
|
}
|
|
141
214
|
|
|
142
215
|
// src/service.ts
|
|
216
|
+
var import_semver = __toESM(require("semver"), 1);
|
|
143
217
|
var import_lodash = __toESM(require("lodash"), 1);
|
|
144
218
|
var log = (0, import_logger.default)("wdio-obsidian-service");
|
|
145
219
|
function getDefaultCacheDir() {
|
|
146
220
|
return import_path.default.resolve(process.env.WEBDRIVER_CACHE_DIR ?? "./.obsidian-cache");
|
|
147
221
|
}
|
|
222
|
+
var minSupportedObsidianVersion = "1.0.2";
|
|
148
223
|
var ObsidianLauncherService = class {
|
|
149
224
|
constructor(options, capabilities, config) {
|
|
150
225
|
this.options = options;
|
|
@@ -176,10 +251,13 @@ var ObsidianLauncherService = class {
|
|
|
176
251
|
const obsidianOptions = cap[OBSIDIAN_CAPABILITY_KEY] ?? {};
|
|
177
252
|
const vault = obsidianOptions.vault != void 0 ? import_path.default.resolve(obsidianOptions.vault) : void 0;
|
|
178
253
|
const [appVersion, installerVersion] = await this.obsidianLauncher.resolveVersions(
|
|
179
|
-
cap.browserVersion ?? "latest",
|
|
254
|
+
cap.browserVersion ?? cap[OBSIDIAN_CAPABILITY_KEY]?.appVersion ?? "latest",
|
|
180
255
|
obsidianOptions.installerVersion ?? "earliest"
|
|
181
256
|
);
|
|
182
257
|
const installerVersionInfo = await this.obsidianLauncher.getVersionInfo(installerVersion);
|
|
258
|
+
if (import_semver.default.lt(appVersion, minSupportedObsidianVersion)) {
|
|
259
|
+
throw Error(`Minimum supported Obsidian version is ${minSupportedObsidianVersion}`);
|
|
260
|
+
}
|
|
183
261
|
let installerPath = obsidianOptions.binaryPath;
|
|
184
262
|
if (!installerPath) {
|
|
185
263
|
installerPath = await this.obsidianLauncher.downloadInstaller(installerVersion);
|
|
@@ -352,18 +430,16 @@ var ObsidianWorkerService = class {
|
|
|
352
430
|
({ app }) => [...app.plugins.enabledPlugins].sort()
|
|
353
431
|
);
|
|
354
432
|
for (const pluginId of import_lodash.default.difference(enabledPlugins, plugins, ["wdio-obsidian-service-plugin"])) {
|
|
355
|
-
await
|
|
433
|
+
await obsidianPage_default.disablePlugin(pluginId);
|
|
356
434
|
}
|
|
357
435
|
for (const pluginId of import_lodash.default.difference(plugins, enabledPlugins)) {
|
|
358
|
-
await
|
|
436
|
+
await obsidianPage_default.enablePlugin(pluginId);
|
|
359
437
|
}
|
|
360
|
-
await browser2.executeObsidian(async ({ app }) => await app.plugins.saveConfig());
|
|
361
438
|
}
|
|
362
439
|
if (theme) {
|
|
363
|
-
await
|
|
364
|
-
await browser2.executeObsidian(async ({ app }) => await app.vault.saveConfig());
|
|
440
|
+
await obsidianPage_default.setTheme(theme);
|
|
365
441
|
}
|
|
366
|
-
await sleep(
|
|
442
|
+
await sleep(3e3);
|
|
367
443
|
}
|
|
368
444
|
const sessionId = await browser2.reloadSession({
|
|
369
445
|
// if browserName is set, reloadSession tries to restart the driver entirely, so unset those
|
|
@@ -386,6 +462,29 @@ var ObsidianWorkerService = class {
|
|
|
386
462
|
}
|
|
387
463
|
};
|
|
388
464
|
|
|
465
|
+
// src/obsidianReporter.ts
|
|
466
|
+
var import_spec_reporter = __toESM(require("@wdio/spec-reporter"), 1);
|
|
467
|
+
var ObsidianReporter = class extends import_spec_reporter.default {
|
|
468
|
+
// Override this method to change the label shown for each capability
|
|
469
|
+
getHeaderDisplay(runner) {
|
|
470
|
+
const obsidianOptions = runner.config.capabilities?.["wdio:obsidianOptions"];
|
|
471
|
+
let combo;
|
|
472
|
+
if (obsidianOptions) {
|
|
473
|
+
const appVersion = obsidianOptions.appVersion;
|
|
474
|
+
const installerVersion = obsidianOptions.installerVersion;
|
|
475
|
+
combo = `obsidian v${appVersion} (installer: v${installerVersion})`;
|
|
476
|
+
} else {
|
|
477
|
+
combo = this.getEnviromentCombo(runner.capabilities, void 0, runner.isMultiremote).trim();
|
|
478
|
+
}
|
|
479
|
+
const output = [`Running: ${combo}`];
|
|
480
|
+
if (runner.capabilities.sessionId) {
|
|
481
|
+
output.push(`Session ID: ${runner.capabilities.sessionId}`);
|
|
482
|
+
}
|
|
483
|
+
return output;
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
var obsidianReporter_default = ObsidianReporter;
|
|
487
|
+
|
|
389
488
|
// src/index.ts
|
|
390
489
|
var index_default = ObsidianWorkerService;
|
|
391
490
|
var launcher = ObsidianLauncherService;
|
|
@@ -396,7 +495,9 @@ async function obsidianBetaAvailable(cacheDir) {
|
|
|
396
495
|
}
|
|
397
496
|
// Annotate the CommonJS export names for ESM import in node:
|
|
398
497
|
0 && (module.exports = {
|
|
498
|
+
ObsidianReporter,
|
|
399
499
|
launcher,
|
|
400
|
-
obsidianBetaAvailable
|
|
500
|
+
obsidianBetaAvailable,
|
|
501
|
+
obsidianPage
|
|
401
502
|
});
|
|
402
503
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../../../node_modules/tsup/assets/cjs_shims.js","../src/service.ts","../src/types.ts","../src/browserCommands.ts","../src/utils.ts"],"sourcesContent":["import ObsidianLauncher from \"obsidian-launcher\"\nimport { ObsidianLauncherService, ObsidianWorkerService } from \"./service.js\";\n\nexport default ObsidianWorkerService;\nexport const launcher = ObsidianLauncherService;\n\nexport type { ObsidianServiceOptions, ObsidianCapabilityOptions } from \"./types.js\";\n\nexport type {\n LocalPluginEntry, GitHubPluginEntry, CommunityPluginEntry, PluginEntry,\n LocalThemeEntry, GitHubThemeEntry, CommunityThemeEntry, ThemeEntry,\n} from \"obsidian-launcher\"\n\n/**\n * Returns true if there's currently an Obsidian beta and we have the credentials to download it or it's already in the\n * cache.\n */\nexport async function obsidianBetaAvailable(cacheDir?: string) {\n const launcher = new ObsidianLauncher({cacheDir: cacheDir});\n const versionInfo = await launcher.getVersionInfo(\"latest-beta\");\n return versionInfo.isBeta && await launcher.isAvailable(versionInfo.version);\n}\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () =>\n typeof document === 'undefined'\n ? new URL(`file:${__filename}`).href\n : (document.currentScript && document.currentScript.src) ||\n new URL('main.js', document.baseURI).href\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import fsAsync from \"fs/promises\"\nimport path from \"path\"\nimport { SevereServiceError } from 'webdriverio'\nimport type { Capabilities, Options, Services } from '@wdio/types'\nimport logger from '@wdio/logger'\nimport { fileURLToPath } from \"url\"\nimport ObsidianLauncher, { DownloadedPluginEntry, DownloadedThemeEntry } from \"obsidian-launcher\"\nimport browserCommands from \"./browserCommands.js\"\nimport { ObsidianCapabilityOptions, ObsidianServiceOptions, OBSIDIAN_CAPABILITY_KEY } from \"./types.js\"\nimport { sleep } from \"./utils.js\"\nimport _ from \"lodash\"\n\n\nconst log = logger(\"wdio-obsidian-service\");\n\nfunction getDefaultCacheDir() {\n return path.resolve(process.env.WEBDRIVER_CACHE_DIR ?? \"./.obsidian-cache\")\n}\n\nexport class ObsidianLauncherService implements Services.ServiceInstance {\n private obsidianLauncher: ObsidianLauncher\n private readonly helperPluginPath: string\n\n constructor (\n public options: ObsidianServiceOptions,\n public capabilities: WebdriverIO.Capabilities,\n public config: Options.Testrunner\n ) {\n this.obsidianLauncher = new ObsidianLauncher({\n cacheDir: config.cacheDir ?? getDefaultCacheDir(),\n versionsUrl: options.versionsUrl,\n communityPluginsUrl: options.communityPluginsUrl, communityThemesUrl: options.communityThemesUrl,\n });\n this.helperPluginPath = path.resolve(path.join(fileURLToPath(import.meta.url), '../../helper-plugin'));\n }\n\n async onPrepare(config: Options.Testrunner, capabilities: Capabilities.TestrunnerCapabilities) {\n if (!Array.isArray(capabilities)) {\n capabilities = Object.values(capabilities as Capabilities.RequestedMultiremoteCapabilities).map(\n (multiremoteOption) => (multiremoteOption as Capabilities.WithRequestedCapabilities).capabilities,\n );\n }\n\n const obsidianCapabilities = capabilities.flatMap((cap) => {\n if ((\"browserName\" in cap) && cap.browserName === \"obsidian\") {\n return [cap as WebdriverIO.Capabilities];\n } else {\n return [];\n }\n });\n\n try {\n for (const cap of obsidianCapabilities) {\n const obsidianOptions = cap[OBSIDIAN_CAPABILITY_KEY] ?? {};\n \n const vault = obsidianOptions.vault != undefined ? path.resolve(obsidianOptions.vault) : undefined;\n \n const [appVersion, installerVersion] = await this.obsidianLauncher.resolveVersions(\n cap.browserVersion ?? \"latest\",\n obsidianOptions.installerVersion ?? \"earliest\",\n );\n const installerVersionInfo = await this.obsidianLauncher.getVersionInfo(installerVersion);\n\n let installerPath = obsidianOptions.binaryPath;\n if (!installerPath) {\n installerPath = await this.obsidianLauncher.downloadInstaller(installerVersion);\n }\n let appPath = obsidianOptions.appPath;\n if (!appPath) {\n appPath = await this.obsidianLauncher.downloadApp(appVersion);\n }\n let chromedriverPath = cap['wdio:chromedriverOptions']?.binary\n // wdio can download chromedriver for versions greater than 115 automatically\n if (!chromedriverPath && Number(installerVersionInfo.chromeVersion!.split(\".\")[0]) <= 115) {\n chromedriverPath = await this.obsidianLauncher.downloadChromedriver(installerVersion);\n }\n\n let plugins = obsidianOptions.plugins ?? [\".\"];\n plugins.push(this.helperPluginPath); // Always install the helper plugin\n plugins = await this.obsidianLauncher.downloadPlugins(plugins);\n\n const themes = await this.obsidianLauncher.downloadThemes(obsidianOptions.themes ?? []);\n\n const args = [\n // Workaround for SUID issue on AppImages. See https://github.com/electron/electron/issues/42510\n ...(process.platform == 'linux' ? [\"--no-sandbox\"] : []),\n ...(cap['goog:chromeOptions']?.args ?? [])\n ];\n\n cap.browserName = \"chrome\";\n cap.browserVersion = installerVersionInfo.chromeVersion;\n cap[OBSIDIAN_CAPABILITY_KEY] = {\n ...obsidianOptions,\n plugins: plugins,\n themes: themes,\n binaryPath: installerPath,\n appPath: appPath,\n vault: vault,\n appVersion: appVersion, // Resolve the versions\n installerVersion: installerVersion,\n };\n cap['goog:chromeOptions'] = {\n binary: installerPath,\n windowTypes: [\"app\", \"webview\"],\n ...cap['goog:chromeOptions'],\n args: args,\n }\n cap['wdio:chromedriverOptions'] = {\n // allowedIps is not included in the types, but gets passed as --allowed-ips to chromedriver.\n // It defaults to [\"0.0.0.0\"] which makes Windows Firewall complain, and we don't need remote\n // connections anyways.\n allowedIps: [],\n ...cap['wdio:chromedriverOptions'],\n binary: chromedriverPath,\n } as any\n cap[\"wdio:enforceWebDriverClassic\"] = true;\n }\n } catch (e: any) {\n // By default wdio just logs service errors, throwing this makes it bail if anything goes wrong.\n throw new SevereServiceError(`Failed to download and setup Obsidian. Caused by: ${e.stack}\\n`+\n ` ------The above causes:-----`);\n }\n }\n}\n\nexport class ObsidianWorkerService implements Services.ServiceInstance {\n private obsidianLauncher: ObsidianLauncher\n /** Directories to clean up after the tests */\n private tmpDirs: string[]\n\n constructor (\n public options: ObsidianServiceOptions,\n public capabilities: WebdriverIO.Capabilities,\n public config: Options.Testrunner\n ) {\n this.obsidianLauncher = new ObsidianLauncher({\n cacheDir: config.cacheDir ?? getDefaultCacheDir(),\n versionsUrl: options.versionsUrl,\n communityPluginsUrl: options.communityPluginsUrl, communityThemesUrl: options.communityThemesUrl,\n });\n this.tmpDirs = [];\n }\n\n private async setupObsidian(obsidianOptions: ObsidianCapabilityOptions) {\n let vault = obsidianOptions.vault;\n if (vault != undefined) {\n log.info(`Opening vault ${obsidianOptions.vault}`);\n vault = await this.obsidianLauncher.setupVault({\n vault,\n copy: true,\n plugins: obsidianOptions.plugins,\n themes: obsidianOptions.themes,\n });\n this.tmpDirs.push(vault);\n } else {\n log.info(`Opening Obsidian without a vault`)\n }\n\n const configDir = await this.obsidianLauncher.setupConfigDir({\n appVersion: obsidianOptions.appVersion!, installerVersion: obsidianOptions.installerVersion!,\n appPath: obsidianOptions.appPath!,\n vault: vault,\n });\n this.tmpDirs.push(configDir);\n\n return configDir;\n }\n\n private async waitForReady(browser: WebdriverIO.Browser) {\n if (browser.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].vault != undefined) {\n await browser.waitUntil( // wait until the helper plugin is loaded\n () => browser.execute(() => !!(window as any).wdioObsidianService),\n {timeout: 30 * 1000, interval: 100},\n );\n await browser.executeObsidian(async ({app}) => {\n await new Promise<void>((resolve) => app.workspace.onLayoutReady(resolve) );\n })\n }\n }\n\n async beforeSession(config: Options.Testrunner, capabilities: WebdriverIO.Capabilities) {\n if (!capabilities[OBSIDIAN_CAPABILITY_KEY]) return;\n\n const configDir = await this.setupObsidian(capabilities[OBSIDIAN_CAPABILITY_KEY]);\n\n capabilities['goog:chromeOptions']!.args = [\n `--user-data-dir=${configDir}`,\n ...(capabilities['goog:chromeOptions']!.args ?? [])\n ];\n }\n\n private selectPlugins(currentPlugins: DownloadedPluginEntry[], selection?: string[]) {\n if (selection !== undefined) {\n const unknownPlugins = _.difference(selection, currentPlugins.map(p => p.id));\n if (unknownPlugins.length > 0) {\n throw Error(`Unknown plugin ids: ${unknownPlugins.join(', ')}`)\n }\n return currentPlugins.map(p => ({\n ...p,\n enabled: selection.includes(p.id) || p.id == \"wdio-obsidian-service-plugin\",\n }));\n } else {\n return currentPlugins;\n }\n }\n\n private selectThemes(currentThemes: DownloadedThemeEntry[], selection?: string) {\n if (selection !== undefined) {\n if (selection != \"default\" && currentThemes.every((t: any) => t.name != selection)) {\n throw Error(`Unknown theme: ${selection}`);\n }\n return currentThemes.map((t: any) => ({...t, enabled: selection != 'default' && t.name === selection}));\n } else {\n return currentThemes;\n }\n }\n\n async before(capabilities: WebdriverIO.Capabilities, specs: never, browser: WebdriverIO.Browser) {\n // There's a slow event listener link on the browser \"command\" event when you reloadSession that causes some\n // warnings. This will silence them. TODO: Make issue or PR to wdio to fix this.\n browser.setMaxListeners(1000);\n\n if (!capabilities[OBSIDIAN_CAPABILITY_KEY]) return;\n\n const service = this; // eslint-disable-line @typescript-eslint/no-this-alias\n const reloadObsidian: typeof browser['reloadObsidian'] = async function(\n this: WebdriverIO.Browser,\n {vault, plugins, theme} = {},\n ) {\n const oldObsidianOptions = this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY];\n let newCapabilities: WebdriverIO.Capabilities\n\n if (vault) {\n const newObsidianOptions = {\n ...oldObsidianOptions,\n vault: path.resolve(vault),\n plugins: service.selectPlugins(oldObsidianOptions.plugins, plugins),\n themes: service.selectThemes(oldObsidianOptions.themes, theme),\n }\n \n const configDir = await service.setupObsidian(newObsidianOptions);\n \n const newArgs = [\n `--user-data-dir=${configDir}`,\n ...this.requestedCapabilities['goog:chromeOptions'].args.filter((arg: string) => {\n const match = arg.match(/^--user-data-dir=(.*)$/);\n return !match || !service.tmpDirs.includes(match[1]);\n }),\n ]\n \n newCapabilities = {\n [OBSIDIAN_CAPABILITY_KEY]: newObsidianOptions,\n 'goog:chromeOptions': {\n ...this.requestedCapabilities['goog:chromeOptions'],\n args: newArgs,\n },\n };\n } else {\n // preserve vault and config dir\n newCapabilities = {};\n // Since we aren't recreating the vault, we'll need to reset plugins and themes here if specified.\n if (plugins) {\n const enabledPlugins = await browser.executeObsidian(({app}) =>\n [...(app as any).plugins.enabledPlugins].sort()\n )\n for (const pluginId of _.difference(enabledPlugins, plugins, ['wdio-obsidian-service-plugin'])) {\n await browser.disablePlugin(pluginId);\n }\n for (const pluginId of _.difference(plugins, enabledPlugins)) {\n await browser.enablePlugin(pluginId);\n }\n await browser.executeObsidian(async ({app}) => await (app as any).plugins.saveConfig())\n }\n if (theme) {\n await browser.setTheme(theme);\n await browser.executeObsidian(async ({app}) => await (app.vault as any).saveConfig())\n }\n // Obsidian debounces saves to the config dir, and so changes to plugin list, themes, and anything else\n // you set in your tests may not get saved to disk before the reboot. I haven't found a better way to\n // make sure everything's saved then just waiting a bit.\n await sleep(2000);\n }\n\n const sessionId = await browser.reloadSession({\n // if browserName is set, reloadSession tries to restart the driver entirely, so unset those\n ..._.omit(this.requestedCapabilities, ['browserName', 'browserVersion']),\n ...newCapabilities,\n });\n await service.waitForReady(this);\n return sessionId;\n }\n\n await browser.addCommand(\"reloadObsidian\", reloadObsidian);\n\n for (const [name, cmd] of Object.entries(browserCommands)) {\n await browser.addCommand(name, cmd);\n }\n\n await service.waitForReady(browser);\n }\n\n async afterSession() {\n for (const tmpDir of this.tmpDirs) {\n await fsAsync.rm(tmpDir, { recursive: true, force: true });\n }\n }\n}\n","import type { ObsidianBrowserCommands } from \"./browserCommands.js\";\nimport type { PluginEntry, ThemeEntry } from \"obsidian-launcher\";\n\nexport const OBSIDIAN_CAPABILITY_KEY = \"wdio:obsidianOptions\" as const;\n\nexport interface ObsidianServiceOptions {\n /**\n * Override the `obsidian-versions.json` used by the service. Can be a file URL.\n * This is only really useful for this package's own internal tests.\n */\n versionsUrl?: string,\n /**\n * Override the `community-plugins.json` used by the service. Can be a file URL.\n * This is only really useful for this package's own internal tests.\n */\n communityPluginsUrl?: string,\n /**\n * Override the `community-css-themes.json` used by the service. Can be a file URL.\n * This is only really useful for this package's own internal tests.\n */\n communityThemesUrl?: string,\n}\n\nexport interface ObsidianCapabilityOptions {\n /**\n * Version of Obsidian to run.\n * \n * Can be set to \"latest\", \"latest-beta\", or a specific version. Defaults to \"latest\". To download beta versions\n * you'll need to be an Obsidian insider and set the OBSIDIAN_USERNAME and OBSIDIAN_PASSWORD environment\n * variables.\n * \n * You can also use the wdio capability `browserVersion` field to set the Obsidian version.\n */\n appVersion?: string\n\n /**\n * Version of the Obsidian Installer to download.\n * \n * Note that Obsidian is distributed in two parts, the \"installer\", which is the executable containing Electron, and\n * the \"app\" which is a bundle of JavaScript containing the Obsidian code. Obsidian's self-update system only\n * updates the JavaScript bundle, and not the base installer/Electron version. This makes Obsidian's auto-update\n * fast as it only needs to download a few MiB of JS instead of all of Electron. But, it means different users with\n * the same Obsidian version may be running on different versions of Electron, which could cause subtle differences\n * in plugin behavior if you are using newer JavaScript features and the like in your plugin.\n * \n * If passed \"latest\", it will use the maximum installer version compatible with the selected Obsidian version. If\n * passed \"earliest\" it will use the oldest installer version compatible with the selected Obsidian version. The \n * default is \"earliest\".\n */\n installerVersion?: string,\n\n /**\n * List of plugins to install.\n * \n * Each entry is a path to the local plugin to install, e.g. [\".\"] or [\"dist\"] depending on your build setup. You\n * can also pass objects. If you pass an object it can contain one of either `path` (to install a local plugin),\n * `repo` (to install a plugin from github), or `id` (to install a community plugin). You can set `enabled: false`\n * to install the plugin but start it disabled. You can enable the plugin later using `reloadObsidian` or the\n * `enablePlugin` command.\n */\n plugins?: PluginEntry[],\n\n /**\n * List of themes to install.\n * \n * Each entry is a path to the local theme to install. You can also pass an object. If you pass an object it can\n * contain one of either `path` (to install a local theme), `repo` (to install a theme from github), or `name` (to\n * install a community theme). You can set `enabled: false` to install the theme, but start it disabled. You can\n * only have one enabled theme, so if you pass multiple you'll have to disable all but one.\n */\n themes?: ThemeEntry[],\n\n /**\n * The path to the vault to open.\n * \n * The vault will be copied, so any changes made in your tests won't affect the original. If omitted, no vault will\n * be opened and you'll need to call `browser.reloadObsidian` to open a vault during your tests.\n */\n vault?: string,\n\n /** Path to the Obsidian binary to use. If omitted it will download Obsidian automatically. */\n binaryPath?: string,\n\n /** Path to the app asar to load into obsidian. If omitted it will be downloaded automatically. */\n appPath?: string,\n}\n\n\ndeclare global {\n namespace WebdriverIO {\n interface Capabilities {\n [OBSIDIAN_CAPABILITY_KEY]?: ObsidianCapabilityOptions,\n }\n\n interface Browser extends ObsidianBrowserCommands {\n /**\n * Relaunch obsidian. Can be used to switch to a new vault, change the plugin list, or just to reboot\n * Obsidian.\n * \n * As this does a full reboot of Obsidian, avoid calling this too often so you don't slow your tests down.\n * You can also set the vault in the `wdio.conf.ts` capabilities section which may be useful if all\n * your tests use the same vault.\n * \n * @param vault Path to the vault to open. The vault will be copied, so any changes made in your tests won't\n * be persited to the original. If omitted, it will reboot Obsidian with the current vault, without\n * creating a new copy of the vault.\n * @param plugins List of plugin ids to enable. If omitted it will keep current plugin list. Note, all the\n * plugins must be defined in your wdio.conf.ts capabilities. You can also use the enablePlugin and \n * disablePlugin commands to change plugins without relaunching Obsidian.\n * @param theme Name of the theme to enable. If omitted it will keep the current theme. Pass \"default\" to\n * switch back to the default theme. Like with plugins, the theme must be defined in wdio.conf.ts.\n * @returns Returns the new sessionId (same as browser.reloadSession()).\n */\n reloadObsidian(params?: {\n vault?: string,\n plugins?: string[], theme?: string,\n }): Promise<string>;\n }\n }\n}\n","import { OBSIDIAN_CAPABILITY_KEY } from \"./types.js\";\nimport type * as obsidian from \"obsidian\"\n\n\ntype ExecuteObsidianArg = {\n /**\n * There is a global \"app\" instance, but that may be removed in the future so you can use this to access it from\n * tests. See https://docs.obsidian.md/Plugins/Releasing/Plugin+guidelines#Avoid+using+global+app+instance\n */\n app: obsidian.App,\n\n /**\n * The full obsidian API. See https://github.com/obsidianmd/obsidian-api/blob/master/obsidian.d.ts\n */\n obsidian: typeof obsidian,\n}\n\nconst browserCommands = {\n /** Returns the Obsidian version this test is running under. */\n async getObsidianVersion(this: WebdriverIO.Browser): Promise<string> {\n return this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].appVersion;\n },\n\n /** Returns the Obsidian installer version this test is running under. */\n async getObsidianInstallerVersion(this: WebdriverIO.Browser): Promise<string> {\n return this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].installerVersion;\n },\n\n /**\n * Wrapper around browser.execute that passes the Obsidian API to the function. The function will be run inside\n * Obsidian. The first argument to the function is an object containing keys:\n * - app: Obsidian app instance\n * - obsidian: Full Obsidian API\n * See also: https://webdriver.io/docs/api/browser/execute\n * \n * Example usage\n * ```ts\n * const file = browser.executeObsidian(({app, obsidian}, path) => {\n * return app.vault.getMarkdownFiles().find(f => f.path == path)\n * })\n * ```\n */\n async executeObsidian<Return, Params extends unknown[]>(\n func: (obs: ExecuteObsidianArg, ...params: Params) => Return,\n ...params: Params\n ): Promise<Return> {\n return await browser.execute<Return, Params>(\n `return (${func.toString()}).call(null, {...window.wdioObsidianService}, ...arguments )`,\n ...params,\n )\n },\n\n /** Returns the path to the vault opened in Obsidian */\n async getVaultPath(this: WebdriverIO.Browser): Promise<string|undefined> {\n if (this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].vault == undefined) {\n return undefined; // no vault open\n } else { // return the actual path to the vault\n return await this.executeObsidian(({app, obsidian}) => {\n if (app.vault.adapter instanceof obsidian.FileSystemAdapter) {\n return app.vault.adapter.getBasePath()\n } else { // TODO handle CapacitorAdapater\n throw new Error(`Unrecognized DataAdapater type`)\n };\n })\n }\n },\n\n /** Enables a plugin */\n async enablePlugin(this: WebdriverIO.Browser, pluginId: string): Promise<void> {\n await this.executeObsidian(\n async ({app}, pluginId) => await (app as any).plugins.enablePluginAndSave(pluginId),\n pluginId,\n );\n },\n\n /** Disables a plugin */\n async disablePlugin(this: WebdriverIO.Browser, pluginId: string): Promise<void> {\n await this.executeObsidian(\n async ({app}, pluginId) => await (app as any).plugins.disablePluginAndSave(pluginId),\n pluginId,\n );\n },\n\n /** Sets the theme. Pass \"default\" to reset to the Obsidian theme. */\n async setTheme(this: WebdriverIO.Browser, themeName: string): Promise<void> {\n themeName = themeName == 'default' ? '' : themeName;\n await this.executeObsidian(\n async ({app}, themeName) => await (app as any).customCss.setTheme(themeName),\n themeName,\n )\n },\n\n /**\n * Executes an Obsidian command.\n * @param id Id of the command to run.\n */\n async executeObsidianCommand(this: WebdriverIO.Browser, id: string) {\n const result = await this.executeObsidian(({app}, id) => (app as any).commands.executeCommandById(id), id);\n if (!result) {\n throw Error(`Obsidian command ${id} not found or failed.`);\n }\n },\n} as const\n\nexport type ObsidianBrowserCommands = typeof browserCommands;\nexport default browserCommands;\n","export async function sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}"],"mappings":"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","names":["import_obsidian_launcher","pluginId","themeName","id","logger","path","ObsidianLauncher","browser","_","fsAsync","launcher","ObsidianLauncher"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../../../node_modules/tsup/assets/cjs_shims.js","../src/service.ts","../src/types.ts","../src/pageobjects/obsidianPage.ts","../src/browserCommands.ts","../src/utils.ts","../src/obsidianReporter.ts"],"sourcesContent":["import ObsidianLauncher from \"obsidian-launcher\";\nimport { ObsidianLauncherService, ObsidianWorkerService } from \"./service.js\";\n\nexport default ObsidianWorkerService;\nexport const launcher = ObsidianLauncherService;\n\nexport type { ObsidianServiceOptions, ObsidianCapabilityOptions } from \"./types.js\";\n\nexport { default as obsidianPage } from \"./pageobjects/obsidianPage.js\";\n\nexport type {\n LocalPluginEntry, GitHubPluginEntry, CommunityPluginEntry, PluginEntry,\n LocalThemeEntry, GitHubThemeEntry, CommunityThemeEntry, ThemeEntry,\n} from \"obsidian-launcher\";\n\nexport { default as ObsidianReporter } from \"./obsidianReporter.js\";\n\n/**\n * Returns true if there's currently an Obsidian beta and we have the credentials to download it or it's already in the\n * cache.\n */\nexport async function obsidianBetaAvailable(cacheDir?: string) {\n const launcher = new ObsidianLauncher({cacheDir: cacheDir});\n const versionInfo = await launcher.getVersionInfo(\"latest-beta\");\n return versionInfo.isBeta && await launcher.isAvailable(versionInfo.version);\n}\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () =>\n typeof document === 'undefined'\n ? new URL(`file:${__filename}`).href\n : (document.currentScript && document.currentScript.src) ||\n new URL('main.js', document.baseURI).href\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import fsAsync from \"fs/promises\"\nimport path from \"path\"\nimport { SevereServiceError } from 'webdriverio'\nimport type { Capabilities, Options, Services } from '@wdio/types'\nimport logger from '@wdio/logger'\nimport { fileURLToPath } from \"url\"\nimport ObsidianLauncher, { DownloadedPluginEntry, DownloadedThemeEntry } from \"obsidian-launcher\"\nimport browserCommands from \"./browserCommands.js\"\nimport { ObsidianCapabilityOptions, ObsidianServiceOptions, OBSIDIAN_CAPABILITY_KEY } from \"./types.js\"\nimport obsidianPage from \"./pageobjects/obsidianPage.js\"\nimport { sleep } from \"./utils.js\"\nimport semver from \"semver\"\nimport _ from \"lodash\"\n\n\nconst log = logger(\"wdio-obsidian-service\");\n\nfunction getDefaultCacheDir() {\n return path.resolve(process.env.WEBDRIVER_CACHE_DIR ?? \"./.obsidian-cache\")\n}\n\n/**\n * Minimum Obsidian version that wdio-obsidian-service supports.\n */\nexport const minSupportedObsidianVersion: string = \"1.0.2\"\n\n\nexport class ObsidianLauncherService implements Services.ServiceInstance {\n private obsidianLauncher: ObsidianLauncher\n private readonly helperPluginPath: string\n\n constructor (\n public options: ObsidianServiceOptions,\n public capabilities: WebdriverIO.Capabilities,\n public config: Options.Testrunner\n ) {\n this.obsidianLauncher = new ObsidianLauncher({\n cacheDir: config.cacheDir ?? getDefaultCacheDir(),\n versionsUrl: options.versionsUrl,\n communityPluginsUrl: options.communityPluginsUrl, communityThemesUrl: options.communityThemesUrl,\n });\n this.helperPluginPath = path.resolve(path.join(fileURLToPath(import.meta.url), '../../helper-plugin'));\n }\n\n async onPrepare(config: Options.Testrunner, capabilities: Capabilities.TestrunnerCapabilities) {\n if (!Array.isArray(capabilities)) {\n capabilities = Object.values(capabilities as Capabilities.RequestedMultiremoteCapabilities).map(\n (multiremoteOption) => (multiremoteOption as Capabilities.WithRequestedCapabilities).capabilities,\n );\n }\n\n const obsidianCapabilities = capabilities.flatMap((cap) => {\n if ((\"browserName\" in cap) && cap.browserName === \"obsidian\") {\n return [cap as WebdriverIO.Capabilities];\n } else {\n return [];\n }\n });\n\n try {\n for (const cap of obsidianCapabilities) {\n const obsidianOptions = cap[OBSIDIAN_CAPABILITY_KEY] ?? {};\n \n const vault = obsidianOptions.vault != undefined ? path.resolve(obsidianOptions.vault) : undefined;\n \n const [appVersion, installerVersion] = await this.obsidianLauncher.resolveVersions(\n cap.browserVersion ?? cap[OBSIDIAN_CAPABILITY_KEY]?.appVersion ?? \"latest\",\n obsidianOptions.installerVersion ?? \"earliest\",\n );\n const installerVersionInfo = await this.obsidianLauncher.getVersionInfo(installerVersion);\n if (semver.lt(appVersion, minSupportedObsidianVersion)) {\n throw Error(`Minimum supported Obsidian version is ${minSupportedObsidianVersion}`)\n }\n\n let installerPath = obsidianOptions.binaryPath;\n if (!installerPath) {\n installerPath = await this.obsidianLauncher.downloadInstaller(installerVersion);\n }\n let appPath = obsidianOptions.appPath;\n if (!appPath) {\n appPath = await this.obsidianLauncher.downloadApp(appVersion);\n }\n let chromedriverPath = cap['wdio:chromedriverOptions']?.binary\n // wdio can download chromedriver for versions greater than 115 automatically\n if (!chromedriverPath && Number(installerVersionInfo.chromeVersion!.split(\".\")[0]) <= 115) {\n chromedriverPath = await this.obsidianLauncher.downloadChromedriver(installerVersion);\n }\n\n let plugins = obsidianOptions.plugins ?? [\".\"];\n plugins.push(this.helperPluginPath); // Always install the helper plugin\n plugins = await this.obsidianLauncher.downloadPlugins(plugins);\n\n const themes = await this.obsidianLauncher.downloadThemes(obsidianOptions.themes ?? []);\n\n const args = [\n // Workaround for SUID issue on AppImages. See https://github.com/electron/electron/issues/42510\n ...(process.platform == 'linux' ? [\"--no-sandbox\"] : []),\n ...(cap['goog:chromeOptions']?.args ?? [])\n ];\n\n cap.browserName = \"chrome\";\n cap.browserVersion = installerVersionInfo.chromeVersion;\n cap[OBSIDIAN_CAPABILITY_KEY] = {\n ...obsidianOptions,\n plugins: plugins,\n themes: themes,\n binaryPath: installerPath,\n appPath: appPath,\n vault: vault,\n appVersion: appVersion, // Resolve the versions\n installerVersion: installerVersion,\n };\n cap['goog:chromeOptions'] = {\n binary: installerPath,\n windowTypes: [\"app\", \"webview\"],\n ...cap['goog:chromeOptions'],\n args: args,\n }\n cap['wdio:chromedriverOptions'] = {\n // allowedIps is not included in the types, but gets passed as --allowed-ips to chromedriver.\n // It defaults to [\"0.0.0.0\"] which makes Windows Firewall complain, and we don't need remote\n // connections anyways.\n allowedIps: [],\n ...cap['wdio:chromedriverOptions'],\n binary: chromedriverPath,\n } as any\n cap[\"wdio:enforceWebDriverClassic\"] = true;\n }\n } catch (e: any) {\n // By default wdio just logs service errors, throwing this makes it bail if anything goes wrong.\n throw new SevereServiceError(`Failed to download and setup Obsidian. Caused by: ${e.stack}\\n`+\n ` ------The above causes:-----`);\n }\n }\n}\n\nexport class ObsidianWorkerService implements Services.ServiceInstance {\n private obsidianLauncher: ObsidianLauncher\n /** Directories to clean up after the tests */\n private tmpDirs: string[]\n\n constructor (\n public options: ObsidianServiceOptions,\n public capabilities: WebdriverIO.Capabilities,\n public config: Options.Testrunner\n ) {\n this.obsidianLauncher = new ObsidianLauncher({\n cacheDir: config.cacheDir ?? getDefaultCacheDir(),\n versionsUrl: options.versionsUrl,\n communityPluginsUrl: options.communityPluginsUrl, communityThemesUrl: options.communityThemesUrl,\n });\n this.tmpDirs = [];\n }\n\n private async setupObsidian(obsidianOptions: ObsidianCapabilityOptions) {\n let vault = obsidianOptions.vault;\n if (vault != undefined) {\n log.info(`Opening vault ${obsidianOptions.vault}`);\n vault = await this.obsidianLauncher.setupVault({\n vault,\n copy: true,\n plugins: obsidianOptions.plugins,\n themes: obsidianOptions.themes,\n });\n this.tmpDirs.push(vault);\n } else {\n log.info(`Opening Obsidian without a vault`)\n }\n\n const configDir = await this.obsidianLauncher.setupConfigDir({\n appVersion: obsidianOptions.appVersion!, installerVersion: obsidianOptions.installerVersion!,\n appPath: obsidianOptions.appPath!,\n vault: vault,\n });\n this.tmpDirs.push(configDir);\n\n return configDir;\n }\n\n private async waitForReady(browser: WebdriverIO.Browser) {\n if (browser.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].vault != undefined) {\n await browser.waitUntil( // wait until the helper plugin is loaded\n () => browser.execute(() => !!(window as any).wdioObsidianService),\n {timeout: 30 * 1000, interval: 100},\n );\n await browser.executeObsidian(async ({app}) => {\n await new Promise<void>((resolve) => app.workspace.onLayoutReady(resolve) );\n })\n }\n }\n\n async beforeSession(config: Options.Testrunner, capabilities: WebdriverIO.Capabilities) {\n if (!capabilities[OBSIDIAN_CAPABILITY_KEY]) return;\n\n const configDir = await this.setupObsidian(capabilities[OBSIDIAN_CAPABILITY_KEY]);\n\n capabilities['goog:chromeOptions']!.args = [\n `--user-data-dir=${configDir}`,\n ...(capabilities['goog:chromeOptions']!.args ?? [])\n ];\n }\n\n private selectPlugins(currentPlugins: DownloadedPluginEntry[], selection?: string[]) {\n if (selection !== undefined) {\n const unknownPlugins = _.difference(selection, currentPlugins.map(p => p.id));\n if (unknownPlugins.length > 0) {\n throw Error(`Unknown plugin ids: ${unknownPlugins.join(', ')}`)\n }\n return currentPlugins.map(p => ({\n ...p,\n enabled: selection.includes(p.id) || p.id == \"wdio-obsidian-service-plugin\",\n }));\n } else {\n return currentPlugins;\n }\n }\n\n private selectThemes(currentThemes: DownloadedThemeEntry[], selection?: string) {\n if (selection !== undefined) {\n if (selection != \"default\" && currentThemes.every((t: any) => t.name != selection)) {\n throw Error(`Unknown theme: ${selection}`);\n }\n return currentThemes.map((t: any) => ({...t, enabled: selection != 'default' && t.name === selection}));\n } else {\n return currentThemes;\n }\n }\n\n async before(capabilities: WebdriverIO.Capabilities, specs: never, browser: WebdriverIO.Browser) {\n // There's a slow event listener link on the browser \"command\" event when you reloadSession that causes some\n // warnings. This will silence them. TODO: Make issue or PR to wdio to fix this.\n browser.setMaxListeners(1000);\n\n if (!capabilities[OBSIDIAN_CAPABILITY_KEY]) return;\n\n const service = this; // eslint-disable-line @typescript-eslint/no-this-alias\n const reloadObsidian: typeof browser['reloadObsidian'] = async function(\n this: WebdriverIO.Browser,\n {vault, plugins, theme} = {},\n ) {\n const oldObsidianOptions = this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY];\n let newCapabilities: WebdriverIO.Capabilities\n\n if (vault) {\n const newObsidianOptions = {\n ...oldObsidianOptions,\n vault: path.resolve(vault),\n plugins: service.selectPlugins(oldObsidianOptions.plugins, plugins),\n themes: service.selectThemes(oldObsidianOptions.themes, theme),\n }\n \n const configDir = await service.setupObsidian(newObsidianOptions);\n \n const newArgs = [\n `--user-data-dir=${configDir}`,\n ...this.requestedCapabilities['goog:chromeOptions'].args.filter((arg: string) => {\n const match = arg.match(/^--user-data-dir=(.*)$/);\n return !match || !service.tmpDirs.includes(match[1]);\n }),\n ]\n \n newCapabilities = {\n [OBSIDIAN_CAPABILITY_KEY]: newObsidianOptions,\n 'goog:chromeOptions': {\n ...this.requestedCapabilities['goog:chromeOptions'],\n args: newArgs,\n },\n };\n } else {\n // preserve vault and config dir\n newCapabilities = {};\n // Since we aren't recreating the vault, we'll need to reset plugins and themes here if specified.\n if (plugins) {\n const enabledPlugins = await browser.executeObsidian(({app}) =>\n [...(app as any).plugins.enabledPlugins].sort()\n )\n for (const pluginId of _.difference(enabledPlugins, plugins, ['wdio-obsidian-service-plugin'])) {\n await obsidianPage.disablePlugin(pluginId);\n }\n for (const pluginId of _.difference(plugins, enabledPlugins)) {\n await obsidianPage.enablePlugin(pluginId);\n }\n }\n if (theme) {\n await obsidianPage.setTheme(theme);\n }\n // Obsidian debounces saves to the config dir, and so changes to plugin list, themes, and anything else\n // you set in your tests may not get saved to disk before the reboot. I haven't found a better way to\n // make sure everything's saved then just waiting a bit. Maybe we could mock setTimeout? wdio has ways\n // to mock the clock, but they only work when using BiDi, which I can't get working on Obsidian.\n await sleep(3000);\n }\n\n const sessionId = await browser.reloadSession({\n // if browserName is set, reloadSession tries to restart the driver entirely, so unset those\n ..._.omit(this.requestedCapabilities, ['browserName', 'browserVersion']),\n ...newCapabilities,\n });\n await service.waitForReady(this);\n return sessionId;\n }\n\n await browser.addCommand(\"reloadObsidian\", reloadObsidian);\n\n for (const [name, cmd] of Object.entries(browserCommands)) {\n await browser.addCommand(name, cmd);\n }\n\n await service.waitForReady(browser);\n }\n\n async afterSession() {\n for (const tmpDir of this.tmpDirs) {\n await fsAsync.rm(tmpDir, { recursive: true, force: true });\n }\n }\n}\n","import type { ObsidianBrowserCommands } from \"./browserCommands.js\";\nimport type { PluginEntry, ThemeEntry } from \"obsidian-launcher\";\n\nexport const OBSIDIAN_CAPABILITY_KEY = \"wdio:obsidianOptions\" as const;\n\nexport interface ObsidianServiceOptions {\n /**\n * Override the `obsidian-versions.json` used by the service. Can be a file URL.\n * This is only really useful for this package's own internal tests.\n */\n versionsUrl?: string,\n /**\n * Override the `community-plugins.json` used by the service. Can be a file URL.\n * This is only really useful for this package's own internal tests.\n */\n communityPluginsUrl?: string,\n /**\n * Override the `community-css-themes.json` used by the service. Can be a file URL.\n * This is only really useful for this package's own internal tests.\n */\n communityThemesUrl?: string,\n}\n\nexport interface ObsidianCapabilityOptions {\n /**\n * Version of Obsidian to run.\n * \n * Can be set to \"latest\", \"latest-beta\", or a specific version. Defaults to \"latest\". To download beta versions\n * you'll need to be an Obsidian insider and set the OBSIDIAN_USERNAME and OBSIDIAN_PASSWORD environment\n * variables.\n * \n * You can also use the wdio capability `browserVersion` field to set the Obsidian version.\n */\n appVersion?: string\n\n /**\n * Version of the Obsidian Installer to download.\n * \n * Note that Obsidian is distributed in two parts, the \"installer\", which is the executable containing Electron, and\n * the \"app\" which is a bundle of JavaScript containing the Obsidian code. Obsidian's self-update system only\n * updates the JavaScript bundle, and not the base installer/Electron version. This makes Obsidian's auto-update\n * fast as it only needs to download a few MiB of JS instead of all of Electron. But, it means different users with\n * the same Obsidian version may be running on different versions of Electron, which could cause subtle differences\n * in plugin behavior if you are using newer JavaScript features and the like in your plugin.\n * \n * If passed \"latest\", it will use the maximum installer version compatible with the selected Obsidian version. If\n * passed \"earliest\" it will use the oldest installer version compatible with the selected Obsidian version. The \n * default is \"earliest\".\n */\n installerVersion?: string,\n\n /**\n * List of plugins to install.\n * \n * Each entry is a path to the local plugin to install, e.g. [\".\"] or [\"dist\"] depending on your build setup. You\n * can also pass objects. If you pass an object it can contain one of either `path` (to install a local plugin),\n * `repo` (to install a plugin from github), or `id` (to install a community plugin). You can set `enabled: false`\n * to install the plugin but start it disabled. You can enable the plugin later using `reloadObsidian` or the\n * `enablePlugin` command.\n */\n plugins?: PluginEntry[],\n\n /**\n * List of themes to install.\n * \n * Each entry is a path to the local theme to install. You can also pass an object. If you pass an object it can\n * contain one of either `path` (to install a local theme), `repo` (to install a theme from github), or `name` (to\n * install a community theme). You can set `enabled: false` to install the theme, but start it disabled. You can\n * only have one enabled theme, so if you pass multiple you'll have to disable all but one.\n */\n themes?: ThemeEntry[],\n\n /**\n * The path to the vault to open.\n * \n * The vault will be copied, so any changes made in your tests won't affect the original. If omitted, no vault will\n * be opened and you'll need to call `browser.reloadObsidian` to open a vault during your tests.\n */\n vault?: string,\n\n /** Path to the Obsidian binary to use. If omitted it will download Obsidian automatically. */\n binaryPath?: string,\n\n /** Path to the app asar to load into obsidian. If omitted it will be downloaded automatically. */\n appPath?: string,\n}\n\n\ndeclare global {\n namespace WebdriverIO {\n interface Capabilities {\n [OBSIDIAN_CAPABILITY_KEY]?: ObsidianCapabilityOptions,\n }\n\n interface Browser extends ObsidianBrowserCommands {\n /**\n * Relaunch obsidian. Can be used to switch to a new vault, change the plugin list, or just to reboot\n * Obsidian.\n * \n * As this does a full reboot of Obsidian, avoid calling this too often so you don't slow your tests down.\n * You can also set the vault in the `wdio.conf.ts` capabilities section which may be useful if all\n * your tests use the same vault.\n * \n * @param vault Path to the vault to open. The vault will be copied, so any changes made in your tests won't\n * be persited to the original. If omitted, it will reboot Obsidian with the current vault, without\n * creating a new copy of the vault.\n * @param plugins List of plugin ids to enable. If omitted it will keep current plugin list. Note, all the\n * plugins must be defined in your wdio.conf.ts capabilities. You can also use the enablePlugin and \n * disablePlugin commands to change plugins without relaunching Obsidian.\n * @param theme Name of the theme to enable. If omitted it will keep the current theme. Pass \"default\" to\n * switch back to the default theme. Like with plugins, the theme must be defined in wdio.conf.ts.\n * @returns Returns the new sessionId (same as browser.reloadSession()).\n */\n reloadObsidian(params?: {\n vault?: string,\n plugins?: string[], theme?: string,\n }): Promise<string>;\n }\n }\n}\n","import * as path from \"path\"\nimport * as fsAsync from \"fs/promises\"\n\n/**\n * Class with various helper methods for writing Obsidian tests using the\n * [page object pattern](https://webdriver.io/docs/pageobjects).\n */\nclass ObsidianPage {\n /** Enables a plugin */\n async enablePlugin(pluginId: string): Promise<void> {\n await browser.executeObsidian(\n async ({app}, pluginId) => await (app as any).plugins.enablePluginAndSave(pluginId),\n pluginId,\n );\n }\n\n /** Disables a plugin */\n async disablePlugin(pluginId: string): Promise<void> {\n await browser.executeObsidian(\n async ({app}, pluginId) => await (app as any).plugins.disablePluginAndSave(pluginId),\n pluginId,\n );\n }\n\n /** Sets the theme. Pass \"default\" to reset to the Obsidian theme. */\n async setTheme(themeName: string): Promise<void> {\n themeName = themeName == 'default' ? '' : themeName;\n await browser.executeObsidian(\n async ({app}, themeName) => await (app as any).customCss.setTheme(themeName),\n themeName,\n )\n }\n\n /**\n * Opens a file in a new tab.\n */\n async openFile(path: string) {\n await browser.executeObsidian(async ({app, obsidian}, path) => {\n const file = app.vault.getAbstractFileByPath(path);\n if (file instanceof obsidian.TFile) {\n await app.workspace.getLeaf('tab').openFile(file);\n } else {\n throw Error(`No file ${path} exists`);\n }\n }, path)\n }\n\n /**\n * Loads a saved workspace from `workspaces.json` by name. You can use the core \"Workspaces\" plugin to create the\n * layouts.\n */\n async loadWorkspaceLayout(layoutName: string): Promise<void> {\n // read from .obsidian/workspaces.json like the built-in workspaces plugin does\n const vaultPath = (await browser.getVaultPath())!;\n const workspacesPath = path.join(vaultPath, '.obsidian/workspaces.json');\n \n let layout: any = undefined\n try {\n layout = await fsAsync.readFile(workspacesPath, 'utf-8')\n } catch {\n throw new Error(`No workspace ${layout} found in .obsidian/workspaces.json`);\n }\n layout = JSON.parse(layout).workspaces?.[layoutName];\n \n // Click on the status-bar to focus the main window in case there are multiple Obsidian windows panes\n await $(\".status-bar\").click();\n await browser.executeObsidian(async ({app}, layout) => {\n await app.workspace.changeLayout(layout)\n }, layout)\n }\n \n}\n\nconst obsidianPage = new ObsidianPage()\nexport default obsidianPage;\nexport { ObsidianPage };\n","import { OBSIDIAN_CAPABILITY_KEY } from \"./types.js\";\nimport type * as obsidian from \"obsidian\"\nimport obsidianPage, { ObsidianPage } from \"./pageobjects/obsidianPage.js\"\n\n\ntype ExecuteObsidianArg = {\n /**\n * There is a global \"app\" instance, but that may be removed in the future so you can use this to access it from\n * tests. See https://docs.obsidian.md/Plugins/Releasing/Plugin+guidelines#Avoid+using+global+app+instance\n */\n app: obsidian.App,\n\n /**\n * The full obsidian API. See https://github.com/obsidianmd/obsidian-api/blob/master/obsidian.d.ts\n */\n obsidian: typeof obsidian,\n}\n\nconst browserCommands = {\n /** Returns the Obsidian version this test is running under. */\n async getObsidianVersion(this: WebdriverIO.Browser): Promise<string> {\n return this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].appVersion;\n },\n\n /** Returns the Obsidian installer version this test is running under. */\n async getObsidianInstallerVersion(this: WebdriverIO.Browser): Promise<string> {\n return this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].installerVersion;\n },\n\n /**\n * Wrapper around browser.execute that passes the Obsidian API to the function. The first argument to the function\n * is an object containing keys:\n * - app: Obsidian app instance\n * - obsidian: Full Obsidian API\n * See also: https://webdriver.io/docs/api/browser/execute\n * \n * Example usage\n * ```ts\n * const file = browser.executeObsidian(({app, obsidian}, path) => {\n * return app.vault.getMarkdownFiles().find(f => f.path == path)\n * })\n * ```\n * \n * Note: The same caveats as `browser.execute` apply. The function will be stringified and then run inside Obsidian,\n * so you can't capture any local variables. E.g.\n * \n * This *won't* work:\n * ```ts\n * import { FileView } from Obsidian\n * browser.executeObsidian(({app, obsidian}) => {\n * if (leaf.view instanceof FileView) {\n * ...\n * }\n * })\n * ```\n * do this instead:\n * ```ts\n * browser.executeObsidian(({app, obsidian}) => {\n * if (leaf.view instanceof obsidian.FileView) {\n * ...\n * }\n * })\n * ```\n */\n async executeObsidian<Return, Params extends unknown[]>(\n func: (obs: ExecuteObsidianArg, ...params: Params) => Return,\n ...params: Params\n ): Promise<Return> {\n return await browser.execute<Return, Params>(\n `return (${func.toString()}).call(null, {...window.wdioObsidianService}, ...arguments )`,\n ...params,\n )\n },\n\n /**\n * Executes an Obsidian command by id.\n * @param id Id of the command to run.\n */\n async executeObsidianCommand(this: WebdriverIO.Browser, id: string) {\n const result = await this.executeObsidian(({app}, id) => (app as any).commands.executeCommandById(id), id);\n if (!result) {\n throw Error(`Obsidian command ${id} not found or failed.`);\n }\n },\n\n /** Returns the path to the vault opened in Obsidian */\n async getVaultPath(this: WebdriverIO.Browser): Promise<string|undefined> {\n if (this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].vault == undefined) {\n return undefined; // no vault open\n } else { // return the actual path to the vault\n return await this.executeObsidian(({app, obsidian}) => {\n if (app.vault.adapter instanceof obsidian.FileSystemAdapter) {\n return app.vault.adapter.getBasePath()\n } else { // TODO handle CapacitorAdapater\n throw new Error(`Unrecognized DataAdapater type`)\n };\n })\n }\n },\n\n /**\n * Returns the Workspace page object with convenience helper functions.\n * You can also import the page object directly with\n * ```ts\n * import { obsidianPage } from \"wdio-obsidian-service\"\n * ```\n */\n async getObsidianPage(this: WebdriverIO.Browser): Promise<ObsidianPage> {\n return obsidianPage;\n }\n} as const\n\nexport type ObsidianBrowserCommands = typeof browserCommands;\nexport default browserCommands;\n","export async function sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}","import SpecReporter from '@wdio/spec-reporter';\nimport { RunnerStats } from \"@wdio/reporter\"\nimport { Reporters } from \"@wdio/types\"\n\n\n/**\n * Simple extension of SpecReporter that print the Obsidian version instead of the Chrome version.\n */\nclass ObsidianReporter extends SpecReporter {\n // Override this method to change the label shown for each capability \n getHeaderDisplay(runner: RunnerStats) {\n const obsidianOptions = (runner.config as any).capabilities?.['wdio:obsidianOptions']\n\n let combo: string\n if (obsidianOptions) {\n const appVersion = obsidianOptions.appVersion;\n const installerVersion = obsidianOptions.installerVersion;\n combo = `obsidian v${appVersion} (installer: v${installerVersion})`\n } else { // fall back to SpecReporter behavior\n combo = this.getEnviromentCombo(runner.capabilities, undefined, runner.isMultiremote).trim()\n }\n \n // Spec file name and enviroment information\n const output = [`Running: ${combo}`]\n\n if ((runner.capabilities as any).sessionId) {\n output.push(`Session ID: ${(runner.capabilities as any).sessionId}`)\n }\n\n return output\n }\n}\n\nexport default ObsidianReporter as Reporters.ReporterClass\n"],"mappings":"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","names":["import_obsidian_launcher","pluginId","themeName","path","layout","id","logger","path","ObsidianLauncher","semver","browser","_","fsAsync","SpecReporter","launcher","ObsidianLauncher"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
|
-
import { Services, Options, Capabilities } from '@wdio/types';
|
|
1
|
+
import { Services, Options, Capabilities, Reporters } from '@wdio/types';
|
|
2
2
|
import * as obsidian from 'obsidian';
|
|
3
3
|
import { PluginEntry, ThemeEntry } from 'obsidian-launcher';
|
|
4
4
|
export { CommunityPluginEntry, CommunityThemeEntry, GitHubPluginEntry, GitHubThemeEntry, LocalPluginEntry, LocalThemeEntry, PluginEntry, ThemeEntry } from 'obsidian-launcher';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Class with various helper methods for writing Obsidian tests using the
|
|
8
|
+
* [page object pattern](https://webdriver.io/docs/pageobjects).
|
|
9
|
+
*/
|
|
10
|
+
declare class ObsidianPage {
|
|
11
|
+
/** Enables a plugin */
|
|
12
|
+
enablePlugin(pluginId: string): Promise<void>;
|
|
13
|
+
/** Disables a plugin */
|
|
14
|
+
disablePlugin(pluginId: string): Promise<void>;
|
|
15
|
+
/** Sets the theme. Pass "default" to reset to the Obsidian theme. */
|
|
16
|
+
setTheme(themeName: string): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Opens a file in a new tab.
|
|
19
|
+
*/
|
|
20
|
+
openFile(path: string): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Loads a saved workspace from `workspaces.json` by name. You can use the core "Workspaces" plugin to create the
|
|
23
|
+
* layouts.
|
|
24
|
+
*/
|
|
25
|
+
loadWorkspaceLayout(layoutName: string): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
declare const obsidianPage: ObsidianPage;
|
|
28
|
+
|
|
6
29
|
type ExecuteObsidianArg = {
|
|
7
30
|
/**
|
|
8
31
|
* There is a global "app" instance, but that may be removed in the future so you can use this to access it from
|
|
@@ -20,8 +43,8 @@ declare const browserCommands: {
|
|
|
20
43
|
/** Returns the Obsidian installer version this test is running under. */
|
|
21
44
|
readonly getObsidianInstallerVersion: (this: WebdriverIO.Browser) => Promise<string>;
|
|
22
45
|
/**
|
|
23
|
-
* Wrapper around browser.execute that passes the Obsidian API to the function. The
|
|
24
|
-
*
|
|
46
|
+
* Wrapper around browser.execute that passes the Obsidian API to the function. The first argument to the function
|
|
47
|
+
* is an object containing keys:
|
|
25
48
|
* - app: Obsidian app instance
|
|
26
49
|
* - obsidian: Full Obsidian API
|
|
27
50
|
* See also: https://webdriver.io/docs/api/browser/execute
|
|
@@ -32,21 +55,44 @@ declare const browserCommands: {
|
|
|
32
55
|
* return app.vault.getMarkdownFiles().find(f => f.path == path)
|
|
33
56
|
* })
|
|
34
57
|
* ```
|
|
58
|
+
*
|
|
59
|
+
* Note: The same caveats as `browser.execute` apply. The function will be stringified and then run inside Obsidian,
|
|
60
|
+
* so you can't capture any local variables. E.g.
|
|
61
|
+
*
|
|
62
|
+
* This *won't* work:
|
|
63
|
+
* ```ts
|
|
64
|
+
* import { FileView } from Obsidian
|
|
65
|
+
* browser.executeObsidian(({app, obsidian}) => {
|
|
66
|
+
* if (leaf.view instanceof FileView) {
|
|
67
|
+
* ...
|
|
68
|
+
* }
|
|
69
|
+
* })
|
|
70
|
+
* ```
|
|
71
|
+
* do this instead:
|
|
72
|
+
* ```ts
|
|
73
|
+
* browser.executeObsidian(({app, obsidian}) => {
|
|
74
|
+
* if (leaf.view instanceof obsidian.FileView) {
|
|
75
|
+
* ...
|
|
76
|
+
* }
|
|
77
|
+
* })
|
|
78
|
+
* ```
|
|
35
79
|
*/
|
|
36
80
|
readonly executeObsidian: <Return, Params extends unknown[]>(func: (obs: ExecuteObsidianArg, ...params: Params) => Return, ...params: Params) => Promise<Return>;
|
|
37
|
-
/** Returns the path to the vault opened in Obsidian */
|
|
38
|
-
readonly getVaultPath: (this: WebdriverIO.Browser) => Promise<string | undefined>;
|
|
39
|
-
/** Enables a plugin */
|
|
40
|
-
readonly enablePlugin: (this: WebdriverIO.Browser, pluginId: string) => Promise<void>;
|
|
41
|
-
/** Disables a plugin */
|
|
42
|
-
readonly disablePlugin: (this: WebdriverIO.Browser, pluginId: string) => Promise<void>;
|
|
43
|
-
/** Sets the theme. Pass "default" to reset to the Obsidian theme. */
|
|
44
|
-
readonly setTheme: (this: WebdriverIO.Browser, themeName: string) => Promise<void>;
|
|
45
81
|
/**
|
|
46
|
-
* Executes an Obsidian command.
|
|
82
|
+
* Executes an Obsidian command by id.
|
|
47
83
|
* @param id Id of the command to run.
|
|
48
84
|
*/
|
|
49
85
|
readonly executeObsidianCommand: (this: WebdriverIO.Browser, id: string) => Promise<void>;
|
|
86
|
+
/** Returns the path to the vault opened in Obsidian */
|
|
87
|
+
readonly getVaultPath: (this: WebdriverIO.Browser) => Promise<string | undefined>;
|
|
88
|
+
/**
|
|
89
|
+
* Returns the Workspace page object with convenience helper functions.
|
|
90
|
+
* You can also import the page object directly with
|
|
91
|
+
* ```ts
|
|
92
|
+
* import { obsidianPage } from "wdio-obsidian-service"
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
readonly getObsidianPage: (this: WebdriverIO.Browser) => Promise<ObsidianPage>;
|
|
50
96
|
};
|
|
51
97
|
type ObsidianBrowserCommands = typeof browserCommands;
|
|
52
98
|
|
|
@@ -184,6 +230,8 @@ declare class ObsidianWorkerService implements Services.ServiceInstance {
|
|
|
184
230
|
afterSession(): Promise<void>;
|
|
185
231
|
}
|
|
186
232
|
|
|
233
|
+
declare const _default: Reporters.ReporterClass;
|
|
234
|
+
|
|
187
235
|
declare const launcher: typeof ObsidianLauncherService;
|
|
188
236
|
|
|
189
237
|
/**
|
|
@@ -192,4 +240,4 @@ declare const launcher: typeof ObsidianLauncherService;
|
|
|
192
240
|
*/
|
|
193
241
|
declare function obsidianBetaAvailable(cacheDir?: string): Promise<boolean>;
|
|
194
242
|
|
|
195
|
-
export { type ObsidianCapabilityOptions, type ObsidianServiceOptions, ObsidianWorkerService as default, launcher, obsidianBetaAvailable };
|
|
243
|
+
export { type ObsidianCapabilityOptions, _default as ObsidianReporter, type ObsidianServiceOptions, ObsidianWorkerService as default, launcher, obsidianBetaAvailable, obsidianPage };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
|
-
import { Services, Options, Capabilities } from '@wdio/types';
|
|
1
|
+
import { Services, Options, Capabilities, Reporters } from '@wdio/types';
|
|
2
2
|
import * as obsidian from 'obsidian';
|
|
3
3
|
import { PluginEntry, ThemeEntry } from 'obsidian-launcher';
|
|
4
4
|
export { CommunityPluginEntry, CommunityThemeEntry, GitHubPluginEntry, GitHubThemeEntry, LocalPluginEntry, LocalThemeEntry, PluginEntry, ThemeEntry } from 'obsidian-launcher';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Class with various helper methods for writing Obsidian tests using the
|
|
8
|
+
* [page object pattern](https://webdriver.io/docs/pageobjects).
|
|
9
|
+
*/
|
|
10
|
+
declare class ObsidianPage {
|
|
11
|
+
/** Enables a plugin */
|
|
12
|
+
enablePlugin(pluginId: string): Promise<void>;
|
|
13
|
+
/** Disables a plugin */
|
|
14
|
+
disablePlugin(pluginId: string): Promise<void>;
|
|
15
|
+
/** Sets the theme. Pass "default" to reset to the Obsidian theme. */
|
|
16
|
+
setTheme(themeName: string): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Opens a file in a new tab.
|
|
19
|
+
*/
|
|
20
|
+
openFile(path: string): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Loads a saved workspace from `workspaces.json` by name. You can use the core "Workspaces" plugin to create the
|
|
23
|
+
* layouts.
|
|
24
|
+
*/
|
|
25
|
+
loadWorkspaceLayout(layoutName: string): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
declare const obsidianPage: ObsidianPage;
|
|
28
|
+
|
|
6
29
|
type ExecuteObsidianArg = {
|
|
7
30
|
/**
|
|
8
31
|
* There is a global "app" instance, but that may be removed in the future so you can use this to access it from
|
|
@@ -20,8 +43,8 @@ declare const browserCommands: {
|
|
|
20
43
|
/** Returns the Obsidian installer version this test is running under. */
|
|
21
44
|
readonly getObsidianInstallerVersion: (this: WebdriverIO.Browser) => Promise<string>;
|
|
22
45
|
/**
|
|
23
|
-
* Wrapper around browser.execute that passes the Obsidian API to the function. The
|
|
24
|
-
*
|
|
46
|
+
* Wrapper around browser.execute that passes the Obsidian API to the function. The first argument to the function
|
|
47
|
+
* is an object containing keys:
|
|
25
48
|
* - app: Obsidian app instance
|
|
26
49
|
* - obsidian: Full Obsidian API
|
|
27
50
|
* See also: https://webdriver.io/docs/api/browser/execute
|
|
@@ -32,21 +55,44 @@ declare const browserCommands: {
|
|
|
32
55
|
* return app.vault.getMarkdownFiles().find(f => f.path == path)
|
|
33
56
|
* })
|
|
34
57
|
* ```
|
|
58
|
+
*
|
|
59
|
+
* Note: The same caveats as `browser.execute` apply. The function will be stringified and then run inside Obsidian,
|
|
60
|
+
* so you can't capture any local variables. E.g.
|
|
61
|
+
*
|
|
62
|
+
* This *won't* work:
|
|
63
|
+
* ```ts
|
|
64
|
+
* import { FileView } from Obsidian
|
|
65
|
+
* browser.executeObsidian(({app, obsidian}) => {
|
|
66
|
+
* if (leaf.view instanceof FileView) {
|
|
67
|
+
* ...
|
|
68
|
+
* }
|
|
69
|
+
* })
|
|
70
|
+
* ```
|
|
71
|
+
* do this instead:
|
|
72
|
+
* ```ts
|
|
73
|
+
* browser.executeObsidian(({app, obsidian}) => {
|
|
74
|
+
* if (leaf.view instanceof obsidian.FileView) {
|
|
75
|
+
* ...
|
|
76
|
+
* }
|
|
77
|
+
* })
|
|
78
|
+
* ```
|
|
35
79
|
*/
|
|
36
80
|
readonly executeObsidian: <Return, Params extends unknown[]>(func: (obs: ExecuteObsidianArg, ...params: Params) => Return, ...params: Params) => Promise<Return>;
|
|
37
|
-
/** Returns the path to the vault opened in Obsidian */
|
|
38
|
-
readonly getVaultPath: (this: WebdriverIO.Browser) => Promise<string | undefined>;
|
|
39
|
-
/** Enables a plugin */
|
|
40
|
-
readonly enablePlugin: (this: WebdriverIO.Browser, pluginId: string) => Promise<void>;
|
|
41
|
-
/** Disables a plugin */
|
|
42
|
-
readonly disablePlugin: (this: WebdriverIO.Browser, pluginId: string) => Promise<void>;
|
|
43
|
-
/** Sets the theme. Pass "default" to reset to the Obsidian theme. */
|
|
44
|
-
readonly setTheme: (this: WebdriverIO.Browser, themeName: string) => Promise<void>;
|
|
45
81
|
/**
|
|
46
|
-
* Executes an Obsidian command.
|
|
82
|
+
* Executes an Obsidian command by id.
|
|
47
83
|
* @param id Id of the command to run.
|
|
48
84
|
*/
|
|
49
85
|
readonly executeObsidianCommand: (this: WebdriverIO.Browser, id: string) => Promise<void>;
|
|
86
|
+
/** Returns the path to the vault opened in Obsidian */
|
|
87
|
+
readonly getVaultPath: (this: WebdriverIO.Browser) => Promise<string | undefined>;
|
|
88
|
+
/**
|
|
89
|
+
* Returns the Workspace page object with convenience helper functions.
|
|
90
|
+
* You can also import the page object directly with
|
|
91
|
+
* ```ts
|
|
92
|
+
* import { obsidianPage } from "wdio-obsidian-service"
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
readonly getObsidianPage: (this: WebdriverIO.Browser) => Promise<ObsidianPage>;
|
|
50
96
|
};
|
|
51
97
|
type ObsidianBrowserCommands = typeof browserCommands;
|
|
52
98
|
|
|
@@ -184,6 +230,8 @@ declare class ObsidianWorkerService implements Services.ServiceInstance {
|
|
|
184
230
|
afterSession(): Promise<void>;
|
|
185
231
|
}
|
|
186
232
|
|
|
233
|
+
declare const _default: Reporters.ReporterClass;
|
|
234
|
+
|
|
187
235
|
declare const launcher: typeof ObsidianLauncherService;
|
|
188
236
|
|
|
189
237
|
/**
|
|
@@ -192,4 +240,4 @@ declare const launcher: typeof ObsidianLauncherService;
|
|
|
192
240
|
*/
|
|
193
241
|
declare function obsidianBetaAvailable(cacheDir?: string): Promise<boolean>;
|
|
194
242
|
|
|
195
|
-
export { type ObsidianCapabilityOptions, type ObsidianServiceOptions, ObsidianWorkerService as default, launcher, obsidianBetaAvailable };
|
|
243
|
+
export { type ObsidianCapabilityOptions, _default as ObsidianReporter, type ObsidianServiceOptions, ObsidianWorkerService as default, launcher, obsidianBetaAvailable, obsidianPage };
|
package/dist/index.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import ObsidianLauncher2 from "obsidian-launcher";
|
|
3
3
|
|
|
4
4
|
// src/service.ts
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import fsAsync2 from "fs/promises";
|
|
6
|
+
import path2 from "path";
|
|
7
7
|
import { SevereServiceError } from "webdriverio";
|
|
8
8
|
import logger from "@wdio/logger";
|
|
9
9
|
import { fileURLToPath } from "url";
|
|
@@ -12,6 +12,68 @@ import ObsidianLauncher from "obsidian-launcher";
|
|
|
12
12
|
// src/types.ts
|
|
13
13
|
var OBSIDIAN_CAPABILITY_KEY = "wdio:obsidianOptions";
|
|
14
14
|
|
|
15
|
+
// src/pageobjects/obsidianPage.ts
|
|
16
|
+
import * as path from "path";
|
|
17
|
+
import * as fsAsync from "fs/promises";
|
|
18
|
+
var ObsidianPage = class {
|
|
19
|
+
/** Enables a plugin */
|
|
20
|
+
async enablePlugin(pluginId) {
|
|
21
|
+
await browser.executeObsidian(
|
|
22
|
+
async ({ app }, pluginId2) => await app.plugins.enablePluginAndSave(pluginId2),
|
|
23
|
+
pluginId
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
/** Disables a plugin */
|
|
27
|
+
async disablePlugin(pluginId) {
|
|
28
|
+
await browser.executeObsidian(
|
|
29
|
+
async ({ app }, pluginId2) => await app.plugins.disablePluginAndSave(pluginId2),
|
|
30
|
+
pluginId
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
/** Sets the theme. Pass "default" to reset to the Obsidian theme. */
|
|
34
|
+
async setTheme(themeName) {
|
|
35
|
+
themeName = themeName == "default" ? "" : themeName;
|
|
36
|
+
await browser.executeObsidian(
|
|
37
|
+
async ({ app }, themeName2) => await app.customCss.setTheme(themeName2),
|
|
38
|
+
themeName
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Opens a file in a new tab.
|
|
43
|
+
*/
|
|
44
|
+
async openFile(path3) {
|
|
45
|
+
await browser.executeObsidian(async ({ app, obsidian }, path4) => {
|
|
46
|
+
const file = app.vault.getAbstractFileByPath(path4);
|
|
47
|
+
if (file instanceof obsidian.TFile) {
|
|
48
|
+
await app.workspace.getLeaf("tab").openFile(file);
|
|
49
|
+
} else {
|
|
50
|
+
throw Error(`No file ${path4} exists`);
|
|
51
|
+
}
|
|
52
|
+
}, path3);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Loads a saved workspace from `workspaces.json` by name. You can use the core "Workspaces" plugin to create the
|
|
56
|
+
* layouts.
|
|
57
|
+
*/
|
|
58
|
+
async loadWorkspaceLayout(layoutName) {
|
|
59
|
+
const vaultPath = await browser.getVaultPath();
|
|
60
|
+
const workspacesPath = path.join(vaultPath, ".obsidian/workspaces.json");
|
|
61
|
+
let layout = void 0;
|
|
62
|
+
try {
|
|
63
|
+
layout = await fsAsync.readFile(workspacesPath, "utf-8");
|
|
64
|
+
} catch {
|
|
65
|
+
throw new Error(`No workspace ${layout} found in .obsidian/workspaces.json`);
|
|
66
|
+
}
|
|
67
|
+
layout = JSON.parse(layout).workspaces?.[layoutName];
|
|
68
|
+
await $(".status-bar").click();
|
|
69
|
+
await browser.executeObsidian(async ({ app }, layout2) => {
|
|
70
|
+
await app.workspace.changeLayout(layout2);
|
|
71
|
+
}, layout);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
var obsidianPage = new ObsidianPage();
|
|
75
|
+
var obsidianPage_default = obsidianPage;
|
|
76
|
+
|
|
15
77
|
// src/browserCommands.ts
|
|
16
78
|
var browserCommands = {
|
|
17
79
|
/** Returns the Obsidian version this test is running under. */
|
|
@@ -23,8 +85,8 @@ var browserCommands = {
|
|
|
23
85
|
return this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].installerVersion;
|
|
24
86
|
},
|
|
25
87
|
/**
|
|
26
|
-
* Wrapper around browser.execute that passes the Obsidian API to the function. The
|
|
27
|
-
*
|
|
88
|
+
* Wrapper around browser.execute that passes the Obsidian API to the function. The first argument to the function
|
|
89
|
+
* is an object containing keys:
|
|
28
90
|
* - app: Obsidian app instance
|
|
29
91
|
* - obsidian: Full Obsidian API
|
|
30
92
|
* See also: https://webdriver.io/docs/api/browser/execute
|
|
@@ -35,6 +97,27 @@ var browserCommands = {
|
|
|
35
97
|
* return app.vault.getMarkdownFiles().find(f => f.path == path)
|
|
36
98
|
* })
|
|
37
99
|
* ```
|
|
100
|
+
*
|
|
101
|
+
* Note: The same caveats as `browser.execute` apply. The function will be stringified and then run inside Obsidian,
|
|
102
|
+
* so you can't capture any local variables. E.g.
|
|
103
|
+
*
|
|
104
|
+
* This *won't* work:
|
|
105
|
+
* ```ts
|
|
106
|
+
* import { FileView } from Obsidian
|
|
107
|
+
* browser.executeObsidian(({app, obsidian}) => {
|
|
108
|
+
* if (leaf.view instanceof FileView) {
|
|
109
|
+
* ...
|
|
110
|
+
* }
|
|
111
|
+
* })
|
|
112
|
+
* ```
|
|
113
|
+
* do this instead:
|
|
114
|
+
* ```ts
|
|
115
|
+
* browser.executeObsidian(({app, obsidian}) => {
|
|
116
|
+
* if (leaf.view instanceof obsidian.FileView) {
|
|
117
|
+
* ...
|
|
118
|
+
* }
|
|
119
|
+
* })
|
|
120
|
+
* ```
|
|
38
121
|
*/
|
|
39
122
|
async executeObsidian(func, ...params) {
|
|
40
123
|
return await browser.execute(
|
|
@@ -42,6 +125,16 @@ var browserCommands = {
|
|
|
42
125
|
...params
|
|
43
126
|
);
|
|
44
127
|
},
|
|
128
|
+
/**
|
|
129
|
+
* Executes an Obsidian command by id.
|
|
130
|
+
* @param id Id of the command to run.
|
|
131
|
+
*/
|
|
132
|
+
async executeObsidianCommand(id) {
|
|
133
|
+
const result = await this.executeObsidian(({ app }, id2) => app.commands.executeCommandById(id2), id);
|
|
134
|
+
if (!result) {
|
|
135
|
+
throw Error(`Obsidian command ${id} not found or failed.`);
|
|
136
|
+
}
|
|
137
|
+
},
|
|
45
138
|
/** Returns the path to the vault opened in Obsidian */
|
|
46
139
|
async getVaultPath() {
|
|
47
140
|
if (this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].vault == void 0) {
|
|
@@ -57,37 +150,15 @@ var browserCommands = {
|
|
|
57
150
|
});
|
|
58
151
|
}
|
|
59
152
|
},
|
|
60
|
-
/** Enables a plugin */
|
|
61
|
-
async enablePlugin(pluginId) {
|
|
62
|
-
await this.executeObsidian(
|
|
63
|
-
async ({ app }, pluginId2) => await app.plugins.enablePluginAndSave(pluginId2),
|
|
64
|
-
pluginId
|
|
65
|
-
);
|
|
66
|
-
},
|
|
67
|
-
/** Disables a plugin */
|
|
68
|
-
async disablePlugin(pluginId) {
|
|
69
|
-
await this.executeObsidian(
|
|
70
|
-
async ({ app }, pluginId2) => await app.plugins.disablePluginAndSave(pluginId2),
|
|
71
|
-
pluginId
|
|
72
|
-
);
|
|
73
|
-
},
|
|
74
|
-
/** Sets the theme. Pass "default" to reset to the Obsidian theme. */
|
|
75
|
-
async setTheme(themeName) {
|
|
76
|
-
themeName = themeName == "default" ? "" : themeName;
|
|
77
|
-
await this.executeObsidian(
|
|
78
|
-
async ({ app }, themeName2) => await app.customCss.setTheme(themeName2),
|
|
79
|
-
themeName
|
|
80
|
-
);
|
|
81
|
-
},
|
|
82
153
|
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
154
|
+
* Returns the Workspace page object with convenience helper functions.
|
|
155
|
+
* You can also import the page object directly with
|
|
156
|
+
* ```ts
|
|
157
|
+
* import { obsidianPage } from "wdio-obsidian-service"
|
|
158
|
+
* ```
|
|
85
159
|
*/
|
|
86
|
-
async
|
|
87
|
-
|
|
88
|
-
if (!result) {
|
|
89
|
-
throw Error(`Obsidian command ${id} not found or failed.`);
|
|
90
|
-
}
|
|
160
|
+
async getObsidianPage() {
|
|
161
|
+
return obsidianPage_default;
|
|
91
162
|
}
|
|
92
163
|
};
|
|
93
164
|
var browserCommands_default = browserCommands;
|
|
@@ -98,11 +169,13 @@ async function sleep(ms) {
|
|
|
98
169
|
}
|
|
99
170
|
|
|
100
171
|
// src/service.ts
|
|
172
|
+
import semver from "semver";
|
|
101
173
|
import _ from "lodash";
|
|
102
174
|
var log = logger("wdio-obsidian-service");
|
|
103
175
|
function getDefaultCacheDir() {
|
|
104
|
-
return
|
|
176
|
+
return path2.resolve(process.env.WEBDRIVER_CACHE_DIR ?? "./.obsidian-cache");
|
|
105
177
|
}
|
|
178
|
+
var minSupportedObsidianVersion = "1.0.2";
|
|
106
179
|
var ObsidianLauncherService = class {
|
|
107
180
|
constructor(options, capabilities, config) {
|
|
108
181
|
this.options = options;
|
|
@@ -114,7 +187,7 @@ var ObsidianLauncherService = class {
|
|
|
114
187
|
communityPluginsUrl: options.communityPluginsUrl,
|
|
115
188
|
communityThemesUrl: options.communityThemesUrl
|
|
116
189
|
});
|
|
117
|
-
this.helperPluginPath =
|
|
190
|
+
this.helperPluginPath = path2.resolve(path2.join(fileURLToPath(import.meta.url), "../../helper-plugin"));
|
|
118
191
|
}
|
|
119
192
|
async onPrepare(config, capabilities) {
|
|
120
193
|
if (!Array.isArray(capabilities)) {
|
|
@@ -132,12 +205,15 @@ var ObsidianLauncherService = class {
|
|
|
132
205
|
try {
|
|
133
206
|
for (const cap of obsidianCapabilities) {
|
|
134
207
|
const obsidianOptions = cap[OBSIDIAN_CAPABILITY_KEY] ?? {};
|
|
135
|
-
const vault = obsidianOptions.vault != void 0 ?
|
|
208
|
+
const vault = obsidianOptions.vault != void 0 ? path2.resolve(obsidianOptions.vault) : void 0;
|
|
136
209
|
const [appVersion, installerVersion] = await this.obsidianLauncher.resolveVersions(
|
|
137
|
-
cap.browserVersion ?? "latest",
|
|
210
|
+
cap.browserVersion ?? cap[OBSIDIAN_CAPABILITY_KEY]?.appVersion ?? "latest",
|
|
138
211
|
obsidianOptions.installerVersion ?? "earliest"
|
|
139
212
|
);
|
|
140
213
|
const installerVersionInfo = await this.obsidianLauncher.getVersionInfo(installerVersion);
|
|
214
|
+
if (semver.lt(appVersion, minSupportedObsidianVersion)) {
|
|
215
|
+
throw Error(`Minimum supported Obsidian version is ${minSupportedObsidianVersion}`);
|
|
216
|
+
}
|
|
141
217
|
let installerPath = obsidianOptions.binaryPath;
|
|
142
218
|
if (!installerPath) {
|
|
143
219
|
installerPath = await this.obsidianLauncher.downloadInstaller(installerVersion);
|
|
@@ -284,7 +360,7 @@ var ObsidianWorkerService = class {
|
|
|
284
360
|
if (vault) {
|
|
285
361
|
const newObsidianOptions = {
|
|
286
362
|
...oldObsidianOptions,
|
|
287
|
-
vault:
|
|
363
|
+
vault: path2.resolve(vault),
|
|
288
364
|
plugins: service.selectPlugins(oldObsidianOptions.plugins, plugins),
|
|
289
365
|
themes: service.selectThemes(oldObsidianOptions.themes, theme)
|
|
290
366
|
};
|
|
@@ -310,18 +386,16 @@ var ObsidianWorkerService = class {
|
|
|
310
386
|
({ app }) => [...app.plugins.enabledPlugins].sort()
|
|
311
387
|
);
|
|
312
388
|
for (const pluginId of _.difference(enabledPlugins, plugins, ["wdio-obsidian-service-plugin"])) {
|
|
313
|
-
await
|
|
389
|
+
await obsidianPage_default.disablePlugin(pluginId);
|
|
314
390
|
}
|
|
315
391
|
for (const pluginId of _.difference(plugins, enabledPlugins)) {
|
|
316
|
-
await
|
|
392
|
+
await obsidianPage_default.enablePlugin(pluginId);
|
|
317
393
|
}
|
|
318
|
-
await browser2.executeObsidian(async ({ app }) => await app.plugins.saveConfig());
|
|
319
394
|
}
|
|
320
395
|
if (theme) {
|
|
321
|
-
await
|
|
322
|
-
await browser2.executeObsidian(async ({ app }) => await app.vault.saveConfig());
|
|
396
|
+
await obsidianPage_default.setTheme(theme);
|
|
323
397
|
}
|
|
324
|
-
await sleep(
|
|
398
|
+
await sleep(3e3);
|
|
325
399
|
}
|
|
326
400
|
const sessionId = await browser2.reloadSession({
|
|
327
401
|
// if browserName is set, reloadSession tries to restart the driver entirely, so unset those
|
|
@@ -339,10 +413,33 @@ var ObsidianWorkerService = class {
|
|
|
339
413
|
}
|
|
340
414
|
async afterSession() {
|
|
341
415
|
for (const tmpDir of this.tmpDirs) {
|
|
342
|
-
await
|
|
416
|
+
await fsAsync2.rm(tmpDir, { recursive: true, force: true });
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
// src/obsidianReporter.ts
|
|
422
|
+
import SpecReporter from "@wdio/spec-reporter";
|
|
423
|
+
var ObsidianReporter = class extends SpecReporter {
|
|
424
|
+
// Override this method to change the label shown for each capability
|
|
425
|
+
getHeaderDisplay(runner) {
|
|
426
|
+
const obsidianOptions = runner.config.capabilities?.["wdio:obsidianOptions"];
|
|
427
|
+
let combo;
|
|
428
|
+
if (obsidianOptions) {
|
|
429
|
+
const appVersion = obsidianOptions.appVersion;
|
|
430
|
+
const installerVersion = obsidianOptions.installerVersion;
|
|
431
|
+
combo = `obsidian v${appVersion} (installer: v${installerVersion})`;
|
|
432
|
+
} else {
|
|
433
|
+
combo = this.getEnviromentCombo(runner.capabilities, void 0, runner.isMultiremote).trim();
|
|
434
|
+
}
|
|
435
|
+
const output = [`Running: ${combo}`];
|
|
436
|
+
if (runner.capabilities.sessionId) {
|
|
437
|
+
output.push(`Session ID: ${runner.capabilities.sessionId}`);
|
|
343
438
|
}
|
|
439
|
+
return output;
|
|
344
440
|
}
|
|
345
441
|
};
|
|
442
|
+
var obsidianReporter_default = ObsidianReporter;
|
|
346
443
|
|
|
347
444
|
// src/index.ts
|
|
348
445
|
var index_default = ObsidianWorkerService;
|
|
@@ -353,8 +450,10 @@ async function obsidianBetaAvailable(cacheDir) {
|
|
|
353
450
|
return versionInfo.isBeta && await launcher2.isAvailable(versionInfo.version);
|
|
354
451
|
}
|
|
355
452
|
export {
|
|
453
|
+
obsidianReporter_default as ObsidianReporter,
|
|
356
454
|
index_default as default,
|
|
357
455
|
launcher,
|
|
358
|
-
obsidianBetaAvailable
|
|
456
|
+
obsidianBetaAvailable,
|
|
457
|
+
obsidianPage_default as obsidianPage
|
|
359
458
|
};
|
|
360
459
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/service.ts","../src/types.ts","../src/browserCommands.ts","../src/utils.ts"],"sourcesContent":["import ObsidianLauncher from \"obsidian-launcher\"\nimport { ObsidianLauncherService, ObsidianWorkerService } from \"./service.js\";\n\nexport default ObsidianWorkerService;\nexport const launcher = ObsidianLauncherService;\n\nexport type { ObsidianServiceOptions, ObsidianCapabilityOptions } from \"./types.js\";\n\nexport type {\n LocalPluginEntry, GitHubPluginEntry, CommunityPluginEntry, PluginEntry,\n LocalThemeEntry, GitHubThemeEntry, CommunityThemeEntry, ThemeEntry,\n} from \"obsidian-launcher\"\n\n/**\n * Returns true if there's currently an Obsidian beta and we have the credentials to download it or it's already in the\n * cache.\n */\nexport async function obsidianBetaAvailable(cacheDir?: string) {\n const launcher = new ObsidianLauncher({cacheDir: cacheDir});\n const versionInfo = await launcher.getVersionInfo(\"latest-beta\");\n return versionInfo.isBeta && await launcher.isAvailable(versionInfo.version);\n}\n","import fsAsync from \"fs/promises\"\nimport path from \"path\"\nimport { SevereServiceError } from 'webdriverio'\nimport type { Capabilities, Options, Services } from '@wdio/types'\nimport logger from '@wdio/logger'\nimport { fileURLToPath } from \"url\"\nimport ObsidianLauncher, { DownloadedPluginEntry, DownloadedThemeEntry } from \"obsidian-launcher\"\nimport browserCommands from \"./browserCommands.js\"\nimport { ObsidianCapabilityOptions, ObsidianServiceOptions, OBSIDIAN_CAPABILITY_KEY } from \"./types.js\"\nimport { sleep } from \"./utils.js\"\nimport _ from \"lodash\"\n\n\nconst log = logger(\"wdio-obsidian-service\");\n\nfunction getDefaultCacheDir() {\n return path.resolve(process.env.WEBDRIVER_CACHE_DIR ?? \"./.obsidian-cache\")\n}\n\nexport class ObsidianLauncherService implements Services.ServiceInstance {\n private obsidianLauncher: ObsidianLauncher\n private readonly helperPluginPath: string\n\n constructor (\n public options: ObsidianServiceOptions,\n public capabilities: WebdriverIO.Capabilities,\n public config: Options.Testrunner\n ) {\n this.obsidianLauncher = new ObsidianLauncher({\n cacheDir: config.cacheDir ?? getDefaultCacheDir(),\n versionsUrl: options.versionsUrl,\n communityPluginsUrl: options.communityPluginsUrl, communityThemesUrl: options.communityThemesUrl,\n });\n this.helperPluginPath = path.resolve(path.join(fileURLToPath(import.meta.url), '../../helper-plugin'));\n }\n\n async onPrepare(config: Options.Testrunner, capabilities: Capabilities.TestrunnerCapabilities) {\n if (!Array.isArray(capabilities)) {\n capabilities = Object.values(capabilities as Capabilities.RequestedMultiremoteCapabilities).map(\n (multiremoteOption) => (multiremoteOption as Capabilities.WithRequestedCapabilities).capabilities,\n );\n }\n\n const obsidianCapabilities = capabilities.flatMap((cap) => {\n if ((\"browserName\" in cap) && cap.browserName === \"obsidian\") {\n return [cap as WebdriverIO.Capabilities];\n } else {\n return [];\n }\n });\n\n try {\n for (const cap of obsidianCapabilities) {\n const obsidianOptions = cap[OBSIDIAN_CAPABILITY_KEY] ?? {};\n \n const vault = obsidianOptions.vault != undefined ? path.resolve(obsidianOptions.vault) : undefined;\n \n const [appVersion, installerVersion] = await this.obsidianLauncher.resolveVersions(\n cap.browserVersion ?? \"latest\",\n obsidianOptions.installerVersion ?? \"earliest\",\n );\n const installerVersionInfo = await this.obsidianLauncher.getVersionInfo(installerVersion);\n\n let installerPath = obsidianOptions.binaryPath;\n if (!installerPath) {\n installerPath = await this.obsidianLauncher.downloadInstaller(installerVersion);\n }\n let appPath = obsidianOptions.appPath;\n if (!appPath) {\n appPath = await this.obsidianLauncher.downloadApp(appVersion);\n }\n let chromedriverPath = cap['wdio:chromedriverOptions']?.binary\n // wdio can download chromedriver for versions greater than 115 automatically\n if (!chromedriverPath && Number(installerVersionInfo.chromeVersion!.split(\".\")[0]) <= 115) {\n chromedriverPath = await this.obsidianLauncher.downloadChromedriver(installerVersion);\n }\n\n let plugins = obsidianOptions.plugins ?? [\".\"];\n plugins.push(this.helperPluginPath); // Always install the helper plugin\n plugins = await this.obsidianLauncher.downloadPlugins(plugins);\n\n const themes = await this.obsidianLauncher.downloadThemes(obsidianOptions.themes ?? []);\n\n const args = [\n // Workaround for SUID issue on AppImages. See https://github.com/electron/electron/issues/42510\n ...(process.platform == 'linux' ? [\"--no-sandbox\"] : []),\n ...(cap['goog:chromeOptions']?.args ?? [])\n ];\n\n cap.browserName = \"chrome\";\n cap.browserVersion = installerVersionInfo.chromeVersion;\n cap[OBSIDIAN_CAPABILITY_KEY] = {\n ...obsidianOptions,\n plugins: plugins,\n themes: themes,\n binaryPath: installerPath,\n appPath: appPath,\n vault: vault,\n appVersion: appVersion, // Resolve the versions\n installerVersion: installerVersion,\n };\n cap['goog:chromeOptions'] = {\n binary: installerPath,\n windowTypes: [\"app\", \"webview\"],\n ...cap['goog:chromeOptions'],\n args: args,\n }\n cap['wdio:chromedriverOptions'] = {\n // allowedIps is not included in the types, but gets passed as --allowed-ips to chromedriver.\n // It defaults to [\"0.0.0.0\"] which makes Windows Firewall complain, and we don't need remote\n // connections anyways.\n allowedIps: [],\n ...cap['wdio:chromedriverOptions'],\n binary: chromedriverPath,\n } as any\n cap[\"wdio:enforceWebDriverClassic\"] = true;\n }\n } catch (e: any) {\n // By default wdio just logs service errors, throwing this makes it bail if anything goes wrong.\n throw new SevereServiceError(`Failed to download and setup Obsidian. Caused by: ${e.stack}\\n`+\n ` ------The above causes:-----`);\n }\n }\n}\n\nexport class ObsidianWorkerService implements Services.ServiceInstance {\n private obsidianLauncher: ObsidianLauncher\n /** Directories to clean up after the tests */\n private tmpDirs: string[]\n\n constructor (\n public options: ObsidianServiceOptions,\n public capabilities: WebdriverIO.Capabilities,\n public config: Options.Testrunner\n ) {\n this.obsidianLauncher = new ObsidianLauncher({\n cacheDir: config.cacheDir ?? getDefaultCacheDir(),\n versionsUrl: options.versionsUrl,\n communityPluginsUrl: options.communityPluginsUrl, communityThemesUrl: options.communityThemesUrl,\n });\n this.tmpDirs = [];\n }\n\n private async setupObsidian(obsidianOptions: ObsidianCapabilityOptions) {\n let vault = obsidianOptions.vault;\n if (vault != undefined) {\n log.info(`Opening vault ${obsidianOptions.vault}`);\n vault = await this.obsidianLauncher.setupVault({\n vault,\n copy: true,\n plugins: obsidianOptions.plugins,\n themes: obsidianOptions.themes,\n });\n this.tmpDirs.push(vault);\n } else {\n log.info(`Opening Obsidian without a vault`)\n }\n\n const configDir = await this.obsidianLauncher.setupConfigDir({\n appVersion: obsidianOptions.appVersion!, installerVersion: obsidianOptions.installerVersion!,\n appPath: obsidianOptions.appPath!,\n vault: vault,\n });\n this.tmpDirs.push(configDir);\n\n return configDir;\n }\n\n private async waitForReady(browser: WebdriverIO.Browser) {\n if (browser.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].vault != undefined) {\n await browser.waitUntil( // wait until the helper plugin is loaded\n () => browser.execute(() => !!(window as any).wdioObsidianService),\n {timeout: 30 * 1000, interval: 100},\n );\n await browser.executeObsidian(async ({app}) => {\n await new Promise<void>((resolve) => app.workspace.onLayoutReady(resolve) );\n })\n }\n }\n\n async beforeSession(config: Options.Testrunner, capabilities: WebdriverIO.Capabilities) {\n if (!capabilities[OBSIDIAN_CAPABILITY_KEY]) return;\n\n const configDir = await this.setupObsidian(capabilities[OBSIDIAN_CAPABILITY_KEY]);\n\n capabilities['goog:chromeOptions']!.args = [\n `--user-data-dir=${configDir}`,\n ...(capabilities['goog:chromeOptions']!.args ?? [])\n ];\n }\n\n private selectPlugins(currentPlugins: DownloadedPluginEntry[], selection?: string[]) {\n if (selection !== undefined) {\n const unknownPlugins = _.difference(selection, currentPlugins.map(p => p.id));\n if (unknownPlugins.length > 0) {\n throw Error(`Unknown plugin ids: ${unknownPlugins.join(', ')}`)\n }\n return currentPlugins.map(p => ({\n ...p,\n enabled: selection.includes(p.id) || p.id == \"wdio-obsidian-service-plugin\",\n }));\n } else {\n return currentPlugins;\n }\n }\n\n private selectThemes(currentThemes: DownloadedThemeEntry[], selection?: string) {\n if (selection !== undefined) {\n if (selection != \"default\" && currentThemes.every((t: any) => t.name != selection)) {\n throw Error(`Unknown theme: ${selection}`);\n }\n return currentThemes.map((t: any) => ({...t, enabled: selection != 'default' && t.name === selection}));\n } else {\n return currentThemes;\n }\n }\n\n async before(capabilities: WebdriverIO.Capabilities, specs: never, browser: WebdriverIO.Browser) {\n // There's a slow event listener link on the browser \"command\" event when you reloadSession that causes some\n // warnings. This will silence them. TODO: Make issue or PR to wdio to fix this.\n browser.setMaxListeners(1000);\n\n if (!capabilities[OBSIDIAN_CAPABILITY_KEY]) return;\n\n const service = this; // eslint-disable-line @typescript-eslint/no-this-alias\n const reloadObsidian: typeof browser['reloadObsidian'] = async function(\n this: WebdriverIO.Browser,\n {vault, plugins, theme} = {},\n ) {\n const oldObsidianOptions = this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY];\n let newCapabilities: WebdriverIO.Capabilities\n\n if (vault) {\n const newObsidianOptions = {\n ...oldObsidianOptions,\n vault: path.resolve(vault),\n plugins: service.selectPlugins(oldObsidianOptions.plugins, plugins),\n themes: service.selectThemes(oldObsidianOptions.themes, theme),\n }\n \n const configDir = await service.setupObsidian(newObsidianOptions);\n \n const newArgs = [\n `--user-data-dir=${configDir}`,\n ...this.requestedCapabilities['goog:chromeOptions'].args.filter((arg: string) => {\n const match = arg.match(/^--user-data-dir=(.*)$/);\n return !match || !service.tmpDirs.includes(match[1]);\n }),\n ]\n \n newCapabilities = {\n [OBSIDIAN_CAPABILITY_KEY]: newObsidianOptions,\n 'goog:chromeOptions': {\n ...this.requestedCapabilities['goog:chromeOptions'],\n args: newArgs,\n },\n };\n } else {\n // preserve vault and config dir\n newCapabilities = {};\n // Since we aren't recreating the vault, we'll need to reset plugins and themes here if specified.\n if (plugins) {\n const enabledPlugins = await browser.executeObsidian(({app}) =>\n [...(app as any).plugins.enabledPlugins].sort()\n )\n for (const pluginId of _.difference(enabledPlugins, plugins, ['wdio-obsidian-service-plugin'])) {\n await browser.disablePlugin(pluginId);\n }\n for (const pluginId of _.difference(plugins, enabledPlugins)) {\n await browser.enablePlugin(pluginId);\n }\n await browser.executeObsidian(async ({app}) => await (app as any).plugins.saveConfig())\n }\n if (theme) {\n await browser.setTheme(theme);\n await browser.executeObsidian(async ({app}) => await (app.vault as any).saveConfig())\n }\n // Obsidian debounces saves to the config dir, and so changes to plugin list, themes, and anything else\n // you set in your tests may not get saved to disk before the reboot. I haven't found a better way to\n // make sure everything's saved then just waiting a bit.\n await sleep(2000);\n }\n\n const sessionId = await browser.reloadSession({\n // if browserName is set, reloadSession tries to restart the driver entirely, so unset those\n ..._.omit(this.requestedCapabilities, ['browserName', 'browserVersion']),\n ...newCapabilities,\n });\n await service.waitForReady(this);\n return sessionId;\n }\n\n await browser.addCommand(\"reloadObsidian\", reloadObsidian);\n\n for (const [name, cmd] of Object.entries(browserCommands)) {\n await browser.addCommand(name, cmd);\n }\n\n await service.waitForReady(browser);\n }\n\n async afterSession() {\n for (const tmpDir of this.tmpDirs) {\n await fsAsync.rm(tmpDir, { recursive: true, force: true });\n }\n }\n}\n","import type { ObsidianBrowserCommands } from \"./browserCommands.js\";\nimport type { PluginEntry, ThemeEntry } from \"obsidian-launcher\";\n\nexport const OBSIDIAN_CAPABILITY_KEY = \"wdio:obsidianOptions\" as const;\n\nexport interface ObsidianServiceOptions {\n /**\n * Override the `obsidian-versions.json` used by the service. Can be a file URL.\n * This is only really useful for this package's own internal tests.\n */\n versionsUrl?: string,\n /**\n * Override the `community-plugins.json` used by the service. Can be a file URL.\n * This is only really useful for this package's own internal tests.\n */\n communityPluginsUrl?: string,\n /**\n * Override the `community-css-themes.json` used by the service. Can be a file URL.\n * This is only really useful for this package's own internal tests.\n */\n communityThemesUrl?: string,\n}\n\nexport interface ObsidianCapabilityOptions {\n /**\n * Version of Obsidian to run.\n * \n * Can be set to \"latest\", \"latest-beta\", or a specific version. Defaults to \"latest\". To download beta versions\n * you'll need to be an Obsidian insider and set the OBSIDIAN_USERNAME and OBSIDIAN_PASSWORD environment\n * variables.\n * \n * You can also use the wdio capability `browserVersion` field to set the Obsidian version.\n */\n appVersion?: string\n\n /**\n * Version of the Obsidian Installer to download.\n * \n * Note that Obsidian is distributed in two parts, the \"installer\", which is the executable containing Electron, and\n * the \"app\" which is a bundle of JavaScript containing the Obsidian code. Obsidian's self-update system only\n * updates the JavaScript bundle, and not the base installer/Electron version. This makes Obsidian's auto-update\n * fast as it only needs to download a few MiB of JS instead of all of Electron. But, it means different users with\n * the same Obsidian version may be running on different versions of Electron, which could cause subtle differences\n * in plugin behavior if you are using newer JavaScript features and the like in your plugin.\n * \n * If passed \"latest\", it will use the maximum installer version compatible with the selected Obsidian version. If\n * passed \"earliest\" it will use the oldest installer version compatible with the selected Obsidian version. The \n * default is \"earliest\".\n */\n installerVersion?: string,\n\n /**\n * List of plugins to install.\n * \n * Each entry is a path to the local plugin to install, e.g. [\".\"] or [\"dist\"] depending on your build setup. You\n * can also pass objects. If you pass an object it can contain one of either `path` (to install a local plugin),\n * `repo` (to install a plugin from github), or `id` (to install a community plugin). You can set `enabled: false`\n * to install the plugin but start it disabled. You can enable the plugin later using `reloadObsidian` or the\n * `enablePlugin` command.\n */\n plugins?: PluginEntry[],\n\n /**\n * List of themes to install.\n * \n * Each entry is a path to the local theme to install. You can also pass an object. If you pass an object it can\n * contain one of either `path` (to install a local theme), `repo` (to install a theme from github), or `name` (to\n * install a community theme). You can set `enabled: false` to install the theme, but start it disabled. You can\n * only have one enabled theme, so if you pass multiple you'll have to disable all but one.\n */\n themes?: ThemeEntry[],\n\n /**\n * The path to the vault to open.\n * \n * The vault will be copied, so any changes made in your tests won't affect the original. If omitted, no vault will\n * be opened and you'll need to call `browser.reloadObsidian` to open a vault during your tests.\n */\n vault?: string,\n\n /** Path to the Obsidian binary to use. If omitted it will download Obsidian automatically. */\n binaryPath?: string,\n\n /** Path to the app asar to load into obsidian. If omitted it will be downloaded automatically. */\n appPath?: string,\n}\n\n\ndeclare global {\n namespace WebdriverIO {\n interface Capabilities {\n [OBSIDIAN_CAPABILITY_KEY]?: ObsidianCapabilityOptions,\n }\n\n interface Browser extends ObsidianBrowserCommands {\n /**\n * Relaunch obsidian. Can be used to switch to a new vault, change the plugin list, or just to reboot\n * Obsidian.\n * \n * As this does a full reboot of Obsidian, avoid calling this too often so you don't slow your tests down.\n * You can also set the vault in the `wdio.conf.ts` capabilities section which may be useful if all\n * your tests use the same vault.\n * \n * @param vault Path to the vault to open. The vault will be copied, so any changes made in your tests won't\n * be persited to the original. If omitted, it will reboot Obsidian with the current vault, without\n * creating a new copy of the vault.\n * @param plugins List of plugin ids to enable. If omitted it will keep current plugin list. Note, all the\n * plugins must be defined in your wdio.conf.ts capabilities. You can also use the enablePlugin and \n * disablePlugin commands to change plugins without relaunching Obsidian.\n * @param theme Name of the theme to enable. If omitted it will keep the current theme. Pass \"default\" to\n * switch back to the default theme. Like with plugins, the theme must be defined in wdio.conf.ts.\n * @returns Returns the new sessionId (same as browser.reloadSession()).\n */\n reloadObsidian(params?: {\n vault?: string,\n plugins?: string[], theme?: string,\n }): Promise<string>;\n }\n }\n}\n","import { OBSIDIAN_CAPABILITY_KEY } from \"./types.js\";\nimport type * as obsidian from \"obsidian\"\n\n\ntype ExecuteObsidianArg = {\n /**\n * There is a global \"app\" instance, but that may be removed in the future so you can use this to access it from\n * tests. See https://docs.obsidian.md/Plugins/Releasing/Plugin+guidelines#Avoid+using+global+app+instance\n */\n app: obsidian.App,\n\n /**\n * The full obsidian API. See https://github.com/obsidianmd/obsidian-api/blob/master/obsidian.d.ts\n */\n obsidian: typeof obsidian,\n}\n\nconst browserCommands = {\n /** Returns the Obsidian version this test is running under. */\n async getObsidianVersion(this: WebdriverIO.Browser): Promise<string> {\n return this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].appVersion;\n },\n\n /** Returns the Obsidian installer version this test is running under. */\n async getObsidianInstallerVersion(this: WebdriverIO.Browser): Promise<string> {\n return this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].installerVersion;\n },\n\n /**\n * Wrapper around browser.execute that passes the Obsidian API to the function. The function will be run inside\n * Obsidian. The first argument to the function is an object containing keys:\n * - app: Obsidian app instance\n * - obsidian: Full Obsidian API\n * See also: https://webdriver.io/docs/api/browser/execute\n * \n * Example usage\n * ```ts\n * const file = browser.executeObsidian(({app, obsidian}, path) => {\n * return app.vault.getMarkdownFiles().find(f => f.path == path)\n * })\n * ```\n */\n async executeObsidian<Return, Params extends unknown[]>(\n func: (obs: ExecuteObsidianArg, ...params: Params) => Return,\n ...params: Params\n ): Promise<Return> {\n return await browser.execute<Return, Params>(\n `return (${func.toString()}).call(null, {...window.wdioObsidianService}, ...arguments )`,\n ...params,\n )\n },\n\n /** Returns the path to the vault opened in Obsidian */\n async getVaultPath(this: WebdriverIO.Browser): Promise<string|undefined> {\n if (this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].vault == undefined) {\n return undefined; // no vault open\n } else { // return the actual path to the vault\n return await this.executeObsidian(({app, obsidian}) => {\n if (app.vault.adapter instanceof obsidian.FileSystemAdapter) {\n return app.vault.adapter.getBasePath()\n } else { // TODO handle CapacitorAdapater\n throw new Error(`Unrecognized DataAdapater type`)\n };\n })\n }\n },\n\n /** Enables a plugin */\n async enablePlugin(this: WebdriverIO.Browser, pluginId: string): Promise<void> {\n await this.executeObsidian(\n async ({app}, pluginId) => await (app as any).plugins.enablePluginAndSave(pluginId),\n pluginId,\n );\n },\n\n /** Disables a plugin */\n async disablePlugin(this: WebdriverIO.Browser, pluginId: string): Promise<void> {\n await this.executeObsidian(\n async ({app}, pluginId) => await (app as any).plugins.disablePluginAndSave(pluginId),\n pluginId,\n );\n },\n\n /** Sets the theme. Pass \"default\" to reset to the Obsidian theme. */\n async setTheme(this: WebdriverIO.Browser, themeName: string): Promise<void> {\n themeName = themeName == 'default' ? '' : themeName;\n await this.executeObsidian(\n async ({app}, themeName) => await (app as any).customCss.setTheme(themeName),\n themeName,\n )\n },\n\n /**\n * Executes an Obsidian command.\n * @param id Id of the command to run.\n */\n async executeObsidianCommand(this: WebdriverIO.Browser, id: string) {\n const result = await this.executeObsidian(({app}, id) => (app as any).commands.executeCommandById(id), id);\n if (!result) {\n throw Error(`Obsidian command ${id} not found or failed.`);\n }\n },\n} as const\n\nexport type ObsidianBrowserCommands = typeof browserCommands;\nexport default browserCommands;\n","export async function sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}"],"mappings":"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","names":["ObsidianLauncher","pluginId","themeName","id","browser","launcher","ObsidianLauncher"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/service.ts","../src/types.ts","../src/pageobjects/obsidianPage.ts","../src/browserCommands.ts","../src/utils.ts","../src/obsidianReporter.ts"],"sourcesContent":["import ObsidianLauncher from \"obsidian-launcher\";\nimport { ObsidianLauncherService, ObsidianWorkerService } from \"./service.js\";\n\nexport default ObsidianWorkerService;\nexport const launcher = ObsidianLauncherService;\n\nexport type { ObsidianServiceOptions, ObsidianCapabilityOptions } from \"./types.js\";\n\nexport { default as obsidianPage } from \"./pageobjects/obsidianPage.js\";\n\nexport type {\n LocalPluginEntry, GitHubPluginEntry, CommunityPluginEntry, PluginEntry,\n LocalThemeEntry, GitHubThemeEntry, CommunityThemeEntry, ThemeEntry,\n} from \"obsidian-launcher\";\n\nexport { default as ObsidianReporter } from \"./obsidianReporter.js\";\n\n/**\n * Returns true if there's currently an Obsidian beta and we have the credentials to download it or it's already in the\n * cache.\n */\nexport async function obsidianBetaAvailable(cacheDir?: string) {\n const launcher = new ObsidianLauncher({cacheDir: cacheDir});\n const versionInfo = await launcher.getVersionInfo(\"latest-beta\");\n return versionInfo.isBeta && await launcher.isAvailable(versionInfo.version);\n}\n","import fsAsync from \"fs/promises\"\nimport path from \"path\"\nimport { SevereServiceError } from 'webdriverio'\nimport type { Capabilities, Options, Services } from '@wdio/types'\nimport logger from '@wdio/logger'\nimport { fileURLToPath } from \"url\"\nimport ObsidianLauncher, { DownloadedPluginEntry, DownloadedThemeEntry } from \"obsidian-launcher\"\nimport browserCommands from \"./browserCommands.js\"\nimport { ObsidianCapabilityOptions, ObsidianServiceOptions, OBSIDIAN_CAPABILITY_KEY } from \"./types.js\"\nimport obsidianPage from \"./pageobjects/obsidianPage.js\"\nimport { sleep } from \"./utils.js\"\nimport semver from \"semver\"\nimport _ from \"lodash\"\n\n\nconst log = logger(\"wdio-obsidian-service\");\n\nfunction getDefaultCacheDir() {\n return path.resolve(process.env.WEBDRIVER_CACHE_DIR ?? \"./.obsidian-cache\")\n}\n\n/**\n * Minimum Obsidian version that wdio-obsidian-service supports.\n */\nexport const minSupportedObsidianVersion: string = \"1.0.2\"\n\n\nexport class ObsidianLauncherService implements Services.ServiceInstance {\n private obsidianLauncher: ObsidianLauncher\n private readonly helperPluginPath: string\n\n constructor (\n public options: ObsidianServiceOptions,\n public capabilities: WebdriverIO.Capabilities,\n public config: Options.Testrunner\n ) {\n this.obsidianLauncher = new ObsidianLauncher({\n cacheDir: config.cacheDir ?? getDefaultCacheDir(),\n versionsUrl: options.versionsUrl,\n communityPluginsUrl: options.communityPluginsUrl, communityThemesUrl: options.communityThemesUrl,\n });\n this.helperPluginPath = path.resolve(path.join(fileURLToPath(import.meta.url), '../../helper-plugin'));\n }\n\n async onPrepare(config: Options.Testrunner, capabilities: Capabilities.TestrunnerCapabilities) {\n if (!Array.isArray(capabilities)) {\n capabilities = Object.values(capabilities as Capabilities.RequestedMultiremoteCapabilities).map(\n (multiremoteOption) => (multiremoteOption as Capabilities.WithRequestedCapabilities).capabilities,\n );\n }\n\n const obsidianCapabilities = capabilities.flatMap((cap) => {\n if ((\"browserName\" in cap) && cap.browserName === \"obsidian\") {\n return [cap as WebdriverIO.Capabilities];\n } else {\n return [];\n }\n });\n\n try {\n for (const cap of obsidianCapabilities) {\n const obsidianOptions = cap[OBSIDIAN_CAPABILITY_KEY] ?? {};\n \n const vault = obsidianOptions.vault != undefined ? path.resolve(obsidianOptions.vault) : undefined;\n \n const [appVersion, installerVersion] = await this.obsidianLauncher.resolveVersions(\n cap.browserVersion ?? cap[OBSIDIAN_CAPABILITY_KEY]?.appVersion ?? \"latest\",\n obsidianOptions.installerVersion ?? \"earliest\",\n );\n const installerVersionInfo = await this.obsidianLauncher.getVersionInfo(installerVersion);\n if (semver.lt(appVersion, minSupportedObsidianVersion)) {\n throw Error(`Minimum supported Obsidian version is ${minSupportedObsidianVersion}`)\n }\n\n let installerPath = obsidianOptions.binaryPath;\n if (!installerPath) {\n installerPath = await this.obsidianLauncher.downloadInstaller(installerVersion);\n }\n let appPath = obsidianOptions.appPath;\n if (!appPath) {\n appPath = await this.obsidianLauncher.downloadApp(appVersion);\n }\n let chromedriverPath = cap['wdio:chromedriverOptions']?.binary\n // wdio can download chromedriver for versions greater than 115 automatically\n if (!chromedriverPath && Number(installerVersionInfo.chromeVersion!.split(\".\")[0]) <= 115) {\n chromedriverPath = await this.obsidianLauncher.downloadChromedriver(installerVersion);\n }\n\n let plugins = obsidianOptions.plugins ?? [\".\"];\n plugins.push(this.helperPluginPath); // Always install the helper plugin\n plugins = await this.obsidianLauncher.downloadPlugins(plugins);\n\n const themes = await this.obsidianLauncher.downloadThemes(obsidianOptions.themes ?? []);\n\n const args = [\n // Workaround for SUID issue on AppImages. See https://github.com/electron/electron/issues/42510\n ...(process.platform == 'linux' ? [\"--no-sandbox\"] : []),\n ...(cap['goog:chromeOptions']?.args ?? [])\n ];\n\n cap.browserName = \"chrome\";\n cap.browserVersion = installerVersionInfo.chromeVersion;\n cap[OBSIDIAN_CAPABILITY_KEY] = {\n ...obsidianOptions,\n plugins: plugins,\n themes: themes,\n binaryPath: installerPath,\n appPath: appPath,\n vault: vault,\n appVersion: appVersion, // Resolve the versions\n installerVersion: installerVersion,\n };\n cap['goog:chromeOptions'] = {\n binary: installerPath,\n windowTypes: [\"app\", \"webview\"],\n ...cap['goog:chromeOptions'],\n args: args,\n }\n cap['wdio:chromedriverOptions'] = {\n // allowedIps is not included in the types, but gets passed as --allowed-ips to chromedriver.\n // It defaults to [\"0.0.0.0\"] which makes Windows Firewall complain, and we don't need remote\n // connections anyways.\n allowedIps: [],\n ...cap['wdio:chromedriverOptions'],\n binary: chromedriverPath,\n } as any\n cap[\"wdio:enforceWebDriverClassic\"] = true;\n }\n } catch (e: any) {\n // By default wdio just logs service errors, throwing this makes it bail if anything goes wrong.\n throw new SevereServiceError(`Failed to download and setup Obsidian. Caused by: ${e.stack}\\n`+\n ` ------The above causes:-----`);\n }\n }\n}\n\nexport class ObsidianWorkerService implements Services.ServiceInstance {\n private obsidianLauncher: ObsidianLauncher\n /** Directories to clean up after the tests */\n private tmpDirs: string[]\n\n constructor (\n public options: ObsidianServiceOptions,\n public capabilities: WebdriverIO.Capabilities,\n public config: Options.Testrunner\n ) {\n this.obsidianLauncher = new ObsidianLauncher({\n cacheDir: config.cacheDir ?? getDefaultCacheDir(),\n versionsUrl: options.versionsUrl,\n communityPluginsUrl: options.communityPluginsUrl, communityThemesUrl: options.communityThemesUrl,\n });\n this.tmpDirs = [];\n }\n\n private async setupObsidian(obsidianOptions: ObsidianCapabilityOptions) {\n let vault = obsidianOptions.vault;\n if (vault != undefined) {\n log.info(`Opening vault ${obsidianOptions.vault}`);\n vault = await this.obsidianLauncher.setupVault({\n vault,\n copy: true,\n plugins: obsidianOptions.plugins,\n themes: obsidianOptions.themes,\n });\n this.tmpDirs.push(vault);\n } else {\n log.info(`Opening Obsidian without a vault`)\n }\n\n const configDir = await this.obsidianLauncher.setupConfigDir({\n appVersion: obsidianOptions.appVersion!, installerVersion: obsidianOptions.installerVersion!,\n appPath: obsidianOptions.appPath!,\n vault: vault,\n });\n this.tmpDirs.push(configDir);\n\n return configDir;\n }\n\n private async waitForReady(browser: WebdriverIO.Browser) {\n if (browser.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].vault != undefined) {\n await browser.waitUntil( // wait until the helper plugin is loaded\n () => browser.execute(() => !!(window as any).wdioObsidianService),\n {timeout: 30 * 1000, interval: 100},\n );\n await browser.executeObsidian(async ({app}) => {\n await new Promise<void>((resolve) => app.workspace.onLayoutReady(resolve) );\n })\n }\n }\n\n async beforeSession(config: Options.Testrunner, capabilities: WebdriverIO.Capabilities) {\n if (!capabilities[OBSIDIAN_CAPABILITY_KEY]) return;\n\n const configDir = await this.setupObsidian(capabilities[OBSIDIAN_CAPABILITY_KEY]);\n\n capabilities['goog:chromeOptions']!.args = [\n `--user-data-dir=${configDir}`,\n ...(capabilities['goog:chromeOptions']!.args ?? [])\n ];\n }\n\n private selectPlugins(currentPlugins: DownloadedPluginEntry[], selection?: string[]) {\n if (selection !== undefined) {\n const unknownPlugins = _.difference(selection, currentPlugins.map(p => p.id));\n if (unknownPlugins.length > 0) {\n throw Error(`Unknown plugin ids: ${unknownPlugins.join(', ')}`)\n }\n return currentPlugins.map(p => ({\n ...p,\n enabled: selection.includes(p.id) || p.id == \"wdio-obsidian-service-plugin\",\n }));\n } else {\n return currentPlugins;\n }\n }\n\n private selectThemes(currentThemes: DownloadedThemeEntry[], selection?: string) {\n if (selection !== undefined) {\n if (selection != \"default\" && currentThemes.every((t: any) => t.name != selection)) {\n throw Error(`Unknown theme: ${selection}`);\n }\n return currentThemes.map((t: any) => ({...t, enabled: selection != 'default' && t.name === selection}));\n } else {\n return currentThemes;\n }\n }\n\n async before(capabilities: WebdriverIO.Capabilities, specs: never, browser: WebdriverIO.Browser) {\n // There's a slow event listener link on the browser \"command\" event when you reloadSession that causes some\n // warnings. This will silence them. TODO: Make issue or PR to wdio to fix this.\n browser.setMaxListeners(1000);\n\n if (!capabilities[OBSIDIAN_CAPABILITY_KEY]) return;\n\n const service = this; // eslint-disable-line @typescript-eslint/no-this-alias\n const reloadObsidian: typeof browser['reloadObsidian'] = async function(\n this: WebdriverIO.Browser,\n {vault, plugins, theme} = {},\n ) {\n const oldObsidianOptions = this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY];\n let newCapabilities: WebdriverIO.Capabilities\n\n if (vault) {\n const newObsidianOptions = {\n ...oldObsidianOptions,\n vault: path.resolve(vault),\n plugins: service.selectPlugins(oldObsidianOptions.plugins, plugins),\n themes: service.selectThemes(oldObsidianOptions.themes, theme),\n }\n \n const configDir = await service.setupObsidian(newObsidianOptions);\n \n const newArgs = [\n `--user-data-dir=${configDir}`,\n ...this.requestedCapabilities['goog:chromeOptions'].args.filter((arg: string) => {\n const match = arg.match(/^--user-data-dir=(.*)$/);\n return !match || !service.tmpDirs.includes(match[1]);\n }),\n ]\n \n newCapabilities = {\n [OBSIDIAN_CAPABILITY_KEY]: newObsidianOptions,\n 'goog:chromeOptions': {\n ...this.requestedCapabilities['goog:chromeOptions'],\n args: newArgs,\n },\n };\n } else {\n // preserve vault and config dir\n newCapabilities = {};\n // Since we aren't recreating the vault, we'll need to reset plugins and themes here if specified.\n if (plugins) {\n const enabledPlugins = await browser.executeObsidian(({app}) =>\n [...(app as any).plugins.enabledPlugins].sort()\n )\n for (const pluginId of _.difference(enabledPlugins, plugins, ['wdio-obsidian-service-plugin'])) {\n await obsidianPage.disablePlugin(pluginId);\n }\n for (const pluginId of _.difference(plugins, enabledPlugins)) {\n await obsidianPage.enablePlugin(pluginId);\n }\n }\n if (theme) {\n await obsidianPage.setTheme(theme);\n }\n // Obsidian debounces saves to the config dir, and so changes to plugin list, themes, and anything else\n // you set in your tests may not get saved to disk before the reboot. I haven't found a better way to\n // make sure everything's saved then just waiting a bit. Maybe we could mock setTimeout? wdio has ways\n // to mock the clock, but they only work when using BiDi, which I can't get working on Obsidian.\n await sleep(3000);\n }\n\n const sessionId = await browser.reloadSession({\n // if browserName is set, reloadSession tries to restart the driver entirely, so unset those\n ..._.omit(this.requestedCapabilities, ['browserName', 'browserVersion']),\n ...newCapabilities,\n });\n await service.waitForReady(this);\n return sessionId;\n }\n\n await browser.addCommand(\"reloadObsidian\", reloadObsidian);\n\n for (const [name, cmd] of Object.entries(browserCommands)) {\n await browser.addCommand(name, cmd);\n }\n\n await service.waitForReady(browser);\n }\n\n async afterSession() {\n for (const tmpDir of this.tmpDirs) {\n await fsAsync.rm(tmpDir, { recursive: true, force: true });\n }\n }\n}\n","import type { ObsidianBrowserCommands } from \"./browserCommands.js\";\nimport type { PluginEntry, ThemeEntry } from \"obsidian-launcher\";\n\nexport const OBSIDIAN_CAPABILITY_KEY = \"wdio:obsidianOptions\" as const;\n\nexport interface ObsidianServiceOptions {\n /**\n * Override the `obsidian-versions.json` used by the service. Can be a file URL.\n * This is only really useful for this package's own internal tests.\n */\n versionsUrl?: string,\n /**\n * Override the `community-plugins.json` used by the service. Can be a file URL.\n * This is only really useful for this package's own internal tests.\n */\n communityPluginsUrl?: string,\n /**\n * Override the `community-css-themes.json` used by the service. Can be a file URL.\n * This is only really useful for this package's own internal tests.\n */\n communityThemesUrl?: string,\n}\n\nexport interface ObsidianCapabilityOptions {\n /**\n * Version of Obsidian to run.\n * \n * Can be set to \"latest\", \"latest-beta\", or a specific version. Defaults to \"latest\". To download beta versions\n * you'll need to be an Obsidian insider and set the OBSIDIAN_USERNAME and OBSIDIAN_PASSWORD environment\n * variables.\n * \n * You can also use the wdio capability `browserVersion` field to set the Obsidian version.\n */\n appVersion?: string\n\n /**\n * Version of the Obsidian Installer to download.\n * \n * Note that Obsidian is distributed in two parts, the \"installer\", which is the executable containing Electron, and\n * the \"app\" which is a bundle of JavaScript containing the Obsidian code. Obsidian's self-update system only\n * updates the JavaScript bundle, and not the base installer/Electron version. This makes Obsidian's auto-update\n * fast as it only needs to download a few MiB of JS instead of all of Electron. But, it means different users with\n * the same Obsidian version may be running on different versions of Electron, which could cause subtle differences\n * in plugin behavior if you are using newer JavaScript features and the like in your plugin.\n * \n * If passed \"latest\", it will use the maximum installer version compatible with the selected Obsidian version. If\n * passed \"earliest\" it will use the oldest installer version compatible with the selected Obsidian version. The \n * default is \"earliest\".\n */\n installerVersion?: string,\n\n /**\n * List of plugins to install.\n * \n * Each entry is a path to the local plugin to install, e.g. [\".\"] or [\"dist\"] depending on your build setup. You\n * can also pass objects. If you pass an object it can contain one of either `path` (to install a local plugin),\n * `repo` (to install a plugin from github), or `id` (to install a community plugin). You can set `enabled: false`\n * to install the plugin but start it disabled. You can enable the plugin later using `reloadObsidian` or the\n * `enablePlugin` command.\n */\n plugins?: PluginEntry[],\n\n /**\n * List of themes to install.\n * \n * Each entry is a path to the local theme to install. You can also pass an object. If you pass an object it can\n * contain one of either `path` (to install a local theme), `repo` (to install a theme from github), or `name` (to\n * install a community theme). You can set `enabled: false` to install the theme, but start it disabled. You can\n * only have one enabled theme, so if you pass multiple you'll have to disable all but one.\n */\n themes?: ThemeEntry[],\n\n /**\n * The path to the vault to open.\n * \n * The vault will be copied, so any changes made in your tests won't affect the original. If omitted, no vault will\n * be opened and you'll need to call `browser.reloadObsidian` to open a vault during your tests.\n */\n vault?: string,\n\n /** Path to the Obsidian binary to use. If omitted it will download Obsidian automatically. */\n binaryPath?: string,\n\n /** Path to the app asar to load into obsidian. If omitted it will be downloaded automatically. */\n appPath?: string,\n}\n\n\ndeclare global {\n namespace WebdriverIO {\n interface Capabilities {\n [OBSIDIAN_CAPABILITY_KEY]?: ObsidianCapabilityOptions,\n }\n\n interface Browser extends ObsidianBrowserCommands {\n /**\n * Relaunch obsidian. Can be used to switch to a new vault, change the plugin list, or just to reboot\n * Obsidian.\n * \n * As this does a full reboot of Obsidian, avoid calling this too often so you don't slow your tests down.\n * You can also set the vault in the `wdio.conf.ts` capabilities section which may be useful if all\n * your tests use the same vault.\n * \n * @param vault Path to the vault to open. The vault will be copied, so any changes made in your tests won't\n * be persited to the original. If omitted, it will reboot Obsidian with the current vault, without\n * creating a new copy of the vault.\n * @param plugins List of plugin ids to enable. If omitted it will keep current plugin list. Note, all the\n * plugins must be defined in your wdio.conf.ts capabilities. You can also use the enablePlugin and \n * disablePlugin commands to change plugins without relaunching Obsidian.\n * @param theme Name of the theme to enable. If omitted it will keep the current theme. Pass \"default\" to\n * switch back to the default theme. Like with plugins, the theme must be defined in wdio.conf.ts.\n * @returns Returns the new sessionId (same as browser.reloadSession()).\n */\n reloadObsidian(params?: {\n vault?: string,\n plugins?: string[], theme?: string,\n }): Promise<string>;\n }\n }\n}\n","import * as path from \"path\"\nimport * as fsAsync from \"fs/promises\"\n\n/**\n * Class with various helper methods for writing Obsidian tests using the\n * [page object pattern](https://webdriver.io/docs/pageobjects).\n */\nclass ObsidianPage {\n /** Enables a plugin */\n async enablePlugin(pluginId: string): Promise<void> {\n await browser.executeObsidian(\n async ({app}, pluginId) => await (app as any).plugins.enablePluginAndSave(pluginId),\n pluginId,\n );\n }\n\n /** Disables a plugin */\n async disablePlugin(pluginId: string): Promise<void> {\n await browser.executeObsidian(\n async ({app}, pluginId) => await (app as any).plugins.disablePluginAndSave(pluginId),\n pluginId,\n );\n }\n\n /** Sets the theme. Pass \"default\" to reset to the Obsidian theme. */\n async setTheme(themeName: string): Promise<void> {\n themeName = themeName == 'default' ? '' : themeName;\n await browser.executeObsidian(\n async ({app}, themeName) => await (app as any).customCss.setTheme(themeName),\n themeName,\n )\n }\n\n /**\n * Opens a file in a new tab.\n */\n async openFile(path: string) {\n await browser.executeObsidian(async ({app, obsidian}, path) => {\n const file = app.vault.getAbstractFileByPath(path);\n if (file instanceof obsidian.TFile) {\n await app.workspace.getLeaf('tab').openFile(file);\n } else {\n throw Error(`No file ${path} exists`);\n }\n }, path)\n }\n\n /**\n * Loads a saved workspace from `workspaces.json` by name. You can use the core \"Workspaces\" plugin to create the\n * layouts.\n */\n async loadWorkspaceLayout(layoutName: string): Promise<void> {\n // read from .obsidian/workspaces.json like the built-in workspaces plugin does\n const vaultPath = (await browser.getVaultPath())!;\n const workspacesPath = path.join(vaultPath, '.obsidian/workspaces.json');\n \n let layout: any = undefined\n try {\n layout = await fsAsync.readFile(workspacesPath, 'utf-8')\n } catch {\n throw new Error(`No workspace ${layout} found in .obsidian/workspaces.json`);\n }\n layout = JSON.parse(layout).workspaces?.[layoutName];\n \n // Click on the status-bar to focus the main window in case there are multiple Obsidian windows panes\n await $(\".status-bar\").click();\n await browser.executeObsidian(async ({app}, layout) => {\n await app.workspace.changeLayout(layout)\n }, layout)\n }\n \n}\n\nconst obsidianPage = new ObsidianPage()\nexport default obsidianPage;\nexport { ObsidianPage };\n","import { OBSIDIAN_CAPABILITY_KEY } from \"./types.js\";\nimport type * as obsidian from \"obsidian\"\nimport obsidianPage, { ObsidianPage } from \"./pageobjects/obsidianPage.js\"\n\n\ntype ExecuteObsidianArg = {\n /**\n * There is a global \"app\" instance, but that may be removed in the future so you can use this to access it from\n * tests. See https://docs.obsidian.md/Plugins/Releasing/Plugin+guidelines#Avoid+using+global+app+instance\n */\n app: obsidian.App,\n\n /**\n * The full obsidian API. See https://github.com/obsidianmd/obsidian-api/blob/master/obsidian.d.ts\n */\n obsidian: typeof obsidian,\n}\n\nconst browserCommands = {\n /** Returns the Obsidian version this test is running under. */\n async getObsidianVersion(this: WebdriverIO.Browser): Promise<string> {\n return this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].appVersion;\n },\n\n /** Returns the Obsidian installer version this test is running under. */\n async getObsidianInstallerVersion(this: WebdriverIO.Browser): Promise<string> {\n return this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].installerVersion;\n },\n\n /**\n * Wrapper around browser.execute that passes the Obsidian API to the function. The first argument to the function\n * is an object containing keys:\n * - app: Obsidian app instance\n * - obsidian: Full Obsidian API\n * See also: https://webdriver.io/docs/api/browser/execute\n * \n * Example usage\n * ```ts\n * const file = browser.executeObsidian(({app, obsidian}, path) => {\n * return app.vault.getMarkdownFiles().find(f => f.path == path)\n * })\n * ```\n * \n * Note: The same caveats as `browser.execute` apply. The function will be stringified and then run inside Obsidian,\n * so you can't capture any local variables. E.g.\n * \n * This *won't* work:\n * ```ts\n * import { FileView } from Obsidian\n * browser.executeObsidian(({app, obsidian}) => {\n * if (leaf.view instanceof FileView) {\n * ...\n * }\n * })\n * ```\n * do this instead:\n * ```ts\n * browser.executeObsidian(({app, obsidian}) => {\n * if (leaf.view instanceof obsidian.FileView) {\n * ...\n * }\n * })\n * ```\n */\n async executeObsidian<Return, Params extends unknown[]>(\n func: (obs: ExecuteObsidianArg, ...params: Params) => Return,\n ...params: Params\n ): Promise<Return> {\n return await browser.execute<Return, Params>(\n `return (${func.toString()}).call(null, {...window.wdioObsidianService}, ...arguments )`,\n ...params,\n )\n },\n\n /**\n * Executes an Obsidian command by id.\n * @param id Id of the command to run.\n */\n async executeObsidianCommand(this: WebdriverIO.Browser, id: string) {\n const result = await this.executeObsidian(({app}, id) => (app as any).commands.executeCommandById(id), id);\n if (!result) {\n throw Error(`Obsidian command ${id} not found or failed.`);\n }\n },\n\n /** Returns the path to the vault opened in Obsidian */\n async getVaultPath(this: WebdriverIO.Browser): Promise<string|undefined> {\n if (this.requestedCapabilities[OBSIDIAN_CAPABILITY_KEY].vault == undefined) {\n return undefined; // no vault open\n } else { // return the actual path to the vault\n return await this.executeObsidian(({app, obsidian}) => {\n if (app.vault.adapter instanceof obsidian.FileSystemAdapter) {\n return app.vault.adapter.getBasePath()\n } else { // TODO handle CapacitorAdapater\n throw new Error(`Unrecognized DataAdapater type`)\n };\n })\n }\n },\n\n /**\n * Returns the Workspace page object with convenience helper functions.\n * You can also import the page object directly with\n * ```ts\n * import { obsidianPage } from \"wdio-obsidian-service\"\n * ```\n */\n async getObsidianPage(this: WebdriverIO.Browser): Promise<ObsidianPage> {\n return obsidianPage;\n }\n} as const\n\nexport type ObsidianBrowserCommands = typeof browserCommands;\nexport default browserCommands;\n","export async function sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}","import SpecReporter from '@wdio/spec-reporter';\nimport { RunnerStats } from \"@wdio/reporter\"\nimport { Reporters } from \"@wdio/types\"\n\n\n/**\n * Simple extension of SpecReporter that print the Obsidian version instead of the Chrome version.\n */\nclass ObsidianReporter extends SpecReporter {\n // Override this method to change the label shown for each capability \n getHeaderDisplay(runner: RunnerStats) {\n const obsidianOptions = (runner.config as any).capabilities?.['wdio:obsidianOptions']\n\n let combo: string\n if (obsidianOptions) {\n const appVersion = obsidianOptions.appVersion;\n const installerVersion = obsidianOptions.installerVersion;\n combo = `obsidian v${appVersion} (installer: v${installerVersion})`\n } else { // fall back to SpecReporter behavior\n combo = this.getEnviromentCombo(runner.capabilities, undefined, runner.isMultiremote).trim()\n }\n \n // Spec file name and enviroment information\n const output = [`Running: ${combo}`]\n\n if ((runner.capabilities as any).sessionId) {\n output.push(`Session ID: ${(runner.capabilities as any).sessionId}`)\n }\n\n return output\n }\n}\n\nexport default ObsidianReporter as Reporters.ReporterClass\n"],"mappings":"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","names":["ObsidianLauncher","fsAsync","path","pluginId","themeName","path","layout","id","path","browser","fsAsync","launcher","ObsidianLauncher"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wdio-obsidian-service",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "TODO",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -49,14 +49,15 @@
|
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"lodash": "^4.17.21",
|
|
52
|
-
"obsidian-launcher": "^0.1
|
|
52
|
+
"obsidian-launcher": "^0.2.1",
|
|
53
|
+
"semver": "^7.7.1"
|
|
53
54
|
},
|
|
54
55
|
"peerDependencies": {
|
|
55
56
|
"@wdio/cli": "^9.5.0",
|
|
56
57
|
"@wdio/local-runner": "^9.5.0",
|
|
58
|
+
"@wdio/logger": "^9.4.4",
|
|
57
59
|
"@wdio/mocha-framework": "^9.5.0",
|
|
58
60
|
"@wdio/spec-reporter": "^9.5.0",
|
|
59
|
-
"@wdio/logger": "^9.4.4",
|
|
60
61
|
"obsidian": ">=1.7.2",
|
|
61
62
|
"webdriverio": "^9.5.0"
|
|
62
63
|
},
|