Skip to content

Commit f14609a

Browse files
committed
fix: ensure plugins receive options correctly
1 parent 090afc1 commit f14609a

File tree

3 files changed

+87
-57
lines changed

3 files changed

+87
-57
lines changed

src/config.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ComponentPublicInstance } from 'vue'
22
import { GlobalMountOptions } from './types'
33
import { VueWrapper } from './vueWrapper'
44
import { DOMWrapper } from './domWrapper'
5+
import { allowedNodeEnvironmentFlags } from 'process'
56

67
interface GlobalConfigOptions {
78
global: Required<GlobalMountOptions>
@@ -13,15 +14,21 @@ interface GlobalConfigOptions {
1314
}
1415

1516
interface Plugin<Instance> {
16-
handler: (instance: Instance) => Record<string, any>
17+
handler: (
18+
instance: Instance,
19+
options: Record<string, any>
20+
) => Record<string, any>
1721
options: Record<string, any>
1822
}
1923

2024
class Pluggable<Instance = DOMWrapper<Element>> {
2125
installedPlugins: Plugin<Instance>[] = []
2226

2327
install(
24-
handler: (instance: Instance) => Record<string, any>,
28+
handler: (
29+
instance: Instance,
30+
options?: Record<string, any>
31+
) => Record<string, any>,
2532
options: Record<string, any> = {}
2633
) {
2734
if (typeof handler !== 'function') {
@@ -32,7 +39,9 @@ class Pluggable<Instance = DOMWrapper<Element>> {
3239
}
3340

3441
extend(instance: Instance) {
35-
const invokeSetup = (plugin: Plugin<Instance>) => plugin.handler(instance) // invoke the setup method passed to install
42+
const invokeSetup = ({ handler, options }: Plugin<Instance>) => {
43+
return handler(instance, options) // invoke the setup method passed to install
44+
}
3645
const bindProperty = ([property, value]: [string, any]) => {
3746
;(instance as any)[property] =
3847
typeof value === 'function' ? value.bind(instance) : value
@@ -42,7 +51,12 @@ class Pluggable<Instance = DOMWrapper<Element>> {
4251
Object.entries(setupResult).forEach(bindProperty)
4352
}
4453

45-
this.installedPlugins.map(invokeSetup).forEach(addAllPropertiesFromSetup)
54+
// this.installedPlugins.map(invokeSetup).forEach(addAllPropertiesFromSetup)
55+
this.installedPlugins
56+
.map((plugin) => {
57+
return invokeSetup({ handler: plugin.handler, options: plugin.options })
58+
})
59+
.forEach(addAllPropertiesFromSetup)
4660
}
4761

4862
/** For testing */

src/vueWrapper.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ export class VueWrapper<T extends ComponentPublicInstance> {
2525
this.rootVM = vm?.$root
2626
this.componentVM = vm as T
2727
this.__setProps = setProps
28-
// plugins hook
2928
config.plugins.VueWrapper.extend(this)
3029
}
3130

tests/features/plugins.spec.ts

Lines changed: 69 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,72 +7,89 @@ declare module '../../src/vueWrapper' {
77
width(): number
88
$el: Element
99
myMethod(): void
10+
greet: (name: string) => string
1011
}
1112
}
1213

1314
const textValue = `I'm the innerHTML`
1415
const mountComponent = () => mount({ template: `<h1>${textValue}</h1>` })
1516

16-
describe('Plugin', () => {
17-
describe('#install method', () => {
18-
beforeEach(() => {
19-
config.plugins.VueWrapper.reset()
20-
})
21-
22-
it('extends wrappers with the return values from the install function', () => {
23-
const width = 230
24-
const plugin = () => ({ width })
25-
config.plugins.VueWrapper.install(plugin)
26-
const wrapper = mountComponent()
27-
expect(wrapper).toHaveProperty('width', width)
28-
})
17+
describe('Plugin#install', () => {
18+
beforeEach(() => {
19+
config.plugins.VueWrapper.reset()
20+
})
2921

30-
it('receives the wrapper inside the plugin setup', () => {
31-
const plugin = (wrapper: VueWrapper<ComponentPublicInstance>) => {
32-
return {
33-
$el: wrapper.element // simple aliases
22+
it('accepts options', () => {
23+
function PluginWithOptions(
24+
wrapper: VueWrapper<ComponentPublicInstance>,
25+
options: Record<string, string>
26+
) {
27+
return {
28+
greet: (name: string) => {
29+
return `${options.msg}, ${name}`
3430
}
3531
}
36-
config.plugins.VueWrapper.install(plugin)
37-
const wrapper = mountComponent()
38-
expect(wrapper.$el.innerHTML).toEqual(textValue)
39-
})
32+
}
33+
config.plugins.VueWrapper.install(PluginWithOptions, { msg: 'Hello' })
4034

41-
it('supports functions', () => {
42-
const myMethod = jest.fn()
43-
const plugin = () => ({ myMethod })
44-
config.plugins.VueWrapper.install(plugin)
45-
mountComponent().myMethod()
46-
expect(myMethod).toHaveBeenCalledTimes(1)
47-
})
35+
const wrapper = mountComponent()
36+
// @ts-ignore
37+
expect(wrapper.greet('Lachlan')).toBe('Hello, Lachlan')
38+
})
4839

49-
describe('error states', () => {
50-
beforeAll(() => {
51-
jest.spyOn(console, 'error').mockImplementation(() => {})
52-
})
40+
it('extends wrappers with the return values from the install function', () => {
41+
const width = 230
42+
const plugin = () => ({ width })
43+
config.plugins.VueWrapper.install(plugin)
44+
const wrapper = mountComponent()
45+
expect(wrapper).toHaveProperty('width', width)
46+
})
5347

54-
afterAll(() => {
55-
// @ts-ignore
56-
console.error.mockRestore()
57-
})
48+
it('receives the wrapper inside the plugin setup', () => {
49+
const plugin = (wrapper: VueWrapper<ComponentPublicInstance>) => {
50+
return {
51+
$el: wrapper.element // simple aliases
52+
}
53+
}
54+
config.plugins.VueWrapper.install(plugin)
55+
const wrapper = mountComponent()
56+
expect(wrapper.$el.innerHTML).toEqual(textValue)
57+
})
5858

59-
const plugins = [
60-
() => false,
61-
() => true,
62-
() => [],
63-
true,
64-
false,
65-
'property',
66-
120
67-
]
59+
it('supports functions', () => {
60+
const myMethod = jest.fn()
61+
const plugin = () => ({ myMethod })
62+
config.plugins.VueWrapper.install(plugin)
63+
mountComponent().myMethod()
64+
expect(myMethod).toHaveBeenCalledTimes(1)
65+
})
6866

69-
it.each(plugins)(
70-
'Calling install with %p is handled gracefully',
71-
(plugin) => {
72-
config.plugins.VueWrapper.install(plugin as any)
73-
expect(() => mountComponent()).not.toThrow()
74-
}
75-
)
67+
describe('error states', () => {
68+
beforeAll(() => {
69+
jest.spyOn(console, 'error').mockImplementation(() => {})
70+
})
71+
72+
afterAll(() => {
73+
// @ts-ignore
74+
console.error.mockRestore()
7675
})
76+
77+
const plugins = [
78+
() => false,
79+
() => true,
80+
() => [],
81+
true,
82+
false,
83+
'property',
84+
120
85+
]
86+
87+
it.each(plugins)(
88+
'Calling install with %p is handled gracefully',
89+
(plugin) => {
90+
config.plugins.VueWrapper.install(plugin as any)
91+
expect(() => mountComponent()).not.toThrow()
92+
}
93+
)
7794
})
7895
})

0 commit comments

Comments
 (0)