I recently started working with Nest.js and its built-in unit testing library Jest, while on a task to upload a .CSV file and perform some operations on it, I decided to also unit test the endpoint and this required me to mock the CSV file object, which I did as thus
const mockFile = {
fieldname: 'file',
originalname: 'TradeHistory.csv',
encoding: '7bit',
mimetype: 'text/csv',
buffer: Buffer.from(__dirname + '/../../TradeHistory.csv', 'utf8'),
size: 51828,
}
I quickly ran into these issues;
For file upload, I was using the #UseInterceptors() and #UploadedFile()
which takes a type of file: Express.Multer.File
Which won't accept my mocked file object type as an argument
So I searched for a way to convert the mocked file into a type Express.Multer.File
and after a while what worked for me turned out to be embarrassingly simple and straightforward as using the type assertion as keyword to cast the file object Express.Multer.File
const mockFile = {
fieldname: 'file',
originalname: 'TradeHistory.csv',
encoding: '7bit',
mimetype: 'text/csv',
buffer: Buffer.from(__dirname + '/../../TradeHistory.csv', 'utf8'),
size: 51828,
} as Express.Multer.File
Other ways might exist, I'm open to suggestions
Related
I am using URQL as my react native graphql client. I like using the library but there doesn't seem to be an easy way to upload files selected from the expo image picker to my node server.
I did some googling, found a Ben Awad video where he uses ReactNativeFile to convert the result to a file. The issue is that this is the only way it seems fit for an apollo client. Is there something like this for urql? What would the code look like to convert the uri & base64 to a JS file?
...
if (!imageResult.cancelled) {
const file = new ReactNativeFile({
uri: imageResult.uri,
type: imageResult.type,
name: "picture"
});
image selection fn
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
base64: true,
aspect: [1, 1],
quality: 1,
});
if (result.cancelled || !result.uri || !onSuccessful) return;
await onSuccessful(result);
According to source code of the ReactNativeFile class (extract-files/public/ReactNativeFile.js) it just returns the same values you've entered. I don't see a problem to use plain object with same data. If you want to use this, you can, apollo-upload-client only exports ReactNativeFile from extract-files library (apollo-upload-client/public/ReactNativeFile.js)
Probably apollo-client checks if it is instanceof ReactNativeFile class but, I don't think URQL checks it.
You should follow the official URQL documentation for file uploads, and do not use apollo https://formidable.com/open-source/urql/docs/advanced/persistence-and-uploads/#file-uploads
I am writing unit tests and I want to test an img atrributes. However, when I make an assertion, I get mocked img attributes which is under __mocks__>fileMock.js. Because I mock files, I only get mocked file atrributes. How can I skip mocked files in my tests?
describe('Buttons', () => {
test('Clear filters work after filtering tools, workflows and using searchbar', async () => {
render(<HeaderBar {...defaults} />);
const clearFilterButton = screen.getByRole('button', { name: 'Clear Filters' });
const toolsButton = screen.getByRole('button', { name: 'TOOLS' });
const selectedTools = await within(toolsButton).findByRole('img');
expect(selectedTools).toHaveAttribute('src', 'images/tools-selected.png');
});
And test result is :
Buttons › Clear filters work after filtering tools, workflows and using searchbar
expect(element).toHaveAttribute("src", "images/tools-selected.png") // element.getAttribute("src") === "images/tools-selected.png"
Expected the element to have attribute:
src="images/tools-selected.png"
Received:
src="test-file-stub"
39 | const toolsButton = screen.getByRole('button', { name: 'TOOLS' });
40 | const selectedTools = await within(toolsButton).findByRole('img');
> 41 | expect(selectedTools).toHaveAttribute('src', 'images/tools-selected.png');
I need to test real image, and skip mocking that img in my test.
It sounds like you have a manual user module mock defined in a __mock__ folder next to your actual code.
In that case the mock is used in any test file where you call jest.mock('moduleName') unless automock is set to true in which case the mock will always be used.
If you are explicitly mocking the file using jest.mock('moduleName') then simply remove that from the test file where you want to use the actual code instead of the mock.
If you have automock set to true in your Jest config then you can tell Jest to use the original code file in a given test by using jest.unmock('moduleName').
I'm trying to mock PackedAvroSource, no luck.
Here is an exception:
unable to resolve argument selector: [{1}:'bytes'], with incoming: [{1}:0]
it happens when I try to access 'byte field in map taken from avro. Map func whic converts bytes expects to get field named 'bytes
Here is a test code snippet
test("My test"){
JobTest(classOf[PackedAvroSourceJob].getName)
.arg("input", "input")
.arg("output", "output")
.source(PackedAvroSource[ByteBuffer]("input"), createInput)
.sink(PackedAvroSource[ByteBuffer]("output")) { buffer: mutable.Buffer[(Byte)] =>
println("hERE!!!")
}
.run
}
What is the right way to pass schema 'bytes to that PackedAvroSource?
In your Job, when reading PackedAvroSource, use Fields.FIRST for the ByteBuffer field. This will work for both the job and the test.
I'm using fabric.js to dynamically create textures in Threes.js, and I need to save the textures to AWS. I'm using meteor-slingshot, which normally takes images passed in through a file selector input. Here's the uploader:
var uploader = new Slingshot.Upload("myFileUploads");
uploader.send(document.getElementById('input').files[0], function (error, downloadUrl) {
if (error) {
console.error('Error uploading', uploader.xhr.response);
alert (error);
}
else {
Meteor.users.update(Meteor.userId(), {$push: {"profile.files":downloadUrl}});
}
});
Uploading works fine from the drive ... but I'm generating my files in the browser, not getting them from the drive. Instead, they are generated from a canvas element with the following method:
generateTex: function(){
var canvTex = document.getElementById('texture-generator');
var canvImg = canvTex.toDataURL('image/jpeg');
var imageNew = document.createElement( 'img' );
imageNew.src = canvImg;
}
This works great as well. If I console.log the imageNew, I get my lovely image with base 64 encoding:
<img src="data:image/jpeg;base64,/9j/
4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgID
//....carries on to 15k or so characters
If I console.log a file object added from the drive via filepicker ( not generated from a canvas ), I can see what the file object should look like:
file{
lastModified: 1384216556000
lastModifiedDate: Mon Nov 11 2013 16:35:56 GMT-0800 (PST)
name: "filename.png"
size: 3034
type: "image/png"
webkitRelativePath: ""
__proto__: File
}
But I can't create a file from the blob for upload, because there is no place in the file object to add the actual data.
To sum up I can:
Generate an image blob and display it in a dom element
Upload files from the drive using meteor-slingshot
inspect the existing file object
But I don't know how to convert the blob into a named file, so I can pass it to the uploader.
I don't want to download the image, (there are answers for that), I want to upload it. There is a "chrome only" way to do this with the filesystem API but I need something cross browser (and eventually cross platform). If someone could help me with this, I would have uncontainable joy.
Slingshot supports blobs just as well as files: https://github.com/CulturalMe/meteor-slingshot/issues/22
So when you have a canvas object called canvTex and a Slingshot.Upload instance called uploader, then uploading the canvas image is as easy as:
canvTex.toBlob(function (blob) {
uploader.send(blob, function (error, downloadUrl) {
//...
});
});
Because blobs have no names, you must take that into account when defining your directive. Do not attempt to generate a key based on the name of the file.
Grails 2.3.10.
How can I configure the available mime types for content type negotiation in a Grails Spock test?
When I try to tell the controller to produce JSON content, it seems to want to return an HTTP 406 error. I send in the Accept header in my test code; but, the parser is not able to match it because HTML is the only MIME type that's configured.
My use case...
I have implemented a controller action using the Grails respond method which can return a JSON response. When I hit the endpoint using a REST API call, I am able to get back JSON output (even if no Accept header is specified).
The controller code:
#Transactional(readOnly = true)
class MyObjectController {
static allowedMethods = [save: 'POST']
static responseFormats = ['json']
def myService
#Transactional
def save(MyObject obj) {
obj.validate()
if (obj.hasErrors()) {
respond obj.getErrors(), [status: BAD_REQUEST]
}
myService.addNewCustomer(obj)
respond obj, [formats: responseFormats]
}
}
And my test code:
#TestFor(MyObjectController)
class MyObjectControllerSpec extends Specification {
def setup() {
}
def cleanup() {
}
void "test save - json success"() {
given:
def myObj = new MyObject()
controller.myService= Mock(MyObjectService)
when:
request.addHeader "Accept", "application/json"
controller.save(individual)
then:
response.status == HttpStatus.CREATED.value()
response.text == "{}" //.text is giving me an empty string
response.json.x == x //.json throws an exception (parsing an empty string)
}
}
I have verified in the debugger that obj has a valid value and that the respond method is invoked on the last line of the controller action.
What I am finding is that inside the Grails ResponseMimeTypesApi class, the DefaultAcceptHeaderParser is getting constructed with only the HTML mime type. Even though the JSON accept header is being read correctly, the DefaultAcceptHeaderParser isn't able to understand it because no mime types are configured.
How do I control the mime types that get sent to ResponseMimeTypesApi in my unit test spec?
Edit
I have also tried setting the response.format property, as suggested in this answer; but, to no avail.
If you assign a value to request.json that will set the content type. You can also set the content type explicitly with something like request.contentType = 'application/json' or request.contentType = JSON_CONTENT_TYPE. For a list of the content type constants available in your unit tests see the "Testing Mime Type Handling" section under http://grails.org/doc/latest/guide/testing.html#unitTestingControllers.
Another resource to look at is the unit tests at https://github.com/grails/grails-core/blob/4f8d1a605cde60a4a00021102959578dae8bc5a8/grails-test-suite-web/src/test/groovy/org/codehaus/groovy/grails/web/binding/json/JsonBindingSpec.groovy and https://github.com/grails/grails-core/blob/801d507cf3fec5866baa14f6d6b0acd05aa5fb56/grails-test-suite-web/src/test/groovy/org/codehaus/groovy/grails/web/binding/xml/XmlBindingSpec.groovy.
I hope that helps.
EDIT:
To clarify...
I mentioned assigning a value to request.json. The value you assign to that of course is JSON, not the content type. Like this...
request.json = '''
{
"name": "Douglas", "age": "42"
}
'''
When you do that, the content type gets set automatically.
I found that I could write the test that I wanted by converting from a unit to an integration test.
Move the test to the /integration path.
Change the test spec to extend IntegrationSpec
#Autowire the class under test instead of using #TestFor:
Set controller.response.format = 'json' and call controller.request.addHeader 'Accept', 'application/json'