@@ -361,6 +361,68 @@ def test_fork_global_notebook_creates_personal_copy(
361361 assert "aaaa1111-aaaa-aaaa-aaaa-aaaaaaaaaaaa" not in data ["source" ]
362362 assert "[id=" in data ["source" ]
363363
364+ @pytest .mark .parametrize ("scopes" , [["lab:create" ]])
365+ def test_publish_personal_to_global_creates_global_copy (
366+ self ,
367+ client : TestClient ,
368+ db : Session ,
369+ api_tester_user : user_models .User ,
370+ auth_token : auth .Token ,
371+ ):
372+ original_source = (
373+ "# %% [id=aaaa2222-aaaa-aaaa-aaaa-aaaaaaaaaaaa] code\n "
374+ "y = 2\n "
375+ )
376+ nb = lab_repository .create_notebook (
377+ db ,
378+ lab_schemas .LabNotebookCreate (
379+ name = "shareable" ,
380+ visibility = "personal" ,
381+ source = original_source ,
382+ ),
383+ current_user_id = api_tester_user .id ,
384+ )
385+ response = client .post (
386+ f"/tech-lab/notebooks/{ nb .id } /fork?visibility=global" ,
387+ headers = {"Authorization" : "Bearer " + auth_token },
388+ )
389+ assert response .status_code == status .HTTP_201_CREATED , response .text
390+ data = response .json ()
391+ assert data ["user_id" ] == api_tester_user .id
392+ assert data ["visibility" ] == "global"
393+ # Global publish keeps the original name (no "(fork)" suffix).
394+ assert data ["name" ] == "shareable"
395+ assert data ["folder_id" ] is None
396+ assert "aaaa2222-aaaa-aaaa-aaaa-aaaaaaaaaaaa" not in data ["source" ]
397+ assert "[id=" in data ["source" ]
398+ # Personal original is untouched.
399+ db .refresh (nb )
400+ assert nb .visibility == "personal"
401+
402+ @pytest .mark .parametrize ("scopes" , [["lab:create" ]])
403+ def test_publish_library_to_global_rejected (
404+ self ,
405+ client : TestClient ,
406+ db : Session ,
407+ api_tester_user : user_models .User ,
408+ auth_token : auth .Token ,
409+ ):
410+ nb = lab_repository .create_notebook (
411+ db ,
412+ lab_schemas .LabNotebookCreate (
413+ name = "lib-thing" ,
414+ visibility = "library" ,
415+ source = "# %% code\n print('hi')\n " ,
416+ ),
417+ current_user_id = api_tester_user .id ,
418+ via_api = False ,
419+ )
420+ response = client .post (
421+ f"/tech-lab/notebooks/{ nb .id } /fork?visibility=global" ,
422+ headers = {"Authorization" : "Bearer " + auth_token },
423+ )
424+ assert response .status_code == status .HTTP_400_BAD_REQUEST
425+
364426
365427class TestLabExecution (ApiTester ):
366428 """Execute-flow tests with the celery task stubbed to a synchronous runner."""
0 commit comments