Skip to content

Commit 49b38c4

Browse files
authored
Merge pull request #276 from vuejs/fix-plugins
fix: ensure plugins receive options correctly
2 parents 090afc1 + 9039531 commit 49b38c4

File tree

3 files changed

+79
-56
lines changed

3 files changed

+79
-56
lines changed

src/config.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,21 @@ interface GlobalConfigOptions {
1313
}
1414

1515
interface Plugin<Instance> {
16-
handler: (instance: Instance) => Record<string, any>
16+
handler: (
17+
instance: Instance,
18+
options: Record<string, any>
19+
) => Record<string, any>
1720
options: Record<string, any>
1821
}
1922

2023
class Pluggable<Instance = DOMWrapper<Element>> {
2124
installedPlugins: Plugin<Instance>[] = []
2225

2326
install(
24-
handler: (instance: Instance) => Record<string, any>,
27+
handler: (
28+
instance: Instance,
29+
options?: Record<string, any>
30+
) => Record<string, any>,
2531
options: Record<string, any> = {}
2632
) {
2733
if (typeof handler !== 'function') {
@@ -32,7 +38,9 @@ class Pluggable<Instance = DOMWrapper<Element>> {
3238
}
3339

3440
extend(instance: Instance) {
35-
const invokeSetup = (plugin: Plugin<Instance>) => plugin.handler(instance) // invoke the setup method passed to install
41+
const invokeSetup = ({ handler, options }: Plugin<Instance>) => {
42+
return handler(instance, options) // invoke the setup method passed to install
43+
}
3644
const bindProperty = ([property, value]: [string, any]) => {
3745
;(instance as any)[property] =
3846
typeof value === 'function' ? value.bind(instance) : value

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: 68 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,72 +7,88 @@ 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+
expect(wrapper.greet('Lachlan')).toBe('Hello, Lachlan')
37+
})
4838

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

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

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

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

0 commit comments

Comments
 (0)