File: generators_test_helper.rb

package info (click to toggle)
rails 2%3A7.2.2.1%2Bdfsg-7
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 43,352 kB
  • sloc: ruby: 349,799; javascript: 30,703; yacc: 46; sql: 43; sh: 29; makefile: 27
file content (157 lines) | stat: -rw-r--r-- 5,087 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# frozen_string_literal: true

require "abstract_unit"
require "active_support/testing/stream"
require "active_support/testing/method_call_assertions"
require "rails/generators"
require "rails/generators/test_case"
require "rails/generators/app_base"

Rails.application.config.generators.templates = [File.expand_path("../fixtures/lib/templates", __dir__)]

# Call configure to load the settings from
# Rails.application.config.generators to Rails::Generators
Rails.application.load_generators

require "active_record"
require "action_dispatch"
require "action_view"

module GeneratorsTestHelper
  include ActiveSupport::Testing::Stream
  include ActiveSupport::Testing::MethodCallAssertions

  def self.included(base)
    base.class_eval do
      destination File.expand_path("../fixtures/tmp", __dir__)
      setup :prepare_destination

      setup { Rails.application.config.root = Pathname("../fixtures").expand_path(__dir__) }

      setup { @original_rakeopt, ENV["RAKEOPT"] = ENV["RAKEOPT"], "--silent" }
      teardown { ENV["RAKEOPT"] = @original_rakeopt }

      begin
        base.tests Rails::Generators.const_get(base.name.delete_suffix("Test"))
      rescue
      end
    end
  end

  def run_generator_instance
    capture(:stdout) do
      generator.invoke_all
    end
  end

  def with_database_configuration(database_name = "secondary")
    original_configurations = ActiveRecord::Base.configurations
    ActiveRecord::Base.configurations = {
      test: {
        "#{database_name}": {
          adapter: "sqlite3",
          database: "db/#{database_name}.sqlite3",
          migrations_paths: "db/#{database_name}_migrate",
        },
      },
    }
    yield
  ensure
    ActiveRecord::Base.configurations = original_configurations
  end

  def copy_routes
    routes = File.expand_path("../../lib/rails/generators/rails/app/templates/config/routes.rb.tt", __dir__)
    routes = evaluate_template(routes, {
      options: ActiveSupport::OrderedOptions.new
    })
    destination = File.join(destination_root, "config")
    FileUtils.mkdir_p(destination)
    File.write File.join(destination, "routes.rb"), routes
  end

  def copy_gemfile(*gemfile_entries)
    locals = gemfile_locals.merge(gemfile_entries: gemfile_entries)
    gemfile = File.expand_path("../../lib/rails/generators/rails/app/templates/Gemfile.tt", __dir__)
    gemfile = evaluate_template(gemfile, locals)
    destination = File.join(destination_root)
    File.write File.join(destination, "Gemfile"), gemfile
  end

  def copy_dockerfile
    dockerfile = File.expand_path("../fixtures/Dockerfile.test", __dir__)
    dockerfile = evaluate_template_docker(dockerfile)
    destination = File.join(destination_root)
    File.write File.join(destination, "Dockerfile"), dockerfile
  end

  def copy_devcontainer_files
    destination = File.join(destination_root, ".devcontainer")
    mkdir_p(destination)

    devcontainer_json = File.read(File.expand_path("../fixtures/.devcontainer/devcontainer.json", __dir__))
    File.write File.join(destination, "devcontainer.json"), devcontainer_json

    compose_yaml = File.read(File.expand_path("../fixtures/.devcontainer/compose.yaml", __dir__))
    File.write File.join(destination, "compose.yaml"), compose_yaml
  end

  def copy_minimal_devcontainer_compose_file
    destination = File.join(destination_root, ".devcontainer")
    mkdir_p(destination)

    compose_yaml = File.read(File.expand_path("../fixtures/.devcontainer/compose-minimal.yaml", __dir__))
    File.write File.join(destination, "compose.yaml"), compose_yaml
  end

  def evaluate_template(file, locals = {})
    erb = ERB.new(File.read(file), trim_mode: "-", eoutvar: "@output_buffer")
    context = Class.new do
      locals.each do |local, value|
        class_attribute local, default: value
      end
    end
    erb.result(context.new.instance_eval("binding"))
  end

  def evaluate_template_docker(file)
    erb = ERB.new(File.read(file), trim_mode: "-", eoutvar: "@output_buffer")
    erb.result()
  end

  def assert_compose_file
    assert_file ".devcontainer/compose.yaml" do |content|
      yield YAML.load(content)
    end
  end

  def assert_devcontainer_json_file
    assert_file ".devcontainer/devcontainer.json" do |content|
      yield JSON.load(content)
    end
  end

  def run_app_update(app_root = destination_root, flags: "--force")
    Dir.chdir(app_root) do
      gemfile_contents = File.read("Gemfile")
      gemfile_contents.sub!(/^(gem "rails").*/, "\\1, path: #{File.expand_path("../../..", __dir__).inspect}")
      File.write("Gemfile", gemfile_contents)

      quietly { system({ "BUNDLE_GEMFILE" => "Gemfile" }, "bin/rails app:update #{flags}", exception: true) }
    end
  end

  private
    def gemfile_locals
      {
        gem_ruby_version: RUBY_VERSION,
        rails_prerelease: false,
        skip_active_storage: true,
        depend_on_bootsnap: false,
        depends_on_system_test: false,
        options: ActiveSupport::OrderedOptions.new,
        skip_sprockets: false,
        bundler_windows_platforms: "windows",
      }
    end
end