|
5 | 5 |
|
6 | 6 | RSpec.describe ReactOnRails::Dev::PackGenerator do |
7 | 7 | describe ".generate" do |
8 | | - context "when in Bundler context with Rails available" do |
9 | | - let(:mock_task) { instance_double(Rake::Task) } |
10 | | - let(:mock_rails_app) do |
11 | | - # rubocop:disable RSpec/VerifiedDoubles |
12 | | - double("Rails.application").tap do |app| |
13 | | - allow(app).to receive(:load_tasks) |
14 | | - allow(app).to receive(:respond_to?).with(:load_tasks).and_return(true) |
15 | | - end |
16 | | - # rubocop:enable RSpec/VerifiedDoubles |
17 | | - end |
| 8 | + before do |
| 9 | + # Mock the precompile hook check to return false by default |
| 10 | + allow(ReactOnRails::PackerUtils).to receive(:shakapacker_precompile_hook_configured?).and_return(false) |
| 11 | + end |
18 | 12 |
|
| 13 | + context "when shakapacker precompile hook is configured" do |
19 | 14 | before do |
20 | | - # Setup Bundler context |
21 | | - stub_const("Bundler", Module.new) |
22 | | - allow(ENV).to receive(:[]).and_call_original |
23 | | - allow(ENV).to receive(:[]).with("BUNDLE_GEMFILE").and_return("/path/to/Gemfile") |
24 | | - |
25 | | - # Setup Rails availability |
26 | | - app = mock_rails_app |
27 | | - rails_module = Module.new do |
28 | | - define_singleton_method(:application) { app } |
29 | | - define_singleton_method(:respond_to?) { |method, *| method == :application } |
30 | | - end |
31 | | - stub_const("Rails", rails_module) |
32 | | - |
33 | | - # Mock Rake::Task at the boundary |
34 | | - allow(Rake::Task).to receive(:task_defined?).with("react_on_rails:generate_packs").and_return(false) |
35 | | - allow(Rake::Task).to receive(:[]).with("react_on_rails:generate_packs").and_return(mock_task) |
36 | | - allow(mock_task).to receive(:reenable) |
37 | | - allow(mock_task).to receive(:invoke) |
| 15 | + allow(ReactOnRails::PackerUtils).to receive(:shakapacker_precompile_hook_configured?).and_return(true) |
38 | 16 | end |
39 | 17 |
|
40 | | - it "runs pack generation successfully in verbose mode using direct rake execution" do |
| 18 | + it "skips pack generation in verbose mode" do |
41 | 19 | expect { described_class.generate(verbose: true) } |
42 | | - .to output(/📦 Generating React on Rails packs.../).to_stdout_from_any_process |
43 | | - |
44 | | - expect(mock_task).to have_received(:invoke) |
45 | | - expect(mock_rails_app).to have_received(:load_tasks) |
| 20 | + .to output(/⏭️ Skipping pack generation \(handled by shakapacker precompile hook\)/) |
| 21 | + .to_stdout_from_any_process |
46 | 22 | end |
47 | 23 |
|
48 | | - it "runs pack generation successfully in quiet mode using direct rake execution" do |
| 24 | + it "skips pack generation in quiet mode" do |
49 | 25 | expect { described_class.generate(verbose: false) } |
50 | | - .to output(/📦 Generating packs\.\.\. ✅/).to_stdout_from_any_process |
51 | | - |
52 | | - expect(mock_task).to have_received(:invoke) |
| 26 | + .not_to output.to_stdout_from_any_process |
53 | 27 | end |
| 28 | + end |
54 | 29 |
|
55 | | - it "exits with error when pack generation fails" do |
56 | | - allow(mock_task).to receive(:invoke).and_raise(StandardError.new("Task failed")) |
| 30 | + context "when shakapacker precompile hook is not configured" do |
| 31 | + context "when in Bundler context with Rails available" do |
| 32 | + let(:mock_task) { instance_double(Rake::Task) } |
| 33 | + let(:mock_rails_app) do |
| 34 | + # rubocop:disable RSpec/VerifiedDoubles |
| 35 | + double("Rails.application").tap do |app| |
| 36 | + allow(app).to receive(:load_tasks) |
| 37 | + allow(app).to receive(:respond_to?).with(:load_tasks).and_return(true) |
| 38 | + end |
| 39 | + # rubocop:enable RSpec/VerifiedDoubles |
| 40 | + end |
57 | 41 |
|
58 | | - # Mock STDERR.puts to capture output |
59 | | - error_output = [] |
60 | | - # rubocop:disable Style/GlobalStdStream |
61 | | - allow(STDERR).to receive(:puts) { |msg| error_output << msg } |
62 | | - # rubocop:enable Style/GlobalStdStream |
| 42 | + before do |
| 43 | + # Setup Bundler context |
| 44 | + stub_const("Bundler", Module.new) |
| 45 | + allow(ENV).to receive(:[]).and_call_original |
| 46 | + allow(ENV).to receive(:[]).with("BUNDLE_GEMFILE").and_return("/path/to/Gemfile") |
| 47 | + |
| 48 | + # Setup Rails availability |
| 49 | + app = mock_rails_app |
| 50 | + rails_module = Module.new do |
| 51 | + define_singleton_method(:application) { app } |
| 52 | + define_singleton_method(:respond_to?) { |method, *| method == :application } |
| 53 | + end |
| 54 | + stub_const("Rails", rails_module) |
| 55 | + |
| 56 | + # Mock Rake::Task at the boundary |
| 57 | + allow(Rake::Task).to receive(:task_defined?).with("react_on_rails:generate_packs").and_return(false) |
| 58 | + allow(Rake::Task).to receive(:[]).with("react_on_rails:generate_packs").and_return(mock_task) |
| 59 | + allow(mock_task).to receive(:reenable) |
| 60 | + allow(mock_task).to receive(:invoke) |
| 61 | + end |
63 | 62 |
|
64 | | - expect { described_class.generate(verbose: false) }.to raise_error(SystemExit) |
65 | | - expect(error_output.join("\n")).to match(/Error generating packs: Task failed/) |
66 | | - end |
| 63 | + it "runs pack generation successfully in verbose mode using direct rake execution" do |
| 64 | + expect { described_class.generate(verbose: true) } |
| 65 | + .to output(/📦 Generating React on Rails packs.../).to_stdout_from_any_process |
67 | 66 |
|
68 | | - it "outputs errors to stderr even in silent mode" do |
69 | | - allow(mock_task).to receive(:invoke).and_raise(StandardError.new("Silent mode error")) |
| 67 | + expect(mock_task).to have_received(:invoke) |
| 68 | + expect(mock_rails_app).to have_received(:load_tasks) |
| 69 | + end |
70 | 70 |
|
71 | | - # Mock STDERR.puts to capture output |
72 | | - error_output = [] |
73 | | - # rubocop:disable Style/GlobalStdStream |
74 | | - allow(STDERR).to receive(:puts) { |msg| error_output << msg } |
75 | | - # rubocop:enable Style/GlobalStdStream |
| 71 | + it "runs pack generation successfully in quiet mode using direct rake execution" do |
| 72 | + expect { described_class.generate(verbose: false) } |
| 73 | + .to output(/📦 Generating packs\.\.\. ✅/).to_stdout_from_any_process |
76 | 74 |
|
77 | | - expect { described_class.generate(verbose: false) }.to raise_error(SystemExit) |
78 | | - expect(error_output.join("\n")).to match(/Error generating packs: Silent mode error/) |
79 | | - end |
| 75 | + expect(mock_task).to have_received(:invoke) |
| 76 | + end |
80 | 77 |
|
81 | | - it "includes backtrace in error output when DEBUG env is set" do |
82 | | - allow(ENV).to receive(:[]).with("DEBUG").and_return("true") |
83 | | - allow(mock_task).to receive(:invoke).and_raise(StandardError.new("Debug error")) |
| 78 | + it "exits with error when pack generation fails" do |
| 79 | + allow(mock_task).to receive(:invoke).and_raise(StandardError.new("Task failed")) |
84 | 80 |
|
85 | | - # Mock STDERR.puts to capture output |
86 | | - error_output = [] |
87 | | - # rubocop:disable Style/GlobalStdStream |
88 | | - allow(STDERR).to receive(:puts) { |msg| error_output << msg } |
89 | | - # rubocop:enable Style/GlobalStdStream |
| 81 | + # Mock STDERR.puts to capture output |
| 82 | + error_output = [] |
| 83 | + # rubocop:disable Style/GlobalStdStream |
| 84 | + allow(STDERR).to receive(:puts) { |msg| error_output << msg } |
| 85 | + # rubocop:enable Style/GlobalStdStream |
90 | 86 |
|
91 | | - expect { described_class.generate(verbose: false) }.to raise_error(SystemExit) |
92 | | - expect(error_output.join("\n")).to match(/Error generating packs: Debug error.*pack_generator_spec\.rb/m) |
93 | | - end |
| 87 | + expect { described_class.generate(verbose: false) }.to raise_error(SystemExit) |
| 88 | + expect(error_output.join("\n")).to match(/Error generating packs: Task failed/) |
| 89 | + end |
94 | 90 |
|
95 | | - it "suppresses stdout in silent mode" do |
96 | | - # Mock task to produce output |
97 | | - allow(mock_task).to receive(:invoke) do |
98 | | - puts "This should be suppressed" |
| 91 | + it "outputs errors to stderr even in silent mode" do |
| 92 | + allow(mock_task).to receive(:invoke).and_raise(StandardError.new("Silent mode error")) |
| 93 | + |
| 94 | + # Mock STDERR.puts to capture output |
| 95 | + error_output = [] |
| 96 | + # rubocop:disable Style/GlobalStdStream |
| 97 | + allow(STDERR).to receive(:puts) { |msg| error_output << msg } |
| 98 | + # rubocop:enable Style/GlobalStdStream |
| 99 | + |
| 100 | + expect { described_class.generate(verbose: false) }.to raise_error(SystemExit) |
| 101 | + expect(error_output.join("\n")).to match(/Error generating packs: Silent mode error/) |
99 | 102 | end |
100 | 103 |
|
101 | | - expect { described_class.generate(verbose: false) } |
102 | | - .not_to output(/This should be suppressed/).to_stdout_from_any_process |
103 | | - end |
104 | | - end |
| 104 | + it "includes backtrace in error output when DEBUG env is set" do |
| 105 | + allow(ENV).to receive(:[]).with("DEBUG").and_return("true") |
| 106 | + allow(mock_task).to receive(:invoke).and_raise(StandardError.new("Debug error")) |
105 | 107 |
|
106 | | - context "when not in Bundler context" do |
107 | | - before do |
108 | | - # Ensure we're not in Bundler context |
109 | | - hide_const("Bundler") if defined?(Bundler) |
110 | | - end |
| 108 | + # Mock STDERR.puts to capture output |
| 109 | + error_output = [] |
| 110 | + # rubocop:disable Style/GlobalStdStream |
| 111 | + allow(STDERR).to receive(:puts) { |msg| error_output << msg } |
| 112 | + # rubocop:enable Style/GlobalStdStream |
111 | 113 |
|
112 | | - it "runs pack generation successfully in verbose mode using bundle exec" do |
113 | | - allow(described_class).to receive(:system) |
114 | | - .with("bundle", "exec", "rake", "react_on_rails:generate_packs") |
115 | | - .and_return(true) |
| 114 | + expect { described_class.generate(verbose: false) }.to raise_error(SystemExit) |
| 115 | + expect(error_output.join("\n")).to match(/Error generating packs: Debug error.*pack_generator_spec\.rb/m) |
| 116 | + end |
116 | 117 |
|
117 | | - expect { described_class.generate(verbose: true) } |
118 | | - .to output(/📦 Generating React on Rails packs.../).to_stdout_from_any_process |
| 118 | + it "suppresses stdout in silent mode" do |
| 119 | + # Mock task to produce output |
| 120 | + allow(mock_task).to receive(:invoke) do |
| 121 | + puts "This should be suppressed" |
| 122 | + end |
119 | 123 |
|
120 | | - expect(described_class).to have_received(:system) |
121 | | - .with("bundle", "exec", "rake", "react_on_rails:generate_packs") |
| 124 | + expect { described_class.generate(verbose: false) } |
| 125 | + .not_to output(/This should be suppressed/).to_stdout_from_any_process |
| 126 | + end |
122 | 127 | end |
123 | 128 |
|
124 | | - it "runs pack generation successfully in quiet mode using bundle exec" do |
125 | | - allow(described_class).to receive(:system) |
126 | | - .with("bundle", "exec", "rake", "react_on_rails:generate_packs", |
127 | | - out: File::NULL, err: File::NULL) |
128 | | - .and_return(true) |
| 129 | + context "when not in Bundler context" do |
| 130 | + before do |
| 131 | + # Ensure we're not in Bundler context |
| 132 | + hide_const("Bundler") if defined?(Bundler) |
| 133 | + end |
129 | 134 |
|
130 | | - expect { described_class.generate(verbose: false) } |
131 | | - .to output(/📦 Generating packs\.\.\. ✅/).to_stdout_from_any_process |
| 135 | + it "runs pack generation successfully in verbose mode using bundle exec" do |
| 136 | + allow(described_class).to receive(:system) |
| 137 | + .with("bundle", "exec", "rake", "react_on_rails:generate_packs") |
| 138 | + .and_return(true) |
132 | 139 |
|
133 | | - expect(described_class).to have_received(:system) |
134 | | - .with("bundle", "exec", "rake", "react_on_rails:generate_packs", |
135 | | - out: File::NULL, err: File::NULL) |
136 | | - end |
| 140 | + expect { described_class.generate(verbose: true) } |
| 141 | + .to output(/📦 Generating React on Rails packs.../).to_stdout_from_any_process |
137 | 142 |
|
138 | | - it "exits with error when pack generation fails" do |
139 | | - allow(described_class).to receive(:system) |
140 | | - .with("bundle", "exec", "rake", "react_on_rails:generate_packs", |
141 | | - out: File::NULL, err: File::NULL) |
142 | | - .and_return(false) |
| 143 | + expect(described_class).to have_received(:system) |
| 144 | + .with("bundle", "exec", "rake", "react_on_rails:generate_packs") |
| 145 | + end |
143 | 146 |
|
144 | | - expect { described_class.generate(verbose: false) }.to raise_error(SystemExit) |
145 | | - end |
146 | | - end |
| 147 | + it "runs pack generation successfully in quiet mode using bundle exec" do |
| 148 | + allow(described_class).to receive(:system) |
| 149 | + .with("bundle", "exec", "rake", "react_on_rails:generate_packs", |
| 150 | + out: File::NULL, err: File::NULL) |
| 151 | + .and_return(true) |
147 | 152 |
|
148 | | - context "when Rails is not available" do |
149 | | - before do |
150 | | - stub_const("Bundler", Module.new) |
151 | | - allow(ENV).to receive(:[]).and_call_original |
152 | | - allow(ENV).to receive(:[]).with("BUNDLE_GEMFILE").and_return("/path/to/Gemfile") |
| 153 | + expect { described_class.generate(verbose: false) } |
| 154 | + .to output(/📦 Generating packs\.\.\. ✅/).to_stdout_from_any_process |
| 155 | + |
| 156 | + expect(described_class).to have_received(:system) |
| 157 | + .with("bundle", "exec", "rake", "react_on_rails:generate_packs", |
| 158 | + out: File::NULL, err: File::NULL) |
| 159 | + end |
153 | 160 |
|
154 | | - # Rails not available |
155 | | - hide_const("Rails") if defined?(Rails) |
| 161 | + it "exits with error when pack generation fails" do |
| 162 | + allow(described_class).to receive(:system) |
| 163 | + .with("bundle", "exec", "rake", "react_on_rails:generate_packs", |
| 164 | + out: File::NULL, err: File::NULL) |
| 165 | + .and_return(false) |
| 166 | + |
| 167 | + expect { described_class.generate(verbose: false) }.to raise_error(SystemExit) |
| 168 | + end |
156 | 169 | end |
157 | 170 |
|
158 | | - it "falls back to bundle exec when Rails is not defined" do |
159 | | - allow(described_class).to receive(:system) |
160 | | - .with("bundle", "exec", "rake", "react_on_rails:generate_packs") |
161 | | - .and_return(true) |
| 171 | + context "when Rails is not available" do |
| 172 | + before do |
| 173 | + stub_const("Bundler", Module.new) |
| 174 | + allow(ENV).to receive(:[]).and_call_original |
| 175 | + allow(ENV).to receive(:[]).with("BUNDLE_GEMFILE").and_return("/path/to/Gemfile") |
162 | 176 |
|
163 | | - expect { described_class.generate(verbose: true) } |
164 | | - .to output(/📦 Generating React on Rails packs.../).to_stdout_from_any_process |
| 177 | + # Rails not available |
| 178 | + hide_const("Rails") if defined?(Rails) |
| 179 | + end |
| 180 | + |
| 181 | + it "falls back to bundle exec when Rails is not defined" do |
| 182 | + allow(described_class).to receive(:system) |
| 183 | + .with("bundle", "exec", "rake", "react_on_rails:generate_packs") |
| 184 | + .and_return(true) |
165 | 185 |
|
166 | | - expect(described_class).to have_received(:system) |
167 | | - .with("bundle", "exec", "rake", "react_on_rails:generate_packs") |
| 186 | + expect { described_class.generate(verbose: true) } |
| 187 | + .to output(/📦 Generating React on Rails packs.../).to_stdout_from_any_process |
| 188 | + |
| 189 | + expect(described_class).to have_received(:system) |
| 190 | + .with("bundle", "exec", "rake", "react_on_rails:generate_packs") |
| 191 | + end |
168 | 192 | end |
169 | 193 | end |
170 | 194 | end |
|
0 commit comments