Skip to content

Commit f71275a

Browse files
egor-romanovlaktek
authored andcommitted
feat: add blob arrayBuf and queryString tests
1 parent b027cb7 commit f71275a

File tree

3 files changed

+192
-5
lines changed

3 files changed

+192
-5
lines changed

test/functions/mirror/index.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,35 @@ import { serve } from 'https://deno.land/std/http/server.ts'
22

33
serve(async (request: Request) => {
44
let body
5-
switch (request.headers.get('content-type')) {
6-
case 'application/json': {
5+
let contentType = 'application/json'
6+
switch (request.headers.get('response-type')) {
7+
case 'json': {
78
body = await request.json()
89
break
910
}
10-
case 'application/x-www-form-urlencoded': {
11+
case 'form': {
1112
const formBody = await request.formData()
1213
body = []
1314
for (const e of formBody.entries()) {
1415
body.push(e)
1516
}
1617
break
1718
}
19+
case 'blob': {
20+
const data = await request.blob()
21+
body = await data.text()
22+
contentType = 'application/octet-stream'
23+
break
24+
}
25+
case 'arrayBuffer': {
26+
const data = await request.arrayBuffer()
27+
body = new TextDecoder().decode(data || new Uint8Array())
28+
contentType = 'application/octet-stream'
29+
break
30+
}
1831
default: {
1932
body = await request.text()
33+
contentType = 'text/plain'
2034
break
2135
}
2236
}
@@ -31,10 +45,16 @@ serve(async (request: Request) => {
3145
body: body ?? 'empty',
3246
}
3347

34-
return new Response(JSON.stringify(resp), {
48+
let responseData
49+
if (request.headers.get('response-type') === 'blob') {
50+
responseData = new Blob([JSON.stringify(resp)], { type: 'application/json' })
51+
} else {
52+
responseData = JSON.stringify(resp)
53+
}
54+
return new Response(responseData, {
3555
status: 200,
3656
headers: {
37-
'content-type': 'application/json',
57+
'content-type': contentType,
3858
},
3959
})
4060
})

test/spec/params.spec.ts

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import { Blob } from 'buffer'
2+
import querystring from 'querystring'
3+
14
import 'jest'
25
import { nanoid } from 'nanoid'
36
import { sign } from 'jsonwebtoken'
@@ -7,6 +10,7 @@ import { FunctionsClient } from '../../src/index'
710

811
import { Relay, runRelay } from '../relay/container'
912
import { attach, log } from '../utils/jest-custom-reporter'
13+
import { str2ab } from '../utils/binaries'
1014
import { MirrorResponse } from '../models/mirrorResponse'
1115

1216
describe('params reached to function', () => {
@@ -158,6 +162,7 @@ describe('params reached to function', () => {
158162
body: form,
159163
headers: {
160164
'content-type': 'application/x-www-form-urlencoded',
165+
'response-type': 'form',
161166
},
162167
})
163168

@@ -204,6 +209,7 @@ describe('params reached to function', () => {
204209
body: JSON.stringify(body),
205210
headers: {
206211
'content-type': 'application/json',
212+
'response-type': 'json',
207213
},
208214
})
209215

@@ -223,4 +229,138 @@ describe('params reached to function', () => {
223229
)
224230
expect(data).toEqual(expected)
225231
})
232+
233+
test('invoke mirror with body arrayBuffer', async () => {
234+
/**
235+
* @feature body
236+
*/
237+
log('create FunctionsClient')
238+
const fclient = new FunctionsClient(`http://localhost:${relay.container.getMappedPort(8081)}`)
239+
attach('setAuth', apiKey, ContentType.TEXT)
240+
fclient.setAuth(apiKey)
241+
242+
log('invoke mirror')
243+
const body = {
244+
one: nanoid(10),
245+
two: nanoid(5),
246+
three: nanoid(),
247+
num: 11,
248+
flag: false,
249+
}
250+
const arrayBuffer = str2ab(JSON.stringify(body))
251+
const { data, error } = await fclient.invoke<ArrayBuffer>('mirror', {
252+
responseType: 'arrayBuffer',
253+
body: arrayBuffer,
254+
headers: {
255+
'content-type': 'application/octet-stream',
256+
'response-type': 'arrayBuffer',
257+
},
258+
})
259+
const dataJSON = JSON.parse(new TextDecoder().decode(data ?? Buffer.from('').buffer))
260+
dataJSON.body = JSON.parse(dataJSON.body.replace(/\0/g, ''))
261+
262+
log('assert no error')
263+
expect(error).toBeNull()
264+
265+
const expected = {
266+
url: 'http://localhost:8000/mirror',
267+
method: 'POST',
268+
headers: dataJSON?.headers ?? [],
269+
body: body,
270+
}
271+
attach(
272+
'check data from function',
273+
`expected: ${JSON.stringify(expected)}\n actual: ${JSON.stringify(dataJSON)}`,
274+
ContentType.TEXT
275+
)
276+
expect(dataJSON).toEqual(expected)
277+
})
278+
279+
test('invoke mirror with body blob', async () => {
280+
/**
281+
* @feature body
282+
*/
283+
log('create FunctionsClient')
284+
const fclient = new FunctionsClient(`http://localhost:${relay.container.getMappedPort(8081)}`)
285+
attach('setAuth', apiKey, ContentType.TEXT)
286+
fclient.setAuth(apiKey)
287+
288+
log('invoke mirror')
289+
const body = {
290+
one: nanoid(10),
291+
two: nanoid(5),
292+
three: nanoid(),
293+
num: 11,
294+
flag: false,
295+
}
296+
const bodyEncoded = str2ab(JSON.stringify(body))
297+
const { data, error } = await fclient.invoke<Blob>('mirror', {
298+
responseType: 'blob',
299+
body: bodyEncoded,
300+
headers: {
301+
'content-type': 'application/octet-stream',
302+
'response-type': 'blob',
303+
},
304+
})
305+
const dataJSON = JSON.parse((await data?.text()) ?? '')
306+
dataJSON.body = JSON.parse(dataJSON.body.replace(/\0/g, ''))
307+
308+
log('assert no error')
309+
expect(error).toBeNull()
310+
311+
const expected = {
312+
url: 'http://localhost:8000/mirror',
313+
method: 'POST',
314+
headers: dataJSON?.headers ?? [],
315+
body: body,
316+
}
317+
attach(
318+
'check data from function',
319+
`expected: ${JSON.stringify(expected)}\n actual: ${JSON.stringify(dataJSON)}`,
320+
ContentType.TEXT
321+
)
322+
expect(dataJSON).toEqual(expected)
323+
})
324+
325+
test('invoke mirror with url params', async () => {
326+
/**
327+
* @feature body
328+
*/
329+
log('create FunctionsClient')
330+
const fclient = new FunctionsClient(`http://localhost:${relay.container.getMappedPort(8081)}`)
331+
attach('setAuth', apiKey, ContentType.TEXT)
332+
fclient.setAuth(apiKey)
333+
334+
log('invoke mirror')
335+
const body = {
336+
one: nanoid(10),
337+
two: nanoid(5),
338+
three: nanoid(),
339+
num: '11',
340+
flag: 'false',
341+
}
342+
const queryParams = new URLSearchParams(body)
343+
const { data, error } = await fclient.invoke<MirrorResponse>(
344+
`mirror?${queryParams.toString()}`,
345+
{
346+
responseType: 'json',
347+
}
348+
)
349+
350+
log('assert no error')
351+
expect(error).toBeNull()
352+
353+
const expected = {
354+
url: `http://localhost:8000/mirror?${queryParams.toString()}`,
355+
method: 'POST',
356+
headers: data?.headers ?? [],
357+
body: '',
358+
}
359+
attach(
360+
'check data from function',
361+
`expected: ${JSON.stringify(expected)}\n actual: ${JSON.stringify(data)}`,
362+
ContentType.TEXT
363+
)
364+
expect(data).toEqual(expected)
365+
})
226366
})

test/utils/binaries.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Convert a buffer to a string
3+
* @param buf - the buffer to convert to a string
4+
* @returns The string representation of the buffer.
5+
*/
6+
export function ab2str(buf: ArrayBufferLike) {
7+
let str = ''
8+
9+
new Uint16Array(buf).forEach(function (byte: number) {
10+
str += String.fromCharCode(byte)
11+
})
12+
return str
13+
}
14+
15+
/**
16+
* Convert a string to an array buffer
17+
* @param str - The string to be converted into an ArrayBuffer.
18+
* @returns The array buffer that contains the string.
19+
*/
20+
export function str2ab(str: string) {
21+
var buf = new ArrayBuffer(str.length * 2) // 2 bytes for each char
22+
var bufView = new Uint16Array(buf)
23+
for (var i = 0, strLen = str.length; i < strLen; i++) {
24+
bufView[i] = str.charCodeAt(i)
25+
}
26+
return buf
27+
}

0 commit comments

Comments
 (0)