I know that there is a plugin for doing this in cypress already. However using it with jar files just corrupts the file and therefore it is useless in my usecase. This is really weird because i tried it with every combination of encoding and it still does not work. Works perfectly fine with other filetypes however.
This is the code i am using (works except with jar files).
cy.fixture('test.jar', 'binary')
.then(Cypress.Blob.binaryStringToBlob)
.then(fileContent => {
cy.get('[data-cy="dropzone"]')
.contains('Jar file')
.parent()
.find('div')
.attachFile({
fileContent,
filePath: 'test.jar',
mimeType: 'application/java-archive',
encoding: 'binary',
lastModified: new Date().getTime(),
subjectType: 'drag-n-drop',
force: true
});
});
I know that you can perform post requests in cypress. Is it possible to perfom the file upload with it after clicking the dropzone element?
cypress-file-upload lacks explicit support for .jar extension, this is the current list of supported extensions
const FILE_EXTENSION = Object.freeze({
JSON: 'json',
JS: 'js',
COFFEE: 'coffee',
HTML: 'html',
TXT: 'txt',
CSV: 'csv',
PNG: 'png',
JPG: 'jpg',
JPEG: 'jpeg',
GIF: 'gif',
TIF: 'tif',
TIFF: 'tiff',
ZIP: 'zip',
PDF: 'pdf',
VCF: 'vcf',
SVG: 'svg',
XLS: 'xls',
XLSX: 'xlsx',
DOC: 'doc',
DOCX: 'docx',
MP3: 'mp3'
});
The default encoding used is therefore utf8. To explicitly pass in the encoding as an option, you need to use raw mode
cy.fixture('sample.jar', 'binary')
.then(Cypress.Blob.binaryStringToBlob)
.then(fileContent => {
cy.get('[data-cy="dropzone"]').attachFile({
fileContent,
filePath: 'sample.jar',
mimeType: 'application/java-archive',
encoding: 'binary',
lastModified: new Date().getTime(),
},
{
subjectType: 'drag-n-drop',
force: true
});
});
Note you need to try both subjectType values, as they trigger different events.
Here's the code that shows which shows which events are triggered with force option
export const EVENTS_BY_SUBJECT_TYPE: Record<Required<HtmlSubjectType>, string[]> = {
[HtmlSubjectType.input]: ['change'],
/**
* #see https://developer.mozilla.org/en-US/docs/Web/API/DragEvent
*/
[HtmlSubjectType.dragAndDrop]: ['dragstart', 'drag', 'dragenter', 'drop', 'dragleave', 'dragend'],
};
If you still get no action, you will need to manually trigger events, e.g chain .trigger('change') after attachFile(). Ideally you can figure out which events from the app source code.
The workaround given by abramenal is incorrect, this is the part of cypress-file-upload that handles the options parameter. If you pass fixture as a string, encoding is ignored
function getFixtureInfo(fixtureInput) {
// Normal mode
// fixture name and options passed separately.
if (typeof fixtureInput === 'string') {
return {
filePath: fixtureInput,
encoding: '',
mimeType: '',
fileName: getFileName(fixtureInput)
};
}
// Raw mode
// If you pass an object, encoding can be specified
return {
filePath: fixtureInput.filePath,
encoding: fixtureInput.encoding || '',
mimeType: fixtureInput.mimeType || '',
fileName: fixtureInput.fileName || getFileName(fixtureInput.filePath),
fileContent: fixtureInput.fileContent,
lastModified: fixtureInput.lastModified
};
}
Related
I try to upload a file with GraphQL. While upload, I get following error message:
Variable "$file" got invalid value { resolve: [function], reject:
[function], promise: {}, file: { filename:
"insung-yoon-TPvE8qPfMr0-unsplash.jpg", mimetype: "image/jpeg",
encoding: "7bit", createReadStream: [function createReadStream] } };
Upload value invalid.
The only solution I found, was to disable the upload at apollo-graphql and add graphql-upload
new ApolloServer({ schema, context, uploads: false })
app.use(graphqlUploadExpress({ maxFileSize: 10000, maxFiles: 10 }))
I already had added this setting, but the issue is still there.
My mutation looks like:
#Mutation(() => ReturnType)
uploadFileAndData(
#Ctx() ctx: Context,
#Arg('data', { description: 'File Upload' }) data: MyInputType,
): Promise<ReturnType> {
return functionWithMagic({ ctx, data })
}
and my InputType like:
import { FileUpload, GraphQLUpload } from 'graphql-upload'
...
#InputType({ description: 'Upload data input' })
export class MyInputType {
#Field(() => GraphQLUpload)
#Joiful.any()
file: FileUpload
}
After a lot of searching, I finally found my issue. We are using a mono repo, and had installed two different version of file-upload in two packages. When I changed the version, at both packages on the same version and the error is gone.
To add, if you're using Altair graphql client, this error can originate from the client itself.
try:
1- close all tabs and start altair again
2- redo step one, then close the query tab and rewrite the query.
I'm a beginner when it comes to using Uppy. I'm sure that this can be resolved by pros like you. But I am having trouble sending specific meta data information to my upload route.
uppy.js
// Import the plugins
const Uppy = require('#uppy/core');
const XHRUpload = require('#uppy/xhr-upload');
const Dashboard = require('#uppy/dashboard');
const request = require('request');
const uppy = Uppy({
debug: true,
autoProceed: false,
restrictions: {
maxFileSize: 1024000,
maxNumberOfFiles: 3,
minNumberOfFiles: 1,
allowedFileTypes: ['image/*', 'video/*']
}
})
.use(Dashboard, {
trigger: '.UppyModalOpenerBtn',
inline: true,
target: '#drag-drop-area',
replaceTargetContent: true,
showProgressDetails: true,
proudlyDisplayPoweredByUppy: false,
animateOpenClose: true,
note: 'Images and video only, 1–3 files, up to 1 MB',
height: 470,
browserBackButtonClose: true,
theme: 'dark',
metaFields: [
{id: 'caption', name: 'Caption', placeholder: 'describe what the image is about'}
]
});
uppy.on('file-added', (file) =>{
console.log(file);
uppy.setFileMeta(file.meta.id, {
caption: file.name
});
});
uppy.use(XHRUpload, {
id: 'XHRUpload',
endpoint: 'http://localhost:8000/upload',
method: 'POST',
formData: true,
fieldName: 'my_file',
metaFields: ['caption'],
bundle: true
});
uppy.on('upload-success', (file, response) => {
//console.log(file.meta.caption);
console.log("File uploaded successfully ", file);
});
module.exports = uppy;
upload.js
router.post('/',(req, res, next) => {
console.log("Coming form uppy.js " , req.body);
});
module.exports = router;
I'm having trouble passing the 'caption' value to my route. When I look on the 'network tab' on Google Chrome's developer tools, it give me a message of 'undefined'. If you can point me at the right direction, I'd appreciate it! Thank you!
First of all need to change file.meta.id to file.id
uppy.on('file-added', (file) =>{
console.log(file);
uppy.setFileMeta(file.id, {
test: 'hello'
});
});
but if you use bundle you should know about that note
Note: When bundle is set to true, only global uppy metadata, the one set via meta options property, is sent to the endpoint. Individual per-file metadata is ignored.
so, if you want send meta data for each file you should change it to false, then you faced with separate request for each file, but all meta data would be present in request
The test objective is to confirm that an uploaded images 'src' attribute changes if a user uploads a new image, meaning the image has changed.
I've tried to use a couple approaches, outlined below.
First Approach
cy.get('.img').then($img => {
//store the src
const source = $('img').attr('src');
/**
* File drop 2mb jpg
*/
cy.fixture(Cypress.env("JPG_2MB_ASSET"), "base64").then(fileContent => {
cy.get(".dropzone").upload(
{
fileContent,
fileName: "sampleimage.jpg",
mimeType: "image/jpeg"
},
{ subjectType: "drag-n-drop" }
);
});
cy.wait(16000);
cy.get('img')
.attr('src')
.should($src2 => {
expect($src2).not.to.eq(source);
});
Second Approach
//store the src
const source = $img.attr('src')
/**
* File drop 2mb jpg
*/
cy.fixture(Cypress.env("JPG_2MB"), "base64").then(fileContent => {
cy.get(".dropzone").upload(
{
fileContent,
fileName: "sampleimage.jpg",
mimeType: "image/jpeg"
},
{ subjectType: "drag-n-drop" }
);
});
cy.wait(16000);
cy.get("img").attr('src').should(($src2) => {
expect($src2).not.to.eq(source)
Third Approach
cy.get("img")
.attr("src")
.then($src1 => {
/**
* File drop 2mb jpg
*/
cy.fixture(Cypress.env("JPG_2MB"), "base64").then(fileContent => {
cy.get(".dropzone").upload(
{
fileContent,
fileName: "sampleimage.jpg",
mimeType: "image/jpeg"
},
{ subjectType: "drag-n-drop" }
);
});
cy.wait(16000);
cy.get('img')
.attr('src')
.should($src2 => {
expect($src2).not.to.eq($src1);
});
The uploads work great, but the comparison of the src does not.
First & Second Approach
Expected- it stores the first image's src as the const source, and it drops a 2mb jpg. It then compares the 2nd image's src to the first and confirm they are different.
Result- ReferenceError: $ is not defined
Third Approach
Expected- It stores the first src as $src1, and then compares it to the second src, $src2
Result- cy.get(...).attr is not a function
After a plentitude of being angry at my keyboard, I have found the winning solution.
Using invoke you can store the value of an attr like src, as shown here:
https://docs.cypress.io/api/commands/invoke.html#Arguments-are-automatically-forwarded-to-the-function
So, after a few tweaks to the above attempts, I found this to work perfectly:
cy.get('.image-root img').invoke('attr', 'src').then((firstSrc) => {
const src1 = firstSrc
/**
* File drop 2mb jpg
*/
cy.fixture(Cypress.env("JPG_2MB"), "base64").then(fileContent => {
cy.get(".dropzone").upload(
{
fileContent,
fileName: "sampleimage.jpg",
mimeType: "image/jpeg"
},
{ subjectType: "drag-n-drop" }
);
});
cy.wait(16000);
cy.get('.image-root img').invoke('attr', 'src').then((nextSrc) => {
expect(nextSrc).to.not.equal(src1)
});
});
I intend to download a dynamically generated pdf file using a remote method, the file exists at a particular path and I am using return type "file". My implementation is:
customer.downloadFile = function downloadFile(userId, res, cb){
var reader = fs.createReadStream(__dirname + '/../document.pdf');
cb(null, reader, 'application/pdf');
};
customer.remoteMethod(
'downloadFile',
{
isStatic: true,
accepts: [
{ arg: 'id', type: 'string', required: true },
{ arg: 'res', type: 'object', 'http': { source: 'res' } }
],
returns: [
{ arg: 'body', type: 'file', root: true },
{ arg: 'Content-Type', type: 'string', http: { target: 'header' } }
],
http: {path: '/:id/downloadFile', verb: 'get'}
}
);
The issue with the above code is that the browser although displays the beautiful pdf file container, but instead of the file following error is shown:
Please point out as to what is wrong with the code and how to correct.
Got lead from this URL: https://github.com/strongloop/loopback-swagger/issues/34
Got that working with following:
fs.readFile(fileName, function (err, fileData) {
res.contentType("application/pdf");
res.status(200).send(fileData);
if (!err) {
fs.unlink(fileName);
}
else {
cb(err);
}
});
You should use loopback-component-storage to manage downloadable files.
Files are grouped in so-called containers (Basically, a folder with a single level of hierarchy, not more).
How it is done:
Create a model called container for instance.
Create a storage datasource that uses as connector the loopback-component-storage
Give to container model the datasource storage
That's it. You can upload and download files to/from your container.
With a container, you can store files to a local filesystem, or move later to Cloud solutions.
How to add existing files on server to dropzone with right work all functions and right styling?
I wrote a function to add files: addCustomFile(file, thumbnail_url , responce)
Powered by Version: 4.0.1 stable
Correct working: maxFiles limit, event maxfilesexceeded, event success and others
$("#dropzone-images").dropzone({
url: "...",
paramName: 'image_temp',
maxFiles: 1,
init: function () {
this.addCustomFile = function(file, thumbnail_url , responce){
// Push file to collection
this.files.push(file);
// Emulate event to create interface
this.emit("addedfile", file);
// Add thumbnail url
this.emit("thumbnail", file, thumbnail_url);
// Add status processing to file
this.emit("processing", file);
// Add status success to file AND RUN EVENT success from responce
this.emit("success", file, responce , false);
// Add status complete to file
this.emit("complete", file);
}
this.addCustomFile(
// File options
{
// flag: processing is complete
processing: true,
// flag: file is accepted (for limiting maxFiles)
accepted: true,
// name of file on page
name: "The name",
// image size
size: 12345,
// image type
type: 'image/jpeg',
// flag: status upload
status: Dropzone.SUCCESS
},
// Thumbnail url
"http://.../img.jpg",
// Custom responce for event success
{
status: "success"
}
);
}
});