Skip to content

Commit

Permalink
System test for dropping a file (#939)
Browse files Browse the repository at this point in the history
* Support DataTransfer without system file

* Build

* Add dnd system test
  • Loading branch information
mbraak authored Oct 11, 2024
1 parent 3ddbddc commit 449f7d2
Show file tree
Hide file tree
Showing 7 changed files with 1,349 additions and 1,259 deletions.
2,495 changes: 1,256 additions & 1,239 deletions django_file_form/static/file_form/file_form.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion django_file_form/static/file_form/file_form.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions django_file_form/static/file_form/file_form.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion django_file_form/static/file_form/file_form.min.js.map

Large diffs are not rendered by default.

58 changes: 42 additions & 16 deletions frontend/src/drop_area.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const getEntriesFromDirectory = async (
directoryEntry.createReader().readEntries(resolve, reject);
});

const getFileFromFileEntry = async (
const getFileFromFileSystemFileEntry = async (
fileEntry: FileSystemFileEntry
): Promise<File> =>
new Promise((resolve, reject) => {
Expand All @@ -18,19 +18,32 @@ const getFileFromFileEntry = async (
const getFilesFromFileSystemEntries = async (
entries: FileSystemEntry[]
): Promise<File[]> => {
const result = [];
const result: File[] = [];

for (const entry of entries) {
if (entry.isFile) {
const file = await getFileFromFileEntry(entry as FileSystemFileEntry);
result.push(file);
} else if (entry.isDirectory) {
const entriesFromDirectory = await getEntriesFromDirectory(
entry as FileSystemDirectoryEntry
);
const files = await getFilesFromFileSystemEntries(entriesFromDirectory);
files.forEach(file => result.push(file));
}
const filesFromEntry = await getFilesFromFileSystemEntry(entry);
filesFromEntry.forEach(file => result.push(file));
}

return result;
};

const getFilesFromFileSystemEntry = async (
entry: FileSystemEntry
): Promise<File[]> => {
const result: File[] = [];

if (entry.isFile) {
const file = await getFileFromFileSystemFileEntry(
entry as FileSystemFileEntry
);
result.push(file);
} else if (entry.isDirectory) {
const entriesFromDirectory = await getEntriesFromDirectory(
entry as FileSystemDirectoryEntry
);
const files = await getFilesFromFileSystemEntries(entriesFromDirectory);
files.forEach(file => result.push(file));
}

return result;
Expand All @@ -41,11 +54,24 @@ const getFilesFromDataTransfer = async (
): Promise<File[]> => {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (dataTransfer.items) {
const entries = [...dataTransfer.items]
.map(item => item.webkitGetAsEntry())
.filter(entry => entry != null);
const files: File[] = [];

for (const item of dataTransfer.items) {
const fileSystemEntry = item.webkitGetAsEntry();
if (fileSystemEntry) {
const filesFromEntry = await getFilesFromFileSystemEntry(
fileSystemEntry
);
filesFromEntry.forEach(file => files.push(file));
} else {
const file = item.getAsFile();

if (file) {
files.push(file);
}
}
}

const files = await getFilesFromFileSystemEntries(entries);
return files;
} else {
// backwards compatibility
Expand Down
12 changes: 12 additions & 0 deletions testproject/django_file_form_example/tests/live/test_with_ajax.py
Original file line number Diff line number Diff line change
Expand Up @@ -947,3 +947,15 @@ def test_disabled_field(self):
self.assertTrue(file_input.get_attribute("disabled"))

self.assertEqual(len(page.find_elements_by_text("Drop your files here")), 0)

def test_drop_file(self):
page = self.page
temp_file = page.create_temp_file("content1")

page.open("/")
drop_area = page.selenium.find_element(By.CSS_SELECTOR, ".dff-files")
page.drop_file(drop_area, temp_file)

page.find_upload_success(temp_file)
page.assert_page_contains_text("8 Bytes")
self.assertEqual(TemporaryUploadedFile.objects.count(), 1)
35 changes: 35 additions & 0 deletions testproject/django_file_form_example/tests/utils/page.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,38 @@ def get_percentage(selenium):
WebDriverWait(self.selenium, timeout=10, poll_frequency=0.1).until(
lambda selenium: get_percentage(selenium) > 5
)

def drop_file(self, drop_area, temp_file):
ATTACH_FILE = """
var input = document.createElement('INPUT');
input.type = "file";
input.id = "_capybara_drop_file";
input.multiple = true;
document.body.appendChild(input);
return input;
"""

DROP_FILE = """
var el = arguments[0],
input = arguments[1],
files = input.files,
dt = new DataTransfer(),
opts = { cancelable: true, bubbles: true, dataTransfer: dt };
input.parentElement.removeChild(input);
if (dt.items){
for (var i=0; i<files.length; i++){
dt.items.add(files[i]);
}
} else {
Object.defineProperty(dt, "files", {
value: files,
writable: false
});
}
var dropEvent = new DragEvent('drop', opts);
el.dispatchEvent(dropEvent);
"""

input_element = self.selenium.execute_script(ATTACH_FILE)
input_element.send_keys(temp_file.path())
self.selenium.execute_script(DROP_FILE, drop_area, input_element)

0 comments on commit 449f7d2

Please sign in to comment.