2424)
2525from grandchallenge .components .form_fields import INTERFACE_FORM_FIELD_PREFIX
2626from grandchallenge .components .models import (
27- ComponentInterface ,
2827 ComponentJob ,
2928 ImportStatusChoices ,
3029 InterfaceKindChoices ,
@@ -203,120 +202,164 @@ def try_create_algorithm():
203202
204203@pytest .mark .django_db
205204@pytest .mark .parametrize (
206- "slug , content_parts" ,
205+ "socket_kwargs , content_parts" ,
207206 (
208207 (
209- "generic-overlay" ,
208+ {
209+ "kind" : InterfaceKindChoices .PANIMG_HEAT_MAP ,
210+ "title" : "some-overlay" ,
211+ },
210212 [
211213 '<select class="custom-select"' ,
212- f'name="widget-choice-{ INTERFACE_FORM_FIELD_PREFIX } generic -overlay"' ,
214+ f'name="widget-choice-{ INTERFACE_FORM_FIELD_PREFIX } some -overlay"' ,
213215 ],
214216 ),
215217 (
216- "generic-medical-image" ,
218+ {
219+ "kind" : InterfaceKindChoices .PANIMG_IMAGE ,
220+ "title" : "some-medical-image" ,
221+ },
217222 [
218223 '<select class="custom-select"' ,
219- f'name="widget-choice-{ INTERFACE_FORM_FIELD_PREFIX } generic -medical-image"' ,
224+ f'name="widget-choice-{ INTERFACE_FORM_FIELD_PREFIX } some -medical-image"' ,
220225 ],
221226 ),
222227 (
223- "boolean" ,
228+ {
229+ "kind" : InterfaceKindChoices .BOOL ,
230+ "title" : "boolean" ,
231+ },
224232 [
225233 '<input type="checkbox"' ,
226234 f'name="{ INTERFACE_FORM_FIELD_PREFIX } boolean"' ,
227235 ],
228236 ),
229237 (
230- "string" ,
238+ {
239+ "kind" : InterfaceKindChoices .STRING ,
240+ "title" : "string" ,
241+ },
231242 [
232243 '<input type="text"' ,
233244 f'name="{ INTERFACE_FORM_FIELD_PREFIX } string"' ,
234245 ],
235246 ),
236247 (
237- "integer" ,
248+ {
249+ "kind" : InterfaceKindChoices .INTEGER ,
250+ "title" : "integer" ,
251+ },
238252 [
239253 '<input type="number"' ,
240254 f'name="{ INTERFACE_FORM_FIELD_PREFIX } integer"' ,
241255 ],
242256 ),
243257 (
244- "float" ,
258+ {
259+ "kind" : InterfaceKindChoices .FLOAT ,
260+ "title" : "float" ,
261+ },
245262 [
246263 '<input type="number"' ,
247264 f'name="{ INTERFACE_FORM_FIELD_PREFIX } float"' ,
248265 'step="any"' ,
249266 ],
250267 ),
251268 (
252- "2d-bounding-box" ,
269+ {
270+ "kind" : InterfaceKindChoices .TWO_D_BOUNDING_BOX ,
271+ "title" : "2d-bounding-box" ,
272+ },
253273 [
254274 'class="jsoneditorwidget ' ,
255275 f'<div id="jsoneditor_id_{ INTERFACE_FORM_FIELD_PREFIX } 2d-bounding-box"' ,
256276 ],
257277 ),
258278 (
259- "multiple-2d-bounding-boxes" ,
279+ {
280+ "kind" : InterfaceKindChoices .MULTIPLE_TWO_D_BOUNDING_BOXES ,
281+ "title" : "multiple-2d-bounding-boxes" ,
282+ },
260283 [
261284 'class="jsoneditorwidget ' ,
262285 f'<div id="jsoneditor_id_{ INTERFACE_FORM_FIELD_PREFIX } multiple-2d-bounding-boxes"' ,
263286 ],
264287 ),
265288 (
266- "distance-measurement" ,
289+ {
290+ "kind" : InterfaceKindChoices .DISTANCE_MEASUREMENT ,
291+ "title" : "distance-measurement" ,
292+ },
267293 [
268294 'class="jsoneditorwidget ' ,
269295 f'<div id="jsoneditor_id_{ INTERFACE_FORM_FIELD_PREFIX } distance-measurement"' ,
270296 ],
271297 ),
272298 (
273- "multiple-distance-measurements" ,
299+ {
300+ "kind" : InterfaceKindChoices .MULTIPLE_DISTANCE_MEASUREMENTS ,
301+ "title" : "multiple-distance-measurements" ,
302+ },
274303 [
275304 'class="jsoneditorwidget ' ,
276305 f'<div id="jsoneditor_id_{ INTERFACE_FORM_FIELD_PREFIX } multiple-distance-measurements"' ,
277306 ],
278307 ),
279308 (
280- "point" ,
309+ {
310+ "kind" : InterfaceKindChoices .POINT ,
311+ "title" : "point" ,
312+ },
281313 [
282314 'class="jsoneditorwidget ' ,
283315 f'<div id="jsoneditor_id_{ INTERFACE_FORM_FIELD_PREFIX } point"' ,
284316 ],
285317 ),
286318 (
287- "multiple-points" ,
319+ {
320+ "kind" : InterfaceKindChoices .MULTIPLE_POINTS ,
321+ "title" : "multiple-points" ,
322+ },
288323 [
289324 'class="jsoneditorwidget ' ,
290325 f'<div id="jsoneditor_id_{ INTERFACE_FORM_FIELD_PREFIX } multiple-points"' ,
291326 ],
292327 ),
293328 (
294- "polygon" ,
329+ {
330+ "kind" : InterfaceKindChoices .POLYGON ,
331+ "title" : "polygon" ,
332+ },
295333 [
296334 'class="jsoneditorwidget ' ,
297335 f'<div id="jsoneditor_id_{ INTERFACE_FORM_FIELD_PREFIX } polygon"' ,
298336 ],
299337 ),
300338 (
301- "multiple-polygons" ,
339+ {
340+ "kind" : InterfaceKindChoices .MULTIPLE_POLYGONS ,
341+ "title" : "multiple-polygons" ,
342+ },
302343 [
303344 'class="jsoneditorwidget ' ,
304345 f'<div id="jsoneditor_id_{ INTERFACE_FORM_FIELD_PREFIX } multiple-polygons"' ,
305346 ],
306347 ),
307348 (
308- "anything" ,
349+ {
350+ "kind" : InterfaceKindChoices .ANY ,
351+ "title" : "anything" ,
352+ "store_in_database" : False ,
353+ },
309354 [
310355 '<select class="custom-select"' ,
311356 f'name="widget-choice-{ INTERFACE_FORM_FIELD_PREFIX } anything"' ,
312357 ],
313358 ),
314359 ),
315360)
316- def test_create_job_input_fields (
317- client , component_interfaces , slug , content_parts
318- ):
319- alg , creator = create_algorithm_with_input (slug )
361+ def test_create_job_input_fields (client , socket_kwargs , content_parts ):
362+ alg , creator , _ = create_algorithm_with_input (** socket_kwargs )
320363
321364 response = get_view_for_user (
322365 viewname = "algorithms:job-create" ,
@@ -336,56 +379,17 @@ def test_create_job_input_fields(
336379
337380@pytest .mark .django_db
338381@pytest .mark .parametrize (
339- "slug " ,
382+ "socket_kwargs " ,
340383 [
341- "2d-bounding-box" ,
342- "multiple-2d-bounding-boxes" ,
343- "distance-measurement" ,
344- "multiple-distance-measurements" ,
345- "point" ,
346- "multiple-points" ,
347- "polygon" ,
348- "multiple-polygons" ,
349- ],
350- )
351- def test_create_job_json_input_field_validation (
352- client , component_interfaces , slug
353- ):
354- alg , creator = create_algorithm_with_input (slug )
355-
356- response = get_view_for_user (
357- viewname = "algorithms:job-create" ,
358- client = client ,
359- reverse_kwargs = {
360- "slug" : alg .slug ,
361- "interface_pk" : alg .interfaces .first ().pk ,
362- },
363- method = client .post ,
364- follow = True ,
365- user = creator ,
366- )
367- assert response .context ["form" ].errors == {
368- f"{ INTERFACE_FORM_FIELD_PREFIX } { slug } " : ["This field is required." ],
369- }
370-
371-
372- @pytest .mark .django_db
373- @pytest .mark .parametrize (
374- "slug, content_parts" ,
375- (
376- (
377- "generic-overlay" ,
378- ['class="invalid-feedback"' , "This field is required." ],
379- ),
380- ("string" , ['class="invalid-feedback"' , "This field is required." ]),
381- ("integer" , ['class="invalid-feedback"' , "This field is required." ]),
382- ("float" , ['class="invalid-feedback"' , "This field is required." ]),
383- ),
384+ {"kind" : choice }
385+ for choice in set (InterfaceKindChoices ).difference (
386+ {InterfaceKindChoices .BOOL , InterfaceKindChoices .ANY }
387+ )
388+ ]
389+ + [{"kind" : InterfaceKindChoices .ANY , "store_in_database" : False }],
384390)
385- def test_create_job_simple_input_field_validation (
386- client , component_interfaces , slug , content_parts
387- ):
388- alg , creator = create_algorithm_with_input (slug )
391+ def test_create_job_input_field_required_validation (client , socket_kwargs ):
392+ alg , creator , input_socket = create_algorithm_with_input (** socket_kwargs )
389393
390394 response = get_view_for_user (
391395 viewname = "algorithms:job-create" ,
@@ -400,17 +404,21 @@ def test_create_job_simple_input_field_validation(
400404 )
401405
402406 assert response .status_code == 200
403- for c in content_parts :
404- assert c in response .rendered_content
407+ assert response .context ["form" ].errors == {
408+ f"{ INTERFACE_FORM_FIELD_PREFIX } { input_socket .slug } " : [
409+ "This field is required."
410+ ],
411+ }
405412
406413
407- def create_algorithm_with_input (slug ):
414+ def create_algorithm_with_input (** kwargs ):
408415 creator = get_algorithm_creator ()
409416 VerificationFactory (user = creator , is_verified = True )
410417 alg = AlgorithmFactory ()
411418 alg .add_editor (user = creator )
419+ input_socket = ComponentInterfaceFactory (** kwargs )
412420 interface = AlgorithmInterfaceFactory (
413- inputs = [ComponentInterface . objects . get ( slug = slug ) ],
421+ inputs = [input_socket ],
414422 outputs = [ComponentInterfaceFactory ()],
415423 )
416424 alg .interfaces .add (interface )
@@ -420,7 +428,7 @@ def create_algorithm_with_input(slug):
420428 is_in_registry = True ,
421429 is_desired_version = True ,
422430 )
423- return alg , creator
431+ return alg , creator , input_socket
424432
425433
426434@pytest .mark .django_db
@@ -515,7 +523,7 @@ def test_only_publish_successful_jobs():
515523class TestJobCreateLimits :
516524
517525 def create_form (self , algorithm , user , algorithm_image = None ):
518- ci = ComponentInterfaceFactory (kind = ComponentInterface . Kind .STRING )
526+ ci = ComponentInterfaceFactory (kind = InterfaceKindChoices .STRING )
519527 interface = AlgorithmInterfaceFactory (inputs = [ci ])
520528 algorithm .interfaces .add (interface )
521529
0 commit comments