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

+2-2
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

+39-23
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

+5-1
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

+8
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

+16-2
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

+23-3
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)