diff --git a/lib/content-services/src/lib/upload/directives/file-draggable.directive.spec.ts b/lib/content-services/src/lib/upload/directives/file-draggable.directive.spec.ts
index 08f59cae4e..52925a9d9c 100644
--- a/lib/content-services/src/lib/upload/directives/file-draggable.directive.spec.ts
+++ b/lib/content-services/src/lib/upload/directives/file-draggable.directive.spec.ts
@@ -15,108 +15,176 @@
* limitations under the License.
*/
-import { ElementRef } from '@angular/core';
-import { FileDraggableDirective } from '../directives/file-draggable.directive';
+import { Component, ViewChild } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FileDraggableDirective, INPUT_FOCUS_CSS_CLASS } from '../directives/file-draggable.directive';
+
+@Component({
+ selector: 'adf-test-component',
+ template: `
+
+ `
+})
+class TestComponent {
+ @ViewChild(FileDraggableDirective, { static: true })
+ directive: FileDraggableDirective;
+}
describe('FileDraggableDirective', () => {
+ let fixture: ComponentFixture;
+ let component: TestComponent;
+ let directive: FileDraggableDirective;
- let component: FileDraggableDirective;
+ let testContainer: HTMLDivElement;
+ let testContent: HTMLDivElement;
- beforeEach( () => {
- const el = new ElementRef(null);
- component = new FileDraggableDirective(el, null);
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [
+ TestComponent,
+ FileDraggableDirective
+ ]
+ });
+
+ fixture = TestBed.createComponent(TestComponent);
+ component = fixture.componentInstance;
+ directive = component.directive;
+
+ fixture.detectChanges();
+ testContainer = fixture.nativeElement.querySelector('#test-container');
+ testContent = fixture.nativeElement.querySelector('#test-content');
});
+ afterEach(() => {
+ fixture.destroy();
+ });
+
+ function createEvent(eventName: string): DragEvent {
+ return new DragEvent(eventName, {
+ bubbles: true,
+ cancelable: true,
+ dataTransfer: new DataTransfer()
+ });
+ }
+
+ function raiseEvent(eventName: string): DragEvent {
+ const event = createEvent(eventName);
+ testContent.dispatchEvent(event);
+ return event;
+ }
+
it('should always be enabled by default', () => {
- expect(component.enabled).toBeTruthy();
+ expect(directive.enabled).toBeTruthy();
});
- it('should not allow drag and drop when disabled', () => {
- component.enabled = false;
- const event = new DragEvent('custom-event');
- spyOn(event, 'preventDefault').and.stub();
- component.onDropFiles(event);
- component.onDragEnter(event);
- component.onDragLeave(event);
- expect(event.preventDefault).not.toHaveBeenCalled();
+ it('should add focus style on [dragenter]', () => {
+ raiseEvent('dragenter');
+ expect(testContainer.classList.contains(INPUT_FOCUS_CSS_CLASS)).toBeTruthy();
});
- /*
- it('should emit onFolderEntityDropped event when a folder is dragged with Chrome' , (done) => {
+ it('should add focus style on [dragenter] only if not already handled', () => {
+ const dragEvent = createEvent('dragenter');
+ dragEvent.preventDefault();
- let itemEntity = {
- fullPath: '/folder-fake',
- isDirectory: true,
- isFile: false,
- name: 'folder-fake'
- };
- let fakeEvent = {
- dataTransfer: {
- items: [{
- webkitGetAsEntry: () => {
- return itemEntity;
- }
- }]
- },
- stopPropagation: jasmine.createSpy('stopPropagation'),
- preventDefault: jasmine.createSpy('preventDefault')
- };
-
- component.onFolderEntityDropped.subscribe(files => {
- expect(files).toEqual(itemEntity);
- expect(component.getInputFocus()).toBe(false);
- done();
- });
-
- component.onDropFiles(fakeEvent);
+ testContainer.dispatchEvent(dragEvent);
+ expect(testContainer.classList.contains(INPUT_FOCUS_CSS_CLASS)).toBeFalsy();
});
- it('should emit onFilesDropped event when a file is dragged not with Chrome' , (done) => {
- let file = {name: 'fake-name-1', size: 10, webkitRelativePath: 'fake-folder1/fake-name-1.json'};
- let fakeEvent = {
- dataTransfer: {
- files: [file]
- },
- stopPropagation: jasmine.createSpy('stopPropagation'),
- preventDefault: jasmine.createSpy('preventDefault')
- };
+ it('should add focus style only on [dragover]', () => {
+ raiseEvent('dragover');
+ expect(testContainer.classList.contains(INPUT_FOCUS_CSS_CLASS)).toBeTruthy();
- component.onFilesDropped.subscribe(files => {
- expect(files).toEqual([file]);
- expect(component.getInputFocus()).toBe(false);
- done();
- });
-
- component.onDropFiles(fakeEvent);
+ raiseEvent('dragleave');
+ expect(testContainer.classList.contains(INPUT_FOCUS_CSS_CLASS)).toBeFalsy();
});
- it('should emit onFilesDropped event when a file is dragged with Chrome', (done) => {
- let file = {name: 'fake-name-2', size: 10, webkitRelativePath: 'fake-folder1/fake-name-2.json'};
- let fakeEvent = {
- dataTransfer: {
- items: [''],
- files: [file]
- },
- stopPropagation: jasmine.createSpy('stopPropagation'),
- preventDefault: jasmine.createSpy('preventDefault')
- };
+ it('should remove focus style after [drop] of files', () => {
+ raiseEvent('dragover');
+ expect(testContainer.classList.contains(INPUT_FOCUS_CSS_CLASS)).toBeTruthy();
- component.onFilesDropped.subscribe(files => {
- expect(files).toEqual([file]);
- expect(component.getInputFocus()).toBe(false);
- done();
- });
-
- component.onDropFiles(fakeEvent);
+ raiseEvent('drop');
+ expect(testContainer.classList.contains(INPUT_FOCUS_CSS_CLASS)).toBeFalsy();
});
- it('should take the focus when the drag enter is called', () => {
- let mockEvent = new Event('dragstart');
- spyOn(mockEvent, 'preventDefault');
+ it('should add focus style on [dragover] only if not already handled', () => {
+ const dragEvent = createEvent('dragover');
+ dragEvent.preventDefault();
- expect(component.getInputFocus()).toBe(false);
- component.onDragEnter(mockEvent);
- expect(component.getInputFocus()).toBe(true);
+ testContainer.dispatchEvent(dragEvent);
+ expect(testContainer.classList.contains(INPUT_FOCUS_CSS_CLASS)).toBeFalsy();
+ });
+
+ it('should prevent [drop] event propagation after handling', () => {
+ const dragEvent = createEvent('drop');
+ expect(dragEvent.defaultPrevented).toBeFalsy();
+
+ testContainer.dispatchEvent(dragEvent);
+ expect(dragEvent.defaultPrevented).toBeTruthy();
+ });
+
+ it('should not prevent [drop] event propagation if component is disabled', () => {
+ component.directive.enabled = false;
+
+ const dragEvent = createEvent('drop');
+ expect(dragEvent.defaultPrevented).toBeFalsy();
+
+ testContainer.dispatchEvent(dragEvent);
+ expect(dragEvent.defaultPrevented).toBeFalsy();
+ });
+
+ it('should prevent [dragenter] event propagation after handling', () => {
+ const dragEvent = createEvent('dragenter');
+ expect(dragEvent.defaultPrevented).toBeFalsy();
+
+ testContainer.dispatchEvent(dragEvent);
+ expect(dragEvent.defaultPrevented).toBeTruthy();
+ });
+
+ it('should not prevent [dragenter] event propagation if component is disabled', () => {
+ component.directive.enabled = false;
+
+ const dragEvent = createEvent('dragenter');
+ expect(dragEvent.defaultPrevented).toBeFalsy();
+
+ testContainer.dispatchEvent(dragEvent);
+ expect(dragEvent.defaultPrevented).toBeFalsy();
+ });
+
+ it('should prevent [dragleave] event propagation after hanlding', () => {
+ const dragEvent = createEvent('dragleave');
+ expect(dragEvent.defaultPrevented).toBeFalsy();
+
+ testContainer.dispatchEvent(dragEvent);
+ expect(dragEvent.defaultPrevented).toBeTruthy();
+ });
+
+ it('should not prevent [dragleave] event propagation if component is disabled', () => {
+ component.directive.enabled = false;
+
+ const dragEvent = createEvent('dragleave');
+ expect(dragEvent.defaultPrevented).toBeFalsy();
+
+ testContainer.dispatchEvent(dragEvent);
+ expect(dragEvent.defaultPrevented).toBeFalsy();
+ });
+
+ it('should prevent [dragover] event propagation after handling', () => {
+ const dragEvent = createEvent('dragover');
+ expect(dragEvent.defaultPrevented).toBeFalsy();
+
+ testContainer.dispatchEvent(dragEvent);
+ expect(dragEvent.defaultPrevented).toBeTruthy();
+ });
+
+ it('should not prevent [dragover] event propagation if component is disabled', () => {
+ component.directive.enabled = false;
+
+ const dragEvent = createEvent('dragover');
+ expect(dragEvent.defaultPrevented).toBeFalsy();
+
+ testContainer.dispatchEvent(dragEvent);
+ expect(dragEvent.defaultPrevented).toBeFalsy();
});
- */
});
diff --git a/lib/content-services/src/lib/upload/directives/file-draggable.directive.ts b/lib/content-services/src/lib/upload/directives/file-draggable.directive.ts
index f9db3e9c03..ea5e81de74 100644
--- a/lib/content-services/src/lib/upload/directives/file-draggable.directive.ts
+++ b/lib/content-services/src/lib/upload/directives/file-draggable.directive.ts
@@ -20,6 +20,9 @@
import { FileUtils } from '@alfresco/adf-core';
import { Directive, ElementRef, EventEmitter, Input, NgZone, OnDestroy, OnInit, Output } from '@angular/core';
+export const INPUT_FOCUS_CSS_CLASS = 'adf-file-draggable-input-focus';
+export const DROP_EFFECT = 'copy';
+
@Directive({
selector: '[adf-file-draggable]'
})
@@ -39,7 +42,6 @@ export class FileDraggableDirective implements OnInit, OnDestroy {
@Output()
folderEntityDropped = new EventEmitter();
- private cssClassName = 'adf-file-draggable__input-focus';
private element: HTMLElement;
constructor(el: ElementRef, private ngZone: NgZone) {
@@ -71,7 +73,7 @@ export class FileDraggableDirective implements OnInit, OnDestroy {
this.preventDefault(event);
// Chrome, Edge, Firefox, Opera (Files + Folders)
- const items = event.dataTransfer.items;
+ const items = event.dataTransfer?.items;
if (items) {
const files: File[] = [];
@@ -95,13 +97,13 @@ export class FileDraggableDirective implements OnInit, OnDestroy {
if (files.length > 0) {
this.filesDropped.emit(files);
}
- } else {
+ } else if (event.dataTransfer?.files) {
// IE, Safari, Chrome, Edge, Firefox, Opera (Files only)
const files = FileUtils.toFileArray(event.dataTransfer.files);
this.filesDropped.emit(files);
}
- this.element.classList.remove(this.cssClassName);
+ this.element.classList.remove(INPUT_FOCUS_CSS_CLASS);
}
}
@@ -113,8 +115,12 @@ export class FileDraggableDirective implements OnInit, OnDestroy {
onDragEnter(event: DragEvent): void {
if (this.enabled && !event.defaultPrevented) {
this.preventDefault(event);
- event.dataTransfer.dropEffect = 'copy';
- this.element.classList.add(this.cssClassName);
+
+ if (event.dataTransfer) {
+ event.dataTransfer.dropEffect = DROP_EFFECT;
+ }
+
+ this.element.classList.add(INPUT_FOCUS_CSS_CLASS);
}
}
@@ -126,7 +132,7 @@ export class FileDraggableDirective implements OnInit, OnDestroy {
onDragLeave(event: Event): void {
if (this.enabled && !event.defaultPrevented) {
this.preventDefault(event);
- this.element.classList.remove(this.cssClassName);
+ this.element.classList.remove(INPUT_FOCUS_CSS_CLASS);
}
}
@@ -138,8 +144,12 @@ export class FileDraggableDirective implements OnInit, OnDestroy {
onDragOver(event: DragEvent): void {
if (this.enabled && !event.defaultPrevented) {
this.preventDefault(event);
- event.dataTransfer.dropEffect = 'copy';
- this.element.classList.add(this.cssClassName);
+
+ if (event.dataTransfer) {
+ event.dataTransfer.dropEffect = DROP_EFFECT;
+ }
+
+ this.element.classList.add(INPUT_FOCUS_CSS_CLASS);
}
}