initial fun commit
This commit is contained in:
commit
3325bce18b
|
@ -0,0 +1,17 @@
|
||||||
|
*.gem
|
||||||
|
*.rbc
|
||||||
|
.bundle
|
||||||
|
.config
|
||||||
|
.yardoc
|
||||||
|
Gemfile.lock
|
||||||
|
InstalledFiles
|
||||||
|
_yardoc
|
||||||
|
coverage
|
||||||
|
doc/
|
||||||
|
lib/bundler/man
|
||||||
|
pkg
|
||||||
|
rdoc
|
||||||
|
spec/reports
|
||||||
|
test/tmp
|
||||||
|
test/version_tmp
|
||||||
|
tmp
|
|
@ -0,0 +1,4 @@
|
||||||
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
|
# Specify your gem's dependencies in vegetable_glue.gemspec
|
||||||
|
gemspec
|
|
@ -0,0 +1,22 @@
|
||||||
|
Copyright (c) 2012 John Bintz
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,54 @@
|
||||||
|
# VegetableGlue
|
||||||
|
|
||||||
|
Easy way to start/stop/restart a dependent Rails API app in a consumer's acceptance tests.
|
||||||
|
Uses `database_cleaner`'s `:truncation` mode to clean out your databases after each run.
|
||||||
|
|
||||||
|
## Installation & Usage
|
||||||
|
|
||||||
|
In both apps' Gemfiles:
|
||||||
|
|
||||||
|
``` ruby
|
||||||
|
gem 'vegetable_glue'
|
||||||
|
```
|
||||||
|
|
||||||
|
In the provider (API):
|
||||||
|
|
||||||
|
* Create or use a Rails environment that has a database that you don't mind nuking (say `test`, `acceptance`, or `cucumber`)
|
||||||
|
* Modify `config/routes.rb`:
|
||||||
|
|
||||||
|
``` ruby
|
||||||
|
require 'vegetable_glue/routes'
|
||||||
|
|
||||||
|
MyApp::Application.routes.draw do
|
||||||
|
# ... your other routes ...
|
||||||
|
|
||||||
|
acceptance_helper_routes #=> for the :acceptance env, or
|
||||||
|
acceptance_helper_routes_for :cucumber #=> for the :cucumber env
|
||||||
|
end
|
||||||
|
|
||||||
|
The two additional routes are only added in that environment.
|
||||||
|
|
||||||
|
In the consumer (Frontend):
|
||||||
|
|
||||||
|
* For Cucumber, add the following to `features/support/env.rb`:
|
||||||
|
|
||||||
|
``` ruby
|
||||||
|
require 'vegetable_glue/cucumber'
|
||||||
|
|
||||||
|
VegetableGlue.url = 'http://localhost:6161/' #=> include the port in here, too, that's where the app will run
|
||||||
|
VegetableGlue.path = '../path/to/the/app'
|
||||||
|
```
|
||||||
|
|
||||||
|
The app will clean its database on each scenario. To restart the app, pass in the environment variable `GLUE_RESTART`:
|
||||||
|
|
||||||
|
GLUE_RESTART=true bundle exec cucumber
|
||||||
|
|
||||||
|
If you're using ActiveResource, a good source of the URL is `ActiveResource::Base.site`.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
1. Fork it
|
||||||
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
||||||
|
3. Commit your changes (`git commit -am 'Added some feature'`)
|
||||||
|
4. Push to the branch (`git push origin my-new-feature`)
|
||||||
|
5. Create new Pull Request
|
|
@ -0,0 +1,33 @@
|
||||||
|
require "vegetable_glue/version"
|
||||||
|
require 'net/http'
|
||||||
|
require 'fileutils'
|
||||||
|
|
||||||
|
module VegetableGlue
|
||||||
|
autoload :Runner, 'vegetable_glue/runner'
|
||||||
|
|
||||||
|
ACCEPTANCE = '__acceptance__'
|
||||||
|
CLEAN = '__clean__'
|
||||||
|
|
||||||
|
class << self
|
||||||
|
attr_accessor :url, :path, :env
|
||||||
|
|
||||||
|
def shutdown
|
||||||
|
Runner.new(options).shutdown
|
||||||
|
end
|
||||||
|
|
||||||
|
def clean
|
||||||
|
Runner.new(options).clean
|
||||||
|
end
|
||||||
|
|
||||||
|
def env
|
||||||
|
@env ||= :cucumber
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def options
|
||||||
|
{ :url => url, :path => path, :env => env }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
Before do
|
||||||
|
if ENV['GLUE_RESTART']
|
||||||
|
VegetableGlue.shutdown
|
||||||
|
|
||||||
|
ENV.delete('GLUE_RESTART')
|
||||||
|
end
|
||||||
|
|
||||||
|
VegetableGlue.clean
|
||||||
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
class ActionDispatch::Routing::Mapper
|
||||||
|
def acceptance_helper_routes
|
||||||
|
acceptance_helper_routes_for
|
||||||
|
end
|
||||||
|
|
||||||
|
def acceptance_helper_routes_for(env = :acceptance)
|
||||||
|
if Rails.env.to_sym == env
|
||||||
|
get VegetableGlue::ACCEPTANCE => lambda { |env| [ 200, {}, [ VegetableGlue::ACCEPTANCE ] ] }
|
||||||
|
|
||||||
|
get VegetableGlue::CLEAN => lambda { |env|
|
||||||
|
require 'database_cleaner'
|
||||||
|
|
||||||
|
DatabaseCleaner.clean_with :truncation
|
||||||
|
|
||||||
|
[ 200, {}, [ VegetableGlue::CLEAN ] ]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
module VegetableGlue
|
||||||
|
class Runner
|
||||||
|
attr_reader :options
|
||||||
|
|
||||||
|
def initialize(options = {})
|
||||||
|
@options = options
|
||||||
|
end
|
||||||
|
|
||||||
|
def ensure_running
|
||||||
|
port = options[:url].port
|
||||||
|
|
||||||
|
result = nil
|
||||||
|
|
||||||
|
begin
|
||||||
|
result = get_acceptance
|
||||||
|
rescue Errno::ECONNREFUSED => e
|
||||||
|
$stdout.puts "Starting #{app_name}..."
|
||||||
|
|
||||||
|
Bundler.with_clean_env do
|
||||||
|
system %{cd #{options[:path]} && bundle exec rails server -p #{port} -d -e #{options[:env]} -P #{pid_path}}
|
||||||
|
end
|
||||||
|
|
||||||
|
raise StandardError.new("#{app_name} did not start up in 30 seconds!") if !(result = wait_for_up)
|
||||||
|
end
|
||||||
|
|
||||||
|
if result == VegetableGlue::ACCEPTANCE
|
||||||
|
$stdout.puts "#{app_name} running on port #{port}"
|
||||||
|
else
|
||||||
|
raise StandardError.new("Is #{app_name} running? You should have included the routes with `acceptance_helper_routes`")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def shutdown
|
||||||
|
if File.file?(pid_path)
|
||||||
|
system %{kill -INT #{File.read(pid_path)}}
|
||||||
|
|
||||||
|
wait_for_down
|
||||||
|
|
||||||
|
$stdout.puts "#{app_name} shut down"
|
||||||
|
end
|
||||||
|
|
||||||
|
FileUtils.rm_f pid_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def clean
|
||||||
|
ensure_running
|
||||||
|
|
||||||
|
result = Net::HTTP.get(options[:url].merge(URI("/#{VegetableGlue::CLEAN}")))
|
||||||
|
|
||||||
|
raise StandardError.new("#{app_name} database not cleaned") if result != VegetableGlue::CLEAN
|
||||||
|
end
|
||||||
|
|
||||||
|
def pid_path
|
||||||
|
File.join(File.expand_path(options[:path]), "tmp/pids/#{options[:env]}.pid")
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def get_acceptance
|
||||||
|
Net::HTTP.get(options[:url].merge(URI("/#{VegetableGlue::ACCEPTANCE}")))
|
||||||
|
end
|
||||||
|
|
||||||
|
def app_name
|
||||||
|
File.basename(options[:path])
|
||||||
|
end
|
||||||
|
|
||||||
|
def wait_for_down
|
||||||
|
times = 30
|
||||||
|
|
||||||
|
while times > 0
|
||||||
|
begin
|
||||||
|
Net::HTTP.get(options[:url])
|
||||||
|
rescue Errno::ECONNREFUSED, Errno::ECONNRESET
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
times -= 1
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
end
|
||||||
|
|
||||||
|
raise StandardError.new("#{app_name} did not shut down")
|
||||||
|
end
|
||||||
|
|
||||||
|
def wait_for_up
|
||||||
|
times = 30
|
||||||
|
result = nil
|
||||||
|
|
||||||
|
while times > 0
|
||||||
|
begin
|
||||||
|
result = get_acceptance
|
||||||
|
rescue Errno::ECONNREFUSED, Errno::ECONNRESET
|
||||||
|
end
|
||||||
|
|
||||||
|
break if result
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
times -= 1
|
||||||
|
end
|
||||||
|
|
||||||
|
result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
module VegetableGlue
|
||||||
|
VERSION = "0.0.1"
|
||||||
|
end
|
|
@ -0,0 +1,19 @@
|
||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
require File.expand_path('../lib/vegetable_glue/version', __FILE__)
|
||||||
|
|
||||||
|
Gem::Specification.new do |gem|
|
||||||
|
gem.authors = ["John Bintz"]
|
||||||
|
gem.email = ["john@coswellproductions.com"]
|
||||||
|
gem.description = %q{TODO: Write a gem description}
|
||||||
|
gem.summary = %q{TODO: Write a gem summary}
|
||||||
|
gem.homepage = ""
|
||||||
|
|
||||||
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
||||||
|
gem.files = `git ls-files`.split("\n")
|
||||||
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
||||||
|
gem.name = "vegetable_glue"
|
||||||
|
gem.require_paths = ["lib"]
|
||||||
|
gem.version = VegetableGlue::VERSION
|
||||||
|
|
||||||
|
gem.add_dependency 'database_cleaner'
|
||||||
|
end
|
Loading…
Reference in New Issue