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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +57 -2
- data/Gemfile +20 -0
- data/Gemfile.lock +252 -0
- data/README.md +74 -15
- data/Rakefile +6 -10
- data/lib/generators/sun_sword/USAGE +22 -3
- data/lib/generators/sun_sword/frontend_generator.rb +77 -39
- data/lib/generators/sun_sword/frontend_generator_spec.rb +539 -0
- data/lib/generators/sun_sword/init_generator.rb +2 -0
- data/lib/generators/sun_sword/init_generator_spec.rb +82 -0
- data/lib/generators/sun_sword/scaffold_generator.rb +212 -29
- data/lib/generators/sun_sword/scaffold_generator_spec.rb +1414 -0
- data/lib/generators/sun_sword/templates_frontend/{Procfile.dev → Procfile.dev.tt} +1 -0
- data/lib/generators/sun_sword/templates_frontend/bin/{watch → watch.tt} +2 -1
- data/lib/generators/sun_sword/templates_frontend/config/{vite.json → vite.json.tt} +2 -1
- data/lib/generators/sun_sword/templates_frontend/controllers/application_controller.rb.tt +2 -2
- data/lib/generators/sun_sword/templates_frontend/controllers/tests_controller.rb +36 -0
- data/lib/generators/sun_sword/templates_frontend/controllers/tests_controller_spec.rb +62 -0
- data/lib/generators/sun_sword/templates_frontend/env.development +1 -1
- data/lib/generators/sun_sword/templates_frontend/frontend/entrypoints/application.js +2 -2
- data/lib/generators/sun_sword/templates_frontend/frontend/pages/tests-stimulus.js +31 -0
- data/lib/generators/sun_sword/templates_frontend/frontend/pages/web.js +12 -0
- data/lib/generators/sun_sword/templates_frontend/frontend/stylesheets/application.css +1 -3
- data/lib/generators/sun_sword/templates_frontend/helpers/application_helper.rb +17 -0
- data/lib/generators/sun_sword/templates_frontend/helpers/application_helper_spec.rb +30 -0
- data/lib/generators/sun_sword/templates_frontend/package.json.tt +14 -0
- data/lib/generators/sun_sword/templates_frontend/views/components/_action_destroy.html.erb.tt +1 -1
- data/lib/generators/sun_sword/templates_frontend/views/components/_alert.html.erb.tt +1 -1
- data/lib/generators/sun_sword/templates_frontend/views/layouts/application.html.erb.tt +3 -3
- data/lib/generators/sun_sword/templates_frontend/views/tests/_frame_content.html.erb +9 -0
- data/lib/generators/sun_sword/templates_frontend/views/tests/_log_entry.html.erb +4 -0
- data/lib/generators/sun_sword/templates_frontend/views/tests/_updated_content.html.erb +6 -0
- data/lib/generators/sun_sword/templates_frontend/views/tests/stimulus.html.erb +45 -0
- data/lib/generators/sun_sword/templates_frontend/views/tests/turbo_drive.html.erb +55 -0
- data/lib/generators/sun_sword/templates_frontend/views/tests/turbo_frame.html.erb +87 -0
- data/lib/generators/sun_sword/templates_frontend/vite.config.ts.tt +1 -1
- data/lib/generators/sun_sword/templates_init/config/initializers/sun_sword.rb +1 -0
- data/lib/generators/sun_sword/templates_scaffold/controllers/controller.rb.tt +24 -24
- data/lib/generators/sun_sword/templates_scaffold/controllers/controller_spec.rb.tt +398 -0
- data/lib/generators/sun_sword/templates_scaffold/views/index.html.erb.tt +5 -5
- data/lib/generators/sun_sword/templates_scaffold/views/show.html.erb.tt +3 -0
- data/lib/generators/tmp/db/structures/test_structure.yaml +42 -0
- data/lib/sun-sword.rb +1 -0
- data/lib/sun_sword/configuration_spec.rb +77 -0
- data/lib/sun_sword/version.rb +1 -1
- metadata +177 -29
- data/.rspec +0 -3
- data/.rubocop.yml +0 -1146
- data/lib/generators/sun_sword/templates_frontend/controllers/site_controller.rb +0 -16
- data/lib/generators/sun_sword/templates_frontend/db/seeds.rb +0 -3
- data/lib/generators/sun_sword/templates_frontend/db/structures/example.yaml.tt +0 -106
- data/lib/generators/sun_sword/templates_frontend/frontend/pages/stimulus.js +0 -10
- data/lib/generators/sun_sword/templates_frontend/package.json +0 -7
- data/lib/generators/sun_sword/templates_frontend/views/site/_comment.html.erb.tt +0 -3
- 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
|
|
@@ -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
|