bt-core-app 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/test/api.test.ts +84 -0
- package/test/forage.test.ts +31 -0
- package/test/helpers.test.ts +231 -0
- package/test/navigation.test.ts +99 -0
- package/test/stores-last-update.test.ts +138 -0
- package/test/stores-session.test.ts +118 -0
- package/test/track.test.ts +29 -0
- package/test/utils.ts +15 -0
- package/tsconfig.json +33 -0
- package/index.html +0 -13
- package/public/vite.svg +0 -1
package/package.json
CHANGED
package/test/api.test.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { describe, test, expect, afterAll, afterEach, beforeAll } from 'vitest'
|
|
2
|
+
import { createApi } from '../src/composables/api'
|
|
3
|
+
import { setupServer } from 'msw/node'
|
|
4
|
+
import { http, HttpResponse } from 'msw'
|
|
5
|
+
|
|
6
|
+
const handlers = [
|
|
7
|
+
http.get('https://test-api/get/1', () => {
|
|
8
|
+
return HttpResponse.json({
|
|
9
|
+
data: { test: 'a' },
|
|
10
|
+
count: 0,
|
|
11
|
+
filters: ['test']
|
|
12
|
+
})
|
|
13
|
+
}),
|
|
14
|
+
http.get('https://test-api/get/2', () => {
|
|
15
|
+
return new HttpResponse('not found', {
|
|
16
|
+
status: 304
|
|
17
|
+
})
|
|
18
|
+
}),
|
|
19
|
+
http.get('https://test-api/getAll', () => {
|
|
20
|
+
return HttpResponse.json({
|
|
21
|
+
data: [{ test: 'a' }, { test: 'b' }],
|
|
22
|
+
count: 2,
|
|
23
|
+
filters: ['test', 'test two']
|
|
24
|
+
})
|
|
25
|
+
}),
|
|
26
|
+
http.post('https://test-api/post', () => {
|
|
27
|
+
return HttpResponse.json({ data: { test: 'b' } })
|
|
28
|
+
}),
|
|
29
|
+
http.patch('https://test-api/patch', () => {
|
|
30
|
+
return HttpResponse.json({ data: { test: 'c' } })
|
|
31
|
+
})
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
const server = setupServer(...handlers)
|
|
35
|
+
|
|
36
|
+
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
|
|
37
|
+
|
|
38
|
+
afterAll(() => server.close())
|
|
39
|
+
|
|
40
|
+
afterEach(() => server.resetHandlers())
|
|
41
|
+
|
|
42
|
+
describe('default api', () => {
|
|
43
|
+
const api = createApi({
|
|
44
|
+
findPath: () => 'https://test-api/',
|
|
45
|
+
defaultThrowError: false
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('get', async () => {
|
|
49
|
+
const res = await api.get<any>({ additionalUrl: 'get', id: '1', nav: 'test' })
|
|
50
|
+
expect(res).not.toBeNull()
|
|
51
|
+
expect(res.data.test).toEqual('a')
|
|
52
|
+
expect(res.filters[0]).toEqual('test')
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('get fails', async () => {
|
|
56
|
+
const res = await api.get<any>({ additionalUrl: 'get', id: '2', nav: 'test' })
|
|
57
|
+
expect(res.status).toEqual(304)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('getAll', async () => {
|
|
61
|
+
const res = await api.get<any>({ additionalUrl: 'getAll', nav: 'test' })
|
|
62
|
+
expect(res).not.toBeNull()
|
|
63
|
+
expect(res.data.length).toEqual(2)
|
|
64
|
+
expect(res.count).toEqual(2)
|
|
65
|
+
expect(res.filters[0]).toEqual('test')
|
|
66
|
+
expect(res.filters[1]).toEqual('test two')
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('post', async () => {
|
|
70
|
+
const res = await api.post<any>({ additionalUrl: 'post', nav: 'test', data: { data: 'a' }})
|
|
71
|
+
expect(res).not.toBeNull()
|
|
72
|
+
expect(res).toEqual({ data: { test: 'b' } })
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
test('patch', async () => {
|
|
76
|
+
const res = await api.patch<any>({ additionalUrl: 'patch', nav: 'test', data: { data: 'a' }})
|
|
77
|
+
expect(res).not.toBeNull()
|
|
78
|
+
expect(res).toEqual({ data: { test: 'c' } })
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
// describe('default api fails', () => {
|
|
83
|
+
|
|
84
|
+
// })
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
import { withSetup } from './utils'
|
|
3
|
+
import { useLocalDb } from '../src/composables/forage'
|
|
4
|
+
|
|
5
|
+
describe('foraging', () => {
|
|
6
|
+
const [db] = withSetup(() => useLocalDb())
|
|
7
|
+
|
|
8
|
+
test('local db exists', () => {
|
|
9
|
+
expect(db).not.toBeNull()
|
|
10
|
+
expect(db._config.name).toEqual('Db_undefined')
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
// describe('local cache', () => {
|
|
16
|
+
// const [cache] = withSetup(() => useLocalCache())
|
|
17
|
+
|
|
18
|
+
// test('save', async () => {
|
|
19
|
+
// expect(cache).not.toBeNull()
|
|
20
|
+
|
|
21
|
+
// await cache.saveAsync({ test: 'a' }, 'test-key')
|
|
22
|
+
|
|
23
|
+
// const res = await cache.getAsync('test-key')
|
|
24
|
+
|
|
25
|
+
// expect(res.test).toEqual('a')
|
|
26
|
+
|
|
27
|
+
// await cache.clearAsync()
|
|
28
|
+
|
|
29
|
+
// const none = await cache.getAsync('test-key')
|
|
30
|
+
// })
|
|
31
|
+
// })
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { nestedValue, toCompareString, hasSearch, deepSelect, containsSearch, copyItemByAlphabet, copyDeep, csvContains, toggleCSV, roundTo, isArrayOfLength, isLengthyArray, addWeekday, removeWeekday, appendUrl, getAreaAround, getAreaToLeft, getAreaToRight, getLocationLine, capitalizeWords, fromCamelCase, toCamelCase, weekdayValue, weekdayShortName, containsWeekday, validEmail } from '../src/composables/helpers'
|
|
2
|
+
import { describe, expect, test } from 'vitest'
|
|
3
|
+
|
|
4
|
+
describe("helpers", () => {
|
|
5
|
+
|
|
6
|
+
test('append url', () => {
|
|
7
|
+
expect(appendUrl('https://test.com/', '/test')).toEqual('https://test.com/test')
|
|
8
|
+
expect(appendUrl('https://test.com', 'test')).toEqual('https://test.com/test')
|
|
9
|
+
expect(appendUrl('https://test.com/', 'test')).toEqual('https://test.com/test')
|
|
10
|
+
expect(appendUrl('https://test.com', '/test')).toEqual('https://test.com/test')
|
|
11
|
+
expect(appendUrl('https://test.com///', '///test')).toEqual('https://test.com/test')
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test('get area around', () => {
|
|
15
|
+
//starts with top left and goes anti-clockwise
|
|
16
|
+
expect(getAreaAround({ lat: 0, lng: 0 }, 1)).toEqual([{ lat: -1, lng: 1 },{ lat: -1, lng: -1 },{ lat: 1, lng: -1 },{ lat: 1, lng: 1 }])
|
|
17
|
+
expect(getAreaAround({ lat: 0, lng: 0 }, 2)).toEqual([{ lat: -2, lng: 2 },{ lat: -2, lng: -2 },{ lat: 2, lng: -2 },{ lat: 2, lng: 2 }])
|
|
18
|
+
expect(getAreaAround({ lat: 2, lng: 6 }, 1)).toEqual([{ lat: 1, lng: 7 },{ lat: 1, lng: 5 },{ lat: 3, lng: 5 },{ lat: 3, lng: 7 }])
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('get area to left', () => {
|
|
22
|
+
//starts with top left and goes anti-clockwise
|
|
23
|
+
expect(getAreaToLeft({ lat: 0, lng: 0 }, 1)).toEqual([{ lat: -2, lng: 1 },{ lat: -2, lng: -1 },{ lat: 0, lng: -1 },{ lat: 0, lng: 1 }])
|
|
24
|
+
expect(getAreaToLeft({ lat: 0, lng: 0 }, 2)).toEqual([{ lat: -4, lng: 2 },{ lat: -4, lng: -2 },{ lat: 0, lng: -2 },{ lat: 0, lng: 2 }])
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
test('get area to right', () => {
|
|
28
|
+
//starts with top left and goes anti-clockwise
|
|
29
|
+
expect(getAreaToRight({ lat: 0, lng: 0 }, 1)).toEqual([{ lat: 0, lng: 1 },{ lat: 0, lng: -1 },{ lat: 2, lng: -1 },{ lat: 2, lng: 1 }])
|
|
30
|
+
expect(getAreaToRight({ lat: 2, lng: 0 }, 2)).toEqual([{ lat: 2, lng: 2 },{ lat: 2, lng: -2 },{ lat: 6, lng: -2 },{ lat: 6, lng: 2 }])
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('get location line', () => {
|
|
34
|
+
expect(getLocationLine(null)).toEqual('')
|
|
35
|
+
expect(getLocationLine({ streetNumber: '9', streetName: 'Morgan St', suburb: 'Timboon', state: 'VIC', postcode: '3268' })).toEqual('9 Morgan St, Timboon VIC 3268')
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('from camel case', () => {
|
|
39
|
+
expect(fromCamelCase('testOneTwo')).toEqual('Test One Two')
|
|
40
|
+
expect(fromCamelCase('testOne Two')).toEqual('Test One Two')
|
|
41
|
+
expect(fromCamelCase('tesTOneTwo')).not.toEqual('Test One Two')
|
|
42
|
+
expect(fromCamelCase()).toBeUndefined()
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test('to camel case', () => {
|
|
46
|
+
expect(toCamelCase(undefined)).toBeUndefined()
|
|
47
|
+
expect(toCamelCase({ Test: 't' })).not.toEqual({ Test: 't' })
|
|
48
|
+
expect(toCamelCase({ Test: 't' })).toEqual({ test: 't' })
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('capitalize', () => {
|
|
52
|
+
expect(capitalizeWords('test')).toEqual('Test')
|
|
53
|
+
expect(capitalizeWords('test one')).toEqual('Test One')
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
test('weekdays csv string sort value', () => {
|
|
57
|
+
expect(weekdayValue('sun, wed, sat')).toEqual(1)
|
|
58
|
+
expect(weekdayValue('wed, sat')).toEqual(4)
|
|
59
|
+
expect(weekdayValue('')).toEqual(8)
|
|
60
|
+
expect(weekdayValue()).toEqual(0)
|
|
61
|
+
expect(weekdayValue('sun, wed, sat, always')).toEqual(0)
|
|
62
|
+
expect(weekdayValue('Tuesday')).toEqual(3)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
test('weekday short name conversion', () => {
|
|
66
|
+
expect(weekdayShortName('Sun, Mon, tuesday')).toEqual('sun,mon,tue')
|
|
67
|
+
expect(weekdayShortName('Sun, Mon, blah')).toEqual('sun,mon')
|
|
68
|
+
expect(weekdayShortName('Sun, Fri, Wedne')).toEqual('sun,fri')
|
|
69
|
+
expect(weekdayShortName('Sunday')).toEqual('sun')
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
test('contains weekday', () => {
|
|
73
|
+
expect(containsWeekday('sun', 'sun')).toEqual(true)
|
|
74
|
+
expect(containsWeekday('sun', 'Sunday')).toEqual(true)
|
|
75
|
+
expect(containsWeekday('sun,mon,tue, wed', 'Tuesday')).toEqual(true)
|
|
76
|
+
expect(containsWeekday('sun,mon,tuesday, wed', 'Tuesday')).toEqual(true)
|
|
77
|
+
expect(containsWeekday('sun,mon, wed', 'tue')).toEqual(false)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
test('add weekday', () => {
|
|
81
|
+
expect(addWeekday(undefined, 'sun')).toEqual('sun')
|
|
82
|
+
expect(addWeekday(undefined, 'sun')).toEqual('sun')
|
|
83
|
+
expect(addWeekday('mon,sun', 'sun')).toEqual('sun,mon')
|
|
84
|
+
expect(addWeekday('mon,sun, always, m', 'sun')).toEqual('always,sun,mon')
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
test('remove weekday', () => {
|
|
88
|
+
expect(removeWeekday(undefined, 'sun')).toEqual(undefined)
|
|
89
|
+
expect(removeWeekday('sun', 'sun')).toEqual(undefined)
|
|
90
|
+
expect(removeWeekday('sun, thur, tue', 'sun')).toEqual('tue,thu')
|
|
91
|
+
expect(removeWeekday('always', 'sun')).toEqual('always')
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
test('is array of length', () => {
|
|
95
|
+
expect(isArrayOfLength([], 0)).toEqual(true)
|
|
96
|
+
expect(isArrayOfLength([1,1,1], 3)).toEqual(true)
|
|
97
|
+
expect(isArrayOfLength(undefined, 0)).toEqual(false)
|
|
98
|
+
expect(isArrayOfLength({}, 0)).toEqual(false)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
test('is lengthy array', () => {
|
|
102
|
+
expect(isLengthyArray([])).toEqual(false)
|
|
103
|
+
expect(isLengthyArray(undefined)).toEqual(false)
|
|
104
|
+
expect(isLengthyArray([1])).toEqual(true)
|
|
105
|
+
expect(isLengthyArray([1,1])).toEqual(true)
|
|
106
|
+
expect(isLengthyArray([1,1], 1)).toEqual(true)
|
|
107
|
+
expect(isLengthyArray([1,1], 3)).toEqual(false)
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
test('rounding decimal places', () => {
|
|
111
|
+
expect(roundTo(1, 0)).toEqual(1)
|
|
112
|
+
expect(roundTo(1.1, 0)).toEqual(1)
|
|
113
|
+
expect(roundTo(1.6, 0)).toEqual(2)
|
|
114
|
+
expect(roundTo(2.22567, 3)).toEqual(2.226)
|
|
115
|
+
expect(roundTo(2.22547, 3)).toEqual(2.225)
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
test('toggle csv', () => {
|
|
119
|
+
expect(toggleCSV('one,two,three', 'two')).toEqual('one,three')
|
|
120
|
+
expect(toggleCSV('two', 'two')).toEqual(null)
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
test('csv contains', () => {
|
|
124
|
+
expect(csvContains('one,two,three', 'two')).toEqual(true)
|
|
125
|
+
expect(csvContains('one,two,three', 'three')).toEqual(true)
|
|
126
|
+
expect(csvContains('one,three', 'two')).toEqual(false)
|
|
127
|
+
expect(csvContains(undefined, 'two')).toEqual(false)
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
test('copy deep', () => {
|
|
131
|
+
expect(copyDeep(null)).toStrictEqual(null)
|
|
132
|
+
expect(copyDeep(undefined)).toStrictEqual(undefined)
|
|
133
|
+
|
|
134
|
+
let item = { test: { one: 'treat' } }
|
|
135
|
+
let copy = copyDeep(item)
|
|
136
|
+
item.test.one = 'other'
|
|
137
|
+
|
|
138
|
+
expect(item.test).not.toEqual(copy.test)
|
|
139
|
+
expect(item).not.toEqual(copy)
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
test('copy by property alphabet', () => {
|
|
143
|
+
expect(copyItemByAlphabet(null)).toStrictEqual(null)
|
|
144
|
+
expect(copyItemByAlphabet(undefined)).toStrictEqual(undefined)
|
|
145
|
+
|
|
146
|
+
let item = { test: { b: 'treat', a: 't' }, v: 'a', s: 'a', z: undefined }
|
|
147
|
+
//consistency
|
|
148
|
+
expect(JSON.stringify(copyItemByAlphabet(item))).toEqual(JSON.stringify(copyItemByAlphabet(item)))
|
|
149
|
+
expect(JSON.stringify(copyItemByAlphabet(item))).toEqual(JSON.stringify({ s: 'a', test: { a: 't', b: 'treat' }, v: 'a', z: undefined }))
|
|
150
|
+
expect(JSON.stringify(copyItemByAlphabet(item))).not.toEqual(JSON.stringify({ s: 'a', test: { b: 'treat', a: 't' }, v: 'a' }))
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
test('contains search', () => {
|
|
154
|
+
expect(containsSearch(undefined, undefined)).toEqual(true)
|
|
155
|
+
expect(containsSearch('a', undefined)).toEqual(true)
|
|
156
|
+
expect(containsSearch('aa', 'aa')).toEqual(true)
|
|
157
|
+
expect(containsSearch('aa', 'a')).toEqual(true)
|
|
158
|
+
expect(containsSearch('aa', 'b')).toEqual(false)
|
|
159
|
+
expect(containsSearch('Testing One Two Three', ' one')).toEqual(true)
|
|
160
|
+
expect(containsSearch('Testing One Two Three', ' one')).toEqual(false)
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
test('deep select', () => {
|
|
164
|
+
expect(deepSelect(null)).toEqual([])
|
|
165
|
+
|
|
166
|
+
let item = [
|
|
167
|
+
{ a: 'a', b: [{ a: 'd' }] },
|
|
168
|
+
{ a: 'b'},
|
|
169
|
+
{ a: 'c' }
|
|
170
|
+
]
|
|
171
|
+
|
|
172
|
+
expect(deepSelect(item, x => x.b).length).toEqual(4)
|
|
173
|
+
|
|
174
|
+
let ite = [{
|
|
175
|
+
b: [
|
|
176
|
+
{ a: 'a', b: [{ a: 'b', b: [{ a: 'c' }] }]},
|
|
177
|
+
{ a: 'd' },
|
|
178
|
+
{ a: 'e', b: [{ a: 'f' }]}
|
|
179
|
+
]
|
|
180
|
+
}]
|
|
181
|
+
|
|
182
|
+
expect(deepSelect(ite, x => x.b).length).toEqual(7)
|
|
183
|
+
|
|
184
|
+
let te = {
|
|
185
|
+
b: [
|
|
186
|
+
{ a: 'a', b: [{ a: 'b', b: [{ a: 'c' }] }]},
|
|
187
|
+
{ a: 'd' },
|
|
188
|
+
{ a: 'e', b: [{ a: 'f' }]}
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
//misses the parent
|
|
193
|
+
expect(deepSelect(te, x => x.b).length).toEqual(6)
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
test('has search', () => {
|
|
197
|
+
expect(hasSearch(undefined, 'test', ['a', 'b'])).toEqual(false)
|
|
198
|
+
expect(hasSearch('test', undefined, ['a', 'b'])).toEqual(true)
|
|
199
|
+
expect(hasSearch({ test: 'one two three', a: 'one' }, 'four', ['test', 'a'])).toEqual(false)
|
|
200
|
+
expect(hasSearch({ test: 'two', a: 'one' }, 'one', undefined)).toEqual(false)
|
|
201
|
+
expect(hasSearch({ test: 'one two three', a: 'one', b: 'two' }, 'three', ['a', 'b'])).toEqual(false)
|
|
202
|
+
expect(hasSearch({ test: 'one two three', a: 'one', b: 'two' }, 'three', ['a', 'b', 'test'])).toEqual(true)
|
|
203
|
+
expect(hasSearch({ test: 'one two three', a: 'one', b: 'two' }, 'one', ['b'])).toEqual(false)
|
|
204
|
+
expect(hasSearch({ test: 'one two three', a: 'one', b: 'two' }, 'one', ['a', 'b'])).toEqual(true)
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
test('to compare string', () => {
|
|
208
|
+
expect(toCompareString('one')).toEqual('one')
|
|
209
|
+
expect(toCompareString(undefined)).toStrictEqual(null)
|
|
210
|
+
expect(toCompareString('one two three')).toEqual('onetwothree')
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
test('nested value', () => {
|
|
214
|
+
let item = {
|
|
215
|
+
a: { b: 'b', c: { d: 'd' } },
|
|
216
|
+
b: 'str'
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
expect(nestedValue(item, 'b')).toEqual('str')
|
|
220
|
+
expect(nestedValue(item, 'a.c.d')).toEqual('d')
|
|
221
|
+
expect(nestedValue(item, 'a.b')).toEqual('b')
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
test('valid email', () => {
|
|
225
|
+
expect(validEmail('andrewderoon@gmail.com')).toEqual(true)
|
|
226
|
+
expect(validEmail('@gmail.com')).toEqual(false)
|
|
227
|
+
expect(validEmail('a@')).toEqual(false)
|
|
228
|
+
expect(validEmail('a@e')).toEqual(true)
|
|
229
|
+
expect(validEmail('andrewderoon.com')).toEqual(false)
|
|
230
|
+
})
|
|
231
|
+
})
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { createNavigation } from '../src/composables/navigation'
|
|
2
|
+
import { describe, expect, test } from 'vitest'
|
|
3
|
+
|
|
4
|
+
describe("navigation", () => {
|
|
5
|
+
const nav = createNavigation({
|
|
6
|
+
defaultCacheExpiryHours: 3,
|
|
7
|
+
navItems: [
|
|
8
|
+
{
|
|
9
|
+
name: 'test-nav'
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
name: 'navA',
|
|
13
|
+
background: 'b',
|
|
14
|
+
displayName: 'discs',
|
|
15
|
+
hideAppBar: true,
|
|
16
|
+
hideNavigation: true,
|
|
17
|
+
hesitate: true,
|
|
18
|
+
icon: 'mdi-plus',
|
|
19
|
+
path: '/testing/one',
|
|
20
|
+
children: [
|
|
21
|
+
{
|
|
22
|
+
name: 'navB',
|
|
23
|
+
cacheExpiryHours: 4,
|
|
24
|
+
children: [
|
|
25
|
+
{
|
|
26
|
+
archiveName: 'nav-archive',
|
|
27
|
+
aliases: ['nav-alias', 'nav-alia'],
|
|
28
|
+
name: 'navC',
|
|
29
|
+
path: '/test/alias'
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
singleName: 'navone'
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('find archive name', () => {
|
|
40
|
+
expect(nav.findArchiveName('navC')).toEqual('nav-archive')
|
|
41
|
+
expect(nav.findArchiveName('navB')).toEqual(undefined)
|
|
42
|
+
expect(nav.findArchiveName('navD')).toEqual(undefined)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test('find cache length', () => {
|
|
46
|
+
expect(nav.findCacheHours('navC')).toEqual(3)
|
|
47
|
+
expect(nav.findCacheHours('navB')).toEqual(4)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('find display', () => {
|
|
51
|
+
expect(nav.findDisplay('test-nav')).toEqual(undefined)
|
|
52
|
+
expect(nav.findDisplay('navA')).toEqual('discs')
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('find icon', () => {
|
|
56
|
+
expect(nav.findIcon('test-nav')).toEqual(undefined)
|
|
57
|
+
expect(nav.findIcon('navA')).toEqual('mdi-plus')
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('find item', () => {
|
|
61
|
+
expect(nav.findItem('test-nav')).not.toBeNull()
|
|
62
|
+
expect(nav.findItem('test-navs')).toBeNull()
|
|
63
|
+
expect(nav.findItem('test-nav')?.name).toEqual('test-nav')
|
|
64
|
+
expect(nav.findItem('nav-alias')?.name).toEqual('navC')
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test('find store name', () => {
|
|
68
|
+
expect(nav.findStoreName('navA')).toEqual('navA')
|
|
69
|
+
expect(nav.findStoreName('navB')).toEqual('navB')
|
|
70
|
+
expect(nav.findStoreName('test-nav')).toEqual('test-nav')
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('find path', () => {
|
|
74
|
+
expect(nav.findPath('test-nav')).toEqual('')
|
|
75
|
+
expect(nav.findPath('navA')).toEqual('/testing/one')
|
|
76
|
+
expect(nav.findPath('nav-alias')).toEqual('/test/alias')
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
test('find single display', () => {
|
|
80
|
+
expect(nav.findSingleDisplay('navA')).toEqual('disc')
|
|
81
|
+
expect(nav.findSingleDisplay('navB')).toEqual('navone')
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
test('update nav props', () => {
|
|
85
|
+
nav.updateNavigationProperties('test-nav')
|
|
86
|
+
|
|
87
|
+
expect(nav.showAppBar.value).toEqual(true)
|
|
88
|
+
expect(nav.showAppNavigation.value).toEqual(true)
|
|
89
|
+
expect(nav.backgroundName.value).toEqual(undefined)
|
|
90
|
+
expect(nav.hesitate.value).toEqual(false)
|
|
91
|
+
|
|
92
|
+
nav.updateNavigationProperties('navA')
|
|
93
|
+
|
|
94
|
+
expect(nav.showAppBar.value).toEqual(false)
|
|
95
|
+
expect(nav.showAppNavigation.value).toEqual(false)
|
|
96
|
+
expect(nav.backgroundName.value).toEqual('b')
|
|
97
|
+
expect(nav.hesitate.value).toEqual(true)
|
|
98
|
+
})
|
|
99
|
+
})
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { setActivePinia, createPinia } from 'pinia'
|
|
2
|
+
import { createSessionStore, createWholeLastUpdateStore } from '../src/composables/stores'
|
|
3
|
+
import { createApi } from '../src/composables/api'
|
|
4
|
+
import { describe, test, expect, beforeEach, afterAll, afterEach, beforeAll } from 'vitest'
|
|
5
|
+
import { setupServer } from 'msw/node'
|
|
6
|
+
import { http, HttpResponse } from 'msw'
|
|
7
|
+
import { createApp } from 'vue'
|
|
8
|
+
import { withSetup } from './utils'
|
|
9
|
+
|
|
10
|
+
const handlers = [
|
|
11
|
+
http.get('https://api/get/1', () => {
|
|
12
|
+
return HttpResponse.json({
|
|
13
|
+
data: { test: 'g' }
|
|
14
|
+
})
|
|
15
|
+
}),
|
|
16
|
+
http.get('https://api/getAll', () => {
|
|
17
|
+
return HttpResponse.json({
|
|
18
|
+
data: [{ test: 'a', id: '1' }, { test: 'b', id: '2' }],
|
|
19
|
+
count: 2,
|
|
20
|
+
filters: ['test', 'test two']
|
|
21
|
+
})
|
|
22
|
+
}),
|
|
23
|
+
http.post('https://api/post', () => {
|
|
24
|
+
return HttpResponse.json({ data: { test: 'd', id: '11' } })
|
|
25
|
+
}),
|
|
26
|
+
http.patch('https://api/patch', () => {
|
|
27
|
+
return HttpResponse.json({ data: { test: 'e', rowVersion: 2 } })
|
|
28
|
+
})
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
const server = setupServer(...handlers)
|
|
32
|
+
|
|
33
|
+
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
|
|
34
|
+
|
|
35
|
+
afterAll(() => server.close())
|
|
36
|
+
|
|
37
|
+
afterEach(() => {
|
|
38
|
+
server.resetHandlers()
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
describe('use last update store no api no caching', () => {
|
|
42
|
+
const [api, app] = withSetup(() => createApi({
|
|
43
|
+
findPath: () => 'https://api/',
|
|
44
|
+
defaultThrowError: false
|
|
45
|
+
}))
|
|
46
|
+
|
|
47
|
+
const pinia = createPinia()
|
|
48
|
+
app.use(pinia)
|
|
49
|
+
|
|
50
|
+
setActivePinia(pinia)
|
|
51
|
+
|
|
52
|
+
const store = createWholeLastUpdateStore({
|
|
53
|
+
api: null,
|
|
54
|
+
storageMode: 'session',
|
|
55
|
+
storeName: 'whole'
|
|
56
|
+
})()
|
|
57
|
+
|
|
58
|
+
test('all session activity', async () => {
|
|
59
|
+
|
|
60
|
+
await store.post<any>({ data: { id: '1', test: 'a' }})
|
|
61
|
+
await store.post<any>({ data: { id: '2', test: 'b' }})
|
|
62
|
+
await store.post<any>({ data: { id: '3', test: 'c' }})
|
|
63
|
+
|
|
64
|
+
let postRes = await store.get<any>({ id: '1' })
|
|
65
|
+
expect(postRes.data).toEqual({ id: '1', test: 'a' })
|
|
66
|
+
|
|
67
|
+
await store.patch<any>({ data: { id: '1', test: 'd' }})
|
|
68
|
+
postRes = await store.get<any>({ id: '1' })
|
|
69
|
+
expect(postRes.data).toEqual({ id: '1', test: 'd' })
|
|
70
|
+
|
|
71
|
+
let getAll = await store.getAll<any>({})
|
|
72
|
+
expect(getAll.data.length).toEqual(3)
|
|
73
|
+
expect(getAll.count).toEqual(3)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
await store.deleteItem({ data: { id: '1' }})
|
|
77
|
+
postRes = await store.get<any>({ id: '1' })
|
|
78
|
+
expect(postRes.data).toEqual(undefined)
|
|
79
|
+
|
|
80
|
+
getAll = await store.getAll<any>({})
|
|
81
|
+
expect(getAll.data.length).toEqual(2)
|
|
82
|
+
expect(getAll.count).toEqual(2)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
describe('use last update store with api no caching', () => {
|
|
89
|
+
const [api, app] = withSetup(() => createApi({
|
|
90
|
+
findPath: () => 'https://api/',
|
|
91
|
+
defaultThrowError: false
|
|
92
|
+
}))
|
|
93
|
+
|
|
94
|
+
const pinia = createPinia()
|
|
95
|
+
app.use(pinia)
|
|
96
|
+
setActivePinia(pinia)
|
|
97
|
+
|
|
98
|
+
const store = createWholeLastUpdateStore({
|
|
99
|
+
storageMode: 'session',
|
|
100
|
+
api: api,
|
|
101
|
+
storeName: 'whole-api'
|
|
102
|
+
})()
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
test('get', async () => {
|
|
106
|
+
const res = await store.get<any>({ id: '1' })
|
|
107
|
+
expect(res.data).toEqual({ test: 'a', id: '1' })
|
|
108
|
+
let getAll = await store.getAll<any>({})
|
|
109
|
+
expect(getAll.data.length).toEqual(2)
|
|
110
|
+
expect(getAll.count).toEqual(2)
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
test('get all', async () => {
|
|
115
|
+
const res = await store.getAll<any>({})
|
|
116
|
+
expect(res).toEqual({
|
|
117
|
+
data: [{test: 'a', id: '1' },{test: 'b', id: '2' }],
|
|
118
|
+
count: 2,
|
|
119
|
+
filters: []
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
test('post', async () => {
|
|
124
|
+
const res = await store.post<any>({ data: { test: 'a', id: '11' }})
|
|
125
|
+
expect(res).not.toBeNull()
|
|
126
|
+
|
|
127
|
+
//gets api post return
|
|
128
|
+
let getRes = await store.get<any>({ id: '11' })
|
|
129
|
+
expect(getRes.data).toEqual({ test: 'd', id: '11' })
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
test('patch', async () => {
|
|
133
|
+
const res = await store.patch<any>({ data: { test: 'a', id: '1', rowVersion: 1 }})
|
|
134
|
+
let getRes = await store.get<any>({ id: '1' })
|
|
135
|
+
expect(getRes.data.rowVersion).toEqual(2)
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
})
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { setActivePinia, createPinia } from 'pinia'
|
|
2
|
+
import { createSessionStore, createWholeLastUpdateStore } from '../src/composables/stores'
|
|
3
|
+
import { createApi } from '../src/composables/api'
|
|
4
|
+
import { describe, test, expect, beforeEach, afterAll, afterEach, beforeAll } from 'vitest'
|
|
5
|
+
import { setupServer } from 'msw/node'
|
|
6
|
+
import { http, HttpResponse } from 'msw'
|
|
7
|
+
import { createApp } from 'vue'
|
|
8
|
+
import { withSetup } from './utils'
|
|
9
|
+
|
|
10
|
+
const handlers = [
|
|
11
|
+
http.get('https://test-api/get/1', () => {
|
|
12
|
+
return HttpResponse.json({
|
|
13
|
+
data: { test: 'a' }
|
|
14
|
+
})
|
|
15
|
+
}),
|
|
16
|
+
http.get('https://test-api/get/2', () => {
|
|
17
|
+
return new HttpResponse('not found', {
|
|
18
|
+
status: 304
|
|
19
|
+
})
|
|
20
|
+
}),
|
|
21
|
+
http.get('https://test-api/getAll', () => {
|
|
22
|
+
return HttpResponse.json({
|
|
23
|
+
data: [{ test: 'a' }, { test: 'b' }],
|
|
24
|
+
count: 2,
|
|
25
|
+
filters: ['test', 'test two']
|
|
26
|
+
})
|
|
27
|
+
}),
|
|
28
|
+
http.post('https://test-api/post', () => {
|
|
29
|
+
return HttpResponse.json({ data: { test: 'b' } })
|
|
30
|
+
}),
|
|
31
|
+
http.patch('https://test-api/patch', () => {
|
|
32
|
+
return HttpResponse.json({ data: { test: 'c', rowVersion: 2 } })
|
|
33
|
+
})
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
const server = setupServer(...handlers)
|
|
37
|
+
|
|
38
|
+
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
|
|
39
|
+
|
|
40
|
+
afterAll(() => server.close())
|
|
41
|
+
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
server.resetHandlers()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
describe('use session store with no api no caching', () => {
|
|
47
|
+
const [api, app] = withSetup(() => createApi())
|
|
48
|
+
|
|
49
|
+
const pinia = createPinia()
|
|
50
|
+
app.use(pinia)
|
|
51
|
+
setActivePinia(pinia)
|
|
52
|
+
|
|
53
|
+
const store = createSessionStore({
|
|
54
|
+
storageMode: 'session',
|
|
55
|
+
storeName: 'sesh'
|
|
56
|
+
})()
|
|
57
|
+
|
|
58
|
+
test('all session activity', async () => {
|
|
59
|
+
await store.post<any>({ data: { id: '1', test: 'a' }})
|
|
60
|
+
let postRes = await store.get<any>({ id: '1' })
|
|
61
|
+
expect(postRes.data).toEqual({ id: '1', test: 'a' })
|
|
62
|
+
await store.patch<any>({ nav: 'test', data: { id: '1', test: 'b' }})
|
|
63
|
+
postRes = await store.get<any>({ id: '1' })
|
|
64
|
+
expect(postRes.data).toEqual({ id: '1', test: 'b' })
|
|
65
|
+
await store.deleteItem({ id: '1' })
|
|
66
|
+
postRes = await store.get<any>({ id: '1' })
|
|
67
|
+
expect(postRes).toEqual(undefined)
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
describe('use session store with api no caching', () => {
|
|
72
|
+
const [api, app] = withSetup(() => createApi({
|
|
73
|
+
findPath: () => 'https://test-api/',
|
|
74
|
+
defaultThrowError: false
|
|
75
|
+
}))
|
|
76
|
+
|
|
77
|
+
const pinia = createPinia()
|
|
78
|
+
app.use(pinia)
|
|
79
|
+
|
|
80
|
+
setActivePinia(pinia)
|
|
81
|
+
|
|
82
|
+
const store = createSessionStore({
|
|
83
|
+
storageMode: 'session',
|
|
84
|
+
api: api,
|
|
85
|
+
storeName: 'test'
|
|
86
|
+
})()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
test('get', async () => {
|
|
90
|
+
const res = await store.get<any>({ nav: 'test', id: '1' })
|
|
91
|
+
expect(res).toEqual({ data: { test: 'a' }})
|
|
92
|
+
//expect(store.searchMemory['test_no-user-id_1']).toEqual({ data: { test: 'a' }})
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
test('get all', async () => {
|
|
96
|
+
const res = await store.getAll<any>({ nav: 'test' })
|
|
97
|
+
expect(res).toEqual({
|
|
98
|
+
data: [{test: 'a' },{test: 'b'}],
|
|
99
|
+
count: 2,
|
|
100
|
+
filters: ['test', 'test two']
|
|
101
|
+
})
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
test('post', async () => {
|
|
105
|
+
const res = await store.post<any>({ nav: 'test', data: { test: 'a', id: '11' }})
|
|
106
|
+
expect(res).not.toBeNull()
|
|
107
|
+
//gets api post return
|
|
108
|
+
let getRes = await store.get<any>({ nav: 'test', id: '11' })
|
|
109
|
+
expect(getRes.data).toEqual({ test: 'b' })
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
test('patch', async () => {
|
|
113
|
+
const res = await store.patch<any>({ nav: 'test', data: { test: 'a', id: '1', rowVersion: 1 }})
|
|
114
|
+
let getRes = await store.get<any>({ nav: 'test', id: '1' })
|
|
115
|
+
expect(getRes.data.rowVersion).toEqual(2)
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
})
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest"
|
|
2
|
+
import { withSetup } from './utils'
|
|
3
|
+
import { useTracker } from '../src/composables/track'
|
|
4
|
+
import { twiddleThumbs } from "../src/composables/helpers"
|
|
5
|
+
|
|
6
|
+
describe("track", () => {
|
|
7
|
+
test('tracker test', async () => {
|
|
8
|
+
|
|
9
|
+
const item = { test: 'a' }
|
|
10
|
+
const [{ asyncItem, isChanged, restartTracker }] = withSetup(() => useTracker(item))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
expect(isChanged.value).toEqual(false)
|
|
14
|
+
asyncItem.value.test = 'b'
|
|
15
|
+
await twiddleThumbs(500)
|
|
16
|
+
expect(isChanged.value).toEqual(true)
|
|
17
|
+
asyncItem.value.test = 'a'
|
|
18
|
+
await twiddleThumbs(500)
|
|
19
|
+
expect(isChanged.value).toEqual(false)
|
|
20
|
+
asyncItem.value.test = 'b'
|
|
21
|
+
await twiddleThumbs(500)
|
|
22
|
+
expect(isChanged.value).toEqual(true)
|
|
23
|
+
restartTracker()
|
|
24
|
+
await twiddleThumbs(500)
|
|
25
|
+
expect(isChanged.value).toEqual(false)
|
|
26
|
+
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
})
|
package/test/utils.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createApp } from 'vue'
|
|
2
|
+
|
|
3
|
+
export function withSetup(composable) {
|
|
4
|
+
let result
|
|
5
|
+
const app = createApp({
|
|
6
|
+
setup() {
|
|
7
|
+
result = composable()
|
|
8
|
+
return () => {}
|
|
9
|
+
}
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
app.mount(document.createElement('div'))
|
|
13
|
+
|
|
14
|
+
return [result, app]
|
|
15
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"baseUrl": ".",
|
|
4
|
+
"target": "ES2020",
|
|
5
|
+
"useDefineForClassFields": true,
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"lib": ["ES2020", "ES2021.String", "DOM", "DOM.Iterable"],
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
|
|
10
|
+
/* Bundler mode */
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"allowImportingTsExtensions": true,
|
|
13
|
+
"resolveJsonModule": true,
|
|
14
|
+
"isolatedModules": true,
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
"jsx": "preserve",
|
|
17
|
+
|
|
18
|
+
/* Linting */
|
|
19
|
+
"strict": true,
|
|
20
|
+
"noUnusedLocals": true,
|
|
21
|
+
"noUnusedParameters": true,
|
|
22
|
+
"noFallthroughCasesInSwitch": true,
|
|
23
|
+
"paths": {
|
|
24
|
+
"@/*": [
|
|
25
|
+
"src/*"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"types": ["vitest/globals"]
|
|
29
|
+
},
|
|
30
|
+
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
|
|
31
|
+
"references": [{ "path": "./tsconfig.node.json" }],
|
|
32
|
+
"exclude": ["node_modules"]
|
|
33
|
+
}
|
package/index.html
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<title>Vite + Vue + TS</title>
|
|
8
|
-
</head>
|
|
9
|
-
<body>
|
|
10
|
-
<div id="app"></div>
|
|
11
|
-
<script type="module" src="/src/main.ts"></script>
|
|
12
|
-
</body>
|
|
13
|
-
</html>
|
package/public/vite.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|