/ tests_integration / tests / fields / test_create.py
test_create.py
  1  """Integration tests for the custom extra fields system."""
  2  
  3  import json
  4  from datetime import datetime, timezone
  5  
  6  import httpx
  7  import pytest
  8  
  9  from ..conftest import URL, assert_httpx_success, assert_lists_compatible
 10  
 11  
 12  def test_add_text_field():
 13      """Test adding a text field for spools."""
 14      result = httpx.post(
 15          f"{URL}/api/v1/field/spool/mytextfield",
 16          json={
 17              "name": "My text field",
 18              "field_type": "text",
 19              "default_value": json.dumps("Hello World"),
 20          },
 21      )
 22      assert_httpx_success(result)
 23  
 24      # Clean up
 25      result = httpx.delete(f"{URL}/api/v1/field/spool/mytextfield")
 26      assert_httpx_success(result)
 27  
 28  
 29  def test_add_text_field_filament():
 30      """Test adding a text field for filaments."""
 31      result = httpx.post(
 32          f"{URL}/api/v1/field/filament/mytextfield",
 33          json={
 34              "name": "My text field",
 35              "field_type": "text",
 36              "default_value": json.dumps("Hello World"),
 37          },
 38      )
 39      assert_httpx_success(result)
 40  
 41      # Clean up
 42      result = httpx.delete(f"{URL}/api/v1/field/filament/mytextfield")
 43      assert_httpx_success(result)
 44  
 45  
 46  def test_add_text_field_vendor():
 47      """Test adding a text field for vendors."""
 48      result = httpx.post(
 49          f"{URL}/api/v1/field/vendor/mytextfield",
 50          json={
 51              "name": "My text field",
 52              "field_type": "text",
 53              "default_value": json.dumps("Hello World"),
 54          },
 55      )
 56      assert_httpx_success(result)
 57  
 58      # Clean up
 59      result = httpx.delete(f"{URL}/api/v1/field/vendor/mytextfield")
 60      assert_httpx_success(result)
 61  
 62  
 63  def test_add_integer_field():
 64      """Test adding an integer field for spools."""
 65      result = httpx.post(
 66          f"{URL}/api/v1/field/spool/myintegerfield",
 67          json={
 68              "name": "My integer field",
 69              "unit": "mm",
 70              "field_type": "integer",
 71              "default_value": json.dumps(42),
 72          },
 73      )
 74      assert_httpx_success(result)
 75  
 76      # Clean up
 77      result = httpx.delete(f"{URL}/api/v1/field/spool/myintegerfield")
 78      assert_httpx_success(result)
 79  
 80  
 81  def test_add_integer_range_field():
 82      """Test adding an integer range field for spools."""
 83      result = httpx.post(
 84          f"{URL}/api/v1/field/spool/myintegerrangefield",
 85          json={
 86              "name": "My integer range field",
 87              "field_type": "integer_range",
 88              "default_value": json.dumps([0, 100]),
 89          },
 90      )
 91      assert_httpx_success(result)
 92  
 93      # Clean up
 94      result = httpx.delete(f"{URL}/api/v1/field/spool/myintegerrangefield")
 95      assert_httpx_success(result)
 96  
 97  
 98  def test_add_float_field():
 99      """Test adding a float field for spools."""
