
    	]j6[                         d dl Z d dlmZ d dlmZ d dlmZ d dlmZ d dl	m
Z
 d dlmZ d dlmZmZmZ  G d	 d
e      Z G d de      Z G d de      Z e j(                   edd      d       G d de             Zy)    N)patch)flag_set)OrganizationFactory)Project)ProjectFactory)APITestCase)AnnotationFactoryPredictionFactoryTaskFactoryc                   4    e Zd Zed        Zd Zd Zd Zd Zy)TestTaskAPIc                     t               | _        t        | j                        | _        | j                  j                  | _        y Norganizationr   r   r   project
created_byuserclss    K/root/env/lib/python3.12/site-packages/label_studio/tasks/tests/test_api.pysetUpTestDatazTestTaskAPI.setUpTestData   2    .0$#2B2BC##..    c                    t        | j                  ddi      }| j                  j                  | j                         | j                  j                  d|j                   d      }|j                  dk(  sJ |j                         i d|j                  d	| j                  j                  d
|j                  j                         j                  dd      d|j                  j                         j                  dd      dg dg dg dddidi dg dddddd dddddg dd dddd ddd d|j                  d g dd ddk(  sJ y ) Ntexttestr   datar   /api/tasks//   idr   
created_at+00:00Z
updated_atannotationspredictionsdraftsr    meta
updated_by
is_labeledFoverlap   file_uploadannotations_ids annotations_results
annotatorscompleted_atr   )predictions_model_versionsdraft_existspredictions_resultspredictions_scoretotal_annotationstotal_predictionsavg_lead_timecancelled_annotationsinner_idstorage_filenamecomment_authorscomment_countlast_comment_updated_atunresolved_comment_count)r   r   clientforce_authenticater   getr%   status_codejsonr&   	isoformatreplacer)   r@   )selftaskresponses      r   test_get_taskzTestTaskAPI.test_get_task   s   4<<vv6FG&&DII&6;;??[	#;<##s***}}  #
$'' #
t|| #
 $//335==hL #
 $//335==hL	 #

 2 #
 2 #
 b #
 VV$ #
 B #
 " #
 % #
 q #
 4 #
 r #
 "2 #
  "! #
" D# #
$ +-!#%!%!"!"!%& $!'+()? #
  
  	
  
r   c           
         t        | j                  ddi      }g g ddii ddd dd d	}| j                  j                  | j                         | j                  j                  d	|j                   d
|d      }|j                  dk(  sJ |j                          |j                         i d|j                  d| j                  j                  d|j                  j                         j                  dd      d|j                  j                         j                  dd      dg dg dddidi dd dddddd ddddd dd!|j                  d"g dd dd#k(  sJ y )$Nr   r   r   zchanged testr4   F)	r*   r+   r    r-   r&   r)   r.   r/   r2   r!   r"   r#   rJ   r    formatr$   r%   r   r&   r'   r(   r)   r*   r+   r    r-   r.   r/   r0   r1   r2   r<   r   r=   r?   r@   rB   )rC   rD   rE   )r   r   rF   rG   r   r   r%   rI   refresh_from_dbrJ   r&   rK   rL   r)   r@   )rM   rN   payloadrO   s       r   test_patch_taskzTestTaskAPI.test_patch_task<   s   4<<vv6FG ^,

 	&&DII&6;;$${477)1%=GTZ$[##s***}} #
$''#
t||#
 $//335==hL#
 $//335==hL	#

 2#
 2#
 V^,#
 B#
 $#
 %#
 q#
 4#
  #
  #
 $Q#
  !#
" r##
$ '+())#
 
 	
 
r   c                     ddii d}| j                   j                  | j                         | j                   j                  d|d      }|j                  dk(  sJ |j                         }|d	   d
   dgk(  sJ y)zQTest that creating a task without project ID fails with appropriate error messager   	test task)r    r-   r!   r"   rJ   rR   i  validation_errorsr   zThis field is required.N)rF   rG   r   postrI   rJ   rM   rU   rO   response_datas       r   )test_create_task_without_project_id_failsz5TestTaskAPI.test_create_task_without_project_id_failsf   s     [)

 	&&DII&6;;##M#O##s*** 01)<AZ@[[[[r   c                 Z   | j                   j                  ddii d}| j                  j                  | j                         | j                  j                  d|d      }|j                  dk(  sJ |j                         }|d	   | j                   j                  k(  sJ |d
   ddik(  sJ y)z8Test that creating a task with valid project ID succeedsr   rX   )r   r    r-   r!   r"   rJ   rR      r   r    N)r   r%   rF   rG   r   rZ   rI   rJ   r[   s       r   )test_create_task_with_project_id_succeedsz5TestTaskAPI.test_create_task_with_project_id_succeedst   s     ||[)
 	&&DII&6;;##M#O##s*** Y'4<<??:::V$(====r   N)	__name__
__module____qualname__classmethodr   rP   rV   r]   r`    r   r   r   r      s+    / /
'
R(
T\>r   r   c                   8    e Zd ZdZed        Zd Zd Zd Zd Z	y)TestTaskAPIResolveUria  Tests for resolve_uri query parameter in task detail endpoint.

    The resolve_uri parameter controls whether storage URLs (e.g., s3://bucket/file.jpg)
    are converted to proxy URLs. This is useful for debugging and viewing original
    source paths in task preview.
    c                     t               | _        t        | j                        | _        | j                  j                  | _        y r   r   r   s    r   r   z#TestTaskAPIResolveUri.setUpTestData   r   r   c                    t        | j                  ddi      }| j                  j                  | j                         t        j                  |j                  dddi      5 }| j                  j                  d|j                   d	      }d
d
d
       j                  dk(  sJ j                          y
# 1 sw Y   +xY w)a  Test that resolve_uri defaults to True when not specified.

        This test validates:
        - Creating a task with a storage-like URL in data
        - Fetching the task without resolve_uri parameter
        - Verifying that Task.resolve_uri method is called (default behavior)

        Critical validation: By default, URLs should be resolved for security,
        preventing direct exposure of storage credentials.
        images3://bucket/image.jpgr   r!   resolve_uri/resolved/urlreturn_valuer"   r#   Nr$   r   r   rF   rG   r   r   object	__class__rH   r%   rI   assert_called_oncerM   rN   mock_resolverO   s       r   &test_get_task_resolve_uri_default_truez<TestTaskAPIResolveUri.test_get_task_resolve_uri_default_true   s     4<<w@W6XY&&DII&6 \\$..-wP_F`a 	Aeq{{TWWIQ'?@H	A ##s***'')	A 	A   $*B88Cc                    t        | j                  ddi      }| j                  j                  | j                         t        j                  |j                  dddi      5 }| j                  j                  d|j                   d	      }d
d
d
       j                  dk(  sJ j                          y
# 1 sw Y   +xY w)aX  Test that resolve_uri=true explicitly enables URL resolution.

        This test validates:
        - Creating a task with a storage-like URL in data
        - Fetching the task with resolve_uri=true
        - Verifying that Task.resolve_uri method is called

        Critical validation: Explicit resolve_uri=true should resolve URLs.
        rj   rk   r   r!   rl   rm   rn   r"   z/?resolve_uri=trueNr$   rp   rt   s       r   'test_get_task_resolve_uri_explicit_truez=TestTaskAPIResolveUri.test_get_task_resolve_uri_explicit_true   s     4<<w@W6XY&&DII&6\\$..-wP_F`a 	Req{{TWWI=O'PQH	R ##s***'')		R 	Rrw   c                    d}t        | j                  |dd      }| j                  j                  | j                         t        j                  |j                  d      5 }| j                  j                  d|j                   d      }d	d	d	       j                  d
k(  sJ j                          |j                         d   d   |k(  sJ |j                         d   d   dk(  sJ y	# 1 sw Y   axY w)a  Test that resolve_uri=false preserves original storage URLs.

        This test validates:
        - Creating a task with a storage-like URL in data
        - Fetching the task with resolve_uri=false
        - Verifying that Task.resolve_uri method is NOT called
        - Original URL is preserved in the response

        Critical validation: When resolve_uri=false, users should see original
        storage URLs (e.g., s3://bucket/file.jpg) for debugging purposes.
        z s3://my-bucket/path/to/image.jpgr   )rj   r   r   r!   rl   r"   /?resolve_uri=falseNr$   r    rj   r   )r   r   rF   rG   r   r   rq   rr   rH   r%   rI   assert_not_calledrJ   )rM   original_urlrN   ru   rO   s        r   7test_get_task_resolve_uri_false_preserves_original_urlszMTestTaskAPIResolveUri.test_get_task_resolve_uri_false_preserves_original_urls   s     :4<<V\6]^&&DII&6\\$..-8 	SL{{TWWI=P'QRH	S ##s***&&(}}v&w/<???}}v&v.&888	S 	Ss   #*C--C6c                 v   ddddd}t        | j                  |      }| j                  j                  | j                         | j                  j                  d|j                   d	      }|j                  d
k(  sJ |j                         d   }|d   dk(  sJ |d   dk(  sJ |d   dk(  sJ |d   dk(  sJ y)aA  Test resolve_uri=false with multiple URL fields in task data.

        This test validates:
        - Creating a task with multiple storage URLs
        - Fetching with resolve_uri=false
        - All original URLs are preserved

        Critical validation: All URL fields should preserve their original values.
        zs3://bucket-1/image1.jpgzgs://bucket-2/image2.pngz azure-blob://container/audio.mp3zPlain text field)image_1image_2audior   r   r!   r"   r{   r$   r    r   r   r   r   N)	r   r   rF   rG   r   rH   r%   rI   rJ   )rM   	task_datarN   rO   r\   s        r   8test_get_task_resolve_uri_false_with_multiple_url_fieldszNTestTaskAPIResolveUri.test_get_task_resolve_uri_false_with_multiple_url_fields   s     217&	
	 4<<i@&&DII&6;;??[	9L#MN##s*** /Y'+EEEEY'+EEEEW%)KKKKV$(::::r   N)
ra   rb   rc   __doc__rd   r   rv   ry   r~   r   re   r   r   rg   rg      s/     / /
*,*&94;r   rg   c                   <    e Zd ZdZed        Z ed      d        Zy)TestTaskAgreementAPIFeatureOffzOWhen feature flag is off, agreement endpoint returns 403. Always run this test.c                     t               | _        t        | j                        | _        | j                  j                  | _        y r   r   r   s    r   r   z,TestTaskAgreementAPIFeatureOff.setUpTestData   r   r   tasks.api.flag_setc                 L   d|_         t        | j                        }| j                  j	                  | j
                         | j                  j                  d|j                   d      }|j                  dk(  sJ d|j                         v sd|j                         v sJ y y )	NFr   r!   r"   /agreement/  detailerror
ro   r   r   rF   rG   r   rH   r%   rI   rJ   )rM   mock_flag_setrN   rO   s       r   8test_distribution_returns_403_when_feature_flag_disabledzWTestTaskAgreementAPIFeatureOff.test_distribution_returns_403_when_feature_flag_disabled   s    %*"4<<0&&DII&6;;??[	#EF##s***8==?*g.HHH.H*r   N)ra   rb   rc   r   rd   r   r   r   re   r   r   r   r      s3    Y/ /
  I !Ir   r   +fflag_fix_all_fit_720_lazy_load_annotationsr!   zPAgreement API tests require fflag_fix_all_fit_720_lazy_load_annotations to be onc                      e Zd ZdZed        Z ed      d        Z ed       ej                  e	d      d               Z
 ed      d        Z ed      d        Z ed      d	        Z ed      d
        Z ed      d        Z ed      d        Z ed      d        Z ed      d        Z ed      d        Zy)TestTaskAgreementAPIz^Tests for TaskAgreementAPI (GET /api/tasks/<id>/agreement/). Run only when feature flag is on.c                     t               | _        t        | j                        | _        | j                  j                  | _        y r   r   r   s    r   r   z"TestTaskAgreementAPI.setUpTestData  r   r   r   c                     d|_         | j                  j                  | j                         | j                  j	                  d      }|j
                  dk(  sJ |j                         ddik(  sJ y )NTr!   z/api/tasks/99999/agreement/i  r   zTask not found)ro   rF   rG   r   rH   rI   rJ   )rM   r   rO   s      r   2test_distribution_returns_404_for_nonexistent_taskzGTestTaskAgreementAPI.test_distribution_returns_404_for_nonexistent_task  sd    %)"&&DII&6;;??#@A##s***}}7,<"====r   has_permissionc                 0   d|_         t               }t        |      t              }fd}||_        | j
                  j                  | j                         | j
                  j                  d|j                   d      }|j                  dk(  sJ y )	NTr   r   c                 6    | j                   j                   k7  S )N)r%   )r   r   other_projects     r   has_permz\TestTaskAgreementAPI.test_distribution_permission_denied_for_other_project.<locals>.has_perm$  s    ::!1!111r   r!   r"   r   r   )ro   r   r   r   side_effectrF   rG   r   rH   r%   rI   )rM   mock_has_permissionr   	other_orgrN   r   rO   r   s          @r   5test_distribution_permission_denied_for_other_projectzJTestTaskAgreementAPI.test_distribution_permission_denied_for_other_project  s     &*"')	&I>=1	2 +3'&&DII&6;;??[	#EF##s***r   c                 F   d|_         t        | j                        }| j                  j	                  | j
                         | j                  j                  d|j                   d      }|j                  dk(  sJ |j                         }|d   dk(  sJ |d	   i k(  sJ y )
NTr   r!   r"   r   r$   r<   r   distributionsr   rM   r   rN   rO   r    s        r   5test_distribution_empty_task_returns_zero_annotationszJTestTaskAgreementAPI.test_distribution_empty_task_returns_zero_annotations,  s    %)"4<<0&&DII&6;;??[	#EF##s***}}'(A---O$***r   c           
         d|_         t        | j                        }t        || j                  ddddddgidg       t        || j                  ddddd	gidg       | j                  j                  | j                  
       | j                  j                  d|j                   d      }|j                  dk(  sJ |j                         }|d   dk(  sJ |d   d   dddddk(  sJ y )NTr   labelrj   rectanglelabelsCar	from_nameto_nametypevaluerN   r   resultPersonr!   r"   r   r$   r<      r   r1   )r   r   r   labelsro   r   r   r	   rF   rG   r   rH   r%   rI   rJ   r   s        r   &test_distribution_with_rectanglelabelsz;TestTaskAgreementAPI.test_distribution_with_rectanglelabels7  s   %)"4<<0LL ")&-/%@		
 	LL ")&-/(<		
 	&&DII&6;;??[	#EF##s***}}'(A---O$W-%1-2
 
 	
 
r   c           	         d|_         t        | j                        }t        || j                  dddddgidg       t        || j                  ddddd	gidg       t        || j                  dddddgidg       | j                  j                  | j                  
       | j                  j                  d|j                   d      }|j                  dk(  sJ |j                         }|d   dk(  sJ |d   d   dddddk(  sJ y )NTr   	sentimentr   choicesPositiver   r   Negativer!   r"   r   r$   r<      r   r   r1   )r   r   r   r   r   s        r   test_distribution_with_choicesz3TestTaskAgreementAPI.test_distribution_with_choices]  sH   %)"4<<0LL "-%%'*6		
 	LL "-%%'*6		
 	LL "-%%'*6		
 	&&DII&6;;??[	#EF##s***}}'(A---O$[1#$!46
 
 	
 
r   c           	      *   d|_         t        | j                        }t        || j                  dddddidg       t        || j                  dddddidg       | j                  j                  | j                  	       | j                  j                  d
|j                   d      }|j                  dk(  sJ |j                         }|d   dk(  sJ |d   d   d   dk(  sJ |d   d   d   dk(  sJ |d   d   d   dk(  sJ d|d   d   vsJ y )NTr   ratingr      r   r      r!   r"   r   r$   r<   r   r   r   averageg      @countvaluesr   r   s        r   test_distribution_with_ratingz2TestTaskAgreementAPI.test_distribution_with_rating  sR   %)"4<<0LL "*%$&]		
 	LL "*%$&]		
 	&&DII&6;;??[	#EF##s***}}'(A---O$X.v6(BBBO$X.y9S@@@O$X.w71<<<tO4X>>>>r   c           	         d|_         t        | j                        }t        || j                  dddddidg       t        || j                  ddddd	idg       | j                  j                  | j                  
       | j                  j                  d|j                   d      }|j                  dk(  sJ |j                         }|d   dk(  sJ |d   d   d   dk(  sJ |d   d   d   dk(  sJ |d   d   d   dk(  sJ y )NTr   r   r   number
   r   r      r!   r"   r   r$   r<   r   r   r   r   g      .@r   r   s        r   test_distribution_with_numberz2TestTaskAgreementAPI.test_distribution_with_number  s:   %)"4<<0LL ")%$&^		
 	LL ")%$&^		
 	&&DII&6;;??[	#EF##s***}}'(A---O$W-f5AAAO$W-i8D@@@O$W-g6!;;;r   c           
         d|_         t        | j                        }t        || j                  ddddddggidg	       t        || j                  dddddd
ggidg	       | j                  j                  | j                         | j                  j                  d|j                   d      }|j                  dk(  sJ |j                         }|d   dk(  sJ |d   d   dddddk(  sJ y )NTr   taxr   taxonomyAnimalsDogr   r   Catr!   r"   r   r$   r<   r   r   r1   )r   r   r   r   r   s        r   test_distribution_with_taxonomyz4TestTaskAgreementAPI.test_distribution_with_taxonomy  s!   %)"4<<0LL "'%&(Iu+=*>?		
 	LL "'%&(Iu+=*>?		
 	&&DII&6;;??[	#EF##s***}}'(A---O$U+*0
 
 	
 
r   c           	         d|_         t        | j                        }t        || j                  dddddidg	       t        || j                  ddddd
idg	       | j                  j                  | j                         | j                  j                  d|j                   d      }|j                  dk(  sJ |j                         }|d   dk(  sJ |d   d   dddddk(  sJ y )NTr   pairr   pairwiseselectedleftr   r   rightr!   r"   r   r$   r<   r   r   r1   )r   r   r   r   r   s        r   test_distribution_with_pairwisez4TestTaskAgreementAPI.test_distribution_with_pairwise   s   %)"4<<0LL "(%&(&1		
 	LL "(%&('2		
 	&&DII&6;;??[	#EF##s***}}'(A---O$V, 1-1
 
 	
 
r   c           
         d|_         t        | j                        }t        || j                  dddddgidg       t        || j                  dddddd	gidg
       | j                  j                  | j                         | j                  j                  d|j                   d      }|j                  dk(  sJ |j                         }|d   dk(  sJ |d   d   d   ddik(  sJ y )NTr   r   rj   r   r   r   r   r   )rN   r   was_cancelledr   r!   r"   r   r$   r<   r1   r   r   r   r   s        r   0test_distribution_excludes_cancelled_annotationszETestTaskAgreementAPI.test_distribution_excludes_cancelled_annotations&  s   %)"4<<0LL ")&-/%9		
 	LL ")&-/(<			
 	&&DII&6;;??[	#EF##s***}}'(A---O$W-h7E1:EEEr   c           
         d|_         t        | j                        }t        || j                  ddddddgidg       t	        || j                  dddddgidg       | j
                  j                  | j                  	       | j
                  j                  d
|j                   d      }|j                  dk(  sJ |j                         }|d   dk(  sJ |d   d   d   ddik(  sJ y)z^Predictions are merged into distributions so aggregate matches client-side (develop / FF off).Tr   r   rj   r   r   r   r   r!   r"   r   r$   r<   r1   r   r   r   N)ro   r   r   r	   r
   rF   rG   r   rH   r%   rI   rJ   r   s        r   6test_distribution_includes_predictions_in_label_countszKTestTaskAgreementAPI.test_distribution_includes_predictions_in_label_countsJ  s    &*"4<<0LL ")&-/%@		
 	LL ")&-/%9		
 	&&DII&6;;??[	#EF##s***}}'(A---O$W-h7E1:EEEr   N)ra   rb   rc   r   rd   r   r   r   rq   r   r   r   r   r   r   r   r   r   r   r   re   r   r   r   r     sY   
 i/ /
  > !>  U\\'+,+ - !+  + !+  #
 !#
J  /
 !/
b  #? !#?J  "< !"<H  #
 !#
J  #
 !#
J  !F !!FF  !F !!Fr   r   )unittestunittest.mockr   core.feature_flagsr   organizations.tests.factoriesr   projects.modelsr   projects.tests.factoriesr   rest_framework.testr   tasks.tests.factoriesr	   r
   r   r   rg   r   
skipUnlessr   re   r   r   <module>r      s      ' = # 3 + S Sv>+ v>rl;K l;^I[ I& :FVaF; aF	aFr   