sun-sword 0.0.10 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +57 -2
  3. data/Gemfile +20 -0
  4. data/Gemfile.lock +252 -0
  5. data/README.md +74 -15
  6. data/Rakefile +6 -10
  7. data/lib/generators/sun_sword/USAGE +22 -3
  8. data/lib/generators/sun_sword/frontend_generator.rb +77 -39
  9. data/lib/generators/sun_sword/frontend_generator_spec.rb +539 -0
  10. data/lib/generators/sun_sword/init_generator.rb +2 -0
  11. data/lib/generators/sun_sword/init_generator_spec.rb +82 -0
  12. data/lib/generators/sun_sword/scaffold_generator.rb +212 -29
  13. data/lib/generators/sun_sword/scaffold_generator_spec.rb +1414 -0
  14. data/lib/generators/sun_sword/templates_frontend/{Procfile.dev → Procfile.dev.tt} +1 -0
  15. data/lib/generators/sun_sword/templates_frontend/bin/{watch → watch.tt} +2 -1
  16. data/lib/generators/sun_sword/templates_frontend/config/{vite.json → vite.json.tt} +2 -1
  17. data/lib/generators/sun_sword/templates_frontend/controllers/application_controller.rb.tt +2 -2
  18. data/lib/generators/sun_sword/templates_frontend/controllers/tests_controller.rb +36 -0
  19. data/lib/generators/sun_sword/templates_frontend/controllers/tests_controller_spec.rb +62 -0
  20. data/lib/generators/sun_sword/templates_frontend/env.development +1 -1
  21. data/lib/generators/sun_sword/templates_frontend/frontend/entrypoints/application.js +2 -2
  22. data/lib/generators/sun_sword/templates_frontend/frontend/pages/tests-stimulus.js +31 -0
  23. data/lib/generators/sun_sword/templates_frontend/frontend/pages/web.js +12 -0
  24. data/lib/generators/sun_sword/templates_frontend/frontend/stylesheets/application.css +1 -3
  25. data/lib/generators/sun_sword/templates_frontend/helpers/application_helper.rb +17 -0
  26. data/lib/generators/sun_sword/templates_frontend/helpers/application_helper_spec.rb +30 -0
  27. data/lib/generators/sun_sword/templates_frontend/package.json.tt +14 -0
  28. data/lib/generators/sun_sword/templates_frontend/views/components/_action_destroy.html.erb.tt +1 -1
  29. data/lib/generators/sun_sword/templates_frontend/views/components/_alert.html.erb.tt +1 -1
  30. data/lib/generators/sun_sword/templates_frontend/views/layouts/application.html.erb.tt +3 -3
  31. data/lib/generators/sun_sword/templates_frontend/views/tests/_frame_content.html.erb +9 -0
  32. data/lib/generators/sun_sword/templates_frontend/views/tests/_log_entry.html.erb +4 -0
  33. data/lib/generators/sun_sword/templates_frontend/views/tests/_updated_content.html.erb +6 -0
  34. data/lib/generators/sun_sword/templates_frontend/views/tests/stimulus.html.erb +45 -0
  35. data/lib/generators/sun_sword/templates_frontend/views/tests/turbo_drive.html.erb +55 -0
  36. data/lib/generators/sun_sword/templates_frontend/views/tests/turbo_frame.html.erb +87 -0
  37. data/lib/generators/sun_sword/templates_frontend/vite.config.ts.tt +1 -1
  38. data/lib/generators/sun_sword/templates_init/config/initializers/sun_sword.rb +1 -0
  39. data/lib/generators/sun_sword/templates_scaffold/controllers/controller.rb.tt +24 -24
  40. data/lib/generators/sun_sword/templates_scaffold/controllers/controller_spec.rb.tt +398 -0
  41. data/lib/generators/sun_sword/templates_scaffold/views/index.html.erb.tt +5 -5
  42. data/lib/generators/sun_sword/templates_scaffold/views/show.html.erb.tt +3 -0
  43. data/lib/generators/tmp/db/structures/test_structure.yaml +42 -0
  44. data/lib/sun-sword.rb +1 -0
  45. data/lib/sun_sword/configuration_spec.rb +77 -0
  46. data/lib/sun_sword/version.rb +1 -1
  47. metadata +177 -29
  48. data/.rspec +0 -3
  49. data/.rubocop.yml +0 -1146
  50. data/lib/generators/sun_sword/templates_frontend/controllers/site_controller.rb +0 -16
  51. data/lib/generators/sun_sword/templates_frontend/db/seeds.rb +0 -3
  52. data/lib/generators/sun_sword/templates_frontend/db/structures/example.yaml.tt +0 -106
  53. data/lib/generators/sun_sword/templates_frontend/frontend/pages/stimulus.js +0 -10
  54. data/lib/generators/sun_sword/templates_frontend/package.json +0 -7
  55. data/lib/generators/sun_sword/templates_frontend/views/site/_comment.html.erb.tt +0 -3
  56. data/lib/generators/sun_sword/templates_frontend/views/site/stimulus.html.erb.tt +0 -26
