@@ -45,6 +45,8 @@ def test_create_code_reference__valid_payload__returns_201_with_accepted_referen
4545 assert len (response .data ["code_references" ]) == 3
4646 assert response .data ["project" ] == project .pk
4747 assert response .data ["created_at" ] == "2025-04-14T12:30:00Z"
48+ assert response .data ["vcs_provider" ] == "github"
49+ assert FeatureFlagCodeReferencesScan .objects .get ().vcs_provider == "github"
4850 assert FeatureFlagCodeReferencesScan .objects .get ().code_references == [
4951 {
5052 "feature_name" : "feature-1" ,
@@ -381,3 +383,96 @@ def test_get_feature_code_references__feature_not_found__returns_404(
381383 # Then
382384 assert response .status_code == 404
383385 assert response .data ["detail" ] == "No Feature matches the given query."
386+
387+ def test_create_code_reference__with_gitlab_provider__returns_201 (
388+ admin_client_new : APIClient ,
389+ project : Project ,
390+ ) -> None :
391+ # Given / When
392+ response = admin_client_new .post (
393+ f"/api/v1/projects/{ project .pk } /code-references/" ,
394+ data = {
395+ "repository_url" : "https://gitlab.com/flagsmith" ,
396+ "revision" : "revision-hash" ,
397+ "vcs_provider" : "gitlab" , # Explicitly testing GitLab
398+ "code_references" : [
399+ {
400+ "feature_name" : "feature-1" ,
401+ "file_path" : "path/to/file1.py" ,
402+ "line_number" : 10 ,
403+ },
404+ ],
405+ },
406+ format = "json" ,
407+ )
408+
409+ # Then
410+ assert response .status_code == 201
411+ assert response .data ["vcs_provider" ] == "gitlab"
412+ assert FeatureFlagCodeReferencesScan .objects .get ().vcs_provider == "gitlab"
413+
414+
415+ def test_create_code_reference__with_invalid_provider__returns_400 (
416+ admin_client_new : APIClient ,
417+ project : Project ,
418+ ) -> None :
419+ # Given / When
420+ response = admin_client_new .post (
421+ f"/api/v1/projects/{ project .pk } /code-references/" ,
422+ data = {
423+ "repository_url" : "https://bitbucket.org/flagsmith" ,
424+ "revision" : "revision-hash" ,
425+ "vcs_provider" : "bitbucket" , # Invalid provider
426+ "code_references" : [
427+ {
428+ "feature_name" : "feature-1" ,
429+ "file_path" : "path/to/file1.py" ,
430+ "line_number" : 10 ,
431+ },
432+ ],
433+ },
434+ format = "json" ,
435+ )
436+
437+ # Then
438+ assert response .status_code == 400
439+ assert "vcs_provider" in response .data
440+ assert not FeatureFlagCodeReferencesScan .objects .exists ()
441+
442+
443+ def test_get_feature_code_references__gitlab_scan__returns_expected_permalinks (
444+ admin_client_new : APIClient ,
445+ feature : Feature ,
446+ project : Project ,
447+ ) -> None :
448+ # Given
449+ with freezegun .freeze_time ("2099-01-01T10:00:00-0300" ):
450+ FeatureFlagCodeReferencesScan .objects .create (
451+ project = project ,
452+ repository_url = "https://gitlab.com/flagsmith/backend" ,
453+ revision = "backend-1" ,
454+ vcs_provider = "gitlab" ,
455+ code_references = [
456+ {
457+ "feature_name" : feature .name ,
458+ "file_path" : "backend/file1.py" ,
459+ "line_number" : 20 ,
460+ },
461+ ],
462+ )
463+
464+ # When
465+ response = admin_client_new .get (
466+ f"/api/v1/projects/{ project .pk } /features/{ feature .pk } /code-references/" ,
467+ )
468+
469+ # Then
470+ assert response .status_code == 200
471+
472+ response_data = response .json ()
473+ assert len (response_data ) == 1
474+ assert response_data [0 ]["vcs_provider" ] == "gitlab"
475+
476+ # Assert the permalink uses the GitLab /-/blob/ format
477+ permalink = response_data [0 ]["code_references" ][0 ]["permalink" ]
478+ assert permalink == "https://gitlab.com/flagsmith/backend/-/blob/backend-1/backend/file1.py#L20"
0 commit comments