File: app_test.rb

package info (click to toggle)
ruby-spring 1.1.3-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 364 kB
  • ctags: 429
  • sloc: ruby: 2,762; makefile: 6
file content (334 lines) | stat: -rw-r--r-- 10,347 bytes parent folder | download
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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
# encoding: utf-8
require "helper"
require "acceptance/helper"
require "io/wait"
require "timeout"
require "spring/sid"
require "spring/client"

class AppTest < ActiveSupport::TestCase
  DEFAULT_SPEEDUP = 0.8

  def rails_version
    ENV['RAILS_VERSION'] || '~> 4.0.0'
  end

  def generator
    @@generator ||= Spring::Test::ApplicationGenerator.new(rails_version)
  end

  def app
    @app ||= Spring::Test::Application.new("#{TEST_ROOT}/apps/tmp")
  end

  def assert_output(artifacts, expected)
    expected.each do |stream, output|
      assert artifacts[stream].include?(output),
             "expected #{stream} to include '#{output}'.\n\n#{app.debug(artifacts)}"
    end
  end

  def assert_success(command, expected_output = nil)
    artifacts = app.run(*Array(command))
    assert artifacts[:status].success?, "expected successful exit status\n\n#{app.debug(artifacts)}"
    assert_output artifacts, expected_output if expected_output
  end

  def assert_failure(command, expected_output = nil)
    artifacts = app.run(*Array(command))
    assert !artifacts[:status].success?, "expected unsuccessful exit status\n\n#{app.debug(artifacts)}"
    assert_output artifacts, expected_output if expected_output
  end

  def assert_speedup(ratio = DEFAULT_SPEEDUP)
    if ENV['CI']
      yield
    else
      app.with_timing do
        yield
        assert app.timing_ratio < ratio, "#{app.last_time} was not less than #{ratio} of #{app.first_time}"
      end
    end
  end

  def assert_app_reloaded
    assert_success app.spring_test_command

    File.write(app.application_config, app.application_config.read + <<-CODE)
      class Foo
        def self.omg
          raise "omg"
        end
      end
    CODE
    File.write(app.test, app.test.read.sub("get :index", "Foo.omg"))

    app.await_reload
    assert_failure app.spring_test_command, stdout: "RuntimeError: omg"
  end

  setup do
    generator.generate_if_missing
    generator.install_spring
    generator.copy_to(app.root)
  end

  teardown do
    app.stop_spring
  end

  test "basic" do
    assert_speedup do
      2.times { app.run app.spring_test_command }
    end
  end

  test "help message when called without arguments" do
    assert_success "bin/spring", stdout: 'Usage: spring COMMAND [ARGS]'
  end

  test "test changes are picked up" do
    assert_speedup do
      assert_success app.spring_test_command, stdout: "0 failures"

      File.write(app.test, app.test.read.sub("get :index", "raise 'omg'"))
      assert_failure app.spring_test_command, stdout: "RuntimeError: omg"
    end
  end

  test "code changes are picked up" do
    assert_speedup do
      assert_success app.spring_test_command, stdout: "0 failures"

      File.write(app.controller, app.controller.read.sub("@posts = Post.all", "raise 'omg'"))
      assert_failure app.spring_test_command, stdout: "RuntimeError: omg"
    end
  end

  test "code changes in pre-referenced app files are picked up" do
    File.write(app.path("config/initializers/load_posts_controller.rb"), "PostsController\n")

    assert_speedup do
      assert_success app.spring_test_command, stdout: "0 failures"

      File.write(app.controller, app.controller.read.sub("@posts = Post.all", "raise 'omg'"))
      assert_failure app.spring_test_command, stdout: "RuntimeError: omg"
    end
  end

  test "app gets reloaded when preloaded files change (polling watcher)" do
    app.env["RAILS_ENV"] = "test"
    assert_success "bin/rails runner 'puts Spring.watcher.class'", stdout: "Polling"
    assert_app_reloaded
  end

  test "app gets reloaded when preloaded files change (listen watcher)" do
    File.write(app.gemfile, "#{app.gemfile.read}gem 'listen', '~> 1.0'")
    File.write(app.spring_config, "Spring.watch_method = :listen")
    app.bundle

    app.env["RAILS_ENV"] = "test"
    assert_success "bin/rails runner 'puts Spring.watcher.class'", stdout: "Listen"
    assert_app_reloaded
  end

  test "app recovers when a boot-level error is introduced" do
    config = app.application_config.read

    assert_success app.spring_test_command

    File.write(app.application_config, "#{config}\nomg")
    app.await_reload

    assert_failure app.spring_test_command

    File.write(app.application_config, config)
    assert_success app.spring_test_command
  end

  test "stop command kills server" do
    app.run app.spring_test_command
    assert app.spring_env.server_running?, "The server should be running but it isn't"

    assert_success "bin/spring stop"
    assert !app.spring_env.server_running?, "The server should not be running but it is"
  end

  test "custom commands" do
    File.write(app.spring_config, <<-CODE)
      class CustomCommand
        def call
          puts "omg"
        end

        def exec_name
          "rake"
        end
      end

      Spring.register_command "custom", CustomCommand.new
    CODE

    assert_success "bin/spring custom", stdout: "omg"

    assert_success "bin/spring binstub custom"
    assert_success "bin/custom", stdout: "omg"

    app.env["DISABLE_SPRING"] = "1"
    assert_success %{bin/custom -e 'puts "foo"'}, stdout: "foo"
  end

  test "binstub" do
    assert_success "bin/rails server --help", stdout: "Usage: rails server" # rails command fallback

    assert_success "#{app.spring} binstub rake", stdout: "bin/rake: spring already present"

    assert_success "#{app.spring} binstub --remove rake", stdout: "bin/rake: spring removed"
    assert !app.path("bin/rake").read.include?(Spring::Client::Binstub::LOADER)
    assert_success "bin/rake -T", stdout: "rake db:migrate"
  end

  test "binstub when spring is uninstalled" do
    app.run! "gem uninstall --ignore-dependencies spring"
    File.write(app.gemfile, app.gemfile.read.gsub(/gem 'spring.*/, ""))
    assert_success "bin/rake -T", stdout: "rake db:migrate"
  end

  test "binstub upgrade" do
    File.write(app.path("bin/rake"), <<CODE)
#!/usr/bin/env ruby

if !Process.respond_to?(:fork) || Gem::Specification.find_all_by_name("spring").empty?
  exec "bundle", "exec", "rake", *ARGV
else
  ARGV.unshift "rake"
  load Gem.bin_path("spring", "spring")
end
CODE

    File.write(app.path("bin/rails"), <<CODE)
#!/usr/bin/env ruby

if !Process.respond_to?(:fork) || Gem::Specification.find_all_by_name("spring").empty?
  APP_PATH = File.expand_path('../../config/application',  __FILE__)
  require_relative '../config/boot'
  require 'rails/commands'
else
  ARGV.unshift "rails"
  load Gem.bin_path("spring", "spring")
end
CODE

    assert_success "bin/spring binstub --all", stdout: "upgraded"

    assert_equal app.path("bin/rake").read, <<CODE
#!/usr/bin/env ruby
#{Spring::Client::Binstub::LOADER.strip}
require 'bundler/setup'
load Gem.bin_path('rake', 'rake')
CODE

    assert_equal app.path("bin/rails").read, <<CODE
#!/usr/bin/env ruby
#{Spring::Client::Binstub::LOADER.strip}
APP_PATH = File.expand_path('../../config/application',  __FILE__)
require_relative '../config/boot'
require 'rails/commands'
CODE
  end

  test "after fork callback" do
    File.write(app.spring_config, "Spring.after_fork { puts '!callback!' }")
    assert_success "bin/rails runner 'puts 2'", stdout: "!callback!\n2"
  end

  test "global config file evaluated" do
    File.write("#{app.user_home}/.spring.rb", "Spring.after_fork { puts '!callback!' }")
    assert_success "bin/rails runner 'puts 2'", stdout: "!callback!\n2"
  end

  test "missing config/application.rb" do
    app.application_config.delete
    assert_failure "bin/rake -T", stderr: "unable to find your config/application.rb"
  end

  test "piping" do
    assert_success "bin/rake -T | grep db", stdout: "rake db:migrate"
  end

  test "status" do
    assert_success "bin/spring status", stdout: "Spring is not running"
    assert_success "bin/rails runner ''"
    assert_success "bin/spring status", stdout: "Spring is running"
  end

  test "runner command sets Rails environment from command-line options" do
    assert_success "bin/rails runner -e test 'puts Rails.env'", stdout: "test"
    assert_success "bin/rails runner --environment=test 'puts Rails.env'", stdout: "test"
  end

  test "forcing rails env via environment variable" do
    app.env['RAILS_ENV'] = 'test'
    assert_success "bin/rake -p 'Rails.env'", stdout: "test"
  end

  test "setting env vars with rake" do
    File.write(app.path("lib/tasks/env.rake"), <<-'CODE')
      task :print_rails_env => :environment do
        puts Rails.env
      end

      task :print_env do
        ENV.each { |k, v| puts "#{k}=#{v}" }
      end

      task(:default).clear.enhance [:print_rails_env]
    CODE

    assert_success "bin/rake RAILS_ENV=test print_rails_env", stdout: "test"
    assert_success "bin/rake FOO=bar print_env", stdout: "FOO=bar"
    assert_success "bin/rake", stdout: "test"
  end

  test "changing the Gemfile works" do
    assert_success %(bin/rails runner 'require "sqlite3"')

    File.write(app.gemfile, app.gemfile.read.sub(%{gem 'sqlite3'}, %{# gem 'sqlite3'}))
    app.await_reload

    assert_failure %(bin/rails runner 'require "sqlite3"'), stderr: "sqlite3"
  end

  test "changing the Gemfile works when spring calls into itself" do
    File.write(app.path("script.rb"), <<-CODE)
      gemfile = Rails.root.join("Gemfile")
      File.write(gemfile, "\#{gemfile.read}gem 'devise'\\n")
      Bundler.with_clean_env do
        system(#{app.env.inspect}, "bundle install")
      end
      output = `\#{Rails.root.join('bin/rails')} runner 'require "devise"; puts "done";'`
      exit output == "done\n"
    CODE

    assert_success [%(bin/rails runner 'load Rails.root.join("script.rb")'), timeout: 60]
  end

  test "changing the environment between runs" do
    File.write(app.application_config, "#{app.application_config.read}\nENV['BAR'] = 'bar'")

    app.env["OMG"] = "1"
    app.env["FOO"] = "1"
    app.env["RUBYOPT"] = "-rubygems"

    assert_success %(bin/rails runner 'p ENV["OMG"]'), stdout: "1"
    assert_success %(bin/rails runner 'p ENV["BAR"]'), stdout: "bar"
    assert_success %(bin/rails runner 'p ENV.key?("BUNDLE_GEMFILE")'), stdout: "true"
    assert_success %(bin/rails runner 'p ENV["RUBYOPT"]'), stdout: "bundler"

    app.env["OMG"] = "2"
    app.env.delete "FOO"

    assert_success %(bin/rails runner 'p ENV["OMG"]'), stdout: "2"
    assert_success %(bin/rails runner 'p ENV.key?("FOO")'), stdout: "false"
  end
end