Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions lib/tasks/bunko/sample_data.rake
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,21 @@ namespace :bunko do
if Rails.env.production?
puts ""
puts "⚠️ WARNING: You're about to generate sample data in PRODUCTION"
puts " Press Ctrl+C to cancel, or Enter to continue..."
$stdin.gets

confirmed = ENV["CONFIRM_PRODUCTION"] == "true"

if !confirmed && $stdin.tty?
puts " Press Ctrl+C to cancel, or Enter to continue..."
# EOF (nil) is never treated as consent
confirmed = !$stdin.gets.nil?
end

unless confirmed
puts " Cannot confirm interactively (no TTY or stdin closed)."
puts " Re-run with CONFIRM_PRODUCTION=true to proceed."
exit 1
end

puts ""
end

Expand Down Expand Up @@ -52,11 +65,16 @@ namespace :bunko do
puts " Clear existing: #{clear_existing ? "Yes" : "No"}"
puts ""

# Clear existing posts if requested
# Clear existing posts if requested (static pages are preserved, matching
# the generator which manages the "pages" post type separately)
if clear_existing
posts_to_clear = Post.joins(:post_type).where.not(post_types: {name: "pages"})
clear_count = posts_to_clear.count

puts "Clearing existing posts..."
Post.destroy_all
puts "✓ Cleared #{Post.count} posts"
puts " Deleting #{clear_count} post(s) from all post types except 'pages'"
posts_to_clear.destroy_all
puts "✓ Cleared #{clear_count} post(s)"
puts ""
end

Expand Down
139 changes: 139 additions & 0 deletions test/tasks/bunko_sample_data_task_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

require_relative "../test_helper"
require "rake"
require "minitest/mock"

class BunkoSampleDataTaskTest < Minitest::Test
def setup
Expand Down Expand Up @@ -87,6 +88,144 @@ def test_sample_data_clears_existing_when_requested
ENV.delete("CLEAR")
end

def test_sample_data_clear_message_reports_actual_deleted_count
3.times do |i|
Post.create!(
post_type: @blog_type,
title: "Existing Post #{i}",
slug: "existing-post-#{i}",
content: "Test content",
status: "published",
published_at: Time.now
)
end

ENV["COUNT"] = "1"
ENV["CLEAR"] = "true"

output = capture_io do
run_rake_task("bunko:sample_data")
end

# Message must reflect the number of posts actually deleted (not the
# post-deletion count, which is always 0)
assert_match(/Deleting 3 post\(s\) from all post types except 'pages'/, output.join)
assert_match(/Cleared 3 post\(s\)/, output.join)
ensure
ENV.delete("COUNT")
ENV.delete("CLEAR")
end

def test_sample_data_clear_preserves_static_pages
pages_type = PostType.create!(name: "pages", title: "Pages")

Post.create!(
post_type: pages_type,
title: "About Us",
slug: "about-us",
content: "Hand-authored page content",
status: "published",
published_at: Time.now
)

Post.create!(
post_type: @blog_type,
title: "Old Blog Post",
slug: "old-blog-post",
content: "Test content",
status: "published",
published_at: Time.now
)

ENV["COUNT"] = "1"
ENV["CLEAR"] = "true"

# Disable static page generation so the task doesn't create standard
# pages or modify the dummy app's routes file
original_allow = Bunko.configuration.allow_static_pages
Bunko.configuration.allow_static_pages = false

capture_io do
run_rake_task("bunko:sample_data")
end

# Static pages must survive CLEAR=true
assert Post.exists?(slug: "about-us"), "Static page should not be deleted by CLEAR=true"
# Non-page posts are cleared
refute Post.exists?(slug: "old-blog-post")
ensure
Bunko.configuration.allow_static_pages = original_allow
ENV.delete("COUNT")
ENV.delete("CLEAR")
end

def test_sample_data_production_non_interactive_aborts_without_confirmation
ENV["COUNT"] = "1"
ENV.delete("CONFIRM_PRODUCTION")

# $stdin is a StringIO in tests, so $stdin.tty? is false (non-interactive)
production_env = ActiveSupport::StringInquirer.new("production")

output = Rails.stub(:env, production_env) do
capture_io do
assert_raises(SystemExit) do
run_rake_task("bunko:sample_data")
end
end
end

assert_match(/WARNING: You're about to generate sample data in PRODUCTION/, output.join)
assert_match(/CONFIRM_PRODUCTION=true/, output.join)
assert_equal 0, Post.count, "No posts should be created when the production guard aborts"
ensure
ENV.delete("COUNT")
end

def test_sample_data_production_non_interactive_proceeds_with_confirmation
ENV["COUNT"] = "1"
ENV["CONFIRM_PRODUCTION"] = "true"

production_env = ActiveSupport::StringInquirer.new("production")

Rails.stub(:env, production_env) do
capture_io do
run_rake_task("bunko:sample_data")
end
end

assert_equal 3, Post.count # 1 post × 3 post types
ensure
ENV.delete("COUNT")
ENV.delete("CONFIRM_PRODUCTION")
end

def test_sample_data_production_eof_on_gets_aborts
ENV["COUNT"] = "1"
ENV.delete("CONFIRM_PRODUCTION")

# Simulate a TTY whose gets returns nil (EOF) — EOF is never consent
eof_stdin = StringIO.new("")
def eof_stdin.tty?
true
end
$stdin = eof_stdin

production_env = ActiveSupport::StringInquirer.new("production")

output = Rails.stub(:env, production_env) do
capture_io do
assert_raises(SystemExit) do
run_rake_task("bunko:sample_data")
end
end
end

assert_match(/CONFIRM_PRODUCTION=true/, output.join)
assert_equal 0, Post.count
ensure
ENV.delete("COUNT")
end

def test_sample_data_preserves_existing_by_default
# Create an existing post
Post.create!(
Expand Down
Loading