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.
Files changed (43) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +70 -0
  6. data/Rakefile +4 -0
  7. data/cucumber.yml +5 -0
  8. data/examples/test_app.rb +62 -0
  9. data/examples/test_models.rb +15 -0
  10. data/features/general_steps/requests.feature +13 -0
  11. data/features/general_steps/requests_with_json_body.feature +15 -0
  12. data/features/general_steps/requests_with_params.feature +27 -0
  13. data/features/general_steps/response.feature +21 -0
  14. data/features/liquid_templates.feature +44 -0
  15. data/features/not_timefreeze.feature +14 -0
  16. data/features/number_transform.feature +5 -0
  17. data/features/step_definitions/liquid_templates_steps.rb +3 -0
  18. data/features/step_definitions/number_transform_steps.rb +7 -0
  19. data/features/step_definitions/timefreeze_steps.rb +15 -0
  20. data/features/support/env.rb +10 -0
  21. data/features/timefreeze.feature +15 -0
  22. data/lib/lookout/rack/test.rb +8 -0
  23. data/lib/lookout/rack/test/cucumber.rb +32 -0
  24. data/lib/lookout/rack/test/cucumber/before.rb +5 -0
  25. data/lib/lookout/rack/test/cucumber/general_steps.rb +42 -0
  26. data/lib/lookout/rack/test/cucumber/server.rb +11 -0
  27. data/lib/lookout/rack/test/cucumber/transforms.rb +3 -0
  28. data/lib/lookout/rack/test/load_factories.rb +5 -0
  29. data/lib/lookout/rack/test/rake.rb +16 -0
  30. data/lib/lookout/rack/test/rake/cucumber.rake +16 -0
  31. data/lib/lookout/rack/test/rake/rspec.rake +21 -0
  32. data/lib/lookout/rack/test/rspec.rb +52 -0
  33. data/lib/lookout/rack/test/rspec/email_helpers.rb +32 -0
  34. data/lib/lookout/rack/test/rspec/fake_request.rb +20 -0
  35. data/lib/lookout/rack/test/rspec/model_examples.rb +12 -0
  36. data/lib/lookout/rack/test/rspec/route_helper.rb +7 -0
  37. data/lib/lookout/rack/test/version.rb +7 -0
  38. data/lookout-rack-test.gemspec +44 -0
  39. data/spec/email_helpers_spec.rb +104 -0
  40. data/spec/model_examples_spec.rb +51 -0
  41. data/spec/setup_spec.rb +51 -0
  42. data/spec/spec_helper.rb +15 -0
  43. metadata +339 -0
@@ -0,0 +1,8 @@
1
+ require 'lookout/rack/test/version'
2
+
3
+ module Lookout
4
+ module Rack
5
+ module Test
6
+ end
7
+ end
8
+ end
@@ -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,5 @@
1
+ require 'timecop'
2
+
3
+ Before('@timefreeze') do
4
+ Timecop.freeze
5
+ end
@@ -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,11 @@
1
+ require 'rack/test'
2
+
3
+ module Lookout::Rack::Test::Cucumber
4
+ module Server
5
+ def app
6
+ @app ||= $application_class.new if $application_class
7
+ end
8
+ end
9
+ end
10
+
11
+ World(Lookout::Rack::Test::Cucumber)
@@ -0,0 +1,3 @@
1
+ Transform /^(-?\d+)$/ do |number|
2
+ number.to_i
3
+ end
@@ -0,0 +1,5 @@
1
+ unless $factories_loaded
2
+ require 'factory_girl'
3
+ ::FactoryGirl.find_definitions
4
+ $factories_loaded = true
5
+ 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,7 @@
1
+ module Lookout::Rack::Test::RSpec
2
+ module RouteHelper
3
+ def app
4
+ @app ||= $application_class.new if $application_class
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Lookout
2
+ module Rack
3
+ module Test
4
+ VERSION = "1.0.0"
5
+ end
6
+ end
7
+ 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