From d7476e239ac7d97fdcfb37c9c6cec861fe47e07a Mon Sep 17 00:00:00 2001 From: DualFroz Date: Wed, 9 Sep 2026 20:10:53 +0200 Subject: [PATCH] test: cover CliDbTest and teardown --- test/test_cli_db.rb | 174 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 test/test_cli_db.rb diff --git a/test/test_cli_db.rb b/test/test_cli_db.rb new file mode 100644 index 0000000..49a14a9 --- /dev/null +++ b/test/test_cli_db.rb @@ -0,0 +1,174 @@ +require 'minitest/autorun' +require 'prism' +require 'stringio' +require 'tmpdir' +require 'fileutils' + +class CliDbTest < Minitest::Test + def setup + @workdir = Dir.mktmpdir('prism-cli-db') + @cli = Prism::Cli.new(@workdir) + @database = 'db/test.pstore' + FileUtils.mkdir_p(File.join(@workdir, 'db', 'migrate')) + end + + def teardown + FileUtils.remove_entry(@workdir) + end + + def write_migration(version, class_name, body) + path = File.join(@workdir, 'db', 'migrate', "#{version}_#{Prism::Inflector.underscore(class_name)}.rb") + File.write(path, <<~RUBY) + class #{class_name} < Prism::Orm::Migration + #{body} + end + RUBY + path + end + + def widgets_migration(version = '20260101000001') + write_migration(version, 'CreateWidgetsForCliDbTest', <<~RUBY) + def up + create_table :widgets_for_cli_db_test do |t| + t.string :name + end + end + + def down + drop_table :widgets_for_cli_db_test + end + RUBY + end + + def gadgets_migration(version = '20260101000002') + write_migration(version, 'CreateGadgetsForCliDbTest', <<~RUBY) + def up + create_table :gadgets_for_cli_db_test do |t| + t.string :label + end + end + + def down + drop_table :gadgets_for_cli_db_test + end + RUBY + end + + def store + Prism::Orm::Store.new(File.join(@workdir, @database)) + end + + def test_db_migrate_applies_pending_migrations_and_reports_them + widgets_migration + out = StringIO.new + applied = @cli.db_migrate(["--database=#{@database}"], out: out) + + assert_equal ['20260101000001'], applied + assert_includes out.string, 'migrated 20260101000001' + assert store.table_exists?(:widgets_for_cli_db_test) + end + + def test_db_migrate_with_nothing_pending_reports_that_instead_of_erroring + widgets_migration + @cli.db_migrate(["--database=#{@database}"], out: StringIO.new) + + out = StringIO.new + applied = @cli.db_migrate(["--database=#{@database}"], out: out) + + assert_empty applied + assert_includes out.string, 'no pending migrations' + end + + def test_db_migrate_dispatches_through_run + widgets_migration + capture_io { @cli.run(['db:migrate', "--database=#{@database}"]) } + assert store.table_exists?(:widgets_for_cli_db_test) + end + + def test_db_rollback_defaults_to_one_step + widgets_migration + gadgets_migration + @cli.db_migrate(["--database=#{@database}"], out: StringIO.new) + assert store.table_exists?(:gadgets_for_cli_db_test) + + out = StringIO.new + reverted = @cli.db_rollback(["--database=#{@database}"], out: out) + + assert_equal ['20260101000002'], reverted + assert_includes out.string, 'rolled back 20260101000002' + refute store.table_exists?(:gadgets_for_cli_db_test) + assert store.table_exists?(:widgets_for_cli_db_test), 'earlier migration must survive a single-step rollback' + end + + def test_db_rollback_honors_explicit_step_count + widgets_migration + gadgets_migration + @cli.db_migrate(["--database=#{@database}"], out: StringIO.new) + + reverted = @cli.db_rollback(["--database=#{@database}", '--step=2'], out: StringIO.new) + + assert_equal ['20260101000002', '20260101000001'], reverted + refute store.table_exists?(:gadgets_for_cli_db_test) + refute store.table_exists?(:widgets_for_cli_db_test) + end + + def test_db_rollback_with_nothing_applied_reports_that_instead_of_erroring + widgets_migration + out = StringIO.new + reverted = @cli.db_rollback(["--database=#{@database}"], out: out) + + assert_empty reverted + assert_includes out.string, 'nothing to roll back' + end + + def test_db_status_marks_applied_migrations_up_and_the_rest_down + widgets_migration + gadgets_migration + @cli.db_migrate(["--database=#{@database}"], out: StringIO.new) + @cli.db_rollback(["--database=#{@database}"], out: StringIO.new) + + out = StringIO.new + status = @cli.db_status(["--database=#{@database}"], out: out) + + assert_equal [['20260101000001', true], ['20260101000002', false]], + status.map { |entry, applied| [entry.version, applied] } + assert_match(/up\s+20260101000001\s+create_widgets_for_cli_db_test/, out.string) + assert_match(/down\s+20260101000002\s+create_gadgets_for_cli_db_test/, out.string) + end + + def test_db_status_with_no_migration_files_prints_only_the_header + out = StringIO.new + status = @cli.db_status(["--database=#{@database}"], out: out) + + assert_empty status + assert_equal "STATUS VERSION NAME\n", out.string + end + + def test_db_commands_use_the_migrations_flag_to_find_a_custom_directory + FileUtils.mkdir_p(File.join(@workdir, 'other_migrations')) + File.write(File.join(@workdir, 'other_migrations', '20260101000003_create_thingies_for_cli_db_test.rb'), <<~RUBY) + class CreateThingiesForCliDbTest < Prism::Orm::Migration + def up + create_table :thingies_for_cli_db_test do |t| + t.string :name + end + end + + def down + drop_table :thingies_for_cli_db_test + end + end + RUBY + + applied = @cli.db_migrate(["--database=#{@database}", '--migrations=other_migrations'], out: StringIO.new) + + assert_equal ['20260101000003'], applied + assert store.table_exists?(:thingies_for_cli_db_test) + end + + def test_db_options_reject_unknown_flags + assert_raises(Prism::Cli::UsageError) { @cli.db_migrate(['--bogus=1']) } + assert_raises(Prism::Cli::UsageError) { @cli.db_rollback(['--bogus=1']) } + assert_raises(Prism::Cli::UsageError) { @cli.db_status(['--bogus=1']) } + end +end