Skip to content

Commit 06070a8

Browse files
committed
Fix #286 -- Narrow CSS selector to avoid mismatches
See also: https://code.djangoproject.com/ticket/35273
1 parent bdb771a commit 06070a8

File tree

6 files changed

+93
-31
lines changed

6 files changed

+93
-31
lines changed

s3file/static/s3file/js/s3file.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@
118118
window.uploading = 0
119119
form.loaded = 0
120120
form.total = 0
121-
var inputs = Array.from(form.querySelectorAll('.s3file'))
121+
var inputs = Array.from(form.querySelectorAll('input[type=file].s3file'))
122122

123123
inputs.forEach(function (input) {
124124
var hiddenS3Input = document.createElement('input')
@@ -140,7 +140,7 @@
140140
}
141141

142142
document.addEventListener('DOMContentLoaded', function () {
143-
var forms = Array.from(document.querySelectorAll('.s3file')).map(function (input) {
143+
var forms = Array.from(document.querySelectorAll('input[type=file].s3file')).map(function (input) {
144144
return input.closest('form')
145145
})
146146
forms = new Set(forms)

tests/test_forms.py

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,17 @@
33
from contextlib import contextmanager
44

55
import pytest
6+
from django.core.files.uploadedfile import SimpleUploadedFile
67
from django.forms import ClearableFileInput
8+
from django.urls import reverse_lazy
79
from selenium.common.exceptions import NoSuchElementException
810
from selenium.webdriver.common.by import By
911
from selenium.webdriver.support.expected_conditions import staleness_of
1012
from selenium.webdriver.support.wait import WebDriverWait
1113

1214
from s3file.storages import storage
13-
from tests.testapp.forms import UploadForm
14-
15-
try:
16-
from django.urls import reverse
17-
except ImportError:
18-
# Django 1.8 support
19-
from django.core.urlresolvers import reverse
15+
from tests.testapp.forms import FileForm
16+
from tests.testapp.models import FileModel
2017

2118

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

2825

2926
class TestS3FileInput:
30-
@property
31-
def url(self):
32-
return reverse("upload")
27+
create_url = reverse_lazy("example-create")
3328

3429
def test_value_from_datadict(self, freeze_upload_folder, client, upload_file):
3530
with open(upload_file) as f:
3631
uploaded_file = storage.save(freeze_upload_folder / "test.jpg", f)
3732
response = client.post(
38-
reverse("upload"),
33+
self.create_url,
3934
{
4035
"file": f"custom/location/{uploaded_file}",
4136
"file-s3f-signature": "FxQXie3wnVnCUFqGzFZ8DCFKAXFA3bnQ8tE96U11o80",
@@ -46,31 +41,31 @@ def test_value_from_datadict(self, freeze_upload_folder, client, upload_file):
4641
assert response.status_code == 201
4742

4843
def test_value_from_datadict_initial_data(self, filemodel):
49-
form = UploadForm(instance=filemodel)
44+
form = FileForm(instance=filemodel)
5045
assert filemodel.file.name in form.as_p(), form.as_p()
5146
assert not form.is_valid()
5247

5348
def test_file_does_not_exist_no_fallback(self, filemodel):
54-
form = UploadForm(
49+
form = FileForm(
5550
data={"file": "foo.bar", "s3file": "file"},
5651
instance=filemodel,
5752
)
5853
assert form.is_valid()
5954
assert form.cleaned_data["file"] == filemodel.file
6055

6156
def test_initial_no_file_uploaded(self, filemodel):
62-
form = UploadForm(data={"file": ""}, instance=filemodel)
57+
form = FileForm(data={"file": ""}, instance=filemodel)
6358
assert form.is_valid(), form.errors
6459
assert not form.has_changed()
6560
assert form.cleaned_data["file"] == filemodel.file
6661

6762
def test_initial_fallback(self, filemodel):
68-
form = UploadForm(data={"file": ""}, instance=filemodel)
63+
form = FileForm(data={"file": ""}, instance=filemodel)
6964
assert form.is_valid()
7065
assert form.cleaned_data["file"] == filemodel.file
7166

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

@@ -137,7 +132,7 @@ def test_accept(self):
137132

138133
@pytest.mark.selenium
139134
def test_no_js_error(self, driver, live_server):
140-
driver.get(live_server + self.url)
135+
driver.get(live_server + self.create_url)
141136

142137
with pytest.raises(NoSuchElementException):
143138
error = driver.find_element(By.XPATH, "//body[@JSError]")
@@ -147,7 +142,28 @@ def test_no_js_error(self, driver, live_server):
147142
def test_file_insert(
148143
self, request, driver, live_server, upload_file, freeze_upload_folder
149144
):
150-
driver.get(live_server + self.url)
145+
driver.get(live_server + self.create_url)
146+
file_input = driver.find_element(By.XPATH, "//input[@name='file']")
147+
file_input.send_keys(upload_file)
148+
assert file_input.get_attribute("name") == "file"
149+
with wait_for_page_load(driver, timeout=10):
150+
file_input.submit()
151+
assert storage.exists("tmp/s3file/%s.txt" % request.node.name)
152+
153+
with pytest.raises(NoSuchElementException):
154+
error = driver.find_element(By.XPATH, "//body[@JSError]")
155+
pytest.fail(error.get_attribute("JSError"))
156+
157+
@pytest.mark.selenium
158+
def test_file_update(
159+
self, request, driver, live_server, upload_file, freeze_upload_folder
160+
):
161+
FileModel.objects.create(
162+
file=SimpleUploadedFile(
163+
f"{request.node.name}.txt", request.node.name.encode()
164+
)
165+
)
166+
driver.get(live_server + reverse_lazy("example-update", kwargs={"pk": 1}))
151167
file_input = driver.find_element(By.XPATH, "//input[@name='file']")
152168
file_input.send_keys(upload_file)
153169
assert file_input.get_attribute("name") == "file"
@@ -163,7 +179,7 @@ def test_file_insert(
163179
def test_file_insert_submit_value(
164180
self, driver, live_server, upload_file, freeze_upload_folder
165181
):
166-
driver.get(live_server + self.url)
182+
driver.get(live_server + self.create_url)
167183
file_input = driver.find_element(By.XPATH, "//input[@name='file']")
168184
file_input.send_keys(upload_file)
169185
assert file_input.get_attribute("name") == "file"
@@ -172,7 +188,7 @@ def test_file_insert_submit_value(
172188
save_button.click()
173189
assert "save" in driver.page_source
174190

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

185201
@pytest.mark.selenium
186202
def test_progress(self, driver, live_server, upload_file, freeze_upload_folder):
187-
driver.get(live_server + self.url)
203+
driver.get(live_server + self.create_url)
188204
file_input = driver.find_element(By.XPATH, "//input[@name='file']")
189205
file_input.send_keys(upload_file)
190206
assert file_input.get_attribute("name") == "file"
@@ -193,7 +209,7 @@ def test_progress(self, driver, live_server, upload_file, freeze_upload_folder):
193209
save_button.click()
194210
assert "save" in driver.page_source
195211

196-
driver.get(live_server + self.url)
212+
driver.get(live_server + self.create_url)
197213
file_input = driver.find_element(By.XPATH, "//input[@name='file']")
198214
file_input.send_keys(upload_file)
199215
assert file_input.get_attribute("name") == "file"
@@ -213,7 +229,7 @@ def test_multi_file(
213229
another_upload_file,
214230
yet_another_upload_file,
215231
):
216-
driver.get(live_server + reverse("upload-multi"))
232+
driver.get(live_server + reverse_lazy("upload-multi"))
217233
file_input = driver.find_element(By.XPATH, "//input[@name='file']")
218234
file_input.send_keys(
219235
" \n ".join(

tests/testapp/forms.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from django import forms
2+
from django.contrib.admin.widgets import AdminFileWidget
23

34
from s3file.forms import S3FileInputMixin
45

@@ -10,10 +11,13 @@
1011
) + forms.ClearableFileInput.__bases__
1112

1213

13-
class UploadForm(forms.ModelForm):
14+
class FileForm(forms.ModelForm):
1415
class Meta:
1516
model = FileModel
1617
fields = ("file", "other_file")
18+
widgets = {
19+
"file": AdminFileWidget,
20+
}
1721

1822

1923
class MultipleFileInput(forms.ClearableFileInput):

tests/testapp/settings.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
"django.contrib.auth",
1717
"django.contrib.contenttypes",
1818
"django.contrib.sessions",
19+
"django.contrib.messages",
1920
"django.contrib.staticfiles",
21+
"django.contrib.admin",
2022
"storages",
2123
"s3file",
2224
"tests.testapp",
@@ -41,6 +43,12 @@
4143
{
4244
"BACKEND": "django.template.backends.django.DjangoTemplates",
4345
"APP_DIRS": True,
46+
"OPTIONS": {
47+
"context_processors": [
48+
"django.contrib.auth.context_processors.auth",
49+
"django.contrib.messages.context_processors.messages",
50+
],
51+
},
4452
},
4553
]
4654

tests/testapp/urls.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,25 @@
11
try:
2-
from django.urls import path
2+
from django.urls import include, path
33
except ImportError:
44
from django.conf.urls import url as path
55

66
from . import views
77

88
urlpatterns = [
9-
path("", views.ExampleFormView.as_view(), name="upload"),
9+
path(
10+
"example/",
11+
include(
12+
[
13+
path(
14+
"create", views.ExampleCreateView.as_view(), name="example-create"
15+
),
16+
path(
17+
"<int:pk>/update",
18+
views.ExampleUpdateView.as_view(),
19+
name="example-update",
20+
),
21+
]
22+
),
23+
),
1024
path("multi/", views.MultiExampleFormView.as_view(), name="upload-multi"),
1125
]

tests/testapp/views.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from django.http import JsonResponse
44
from django.views import generic
55

6-
from tests.testapp import forms
6+
from . import forms, models
77

88

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

1515

16-
class ExampleFormView(generic.FormView):
17-
form_class = forms.UploadForm
16+
class ExampleCreateView(generic.CreateView):
17+
model = models.FileModel
18+
fields = ["file", "other_file"]
19+
template_name = "form.html"
20+
21+
def form_valid(self, form):
22+
return JsonResponse(
23+
{
24+
"POST": self.request.POST,
25+
"FILES": {
26+
"file": self.request.FILES.getlist("file"),
27+
"other_file": self.request.FILES.getlist("other_file"),
28+
},
29+
},
30+
status=201,
31+
encoder=FileEncoder,
32+
)
33+
34+
35+
class ExampleUpdateView(generic.UpdateView):
36+
model = models.FileModel
37+
form_class = forms.FileForm
1838
template_name = "form.html"
1939

2040
def form_valid(self, form):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy