Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit abbb812

Browse files
Split selenium tests into separate CI job
1 parent 92fec2c commit abbb812

File tree

6 files changed

+81
-10
lines changed

6 files changed

+81
-10
lines changed

‎.github/workflows/ci.yml‎

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,36 @@ jobs:
9292
9393
- run: python -m pip install .[test] codecov
9494
- run: python -m pip install django~=${{ matrix.django-version }}.0
95-
- run: python -m pytest
95+
- run: python -m pytest -m "not selenium"
9696
env:
9797
PATH: $PATH:$(pwd)/bin
9898
- run: codecov
9999

100+
selenium:
101+
needs:
102+
- pytest
103+
strategy:
104+
matrix:
105+
python-version:
106+
- "3.x"
107+
runs-on: ubuntu-latest
108+
steps:
109+
- uses: actions/checkout@v3
110+
- name: Install Chrome
111+
run: sudo apt-get install -y google-chrome-stable
112+
- name: Install Selenium
113+
run: |
114+
mkdir bin
115+
curl -O https://chromedriver.storage.googleapis.com/`curl -s https://chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip
116+
unzip chromedriver_linux64.zip -d bin
117+
- uses: actions/setup-python@v4
118+
with:
119+
python-version: ${{ matrix.python-version }}
120+
- run: python -m pip install -e .[test]
121+
- run: python -m pytest -m selenium
122+
- uses: codecov/codecov-action@v3
123+
124+
100125
analyze:
101126
name: CodeQL Analyze
102127
needs:

‎tests/conftest.py‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@
1010
from s3file.storages import get_aws_location
1111

1212

13+
def pytest_configure(config):
14+
config.addinivalue_line("markers", "selenium: skip if selenium is not installed")
15+
16+
1317
@pytest.fixture(scope="session")
1418
def driver():
1519
chrome_options = webdriver.ChromeOptions()
16-
chrome_options.headless=True
20+
chrome_options.add_argument("--headless=new")
1721
try:
1822
b = webdriver.Chrome(options=chrome_options)
1923
except WebDriverException as e:

‎tests/test_forms.py‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,15 @@ def test_accept(self):
135135
"application/pdf,image/*"
136136
)
137137

138+
@pytest.mark.selenium
138139
def test_no_js_error(self, driver, live_server):
139140
driver.get(live_server + self.url)
140141

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

146+
@pytest.mark.selenium
145147
def test_file_insert(
146148
self, request, driver, live_server, upload_file, freeze_upload_folder
147149
):
@@ -157,6 +159,7 @@ def test_file_insert(
157159
error = driver.find_element(By.XPATH, "//body[@JSError]")
158160
pytest.fail(error.get_attribute("JSError"))
159161

162+
@pytest.mark.selenium
160163
def test_file_insert_submit_value(
161164
self, driver, live_server, upload_file, freeze_upload_folder
162165
):
@@ -179,6 +182,7 @@ def test_file_insert_submit_value(
179182
assert "save_continue" in driver.page_source
180183
assert "continue_value" in driver.page_source
181184

185+
@pytest.mark.selenium
182186
def test_progress(self, driver, live_server, upload_file, freeze_upload_folder):
183187
driver.get(live_server + self.url)
184188
file_input = driver.find_element(By.XPATH, "//input[@name='file']")
@@ -199,6 +203,7 @@ def test_progress(self, driver, live_server, upload_file, freeze_upload_folder):
199203
response = json.loads(driver.find_elements(By.CSS_SELECTOR, "pre")[0].text)
200204
assert response["POST"]["progress"] == "1"
201205

206+
@pytest.mark.selenium
202207
def test_multi_file(
203208
self,
204209
driver,
@@ -208,7 +213,7 @@ def test_multi_file(
208213
another_upload_file,
209214
yet_another_upload_file,
210215
):
211-
driver.get(live_server + self.url)
216+
driver.get(live_server + reverse("upload-multi"))
212217
file_input = driver.find_element(By.XPATH, "//input[@name='file']")
213218
file_input.send_keys(
214219
" \n ".join(

‎tests/testapp/forms.py‎

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,32 @@
1010
) + forms.ClearableFileInput.__bases__
1111

1212

13-
class MultipleFileInput(forms.ClearableFileInput):
14-
allow_multiple_selected = True
15-
16-
1713
class UploadForm(forms.ModelForm):
1814
class Meta:
1915
model = FileModel
2016
fields = ("file", "other_file")
21-
widgets = {
22-
"file": MultipleFileInput(attrs={"multiple": True}),
23-
}
17+
18+
19+
class MultipleFileInput(forms.ClearableFileInput):
20+
allow_multiple_selected = True
21+
22+
23+
class MultipleFileField(forms.FileField):
24+
def __init__(self, *args, **kwargs):
25+
kwargs.setdefault("widget", MultipleFileInput())
26+
super().__init__(*args, **kwargs)
27+
28+
def clean(self, data, initial=None):
29+
single_file_clean = super().clean
30+
if isinstance(data, (list, tuple)):
31+
result = [single_file_clean(d, initial) for d in data]
32+
else:
33+
result = single_file_clean(data, initial)
34+
return result
35+
36+
37+
class MultiUploadForm(forms.Form):
38+
file = MultipleFileField(
39+
required=False, widget=MultipleFileInput(attrs={"multiple": True})
40+
)
41+
other_file = forms.FileField(required=False)

‎tests/testapp/urls.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@
77

88
urlpatterns = [
99
path("", views.ExampleFormView.as_view(), name="upload"),
10+
path("multi/", views.MultiExampleFormView.as_view(), name="upload-multi"),
1011
]

‎tests/testapp/views.py‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,21 @@ def form_valid(self, form):
2929
status=201,
3030
encoder=FileEncoder,
3131
)
32+
33+
34+
class MultiExampleFormView(generic.FormView):
35+
form_class = forms.MultiUploadForm
36+
template_name = "form.html"
37+
38+
def form_valid(self, form):
39+
return JsonResponse(
40+
{
41+
"POST": self.request.POST,
42+
"FILES": {
43+
"file": self.request.FILES.getlist("file"),
44+
"other_file": self.request.FILES.getlist("other_file"),
45+
},
46+
},
47+
status=201,
48+
encoder=FileEncoder,
49+
)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /