aboutsummaryrefslogtreecommitdiffstats
path: root/railties/test/generators/plugin_new_generator_test.rb
blob: 638ff8dce5b4bca4c5c10dfca5e51c5d75794c0d (plain) (blame)
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
require 'abstract_unit'
require 'generators/generators_test_helper'
require 'rails/generators/rails/plugin_new/plugin_new_generator'

DEFAULT_PLUGIN_FILES = %w(
  .gitignore
  Gemfile
  Rakefile
  bukkits.gemspec
  MIT-LICENSE
  lib
  lib/bukkits.rb
  script/rails
  test/bukkits_test.rb
  test/integration/navigation_test.rb
  test/support/integration_case.rb
  test/test_helper.rb
  test/dummy
)


class PluginNewGeneratorTest < Rails::Generators::TestCase
  include GeneratorsTestHelper
  destination File.join(Rails.root, "tmp/bukkits")
  arguments [destination_root]

  def setup
    Rails.application = TestApp::Application
    super
    @bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle')

    Kernel::silence_warnings do
      Thor::Base.shell.send(:attr_accessor, :always_force)
      @shell = Thor::Base.shell.new
      @shell.send(:always_force=, true)
    end
  end

  def teardown
    super
    Rails.application = TestApp::Application.instance
  end

  def test_plugin_skeleton_is_created
    run_generator

    DEFAULT_PLUGIN_FILES.each{ |path| assert_file path }
  end

  def test_plugin_new_generate_pretend
    run_generator ["testapp", "--pretend"]

    DEFAULT_PLUGIN_FILES.each{ |path| assert_no_file path }
  end

  def test_options_before_plugin_name_raises_an_error
    content = capture(:stderr){ run_generator(["--pretend", destination_root]) }
    assert_equal "Options should be given after plugin name. For details run: rails plugin --help\n", content
  end

  def test_name_collision_raises_an_error
    reserved_words = %w[application destroy plugin runner test]
    reserved_words.each do |reserved|
      content = capture(:stderr){ run_generator [File.join(destination_root, reserved)] }
      assert_equal "Invalid plugin name #{reserved}. Please give a name which does not match one of the reserved rails words.\n", content
    end
  end

  def test_invalid_plugin_name_raises_an_error
    content = capture(:stderr){ run_generator [File.join(destination_root, "43-things")] }
    assert_equal "Invalid plugin name 43-things. Please give a name which does not start with numbers.\n", content
  end

  def test_plugin_name_raises_an_error_if_name_already_used_constant
    %w{ String Hash Class Module Set Symbol }.each do |ruby_class|
      content = capture(:stderr){ run_generator [File.join(destination_root, ruby_class)] }
      assert_equal "Invalid plugin name #{ruby_class}, constant #{ruby_class} is already in use. Please choose another application name.\n", content
    end
  end

  def test_invalid_plugin_name_is_fixed
    run_generator [File.join(destination_root, "things-43")]
    assert_file "things-43/lib/things-43.rb", /module Things43/
  end

  def test_shebang_is_added_to_rails_file
    run_generator [destination_root, "--ruby", "foo/bar/baz"]
    assert_file "script/rails", /#!foo\/bar\/baz/
  end

  def test_shebang_when_is_the_same_as_default_use_env
    run_generator [destination_root, "--ruby", Thor::Util.ruby_command]
    assert_file "script/rails", /#!\/usr\/bin\/env/
  end

  def test_generating_test_files
    run_generator
    assert_file "test/test_helper.rb"
    assert_directory "test/support/"
    assert_directory "test/integration/"

    assert_file "test/bukkits_test.rb", /assert_kind_of Module, Bukkits/
    assert_file "test/integration/navigation_test.rb", /assert_kind_of Dummy::Application, Rails.application/
    assert_file "test/support/integration_case.rb", /class ActiveSupport::IntegrationCase/
  end

  def test_ensure_that_plugin_options_are_not_passed_app_generator
    output = run_generator [destination_root, "--skip_gemfile"]
    assert_no_file "Gemfile"
    assert_match /STEP 2.*create  Gemfile/m, output
  end

  def test_template_from_dir_pwd
    FileUtils.cd(Rails.root)
    assert_match /It works from file!/, run_generator([destination_root, "-m", "lib/template.rb"])
  end

  def test_template_raises_an_error_with_invalid_path
    content = capture(:stderr){ run_generator([destination_root, "-m", "non/existant/path"]) }
    assert_match /The template \[.*\] could not be loaded/, content
    assert_match /non\/existant\/path/, content
  end

  def test_template_is_executed_when_supplied
    path = "http://gist.github.com/103208.txt"
    template = %{ say "It works!" }
    template.instance_eval "def read; self; end" # Make the string respond to read

    generator([destination_root], :template => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template)
    assert_match /It works!/, silence(:stdout){ generator.invoke_all }
  end

  def test_dev_option
    generator([destination_root], :dev => true).expects(:run).with("#{@bundle_command} install")
    silence(:stdout){ generator.invoke_all }
    rails_path = File.expand_path('../../..', Rails.root)
    assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:path\s+=>\s+["']#{Regexp.escape(rails_path)}["']$/
  end

  def test_edge_option
    generator([destination_root], :edge => true).expects(:run).with("#{@bundle_command} install")
    silence(:stdout){ generator.invoke_all }
    assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:git\s+=>\s+["']#{Regexp.escape("git://github.com/rails/rails.git")}["']$/
  end

protected

  def action(*args, &block)
    silence(:stdout){ generator.send(*args, &block) }
  end

end

class CustomPluginGeneratorTest < Rails::Generators::TestCase
  include GeneratorsTestHelper
  tests Rails::Generators::PluginNewGenerator

  destination File.join(Rails.root, "tmp/bukkits")
  arguments [destination_root]

  def setup
    Rails.application = TestApp::Application
    super
    @bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle')
  end

  def teardown
    super
    Object.class_eval { remove_const :PluginBuilder if const_defined?(:PluginBuilder) }
    Rails.application = TestApp::Application.instance
  end

  def test_builder_option_with_empty_app_builder
    FileUtils.cd(destination_root)
    run_generator([destination_root, "-b", "#{Rails.root}/lib/plugin_builders/empty_builder.rb"])
    DEFAULT_PLUGIN_FILES.each{ |path| assert_no_file path }
  end

  def test_builder_option_with_simple_plugin_builder
    FileUtils.cd(destination_root)
    run_generator([destination_root, "-b", "#{Rails.root}/lib/plugin_builders/simple_builder.rb"])
    (DEFAULT_PLUGIN_FILES - ['.gitignore']).each{ |path| assert_no_file path }
    assert_file ".gitignore", "foobar"
  end

  def test_builder_option_with_relative_path
    here = File.expand_path(File.dirname(__FILE__))
    FileUtils.cd(here)
    run_generator([destination_root, "-b", "../fixtures/lib/plugin_builders/simple_builder.rb"])
    FileUtils.cd(destination_root)
    (DEFAULT_PLUGIN_FILES - ['.gitignore']).each{ |path| assert_no_file path }
    assert_file ".gitignore", "foobar"
  end

  def test_builder_option_with_tweak_plugin_builder
    FileUtils.cd(destination_root)
    run_generator([destination_root, "-b", "#{Rails.root}/lib/plugin_builders/tweak_builder.rb"])
    DEFAULT_PLUGIN_FILES.each{ |path| assert_file path }
    assert_file ".gitignore", "foobar"
  end

  def test_builder_option_with_http
    path = "http://gist.github.com/103208.txt"
    template = "class PluginBuilder; end"
    template.instance_eval "def read; self; end" # Make the string respond to read

    generator([destination_root], :builder => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template)
    capture(:stdout) { generator.invoke_all }

    DEFAULT_PLUGIN_FILES.each{ |path| assert_no_file path }
  end

protected

  def action(*args, &block)
    silence(:stdout){ generator.send(*args, &block) }
  end
end