generated from florian-lefebvre/astro-integration-template
-
-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Allow plugins to initalize themselves on unused hooks (#114)
- Loading branch information
Showing
3 changed files
with
196 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"astro-integration-kit": patch | ||
--- | ||
|
||
Fixes initialization of plugins when necessary hooks are not used by consumer integrations |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
import { describe, expect, it } from "vitest"; | ||
import { definePlugin } from "../../src/core/define-plugin.js"; | ||
import { withPlugins } from "../../src/core/with-plugins.js"; | ||
import type { AstroIntegrationLogger } from "astro"; | ||
|
||
describe('withPlugins', () => { | ||
const fooPlugin = definePlugin({ | ||
name: 'foo', | ||
setup({ name }) { | ||
let innerState: string = 'initial state'; | ||
|
||
return { | ||
'astro:build:start': ({ logger }) => { | ||
logger.info(`Called from plugin "foo" on integration "${name}".`); | ||
|
||
return { | ||
foo: (msg: string) => { | ||
logger.info(`Calling "foo" with msg: ${msg}`); | ||
}, | ||
setState: (state: string) => { | ||
innerState = state; | ||
}, | ||
}; | ||
}, | ||
'astro:server:done': ({ logger }) => ({ | ||
getState: () => { | ||
logger.info('Reading state'); | ||
return innerState; | ||
}, | ||
}), | ||
}; | ||
}, | ||
}); | ||
|
||
const otherFooPlugin = definePlugin({ | ||
name: 'foo', | ||
setup({ name }) { | ||
return { | ||
'astro:build:start': ({ logger }) => { | ||
logger.info(`Called from plugin "otherFoo" on integration "${name}".`); | ||
|
||
return { | ||
foo: (msg: string) => { | ||
logger.info(`Calling "foo" (from otherFoo) with msg: ${msg}`); | ||
} | ||
}; | ||
}, | ||
}; | ||
}, | ||
}); | ||
|
||
const barPlugin = definePlugin({ | ||
name: 'bar', | ||
setup({ name }) { | ||
return { | ||
'astro:build:start': ({ logger }) => { | ||
logger.info(`Called from plugin "bar" on integration "${name}".`); | ||
|
||
return { | ||
foo: (msg: string) => { | ||
logger.info(`Calling "foo" (from bar) with msg: ${msg}`); | ||
} | ||
}; | ||
}, | ||
}; | ||
}, | ||
}); | ||
|
||
it('should provide the plugins API to the hooks', () => { | ||
const integration = withPlugins({ | ||
name: 'my-integration', | ||
plugins: [fooPlugin], | ||
hooks: { | ||
'astro:build:start': ({ foo, setState }) => { | ||
foo('from integration'); | ||
setState('integrationState') | ||
}, | ||
'astro:server:done': ({ getState }) => { | ||
expect(getState()).toEqual('integrationState'); | ||
}, | ||
}, | ||
}); | ||
|
||
const logger = new MemoryLogger(); | ||
|
||
integration.hooks['astro:build:start']?.({ logger }); | ||
integration.hooks['astro:server:done']?.({ logger }); | ||
|
||
expect(logger.log).toStrictEqual([ | ||
'Called from plugin "foo" on integration "my-integration".', | ||
'Calling "foo" with msg: from integration', | ||
'Reading state', | ||
]); | ||
}); | ||
|
||
it('should override plugins with the same name', () => { | ||
const integration = withPlugins({ | ||
name: 'my-integration', | ||
plugins: [fooPlugin, otherFooPlugin], | ||
hooks: { | ||
'astro:build:start': ({ foo }) => { | ||
foo('from integration'); | ||
} | ||
}, | ||
}); | ||
|
||
const logger = new MemoryLogger(); | ||
|
||
integration.hooks['astro:build:start']?.({ logger }); | ||
|
||
expect(logger.log).toStrictEqual([ | ||
'Called from plugin "otherFoo" on integration "my-integration".', | ||
'Calling "foo" (from otherFoo) with msg: from integration', | ||
]); | ||
}); | ||
|
||
it('should override plugin APIs with the same name', () => { | ||
const integration = withPlugins({ | ||
name: 'my-integration', | ||
plugins: [fooPlugin, barPlugin], | ||
hooks: { | ||
'astro:build:start': ({ foo }) => { | ||
foo('from integration'); | ||
} | ||
}, | ||
}); | ||
|
||
const logger = new MemoryLogger(); | ||
|
||
integration.hooks['astro:build:start']?.({ logger }); | ||
|
||
expect(logger.log).toStrictEqual([ | ||
'Called from plugin "foo" on integration "my-integration".', | ||
'Called from plugin "bar" on integration "my-integration".', | ||
'Calling "foo" (from bar) with msg: from integration', | ||
]); | ||
}); | ||
|
||
it('should run plugin hooks that are not part of the integration', () => { | ||
const integration = withPlugins({ | ||
name: 'my-integration', | ||
plugins: [fooPlugin], | ||
hooks: { | ||
'astro:server:done': ({ getState }) => { | ||
expect(getState()).toEqual('initial state'); | ||
}, | ||
}, | ||
}); | ||
|
||
const logger = new MemoryLogger(); | ||
|
||
integration.hooks['astro:build:start']?.({ logger }); | ||
integration.hooks['astro:server:done']?.({ logger }); | ||
|
||
expect(logger.log).toStrictEqual([ | ||
'Called from plugin "foo" on integration "my-integration".', | ||
'Reading state' | ||
]); | ||
}); | ||
}); | ||
|
||
class MemoryLogger implements AstroIntegrationLogger { | ||
log: string[] = []; | ||
|
||
options = {} as any; | ||
label: string = ''; | ||
|
||
fork(): AstroIntegrationLogger { | ||
return this; | ||
} | ||
|
||
info(message: string): void { | ||
this.log.push(message); | ||
} | ||
warn(message: string): void { | ||
this.log.push(message); | ||
} | ||
error(message: string): void { | ||
this.log.push(message); | ||
} | ||
debug(message: string): void { | ||
this.log.push(message); | ||
} | ||
} | ||
|