Closed corteshvictor closed 7 months ago
fastify.inject()
is identical to doing an http request. You can't send functions in HTTP requests.
@mcollina I understand what you are saying and I partly agree, but the context that I am explaining to you applies that this allows at least a good functionality.
@fastify/multipart
injects toBuffer into the body, and in my scheme I have to place them to be able to inject the types. So you need to be able to dispatch a function in inject to be able to cover the toBuffer
that @fastify/multipart
adds when you enable { attachFieldsToBody: true }
If you are not loading @fastify/multipart
in your tests, you can simulate that using a preHandler
hook.
Please create a repository
I deleted the previous comment, I was seeing that what I had in mind didn't work for me. I already created the repo and I'll share it with you....
preHandler
doesn't work either because by enabling { attachFieldsToBody: true }
the entire form-data
is already in the body. Then I will have the same error, toBuffer
is required since fastify.inject()
does not allow the function to be sent. The schema is validating that body in both the preHandler
and the handler
.
If I add it in another life cycle before preHandler, multipart
has not yet injected the form-data
information into body and the JSON schema validation does nothing because the body is empty.
I know it is a complicated case, but it is the behavior of multipart
that injects several properties into the body and among that adds the toBuffer
function when loading a file in the form-data
and the schema I need that toBuffer to arrive in order to have the form types inferred in typescript with the @fastify/type-provider-typebox
library
https://github.com/corteshvictor/fastify-demo
Here is the repository. Although I did this quickly with the template that Fastify
generates and does not have typescript, but you can see the behavior of the test I want to do.
I don't understand, you are trying to send JSON
to test multipart
endpoint. It is expected to not working.
If you want to mock the payload of file
, please send a proper multipart/form-data
payload to the endpoint.
@climba03003 How do I send a file via fastify.inject()
?
In addition, the problem is not sending it, it is the validation of the scheme. When validating that toBuffer
must be in the body because multipart
adds them, fastify.inject()
tells you that toBuffer
is required.
How would you recommend me to do the unit test with fastify.inject()
to send the file and get the toBuffer
so I can convert the file?
How do I send a file via fastify.inject()?
import fastifyMultipart from '@fastify/multipart'
import Fastify from 'fastify'
import { Readable } from 'node:stream'
const fastify = Fastify()
fastify.register(fastifyMultipart, {
attachFieldsToBody: true
})
fastify.post('/', {
schema: {
body: {
id: {
type: 'object',
properties: {
value: { type: 'string' },
mimetype: { type: 'string' }
},
required: ['value', 'mimetype']
},
file: {
type: 'object',
properties: {
filename: { type: 'string' },
mimetype: { type: 'string' },
toBuffer: { }
},
required: ['filename', 'mimetype', 'toBuffer']
}
}
}
}, async function(request) {
const { id, file } = request.body;
try {
console.log(id.value) // helloworld
console.log(await file.toBuffer()) // <Buffer 66 69 6c 65 3a 68 65 6c 6c 6f 77 6f 72 6c 64>
return { ok: true }
} catch {
return { ok: false }
}
})
await fastify.ready()
const readable = new Readable()
readable.push('--foobar\r\n')
readable.push('Content-Disposition: form-data; name="id"\r\n')
readable.push('Content-Type: text/plain\r\n\r\n')
readable.push('helloworld\r\n')
readable.push('--foobar\r\n')
readable.push('Content-Disposition: form-data; name="file"; filename="file.txt"\r\n')
readable.push('Content-Type: text/plain\r\n\r\n')
// here is the content of file
readable.push('file:helloworld\r\n')
readable.push('--foobar--')
readable.push(null)
const { body }= await fastify.inject({
path: '/',
method: 'POST',
headers: {
"content-type": "multipart/form-data; boundary=foobar"
},
body: readable
})
console.log(body)
In addition, the problem is not sending it, it is the validation of the scheme.
I really doesn't understand what is the problem. When you send multipart
normally, all the property you have will be provided by @fastify/multipart
. The schema validation will works as it should.
How would you recommend me to do the unit test with fastify.inject() to send the file and get the toBuffer so I can convert the file?
Send what it should send by a browser. It is the main point of testing. Use a Readable
for multipart/form-data
or any package to form a proper multipart
stream.
https://www.npmjs.com/package/form-data is what I use.
I’ve transferred this to help, because it’s mostly a question on how to do something
Thank you very much @climba03003, I will perform the tests tomorrow.
@mcollina I had tried with new formData()
but it also failed me, the schema did not realize it and returned the error body must be object
. But I did not think to try with new Readable()
.
I do the tests and I will tell you how it went, but thanks for the help.
@mcollina @climba03003 thank you very much for the help, with the new Readable()
it works without problem.
The new fromData()
native using Node v20, if placed problems but using the form-data
library seems to work passing the headers with the getHeaders()
function but this library has several years without being updated and may have security issue.
I decided to stick with new Readable()
which worked very well.
Thanks again to both of you for your help.
Prerequisites
Fastify version
4.20.0
Plugin version
No response
Node.js version
20
Operating system
macOS
Operating system version (i.e. 20.04, 11.3, 10)
14.2.1
Description
I am unit testing my routes using
fastify.inject()
, the route receives a form-data with text fields and a file.The '@fastify/multipart' plugin, enabling attachFieldsToBody to true, injects those fields into the body.
In my route I have a schema that validates some information from the body, but inject cannot send a mock function, it says that the property is required and I cannot invoke the route.
Steps to Reproduce
I have a route similar to this, where I am validating the schema with the plugin
"@fastify/type-provider-typebox":"^3.3.0"
.As you can see in the path, I am getting a file with other fields, to do this, I am using the plugin
"@fastify/multipart":"^8.1.0"
. By using this plugin as followsI am injecting all the form-data into the body so I can validate it in the schema, that file injects a toBuffer() function which I validate it type
any
in my schema.When I want to use fastify.inject as follows, the body validates the text fields fine but the toBuffer function, even though it is type
any
in the schema says it is required because inject does not allow to send that mock function, but if I send a texttoBuffer: 'text'
if the path is executed.Expected Behavior
The behavior I expect, is that
fastify.inject()
can allow to send a mock function in the properties and this replaces the one injected in the body when using the @fastify/multipart plugin.