n8n/packages/frontend/@n8n/composables/src/useExternalHooks.test.ts
Alex Grozav 7c5196ddf6
Some checks are pending
Build: Benchmark Image / build (push) Waiting to run
CI: Master (Build, Test, Lint) / Build for Github Cache (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (22.22.3) (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (24.18.0) (push) Waiting to run
CI: Master (Build, Test, Lint) / Lint (push) Waiting to run
CI: Master (Build, Test, Lint) / Performance (push) Waiting to run
CI: Master (Build, Test, Lint) / Notify Slack on failure (push) Blocked by required conditions
Util: Sync API Docs / sync-public-api (push) Waiting to run
refactor(editor): Decouple useExternalHooks for package use (no-changelog) (#34705)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 07:28:19 +00:00

75 lines
1.9 KiB
TypeScript

import { render } from '@testing-library/vue';
import { defineComponent, h } from 'vue';
import {
setExternalHooks,
ExternalHooksKey,
useExternalHooks,
type ExternalHooks,
} from './useExternalHooks';
function createExternalHooks(): ExternalHooks {
return {
run: vi.fn().mockResolvedValue(undefined),
};
}
describe('useExternalHooks', () => {
afterEach(() => {
setExternalHooks(undefined);
});
it('returns a no-op runner when nothing is registered', async () => {
const externalHooks = useExternalHooks();
// `run` resolves to a no-op; calling must not throw and must be awaitable.
await expect(externalHooks.run('app.mount')).resolves.toBeUndefined();
});
it('returns the registered runner from any context', async () => {
const registered = createExternalHooks();
setExternalHooks(registered);
const externalHooks = useExternalHooks();
await externalHooks.run('app.mount', { foo: 'bar' });
expect(externalHooks).toBe(registered);
expect(registered.run).toHaveBeenCalledWith('app.mount', { foo: 'bar' });
});
it('prefers a component-provided runner over the registered one', () => {
const registered = createExternalHooks();
const provided = createExternalHooks();
setExternalHooks(registered);
let resolved: ExternalHooks | undefined;
const Consumer = defineComponent({
setup() {
resolved = useExternalHooks();
return () => h('div');
},
});
render(Consumer, { global: { provide: { [ExternalHooksKey as symbol]: provided } } });
expect(resolved).toBe(provided);
expect(resolved).not.toBe(registered);
});
it('falls back to the registered runner inside a component without a provided key', () => {
const registered = createExternalHooks();
setExternalHooks(registered);
let resolved: ExternalHooks | undefined;
const Consumer = defineComponent({
setup() {
resolved = useExternalHooks();
return () => h('div');
},
});
render(Consumer);
expect(resolved).toBe(registered);
});
});