100      result = httpx.post(
101          f"{URL}/api/v1/field/spool/myfloatfield",
102          json={
103              "name": "My float field",
104              "field_type": "float",
105              "default_value": json.dumps(3.14),
106          },
107      )
108      assert_httpx_success(result)
109  
110      # Clean up
111      result = httpx.delete(f"{URL}/api/v1/field/spool/myfloatfield")
112      assert_httpx_success(result)
113  
114  
115  def test_add_float_range_field():
116      """Test adding a float range field for spools."""
117      result = httpx.post(
118          f"{URL}/api/v1/field/spool/myfloatrangefield",
119          json={
120              "name": "My float range field",
121              "field_type": "float_range",
122              "default_value": json.dumps([0.0, 1.0]),
123          },
124      )
125      assert_httpx_success(result)
126  
127      # Clean up
128      result = httpx.delete(f"{URL}/api/v1/field/spool/myfloatrangefield")
129      assert_httpx_success(result)
130  
131  
132  def test_add_datetime_field():
133      """Test adding a datetime field for spools."""
134      result = httpx.post(
135          f"{URL}/api/v1/field/spool/mydatetimefield",
136          json={
137              "name": "My datetime field",
138              "field_type": "datetime",
139              "default_value": json.dumps(datetime.now(timezone.utc).isoformat()),
140          },
141      )
142      assert_httpx_success(result)
143  
144      # Clean up
145      result = httpx.delete(f"{URL}/api/v1/field/spool/mydatetimefield")
146      assert_httpx_success(result)
147  
148  
149  def test_add_boolean_field():
150      """Test adding a boolean field for spools."""
151      result = httpx.post(
152          f"{URL}/api/v1/field/spool/mybooleanfield",
153          json={
154              "name": "My boolean field",
155              "field_type": "boolean",
156              "default_value": json.dumps(True),  # noqa: FBT003
157          },
158      )
159      assert_httpx_success(result)
160  
161      # Clean up
162      result = httpx.delete(f"{URL}/api/v1/field/spool/mybooleanfield")
163      assert_httpx_success(result)
164  
165  
166  @pytest.mark.parametrize(
167      "multi_choice",
168      [True, False],
169  )
170  def test_add_choice_field(multi_choice: bool):  # noqa: FBT001
171      """Test adding a choice field for spools."""
172      result = httpx.post(
173          f"{URL}/api/v1/field/spool/mychoicefield",
174          json={
175              "name": "My choice field",
176              "field_type": "choice",
177              "choices": ["foo", "bar", "baz"],
178              "default_value": json.dumps(["foo"]) if multi_choice else json.dumps("foo"),
179              "multi_choice": multi_choice,
180          },
181      )
182      assert_httpx_success(result)
183  
184      # Clean up
185      result = httpx.delete(f"{URL}/api/v1/field/spool/mychoicefield")
186      assert_httpx_success(result)
187  
188  
189  def test_add_text_field_invalid_data():
190      """Test adding a text field with invalid default value."""
191      result = httpx.post(
192          f"{URL}/api/v1/field/spool/mytextfield",
193          json={
194              "name": "My text field",
195              "field_type": "text",
196              "default_value": json.dumps(42),
197          },
198      )
199      assert result.status_code == 400
200      assert result.json()["message"] == "Default value is not valid: Value is not a string."
201  
202  
203  def test_add_choice_field_without_multi_choice():
204      """Test adding a choice field without multi_choice set."""
205      result = httpx.post(
206          f"{URL}/api/v1/field/spool/mychoicefield",
207          json={
208              "name": "My choice field",
209              "field_type": "choice",
210              "choices": ["foo", "bar", "baz"],
211              "default_value": json.dumps("foo"),
212          },
213      )
214      assert result.status_code == 400
215      assert result.json()["message"] == "Multi choice must be set for field type choice."
216  
217  
218  def test_add_choice_field_invalid_choices():
219      """Test adding a choice field with invalid choices."""
220      result = httpx.post(
221          f"{URL}/api/v1/field/spool/mychoicefield",
222          json={
223              "name": "My choice field",
224              "field_type": "choice",
225              "choices": ["foo", "bar", "baz", {"foo": "bar"}],
226              "default_value": json.dumps(["foo"]),
227              "multi_choice": True,
228          },
229      )
230      assert result.status_code == 422
231  
232  
233  def test_add_choice_field_invalid_default_value():
234      """Test adding a choice field with invalid default value."""
235      result = httpx.post(
236          f"{URL}/api/v1/field/spool/mychoicefield",
237          json={
238              "name": "My choice field",
239              "field_type": "choice",
240              "choices": ["foo", "bar", "baz"],
241              "default_value": json.dumps(42),
242              "multi_choice": False,
243          },
244      )
245      assert result.status_code == 400
246      assert result.json()["message"] == "Default value is not valid: Value is not a string."
247  
248  
249  def test_add_choice_field_no_choices():
250      """Test adding a choice field without choices set."""
251      result = httpx.post(
252          f"{URL}/api/v1/field/spool/mychoicefield",
253          json={
254              "name": "My choice field",
255              "field_type": "choice",
256              "default_value": json.dumps("foo"),
257              "multi_choice": True,
258          },
259      )
260      assert result.status_code == 400
261      assert result.json()["message"] == "Choices must be set for field type choice."
262  
263  
264  def test_update_existing_field():
265      """Test updating an existing field."""
266      result = httpx.post(
267          f"{URL}/api/v1/field/spool/mytextfield",
268          json={
269              "name": "My text field",
270              "field_type": "text",
271              "default_value": json.dumps("Hello World"),
272          },
273      )
274      assert_httpx_success(result)
275  
276      result = httpx.post(
277          f"{URL}/api/v1/field/spool/mytextfield",
278          json={
279              "name": "My text field",
280              "field_type": "text",
281              "default_value": json.dumps("Goodbye World"),
282          },
283      )
284      assert_httpx_success(result)
285  
286      # Verify that the default value was updated, and that it is still the only field
287      result = httpx.get(f"{URL}/api/v1/field/spool")
288      assert_httpx_success(result)
289      assert_lists_compatible(
290          result.json(),
291          [
292              {
293                  "name": "My text field",
294                  "key": "mytextfield",
295                  "field_type": "text",
296                  "default_value": json.dumps("Goodbye World"),
297              },
298          ],
299          sort_key="key",
300      )
301  
302      # Clean up
303      result = httpx.delete(f"{URL}/api/v1/field/spool/mytextfield")
304      assert_httpx_success(result)
305  
306  
307  def test_update_field_change_field_type():
308      """Test updating an existing field and changing the field type, should not be allowed."""
309      result = httpx.post(
310          f"{URL}/api/v1/field/spool/mytextfield",
311          json={
312              "name": "My text field",
313              "field_type": "text",
314              "default_value": json.dumps("Hello World"),
315          },
316      )
317      assert_httpx_success(result)
318  
319      result = httpx.post(
320          f"{URL}/api/v1/field/spool/mytextfield",
321          json={
322              "name": "My text field",
323              "field_type": "integer",
324              "default_value": json.dumps(42),
325          },
326      )
327      assert result.status_code == 400
328      assert result.json()["message"] == "Field type cannot be changed."
329  
330      # Clean up
331      result = httpx.delete(f"{URL}/api/v1/field/spool/mytextfield")
332      assert_httpx_success(result)
333  
334  
335  def test_update_field_add_choice():
336      """Test updating an existing field and adding a choice, should be allowed."""
337      result = httpx.post(
338          f"{URL}/api/v1/field/spool/mychoicefield",
339          json={
340              "name": "My choice field",
341              "field_type": "choice",
342              "choices": ["foo", "bar", "baz"],
343              "default_value": json.dumps(["foo"]),
344              "multi_choice": True,
345          },
346      )
347      assert_httpx_success(result)
348  
349      result = httpx.post(
350          f"{URL}/api/v1/field/spool/mychoicefield",
351          json={
352              "name": "My choice field",
353              "field_type": "choice",
354              "choices": ["foo", "bar", "baz", "qux"],
355              "default_value": json.dumps(["foo"]),
356              "multi_choice": True,
357          },
358      )
359      assert_httpx_success(result)
360  
361      # Clean up
362      result = httpx.delete(f"{URL}/api/v1/field/spool/mychoicefield")
363      assert_httpx_success(result)
364  
365  
366  def test_update_field_remove_choice():
367      """Test updating an existing field and removing a choice, should not be allowed."""
368      result = httpx.post(
369          f"{URL}/api/v1/field/spool/mychoicefield",
370          json={
371              "name": "My choice field",
372              "field_type": "choice",
373              "choices": ["foo", "bar", "baz"],
374              "default_value": json.dumps(["foo"]),
375              "multi_choice": True,
376          },
377      )
378      assert_httpx_success(result)
379  
380      result = httpx.post(
381          f"{URL}/api/v1/field/spool/mychoicefield",
382          json={
383              "name": "My choice field",
384              "field_type": "choice",
385              "choices": ["foo", "baz"],
386              "default_value": json.dumps(["foo"]),
387              "multi_choice": True,
388          },
389      )
390      assert result.status_code == 400
391      assert result.json()["message"] == "Cannot remove existing choices."
392  
393      # Clean up
394      result = httpx.delete(f"{URL}/api/v1/field/spool/mychoicefield")
395      assert_httpx_success(result)
396  
397  
398  def test_update_field_change_multi_choice():
399      """Test updating an existing field and changing the multi_choice setting, should not be allowed."""
400      result = httpx.post(
401          f"{URL}/api/v1/field/spool/mychoicefield",
402          json={
403              "name": "My choice field",
404              "field_type": "choice",
405              "choices": ["foo", "bar", "baz"],
406              "default_value": json.dumps(["foo"]),
407              "multi_choice": True,
408          },
409      )
410      assert_httpx_success(result)
411  
412      result = httpx.post(
413          f"{URL}/api/v1/field/spool/mychoicefield",
414          json={
415              "name": "My choice field",
416              "field_type": "choice",
417              "choices": ["foo", "bar", "baz"],
418              "default_value": json.dumps("foo"),
419              "multi_choice": False,
420          },
421      )
422      assert result.status_code == 400
423      assert result.json()["message"] == "Multi choice cannot be changed."
424  
425      # Clean up
426      result = httpx.delete(f"{URL}/api/v1/field/spool/mychoicefield")
427      assert_httpx_success(result)