Skip to content

Commit f43a957

Browse files
ihabadhamclaude
andcommitted
Add unit tests for bin/dev argument parsing
Add comprehensive unit tests for ServerManager.run_from_command_line argument parsing. These tests follow Rails' CLI testing pattern (testing argument parsing without starting actual processes). Tests cover: - --route flag with separate value (generator default) - --route=value syntax - Command positioning relative to flags - --rails-env flag parsing - --verbose/-v flag parsing - Multiple flags in various orders - Unknown command error handling These tests would have caught the --route parsing bug that this PR fixes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 6a4e229 commit f43a957

File tree

1 file changed

+156
-0
lines changed

1 file changed

+156
-0
lines changed

react_on_rails/spec/react_on_rails/dev/server_manager_spec.rb

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,4 +440,160 @@ def mock_system_calls
440440
end
441441
end
442442
end
443+
444+
# These tests verify argument parsing works correctly, following Rails' CLI testing pattern
445+
# See: https://github.com/rails/rails/blob/main/railties/test/commands/server_test.rb
446+
describe ".run_from_command_line argument parsing" do
447+
before do
448+
mock_system_calls
449+
allow(ReactOnRails::PackerUtils).to receive(:shakapacker_precompile_hook_value).and_return(nil)
450+
allow(ReactOnRails::Dev::ServiceChecker).to receive(:check_services).and_return(true)
451+
end
452+
453+
context "with --route flag" do
454+
# This test would have caught the bug fixed in PR #2273
455+
# The generator creates bin/dev with: argv_with_defaults.push("--route", DEFAULT_ROUTE)
456+
# which passes ["--route", "hello_world"] to run_from_command_line
457+
it "correctly parses --route with value as separate argument (generator default)" do
458+
expect(described_class).to receive(:start).with(
459+
:development,
460+
"Procfile.dev",
461+
hash_including(route: "hello_world", verbose: false)
462+
)
463+
464+
described_class.run_from_command_line(["--route", "hello_world"])
465+
end
466+
467+
it "correctly parses --route=value syntax" do
468+
expect(described_class).to receive(:start).with(
469+
:development,
470+
"Procfile.dev",
471+
hash_including(route: "hello_world")
472+
)
473+
474+
described_class.run_from_command_line(["--route=hello_world"])
475+
end
476+
477+
it "correctly parses command before --route flag" do
478+
expect(described_class).to receive(:start).with(
479+
:static,
480+
"Procfile.dev-static-assets",
481+
hash_including(route: "myroute")
482+
)
483+
484+
described_class.run_from_command_line(["static", "--route", "myroute"])
485+
end
486+
487+
it "correctly parses command after --route flag" do
488+
expect(described_class).to receive(:start).with(
489+
:static,
490+
"Procfile.dev-static-assets",
491+
hash_including(route: "myroute")
492+
)
493+
494+
described_class.run_from_command_line(["--route", "myroute", "static"])
495+
end
496+
497+
it "does not treat route value as a command" do
498+
# This is the core bug test - "hello_world" should NOT be treated as a command
499+
expect(described_class).not_to receive(:start).with(:unknown, anything, anything)
500+
501+
# Should start development mode (default), not fail with "Unknown argument: hello_world"
502+
expect(described_class).to receive(:start).with(
503+
:development,
504+
"Procfile.dev",
505+
hash_including(route: "hello_world")
506+
)
507+
508+
described_class.run_from_command_line(["--route", "hello_world"])
509+
end
510+
end
511+
512+
context "with --rails-env flag" do
513+
it "correctly parses --rails-env with value as separate argument" do
514+
env = { "NODE_ENV" => "production", "RAILS_ENV" => "staging" }
515+
argv = ["bundle", "exec", "rails", "assets:precompile"]
516+
status_double = instance_double(Process::Status, success?: true)
517+
expect(Open3).to receive(:capture3).with(env, *argv).and_return(["output", "", status_double])
518+
519+
described_class.run_from_command_line(["prod", "--rails-env", "staging"])
520+
end
521+
522+
it "does not treat rails-env value as a command" do
523+
env = { "NODE_ENV" => "production", "RAILS_ENV" => "production" }
524+
argv = ["bundle", "exec", "rails", "assets:precompile"]
525+
status_double = instance_double(Process::Status, success?: true)
526+
expect(Open3).to receive(:capture3).with(env, *argv).and_return(["output", "", status_double])
527+
528+
# "production" after --rails-env should not be treated as a command
529+
described_class.run_from_command_line(["--rails-env", "production", "prod"])
530+
end
531+
end
532+
533+
context "with --verbose flag" do
534+
it "correctly parses --verbose flag" do
535+
expect(described_class).to receive(:start).with(
536+
:development,
537+
"Procfile.dev",
538+
hash_including(verbose: true)
539+
)
540+
541+
described_class.run_from_command_line(["--verbose"])
542+
end
543+
544+
it "correctly parses -v short flag" do
545+
expect(described_class).to receive(:start).with(
546+
:development,
547+
"Procfile.dev",
548+
hash_including(verbose: true)
549+
)
550+
551+
described_class.run_from_command_line(["-v"])
552+
end
553+
end
554+
555+
context "with multiple flags" do
556+
it "correctly parses command with multiple flags" do
557+
expect(described_class).to receive(:start).with(
558+
:static,
559+
"Procfile.dev-static-assets",
560+
hash_including(route: "dashboard", verbose: true)
561+
)
562+
563+
described_class.run_from_command_line(["static", "--route", "dashboard", "--verbose"])
564+
end
565+
566+
it "correctly parses flags in any order" do
567+
expect(described_class).to receive(:start).with(
568+
:static,
569+
"Procfile.dev-static-assets",
570+
hash_including(route: "dashboard", verbose: true)
571+
)
572+
573+
described_class.run_from_command_line(["--verbose", "--route", "dashboard", "static"])
574+
end
575+
end
576+
577+
context "with no arguments (default mode)" do
578+
it "starts development mode with no route" do
579+
expect(described_class).to receive(:start).with(
580+
:development,
581+
"Procfile.dev",
582+
hash_including(route: nil, verbose: false)
583+
)
584+
585+
described_class.run_from_command_line([])
586+
end
587+
end
588+
589+
context "with unknown command" do
590+
it "rejects and shows error message" do
591+
expect_any_instance_of(Kernel).to receive(:puts).with("Unknown argument: invalid_command")
592+
expect_any_instance_of(Kernel).to receive(:puts).with("Run 'dev help' for usage information")
593+
expect_any_instance_of(Kernel).to receive(:exit).with(1)
594+
595+
described_class.run_from_command_line(["invalid_command"])
596+
end
597+
end
598+
end
443599
end

0 commit comments

Comments
 (0)