Skip to content

Fix #286 -- Narrow CSS selector to avoid mismatches #288

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions s3file/static/s3file/js/s3file.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@
window.uploading = 0
form.loaded = 0
form.total = 0
var inputs = Array.from(form.querySelectorAll('.s3file'))
var inputs = Array.from(form.querySelectorAll('input[type=file].s3file'))

inputs.forEach(function (input) {
var hiddenS3Input = document.createElement('input')
Expand All @@ -140,7 +140,7 @@
}

document.addEventListener('DOMContentLoaded', function () {
var forms = Array.from(document.querySelectorAll('.s3file')).map(function (input) {
var forms = Array.from(document.querySelectorAll('input[type=file].s3file')).map(function (input) {
return input.closest('form')
})
forms = new Set(forms)
Expand Down
62 changes: 39 additions & 23 deletions tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,17 @@
from contextlib import contextmanager

import pytest
from django.core.files.uploadedfile import SimpleUploadedFile
from django.forms import ClearableFileInput
from django.urls import reverse_lazy
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.expected_conditions import staleness_of
from selenium.webdriver.support.wait import WebDriverWait

from s3file.storages import storage
from tests.testapp.forms import UploadForm

try:
from django.urls import reverse
except ImportError:
# Django 1.8 support
from django.core.urlresolvers import reverse
from tests.testapp.forms import FileForm
from tests.testapp.models import FileModel


@contextmanager
Expand All @@ -27,15 +24,13 @@ def wait_for_page_load(driver, timeout=30):


class TestS3FileInput:
@property
def url(self):
return reverse("upload")
create_url = reverse_lazy("example-create")

def test_value_from_datadict(self, freeze_upload_folder, client, upload_file):
with open(upload_file) as f:
uploaded_file = storage.save(freeze_upload_folder / "test.jpg", f)
response = client.post(
reverse("upload"),
self.create_url,
{
"file": f"custom/location/{uploaded_file}",
"file-s3f-signature": "FxQXie3wnVnCUFqGzFZ8DCFKAXFA3bnQ8tE96U11o80",
Expand All @@ -46,31 +41,31 @@ def test_value_from_datadict(self, freeze_upload_folder, client, upload_file):
assert response.status_code == 201

def test_value_from_datadict_initial_data(self, filemodel):
form = UploadForm(instance=filemodel)
form = FileForm(instance=filemodel)
assert filemodel.file.name in form.as_p(), form.as_p()
assert not form.is_valid()

def test_file_does_not_exist_no_fallback(self, filemodel):
form = UploadForm(
form = FileForm(
data={"file": "foo.bar", "s3file": "file"},
instance=filemodel,
)
assert form.is_valid()
assert form.cleaned_data["file"] == filemodel.file

def test_initial_no_file_uploaded(self, filemodel):
form = UploadForm(data={"file": ""}, instance=filemodel)
form = FileForm(data={"file": ""}, instance=filemodel)
assert form.is_valid(), form.errors
assert not form.has_changed()
assert form.cleaned_data["file"] == filemodel.file

def test_initial_fallback(self, filemodel):
form = UploadForm(data={"file": ""}, instance=filemodel)
form = FileForm(data={"file": ""}, instance=filemodel)
assert form.is_valid()
assert form.cleaned_data["file"] == filemodel.file

def test_clear(self, filemodel):
form = UploadForm(data={"file-clear": "1"}, instance=filemodel)
form = FileForm(data={"file-clear": "1"}, instance=filemodel)
assert form.is_valid()
assert not form.cleaned_data["file"]

Expand Down Expand Up @@ -137,7 +132,7 @@ def test_accept(self):

@pytest.mark.selenium
def test_no_js_error(self, driver, live_server):
driver.get(live_server + self.url)
driver.get(live_server + self.create_url)

with pytest.raises(NoSuchElementException):
error = driver.find_element(By.XPATH, "//body[@JSError]")
Expand All @@ -147,7 +142,28 @@ def test_no_js_error(self, driver, live_server):
def test_file_insert(
self, request, driver, live_server, upload_file, freeze_upload_folder
):
driver.get(live_server + self.url)
driver.get(live_server + self.create_url)
file_input = driver.find_element(By.XPATH, "//input[@name='file']")
file_input.send_keys(upload_file)
assert file_input.get_attribute("name") == "file"
with wait_for_page_load(driver, timeout=10):
file_input.submit()
assert storage.exists("tmp/s3file/%s.txt" % request.node.name)

with pytest.raises(NoSuchElementException):
error = driver.find_element(By.XPATH, "//body[@JSError]")
pytest.fail(error.get_attribute("JSError"))

@pytest.mark.selenium
def test_file_update(
self, request, driver, live_server, upload_file, freeze_upload_folder
):
FileModel.objects.create(
file=SimpleUploadedFile(
f"{request.node.name}.txt", request.node.name.encode()
)
)
driver.get(live_server + reverse_lazy("example-update", kwargs={"pk": 1}))
file_input = driver.find_element(By.XPATH, "//input[@name='file']")
file_input.send_keys(upload_file)
assert file_input.get_attribute("name") == "file"
Expand All @@ -163,7 +179,7 @@ def test_file_insert(
def test_file_insert_submit_value(
self, driver, live_server, upload_file, freeze_upload_folder
):
driver.get(live_server + self.url)
driver.get(live_server + self.create_url)
file_input = driver.find_element(By.XPATH, "//input[@name='file']")
file_input.send_keys(upload_file)
assert file_input.get_attribute("name") == "file"
Expand All @@ -172,7 +188,7 @@ def test_file_insert_submit_value(
save_button.click()
assert "save" in driver.page_source

driver.get(live_server + self.url)
driver.get(live_server + self.create_url)
file_input = driver.find_element(By.XPATH, "//input[@name='file']")
file_input.send_keys(upload_file)
assert file_input.get_attribute("name") == "file"
Expand All @@ -184,7 +200,7 @@ def test_file_insert_submit_value(

@pytest.mark.selenium
def test_progress(self, driver, live_server, upload_file, freeze_upload_folder):
driver.get(live_server + self.url)
driver.get(live_server + self.create_url)
file_input = driver.find_element(By.XPATH, "//input[@name='file']")
file_input.send_keys(upload_file)
assert file_input.get_attribute("name") == "file"
Expand All @@ -193,7 +209,7 @@ def test_progress(self, driver, live_server, upload_file, freeze_upload_folder):
save_button.click()
assert "save" in driver.page_source

driver.get(live_server + self.url)
driver.get(live_server + self.create_url)
file_input = driver.find_element(By.XPATH, "//input[@name='file']")
file_input.send_keys(upload_file)
assert file_input.get_attribute("name") == "file"
Expand All @@ -213,7 +229,7 @@ def test_multi_file(
another_upload_file,
yet_another_upload_file,
):
driver.get(live_server + reverse("upload-multi"))
driver.get(live_server + reverse_lazy("upload-multi"))
file_input = driver.find_element(By.XPATH, "//input[@name='file']")
file_input.send_keys(
" \n ".join(
Expand Down
6 changes: 5 additions & 1 deletion tests/testapp/forms.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django import forms
from django.contrib.admin.widgets import AdminFileWidget

from s3file.forms import S3FileInputMixin

Expand All @@ -10,10 +11,13 @@
) + forms.ClearableFileInput.__bases__


class UploadForm(forms.ModelForm):
class FileForm(forms.ModelForm):
class Meta:
model = FileModel
fields = ("file", "other_file")
widgets = {
"file": AdminFileWidget,
}


class MultipleFileInput(forms.ClearableFileInput):
Expand Down
8 changes: 8 additions & 0 deletions tests/testapp/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"django.contrib.admin",
"storages",
"s3file",
"tests.testapp",
Expand All @@ -41,6 +43,12 @@
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]

Expand Down
18 changes: 16 additions & 2 deletions tests/testapp/urls.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
try:
from django.urls import path
from django.urls import include, path
except ImportError:
from django.conf.urls import url as path

from . import views

urlpatterns = [
path("", views.ExampleFormView.as_view(), name="upload"),
path(
"example/",
include(
[
path(
"create", views.ExampleCreateView.as_view(), name="example-create"
),
path(
"<int:pk>/update",
views.ExampleUpdateView.as_view(),
name="example-update",
),
]
),
),
path("multi/", views.MultiExampleFormView.as_view(), name="upload-multi"),
]
26 changes: 23 additions & 3 deletions tests/testapp/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from django.http import JsonResponse
from django.views import generic

from tests.testapp import forms
from . import forms, models


class FileEncoder(DjangoJSONEncoder):
Expand All @@ -13,8 +13,28 @@ def default(self, o):
return super().default(o)


class ExampleFormView(generic.FormView):
form_class = forms.UploadForm
class ExampleCreateView(generic.CreateView):
model = models.FileModel
fields = ["file", "other_file"]
template_name = "form.html"

def form_valid(self, form):
return JsonResponse(
{
"POST": self.request.POST,
"FILES": {
"file": self.request.FILES.getlist("file"),
"other_file": self.request.FILES.getlist("other_file"),
},
},
status=201,
encoder=FileEncoder,
)


class ExampleUpdateView(generic.UpdateView):
model = models.FileModel
form_class = forms.FileForm
template_name = "form.html"

def form_valid(self, form):
Expand Down