Our application under test is created using angular which uses a third party package ng-file-upload for file upload functionality.
Cypress throws below error while executing test. After further investigation it is found that this is thrown from ngFileUpload service of third party package ng-file-upload which expects items object as part of dataTransfer object.
Uncaught TypeError: n.item is not a function
This error originated from your application code, not from Cypress.
When Cypress detects uncaught errors originating from your application it will automatically fail the current test.
This behavior is configurable, and you can choose to turn this off by listening to the 'uncaught:exception' event.
Drag and drop upload works with angular applications using nf-file-upload npm package or applications which expects items as part of dataTransfer object. Following code in handleDragDrop.js in local repo found working when tested.
export default ({ subject, force }, { files }) => {
const dataTransfer = new DataTransfer();
files.forEach(file => dataTransfer.items.add(file));
cy.wrap(subject, { log: false }).trigger('drop', {
force,
dataTransfer: {
files,
items: dataTransfer.items,
types: ['Files'],
},
});
};
Pre-requisite
An angular application using ng-file-upload for file upload.
*Cypress test code *
cy.fixture(filesToUpload[0].fileLocation).then((fileContent) => {
cy.get('drag-area').upload(
{ fileContent, fileName: filesToUpload[0].fileName, mimeType: filesToUpload[0].mimeType },
{ subjectType: 'drag-n-drop' },
);
cy.get('.sb2-content-thumbnail-container').should('be.visible').contains(filesToUpload[0].fileName);
Cypress: 3.4.0
OS: Mac
Browser: Chrome 76
Hi @benchaminaa
Thanks for submitting the issue!
Will take a look on the issue later this weel. Likely will create a separate recipe for ng-file-upload as its quite often used together with this plugin.
Hi @benchaminaa
I've added a recipe for angularjs and ng-file-upload.
If you still experience the mentioned issue please take a look on that. If it does not help, feel free to reopen this issue so we can figure out what is your specific issue 馃槇
Hi @abramenal thanks for the update. I did a quick test after installing latest version and I'm running into same issue. FYI I was having issue in uploading files using drag and drop { subjectType: 'drag-n-drop' } not with file input.
@benchaminaa well I think that is the cause of issue you see. ng-file-upload creates a hidden html file input which should be accessed within your test suite. So that is not actually the drag-n-drop type,
see source code:
https://github.com/abramenal/cypress-file-upload/blob/master/recipes/angularjs-ng-file-upload/src/index.html#L12
and its test suite:
https://github.com/abramenal/cypress-file-upload/blob/master/recipes/angularjs-ng-file-upload/cypress/integration/input.spec.js#L22
@abramenal well our application has a div element that uses ngf-drop of ng-file-upload module which I assume should be used as drop zone to trigger drop event. Our application provides both drag and drop(ngf-drop) and button click(ngf-select) to upload files. If I use hidden file input to upload files in both cases there is no difference writing two test scenario.
My current work around using cypress command works fine by using above div element as drop zone and I was expecting same can be achieved with this plugin. As I mentioned in the description of this bug it looks like it's something to do with how ngf-file-upload expects dataTransfer object with items property if it is drag and drop?. I might be wrong as well with my limited exposure to ng-file-upload.
const { fileLocation, filename, contentType } = filesToUpload[0];
cy.fixture(fileLocation).then((fileContent) => {
Cypress.Blob.base64StringToBlob(fileContent, contentType).then((blob) => {
cy.window({ log: false }).then(async (window) => {
const files: File[] = [];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const file = await new (window as any).File(
[blob],
filename,
{ type: contentType },
);
files.push(file);
const dt = new DataTransfer();
dt.items.add(file);
const dataTransfer = {
dataTransfer: {
files,
items: dt.items,
types: ['Files'],
},
};
cy.get('div[class~="sb2-asset-drag-area"]')
.then(dropZone => cy.wrap(dropZone).trigger('drop', dataTransfer));
});
cy.get('.sb2-content-thumbnail-container').should('be.visible').contains(filename);
});
I have the same issue. I'm trying to test an upload using angular1.7 and ng-file-upload. I'm using a button like
<button ngf-select ngf-drop ng-model="$ctrl.file" name="spreadsheet" ngf-model-invalid="$ctrl.rejFile"
ngf-drag-over-class="{accept:'dragover', reject:'dragover-err', delay:100}"
class="btn btn-secondary gtm-upload-file-btn" ngf-multiple="false" ngf-allow-dir="true"
ngf-pattern="'*.csv,*.xlsx'" ngf-drop-available="true" ngf-max-size="$ctrl.maxSize"
ngf-change="$ctrl.readFile($file, $invalidFiles, $event)"
data-eventcategory="{{$ctrl.parentComponent}}" data-eventaction="Select CSV or XLSX file"
data-eventlabel="btn">
Select CSV or XLSX file
</button>
but can't test it using cypress. Do you have any other solutions?
Most helpful comment
Hi @benchaminaa
Thanks for submitting the issue!
Will take a look on the issue later this weel. Likely will create a separate recipe for ng-file-upload as its quite often used together with this plugin.