-
-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #407 from vim-denops/plugin-type-check-no-loaded
👍 `denops#plugin#check_type()` shows 'no plugins are loaded' message
- Loading branch information
Showing
11 changed files
with
2,507 additions
and
2,227 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
218 changes: 218 additions & 0 deletions
218
tests/denops/runtime/functions/plugin/check_type_test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,218 @@ | ||
import { | ||
assertMatch, | ||
assertNotMatch, | ||
assertRejects, | ||
} from "jsr:@std/assert@^1.0.1"; | ||
import { join } from "jsr:@std/path@^1.0.2/join"; | ||
import { testHost } from "/denops-testutil/host.ts"; | ||
import { wait } from "/denops-testutil/wait.ts"; | ||
|
||
const scriptValid = resolve("dummy_valid_plugin.ts"); | ||
|
||
testHost({ | ||
name: "denops#plugin#check_type()", | ||
mode: "all", | ||
postlude: [ | ||
"runtime plugin/denops.vim", | ||
], | ||
fn: async ({ host, t, stderr }) => { | ||
let outputs: string[] = []; | ||
stderr.pipeTo( | ||
new WritableStream({ write: (s) => void outputs.push(s) }), | ||
).catch(() => {}); | ||
await wait(() => host.call("eval", "denops#server#status() ==# 'running'")); | ||
await host.call("execute", [ | ||
"let g:__test_denops_events = []", | ||
"autocmd User DenopsPlugin* call add(g:__test_denops_events, expand('<amatch>'))", | ||
], ""); | ||
|
||
await t.step("if no arguments is specified", async (t) => { | ||
await t.step("if no plugins are loaded", async (t) => { | ||
outputs = []; | ||
await host.call("execute", [ | ||
"let g:__test_denops_events = []", | ||
`call denops#plugin#check_type()`, | ||
], ""); | ||
|
||
await t.step("outputs an info message after delayed", async () => { | ||
await wait(() => outputs.join("").includes("No plugins are loaded")); | ||
}); | ||
}); | ||
|
||
await t.step("if some plugins are loaded", async (t) => { | ||
await host.call("execute", [ | ||
`call denops#plugin#load('dummyCheckNoArguments', '${scriptValid}')`, | ||
], ""); | ||
outputs = []; | ||
await host.call("execute", [ | ||
"let g:__test_denops_events = []", | ||
`call denops#plugin#check_type()`, | ||
], ""); | ||
|
||
await t.step("outputs an info message after delayed", async () => { | ||
await wait(() => outputs.join("").includes("Type check")); | ||
assertMatch(outputs.join(""), /Type check succeeded/); | ||
}); | ||
}); | ||
|
||
await t.step("if not exists plugins are tried to load", async (t) => { | ||
await host.call("execute", [ | ||
"call denops#plugin#load('notexistsplugin', 'path-to-not-exists-plugin.ts')", | ||
], ""); | ||
outputs = []; | ||
await host.call("execute", [ | ||
"let g:__test_denops_events = []", | ||
`call denops#plugin#check_type()`, | ||
], ""); | ||
|
||
await t.step("outputs an error message after delayed", async () => { | ||
await wait(() => outputs.join("").includes("Type check")); | ||
assertMatch(outputs.join(""), /Type check failed:/); | ||
}); | ||
|
||
await t.step("does not outputs an usage", () => { | ||
assertNotMatch(outputs.join(""), /Usage:/); | ||
}); | ||
}); | ||
}); | ||
|
||
await t.step("if the plugin name is invalid", async (t) => { | ||
await t.step("throws an error", async () => { | ||
// NOTE: '.' is not allowed in plugin name. | ||
await assertRejects( | ||
() => host.call("denops#plugin#check_type", "dummy.invalid"), | ||
Error, | ||
"Invalid plugin name: dummy.invalid", | ||
); | ||
}); | ||
}); | ||
|
||
await t.step("if the plugin is not yet loaded", async (t) => { | ||
outputs = []; | ||
await host.call("execute", [ | ||
"let g:__test_denops_events = []", | ||
`call denops#plugin#check_type('notloadedplugin')`, | ||
], ""); | ||
|
||
await t.step("outputs an info message after delayed", async () => { | ||
await wait(() => outputs.join("").includes("No plugins are loaded")); | ||
}); | ||
|
||
await t.step("does not outputs an usage", () => { | ||
assertNotMatch(outputs.join(""), /Usage:/); | ||
}); | ||
}); | ||
|
||
await t.step("if the plugin is not exists", async (t) => { | ||
await host.call("execute", [ | ||
"call denops#plugin#load('notexistsplugin', 'path-to-not-exists-plugin.ts')", | ||
], ""); | ||
outputs = []; | ||
await host.call("execute", [ | ||
"let g:__test_denops_events = []", | ||
`call denops#plugin#check_type('notexistsplugin')`, | ||
], ""); | ||
|
||
await t.step("outputs an error message after delayed", async () => { | ||
await wait(() => outputs.join("").includes("Type check")); | ||
assertMatch(outputs.join(""), /Type check failed:/); | ||
}); | ||
|
||
await t.step("does not outputs an usage", () => { | ||
assertNotMatch(outputs.join(""), /Usage:/); | ||
}); | ||
}); | ||
|
||
await t.step("if the plugin is loaded", async (t) => { | ||
// Load plugin and wait. | ||
await host.call("execute", [ | ||
"let g:__test_denops_events = []", | ||
`call denops#plugin#load('dummyCheckTypeLoaded', '${scriptValid}')`, | ||
], ""); | ||
await wait(async () => | ||
(await host.call("eval", "g:__test_denops_events") as string[]) | ||
.includes("DenopsPluginPost:dummyCheckTypeLoaded") | ||
); | ||
|
||
outputs = []; | ||
await host.call("execute", [ | ||
"let g:__test_denops_events = []", | ||
`call denops#plugin#check_type('dummyCheckTypeLoaded')`, | ||
], ""); | ||
|
||
await t.step("outputs an info message after delayed", async () => { | ||
await wait(() => outputs.join("").includes("Type check")); | ||
assertMatch(outputs.join(""), /Type check succeeded/); | ||
}); | ||
}); | ||
|
||
await t.step("if the plugin is unloaded", async (t) => { | ||
// Load plugin and wait. | ||
await host.call("execute", [ | ||
"let g:__test_denops_events = []", | ||
`call denops#plugin#load('dummyCheckTypeUnloaded', '${scriptValid}')`, | ||
], ""); | ||
await wait(async () => | ||
(await host.call("eval", "g:__test_denops_events") as string[]) | ||
.includes("DenopsPluginPost:dummyCheckTypeUnloaded") | ||
); | ||
// Unload plugin and wait. | ||
await host.call("execute", [ | ||
"let g:__test_denops_events = []", | ||
`call denops#plugin#unload('dummyCheckTypeUnloaded')`, | ||
], ""); | ||
await wait(async () => | ||
(await host.call("eval", "g:__test_denops_events") as string[]) | ||
.includes("DenopsPluginUnloadPost:dummyCheckTypeUnloaded") | ||
); | ||
|
||
outputs = []; | ||
await host.call("execute", [ | ||
"let g:__test_denops_events = []", | ||
`call denops#plugin#check_type('dummyCheckTypeUnloaded')`, | ||
], ""); | ||
|
||
await t.step("outputs an info message after delayed", async () => { | ||
await wait(() => outputs.join("").includes("Type check")); | ||
assertMatch(outputs.join(""), /Type check succeeded/); | ||
}); | ||
}); | ||
|
||
await t.step("if the plugin is reloaded", async (t) => { | ||
// Load plugin and wait. | ||
await host.call("execute", [ | ||
"let g:__test_denops_events = []", | ||
`call denops#plugin#load('dummyCheckTypeReloaded', '${scriptValid}')`, | ||
], ""); | ||
await wait(async () => | ||
(await host.call("eval", "g:__test_denops_events") as string[]) | ||
.includes("DenopsPluginPost:dummyCheckTypeReloaded") | ||
); | ||
// Reload plugin and wait. | ||
await host.call("execute", [ | ||
"let g:__test_denops_events = []", | ||
`call denops#plugin#reload('dummyCheckTypeReloaded')`, | ||
], ""); | ||
await wait(async () => | ||
(await host.call("eval", "g:__test_denops_events") as string[]) | ||
.includes("DenopsPluginPost:dummyCheckTypeReloaded") | ||
); | ||
|
||
outputs = []; | ||
await host.call("execute", [ | ||
"let g:__test_denops_events = []", | ||
`call denops#plugin#check_type('dummyCheckTypeReloaded')`, | ||
], ""); | ||
|
||
await t.step("outputs an info message after delayed", async () => { | ||
await wait(() => outputs.join("").includes("Type check")); | ||
assertMatch(outputs.join(""), /Type check succeeded/); | ||
}); | ||
}); | ||
}, | ||
}); | ||
|
||
/** Resolve testdata script path. */ | ||
function resolve(path: string): string { | ||
return join(import.meta.dirname!, `../../../testdata/${path}`); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { | ||
assertArrayIncludes, | ||
assertEquals, | ||
assertMatch, | ||
} from "jsr:@std/assert@^1.0.1"; | ||
import { delay } from "jsr:@std/async@^0.224.0"; | ||
import { join } from "jsr:@std/path@^1.0.2/join"; | ||
import { testHost } from "/denops-testutil/host.ts"; | ||
import { wait } from "/denops-testutil/wait.ts"; | ||
|
||
const MESSAGE_DELAY = 200; // msc | ||
|
||
const runtimepathPlugin = resolve("dummy_plugins"); | ||
|
||
testHost({ | ||
name: "denops#plugin#discover()", | ||
mode: "all", | ||
postlude: [ | ||
"runtime plugin/denops.vim", | ||
], | ||
fn: async ({ host, t, stderr }) => { | ||
let outputs: string[] = []; | ||
stderr.pipeTo( | ||
new WritableStream({ write: (s) => void outputs.push(s) }), | ||
).catch(() => {}); | ||
await wait(() => host.call("eval", "denops#server#status() ==# 'running'")); | ||
await host.call("execute", [ | ||
"let g:__test_denops_events = []", | ||
"autocmd User DenopsPlugin* call add(g:__test_denops_events, expand('<amatch>'))", | ||
], ""); | ||
|
||
outputs = []; | ||
await host.call("execute", [ | ||
`set runtimepath+=${await host.call("fnameescape", runtimepathPlugin)}`, | ||
`call denops#plugin#discover()`, | ||
], ""); | ||
|
||
await t.step("loads denops plugins", async () => { | ||
const loaded_events = [ | ||
"DenopsPluginPost:", | ||
"DenopsPluginFail:", | ||
]; | ||
await wait(async () => | ||
(await host.call("eval", "g:__test_denops_events") as string[]) | ||
.filter((ev) => loaded_events.some((name) => ev.startsWith(name))) | ||
.length >= 2 | ||
); | ||
}); | ||
|
||
await t.step("fires DenopsPlugin* events", async () => { | ||
assertArrayIncludes( | ||
await host.call("eval", "g:__test_denops_events") as string[], | ||
[ | ||
"DenopsPluginPre:dummy_valid", | ||
"DenopsPluginPost:dummy_valid", | ||
"DenopsPluginPre:dummy_invalid", | ||
"DenopsPluginFail:dummy_invalid", | ||
], | ||
); | ||
}); | ||
|
||
await t.step("does not load invaid name plugins", async () => { | ||
const valid_names = [ | ||
":dummy_valid", | ||
":dummy_invalid", | ||
] as const; | ||
const actual = | ||
(await host.call("eval", "g:__test_denops_events") as string[]) | ||
.filter((ev) => !valid_names.some((name) => ev.endsWith(name))); | ||
assertEquals(actual, []); | ||
}); | ||
|
||
await t.step("calls the plugin entrypoint", () => { | ||
assertMatch(outputs.join(""), /Hello, Denops!/); | ||
}); | ||
|
||
await t.step("outputs an error message after delayed", async () => { | ||
await delay(MESSAGE_DELAY); | ||
assertMatch( | ||
outputs.join(""), | ||
/Failed to load plugin 'dummy_invalid': Error: This is dummy error/, | ||
); | ||
}); | ||
}, | ||
}); | ||
|
||
/** Resolve testdata script path. */ | ||
function resolve(path: string): string { | ||
return join(import.meta.dirname!, `../../../testdata/${path}`); | ||
} |
Oops, something went wrong.