@@ -2631,6 +2631,213 @@ def test_branch_rm_alias
26312631 end
26322632end
26332633
2634+ # Integration tests for branch command with real git repos
2635+ class Git ::Pkgs ::TestBranchCommandIntegration < Minitest ::Test
2636+ include TestHelpers
2637+
2638+ def setup
2639+ Git ::Pkgs ::Database . disconnect
2640+ create_test_repo
2641+ # Create initial commit on main
2642+ add_file ( "Gemfile" , sample_gemfile ( { "rails" => "~> 7.0" } ) )
2643+ commit ( "Add rails" )
2644+ @git_dir = File . join ( @test_dir , ".git" )
2645+ end
2646+
2647+ def teardown
2648+ cleanup_test_repo
2649+ end
2650+
2651+ def test_branch_add_analyzes_commits
2652+ # First init main branch
2653+ Dir . chdir ( @test_dir ) do
2654+ capture_stdout { Git ::Pkgs ::Commands ::Init . new ( [ "--no-hooks" ] ) . run }
2655+ end
2656+
2657+ # Create feature branch with new commits
2658+ Dir . chdir ( @test_dir ) do
2659+ system ( "git checkout -b feature" , out : File ::NULL , err : File ::NULL )
2660+ end
2661+ add_file ( "Gemfile" , sample_gemfile ( { "rails" => "~> 7.0" , "puma" => "~> 6.0" } ) )
2662+ commit ( "Add puma" )
2663+ add_file ( "Gemfile" , sample_gemfile ( { "rails" => "~> 7.0" , "puma" => "~> 6.0" , "sidekiq" => "~> 7.0" } ) )
2664+ commit ( "Add sidekiq" )
2665+
2666+ output = capture_stdout do
2667+ Dir . chdir ( @test_dir ) do
2668+ Git ::Pkgs ::Commands ::Branch . new ( [ "add" , "feature" ] ) . run
2669+ end
2670+ end
2671+
2672+ assert_includes output , "Analyzing branch: feature"
2673+ assert_includes output , "Done!"
2674+ assert_match ( /Analyzed \d + commits/ , output )
2675+
2676+ # Verify branch was created in database
2677+ Git ::Pkgs ::Database . connect ( @git_dir )
2678+ branch = Git ::Pkgs ::Models ::Branch . first ( name : "feature" )
2679+ assert branch
2680+ assert branch . last_analyzed_sha
2681+ assert branch . commits . count >= 3 # Initial + 2 feature commits
2682+ end
2683+
2684+ def test_branch_add_tracks_dependency_changes
2685+ Dir . chdir ( @test_dir ) do
2686+ capture_stdout { Git ::Pkgs ::Commands ::Init . new ( [ "--no-hooks" ] ) . run }
2687+ system ( "git checkout -b feature" , out : File ::NULL , err : File ::NULL )
2688+ end
2689+
2690+ # Add a dependency
2691+ add_file ( "Gemfile" , sample_gemfile ( { "rails" => "~> 7.0" , "puma" => "~> 6.0" } ) )
2692+ commit ( "Add puma" )
2693+
2694+ # Modify a dependency
2695+ add_file ( "Gemfile" , sample_gemfile ( { "rails" => "~> 7.1" , "puma" => "~> 6.0" } ) )
2696+ commit ( "Update rails" )
2697+
2698+ # Remove a dependency
2699+ add_file ( "Gemfile" , sample_gemfile ( { "rails" => "~> 7.1" } ) )
2700+ commit ( "Remove puma" )
2701+
2702+ capture_stdout do
2703+ Dir . chdir ( @test_dir ) do
2704+ Git ::Pkgs ::Commands ::Branch . new ( [ "add" , "feature" ] ) . run
2705+ end
2706+ end
2707+
2708+ Git ::Pkgs ::Database . connect ( @git_dir )
2709+
2710+ # Check for added change
2711+ added = Git ::Pkgs ::Models ::DependencyChange . first ( name : "puma" , change_type : "added" )
2712+ assert added , "Should have recorded puma being added"
2713+
2714+ # Check for modified change
2715+ modified = Git ::Pkgs ::Models ::DependencyChange . first ( name : "rails" , change_type : "modified" )
2716+ assert modified , "Should have recorded rails being modified"
2717+ assert_equal "~> 7.0" , modified . previous_requirement
2718+ assert_equal "~> 7.1" , modified . requirement
2719+
2720+ # Check for removed change
2721+ removed = Git ::Pkgs ::Models ::DependencyChange . first ( name : "puma" , change_type : "removed" )
2722+ assert removed , "Should have recorded puma being removed"
2723+ end
2724+
2725+ def test_branch_add_creates_snapshots
2726+ Dir . chdir ( @test_dir ) do
2727+ capture_stdout { Git ::Pkgs ::Commands ::Init . new ( [ "--no-hooks" ] ) . run }
2728+ system ( "git checkout -b feature" , out : File ::NULL , err : File ::NULL )
2729+ end
2730+
2731+ # Create enough commits to trigger snapshot storage
2732+ 5 . times do |i |
2733+ add_file ( "Gemfile" , sample_gemfile ( { "rails" => "~> 7.0" , "gem#{ i } " => "~> 1.0" } ) )
2734+ commit ( "Add gem#{ i } " )
2735+ end
2736+
2737+ capture_stdout do
2738+ Dir . chdir ( @test_dir ) do
2739+ Git ::Pkgs ::Commands ::Branch . new ( [ "add" , "feature" ] ) . run
2740+ end
2741+ end
2742+
2743+ Git ::Pkgs ::Database . connect ( @git_dir )
2744+ assert Git ::Pkgs ::Models ::Branch . first ( name : "feature" )
2745+
2746+ # Should have snapshots (at least the final one)
2747+ snapshots = Git ::Pkgs ::Models ::DependencySnapshot . count
2748+ assert snapshots > 0 , "Should have created snapshots"
2749+ end
2750+
2751+ def test_branch_add_handles_merge_commits
2752+ Dir . chdir ( @test_dir ) do
2753+ capture_stdout { Git ::Pkgs ::Commands ::Init . new ( [ "--no-hooks" ] ) . run }
2754+
2755+ # Create feature branch
2756+ system ( "git checkout -b feature" , out : File ::NULL , err : File ::NULL )
2757+ end
2758+ add_file ( "Gemfile" , sample_gemfile ( { "rails" => "~> 7.0" , "puma" => "~> 6.0" } ) )
2759+ commit ( "Add puma on feature" )
2760+
2761+ Dir . chdir ( @test_dir ) do
2762+ # Go back to main and make a change
2763+ system ( "git checkout main" , out : File ::NULL , err : File ::NULL )
2764+ end
2765+ add_file ( "README.md" , "# Test" )
2766+ commit ( "Add readme on main" )
2767+
2768+ Dir . chdir ( @test_dir ) do
2769+ # Merge main into feature (creates merge commit)
2770+ system ( "git checkout feature" , out : File ::NULL , err : File ::NULL )
2771+ system ( "git merge main -m 'Merge main'" , out : File ::NULL , err : File ::NULL )
2772+ end
2773+
2774+ # Should handle merge commits gracefully (skip them)
2775+ output = capture_stdout do
2776+ Dir . chdir ( @test_dir ) do
2777+ Git ::Pkgs ::Commands ::Branch . new ( [ "add" , "feature" ] ) . run
2778+ end
2779+ end
2780+
2781+ assert_includes output , "Done!"
2782+ end
2783+
2784+ def test_branch_add_with_multiple_ecosystems
2785+ Dir . chdir ( @test_dir ) do
2786+ capture_stdout { Git ::Pkgs ::Commands ::Init . new ( [ "--no-hooks" ] ) . run }
2787+ system ( "git checkout -b feature" , out : File ::NULL , err : File ::NULL )
2788+ end
2789+
2790+ # Add both Gemfile and package.json
2791+ add_file ( "Gemfile" , sample_gemfile ( { "rails" => "~> 7.0" } ) )
2792+ add_file ( "package.json" , sample_package_json ( { "lodash" => "^4.0.0" } ) )
2793+ commit ( "Add deps" )
2794+
2795+ capture_stdout do
2796+ Dir . chdir ( @test_dir ) do
2797+ Git ::Pkgs ::Commands ::Branch . new ( [ "add" , "feature" ] ) . run
2798+ end
2799+ end
2800+
2801+ Git ::Pkgs ::Database . connect ( @git_dir )
2802+
2803+ # Check both ecosystems tracked
2804+ rubygems_manifest = Git ::Pkgs ::Models ::Manifest . first ( ecosystem : "rubygems" )
2805+ npm_manifest = Git ::Pkgs ::Models ::Manifest . first ( ecosystem : "npm" )
2806+
2807+ assert rubygems_manifest , "Should track rubygems manifest"
2808+ assert npm_manifest , "Should track npm manifest"
2809+ end
2810+
2811+ def test_branch_add_quiet_mode
2812+ Dir . chdir ( @test_dir ) do
2813+ capture_stdout { Git ::Pkgs ::Commands ::Init . new ( [ "--no-hooks" ] ) . run }
2814+ system ( "git checkout -b feature" , out : File ::NULL , err : File ::NULL )
2815+ end
2816+ add_file ( "Gemfile" , sample_gemfile ( { "rails" => "~> 7.0" , "puma" => "~> 6.0" } ) )
2817+ commit ( "Add puma" )
2818+
2819+ Git ::Pkgs . quiet = true
2820+ output = capture_stdout do
2821+ Dir . chdir ( @test_dir ) do
2822+ Git ::Pkgs ::Commands ::Branch . new ( [ "add" , "feature" ] ) . run
2823+ end
2824+ end
2825+ Git ::Pkgs . quiet = false
2826+
2827+ # Should have minimal output in quiet mode
2828+ refute_includes output , "Processing commit"
2829+ end
2830+
2831+ def capture_stdout
2832+ original = $stdout
2833+ $stdout = StringIO . new
2834+ yield
2835+ $stdout. string
2836+ ensure
2837+ $stdout = original
2838+ end
2839+ end
2840+
26342841class Git ::Pkgs ::TestInitCommand < Minitest ::Test
26352842 include TestHelpers
26362843
0 commit comments