@@ -0,0 +1,539 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+ require 'generators/sun_sword/frontend_generator'
5
+
6
+ RSpec.describe SunSword::FrontendGenerator, type: :generator do
7
+ include FileUtils
8
+
9
+ let(:destination_root) { File.expand_path('../tmp', __dir__) }
10
+
11
+ before do
12
+ FileUtils.mkdir_p(destination_root) unless Dir.exist?(destination_root)
13
+ end
14
+
15
+ after do
16
+ FileUtils.rm_rf(destination_root) if Dir.exist?(destination_root)
17
+ end
18
+
19
+ describe 'generator options' do
20
+ it 'requires the setup option' do
21
+ generator = described_class.new([], setup: false)
22
+ expect {
23
+ generator.validate_setup_option
24
+ }.to raise_error(Thor::Error, 'The --setup option must be specified to create the domain structure.')
25
+ end
26
+
27
+ it 'accepts the setup option' do
28
+ generator = described_class.new([], setup: true)
29
+ expect {
30
+ generator.validate_setup_option
31
+ }.not_to raise_error
32
+ end
33
+
34
+ it 'rejects engine option' do
35
+ generator = described_class.new([], setup: true, engine: 'admin')
36
+ expect {
37
+ generator.validate_no_engine
38
+ }.to raise_error(Thor::Error, 'Frontend generator does not support --engine option. Frontend setup must be done in the main app only. Use "rails generate sun_sword:frontend --setup" without engine option.')
39
+ end
40
+
41
+ it 'accepts setup without engine option' do
42
+ generator = described_class.new([], setup: true, engine: nil)
43
+ expect {
44
+ generator.validate_no_engine
45
+ }.not_to raise_error
46
+ end
47
+ end
48
+
49
+ describe 'source root' do
50
+ it 'has the correct source root' do
51
+ source_path = File.expand_path('templates_frontend', File.dirname(__FILE__))
52
+ expect(described_class.source_root).to eq(source_path)
53
+ end
54
+ end
55
+
56
+ describe '#validate_setup_option' do
57
+ context 'when setup option is false' do
58
+ it 'raises an error' do
59
+ generator = described_class.new([], setup: false)
60
+ expect { generator.validate_setup_option }.to raise_error(Thor::Error)
61
+ end
62
+ end
63
+
64
+ context 'when setup option is true' do
65
+ it 'does not raise an error' do
66
+ generator = described_class.new([], setup: true)
67
+ expect { generator.validate_setup_option }.not_to raise_error
68
+ end
69
+ end
70
+ end
71
+
72
+ describe '#path_app' do
73
+ it 'returns app' do
74
+ generator = described_class.new([], setup: true)
75
+ expect(generator.send(:path_app)).to eq('app')
76
+ end
77
+ end
78
+
79
+ describe 'file operations' do
80
+ before do
81
+ # Create mock files and directories for testing
82
+ FileUtils.mkdir_p(File.join(destination_root, 'app', 'assets', 'config'))
83
+ FileUtils.mkdir_p(File.join(destination_root, 'app', 'javascript'))
84
+ FileUtils.mkdir_p(File.join(destination_root, 'config'))
85
+ FileUtils.touch(File.join(destination_root, 'Gemfile'))
86
+ FileUtils.touch(File.join(destination_root, 'app', 'javascript', 'application.js'))
87
+ FileUtils.touch(File.join(destination_root, 'config', 'routes.rb'))
88
+ end
89
+
90
+ it 'copies assets from template' do
91
+ generator = described_class.new([], setup: true)
92
+ generator.destination_root = destination_root
93
+
94
+ allow(generator).to receive(:template)
95
+
96
+ generator.send(:copy_assets_from_template)
97
+
98
+ expect(generator).to have_received(:template).with(
99
+ 'assets/config/manifest.js',
100
+ File.join('assets/config/manifest.js')
101
+ )
102
+ end
103
+
104
+ it 'adds gem dependencies to Gemfile' do
105
+ generator = described_class.new([], setup: true)
106
+ generator.destination_root = destination_root
107
+
108
+ allow(generator).to receive(:append_to_file)
109
+ allow(generator).to receive(:say)
110
+
111
+ generator.send(:add_to_gemfile)
112
+ end
113
+ end
114
+
115
+ describe 'integration test' do
116
+ it 'can be instantiated with setup option' do
117
+ generator = described_class.new([], setup: true)
118
+ expect(generator).to be_a(described_class)
119
+ expect(generator.options[:setup]).to be true
120
+ end
121
+ end
122
+
123
+ describe '#setup' do
124
+ let(:generator) do
125
+ described_class.new([], setup: true).tap do |g|
126
+ g.destination_root = destination_root
127
+ end
128
+ end
129
+
130
+ before do
131
+ # Mock all dependencies
132
+ allow(generator).to receive(:copy_assets_from_template)
133
+ allow(generator).to receive(:add_to_gemfile)
134
+ allow(generator).to receive(:install_vite)
135
+ allow(generator).to receive(:configure_vite)
136
+ allow(generator).to receive(:modify_application_js)
137
+ allow(generator).to receive(:generate_default_frontend)
138
+ allow(generator).to receive(:generate_controllers_tests)
139
+ allow(generator).to receive(:generate_components)
140
+ allow(generator).to receive(:modify_layout_for_vite)
141
+ end
142
+
143
+ it 'validates no engine option before setup' do
144
+ generator_with_engine = described_class.new([], setup: true, engine: 'admin')
145
+ expect {
146
+ generator_with_engine.setup
147
+ }.to raise_error(Thor::Error, /Frontend generator does not support --engine option/)
148
+ end
149
+
150
+ it 'calls all methods in correct order' do
151
+ generator.setup
152
+
153
+ expect(generator).to have_received(:copy_assets_from_template).ordered
154
+ expect(generator).to have_received(:add_to_gemfile).ordered
155
+ expect(generator).to have_received(:install_vite).ordered
156
+ expect(generator).to have_received(:configure_vite).ordered
157
+ expect(generator).to have_received(:modify_application_js).ordered
158
+ expect(generator).to have_received(:generate_default_frontend).ordered
159
+ expect(generator).to have_received(:generate_controllers_tests).ordered
160
+ expect(generator).to have_received(:generate_components).ordered
161
+ expect(generator).to have_received(:modify_layout_for_vite).ordered
162
+ end
163
+
164
+ it 'calls all required methods' do
165
+ generator.setup
166
+
167
+ expect(generator).to have_received(:copy_assets_from_template)
168
+ expect(generator).to have_received(:add_to_gemfile)
169
+ expect(generator).to have_received(:install_vite)
170
+ expect(generator).to have_received(:configure_vite)
171
+ expect(generator).to have_received(:modify_application_js)
172
+ expect(generator).to have_received(:generate_default_frontend)
173
+ expect(generator).to have_received(:generate_controllers_tests)
174
+ expect(generator).to have_received(:generate_components)
175
+ expect(generator).to have_received(:modify_layout_for_vite)
176
+ end
177
+ end
178
+
179
+ describe '#remove_assets_folder' do
180
+ let(:generator) do
181
+ described_class.new([], setup: true).tap do |g|
182
+ g.destination_root = destination_root
183
+ end
184
+ end
185
+
186
+ context 'when assets folder exists' do
187
+ before do
188
+ FileUtils.mkdir_p(File.join(destination_root, 'app', 'assets'))
189
+ end
190
+
191
+ it 'removes the folder' do
192
+ allow(generator).to receive(:remove_dir)
193
+ allow(generator).to receive(:say)
194
+
195
+ Dir.chdir(destination_root) do
196
+ generator.send(:remove_assets_folder)
197
+ end
198
+
199
+ expect(generator).to have_received(:remove_dir).with('app/assets')
200
+ expect(generator).to have_received(:say).with("Folder 'app/assets' has been removed.", :green)
201
+ end
202
+ end
203
+
204
+ context 'when assets folder does not exist' do
205
+ it 'handles gracefully without removing' do
206
+ allow(generator).to receive(:remove_dir)
207
+ allow(generator).to receive(:say)
208
+
209
+ Dir.chdir(destination_root) do
210
+ generator.send(:remove_assets_folder)
211
+ end
212
+
213
+ expect(generator).not_to have_received(:remove_dir)
214
+ expect(generator).to have_received(:say).with("Folder 'app/assets' does not exist.", :yellow)
215
+ end
216
+ end
217
+ end
218
+
219
+ describe '#install_vite' do
220
+ let(:generator) do
221
+ described_class.new([], setup: true).tap do |g|
222
+ g.destination_root = destination_root
223
+ end
224
+ end
225
+
226
+ before do
227
+ allow(generator).to receive(:template)
228
+ allow(generator).to receive(:run)
229
+ allow(generator).to receive(:say)
230
+ end
231
+
232
+ it 'calls template for package.json' do
233
+ generator.send(:install_vite)
234
+
235
+ expect(generator).to have_received(:template).with('package.json.tt', 'package.json')
236
+ end
237
+
238
+ it 'runs bun install' do
239
+ generator.send(:install_vite)
240
+
241
+ expect(generator).to have_received(:run).with('bun install')
242
+ end
243
+
244
+ it 'runs all bun add commands' do
245
+ generator.send(:install_vite)
246
+
247
+ expect(generator).to have_received(:run).with('bun add -D vite vite-plugin-full-reload vite-plugin-ruby vite-plugin-stimulus-hmr')
248
+ expect(generator).to have_received(:run).with('bun add path stimulus-vite-helpers @hotwired/stimulus @hotwired/turbo-rails @tailwindcss/aspect-ratio @tailwindcss/forms @tailwindcss/line-clamp @tailwindcss/typography @tailwindcss/vite tailwindcss vite-plugin-rails autoprefixer')
249
+ expect(generator).to have_received(:run).with('bun add -D eslint prettier eslint-plugin-prettier eslint-config-prettier eslint-plugin-tailwindcss')
250
+ end
251
+
252
+ it 'displays success message' do
253
+ generator.send(:install_vite)
254
+
255
+ expect(generator).to have_received(:say).with('Vite installed successfully with Bun', :green)
256
+ end
257
+ end
258
+
259
+ describe '#configure_vite' do
260
+ let(:generator) do
261
+ described_class.new([], setup: true).tap do |g|
262
+ g.destination_root = destination_root
263
+ end
264
+ end
265
+
266
+ before do
267
+ allow(generator).to receive(:template)
268
+ allow(generator).to receive(:run)
269
+ allow(generator).to receive(:say)
270
+ end
271
+
272
+ it 'calls template for all vite config files' do
273
+ generator.send(:configure_vite)
274
+
275
+ expect(generator).to have_received(:template).with('vite.config.ts.tt', 'vite.config.ts')
276
+ expect(generator).to have_received(:template).with('Procfile.dev.tt', 'Procfile.dev')
277
+ expect(generator).to have_received(:template).with('bin/watch.tt', 'bin/watch')
278
+ expect(generator).to have_received(:template).with('config/vite.json.tt', 'config/vite.json')
279
+ end
280
+
281
+ it 'runs chmod command for bin/watch' do
282
+ generator.send(:configure_vite)
283
+
284
+ expect(generator).to have_received(:run).with('chmod +x bin/watch')
285
+ end
286
+
287
+ it 'displays configuration messages' do
288
+ generator.send(:configure_vite)
289
+
290
+ expect(generator).to have_received(:say).with('Configuring Vite...')
291
+ expect(generator).to have_received(:say).with('Vite configuration completed', :green)
292
+ end
293
+ end
294
+
295
+ describe '#modify_application_js' do
296
+ let(:generator) do
297
+ described_class.new([], setup: true).tap do |g|
298
+ g.destination_root = destination_root
299
+ end
300
+ end
301
+
302
+ before do
303
+ allow(generator).to receive(:say)
304
+ end
305
+
306
+ context 'when application.js exists' do
307
+ before do
308
+ FileUtils.mkdir_p(File.join(destination_root, 'app', 'javascript'))
309
+ FileUtils.touch(File.join(destination_root, 'app', 'javascript', 'application.js'))
310
+ end
311
+
312
+ it 'displays update message' do
313
+ Dir.chdir(destination_root) do
314
+ generator.send(:modify_application_js)
315
+ end
316
+
317
+ expect(generator).to have_received(:say).with('Updated application.js for Vite', :green)
318
+ end
319
+ end
320
+
321
+ context 'when application.js does not exist' do
322
+ it 'does not display update message' do
323
+ Dir.chdir(destination_root) do
324
+ generator.send(:modify_application_js)
325
+ end
326
+
327
+ expect(generator).not_to have_received(:say).with('Updated application.js for Vite', :green)
328
+ end
329
+ end
330
+ end
331
+
332
+ describe '#generate_default_frontend' do
333
+ let(:generator) do
334
+ described_class.new([], setup: true).tap do |g|
335
+ g.destination_root = destination_root
336
+ end
337
+ end
338
+
339
+ before do
340
+ allow(generator).to receive(:directory)
341
+ allow(generator).to receive(:say)
342
+ end
343
+
344
+ it 'calls directory with correct paths' do
345
+ generator.send(:generate_default_frontend)
346
+
347
+ expect(generator).to have_received(:directory).with('frontend', File.join('app', 'frontend'))
348
+ end
349
+
350
+ it 'displays success message' do
351
+ generator.send(:generate_default_frontend)
352
+
353
+ expect(generator).to have_received(:say).with('Generated default frontend files', :green)
354
+ end
355
+ end
356
+
357
+ describe '#generate_components' do
358
+ let(:generator) do
359
+ described_class.new([], setup: true).tap do |g|
360
+ g.destination_root = destination_root
361
+ end
362
+ end
363
+
364
+ before do
365
+ allow(generator).to receive(:directory)
366
+ allow(generator).to receive(:say)
367
+ end
368
+
369
+ it 'calls directory with correct paths' do
370
+ generator.send(:generate_components)
371
+
372
+ expect(generator).to have_received(:directory).with('views/components', File.join('app', 'views/components'))
373
+ end
374
+
375
+ it 'displays success message' do
376
+ generator.send(:generate_components)
377
+
378
+ expect(generator).to have_received(:say).with('Generate default controller', :green)
379
+ end
380
+ end
381
+
382
+ describe '#generate_controllers_tests' do
383
+ let(:generator) do
384
+ described_class.new([], setup: true).tap do |g|
385
+ g.destination_root = destination_root
386
+ end
387
+ end
388
+
389
+ before do
390
+ FileUtils.mkdir_p(File.join(destination_root, 'config'))
391
+ FileUtils.touch(File.join(destination_root, 'config', 'routes.rb'))
392
+ File.write(File.join(destination_root, 'config', 'routes.rb'), "Rails.application.routes.draw do\nend\n")
393
+
394
+ allow(generator).to receive(:run)
395
+ allow(generator).to receive(:template)
396
+ allow(generator).to receive(:copy_file)
397
+ allow(generator).to receive(:inject_into_file)
398
+ allow(generator).to receive(:say)
399
+ end
400
+
401
+ it 'runs rails generator command' do
402
+ generator.send(:generate_controllers_tests)
403
+
404
+ expect(generator).to have_received(:run).with('rails g controller tests stimulus turbo_drive turbo_frame frame_content update_content')
405
+ end
406
+
407
+ it 'calls template for controller files' do
408
+ generator.send(:generate_controllers_tests)
409
+
410
+ expect(generator).to have_received(:template).with('controllers/tests_controller.rb', File.join('app', 'controllers/tests_controller.rb'))
411
+ expect(generator).to have_received(:template).with('controllers/tests_controller_spec.rb', File.join('app', 'controllers/tests_controller_spec.rb'))
412
+ end
413
+
414
+ it 'calls copy_file for test views' do
415
+ generator.send(:generate_controllers_tests)
416
+
417
+ expect(generator).to have_received(:copy_file).with('views/tests/stimulus.html.erb', File.join('app', 'views/tests/stimulus.html.erb'))
418
+ end
419
+
420
+ it 'copies test view files' do
421
+ generator.send(:generate_controllers_tests)
422
+
423
+ expect(generator).to have_received(:copy_file).with('views/tests/turbo_drive.html.erb', File.join('app', 'views/tests/turbo_drive.html.erb'))
424
+ expect(generator).to have_received(:copy_file).with('views/tests/turbo_frame.html.erb', File.join('app', 'views/tests/turbo_frame.html.erb'))
425
+ expect(generator).to have_received(:copy_file).with('views/tests/_frame_content.html.erb', File.join('app', 'views/tests/_frame_content.html.erb'))
426
+ expect(generator).to have_received(:copy_file).with('views/tests/_updated_content.html.erb', File.join('app', 'views/tests/_updated_content.html.erb'))
427
+ expect(generator).to have_received(:copy_file).with('views/tests/_log_entry.html.erb', File.join('app', 'views/tests/_log_entry.html.erb'))
428
+ end
429
+
430
+ it 'injects routes into routes.rb' do
431
+ Dir.chdir(destination_root) do
432
+ generator.send(:generate_controllers_tests)
433
+ end
434
+
435
+ expect(generator).to have_received(:inject_into_file).with('config/routes.rb', anything, after: "Rails.application.routes.draw do\n")
436
+ end
437
+
438
+ it 'displays success message' do
439
+ generator.send(:generate_controllers_tests)
440
+
441
+ expect(generator).to have_received(:say).with('Generate tests controller for frontend feature testing', :green)
442
+ end
443
+ end
444
+
445
+ describe '#app_name' do
446
+ let(:generator) do
447
+ described_class.new([], setup: true).tap do |g|
448
+ g.destination_root = destination_root
449
+ end
450
+ end
451
+
452
+ context 'with valid Rails application name' do
453
+ before do
454
+ stub_const('Rails', Class.new)
455
+ allow(Rails).to receive_message_chain(:application, :class, :module_parent_name).and_return('TestApp')
456
+ end
457
+
458
+ it 'returns underscored application name' do
459
+ result = generator.send(:app_name)
460
+ expect(result).to eq('test_app')
461
+ end
462
+
463
+ it 'memoizes the result' do
464
+ first_call = generator.send(:app_name)
465
+ second_call = generator.send(:app_name)
466
+
467
+ expect(first_call).to eq(second_call)
468
+ expect(generator.instance_variable_get(:@app_name)).to eq('test_app')
469
+ end
470
+ end
471
+
472
+ context 'when error occurs' do
473
+ before do
474
+ stub_const('Rails', Class.new)
475
+ allow(Rails).to receive_message_chain(:application, :class, :module_parent_name).and_raise(StandardError)
476
+ end
477
+
478
+ it 'falls back to app' do
479
+ result = generator.send(:app_name)
480
+ expect(result).to eq('app')
481
+ end
482
+ end
483
+ end
484
+
485
+ describe '#source_code_dir' do
486
+ let(:generator) do
487
+ described_class.new([], setup: true).tap do |g|
488
+ g.destination_root = destination_root
489
+ end
490
+ end
491
+
492
+ it 'returns app/frontend' do
493
+ result = generator.send(:source_code_dir)
494
+ expect(result).to eq('app/frontend')
495
+ end
496
+
497
+ it 'memoizes the result' do
498
+ first_call = generator.send(:source_code_dir)
499
+ second_call = generator.send(:source_code_dir)
500
+
501
+ expect(first_call).to eq(second_call)
502
+ expect(generator.instance_variable_get(:@source_code_dir)).to eq('app/frontend')
503
+ end
504
+ end
505
+
506
+ describe '#modify_layout_for_vite' do
507
+ let(:generator) do
508
+ described_class.new([], setup: true).tap do |g|
509
+ g.destination_root = destination_root
510
+ end
511
+ end
512
+
513
+ before do
514
+ allow(generator).to receive(:template)
515
+ allow(generator).to receive(:directory)
516
+ allow(generator).to receive(:say)
517
+ end
518
+
519
+ it 'calls template for all layout files' do
520
+ generator.send(:modify_layout_for_vite)
521
+
522
+ expect(generator).to have_received(:template).with('views/layouts/application.html.erb.tt', File.join('app', 'views/layouts/application.html.erb'))
523
+ expect(generator).to have_received(:template).with('views/layouts/dashboard/application.html.erb.tt', File.join('app', 'views/layouts/owner/application.html.erb'))
524
+ expect(generator).to have_received(:template).with('views/layouts/dashboard/_sidebar.html.erb.tt', File.join('app', 'views/components/layouts/_sidebar.html.erb'))
525
+ end
526
+
527
+ it 'calls directory for helpers' do
528
+ generator.send(:modify_layout_for_vite)
529
+
530
+ expect(generator).to have_received(:directory).with('helpers', File.join('app', 'helpers'))
531
+ end
532
+
533
+ it 'displays success message' do
534
+ generator.send(:modify_layout_for_vite)
535
+
536
+ expect(generator).to have_received(:say).with('Updated application layout for Vite integration', :green)
537
+ end
538
+ end
539
+ end
@@ -1,3 +1,5 @@
1
+ require 'rails/generators'
2
+
1
3
  module SunSword
