v2.0.2 breaks specs using fixture_file_upload
dub-squared opened this issue ยท 4 comments
The latest version of this gem (v2.0.2) included this Pull Request that raises an error on type mismatch. This causes issues with spec that leverage the fixture_file_upload
method. When using fixture_file_upload
, the value
argument passed to the coerce_input
method is of type ActionDispatch::Http::UploadedFile
not ApolloUploadServer::Wrappers::UploadedFile
, so the GraphQL::CoercionError
is raised. Since ApolloUploadServer::Wrappers::UploadedFile
is a delegate class of ActionDispatch::Http::UploadedFile
everything works fine without the type check.
Example Spec
The mutation takes a file, and returns true if the upload was successful
def query
<<~GQL
mutation($file: Upload!) {
uploadCsv(file: $file)
}
GQL
end
let(:variables) do
{ file: fixture_file_upload(Rails.root.join('spec', 'fixtures', 'file.csv'), 'text/csv') }
end
it 'returns a true' do
post '/graphql', params: { query: query, variables: variables }
expect(JSON.parse(response.body)['data']['uploadCsv']).to eq true
end
I pulled the gem down to see I could resolve the issue, but the only thing I could come up with is to remove the prior change or add an additional is_a?
check for ActionDispatch::Http::UploadedFile
.
Has anyone else ran into this issue? Is there a different way to define a spec to get around this?
@dub-squared yes! I have run into this issue and I'm currently trying to solve it. I've tried a few things with no luck. Please let me know if you're able to find a fix, I'll do the same ๐
@dub-squared I was able to fix my specs... I was completely forgetting about the format apollo-upload-client
follows. https://github.com/jaydenseric/graphql-multipart-request-spec/tree/v2.0.0-alpha.2
So following this I ended up doing:
let(:params) do
{
query: ...,
variables: variables.to_json,
operations: { "query": ..., "operationName": "...", "variables": variables }.to_json,
map: {"1": ["variables.image"]}.to_json,
"1": image
}
end
and the image file ended up like:
let(:image) do
Rack::Test::UploadedFile.new("spec/fixtures/files/image.jpg", "image/jpeg")
end
although I think you can use fixture_file_upload
instead of Rack::Test::UploadedFile
.
And the post would be as expected:
post graphql_path, params: params, headers: headers
after these updates I got everything working again. Let me know if this works for you! ๐
@sebasjimenez10 I was able to take your advice, and refactor the params structure for the example to:
let(:params) do
{
'operations' => {
'query' => query,
'variables' => { 'file' => file }
}.to_json,
'map' => { '1' => ['variables.file'] }.to_json,
'1' => file
}
end
Once that was done, everything worked as expected. I left the fixture_file_upload
since it returns a Rack::Test::UploadedFile
anyway. Hopefully this helps anyone else that has a similar issue. Thanks.
Here is another working example with an array of attachments if it can help:
let(:image) { fixture_file_upload('spec/support/sample_files/logo.png') }
post '/portal_api/graphql', params: {
operations: {
query: query,
variables: {
attachments: [image]
},
}.to_json,
map: { '0': ['variables.attachments.0'] }.to_json,
'0': image
}
I checked a bit the code to understand wtf is going on under the hood and it seems that the ApolloUploadServer::Middleware
middleware is "casting" the Rack::Test::UploadedFile
to a ApolloUploadServer::Wrappers::UploadedFile
only when the operations
and map
are present in the request, what is done by the apollo client (which respect the GraphQL 2 spec: https://github.com/jaydenseric/graphql-multipart-request-spec/tree/v2.0.0-alpha.2#multipart-form-fields)