Skip to content

Commit 4cc3b51

Browse files
committed
test: 💄 coverage test
1 parent 7f136cf commit 4cc3b51

File tree

3 files changed

+84
-55
lines changed

3 files changed

+84
-55
lines changed

src/__tests__/base-proxy.test.ts

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,19 @@ import Axios from 'axios'
22
import BaseProxy from '../core/BaseProxy'
33
import MockAdapter from 'axios-mock-adapter'
44
import PostProxy from '../core/PostPorxy'
5+
import type { ValidatorType } from '../core/Validator'
6+
import Validator from '../core/Validator'
57
import BaseTransformer from '../core/BaseTransformer'
68
import PaginationTransformer from '../core/PaginationTransformer'
79
import { merge } from '../util/objects'
810

911
let proxy: PostProxy
1012
let mockAdapter: MockAdapter
13+
let validator: ValidatorType
1114

1215
describe('BaseProxy', () => {
1316
beforeEach(() => {
17+
validator = Validator
1418
const axios = Axios.create({ baseURL: 'https://mock-api.test' })
1519
BaseProxy.$http = axios
1620
proxy = new PostProxy()
@@ -21,7 +25,7 @@ describe('BaseProxy', () => {
2125
it('check if http was installed', async () => {
2226
BaseProxy.$http = undefined
2327
try {
24-
await proxy.all()
28+
await proxy.getMany()
2529
} catch (e) {
2630
expect(e.message).toBe('Vue Api Queries, No http library provided.')
2731
}
@@ -178,7 +182,7 @@ describe('BaseProxy', () => {
178182
it('it should find an item by id', async () => {
179183
const item = { first_name: 'Chantouch', last_name: 'Sek', id: 1 }
180184
mockAdapter.onGet('posts/1').reply(200, { data: item })
181-
const { data } = await proxy.find(1)
185+
const { data } = await proxy.getOne(1)
182186
expect(data).toEqual(item)
183187
})
184188

@@ -198,7 +202,7 @@ describe('BaseProxy', () => {
198202
baz: new Date(Date.UTC(2012, 3, 13, 2, 12)),
199203
}
200204
form.field2 = file
201-
form.files = [{ file }]
205+
form.files = [file]
202206

203207
mockAdapter.onPost('/posts').reply((request) => {
204208
expect(request.data).toBeInstanceOf(FormData)
@@ -207,20 +211,20 @@ describe('BaseProxy', () => {
207211
expect(request.data.get('field1[bar][1]')).toBe('testBar2')
208212
expect(request.data.get('field1[baz]')).toBe('2012-04-13T02:12:00.000Z')
209213
expect(request.data.get('field2')).toEqual(file)
210-
expect(request.data.get('files[0][file]')).toEqual(file)
214+
expect(request.data.get('files[0]')).toEqual(file)
211215

212216
expect(getFormDataKeys(request.data)).toEqual([
213217
'field1[foo]',
214218
'field1[bar][0]',
215219
'field1[bar][1]',
216220
'field1[baz]',
217221
'field2',
218-
'files[0][file]',
222+
'files[0]',
219223
])
220224
return [200, {}]
221225
})
222226

223-
await proxy.post(form)
227+
await proxy.create(form)
224228
})
225229

226230
it('transforms the data to a FormData object if there is a File with post', async () => {
@@ -257,44 +261,47 @@ describe('BaseProxy', () => {
257261

258262
it('transforms the boolean values in FormData object to "1" or "0"', async () => {
259263
const file = new File(['hello world!'], 'myfile')
260-
const form: any = { field1: {}, field2: null }
264+
const form: any = { field1: {}, field2: null, files: null }
261265
form.field1 = {
262266
foo: true,
263267
bar: false,
264268
}
265269
form.field2 = file
270+
form.files = [file]
271+
form.__proto__ = file
266272

267273
mockAdapter.onPost('/posts').reply((request) => {
268274
expect(request.data).toBeInstanceOf(FormData)
269275
expect(request.data.get('field1[foo]')).toBe('1')
270276
expect(request.data.get('field1[bar]')).toBe('0')
271277
expect(request.data.get('field2')).toEqual(file)
278+
expect(request.data.get('files[0]')).toEqual(file)
279+
expect(request.data.get('__proto__')).toEqual(null)
272280

273281
expect(getFormDataKeys(request.data)).toEqual([
274282
'field1[foo]',
275283
'field1[bar]',
276284
'field2',
285+
'files[0]',
277286
])
278287
return [200, {}]
279288
})
280289

281290
await proxy.post(form)
282291
})
283292

284-
/*
285293
it('it should throw errors message when data is not valid', async () => {
286294
const item = { first_name: null, last_name: 'Sek', id: 1 }
287-
mockAdapter.onPost('/posts').reply(422, {
295+
mockAdapter.onPost('/posts').replyOnce(422, {
288296
errors: { first_name: ['The first name field is required'] },
289297
})
290298
try {
291299
await proxy.post(item)
292300
} catch (e) {
293-
console.log('post:', e)
301+
expect(e.message).toBe('Request failed with status code 422')
294302
}
295303
expect(validator.has('first_name')).toBeTruthy()
296304
})
297-
*/
298305

299306
it('it should store the item', async () => {
300307
const item = { first_name: 'Chantouch', last_name: 'Sek', id: 1 }
@@ -306,7 +313,7 @@ describe('BaseProxy', () => {
306313
it('it should be able to put item', async () => {
307314
const item = { first_name: 'Chantouch', last_name: 'Sek', id: 1 }
308315
mockAdapter.onPut('posts/1').reply(200, { data: item })
309-
const { data } = await proxy.put(item.id, item)
316+
const { data } = await proxy.replace(item.id, item)
310317
expect(data).toEqual(item)
311318
})
312319

@@ -317,13 +324,27 @@ describe('BaseProxy', () => {
317324
expect(data).toEqual(item)
318325
})
319326

320-
it('it should be able to patch item', async () => {
327+
it('it should be able to update an item', async () => {
328+
const item = { first_name: 'Chantouch', last_name: 'Sek', id: 1 }
329+
mockAdapter.onPatch('posts/1').reply(200, { data: item })
330+
const { data } = await proxy.update(item.id, item)
331+
expect(data).toEqual(item)
332+
})
333+
334+
it('it should be able to delete an item', async () => {
321335
const item = { first_name: 'Chantouch', last_name: 'Sek', id: 1 }
322336
mockAdapter.onDelete('posts/1').reply(200, { data: item })
323337
const { data } = await proxy.delete(item.id)
324338
expect(data).toEqual(item)
325339
})
326340

341+
it('it should be able to remove an item', async () => {
342+
const item = { first_name: 'Chantouch', last_name: 'Sek', id: 1 }
343+
mockAdapter.onDelete('posts/1').reply(200, { data: item })
344+
const { data } = await proxy.remove(item.id)
345+
expect(data).toEqual(item)
346+
})
347+
327348
it('can accept a custom http instance in options', () => {
328349
BaseProxy.$http = Axios.create({ baseURL: 'https://another-example.com' })
329350
expect(proxy.$http.defaults.baseURL).toBe('https://another-example.com')

src/core/BaseProxy.ts

Lines changed: 3 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ import {
55
Method,
66
AxiosRequestConfig,
77
} from 'axios'
8-
import { isArray, isFile } from '../util/objects'
98
import type { Errors } from '..'
109
import Validator from './Validator'
11-
import { objectToFormData } from '../util/formData'
10+
import { hasFiles, objectToFormData } from '../util/formData'
1211
import qs, { ParsedQs } from 'qs'
1312
import { removeDoubleSlash } from '../util/string'
1413

@@ -66,7 +65,7 @@ class BaseProxy {
6665
* Alternative of find method
6766
* @param {string | number} id
6867
*/
69-
getOne<T>(id: string | number) {
68+
getOne<T>(id: number | string) {
7069
return this.find<T>(id)
7170
}
7271

@@ -180,7 +179,7 @@ class BaseProxy {
180179
const method = BaseProxy.__validateRequestType(requestType)
181180
this.beforeSubmit()
182181
return new Promise((resolve, reject) => {
183-
const data = this.__hasFiles(form) ? objectToFormData(form) : form
182+
const data = hasFiles(form) ? objectToFormData(form) : form
184183
const url = parameter
185184
? `/${this.endpoint}/${parameter}`
186185
: `/${this.endpoint}`
@@ -239,44 +238,6 @@ class BaseProxy {
239238
return requestType.toLowerCase()
240239
}
241240

242-
private __hasFiles(form: any): boolean {
243-
for (const property in form) {
244-
if (!form.hasOwnProperty(property)) {
245-
return false
246-
}
247-
if (typeof window === 'undefined') {
248-
return false
249-
}
250-
if (this.__hasFilesDeep(form[property])) {
251-
return true
252-
}
253-
}
254-
return false
255-
}
256-
257-
private __hasFilesDeep(object: any): boolean {
258-
if (object === null) {
259-
return false
260-
}
261-
if (typeof object === 'object') {
262-
for (const key in object) {
263-
if (object.hasOwnProperty(key)) {
264-
if (isFile(object[key])) {
265-
return true
266-
}
267-
}
268-
}
269-
}
270-
if (isArray(object)) {
271-
for (const key in object) {
272-
if (object.hasOwnProperty(key)) {
273-
return this.__hasFilesDeep(object[key])
274-
}
275-
}
276-
}
277-
return isFile(object)
278-
}
279-
280241
/**
281242
* Set parameters by keys
282243
* @param {Object} parameters

src/util/formData.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { isArray, isFile } from './objects'
2+
13
export function objectToFormData(
24
object: any,
35
formData = new FormData(),
@@ -40,5 +42,50 @@ function appendToFormData(formData: FormData, key: string, value: any) {
4042
return formData.append(key, value)
4143
}
4244

45+
if (isArray(value) && hasFilesDeep(value)) {
46+
for (let i = 0; i < value.length; i++) {
47+
formData.append(key + '[' + i + ']', value[i])
48+
}
49+
return formData
50+
}
51+
4352
objectToFormData(value, formData, key)
4453
}
54+
55+
export function hasFilesDeep(object: any): boolean {
56+
if (object === null) {
57+
return false
58+
}
59+
if (typeof object === 'object') {
60+
for (const key in object) {
61+
if (object.hasOwnProperty(key)) {
62+
if (isFile(object[key])) {
63+
return true
64+
}
65+
}
66+
}
67+
}
68+
if (isArray(object)) {
69+
for (const key in object) {
70+
if (object.hasOwnProperty(key)) {
71+
return hasFilesDeep(object[key])
72+
}
73+
}
74+
}
75+
return isFile(object)
76+
}
77+
78+
export function hasFiles(form: any): boolean {
79+
for (const property in form) {
80+
if (!form.hasOwnProperty(property)) {
81+
return false
82+
}
83+
if (typeof window === 'undefined') {
84+
return false
85+
}
86+
if (hasFilesDeep(form[property])) {
87+
return true
88+
}
89+
}
90+
return false
91+
}

0 commit comments

Comments
 (0)