2
4
  class InitGenerator < Rails::Generators::Base
3
5
  source_root File.expand_path('templates_init', __dir__)
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+ require 'generators/sun_sword/init_generator'
5
+
6
+ RSpec.describe SunSword::InitGenerator, type: :generator do
7
+ include FileUtils
8
+
9
+ let(:destination_root) { File.expand_path('../tmp', __dir__) }
10
+
11
+ before do
12
+ FileUtils.mkdir_p(destination_root) unless Dir.exist?(destination_root)
13
+ end
14
+
15
+ after do
16
+ FileUtils.rm_rf(destination_root) if Dir.exist?(destination_root)
17
+ end
18
+
19
+ describe 'source root' do
20
+ it 'has the correct source root' do
21
+ source_path = File.expand_path('templates_init', File.dirname(__FILE__))
22
+ expect(described_class.source_root).to eq(source_path)
23
+ end
24
+ end
25
+
26
+ describe '#setup_configuration' do
27
+ it 'calls copy_initializer with sun_sword' do
28
+ generator = described_class.new([], {})
29
+ generator.destination_root = destination_root
30
+
31
+ allow(generator).to receive(:copy_initializer)
32
+
33
+ generator.setup_configuration
34
+
35
+ expect(generator).to have_received(:copy_initializer).with('sun_sword')
36
+ end
37
+ end
38
+
39
+ describe '#copy_initializer' do
40
+ let(:generator) do
41
+ described_class.new([], {}).tap do |g|
42
+ g.destination_root = destination_root
43
+ end
44
+ end
45
+
46
+ it 'copies initializer template to correct location' do
47
+ allow(generator).to receive(:template)
48
+
49
+ generator.send(:copy_initializer, 'sun_sword')
50
+
51
+ expect(generator).to have_received(:template).with(
52
+ 'config/initializers/sun_sword.rb',
53
+ 'config/initializers/sun_sword.rb'
54
+ )
55
+ end
56
+
57
+ it 'works with different file names' do
58
+ allow(generator).to receive(:template)
59
+
60
+ generator.send(:copy_initializer, 'custom_config')
61
+
62
+ expect(generator).to have_received(:template).with(
63
+ 'config/initializers/custom_config.rb',
64
+ 'config/initializers/custom_config.rb'
65
+ )
66
+ end
67
+ end
68
+
69
+ describe 'integration test' do
70
+ it 'can be instantiated' do
71
+ generator = described_class.new([], {})
72
+ expect(generator).to be_a(described_class)
73
+ end
74
+
75
+ it 'runs setup_configuration method' do
76
+ generator = described_class.new([], {})
77
+ generator.destination_root = destination_root
78
+
79
+ expect(generator).to respond_to(:setup_configuration)
80
+ end
81
+ end
82
+ end