60 |
61 |
We're sorry, but something went wrong.
62 |
63 |
If you are the application owner check the logs for more information.
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/spec/dummyapp/public/apple-touch-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drwl/annotaterb/b66f119ed154f818b3b4937d487e6a76bd17be28/spec/dummyapp/public/apple-touch-icon-precomposed.png
--------------------------------------------------------------------------------
/spec/dummyapp/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drwl/annotaterb/b66f119ed154f818b3b4937d487e6a76bd17be28/spec/dummyapp/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/spec/dummyapp/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/drwl/annotaterb/b66f119ed154f818b3b4937d487e6a76bd17be28/spec/dummyapp/public/favicon.ico
--------------------------------------------------------------------------------
/spec/dummyapp/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2 |
--------------------------------------------------------------------------------
/spec/dummyapp/test/test_helper.rb:
--------------------------------------------------------------------------------
1 | ENV["RAILS_ENV"] ||= "test"
2 | require_relative "../config/environment"
3 | require "rails/test_help"
4 |
5 | class ActiveSupport::TestCase
6 | # Run tests in parallel with specified workers
7 | parallelize(workers: :number_of_processors)
8 |
9 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
10 | fixtures :all
11 |
12 | # Add more helper methods to be used by all tests here...
13 | end
14 |
--------------------------------------------------------------------------------
/spec/integration/annotate_after_migration_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "integration_spec_helper"
4 |
5 | RSpec.describe "Annotate after running migrations", type: "aruba" do
6 | let(:command_timeout_seconds) { 10 }
7 | let(:migration_file) { "20231013230731_add_int_field_to_test_defaults.rb" }
8 | let(:models_dir) { "app/models" }
9 |
10 | it "adds annotations for the new field" do
11 | reset_database
12 | run_migrations
13 |
14 | # Start with the already annotated TestDefault model
15 | copy(model_template("test_default.rb"), models_dir)
16 |
17 | expected_test_default = read_file(model_template("test_default_updated.rb"))
18 | original_test_default = read_file(dummyapp_model("test_default.rb"))
19 |
20 | # Check that files have been copied over correctly
21 | expect(expected_test_default).not_to eq(original_test_default)
22 |
23 | copy(File.join(migrations_template_dir, migration_file), "db/migrate")
24 |
25 | # Apply this specific migration
26 | _run_migrations_cmd = run_command_and_stop("bin/rails db:migrate:up VERSION=20231013230731", fail_on_error: true, exit_timeout: command_timeout_seconds)
27 | _run_annotations_cmd = run_command_and_stop("bundle exec annotaterb models", fail_on_error: true, exit_timeout: command_timeout_seconds)
28 |
29 | annotated_test_default = read_file(dummyapp_model("test_default.rb"))
30 |
31 | expect(last_command_started).to be_successfully_executed
32 | expect(annotated_test_default).to eq(expected_test_default)
33 | end
34 |
35 | context "when the rake task that hooks into database migration exists" do
36 | before do
37 | _cmd = run_command_and_stop("bin/rails g annotate_rb:install", fail_on_error: true, exit_timeout: command_timeout_seconds)
38 | end
39 |
40 | it "annotations are automatically added during migration" do
41 | reset_database
42 |
43 | expected_test_default = read_file(model_template("test_default.rb"))
44 | original_test_default = read_file(dummyapp_model("test_default.rb"))
45 |
46 | # Check that files have been copied over correctly
47 | expect(expected_test_default).not_to eq(original_test_default)
48 |
49 | _run_migrations_cmd = run_command_and_stop("bin/rails db:migrate", fail_on_error: true, exit_timeout: command_timeout_seconds)
50 |
51 | annotated_test_default = read_file(dummyapp_model("test_default.rb"))
52 |
53 | expect(last_command_started).to be_successfully_executed
54 | expect(annotated_test_default).to eq(expected_test_default)
55 | end
56 | end
57 | end
58 |
--------------------------------------------------------------------------------
/spec/integration/annotate_collapsed_models_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "integration_spec_helper"
4 |
5 | RSpec.describe "Annotate collapsed models", type: "aruba" do
6 | let(:models_dir) { "app/models" }
7 | let(:command_timeout_seconds) { 10 }
8 |
9 | context "when annotating collapsed models" do
10 | it "annotates them correctly" do
11 | reset_database
12 | run_migrations
13 |
14 | expected_test_model = read_file(model_template("collapsed_test_model.rb"))
15 |
16 | original_test_model = read_file(dummyapp_model("collapsed/example/test_model.rb"))
17 |
18 | expect(expected_test_model).not_to eq(original_test_model)
19 |
20 | _cmd = run_command_and_stop("bundle exec annotaterb models", fail_on_error: true, exit_timeout: command_timeout_seconds)
21 |
22 | annotated_test_model = read_file(dummyapp_model("collapsed/example/test_model.rb"))
23 |
24 | expect(last_command_started).to be_successfully_executed
25 | expect(expected_test_model).to eq(annotated_test_model)
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/spec/integration/annotate_file_with_existing_annotations_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "integration_spec_helper"
4 |
5 | RSpec.describe "Annotate a file with existing annotations", type: "aruba" do
6 | let(:command_timeout_seconds) { 10 }
7 | let(:models_dir) { "app/models" }
8 | let(:model_file) { "app/models/test_default.rb" }
9 |
10 | context "when using 'force' option and 'position: bottom'" do
11 | before do
12 | # Copy file with existing annotations at the top
13 | copy(model_template("test_default.rb"), "app/models")
14 |
15 | reset_database
16 | run_migrations
17 | end
18 |
19 | it "moves annotations to the bottom of the file" do
20 | expected_test_default = read_file(model_template("test_default_with_bottom_annotations.rb"))
21 | original_test_default = read_file(dummyapp_model("test_default.rb"))
22 |
23 | # Check that files have been copied over correctly
24 | expect(expected_test_default).not_to eq(original_test_default)
25 |
26 | _cmd = run_command_and_stop(
27 | "bundle exec annotaterb models #{model_file} --force --position bottom",
28 | fail_on_error: true,
29 | exit_timeout: command_timeout_seconds
30 | )
31 |
32 | annotated_test_default = read_file(dummyapp_model("test_default.rb"))
33 |
34 | expect(last_command_started).to be_successfully_executed
35 | expect(annotated_test_default).to eq(expected_test_default)
36 | end
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/spec/integration/annotate_model_with_foreign_key_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "integration_spec_helper"
4 |
5 | RSpec.describe "Annotate collapsed models", type: "aruba" do
6 | let(:models_dir) { "app/models" }
7 | let(:command_timeout_seconds) { 10 }
8 |
9 | it "annotates them correctly" do
10 | reset_database
11 | run_migrations
12 |
13 | expected_test_model = read_file(model_template("test_child_default.rb"))
14 |
15 | original_test_model = read_file(dummyapp_model("test_child_default.rb"))
16 |
17 | expect(expected_test_model).not_to eq(original_test_model)
18 |
19 | _cmd = run_command_and_stop("bundle exec annotaterb models", fail_on_error: true, exit_timeout: command_timeout_seconds)
20 |
21 | annotated_test_model = read_file(dummyapp_model("test_child_default.rb"))
22 |
23 | expect(last_command_started).to be_successfully_executed
24 | expect(expected_test_model).to eq(annotated_test_model)
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/spec/integration/annotate_routes_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "integration_spec_helper"
4 |
5 | RSpec.describe "Annotate routes", type: "aruba" do
6 | let(:command_timeout_seconds) { 10 }
7 |
8 | let(:templates_dir) { File.join(aruba.config.root_directory, "spec/templates/") }
9 | let(:routes_file) { "config/routes.rb" }
10 |
11 | it "annotates a single file" do
12 | expected_routes_file = read_file(File.join(templates_dir, "routes.rb"))
13 | original_routes_file = read_file(routes_file)
14 |
15 | # Check that files have been copied over correctly
16 | expect(expected_routes_file).not_to eq(original_routes_file)
17 |
18 | _cmd = run_command_and_stop("bundle exec annotaterb routes", fail_on_error: true, exit_timeout: command_timeout_seconds)
19 |
20 | annotated_routes_file = read_file(routes_file)
21 |
22 | expect(last_command_started).to be_successfully_executed
23 | expect(annotated_routes_file).to eq(expected_routes_file)
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/spec/integration/annotate_single_file_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "integration_spec_helper"
4 |
5 | RSpec.describe "Annotate a single file", type: "aruba" do
6 | let(:models_dir) { "app/models" }
7 | let(:command_timeout_seconds) { 10 }
8 |
9 | let(:model_file) { "app/models/test_default.rb" }
10 |
11 | it "annotates a single file" do
12 | reset_database
13 | run_migrations
14 |
15 | expected_test_default = read_file(model_template("test_default.rb"))
16 | expected_test_null_false = read_file(model_template("test_null_false.rb"))
17 |
18 | original_test_default = read_file(dummyapp_model("test_default.rb"))
19 | original_test_null_false = read_file(dummyapp_model("test_null_false.rb"))
20 |
21 | # Check that files have been copied over correctly
22 | expect(expected_test_default).not_to eq(original_test_default)
23 | expect(expected_test_null_false).not_to eq(original_test_null_false)
24 |
25 | _cmd = run_command_and_stop("bundle exec annotaterb models #{model_file}", fail_on_error: true, exit_timeout: command_timeout_seconds)
26 |
27 | annotated_test_default = read_file(dummyapp_model("test_default.rb"))
28 | annotated_test_null_false = read_file(dummyapp_model("test_null_false.rb"))
29 |
30 | expect(last_command_started).to be_successfully_executed
31 | expect(annotated_test_default).to eq(expected_test_default)
32 | expect(annotated_test_null_false).not_to eq(expected_test_null_false)
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/spec/integration/cli_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "integration_spec_helper"
4 |
5 | RSpec.describe "CLI", type: "aruba" do
6 | let(:models_dir) { "app/models" }
7 | let(:command_timeout_seconds) { 10 }
8 |
9 | context "when running in a non-Rails project directory" do
10 | before do
11 | remove("Rakefile") if exist?("Rakefile")
12 | remove("Gemfile") if exist?("Gemfile")
13 | end
14 |
15 | let(:error_message) { "Please run annotaterb from the root of the project." }
16 |
17 | it "exits and outputs an error message" do
18 | _cmd = run_command("bundle exec annotaterb")
19 |
20 | expect(last_command_started).to have_exit_status(1)
21 | expect(last_command_started).to have_output_on_stderr(error_message)
22 | end
23 | end
24 |
25 | context "when running in a directory with a Rakefile and a Gemfile" do
26 | let(:help_banner_fragment) { "Usage: annotaterb [command] [options]" }
27 |
28 | it "outputs the help message" do
29 | _cmd = run_command("bundle exec annotaterb", fail_on_error: true, exit_timeout: command_timeout_seconds)
30 |
31 | expect(last_command_started).to be_successfully_executed
32 | expect(last_command_started.stdout).to include(help_banner_fragment)
33 | end
34 |
35 | it "annotates files that have not been annotated" do
36 | reset_database
37 | run_migrations
38 |
39 | expected_test_default = read_file(model_template("test_default.rb"))
40 | expected_test_null_false = read_file(model_template("test_null_false.rb"))
41 |
42 | original_test_default = read_file(dummyapp_model("test_default.rb"))
43 | original_test_null_false = read_file(dummyapp_model("test_null_false.rb"))
44 |
45 | expect(expected_test_default).not_to eq(original_test_default)
46 | expect(expected_test_null_false).not_to eq(original_test_null_false)
47 |
48 | _cmd = run_command_and_stop("bundle exec annotaterb models", fail_on_error: true, exit_timeout: command_timeout_seconds)
49 |
50 | annotated_test_default = read_file(dummyapp_model("test_default.rb"))
51 | annotated_test_null_false = read_file(dummyapp_model("test_null_false.rb"))
52 |
53 | expect(last_command_started).to be_successfully_executed
54 | expect(expected_test_default).to eq(annotated_test_default)
55 | expect(expected_test_null_false).to eq(annotated_test_null_false)
56 | end
57 | end
58 | end
59 |
--------------------------------------------------------------------------------
/spec/integration/rails_generator_install_spec.rb:
--------------------------------------------------------------------------------
1 | require "integration_spec_helper"
2 |
3 | RSpec.describe "Generator installs rake file", type: "aruba" do
4 | let(:command_timeout_seconds) { 10 }
5 |
6 | let(:rake_task_file) { "lib/tasks/annotate_rb.rake" }
7 | let(:rake_task) { File.join(aruba.config.root_directory, "lib/generators/annotate_rb/hook/templates/annotate_rb.rake") }
8 | let(:config_file) { ".annotaterb.yml" }
9 |
10 | let(:generator_install_command) { "bin/rails generate annotate_rb:install" }
11 |
12 | it "installs the rake file to Rails project" do
13 | # First check that the file doesn't exist in dummyapp
14 | expect(exist?(rake_task_file)).to be_falsey
15 |
16 | _cmd = run_command_and_stop(generator_install_command, fail_on_error: true, exit_timeout: command_timeout_seconds)
17 |
18 | installed_rake_task = read_file(rake_task_file)
19 | # Read the one in the actual gem
20 | actual_rake_task = read_file(rake_task)
21 |
22 | expect(last_command_started).to be_successfully_executed
23 | expect(installed_rake_task).to eq(actual_rake_task)
24 | end
25 |
26 | it "generates a default config file" do
27 | # First check that the file doesn't exist in dummyapp
28 | expect(exist?(config_file)).to be_falsey
29 |
30 | _cmd = run_command_and_stop(generator_install_command, fail_on_error: true, exit_timeout: command_timeout_seconds)
31 |
32 | expect(exist?(config_file)).to be_truthy
33 |
34 | expect(last_command_started).to be_successfully_executed
35 | end
36 |
37 | context "when the rake task already exists" do
38 | before do
39 | touch(rake_task_file)
40 | end
41 |
42 | it "returns the Thor cli" do
43 | # First check that the file exists in dummyapp
44 | expect(exist?(rake_task_file)).to be_truthy
45 |
46 | # TODO: Improve this so we don't have to rely on `exit_timeout`
47 | _cmd = run_command(generator_install_command, exit_timeout: 5)
48 | # Because the rake task file already exists, there will be a conflict in the Rails generator.
49 | # The prompt should look something like this:
50 | #
51 | # ...
52 | # generate annotate_rb:hook
53 | # rails generate annotate_rb:hook
54 | # conflict lib/tasks/annotate_rb.rake
55 | # Overwrite .../dummyapp/lib/tasks/annotate_rb.rake? (enter "h" for help) [Ynaqdhm]
56 | type("q") # Quit the command
57 |
58 | # When the file already exists, the default behavior is the Thor CLI prompts user on how to proceed
59 | # https://github.com/rails/thor/blob/a4d99cfc97691504d26d0d0aefc649a8f2e89b3c/spec/actions/create_file_spec.rb#L112
60 | expect(all_stdout).to include("conflict")
61 | end
62 | end
63 | end
64 |
--------------------------------------------------------------------------------
/spec/integration/rails_generator_update_config_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "integration_spec_helper"
4 |
5 | RSpec.describe "Generator appends to config file", type: "aruba" do
6 | let(:command_timeout_seconds) { 10 }
7 |
8 | let(:config_file) { ".annotaterb.yml" }
9 | let(:config_file_content) do
10 | <<~YML.strip
11 | ---
12 | :classified_sort: true
13 | :exclude_controllers: true
14 | :exclude_factories: false
15 | :exclude_fixtures: false
16 | :exclude_helpers: true
17 | :exclude_scaffolds: true
18 | :exclude_serializers: false
19 | :exclude_sti_subclasses: false
20 | :exclude_tests: false
21 | :force: false
22 | :format_markdown: false
23 | :format_rdoc: false
24 | :format_yard: false
25 | YML
26 | end
27 |
28 | let(:generator_update_config_command) { "bin/rails generate annotate_rb:update_config" }
29 |
30 | it "appends missing configuration key-value pairs" do
31 | write_file(config_file, config_file_content)
32 |
33 | _cmd = run_command_and_stop(generator_update_config_command, fail_on_error: true, exit_timeout: command_timeout_seconds)
34 |
35 | changed_config_file = read_file(config_file)
36 |
37 | expect(last_command_started).to be_successfully_executed
38 | expect(config_file_content).not_to eq(changed_config_file)
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/spec/integration_spec_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "pry"
4 | require "aruba/rspec"
5 |
6 | Aruba.configure do |config|
7 | config.allow_absolute_paths = true
8 | end
9 |
--------------------------------------------------------------------------------
/spec/lib/annotate_rb/annotate_models/annotate_models_annotating_a_file_frozen_spec.rb:
--------------------------------------------------------------------------------
1 | RSpec.describe AnnotateRb::ModelAnnotator::Annotator do
2 | include AnnotateTestHelpers
3 |
4 | describe "annotating a file" do
5 | let(:options) { AnnotateRb::Options.new({}) }
6 |
7 | before do
8 | @model_dir = Dir.mktmpdir("annotate_models")
9 | (@model_file_name, @file_content) = write_model "user.rb", <<~EOS
10 | class User < ActiveRecord::Base
11 | end
12 | EOS
13 |
14 | @klass = mock_class(:users,
15 | :id,
16 | [
17 | mock_column("id", :integer),
18 | mock_column("name", :string, limit: 50)
19 | ])
20 | @schema_info = AnnotateRb::ModelAnnotator::Annotation::AnnotationBuilder.new(@klass, options).build
21 | end
22 |
23 | # TODO: Check out why this test fails due to test pollution
24 | describe "frozen option" do
25 | it "should abort without existing annotation when frozen: true " do
26 | expect { annotate_one_file frozen: true }.to raise_error SystemExit, /user.rb needs to be updated, but annotaterb was run with `--frozen`./
27 | end
28 |
29 | it "should abort with different annotation when frozen: true " do
30 | annotate_one_file
31 |
32 | another_schema_info = AnnotateRb::ModelAnnotator::Annotation::AnnotationBuilder.new(
33 | mock_class(:users, :id, [mock_column("id", :integer)]),
34 | options
35 | ).build
36 |
37 | @schema_info = another_schema_info
38 |
39 | expect { annotate_one_file frozen: true }.to raise_error SystemExit, /user.rb needs to be updated, but annotaterb was run with `--frozen`./
40 | end
41 |
42 | it "should NOT abort with same annotation when frozen: true " do
43 | annotate_one_file
44 | expect { annotate_one_file frozen: true }.not_to raise_error
45 | end
46 | end
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/spec/lib/annotate_rb/config_generator_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | RSpec.describe AnnotateRb::ConfigGenerator do
4 | describe "#default_config_yml" do
5 | subject { described_class.default_config_yml }
6 |
7 | let(:example_config_pair) { {models: true} }
8 |
9 | it "returns yml containing defaults" do
10 | expect(subject).to be_a(String)
11 |
12 | # Might be a better way to do this
13 | parsed = YAML.safe_load(
14 | subject, permitted_classes: [Regexp, Symbol], aliases: true, symbolize_names: true
15 | )
16 |
17 | expect(parsed).to include(**example_config_pair)
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/spec/lib/annotate_rb/core_spec.rb:
--------------------------------------------------------------------------------
1 | RSpec.describe AnnotateRb::Core do
2 | describe ".version" do
3 | subject { described_class.version }
4 |
5 | it { is_expected.to be_a(String) }
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/spec/lib/annotate_rb/model_annotator/annotation/main_header_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | RSpec.describe AnnotateRb::ModelAnnotator::Annotation::MainHeader do
4 | describe "#to_default" do
5 | subject { described_class.new(version, include_version).to_default }
6 |
7 | let(:version) { 0 }
8 | let(:include_version) { false }
9 | let(:expected_header) { "# == Schema Information" }
10 |
11 | it { is_expected.to eq(expected_header) }
12 |
13 | context "when version is non-zero and include version is true" do
14 | let(:version) { 100 }
15 | let(:include_version) { true }
16 | let(:expected_header) { "# == Schema Information\n# Schema version: 100" }
17 |
18 | it { is_expected.to eq(expected_header) }
19 | end
20 |
21 | context "when version is non-zero and include version is false" do
22 | let(:version) { 100 }
23 | let(:include_version) { false }
24 |
25 | it { is_expected.to eq(expected_header) }
26 | end
27 |
28 | context "when version is zero and include version is true" do
29 | let(:version) { 0 }
30 | let(:include_version) { true }
31 |
32 | it { is_expected.to eq(expected_header) }
33 | end
34 | end
35 |
36 | describe "#to_markdown" do
37 | subject { described_class.new(version, include_version).to_markdown }
38 |
39 | let(:version) { 0 }
40 | let(:include_version) { false }
41 | let(:expected_header) { "# ## Schema Information" }
42 |
43 | it { is_expected.to eq(expected_header) }
44 |
45 | context "when version is non-zero and include version is true" do
46 | let(:version) { 100 }
47 | let(:include_version) { true }
48 | let(:expected_header) { "# ## Schema Information\n# Schema version: 100" }
49 |
50 | it { is_expected.to eq(expected_header) }
51 | end
52 |
53 | context "when version is non-zero and include version is false" do
54 | let(:version) { 100 }
55 | let(:include_version) { false }
56 |
57 | it { is_expected.to eq(expected_header) }
58 | end
59 |
60 | context "when version is zero and include version is true" do
61 | let(:version) { 0 }
62 | let(:include_version) { true }
63 |
64 | it { is_expected.to eq(expected_header) }
65 | end
66 | end
67 | end
68 |
--------------------------------------------------------------------------------
/spec/lib/annotate_rb/model_annotator/annotation/markdown_header_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | RSpec.describe AnnotateRb::ModelAnnotator::Annotation::MarkdownHeader do
4 | subject { described_class.new(max_size) }
5 | let(:markdown_format) { subject.to_markdown }
6 | let(:default_format) { subject.to_default }
7 |
8 | context "using default format" do
9 | let(:max_size) { 0 }
10 |
11 | it { expect(default_format).to be_nil }
12 | end
13 |
14 | context "using markdown format" do
15 | let(:max_size) { 10 }
16 | let(:expected_header) do
17 | <<~HEADER.strip
18 | # ### Columns
19 | #
20 | # Name | Type | Attributes
21 | # ---------------- | ------------------ | ---------------------------
22 | HEADER
23 | end
24 |
25 | it "matches the expected header" do
26 | expect(markdown_format).to eq(expected_header)
27 | end
28 | end
29 |
30 | context "with a larger max size" do
31 | let(:max_size) { 20 }
32 | let(:expected_header) do
33 | <<~HEADER.strip
34 | # ### Columns
35 | #
36 | # Name | Type | Attributes
37 | # -------------------------- | ------------------ | ---------------------------
38 | HEADER
39 | end
40 |
41 | it "matches the expected header" do
42 | expect(markdown_format).to eq(expected_header)
43 | end
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/spec/lib/annotate_rb/model_annotator/annotation_diff_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | RSpec.describe AnnotateRb::ModelAnnotator::AnnotationDiff do
4 | describe "attributes" do
5 | subject { described_class.new(current_columns, new_columns) }
6 | let(:current_columns) { "some current columns string" }
7 | let(:new_columns) { "some new columns string" }
8 |
9 | it "returns the current columns" do
10 | expect(subject.current_columns).to eq(current_columns)
11 | end
12 |
13 | it "returns the new columns" do
14 | expect(subject.new_columns).to eq(new_columns)
15 | end
16 | end
17 |
18 | describe "#changed?" do
19 | subject { described_class.new(current_columns, new_columns).changed? }
20 |
21 | context "when the current and new columns are the same" do
22 | let(:current_columns) { "the same" }
23 | let(:new_columns) { "the same" }
24 |
25 | it { is_expected.to eq(false) }
26 | end
27 |
28 | context "when the current and new columns are different" do
29 | let(:current_columns) { "the current" }
30 | let(:new_columns) { "the new" }
31 |
32 | it { is_expected.to eq(true) }
33 | end
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/spec/lib/annotate_rb/model_annotator/check_constraint_annotation/annotation_builder_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | RSpec.describe AnnotateRb::ModelAnnotator::CheckConstraintAnnotation::AnnotationBuilder do
4 | include AnnotateTestHelpers
5 |
6 | describe "#build" do
7 | subject { described_class.new(model, options).build }
8 | let(:default_format) { subject.to_default }
9 | let(:markdown_format) { subject.to_markdown }
10 |
11 | let(:model) do
12 | instance_double(
13 | AnnotateRb::ModelAnnotator::ModelWrapper,
14 | connection: connection,
15 | table_name: "Foo"
16 | )
17 | end
18 | let(:connection) do
19 | mock_connection([], [], check_constraints)
20 | end
21 | let(:options) { AnnotateRb::Options.new({show_check_constraints: true}) }
22 | let(:check_constraints) do
23 | [
24 | mock_check_constraint("alive", "age < 150"),
25 | mock_check_constraint("must_be_adult", "age >= 18"),
26 | mock_check_constraint("missing_expression", nil),
27 | mock_check_constraint("multiline_test", <<~SQL)
28 | CASE
29 | WHEN (age >= 18) THEN (age <= 21)
30 | ELSE true
31 | END
32 | SQL
33 | ]
34 | end
35 |
36 | context "when show_check_constraints option is false" do
37 | let(:options) { AnnotateRb::Options.new({show_check_constraints: false}) }
38 |
39 | it { is_expected.to be_a(AnnotateRb::ModelAnnotator::Components::NilComponent) }
40 | end
41 |
42 | context "using default format" do
43 | let(:expected_result) do
44 | <<~RESULT.strip
45 | #
46 | # Check Constraints
47 | #
48 | # alive (age < 150)
49 | # missing_expression
50 | # multiline_test (CASE WHEN (age >= 18) THEN (age <= 21) ELSE true END)
51 | # must_be_adult (age >= 18)
52 | RESULT
53 | end
54 |
55 | it "annotates the check constraints" do
56 | expect(default_format).to eq(expected_result)
57 | end
58 | end
59 |
60 | context "using markdown format" do
61 | let(:expected_result) do
62 | <<~RESULT.strip
63 | #
64 | # ### Check Constraints
65 | #
66 | # * `alive`: `(age < 150)`
67 | # * `missing_expression`
68 | # * `multiline_test`: `(CASE WHEN (age >= 18) THEN (age <= 21) ELSE true END)`
69 | # * `must_be_adult`: `(age >= 18)`
70 | RESULT
71 | end
72 |
73 | it "annotates the check constraints" do
74 | expect(markdown_format).to eq(expected_result)
75 | end
76 | end
77 |
78 | context "when model connection does not support check constraints" do
79 | let(:connection) do
80 | conn_options = {supports_check_constraints?: false}
81 |
82 | mock_connection([], [], [], conn_options)
83 | end
84 |
85 | it { expect(default_format).to be_nil }
86 | end
87 |
88 | context "when check constraints is empty" do
89 | let(:connection) do
90 | conn_options = {supports_check_constraints?: true}
91 |
92 | mock_connection([], [], [], conn_options)
93 | end
94 |
95 | it { expect(default_format).to be_nil }
96 | end
97 | end
98 | end
99 |
--------------------------------------------------------------------------------
/spec/lib/annotate_rb/model_annotator/column_annotation/column_wrapper_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | RSpec.describe AnnotateRb::ModelAnnotator::ColumnAnnotation::ColumnWrapper do
4 | include AnnotateTestHelpers
5 |
6 | describe "#default_string" do
7 | subject { described_class.new(column, column_defaults, options).default_string }
8 | let(:column) { mock_column("field", nil, default: value) }
9 | let(:column_defaults) { {"field" => value} }
10 | let(:options) { {} }
11 |
12 | context "when the value is nil" do
13 | let(:value) { nil }
14 | it 'returns string "NULL"' do
15 | is_expected.to eq("NULL")
16 | end
17 | end
18 |
19 | context "when the value is true" do
20 | let(:value) { true }
21 | it 'returns string "TRUE"' do
22 | is_expected.to eq("TRUE")
23 | end
24 | end
25 |
26 | context "when the value is false" do
27 | let(:value) { false }
28 | it 'returns string "FALSE"' do
29 | is_expected.to eq("FALSE")
30 | end
31 | end
32 |
33 | context "when the value is an integer" do
34 | let(:value) { 25 }
35 | it "returns the integer as a string" do
36 | is_expected.to eq("25")
37 | end
38 | end
39 |
40 | context "when the value is a float number" do
41 | context "when the value is like 25.6" do
42 | let(:value) { 25.6 }
43 | it "returns the float number as a string" do
44 | is_expected.to eq("25.6")
45 | end
46 | end
47 |
48 | context "when the value is like 1e-20" do
49 | let(:value) { 1e-20 }
50 | it "returns the float number as a string" do
51 | is_expected.to eq("1.0e-20")
52 | end
53 | end
54 | end
55 |
56 | context "when the value is a BigDecimal number" do
57 | let(:value) { BigDecimal("1.2") }
58 | it "returns the float number as a string" do
59 | is_expected.to eq("1.2")
60 | end
61 | end
62 |
63 | context "when the value is an array" do
64 | let(:value) { [BigDecimal("1.2")] }
65 | it "returns an array of which elements are converted to string" do
66 | is_expected.to eq("[1.2]")
67 | end
68 | end
69 | end
70 | end
71 |
--------------------------------------------------------------------------------
/spec/lib/annotate_rb/model_annotator/column_annotation/default_value_builder_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | RSpec.describe AnnotateRb::ModelAnnotator::ColumnAnnotation::DefaultValueBuilder do
4 | describe "#build" do
5 | subject { described_class.new(value, config).build }
6 | let(:config) { {} }
7 |
8 | context "when value is a String" do
9 | let(:value) { "a random string" }
10 |
11 | it { is_expected.to eq("\"a random string\"") }
12 | end
13 |
14 | context "when value is nil" do
15 | let(:value) { nil }
16 |
17 | it { is_expected.to eq("NULL") }
18 | end
19 |
20 | context "when value is true" do
21 | let(:value) { true }
22 |
23 | it { is_expected.to eq("TRUE") }
24 | end
25 |
26 | context "when value is false" do
27 | let(:value) { false }
28 |
29 | it { is_expected.to eq("FALSE") }
30 | end
31 |
32 | context "when value is an Integer" do
33 | let(:value) { 42 }
34 |
35 | it { is_expected.to eq("42") }
36 | end
37 |
38 | context "when value is an Decimal" do
39 | let(:value) { 1.2 }
40 |
41 | it { is_expected.to eq("1.2") }
42 | end
43 |
44 | context "when value is a BigDecimal" do
45 | let(:value) { BigDecimal("1.2") }
46 |
47 | it { is_expected.to eq("1.2") }
48 | end
49 |
50 | context "when value is an Array" do
51 | context "array is empty" do
52 | let(:value) { [] }
53 |
54 | it { is_expected.to eq("[]") }
55 | end
56 |
57 | context "array has a String" do
58 | let(:value) { ["string"] }
59 |
60 | it { is_expected.to eq("[\"string\"]") }
61 | end
62 |
63 | context "array has Strings" do
64 | let(:value) { ["a", "string"] }
65 |
66 | it { is_expected.to eq("[\"a\", \"string\"]") }
67 | end
68 |
69 | context "array has Numbers" do
70 | let(:value) { [42, 1.2] }
71 |
72 | it { is_expected.to eq("[42, 1.2]") }
73 | end
74 |
75 | context "array has BigDecimals" do
76 | let(:value) { [BigDecimal("0.1"), BigDecimal("0.2")] }
77 |
78 | it { is_expected.to eq("[0.1, 0.2]") }
79 | end
80 |
81 | context "array has Booleans" do
82 | let(:value) { [true, false] }
83 |
84 | it { is_expected.to eq("[TRUE, FALSE]") }
85 | end
86 | end
87 |
88 | context "with specified `classes_default_to_s` config option" do
89 | let(:config) { {classes_default_to_s: ["Integer"]} }
90 |
91 | context "when value is an Integer" do
92 | let(:value) { 42 }
93 |
94 | it { is_expected.to eq("\"42\"") }
95 | end
96 |
97 | context "when config option includes unloaded class" do
98 | let(:config) { {classes_default_to_s: ["Locale", "Float"]} }
99 | let(:value) { 42 }
100 |
101 | it "does not fail" do
102 | expect(subject).to eq("42")
103 | end
104 | end
105 | end
106 | end
107 | end
108 |
--------------------------------------------------------------------------------
/spec/lib/annotate_rb/model_annotator/file_name_resolver_spec.rb:
--------------------------------------------------------------------------------
1 | RSpec.describe AnnotateRb::ModelAnnotator::FileNameResolver do
2 | describe ".call" do
3 | subject do
4 | described_class.call(filename_template, model_name, table_name)
5 | end
6 |
7 | context 'When model_name is "example_model" and table_name is "example_models"' do
8 | let(:model_name) { "example_model" }
9 | let(:table_name) { "example_models" }
10 |
11 | context "when filename_template is 'test/unit/%MODEL_NAME%_test.rb'" do
12 | let(:filename_template) { "test/unit/%MODEL_NAME%_test.rb" }
13 |
14 | it "returns the test path for a model" do
15 | is_expected.to eq "test/unit/example_model_test.rb"
16 | end
17 | end
18 |
19 | context "when filename_template is '/foo/bar/%MODEL_NAME%/testing.rb'" do
20 | let(:filename_template) { "/foo/bar/%MODEL_NAME%/testing.rb" }
21 |
22 | it "returns the additional glob" do
23 | is_expected.to eq "/foo/bar/example_model/testing.rb"
24 | end
25 | end
26 |
27 | context "when filename_template is '/foo/bar/%PLURALIZED_MODEL_NAME%/testing.rb'" do
28 | let(:filename_template) { "/foo/bar/%PLURALIZED_MODEL_NAME%/testing.rb" }
29 |
30 | it "returns the additional glob" do
31 | is_expected.to eq "/foo/bar/example_models/testing.rb"
32 | end
33 | end
34 |
35 | context "when filename_template is 'test/fixtures/%TABLE_NAME%.yml'" do
36 | let(:filename_template) { "test/fixtures/%TABLE_NAME%.yml" }
37 |
38 | it "returns the fixture path for a model" do
39 | is_expected.to eq "test/fixtures/example_models.yml"
40 | end
41 | end
42 | end
43 |
44 | context 'When model_name is "parent/child" and table_name is "parent_children"' do
45 | let(:model_name) { "parent/child" }
46 | let(:table_name) { "parent_children" }
47 |
48 | context "when filename_template is 'test/fixtures/%PLURALIZED_MODEL_NAME%.yml'" do
49 | let(:filename_template) { "test/fixtures/%PLURALIZED_MODEL_NAME%.yml" }
50 |
51 | it "returns the fixture path for a nested model" do
52 | is_expected.to eq "test/fixtures/parent/children.yml"
53 | end
54 | end
55 | end
56 |
57 | context 'When model_name is "collapsed/test_model" and table_name is "collapsed_test_model"' do
58 | let(:model_name) { "collapsed/test_model" }
59 | let(:table_name) { "collapsed_test_models" }
60 |
61 | context "when filename_template is 'spec/models/collapsed/example/%MODEL_NAME_WITHOUT_NS%_spec.rb'" do
62 | let(:filename_template) { "spec/models/collapsed/example/%MODEL_NAME_WITHOUT_NS%_spec.rb" }
63 |
64 | it "returns the custom spec path for a collapsed model" do
65 | is_expected.to eq "spec/models/collapsed/example/test_model_spec.rb"
66 | end
67 | end
68 | end
69 | end
70 | end
71 |
--------------------------------------------------------------------------------
/spec/lib/annotate_rb/model_annotator/file_to_parser_mapper_spec.rb:
--------------------------------------------------------------------------------
1 | RSpec.describe AnnotateRb::ModelAnnotator::FileToParserMapper do
2 | describe ".map" do
3 | subject { described_class.map(file_name) }
4 | let(:custom_parser) { AnnotateRb::ModelAnnotator::FileParser::CustomParser }
5 | let(:yml_parser) { AnnotateRb::ModelAnnotator::FileParser::YmlParser }
6 |
7 | context "when it is a ruby file" do
8 | let(:file_name) { "some_path/script.rb" }
9 |
10 | it { is_expected.to eq(custom_parser) }
11 | end
12 |
13 | context "when it is a yml file" do
14 | let(:file_name) { "some_path/some_file.yml" }
15 |
16 | it { is_expected.to eq(yml_parser) }
17 | end
18 |
19 | context "when it is a non Ruby file" do
20 | let(:file_name) { "some_path/some_file.abc" }
21 |
22 | it "raises an error" do
23 | expect { subject }.to raise_error(described_class::UnsupportedFileTypeError)
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/spec/lib/annotate_rb/runner_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | RSpec.describe AnnotateRb::Runner do
4 | subject(:runner) { described_class.new }
5 |
6 | before do
7 | $stdout = StringIO.new
8 | $stderr = StringIO.new
9 | end
10 |
11 | after do
12 | $stdout = STDOUT
13 | $stderr = STDERR
14 | end
15 |
16 | describe "help option" do
17 | describe "-h/-?/--help" do
18 | it "shows help text" do
19 | runner.run(["-h"])
20 |
21 | expect($stdout.string).to include(AnnotateRb::Parser::BANNER_STRING)
22 | end
23 | end
24 |
25 | describe "help" do
26 | it "shows help text" do
27 | runner.run(["help"])
28 |
29 | expect($stdout.string).to include(AnnotateRb::Parser::BANNER_STRING)
30 | end
31 | end
32 | end
33 |
34 | describe "version option" do
35 | describe "-v/--version" do
36 | it "shows version text" do
37 | runner.run(["-v"])
38 |
39 | version_string = AnnotateRb::Core.version
40 |
41 | expect($stdout.string).to include(version_string)
42 | end
43 | end
44 |
45 | describe "version" do
46 | it "shows version text" do
47 | runner.run(["version"])
48 |
49 | version_string = AnnotateRb::Core.version
50 |
51 | expect($stdout.string).to include(version_string)
52 | end
53 | end
54 | end
55 |
56 | describe "Annotating models" do
57 | let(:args) { ["models"] }
58 | let(:command_double) { instance_double(AnnotateRb::Commands::AnnotateModels) }
59 |
60 | before do
61 | allow(AnnotateRb::Commands::AnnotateModels).to receive(:new).and_return(command_double)
62 | allow(command_double).to receive(:call)
63 | end
64 |
65 | it "calls the annotate models command" do
66 | runner.run(args)
67 |
68 | expect(command_double).to have_received(:call)
69 | end
70 | end
71 |
72 | describe "Annotating routes" do
73 | let(:args) { ["routes"] }
74 | let(:command_double) { instance_double(AnnotateRb::Commands::AnnotateRoutes) }
75 |
76 | before do
77 | allow(AnnotateRb::Commands::AnnotateRoutes).to receive(:new).and_return(command_double)
78 | allow(command_double).to receive(:call)
79 | end
80 |
81 | it "calls the annotate routes command" do
82 | runner.run(args)
83 |
84 | expect(command_double).to have_received(:call)
85 | end
86 | end
87 | end
88 |
--------------------------------------------------------------------------------
/spec/lib/tasks/annotate_models_migrate_spec.rb:
--------------------------------------------------------------------------------
1 | RSpec.describe "ActiveRecord migration rake task hooks" do
2 | before do
3 | Rake.application = Rake::Application.new
4 |
5 | # Stub migration tasks
6 | %w[db:migrate db:migrate:up db:migrate:down db:migrate:reset db:rollback].each do |task|
7 | Rake::Task.define_task(task)
8 | end
9 |
10 | Rake::Task.define_task("db:migrate:redo") do
11 | Rake::Task["db:rollback"].invoke
12 | Rake::Task["db:migrate"].invoke
13 | end
14 |
15 | Rake.load_rakefile("annotate_rb/tasks/annotate_models_migrate.rake")
16 |
17 | Rake.application.instance_variable_set(:@top_level_tasks, [subject])
18 | end
19 |
20 | describe "db:migrate" do
21 | it "should annotate model files" do
22 | expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
23 | Rake.application.top_level
24 | end
25 | end
26 |
27 | describe "db:migrate:up" do
28 | it "should annotate model files" do
29 | expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
30 | Rake.application.top_level
31 | end
32 | end
33 |
34 | describe "db:migrate:down" do
35 | it "should annotate model files" do
36 | expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
37 | Rake.application.top_level
38 | end
39 | end
40 |
41 | describe "db:migrate:reset" do
42 | it "should annotate model files" do
43 | expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
44 | Rake.application.top_level
45 | end
46 | end
47 |
48 | describe "db:rollback" do
49 | it "should annotate model files" do
50 | expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
51 | Rake.application.top_level
52 | end
53 | end
54 |
55 | describe "db:migrate:redo" do
56 | it "should annotate model files after all migration tasks" do
57 | # Hooked 3 times by db:rollback, db:migrate, and db:migrate:redo tasks
58 | expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")).exactly(3).times
59 |
60 | Rake.application.top_level
61 | end
62 | end
63 | end
64 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | require "bundler/setup"
2 | require "rake"
3 | require "active_support"
4 | require "active_support/core_ext/string"
5 | require "active_support/core_ext/object/blank"
6 | require "active_support/core_ext/class/subclasses"
7 | require "active_support/core_ext/string/inflections"
8 | require "byebug"
9 | require "bigdecimal"
10 | require "tmpdir"
11 |
12 | require "annotate_rb"
13 |
14 | # Requires supporting files with custom matchers and macros, etc,
15 | # in ./support/ and its subdirectories.
16 | Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].sort.each { |f| require f }
17 |
18 | RSpec.configure do |config|
19 | config.include(SpecHelper::Aruba, type: :aruba)
20 |
21 | config.before(:example, type: :aruba) do
22 | copy_dummy_app_into_aruba_working_directory
23 |
24 | # Unset the bundler context from running annotaterb integration specs.
25 | # This way, when `run_command("bundle exec annotaterb")` runs, it runs as if it's within the context of dummyapp.
26 | unset_bundler_env_vars
27 | end
28 |
29 | # Enable flags like --only-failures and --next-failure
30 | config.example_status_persistence_file_path = ".rspec_status"
31 |
32 | # Disable RSpec exposing methods globally on `Module` and `main`
33 | config.disable_monkey_patching!
34 |
35 | config.expect_with :rspec do |c|
36 | c.syntax = :expect
37 | end
38 |
39 | config.order = :random
40 |
41 | config.include_context "isolated environment", :isolated_environment
42 | end
43 |
--------------------------------------------------------------------------------
/spec/support/annotate_test_constants.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module AnnotateTestConstants
4 | MAGIC_COMMENTS = [
5 | "# encoding: UTF-8",
6 | "# coding: UTF-8",
7 | "# -*- coding: UTF-8 -*-",
8 | "#encoding: utf-8",
9 | "# encoding: utf-8",
10 | "# -*- encoding : utf-8 -*-",
11 | "# encoding: utf-8\n# frozen_string_literal: true",
12 | "# frozen_string_literal: true\n# encoding: utf-8",
13 | "# frozen_string_literal: true",
14 | "#frozen_string_literal: false",
15 | "# -*- frozen_string_literal : true -*-"
16 | ].freeze
17 | end
18 |
--------------------------------------------------------------------------------
/spec/support/aruba.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "aruba/rspec"
4 |
5 | module SpecHelper
6 | module Aruba
7 | def read_file(name)
8 | # Aruba's #read uses File.readlines, returning an Array
9 | read(name).join("\n")
10 | end
11 |
12 | def models_template_dir
13 | File.join(::Aruba.config.root_directory, "spec/templates/#{ENV["DATABASE_ADAPTER"]}")
14 | end
15 |
16 | def migrations_template_dir
17 | File.join(::Aruba.config.root_directory, "spec/templates/migrations")
18 | end
19 |
20 | def model_template(name)
21 | File.join(models_template_dir, name)
22 | end
23 |
24 | def dummyapp_model(name)
25 | File.join(aruba_working_directory, "app/models", name)
26 | end
27 |
28 | def aruba_working_directory
29 | File.expand_path("../../#{::Aruba.config.working_directory}", __dir__)
30 | end
31 |
32 | def dummy_app_directory
33 | File.expand_path("../../spec/dummyapp/", __dir__)
34 | end
35 |
36 | def copy_dummy_app_into_aruba_working_directory
37 | FileUtils.rm_rf(Dir.glob("#{aruba_working_directory}/**/*"))
38 | FileUtils.cp_r(Dir.glob("#{dummy_app_directory}/."), aruba_working_directory)
39 | end
40 |
41 | def reset_database
42 | run_command_and_stop("bin/rails db:drop db:create", fail_on_error: true, exit_timeout: 10)
43 | end
44 |
45 | def run_migrations
46 | run_command_and_stop("bin/rails db:migrate", fail_on_error: true, exit_timeout: 10)
47 | end
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/spec/support/custom_matchers.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # From Rubocop
4 |
5 | RSpec::Matchers.define :exit_with_code do |code|
6 | supports_block_expectations
7 |
8 | actual = nil
9 |
10 | match do |block|
11 | begin
12 | block.call
13 | rescue SystemExit => e
14 | actual = e.status
15 | end
16 | actual && actual == code
17 | end
18 |
19 | failure_message do
20 | "expected block to call exit(#{code}) but exit" +
21 | (actual.nil? ? " not called" : "(#{actual}) was called")
22 | end
23 |
24 | failure_message_when_negated { "expected block not to call exit(#{code})" }
25 |
26 | description { "expect block to call exit(#{code})" }
27 | end
28 |
--------------------------------------------------------------------------------
/spec/support/shared_contexts.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "tmpdir"
4 |
5 | RSpec.shared_context "isolated environment" do
6 | # Taken from Rubocop's shared_contexts.rb
7 | around do |example|
8 | Dir.mktmpdir do |tmpdir|
9 | # Make sure to expand all symlinks in the path first. Otherwise we may
10 | # get mismatched pathnames when loading config files later on.
11 | tmpdir = File.realpath(tmpdir)
12 |
13 | working_dir = File.join(tmpdir, "work")
14 | begin
15 | FileUtils.mkdir_p(working_dir)
16 |
17 | Dir.chdir(working_dir) { example.run }
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/spec/templates/migrations/20231013230731_add_int_field_to_test_defaults.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class AddIntFieldToTestDefaults < ActiveRecord::Migration["#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}"]
4 | def change
5 | add_column :test_defaults, :int_field, :integer
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/spec/templates/mysql2/collapsed_test_model.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # == Schema Information
4 | #
5 | # Table name: collapsed_test_models
6 | #
7 | # id :bigint not null, primary key
8 | # collapsed :boolean
9 | # name :string(255)
10 | # created_at :datetime not null
11 | # updated_at :datetime not null
12 | #
13 | module Collapsed
14 | class TestModel < ApplicationRecord
15 | def self.table_name_prefix
16 | "collapsed_"
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/spec/templates/mysql2/test_child_default.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: test_child_defaults
4 | #
5 | # id :bigint not null, primary key
6 | # created_at :datetime not null
7 | # updated_at :datetime not null
8 | # test_default_id :bigint not null
9 | #
10 | # Indexes
11 | #
12 | # index_test_child_defaults_on_test_default_id (test_default_id)
13 | #
14 | # Foreign Keys
15 | #
16 | # fk_rails_... (test_default_id => test_defaults.id)
17 | #
18 | class TestChildDefault < ApplicationRecord
19 | belongs_to :test_default
20 | end
21 |
--------------------------------------------------------------------------------
/spec/templates/mysql2/test_default.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # == Schema Information
4 | #
5 | # Table name: test_defaults
6 | #
7 | # id :bigint not null, primary key
8 | # boolean :boolean default(FALSE)
9 | # date :date default(Tue, 04 Jul 2023)
10 | # datetime :datetime default(Tue, 04 Jul 2023 12:34:56.000000000 UTC +00:00)
11 | # decimal :decimal(14, 2) default(43.21)
12 | # float :float(24) default(12.34)
13 | # integer :integer default(99)
14 | # string :string(255) default("hello world!")
15 | # created_at :datetime not null
16 | # updated_at :datetime not null
17 | #
18 | class TestDefault < ApplicationRecord
19 | end
20 |
--------------------------------------------------------------------------------
/spec/templates/mysql2/test_default_updated.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # == Schema Information
4 | #
5 | # Table name: test_defaults
6 | #
7 | # id :bigint not null, primary key
8 | # boolean :boolean default(FALSE)
9 | # date :date default(Tue, 04 Jul 2023)
10 | # datetime :datetime default(Tue, 04 Jul 2023 12:34:56.000000000 UTC +00:00)
11 | # decimal :decimal(14, 2) default(43.21)
12 | # float :float(24) default(12.34)
13 | # int_field :integer
14 | # integer :integer default(99)
15 | # string :string(255) default("hello world!")
16 | # created_at :datetime not null
17 | # updated_at :datetime not null
18 | #
19 | class TestDefault < ApplicationRecord
20 | end
21 |
--------------------------------------------------------------------------------
/spec/templates/mysql2/test_default_with_bottom_annotations.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | class TestDefault < ApplicationRecord
3 | end
4 |
5 | # == Schema Information
6 | #
7 | # Table name: test_defaults
8 | #
9 | # id :bigint not null, primary key
10 | # boolean :boolean default(FALSE)
11 | # date :date default(Tue, 04 Jul 2023)
12 | # datetime :datetime default(Tue, 04 Jul 2023 12:34:56.000000000 UTC +00:00)
13 | # decimal :decimal(14, 2) default(43.21)
14 | # float :float(24) default(12.34)
15 | # integer :integer default(99)
16 | # string :string(255) default("hello world!")
17 | # created_at :datetime not null
18 | # updated_at :datetime not null
19 | #
20 |
--------------------------------------------------------------------------------
/spec/templates/mysql2/test_null_false.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # == Schema Information
4 | #
5 | # Table name: test_null_falses
6 | #
7 | # id :bigint not null, primary key
8 | # binary :binary(65535) not null
9 | # boolean :boolean not null
10 | # date :date not null
11 | # datetime :datetime not null
12 | # decimal :decimal(14, 2) not null
13 | # float :float(24) not null
14 | # integer :integer not null
15 | # string :string(255) not null
16 | # text :text(65535) not null
17 | # timestamp :datetime not null
18 | # created_at :datetime not null
19 | # updated_at :datetime not null
20 | #
21 | # Indexes
22 | #
23 | # by_compound_bool_and_int (boolean,integer)
24 | # index_test_null_falses_on_date (date)
25 | #
26 | class TestNullFalse < ApplicationRecord
27 | end
28 |
--------------------------------------------------------------------------------
/spec/templates/pg/collapsed_test_model.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # == Schema Information
4 | #
5 | # Table name: collapsed_test_models
6 | #
7 | # id :bigint not null, primary key
8 | # collapsed :boolean
9 | # name :string
10 | # created_at :datetime not null
11 | # updated_at :datetime not null
12 | #
13 | module Collapsed
14 | class TestModel < ApplicationRecord
15 | def self.table_name_prefix
16 | "collapsed_"
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/spec/templates/pg/test_child_default.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: test_child_defaults
4 | #
5 | # id :bigint not null, primary key
6 | # created_at :datetime not null
7 | # updated_at :datetime not null
8 | # test_default_id :bigint not null
9 | #
10 | # Indexes
11 | #
12 | # index_test_child_defaults_on_test_default_id (test_default_id)
13 | #
14 | # Foreign Keys
15 | #
16 | # fk_rails_... (test_default_id => test_defaults.id)
17 | #
18 | class TestChildDefault < ApplicationRecord
19 | belongs_to :test_default
20 | end
21 |
--------------------------------------------------------------------------------
/spec/templates/pg/test_default.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # == Schema Information
4 | #
5 | # Table name: test_defaults
6 | #
7 | # id :bigint not null, primary key
8 | # boolean :boolean default(FALSE)
9 | # date :date default(Tue, 04 Jul 2023)
10 | # datetime :datetime default(Tue, 04 Jul 2023 12:34:56.000000000 UTC +00:00)
11 | # decimal :decimal(14, 2) default(43.21)
12 | # float :float default(12.34)
13 | # integer :integer default(99)
14 | # string :string default("hello world!")
15 | # created_at :datetime not null
16 | # updated_at :datetime not null
17 | #
18 | class TestDefault < ApplicationRecord
19 | end
20 |
--------------------------------------------------------------------------------
/spec/templates/pg/test_default_updated.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # == Schema Information
4 | #
5 | # Table name: test_defaults
6 | #
7 | # id :bigint not null, primary key
8 | # boolean :boolean default(FALSE)
9 | # date :date default(Tue, 04 Jul 2023)
10 | # datetime :datetime default(Tue, 04 Jul 2023 12:34:56.000000000 UTC +00:00)
11 | # decimal :decimal(14, 2) default(43.21)
12 | # float :float default(12.34)
13 | # int_field :integer
14 | # integer :integer default(99)
15 | # string :string default("hello world!")
16 | # created_at :datetime not null
17 | # updated_at :datetime not null
18 | #
19 | class TestDefault < ApplicationRecord
20 | end
21 |
--------------------------------------------------------------------------------
/spec/templates/pg/test_default_with_bottom_annotations.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | class TestDefault < ApplicationRecord
3 | end
4 |
5 | # == Schema Information
6 | #
7 | # Table name: test_defaults
8 | #
9 | # id :bigint not null, primary key
10 | # boolean :boolean default(FALSE)
11 | # date :date default(Tue, 04 Jul 2023)
12 | # datetime :datetime default(Tue, 04 Jul 2023 12:34:56.000000000 UTC +00:00)
13 | # decimal :decimal(14, 2) default(43.21)
14 | # float :float default(12.34)
15 | # integer :integer default(99)
16 | # string :string default("hello world!")
17 | # created_at :datetime not null
18 | # updated_at :datetime not null
19 | #
20 |
--------------------------------------------------------------------------------
/spec/templates/pg/test_null_false.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # == Schema Information
4 | #
5 | # Table name: test_null_falses
6 | #
7 | # id :bigint not null, primary key
8 | # binary :binary not null
9 | # boolean :boolean not null
10 | # date :date not null
11 | # datetime :datetime not null
12 | # decimal :decimal(14, 2) not null
13 | # float :float not null
14 | # integer :integer not null
15 | # string :string not null
16 | # text :text not null
17 | # timestamp :datetime not null
18 | # created_at :datetime not null
19 | # updated_at :datetime not null
20 | #
21 | # Indexes
22 | #
23 | # by_compound_bool_and_int (boolean,integer)
24 | # index_test_null_falses_on_date (date)
25 | #
26 | class TestNullFalse < ApplicationRecord
27 | end
28 |
--------------------------------------------------------------------------------
/spec/templates/routes.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # == Route Map
4 | #
5 | # Prefix Verb URI Pattern Controller#Action
6 | # root GET / articles#index
7 | # resources GET /resources(.:format) resources#index
8 | # POST /resources(.:format) resources#create
9 | # new_resource GET /resources/new(.:format) resources#new
10 | # edit_resource GET /resources/:id/edit(.:format) resources#edit
11 | # resource GET /resources/:id(.:format) resources#show
12 | # PATCH /resources/:id(.:format) resources#update
13 | # PUT /resources/:id(.:format) resources#update
14 | # DELETE /resources/:id(.:format) resources#destroy
15 | # new_singular_resource GET /singular_resource/new(.:format) singular_resources#new
16 | # edit_singular_resource GET /singular_resource/edit(.:format) singular_resources#edit
17 | # singular_resource GET /singular_resource(.:format) singular_resources#show
18 | # PATCH /singular_resource(.:format) singular_resources#update
19 | # PUT /singular_resource(.:format) singular_resources#update
20 | # DELETE /singular_resource(.:format) singular_resources#destroy
21 | # POST /singular_resource(.:format) singular_resources#create
22 | # manual GET /manual(.:format) manual#show
23 |
24 | Rails.application.routes.draw do
25 | root "articles#index"
26 | resources :resources
27 | resource :singular_resource
28 |
29 | get "/manual", to: "manual#show"
30 | end
31 |
--------------------------------------------------------------------------------
/spec/templates/sqlite3/collapsed_test_model.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # == Schema Information
4 | #
5 | # Table name: collapsed_test_models
6 | #
7 | # id :integer not null, primary key
8 | # collapsed :boolean
9 | # name :string
10 | # created_at :datetime not null
11 | # updated_at :datetime not null
12 | #
13 | module Collapsed
14 | class TestModel < ApplicationRecord
15 | def self.table_name_prefix
16 | "collapsed_"
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/spec/templates/sqlite3/test_child_default.rb:
--------------------------------------------------------------------------------
1 | # == Schema Information
2 | #
3 | # Table name: test_child_defaults
4 | #
5 | # id :integer not null, primary key
6 | # created_at :datetime not null
7 | # updated_at :datetime not null
8 | # test_default_id :integer not null
9 | #
10 | # Indexes
11 | #
12 | # index_test_child_defaults_on_test_default_id (test_default_id)
13 | #
14 | # Foreign Keys
15 | #
16 | # test_default_id (test_default_id => test_defaults.id)
17 | #
18 | class TestChildDefault < ApplicationRecord
19 | belongs_to :test_default
20 | end
21 |
--------------------------------------------------------------------------------
/spec/templates/sqlite3/test_default.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # == Schema Information
4 | #
5 | # Table name: test_defaults
6 | #
7 | # id :integer not null, primary key
8 | # boolean :boolean default(FALSE)
9 | # date :date default(Tue, 04 Jul 2023)
10 | # datetime :datetime default(Tue, 04 Jul 2023 12:34:56.000000000 UTC +00:00)
11 | # decimal :decimal(14, 2) default(43.21)
12 | # float :float default(12.34)
13 | # integer :integer default(99)
14 | # string :string default("hello world!")
15 | # created_at :datetime not null
16 | # updated_at :datetime not null
17 | #
18 | class TestDefault < ApplicationRecord
19 | end
20 |
--------------------------------------------------------------------------------
/spec/templates/sqlite3/test_default_updated.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # == Schema Information
4 | #
5 | # Table name: test_defaults
6 | #
7 | # id :integer not null, primary key
8 | # boolean :boolean default(FALSE)
9 | # date :date default(Tue, 04 Jul 2023)
10 | # datetime :datetime default(Tue, 04 Jul 2023 12:34:56.000000000 UTC +00:00)
11 | # decimal :decimal(14, 2) default(43.21)
12 | # float :float default(12.34)
13 | # int_field :integer
14 | # integer :integer default(99)
15 | # string :string default("hello world!")
16 | # created_at :datetime not null
17 | # updated_at :datetime not null
18 | #
19 | class TestDefault < ApplicationRecord
20 | end
21 |
--------------------------------------------------------------------------------
/spec/templates/sqlite3/test_default_with_bottom_annotations.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | class TestDefault < ApplicationRecord
3 | end
4 |
5 | # == Schema Information
6 | #
7 | # Table name: test_defaults
8 | #
9 | # id :integer not null, primary key
10 | # boolean :boolean default(FALSE)
11 | # date :date default(Tue, 04 Jul 2023)
12 | # datetime :datetime default(Tue, 04 Jul 2023 12:34:56.000000000 UTC +00:00)
13 | # decimal :decimal(14, 2) default(43.21)
14 | # float :float default(12.34)
15 | # integer :integer default(99)
16 | # string :string default("hello world!")
17 | # created_at :datetime not null
18 | # updated_at :datetime not null
19 | #
20 |
--------------------------------------------------------------------------------
/spec/templates/sqlite3/test_null_false.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # == Schema Information
4 | #
5 | # Table name: test_null_falses
6 | #
7 | # id :integer not null, primary key
8 | # binary :binary not null
9 | # boolean :boolean not null
10 | # date :date not null
11 | # datetime :datetime not null
12 | # decimal :decimal(14, 2) not null
13 | # float :float not null
14 | # integer :integer not null
15 | # string :string not null
16 | # text :text not null
17 | # timestamp :datetime not null
18 | # created_at :datetime not null
19 | # updated_at :datetime not null
20 | #
21 | # Indexes
22 | #
23 | # by_compound_bool_and_int (boolean,integer)
24 | # index_test_null_falses_on_date (date)
25 | #
26 | class TestNullFalse < ApplicationRecord
27 | end
28 |
--------------------------------------------------------------------------------