panda-core 0.9.3 → 0.9.4
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/lib/panda/core/asset_loader.rb +10 -0
- data/lib/panda/core/engine.rb +0 -4
- data/lib/panda/core/module_registry.rb +3 -3
- data/lib/panda/core/testing/support/system/browser_console_logger.rb +49 -0
- data/lib/panda/core/testing/support/system/{capybara_setup.rb → capybara_config.rb} +2 -0
- data/lib/panda/core/testing/support/system/ci_capybara_config.rb +8 -2
- data/lib/panda/core/testing/support/system/cuprite_setup.rb +5 -2
- data/lib/panda/core/version.rb +2 -1
- metadata +30 -17
- data/lib/panda/core/testing/support/generator_spec_helper.rb +0 -97
- data/lib/tasks/assets.rake +0 -159
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '04695145fc8e1f8c8bdd13d1ee35d91e1a3eb470070d265463f72e97f9ddd19c'
|
|
4
|
+
data.tar.gz: 509bd365e3b501f2f34d0add9617f29b757dcb1b2ca6db6d65c6f1dccfc2142f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3187a5adef002caceeda919102eb8f281aad08058bdc53a10be6297fcc78edaeecade4cdd6ead4246d6596f4fdbd1d37c44d1a2b280bb91023de20b6dc9a75c9
|
|
7
|
+
data.tar.gz: 6b7ee0a2d2dc9fcfd4c35bde5217a6390d700085dfdb52417189e702c9906d446d5a8d4f89efb21db8c14bd38962a4f23a7c4748b797f7cc235db349b6d7c7c8
|
|
@@ -248,6 +248,16 @@ module Panda
|
|
|
248
248
|
options[:src] = source.start_with?("/") ? source : "/assets/#{source}"
|
|
249
249
|
content_tag(:script, "", options)
|
|
250
250
|
end
|
|
251
|
+
|
|
252
|
+
def self.last_dummy_asset_report
|
|
253
|
+
# Only expose this in test/CI/development — never in production
|
|
254
|
+
return nil unless Rails.env.test? || ENV["CI"].present?
|
|
255
|
+
|
|
256
|
+
if defined?(Panda::Core::Assets::ReportRegistry) &&
|
|
257
|
+
Panda::Core::Assets::ReportRegistry.present?
|
|
258
|
+
Panda::Core::Assets::ReportRegistry.last
|
|
259
|
+
end
|
|
260
|
+
end
|
|
251
261
|
end
|
|
252
262
|
end
|
|
253
263
|
end
|
data/lib/panda/core/engine.rb
CHANGED
|
@@ -92,11 +92,7 @@ module Panda
|
|
|
92
92
|
|
|
93
93
|
# Compile CSS with timestamp
|
|
94
94
|
require "open3"
|
|
95
|
-
require "fileutils"
|
|
96
95
|
|
|
97
|
-
FileUtils.mkdir_p(assets_dir)
|
|
98
|
-
|
|
99
|
-
# Get content paths from ModuleRegistry
|
|
100
96
|
content_paths = Panda::Core::ModuleRegistry.tailwind_content_paths
|
|
101
97
|
content_flags = content_paths.map { |path| "--content '#{path}'" }.join(" ")
|
|
102
98
|
|
|
@@ -306,15 +306,15 @@ module Panda
|
|
|
306
306
|
file_path = find_javascript_file(relative_path)
|
|
307
307
|
|
|
308
308
|
if file_path && File.file?(file_path)
|
|
309
|
-
puts "[JavaScriptMiddleware] Serving: #{path} from #{file_path}"
|
|
309
|
+
puts "[JavaScriptMiddleware] Serving: #{path} from #{file_path}" if ENV["RSPEC_DEBUG"]
|
|
310
310
|
serve_file(file_path, env)
|
|
311
311
|
else
|
|
312
|
-
puts "[JavaScriptMiddleware] Not found: #{path} (tried #{relative_path})"
|
|
312
|
+
puts "[JavaScriptMiddleware] Not found: #{path} (tried #{relative_path})" if ENV["RSPEC_DEBUG"]
|
|
313
313
|
@app.call(env)
|
|
314
314
|
end
|
|
315
315
|
rescue => e
|
|
316
316
|
# On error, log and pass to next middleware
|
|
317
|
-
puts "[JavaScriptMiddleware] Error: #{e.message}"
|
|
317
|
+
puts "[JavaScriptMiddleware] Error: #{e.message}" if ENV["RSPEC_DEBUG"]
|
|
318
318
|
Rails.logger.error("[ModuleRegistry::JavaScriptMiddleware] Error: #{e.message}\n#{e.backtrace.join("\n")}") if defined?(Rails.logger)
|
|
319
319
|
@app.call(env)
|
|
320
320
|
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Capture and log browser console output for debugging CI failures
|
|
4
|
+
module BrowserConsoleLogger
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.after do |example|
|
|
7
|
+
# Only log console in CI when test fails
|
|
8
|
+
next unless ENV["CI"] && example.exception
|
|
9
|
+
|
|
10
|
+
if respond_to?(:page) && page.driver.is_a?(Capybara::Cuprite::Driver)
|
|
11
|
+
begin
|
|
12
|
+
console_logs = page.driver.browser.console_messages
|
|
13
|
+
|
|
14
|
+
if console_logs.any?
|
|
15
|
+
puts "\n" + "=" * 80
|
|
16
|
+
puts "BROWSER CONSOLE OUTPUT (#{console_logs.length} messages)"
|
|
17
|
+
puts "=" * 80
|
|
18
|
+
|
|
19
|
+
console_logs.each_with_index do |msg, index|
|
|
20
|
+
type_icon = case msg["type"]
|
|
21
|
+
when "error" then "❌"
|
|
22
|
+
when "warning" then "⚠️"
|
|
23
|
+
when "info" then "ℹ️"
|
|
24
|
+
else "📝"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
puts "#{index + 1}. [#{msg["type"].upcase}] #{type_icon}"
|
|
28
|
+
puts " Message: #{msg["message"]}"
|
|
29
|
+
puts " Source: #{msg["source"]}" if msg["source"]
|
|
30
|
+
puts " Line: #{msg["line"]}" if msg["line"]
|
|
31
|
+
puts ""
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
puts "=" * 80
|
|
35
|
+
else
|
|
36
|
+
puts "\n⚠️ No console messages captured (browser may not have started)"
|
|
37
|
+
end
|
|
38
|
+
rescue => e
|
|
39
|
+
puts "\n⚠️ Failed to capture console logs: #{e.message}"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Include in all system tests
|
|
47
|
+
RSpec.configure do |config|
|
|
48
|
+
config.include BrowserConsoleLogger, type: :system
|
|
49
|
+
end
|
|
@@ -32,6 +32,8 @@ Capybara.singleton_class.prepend(Module.new do
|
|
|
32
32
|
end)
|
|
33
33
|
|
|
34
34
|
# Configure server host and port
|
|
35
|
+
# This is loaded for all environments
|
|
36
|
+
# → you do not want fixed ports there
|
|
35
37
|
Capybara.server_host = "127.0.0.1"
|
|
36
38
|
Capybara.server_port = ENV["CAPYBARA_PORT"]&.to_i # Let Capybara choose if not specified
|
|
37
39
|
|
|
@@ -15,11 +15,17 @@ RSpec.configure do |config|
|
|
|
15
15
|
config.before(:suite) do
|
|
16
16
|
Capybara.server = :puma_ci
|
|
17
17
|
Capybara.default_max_wait_time = Integer(ENV.fetch("CAPYBARA_MAX_WAIT_TIME", 5))
|
|
18
|
+
|
|
19
|
+
port = Integer(ENV.fetch("CAPYBARA_PORT", 3001))
|
|
18
20
|
Capybara.server_host = "127.0.0.1"
|
|
21
|
+
Capybara.server_port = port
|
|
22
|
+
Capybara.app_host = "http://127.0.0.1:#{port}"
|
|
19
23
|
Capybara.always_include_port = true
|
|
20
24
|
|
|
21
25
|
puts "[CI Config] Capybara.server = #{Capybara.server.inspect}"
|
|
26
|
+
puts "[CI Config] Capybara.app_host = #{Capybara.app_host.inspect}"
|
|
22
27
|
puts "[CI Config] Capybara.server_host = #{Capybara.server_host.inspect}"
|
|
28
|
+
puts "[CI Config] Capybara.server_port = #{Capybara.server_port.inspect}"
|
|
23
29
|
puts "[CI Config] Capybara.max_wait = #{Capybara.default_max_wait_time}s"
|
|
24
30
|
end
|
|
25
31
|
end
|
|
@@ -35,8 +41,8 @@ Capybara.register_server :puma_ci do |app, port, host|
|
|
|
35
41
|
Port: port,
|
|
36
42
|
Threads: "#{min_threads}:#{max_threads}",
|
|
37
43
|
Workers: 0,
|
|
38
|
-
Silent:
|
|
39
|
-
Verbose:
|
|
44
|
+
Silent: !ENV["RSPEC_DEBUG"],
|
|
45
|
+
Verbose: ENV["RSPEC_DEBUG"],
|
|
40
46
|
PreloadApp: false
|
|
41
47
|
}
|
|
42
48
|
|
|
@@ -19,15 +19,18 @@ module Panda
|
|
|
19
19
|
module CupriteSetup
|
|
20
20
|
# Base Cuprite options shared across all drivers
|
|
21
21
|
def self.base_options
|
|
22
|
+
default_timeout = 2
|
|
23
|
+
default_process_timeout = 2
|
|
24
|
+
|
|
22
25
|
{
|
|
23
26
|
window_size: [1440, 1000],
|
|
24
27
|
inspector: ENV["INSPECTOR"].in?(%w[y 1 yes true]),
|
|
25
28
|
headless: !ENV["HEADLESS"].in?(%w[n 0 no false]),
|
|
26
29
|
slowmo: ENV["SLOWMO"]&.to_f || 0,
|
|
27
|
-
timeout: ENV["CUPRITE_TIMEOUT"]&.to_i ||
|
|
30
|
+
timeout: ENV["CUPRITE_TIMEOUT"]&.to_i || default_timeout,
|
|
28
31
|
js_errors: true, # IMPORTANT: Report JavaScript errors as test failures
|
|
29
32
|
ignore_default_browser_options: false,
|
|
30
|
-
process_timeout: ENV["CUPRITE_PROCESS_TIMEOUT"]&.to_i ||
|
|
33
|
+
process_timeout: ENV["CUPRITE_PROCESS_TIMEOUT"]&.to_i || default_process_timeout,
|
|
31
34
|
wait_for_network_idle: false, # Don't wait for all network requests
|
|
32
35
|
pending_connection_errors: false, # Don't fail on pending external connections
|
|
33
36
|
browser_options: {
|
data/lib/panda/core/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: panda-core
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.9.
|
|
4
|
+
version: 0.9.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Otaina Limited
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2025-11-
|
|
12
|
+
date: 2025-11-15 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: image_processing
|
|
@@ -194,7 +194,21 @@ dependencies:
|
|
|
194
194
|
- !ruby/object:Gem::Version
|
|
195
195
|
version: '0'
|
|
196
196
|
- !ruby/object:Gem::Dependency
|
|
197
|
-
name:
|
|
197
|
+
name: webrick
|
|
198
|
+
requirement: !ruby/object:Gem::Requirement
|
|
199
|
+
requirements:
|
|
200
|
+
- - ">="
|
|
201
|
+
- !ruby/object:Gem::Version
|
|
202
|
+
version: '0'
|
|
203
|
+
type: :runtime
|
|
204
|
+
prerelease: false
|
|
205
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
206
|
+
requirements:
|
|
207
|
+
- - ">="
|
|
208
|
+
- !ruby/object:Gem::Version
|
|
209
|
+
version: '0'
|
|
210
|
+
- !ruby/object:Gem::Dependency
|
|
211
|
+
name: benchmark
|
|
198
212
|
requirement: !ruby/object:Gem::Requirement
|
|
199
213
|
requirements:
|
|
200
214
|
- - ">="
|
|
@@ -208,7 +222,7 @@ dependencies:
|
|
|
208
222
|
- !ruby/object:Gem::Version
|
|
209
223
|
version: '0'
|
|
210
224
|
- !ruby/object:Gem::Dependency
|
|
211
|
-
name: rails
|
|
225
|
+
name: rspec-rails
|
|
212
226
|
requirement: !ruby/object:Gem::Requirement
|
|
213
227
|
requirements:
|
|
214
228
|
- - ">="
|
|
@@ -222,7 +236,7 @@ dependencies:
|
|
|
222
236
|
- !ruby/object:Gem::Version
|
|
223
237
|
version: '0'
|
|
224
238
|
- !ruby/object:Gem::Dependency
|
|
225
|
-
name:
|
|
239
|
+
name: rails-controller-testing
|
|
226
240
|
requirement: !ruby/object:Gem::Requirement
|
|
227
241
|
requirements:
|
|
228
242
|
- - ">="
|
|
@@ -236,7 +250,7 @@ dependencies:
|
|
|
236
250
|
- !ruby/object:Gem::Version
|
|
237
251
|
version: '0'
|
|
238
252
|
- !ruby/object:Gem::Dependency
|
|
239
|
-
name:
|
|
253
|
+
name: capybara
|
|
240
254
|
requirement: !ruby/object:Gem::Requirement
|
|
241
255
|
requirements:
|
|
242
256
|
- - ">="
|
|
@@ -250,7 +264,7 @@ dependencies:
|
|
|
250
264
|
- !ruby/object:Gem::Version
|
|
251
265
|
version: '0'
|
|
252
266
|
- !ruby/object:Gem::Dependency
|
|
253
|
-
name:
|
|
267
|
+
name: cuprite
|
|
254
268
|
requirement: !ruby/object:Gem::Requirement
|
|
255
269
|
requirements:
|
|
256
270
|
- - ">="
|
|
@@ -264,7 +278,7 @@ dependencies:
|
|
|
264
278
|
- !ruby/object:Gem::Version
|
|
265
279
|
version: '0'
|
|
266
280
|
- !ruby/object:Gem::Dependency
|
|
267
|
-
name:
|
|
281
|
+
name: database_cleaner-active_record
|
|
268
282
|
requirement: !ruby/object:Gem::Requirement
|
|
269
283
|
requirements:
|
|
270
284
|
- - ">="
|
|
@@ -278,7 +292,7 @@ dependencies:
|
|
|
278
292
|
- !ruby/object:Gem::Version
|
|
279
293
|
version: '0'
|
|
280
294
|
- !ruby/object:Gem::Dependency
|
|
281
|
-
name:
|
|
295
|
+
name: shoulda-matchers
|
|
282
296
|
requirement: !ruby/object:Gem::Requirement
|
|
283
297
|
requirements:
|
|
284
298
|
- - ">="
|
|
@@ -292,7 +306,7 @@ dependencies:
|
|
|
292
306
|
- !ruby/object:Gem::Version
|
|
293
307
|
version: '0'
|
|
294
308
|
- !ruby/object:Gem::Dependency
|
|
295
|
-
name: simplecov
|
|
309
|
+
name: simplecov
|
|
296
310
|
requirement: !ruby/object:Gem::Requirement
|
|
297
311
|
requirements:
|
|
298
312
|
- - ">="
|
|
@@ -306,7 +320,7 @@ dependencies:
|
|
|
306
320
|
- !ruby/object:Gem::Version
|
|
307
321
|
version: '0'
|
|
308
322
|
- !ruby/object:Gem::Dependency
|
|
309
|
-
name:
|
|
323
|
+
name: simplecov-json
|
|
310
324
|
requirement: !ruby/object:Gem::Requirement
|
|
311
325
|
requirements:
|
|
312
326
|
- - ">="
|
|
@@ -320,7 +334,7 @@ dependencies:
|
|
|
320
334
|
- !ruby/object:Gem::Version
|
|
321
335
|
version: '0'
|
|
322
336
|
- !ruby/object:Gem::Dependency
|
|
323
|
-
name:
|
|
337
|
+
name: standard
|
|
324
338
|
requirement: !ruby/object:Gem::Requirement
|
|
325
339
|
requirements:
|
|
326
340
|
- - ">="
|
|
@@ -334,7 +348,7 @@ dependencies:
|
|
|
334
348
|
- !ruby/object:Gem::Version
|
|
335
349
|
version: '0'
|
|
336
350
|
- !ruby/object:Gem::Dependency
|
|
337
|
-
name:
|
|
351
|
+
name: brakeman
|
|
338
352
|
requirement: !ruby/object:Gem::Requirement
|
|
339
353
|
requirements:
|
|
340
354
|
- - ">="
|
|
@@ -348,7 +362,7 @@ dependencies:
|
|
|
348
362
|
- !ruby/object:Gem::Version
|
|
349
363
|
version: '0'
|
|
350
364
|
- !ruby/object:Gem::Dependency
|
|
351
|
-
name:
|
|
365
|
+
name: bundler-audit
|
|
352
366
|
requirement: !ruby/object:Gem::Requirement
|
|
353
367
|
requirements:
|
|
354
368
|
- - ">="
|
|
@@ -502,20 +516,19 @@ files:
|
|
|
502
516
|
- lib/panda/core/testing/rails_helper.rb
|
|
503
517
|
- lib/panda/core/testing/support/authentication_helpers.rb
|
|
504
518
|
- lib/panda/core/testing/support/authentication_test_helpers.rb
|
|
505
|
-
- lib/panda/core/testing/support/generator_spec_helper.rb
|
|
506
519
|
- lib/panda/core/testing/support/html_helpers.rb
|
|
507
520
|
- lib/panda/core/testing/support/omniauth_setup.rb
|
|
508
521
|
- lib/panda/core/testing/support/service_stubs.rb
|
|
509
522
|
- lib/panda/core/testing/support/setup.rb
|
|
510
523
|
- lib/panda/core/testing/support/system/better_system_tests.rb
|
|
511
|
-
- lib/panda/core/testing/support/system/
|
|
524
|
+
- lib/panda/core/testing/support/system/browser_console_logger.rb
|
|
525
|
+
- lib/panda/core/testing/support/system/capybara_config.rb
|
|
512
526
|
- lib/panda/core/testing/support/system/ci_capybara_config.rb
|
|
513
527
|
- lib/panda/core/testing/support/system/cuprite_helpers.rb
|
|
514
528
|
- lib/panda/core/testing/support/system/cuprite_setup.rb
|
|
515
529
|
- lib/panda/core/testing/support/system/database_connection_helpers.rb
|
|
516
530
|
- lib/panda/core/testing/support/system/system_test_helpers.rb
|
|
517
531
|
- lib/panda/core/version.rb
|
|
518
|
-
- lib/tasks/assets.rake
|
|
519
532
|
- lib/tasks/panda/core/migrations.rake
|
|
520
533
|
- lib/tasks/panda_core.rake
|
|
521
534
|
- lib/tasks/panda_core_tasks.rake
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
require "rails/generators"
|
|
2
|
-
|
|
3
|
-
module GeneratorSpecHelper
|
|
4
|
-
extend ActiveSupport::Concern
|
|
5
|
-
|
|
6
|
-
included do
|
|
7
|
-
before(:each) do
|
|
8
|
-
prepare_destination
|
|
9
|
-
@original_stdout = $stdout
|
|
10
|
-
$stdout = File.new(File::NULL, "w")
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
after(:each) do
|
|
14
|
-
FileUtils.rm_rf(destination_root)
|
|
15
|
-
$stdout = @original_stdout
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def destination_root
|
|
20
|
-
@destination_root ||= File.expand_path("../../tmp/generators", __dir__)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def prepare_destination
|
|
24
|
-
FileUtils.rm_rf(destination_root)
|
|
25
|
-
FileUtils.mkdir_p(destination_root)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def run_generator(args = [])
|
|
29
|
-
args = Array(args)
|
|
30
|
-
# Use the generator namespace instead of class name
|
|
31
|
-
generator_name = described_class.namespace
|
|
32
|
-
Rails::Generators.invoke(generator_name, args, destination_root: destination_root)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def generator
|
|
36
|
-
@generator ||= described_class.new([], destination_root: destination_root)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def file_exists?(path)
|
|
40
|
-
File.exist?(File.join(destination_root, path))
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def read_file(path)
|
|
44
|
-
File.read(File.join(destination_root, path))
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
private
|
|
48
|
-
|
|
49
|
-
def capture(stream)
|
|
50
|
-
stream = stream.to_s
|
|
51
|
-
captured_stream = StringIO.new
|
|
52
|
-
|
|
53
|
-
# Map stream names to their global variables to avoid eval
|
|
54
|
-
streams = {
|
|
55
|
-
"stdout" => $stdout,
|
|
56
|
-
"stderr" => $stderr,
|
|
57
|
-
"stdin" => $stdin
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
original_stream = streams[stream]
|
|
61
|
-
case stream
|
|
62
|
-
when "stdout"
|
|
63
|
-
$stdout = captured_stream
|
|
64
|
-
when "stderr"
|
|
65
|
-
$stderr = captured_stream
|
|
66
|
-
when "stdin"
|
|
67
|
-
$stdin = captured_stream
|
|
68
|
-
else
|
|
69
|
-
raise ArgumentError, "Unsupported stream: #{stream}"
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
yield
|
|
73
|
-
captured_stream.string
|
|
74
|
-
ensure
|
|
75
|
-
case stream
|
|
76
|
-
when "stdout"
|
|
77
|
-
$stdout = original_stream
|
|
78
|
-
when "stderr"
|
|
79
|
-
$stderr = original_stream
|
|
80
|
-
when "stdin"
|
|
81
|
-
$stdin = original_stream
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
RSpec.configure do |config|
|
|
87
|
-
config.include GeneratorSpecHelper, type: :generator
|
|
88
|
-
|
|
89
|
-
# Ensure generator tests have a clean environment
|
|
90
|
-
config.before(:each, type: :generator) do
|
|
91
|
-
prepare_destination
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
config.after(:each, type: :generator) do
|
|
95
|
-
FileUtils.rm_rf(destination_root) if defined?(destination_root)
|
|
96
|
-
end
|
|
97
|
-
end
|
data/lib/tasks/assets.rake
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
# Panda Core Asset Tasks
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
namespace :panda do
|
|
8
|
-
namespace :core do
|
|
9
|
-
namespace :assets do
|
|
10
|
-
# =========================================================
|
|
11
|
-
# 1) ENGINE CSS COMPILATION (unchanged, just cleaned)
|
|
12
|
-
# =========================================================
|
|
13
|
-
|
|
14
|
-
desc "Compile Panda Core CSS assets (development mode)"
|
|
15
|
-
task :compile do
|
|
16
|
-
puts "🐼 Compiling Panda Core CSS assets..."
|
|
17
|
-
|
|
18
|
-
output_dir = panda_engine_root.join("public", "panda-core-assets")
|
|
19
|
-
FileUtils.mkdir_p(output_dir)
|
|
20
|
-
|
|
21
|
-
compile_css_development(output_dir)
|
|
22
|
-
|
|
23
|
-
puts "🎉 CSS compiled → #{output_dir}"
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
desc "Compile and version Panda Core CSS assets for release"
|
|
27
|
-
task :release do
|
|
28
|
-
require_relative "../../panda/core/version"
|
|
29
|
-
|
|
30
|
-
version = Panda::Core::VERSION
|
|
31
|
-
output_dir = panda_engine_root.join("public", "panda-core-assets")
|
|
32
|
-
FileUtils.mkdir_p(output_dir)
|
|
33
|
-
|
|
34
|
-
compile_css_release(output_dir, version)
|
|
35
|
-
|
|
36
|
-
puts "🎉 Release assets compiled"
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# =========================================================
|
|
40
|
-
# CSS INTERNAL HELPERS
|
|
41
|
-
# =========================================================
|
|
42
|
-
|
|
43
|
-
def panda_engine_root
|
|
44
|
-
Panda::Core::Engine.root
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def compile_css_development(output_dir)
|
|
48
|
-
input = panda_engine_root.join("app/assets/tailwind/application.css")
|
|
49
|
-
output = output_dir.join("panda-core.css")
|
|
50
|
-
|
|
51
|
-
content = Panda::Core::ModuleRegistry.tailwind_content_paths
|
|
52
|
-
flags = content.map { |p| "--content '#{p}'" }.join(" ")
|
|
53
|
-
|
|
54
|
-
cmd = "bundle exec tailwindcss -i #{input} -o #{output} #{flags} --minify"
|
|
55
|
-
abort("❌ CSS compile failed") unless system(cmd)
|
|
56
|
-
|
|
57
|
-
puts " ✓ #{output.basename} (#{File.size(output)} bytes)"
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def compile_css_release(output_dir, version)
|
|
61
|
-
input = panda_engine_root.join("app/assets/tailwind/application.css")
|
|
62
|
-
file = output_dir.join("panda-core-#{version}.css")
|
|
63
|
-
|
|
64
|
-
content = Panda::Core::ModuleRegistry.tailwind_content_paths
|
|
65
|
-
flags = content.map { |p| "--content '#{p}'" }.join(" ")
|
|
66
|
-
|
|
67
|
-
cmd = "bundle exec tailwindcss -i #{input} -o #{file} #{flags} --minify"
|
|
68
|
-
abort("❌ CSS release compile failed") unless system(cmd)
|
|
69
|
-
|
|
70
|
-
symlink = output_dir.join("panda-core.css")
|
|
71
|
-
FileUtils.rm_f(symlink)
|
|
72
|
-
FileUtils.ln_sf(file.basename, symlink)
|
|
73
|
-
|
|
74
|
-
puts " ✓ Versioned file + symlink created"
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# =========================================================
|
|
78
|
-
# 2) DUMMY APP PREP (FOR SYSTEM TESTS + CI)
|
|
79
|
-
# =========================================================
|
|
80
|
-
|
|
81
|
-
desc "Compile Panda Core + dummy app assets into spec/dummy/public/assets"
|
|
82
|
-
task compile_dummy: :environment do
|
|
83
|
-
dummy_root = find_dummy_root
|
|
84
|
-
assets_root = dummy_root.join("public/assets")
|
|
85
|
-
|
|
86
|
-
puts "🚧 Compiling dummy assets..."
|
|
87
|
-
puts " → #{assets_root}"
|
|
88
|
-
FileUtils.mkdir_p(assets_root)
|
|
89
|
-
|
|
90
|
-
Dir.chdir(dummy_root) do
|
|
91
|
-
# IMPORTANT: this is now the correct task name
|
|
92
|
-
unless system("bundle exec rake panda:core:assets:compile")
|
|
93
|
-
abort("❌ panda:core:assets:compile failed in dummy app")
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
# Propshaft (Rails 8)
|
|
97
|
-
abort("❌ assets:precompile failed") \
|
|
98
|
-
unless system("bundle exec rake assets:precompile RAILS_ENV=#{Rails.env}")
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
puts "✅ Dummy assets compiled"
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
desc "Generate importmap.json for the dummy app"
|
|
105
|
-
task generate_dummy_importmap: :environment do
|
|
106
|
-
dummy_root = find_dummy_root
|
|
107
|
-
output = dummy_root.join("public/assets/importmap.json")
|
|
108
|
-
|
|
109
|
-
puts "🗺️ Generating importmap.json..."
|
|
110
|
-
FileUtils.mkdir_p(output.dirname)
|
|
111
|
-
|
|
112
|
-
Dir.chdir(dummy_root) do
|
|
113
|
-
json = Rails.application.importmap.to_json(
|
|
114
|
-
resolver: ActionController::Base.helpers
|
|
115
|
-
)
|
|
116
|
-
File.write(output, JSON.pretty_generate(json))
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
puts " ✓ importmap.json written"
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
desc "Verify dummy assets for CI (fail-fast)"
|
|
123
|
-
task verify_dummy: :environment do
|
|
124
|
-
dummy_root = find_dummy_root
|
|
125
|
-
assets = dummy_root.join("public/assets")
|
|
126
|
-
manifest = assets.join(".manifest.json")
|
|
127
|
-
importmap = assets.join("importmap.json")
|
|
128
|
-
|
|
129
|
-
abort("❌ Missing #{assets}") unless assets.exist?
|
|
130
|
-
abort("❌ Missing #{manifest}") unless manifest.exist?
|
|
131
|
-
abort("❌ Missing #{importmap}") unless importmap.exist?
|
|
132
|
-
|
|
133
|
-
begin
|
|
134
|
-
parsed = JSON.parse(File.read(manifest))
|
|
135
|
-
abort("❌ Empty .manifest.json") if parsed.empty?
|
|
136
|
-
rescue
|
|
137
|
-
abort("❌ Invalid .manifest.json")
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
puts "✅ Dummy assets verified"
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
# =========================================================
|
|
144
|
-
# INTERNAL UTILITIES
|
|
145
|
-
# =========================================================
|
|
146
|
-
|
|
147
|
-
def find_dummy_root
|
|
148
|
-
root = Rails.root
|
|
149
|
-
|
|
150
|
-
return root if root.basename.to_s == "dummy"
|
|
151
|
-
|
|
152
|
-
candidate = root.join("spec/dummy")
|
|
153
|
-
return candidate if candidate.exist?
|
|
154
|
-
|
|
155
|
-
abort("❌ Cannot find dummy root — expected #{candidate}")
|
|
156
|
-
end
|
|
157
|
-
end
|
|
158
|
-
end
|
|
159
|
-
end
|