@@ -796,3 +796,128 @@ pub async fn test_get_output_dependencies_output_not_found() {
796796 ) ,
797797 }
798798}
799+
800+ /// Tests that `expand_dev_sources` correctly extracts dependencies from dev
801+ /// sources and allows them to be merged into a PixiEnvironmentSpec.
802+ #[ tokio:: test]
803+ pub async fn test_expand_dev_sources ( ) {
804+ use pixi_command_dispatcher:: { DependencyOnlySource , ExpandDevSourcesSpec } ;
805+ use pixi_spec:: { PathSourceSpec , SourceSpec } ;
806+
807+ // Setup: Create a dispatcher with the in-memory backend
808+ let root_dir = workspaces_dir ( ) . join ( "output-dependencies" ) ;
809+ let tempdir = tempfile:: tempdir ( ) . unwrap ( ) ;
810+ let ( tool_platform, tool_virtual_packages) = tool_platform ( ) ;
811+
812+ let dispatcher = CommandDispatcher :: builder ( )
813+ . with_root_dir ( root_dir. clone ( ) )
814+ . with_cache_dirs ( default_cache_dirs ( ) . with_workspace ( tempdir. path ( ) . to_path_buf ( ) ) )
815+ . with_executor ( Executor :: Serial )
816+ . with_tool_platform ( tool_platform, tool_virtual_packages. clone ( ) )
817+ . with_backend_overrides ( BackendOverride :: from_memory (
818+ PassthroughBackend :: instantiator ( ) ,
819+ ) )
820+ . finish ( ) ;
821+
822+ // Create dev sources for test-package and package-a
823+ // package-a depends on test-package (also a dev source, should be filtered)
824+ // and on package-b (not a dev source, should be included)
825+ let dev_sources = vec ! [
826+ DependencyOnlySource {
827+ source: SourceSpec :: from( PathSourceSpec {
828+ path: "test-package" . into( ) ,
829+ } ) ,
830+ output_name: PackageName :: new_unchecked( "test-package" ) ,
831+ } ,
832+ DependencyOnlySource {
833+ source: SourceSpec :: from( PathSourceSpec {
834+ path: "package-a" . into( ) ,
835+ } ) ,
836+ output_name: PackageName :: new_unchecked( "package-a" ) ,
837+ } ,
838+ ] ;
839+
840+ // Create the spec for expanding dev sources
841+ let spec = ExpandDevSourcesSpec {
842+ dev_sources,
843+ channel_config : default_channel_config ( ) ,
844+ channels : vec ! [ ] ,
845+ build_environment : BuildEnvironment :: simple ( tool_platform, tool_virtual_packages. clone ( ) ) ,
846+ variants : None ,
847+ enabled_protocols : Default :: default ( ) ,
848+ } ;
849+
850+ // Act: Expand the dev sources
851+ let expanded = dispatcher
852+ . expand_dev_sources ( spec)
853+ . await
854+ . map_err ( |e| format_diagnostic ( & e) )
855+ . expect ( "expand_dev_sources should succeed" ) ;
856+
857+ // Print the expanded dependencies in JSON format for easy inspection
858+ println ! ( "\n === Expanded Dependencies ===" ) ;
859+ let json_string = serde_json:: to_string_pretty ( & expanded. dependencies )
860+ . expect ( "Failed to serialize dependencies to JSON" ) ;
861+ println ! ( "{}" , json_string) ;
862+
863+ if !expanded. constraints . is_empty ( ) {
864+ println ! ( "\n === Expanded Constraints ===" ) ;
865+ let constraints_json = serde_json:: to_string_pretty ( & expanded. constraints )
866+ . expect ( "Failed to serialize constraints to JSON" ) ;
867+ println ! ( "{}" , constraints_json) ;
868+ }
869+ println ! ( "=============================\n " ) ;
870+
871+ // Assert: Verify all dependencies were extracted
872+ let all_dep_names: Vec < _ > = expanded
873+ . dependencies
874+ . names ( )
875+ . map ( |name| name. as_normalized ( ) )
876+ . sorted ( )
877+ . collect ( ) ;
878+
879+ // Expected dependencies:
880+ // - From test-package: cmake, make (build), openssl, zlib (host), numpy, python (run)
881+ // - From package-a: gcc (build), requests (run), package-b (run, which is a source)
882+ // - test-package is NOT included even though package-a depends on it (filtered because it's a dev source)
883+ // - package-b IS included (not a dev source)
884+ assert_eq ! (
885+ all_dep_names,
886+ vec![
887+ "cmake" ,
888+ "gcc" ,
889+ "make" ,
890+ "numpy" ,
891+ "openssl" ,
892+ "package-b" ,
893+ "python" ,
894+ "requests" ,
895+ "zlib"
896+ ] ,
897+ "All dependencies should be extracted, with dev sources filtered out"
898+ ) ;
899+
900+ // Verify that test-package is NOT in the dependencies (it's filtered because it's a dev source)
901+ assert ! (
902+ !expanded. dependencies. contains_key( "test-package" ) ,
903+ "test-package should be filtered out because it's a dev source"
904+ ) ;
905+
906+ // Verify that package-a is NOT in the dependencies (it's filtered because it's a dev source)
907+ assert ! (
908+ !expanded. dependencies. contains_key( "package-a" ) ,
909+ "package-a should be filtered out because it's a dev source"
910+ ) ;
911+
912+ // Verify that package-b IS in the dependencies (it's not a dev source)
913+ assert ! (
914+ expanded. dependencies. contains_key( "package-b" ) ,
915+ "package-b should be included because it's not a dev source"
916+ ) ;
917+
918+ // Assert: Verify constraints are empty (test packages have no constraints)
919+ assert ! (
920+ expanded. constraints. is_empty( ) ,
921+ "Test packages have no constraints"
922+ ) ;
923+ }
0 commit comments