lookout-rack-test 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +70 -0
- data/Rakefile +4 -0
- data/cucumber.yml +5 -0
- data/examples/test_app.rb +62 -0
- data/examples/test_models.rb +15 -0
- data/features/general_steps/requests.feature +13 -0
- data/features/general_steps/requests_with_json_body.feature +15 -0
- data/features/general_steps/requests_with_params.feature +27 -0
- data/features/general_steps/response.feature +21 -0
- data/features/liquid_templates.feature +44 -0
- data/features/not_timefreeze.feature +14 -0
- data/features/number_transform.feature +5 -0
- data/features/step_definitions/liquid_templates_steps.rb +3 -0
- data/features/step_definitions/number_transform_steps.rb +7 -0
- data/features/step_definitions/timefreeze_steps.rb +15 -0
- data/features/support/env.rb +10 -0
- data/features/timefreeze.feature +15 -0
- data/lib/lookout/rack/test.rb +8 -0
- data/lib/lookout/rack/test/cucumber.rb +32 -0
- data/lib/lookout/rack/test/cucumber/before.rb +5 -0
- data/lib/lookout/rack/test/cucumber/general_steps.rb +42 -0
- data/lib/lookout/rack/test/cucumber/server.rb +11 -0
- data/lib/lookout/rack/test/cucumber/transforms.rb +3 -0
- data/lib/lookout/rack/test/load_factories.rb +5 -0
- data/lib/lookout/rack/test/rake.rb +16 -0
- data/lib/lookout/rack/test/rake/cucumber.rake +16 -0
- data/lib/lookout/rack/test/rake/rspec.rake +21 -0
- data/lib/lookout/rack/test/rspec.rb +52 -0
- data/lib/lookout/rack/test/rspec/email_helpers.rb +32 -0
- data/lib/lookout/rack/test/rspec/fake_request.rb +20 -0
- data/lib/lookout/rack/test/rspec/model_examples.rb +12 -0
- data/lib/lookout/rack/test/rspec/route_helper.rb +7 -0
- data/lib/lookout/rack/test/version.rb +7 -0
- data/lookout-rack-test.gemspec +44 -0
- data/spec/email_helpers_spec.rb +104 -0
- data/spec/model_examples_spec.rb +51 -0
- data/spec/setup_spec.rb +51 -0
- data/spec/spec_helper.rb +15 -0
- metadata +339 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rack/test'
|
2
|
+
require 'cucumber'
|
3
|
+
require 'liquid'
|
4
|
+
|
5
|
+
require 'lookout/rack/test/cucumber/transforms'
|
6
|
+
require 'lookout/rack/test/cucumber/general_steps'
|
7
|
+
require 'lookout/rack/test/cucumber/before'
|
8
|
+
|
9
|
+
require 'lookout/rack/test/cucumber/server' if $application_class
|
10
|
+
|
11
|
+
module Lookout::Rack::Test
|
12
|
+
module Cucumber
|
13
|
+
def render_string(buffer, opts={})
|
14
|
+
::Liquid::Template.parse(buffer).render(template_vars.merge(opts))
|
15
|
+
end
|
16
|
+
|
17
|
+
def template_vars
|
18
|
+
@template_vars ||= {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def current_locale
|
22
|
+
I18n.locale = ENV['CUCUMBER_LOCALE'] || 'en'
|
23
|
+
end
|
24
|
+
|
25
|
+
def app
|
26
|
+
@app ||= $application_class.new if $application_class
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
World(Rack::Test::Methods)
|
32
|
+
World(Lookout::Rack::Test::Cucumber)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
When /^I (GET|PUT|POST|DELETE)( to)? "(.*?)"$/ do |verb, unused, url_path|
|
2
|
+
verb = verb.downcase.to_sym
|
3
|
+
send(verb, render_string(url_path))
|
4
|
+
end
|
5
|
+
|
6
|
+
When /^I (GET|POST|PUT)( to)? "([^"]*)" with:$/ do |verb, unused, url, params|
|
7
|
+
options = {}
|
8
|
+
|
9
|
+
params.hashes.each do |row|
|
10
|
+
options[row[:Name]] = render_string(row[:Value])
|
11
|
+
end
|
12
|
+
|
13
|
+
verb = verb.downcase.to_sym
|
14
|
+
send(verb, render_string(url), options)
|
15
|
+
end
|
16
|
+
|
17
|
+
When /^I (DELETE|POST) to "(.*?)" with the JSON:$/ do |verb, url, body|
|
18
|
+
verb = verb.downcase.to_sym
|
19
|
+
send(verb, render_string(url), render_string(body))
|
20
|
+
end
|
21
|
+
|
22
|
+
Then /^the response (should be|is) (\d+)$/ do |verb, code|
|
23
|
+
expect(last_response.status).to eq(code), "expected #{code} got #{last_response.status} \n\n #{last_response.body}
|
24
|
+
"
|
25
|
+
end
|
26
|
+
|
27
|
+
Then /^I should be redirected to "([^"]+)"$/ do |path|
|
28
|
+
expect(last_response.location).to end_with path
|
29
|
+
end
|
30
|
+
|
31
|
+
Then /^I should receive the JSON:$/ do |json|
|
32
|
+
template_vars['timestamp'] = Time.now.utc.iso8601
|
33
|
+
expected = JSON.parse(render_string(json))
|
34
|
+
|
35
|
+
begin
|
36
|
+
received = JSON.parse(last_response.body)
|
37
|
+
rescue JSON::ParserError => e
|
38
|
+
raise "Unexpected response: #{last_response.body}\n#{e}"
|
39
|
+
end
|
40
|
+
|
41
|
+
expect(received).to eql(expected)
|
42
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Lookout::Rack::Test
|
2
|
+
module Rake
|
3
|
+
end
|
4
|
+
end
|
5
|
+
|
6
|
+
# Load the rake tasks
|
7
|
+
Dir[File.expand_path(File.dirname(__FILE__) + '/rake/*.rake')].each do |f|
|
8
|
+
begin
|
9
|
+
load f
|
10
|
+
rescue LoadError => ex
|
11
|
+
puts "Failed to load #{f}"
|
12
|
+
puts ex
|
13
|
+
puts ex.backtrace
|
14
|
+
exit 1
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'cucumber/rake/task'
|
2
|
+
require 'ci/reporter/rake/cucumber'
|
3
|
+
|
4
|
+
# parallel_tests is somewhat pointless/nonfunctional on JRuby
|
5
|
+
unless RUBY_VERSION == 'java'
|
6
|
+
require 'parallel_tests/tasks'
|
7
|
+
end
|
8
|
+
|
9
|
+
namespace :cucumber do
|
10
|
+
Cucumber::Rake::Task.new(:api) do |t|
|
11
|
+
t.cucumber_opts = '--profile api'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Cucumber::Rake::Task.new(:cucumber) do |t|
|
16
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
require 'ci/reporter/rake/rspec'
|
3
|
+
|
4
|
+
RSpec::Core::RakeTask.new(:spec) do |r|
|
5
|
+
end
|
6
|
+
|
7
|
+
|
8
|
+
namespace :spec do
|
9
|
+
RSpec::Core::RakeTask.new(:slow) do |r|
|
10
|
+
r.rspec_opts = '-t speed:slow'
|
11
|
+
end
|
12
|
+
|
13
|
+
RSpec::Core::RakeTask.new(:fast) do |r|
|
14
|
+
r.rspec_opts = '-t ~speed:slow'
|
15
|
+
end
|
16
|
+
|
17
|
+
RSpec::Core::RakeTask.new(:routes) do |r|
|
18
|
+
r.rspec_opts = '-t type:route'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'rack/test'
|
3
|
+
require 'timecop'
|
4
|
+
|
5
|
+
require 'lookout/rack/test/rspec/email_helpers'
|
6
|
+
require 'lookout/rack/test/rspec/fake_request'
|
7
|
+
require 'lookout/rack/test/rspec/model_examples'
|
8
|
+
|
9
|
+
module Lookout
|
10
|
+
module Rack
|
11
|
+
module Test
|
12
|
+
module RSpec
|
13
|
+
# Takes one argument, the Models class (or module) that has a .setup and
|
14
|
+
# .unsetup method
|
15
|
+
def setup_models(models)
|
16
|
+
::RSpec.configure do |c|
|
17
|
+
c.around(:each, :speed => :slow) do |example|
|
18
|
+
models.setup
|
19
|
+
example.run
|
20
|
+
models.unsetup
|
21
|
+
end
|
22
|
+
|
23
|
+
c.before(:all, :speed => :slow) do
|
24
|
+
require 'lookout/rack/test/load_factories'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Takes one argument, the application (e.g., SinatraApplication)
|
30
|
+
def setup_routes(application)
|
31
|
+
::RSpec.configure do |c|
|
32
|
+
c.include(::Rack::Test::Methods, :type => :route)
|
33
|
+
|
34
|
+
require 'lookout/rack/test/rspec/route_helper'
|
35
|
+
$application_class = application
|
36
|
+
c.include(::RouteHelper, :type => :route)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def configure_rspec
|
41
|
+
::RSpec.configure do |c|
|
42
|
+
c.around(:each, :timefreeze => true) do |example|
|
43
|
+
::Timecop.freeze do
|
44
|
+
example.run
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'set'
|
3
|
+
require 'mercury-messages'
|
4
|
+
|
5
|
+
module Lookout::Rack::Test::RSpec
|
6
|
+
module Emails
|
7
|
+
def expect_emails(expected_email_names)
|
8
|
+
email_names = []
|
9
|
+
Mercury::Messages::SendImmediateBatchEmail.stub(:new) do |mail_hash|
|
10
|
+
email_names << mail_hash[:email_name]
|
11
|
+
end
|
12
|
+
|
13
|
+
yield
|
14
|
+
|
15
|
+
expect(Set.new(email_names)).to eql Set.new(expected_email_names)
|
16
|
+
end
|
17
|
+
|
18
|
+
def expect_email_attributes(expected_attributes)
|
19
|
+
attributes = []
|
20
|
+
Mercury::Messages::SendImmediateBatchEmail.stub(:new) do |mail_hash|
|
21
|
+
# Get all the keys (attributes) for each of this Message's pieces
|
22
|
+
attributes += mail_hash[:pieces].map{|h| h[:attributes]}.map(&:keys)
|
23
|
+
end
|
24
|
+
|
25
|
+
yield
|
26
|
+
|
27
|
+
attributes.flatten!
|
28
|
+
|
29
|
+
expect(Set.new(attributes)).to eql Set.new(expected_attributes)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
|
3
|
+
module Lookout::Rack::Test::RSpec
|
4
|
+
class FakeRequest
|
5
|
+
attr_accessor :session, :env, :request
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@session = {}
|
9
|
+
@env = {}
|
10
|
+
@request = Object.new
|
11
|
+
@request.stub(:path_info).and_return('')
|
12
|
+
end
|
13
|
+
|
14
|
+
def redirect(path, params={}); end # So we can catch calls to the redirect method
|
15
|
+
|
16
|
+
def halt(status, error_string); end
|
17
|
+
|
18
|
+
def to(url); url; end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
|
3
|
+
module Lookout::Rack::Test::RSpec
|
4
|
+
module Models
|
5
|
+
shared_examples 'a timestamped model' do
|
6
|
+
it { should respond_to :id }
|
7
|
+
it { should respond_to :created_at }
|
8
|
+
it { should respond_to :updated_at }
|
9
|
+
it { should respond_to :deleted_at }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'lookout/rack/test/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "lookout-rack-test"
|
8
|
+
spec.version = Lookout::Rack::Test::VERSION
|
9
|
+
spec.authors = ["Ian Smith"]
|
10
|
+
spec.email = ["ian.smith@lookout.com"]
|
11
|
+
spec.description = %q{RSpec and Cucumber helpers}
|
12
|
+
spec.summary = %q{}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "sinatra"
|
24
|
+
|
25
|
+
# Required for {{token}} substitutions in Cucumber API scenarios
|
26
|
+
spec.add_dependency 'liquid'
|
27
|
+
spec.add_dependency 'rspec', '~> 2.12'
|
28
|
+
spec.add_dependency 'ci_reporter'
|
29
|
+
spec.add_dependency 'nokogiri'
|
30
|
+
spec.add_dependency 'rack-test'
|
31
|
+
# For freezing time inside of tests
|
32
|
+
spec.add_dependency 'timecop'
|
33
|
+
# Used to assist with scaffolded data and generating random data
|
34
|
+
spec.add_dependency 'factory_girl'
|
35
|
+
spec.add_dependency 'cucumber'
|
36
|
+
|
37
|
+
spec.add_dependency 'capybara', '~> 2.x'
|
38
|
+
spec.add_dependency 'selenium-webdriver', '<= 2.35.1'
|
39
|
+
spec.add_dependency 'sauce-connect'
|
40
|
+
spec.add_dependency 'sauce', '~> 3.0'
|
41
|
+
spec.add_dependency 'sauce-cucumber', '~> 3.0'
|
42
|
+
|
43
|
+
spec.add_dependency 'mercury-messages'
|
44
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'lookout/rack/test/rspec/email_helpers'
|
4
|
+
include Lookout::Rack::Test::RSpec::Emails
|
5
|
+
|
6
|
+
describe 'expect_emails' do
|
7
|
+
let(:expected_email_name) { 'foo' }
|
8
|
+
let(:unexpected_email_name) { 'bar' }
|
9
|
+
|
10
|
+
it 'If I create a Mercury::Message with the expected email_name, it should pass' do
|
11
|
+
expect do
|
12
|
+
expect_emails([expected_email_name]) do
|
13
|
+
Mercury::Messages::SendImmediateBatchEmail.new(:email_name => expected_email_name)
|
14
|
+
end
|
15
|
+
end.not_to raise_error
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'If I create a Mercury::Message with the expected email_name, plus some other email(s), it should fail' do
|
19
|
+
expect do
|
20
|
+
expect_emails([expected_email_name]) do
|
21
|
+
Mercury::Messages::SendImmediateBatchEmail.new(:email_name => expected_email_name)
|
22
|
+
Mercury::Messages::SendImmediateBatchEmail.new(:email_name => unexpected_email_name)
|
23
|
+
end
|
24
|
+
end.to raise_error(ExpectationNotMetError)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'If I create a Mercury::Message with an unexpected email_name, it should fail' do
|
28
|
+
expect do
|
29
|
+
expect_emails([expected_email_name]) do
|
30
|
+
Mercury::Messages::SendImmediateBatchEmail.new(:email_name => unexpected_email_name)
|
31
|
+
end
|
32
|
+
end.to raise_error(ExpectationNotMetError)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'If I do not create any Mercury::Message, it should fail' do
|
36
|
+
expect do
|
37
|
+
expect_emails([expected_email_name]) do
|
38
|
+
end
|
39
|
+
end.to raise_error(ExpectationNotMetError)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Array
|
44
|
+
# Create a hash with a key for each element in the array
|
45
|
+
def to_hash
|
46
|
+
hash = {}
|
47
|
+
self.each {|elt| hash[elt] = nil}
|
48
|
+
|
49
|
+
return hash
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def expect_email_attributes_helper(expected_attrs, actual_attrs)
|
54
|
+
expect_email_attributes(expected_attrs) do
|
55
|
+
Mercury::Messages::SendImmediateBatchEmail.new(:email_name => '',
|
56
|
+
:pieces => [{:attributes => actual_attrs.to_hash}])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'expect_email_attributes' do
|
61
|
+
let(:expected_email_attributes) { ['foo', 'bar'] }
|
62
|
+
let(:unexpected_email_attributes) { ['baz', 'quux'] }
|
63
|
+
|
64
|
+
context 'if I create a Mercury::Message with all of - and only - the expected attributes' do
|
65
|
+
let(:actual_attrs) { expected_email_attributes.to_hash }
|
66
|
+
|
67
|
+
it 'should pass' do
|
68
|
+
expect { expect_email_attributes_helper(expected_email_attributes, actual_attrs) }.not_to raise_error
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'if I create a Mercury::Message without all of the expected attributes' do
|
73
|
+
let(:actual_attrs) { [expected_email_attributes.first].to_hash }
|
74
|
+
|
75
|
+
it 'should fail' do
|
76
|
+
expect { expect_email_attributes_helper(expected_email_attributes, actual_attrs) }.to raise_error(ExpectationNotMetError)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'if I create a Mercury::Message with all of the expected attributes, plus some others' do
|
81
|
+
let(:actual_attrs) { [expected_email_attributes + unexpected_email_attributes].to_hash }
|
82
|
+
|
83
|
+
it 'should fail' do
|
84
|
+
expect { expect_email_attributes_helper(expected_email_attributes, actual_attrs) }.to raise_error(ExpectationNotMetError)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'if I create a Mercury::Message with unexpected attributes' do
|
89
|
+
let(:actual_attrs) { unexpected_email_attributes.to_hash }
|
90
|
+
|
91
|
+
it 'should fail' do
|
92
|
+
expect { expect_email_attributes_helper(expected_email_attributes, actual_attrs) }.to raise_error(ExpectationNotMetError)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'if I do not create a Mercury::Message' do
|
97
|
+
it 'it should fail' do
|
98
|
+
expect do
|
99
|
+
expect_email_attributes(expected_email_attributes) do
|
100
|
+
end
|
101
|
+
end.to raise_error(ExpectationNotMetError)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|