Skip to content

Commit 4f66f19

Browse files
committed
feat(useLocalStorage): Adding useLocalStorage function
1 parent b848557 commit 4f66f19

File tree

7 files changed

+348
-40
lines changed

7 files changed

+348
-40
lines changed

src/components/useCookie/useCookie.spec.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ describe('useCookie', () => {
7272
expect(document.cookie).not.toContain(cookieValue)
7373
})
7474

75-
it('should correctly get and set the parseToJson object', async () => {
75+
it('should correctly get and set the isParsing object', async () => {
7676
const cookieName = 'cookieName'
7777
const cookieValue = { value1: 'testValue1', value2: 'testValue2' }
7878
const wrapper = mount(
@@ -133,10 +133,11 @@ describe('useCookie', () => {
133133
const wrapper = mount(
134134
testComponent(cookieName, cookieValue, {
135135
isParsing: true,
136-
serializer: (obj: any) => ({
137-
value1: `${obj.value1}+1`,
138-
value2: `${obj.value2}+1`
139-
})
136+
serializer: (obj: any) =>
137+
JSON.stringify({
138+
value1: `${obj.value1}+1`,
139+
value2: `${obj.value2}+1`
140+
})
140141
})
141142
)
142143
wrapper.find('#setCookie').trigger('click')
@@ -153,10 +154,11 @@ describe('useCookie', () => {
153154
const wrapper = mount(
154155
testComponent(cookieName, cookieValue, {
155156
isParsing: false,
156-
serializer: (obj: any) => ({
157-
value1: `${obj.value1}+1`,
158-
value2: `${obj.value2}+1`
159-
})
157+
serializer: (obj: any) =>
158+
JSON.stringify({
159+
value1: `${obj.value1}+1`,
160+
value2: `${obj.value2}+1`
161+
})
160162
})
161163
)
162164
wrapper.find('#setCookie').trigger('click')

src/components/useCookie/useCookie.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import {
44
createSerializer,
55
createDeserializer,
66
trySerialize,
7-
tryDeserialize
7+
tryDeserialize,
8+
isNullOrUndefined
89
} from '@src/utils'
910
import { ref, onMounted, Ref } from '@src/api'
1011

@@ -24,19 +25,19 @@ export function useCookie(
2425
runOnMount = true
2526
) {
2627
const { isParsing, ...opts } = Object.assign({}, defaultOptions, options)
27-
const cookieLib = Cookies(undefined, undefined, false)
28-
const cookie: Ref<any> = ref(null)
29-
3028
const serializer = createSerializer(opts.serializer)
3129
const deserializer = createDeserializer(opts.deserializer)
3230

31+
const cookieLib = Cookies(undefined, undefined, false)
32+
const cookie: Ref<any> = ref(null)
33+
3334
const getCookie = () => {
3435
const cookieVal = tryDeserialize(
3536
cookieLib.get(cookieName),
3637
deserializer,
3738
isParsing
3839
)
39-
if (typeof cookieVal !== 'undefined') cookie.value = cookieVal
40+
if (!isNullOrUndefined(cookieVal)) cookie.value = cookieVal
4041
}
4142

4243
const setCookie = (

src/components/useLocalStorage/stories/UseLocalStorageDemo.vue

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,77 @@
88
</thead>
99
<tbody>
1010
<tr>
11-
<td>Sample</td>
12-
<td>{{ sample }}</td>
11+
<td>item</td>
12+
<td>{{ item }}</td>
13+
</tr>
14+
<tr>
15+
<td colspan="2">
16+
<button class="button is-primary" @click="handleSetItem">
17+
Set / Update item
18+
</button>
19+
<button class="button is-danger" @click="removeItem()">
20+
Remove item
21+
</button>
22+
</td>
23+
</tr>
24+
<tr>
25+
<td>jsonItem</td>
26+
<td>{{ jsonItem }}</td>
27+
</tr>
28+
<tr>
29+
<td colspan="2">
30+
<button class="button is-primary" @click="handleSetJsonItem">
31+
Set / Update JSON item
32+
</button>
33+
<button class="button is-danger" @click="jsonRemoveItem()">
34+
Remove JSON item
35+
</button>
36+
</td>
1337
</tr>
1438
</tbody>
1539
</table>
1640
</template>
1741

1842
<script lang="ts">
1943
import Vue from 'vue'
20-
// import { useLocalStorage } from '@src/vue-use-kit'
44+
import { useLocalStorage } from '@src/vue-use-kit'
2145
2246
export default Vue.extend({
23-
name: 'UseLocalStorageDemo',
47+
name: 'useLocalStorageDemo',
2448
setup() {
25-
return { sample: 'sample' }
49+
const { item, setItem, removeItem } = useLocalStorage('normalItem')
50+
51+
const {
52+
item: jsonItem,
53+
setItem: jsonSetItem,
54+
removeItem: jsonRemoveItem
55+
} = useLocalStorage('jsonItem', {
56+
isParsing: true
57+
})
58+
59+
let counter = 0
60+
const handleSetItem = () => {
61+
counter++
62+
setItem(`count${counter}`)
63+
}
64+
65+
const handleSetJsonItem = () => {
66+
counter++
67+
jsonSetItem({
68+
counter: counter,
69+
counterTest: `test${counter}`
70+
})
71+
}
72+
73+
return {
74+
item,
75+
handleSetItem,
76+
removeItem,
77+
jsonItem,
78+
handleSetJsonItem,
79+
jsonRemoveItem,
80+
counter
81+
}
2682
}
2783
})
2884
</script>
Lines changed: 182 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,189 @@
1-
// import { mount } from '@src/helpers/test'
2-
// import { useLocalStorage } from '@src/vue-use-kit'
1+
import { mount } from '@src/helpers/test'
2+
import { useLocalStorage } from '@src/vue-use-kit'
3+
4+
const localStorageMock = () => {
5+
let store = {} as any
6+
return {
7+
getItem(key: any) {
8+
return store[key]
9+
},
10+
setItem(key: any, value: any) {
11+
store[key] = String(value)
12+
},
13+
clear() {
14+
store = {}
15+
},
16+
removeItem(key: any) {
17+
delete store[key]
18+
}
19+
}
20+
}
21+
22+
beforeEach(() => {
23+
;(window as any).localStorage = localStorageMock()
24+
})
325

426
afterEach(() => {
527
jest.clearAllMocks()
628
})
729

8-
describe('useLocalStorage', () => {
9-
it('should do something', () => {
10-
// Add test here
30+
const testComponent = (
31+
key = 'key',
32+
itemValue: any = '',
33+
opts = { isParsing: false } as any,
34+
onMount = true
35+
) => ({
36+
template: `
37+
<div>
38+
<div id="item">{{ item }}</div>
39+
<div id="itemJson">
40+
{{ item && item.value1 }} - {{ item && item.value2 }}
41+
</div>
42+
<button id="getItem" @click="getItem"></button>
43+
<button id="setItem" @click="setItem(itemValue)"></button>
44+
<button id="removeItem" @click="removeItem"></button>
45+
</div>
46+
`,
47+
setup() {
48+
const { item, getItem, setItem, removeItem } = useLocalStorage(
49+
key,
50+
opts,
51+
onMount
52+
)
53+
54+
return {
55+
item,
56+
getItem,
57+
setItem,
58+
removeItem,
59+
itemValue
60+
}
61+
}
62+
})
63+
64+
describe('useItem', () => {
65+
it('should get a item with the given value', async () => {
66+
const itemKey = 'itemKey'
67+
const itemValue = 'itemValue'
68+
;(window as any).localStorage.setItem(itemKey, itemValue)
69+
const wrapper = mount(testComponent(itemKey))
70+
await wrapper.vm.$nextTick()
71+
expect(wrapper.html()).toContain(itemValue)
72+
})
73+
74+
it('should set a item with the given value', async () => {
75+
const itemKey = 'itemKey'
76+
const itemValue = 'itemValue'
77+
const wrapper = mount(testComponent(itemKey, itemValue))
78+
await wrapper.vm.$nextTick()
79+
expect(localStorage.getItem(itemKey)).toContain(itemValue)
80+
})
81+
82+
it('should remove a item with the given value', async () => {
83+
const itemKey = 'itemKey'
84+
const itemValue = 'itemValue'
85+
const wrapper = mount(testComponent(itemKey, itemValue))
86+
await wrapper.vm.$nextTick()
87+
expect(localStorage.getItem(itemKey)).toContain(itemValue)
88+
wrapper.find('#removeItem').trigger('click')
89+
await wrapper.vm.$nextTick()
90+
expect(localStorage.getItem(itemKey)).toBeFalsy()
91+
})
92+
93+
it('should correctly get and set the isParsing object', async () => {
94+
const itemKey = 'itemKey'
95+
const itemValue = { value1: 'testValue1', value2: 'testValue2' }
96+
const wrapper = mount(
97+
testComponent(itemKey, itemValue, { isParsing: true })
98+
)
99+
wrapper.find('#setItem').trigger('click')
100+
await wrapper.vm.$nextTick()
101+
expect(wrapper.find('#itemJson').html()).toContain(itemValue.value1)
102+
expect(wrapper.find('#itemJson').html()).toContain(itemValue.value2)
103+
104+
// Also check that when clicking #getItem we still get a proper JSON object
105+
wrapper.find('#getItem').trigger('click')
106+
await wrapper.vm.$nextTick()
107+
expect(wrapper.find('#itemJson').html()).toContain(itemValue.value1)
108+
expect(wrapper.find('#itemJson').html()).toContain(itemValue.value2)
109+
})
110+
111+
it('should correctly get using the deserializer', async () => {
112+
const itemKey = 'itemKey'
113+
const itemValue = { value1: 'testValue1', value2: 'testValue2' }
114+
const deserializerVal = { value1: 'gatto', value2: 'topo' }
115+
const wrapper = mount(
116+
testComponent(itemKey, itemValue, {
117+
isParsing: true,
118+
deserializer: () => deserializerVal
119+
})
120+
)
121+
await wrapper.vm.$nextTick()
122+
expect(wrapper.find('#itemJson').html()).toContain(deserializerVal.value1)
123+
expect(wrapper.find('#itemJson').html()).toContain(deserializerVal.value2)
124+
})
125+
126+
it('should ignore deserializer when isParsing is false', async () => {
127+
const itemKey = 'itemKey'
128+
const itemValue = { value1: 'testValue1', value2: 'testValue2' }
129+
const deserializerVal = { value1: 'gatto', value2: 'topo' }
130+
const wrapper = mount(
131+
testComponent(itemKey, itemValue, {
132+
isParsing: false,
133+
deserializer: () => deserializerVal
134+
})
135+
)
136+
await wrapper.vm.$nextTick()
137+
expect(wrapper.find('#item').html()).toContain(itemValue.value1)
138+
expect(wrapper.find('#item').html()).toContain(itemValue.value2)
139+
expect(wrapper.find('#itemJson').html()).not.toContain(
140+
deserializerVal.value1
141+
)
142+
expect(wrapper.find('#itemJson').html()).not.toContain(
143+
deserializerVal.value2
144+
)
145+
})
146+
147+
it('should correctly set using the serializer', async () => {
148+
const itemKey = 'itemKey'
149+
const itemValue = { value1: 'testValue1', value2: 'testValue2' }
150+
const serializerVal = { value1: 'testValue1+1', value2: 'testValue2+1' }
151+
const wrapper = mount(
152+
testComponent(itemKey, itemValue, {
153+
isParsing: true,
154+
serializer: (obj: any) =>
155+
JSON.stringify({
156+
value1: `${obj.value1}+1`,
157+
value2: `${obj.value2}+1`
158+
})
159+
})
160+
)
161+
wrapper.find('#setItem').trigger('click')
162+
wrapper.find('#getItem').trigger('click')
163+
await wrapper.vm.$nextTick()
164+
expect(wrapper.find('#itemJson').html()).toContain(serializerVal.value1)
165+
expect(wrapper.find('#itemJson').html()).toContain(serializerVal.value2)
166+
})
167+
168+
it('should ignore serializer when isParsing is false', async () => {
169+
const itemKey = 'itemKey'
170+
const itemValue = { value1: 'testValue1', value2: 'testValue2' }
171+
const serializerVal = { value1: 'testValue1+1', value2: 'testValue2+1' }
172+
const wrapper = mount(
173+
testComponent(itemKey, itemValue, {
174+
isParsing: false,
175+
serializer: (obj: any) =>
176+
JSON.stringify({
177+
value1: `${obj.value1}+1`,
178+
value2: `${obj.value2}+1`
179+
})
180+
})
181+
)
182+
wrapper.find('#setItem').trigger('click')
183+
wrapper.find('#getItem').trigger('click')
184+
await wrapper.vm.$nextTick()
185+
expect(wrapper.find('#item').html()).toContain('[object Object]')
186+
expect(wrapper.find('#itemJson').html()).not.toContain(serializerVal.value1)
187+
expect(wrapper.find('#itemJson').html()).not.toContain(serializerVal.value2)
11188
})
12189
})

0 commit comments

Comments
 (0)