Skip to content

Commit f2b070b

Browse files
committed
feat: new lifecycle properties
1 parent 8218908 commit f2b070b

File tree

4 files changed

+162
-3
lines changed

4 files changed

+162
-3
lines changed

README.md

+63
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,69 @@ And then grab it off the global like so:
5252
```js
5353
const Fragment = svelteFragment
5454
```
55+
56+
## Usage
57+
58+
> The examples below are using [svelte-jsx](https://www.npmjs.com/package/svelte-jsx) for the jsx syntax support.
59+
60+
```js
61+
import Fragment from 'svelte-fragment-component'
62+
63+
const Lifecycle = (
64+
<Fragment
65+
onCreate={() => {}}
66+
onMount={() => {}}
67+
beforeUpdate={() => {}}
68+
afterUpdate={() => {}}
69+
onDestroy={() => {}}
70+
>
71+
some content
72+
</Fragment>
73+
)
74+
```
75+
76+
This allows to simplify testing of [context API](https://svelte.dev/docs#setContext):
77+
78+
```js
79+
import Fragment from 'svelte-fragment-component'
80+
import { setContext } from 'svelte'
81+
82+
const Lifecycle = (
83+
<Fragment
84+
onCreate={() => {
85+
setContext('some context key', theValue)
86+
}}
87+
>
88+
children can now access this context value
89+
</Fragment>
90+
)
91+
92+
// or using the context property
93+
const Lifecycle = (
94+
<Fragment context={{ 'some context key': theValue }}>
95+
children can now access this context value
96+
</Fragment>
97+
)
98+
```
99+
100+
## API
101+
102+
The component renders only the default slot children.
103+
104+
### Properties
105+
106+
> All properties are optional.
107+
108+
- `context`: an key-value object where each pair is passed to [setContext](https://svelte.dev/docs#setContext)
109+
110+
Except for `onCreate` these functions are passed to their corresponding svelte lifecycle method and have the same call signature `({ props }): void` where `props` are the `$$restProps`:
111+
112+
- `onCreate`: called during component initialization
113+
- [onMount](https://svelte.dev/docs#onMount)
114+
- [beforeUpdate](https://svelte.dev/docs#beforeUpdate)
115+
- [afterUpdate](https://svelte.dev/docs#afterUpdate)
116+
- [onDestroy](https://svelte.dev/docs#onDestroy)
117+
55118
## Support
56119

57120
This project is free and open-source, so if you think this project can help you or anyone else, you may [star it on GitHub](https://github.com/sastan/svelte-fragment-component). Feel free to [open an issue](https://github.com/sastan/svelte-fragment-component/issues) if you have any idea, question, or you've found a bug.

package.json

-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@
5454
},
5555
"homepage": "https://github.com/sastan/svelte-fragment-component#readme",
5656
"devDependencies": {
57-
"@jest/globals": "^26.0.1",
5857
"@rollup/plugin-commonjs": "^13.0.0",
5958
"@rollup/plugin-node-resolve": "^8.0.1",
6059
"@testing-library/jest-dom": "^5.7.0",

src/fragment.svelte

+28
Original file line numberDiff line numberDiff line change
@@ -1 +1,29 @@
1+
<script>
2+
import * as Svelte from 'svelte'
3+
4+
export let context = null
5+
export let onCreate = null
6+
export let onMount = null
7+
export let beforeUpdate = null
8+
export let afterUpdate = null
9+
export let onDestroy = null
10+
11+
if (context) {
12+
Object.keys(context).forEach((key) => {
13+
Svelte.setContext(key, context[key])
14+
})
15+
}
16+
17+
if (onCreate) bind(onCreate)()
18+
19+
if (onMount) Svelte.onMount(bind(onMount))
20+
if (beforeUpdate) Svelte.beforeUpdate(bind(beforeUpdate))
21+
if (afterUpdate) Svelte.afterUpdate(bind(afterUpdate))
22+
if (onDestroy) Svelte.onDestroy(bind(onDestroy))
23+
24+
function bind(callback) {
25+
return () => callback({ props: $$restProps })
26+
}
27+
</script>
28+
129
<slot></slot>

src/fragment.test.js

+71-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,79 @@
1-
const { expect, test } = require('@jest/globals')
2-
const { render } = require('@testing-library/svelte')
1+
const { render, act } = require('@testing-library/svelte')
2+
const { getContext } = require('svelte')
33

44
const WithChilds = require('./__fixtures__/with-childs.svelte')
5+
const Fragment = require('./fragment.svelte')
56

67
test('renders all childs', () => {
78
const { container } = render(WithChilds)
89

910
expect(container.innerHTML).toMatch('<div>A<span>B</span>C</div>')
1011
})
12+
13+
test('calls onCreate', () => {
14+
const onCreate = jest.fn()
15+
16+
render(Fragment, { props: { onCreate, a: 1 } })
17+
18+
expect(onCreate).toHaveBeenCalledWith({ props: { a: 1 } })
19+
})
20+
21+
test('calls onMount', () => {
22+
const onMount = jest.fn()
23+
24+
render(Fragment, { props: { onMount, a: 1 } })
25+
26+
expect(onMount).toHaveBeenCalledWith({ props: { a: 1 } })
27+
})
28+
29+
test('calls beforeUpdate', async () => {
30+
const beforeUpdate = jest.fn()
31+
32+
const { component } = render(Fragment, { props: { beforeUpdate, a: 1 } })
33+
34+
expect(beforeUpdate).toHaveBeenCalledWith({ props: { a: 1 } })
35+
36+
await act(() => component.$set({ b: 2 }))
37+
38+
expect(beforeUpdate).toHaveBeenCalledWith({ props: { a: 1, b: 2 } })
39+
})
40+
41+
test('calls afterUpdate', async () => {
42+
const afterUpdate = jest.fn()
43+
44+
const { component } = render(Fragment, { props: { afterUpdate, a: 1 } })
45+
46+
expect(afterUpdate).toHaveBeenCalledWith({ props: { a: 1 } })
47+
48+
await act(() => component.$set({ b: 2 }))
49+
50+
expect(afterUpdate).toHaveBeenCalledWith({ props: { a: 1, b: 2 } })
51+
})
52+
53+
test('calls onDestroy', async () => {
54+
const onDestroy = jest.fn()
55+
56+
const { component } = render(Fragment, { props: { onDestroy, a: 1 } })
57+
58+
await act(() => component.$destroy())
59+
60+
expect(onDestroy).toHaveBeenCalledWith({ props: { a: 1 } })
61+
})
62+
63+
test('create context', () => {
64+
let a
65+
let b
66+
67+
render(Fragment, {
68+
props: {
69+
context: { a: 1, b: 2 },
70+
onMount: () => {
71+
a = getContext('a')
72+
b = getContext('b')
73+
},
74+
},
75+
})
76+
77+
expect(a).toBe(1)
78+
expect(b).toBe(2)
79+
})

0 commit comments

Comments
 (0)