heracles-wrapper 0.0.1

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 (34) hide show
  1. data/.gitignore +18 -0
  2. data/.rvmrc +55 -0
  3. data/.travis.yml +14 -0
  4. data/Gemfile +6 -0
  5. data/LICENSE.txt +14 -0
  6. data/README.md +74 -0
  7. data/Rakefile +11 -0
  8. data/heracles-wrapper.gemspec +34 -0
  9. data/lib/heracles-wrapper/config.rb +17 -0
  10. data/lib/heracles-wrapper/exceptions.rb +15 -0
  11. data/lib/heracles-wrapper/notification_response.rb +38 -0
  12. data/lib/heracles-wrapper/request/create_job.rb +63 -0
  13. data/lib/heracles-wrapper/request.rb +6 -0
  14. data/lib/heracles-wrapper/request_success.rb +25 -0
  15. data/lib/heracles-wrapper/test_helper.rb +67 -0
  16. data/lib/heracles-wrapper/version.rb +5 -0
  17. data/lib/heracles-wrapper.rb +38 -0
  18. data/lib/rails/generators/heracles/wrapper/install/USAGE +8 -0
  19. data/lib/rails/generators/heracles/wrapper/install/install_generator.rb +42 -0
  20. data/lib/rails/generators/heracles/wrapper/install/templates/config.rb +11 -0
  21. data/lib/rails/generators/heracles/wrapper/notification_response/USAGE +9 -0
  22. data/lib/rails/generators/heracles/wrapper/notification_response/notification_response_generator.rb +21 -0
  23. data/lib/rails/generators/heracles/wrapper/notification_response/templates/notification_response.rb.erb +17 -0
  24. data/lib/rails/generators/heracles/wrapper/notification_response/templates/notification_response_spec.rb.erb +31 -0
  25. data/spec/heracles-wrapper/config_spec.rb +24 -0
  26. data/spec/heracles-wrapper/exceptions_spec.rb +27 -0
  27. data/spec/heracles-wrapper/notification_response_spec.rb +93 -0
  28. data/spec/heracles-wrapper/request/create_job_spec.rb +163 -0
  29. data/spec/heracles-wrapper/request_success_spec.rb +49 -0
  30. data/spec/heracles-wrapper/test_helper_spec.rb +114 -0
  31. data/spec/heracles-wrapper_spec.rb +51 -0
  32. data/spec/rails/generators/heracles/wrapper/install/install_generator_spec.rb +31 -0
  33. data/spec/rails/generators/heracles/wrapper/notification_response/notification_response_generator_spec.rb +44 -0
  34. metadata +221 -0
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ .DS_Store
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/.rvmrc ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
7
+ environment_id="ruby-1.9.3-p286@heracles-wrapper"
8
+
9
+ #
10
+ # Uncomment following line if you want options to be set only for given project.
11
+ #
12
+ # PROJECT_JRUBY_OPTS=( --1.9 )
13
+
14
+ #
15
+ # First we attempt to load the desired environment directly from the environment
16
+ # file. This is very fast and efficient compared to running through the entire
17
+ # CLI and selector. If you want feedback on which environment was used then
18
+ # insert the word 'use' after --create as this triggers verbose mode.
19
+ #
20
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
21
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
22
+ then
23
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
24
+
25
+ if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
26
+ then
27
+ . "${rvm_path:-$HOME/.rvm}/hooks/after_use"
28
+ fi
29
+ else
30
+ # If the environment file has not yet been created, use the RVM CLI to select.
31
+ if ! rvm --create use "$environment_id"
32
+ then
33
+ echo "Failed to create RVM environment '${environment_id}'."
34
+ exit 1
35
+ fi
36
+ fi
37
+
38
+ #
39
+ # If you use an RVM gemset file to install a list of gems (*.gems), you can have
40
+ # it be automatically loaded. Uncomment the following and adjust the filename if
41
+ # necessary.
42
+ #
43
+ # filename=".gems"
44
+ # if [[ -s "$filename" ]]
45
+ # then
46
+ # rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
47
+ # fi
48
+
49
+ # If you use bundler, this might be useful to you:
50
+ if command -v bundle && [[ -s Gemfile ]]
51
+ then
52
+ bundle
53
+ fi
54
+
55
+
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ language: ruby
2
+ script: "bundle exec rake spec"
3
+ rvm:
4
+ - 1.9.3
5
+ - 1.8.7
6
+ gemfile:
7
+ - Gemfile
8
+ notifications:
9
+ email:
10
+ recipients:
11
+ - jfriesen@nd.edu
12
+ branches:
13
+ only:
14
+ - master
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in heracles-wrapper.gemspec
4
+ gemspec
5
+
6
+ gem 'rake'
data/LICENSE.txt ADDED
@@ -0,0 +1,14 @@
1
+ ##########################################################################
2
+ # Copyright 2012 University of Notre Dame
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # Heracles::Wrapper
2
+
3
+ [![Build Status](https://secure.travis-ci.org/ndlib/heracles-wrapper.png)](http://travis-ci.org/ndlib/heracles-wrapper)
4
+
5
+ API Wrapper for [Heracles](https://github.com/ndlib/heracles) workflow manager.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'heracles-wrapper'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install heracles-wrapper
20
+
21
+ Get your Heracles API key
22
+
23
+ Once installed in your application use rails generate:
24
+
25
+ rails generate heracles:wrapper:install -k <API_KEY_FROM_HERACLES>
26
+
27
+ ## Usage
28
+
29
+ Heracles::Wrapper.service(
30
+ :create_job,
31
+ :workflow_name => 'RabbitWarren',
32
+ :parameters => {
33
+ :callback_url => 'http://google.com'
34
+ }
35
+ )
36
+
37
+ ## Test Usage
38
+
39
+ require 'heracles-wrapper/test_helper'
40
+
41
+ describe YourObject do
42
+ include Heracles::Wrapper::TestHelper
43
+ let(:service) {
44
+ Heracles::Wrapper.service(
45
+ :create_job,
46
+ :workflow_name => 'RabbitWarren',
47
+ :parameters => {
48
+ :callback_url => 'http://google.com'
49
+ }
50
+ )
51
+ }
52
+
53
+ it 'should wrap the API with failing calls' do
54
+ with_heracles_service_failure_stub(:create_job, 'Failure') do
55
+ lambda {
56
+ service.call
57
+ }.must_raise(Heracles::Wrapper::RequestFailure, /Failure/)
58
+ end
59
+ end
60
+
61
+ it 'should wrap the API' do
62
+ with_heracles_service_stub(:create_job) do
63
+ service.call.job_id.must_be_kind_of Fixnum
64
+ end
65
+ end
66
+ end
67
+
68
+ ## Contributing
69
+
70
+ 1. Fork it
71
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
72
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
73
+ 4. Push to the branch (`git push origin my-new-feature`)
74
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new('spec') do |t|
6
+ t.libs.push "lib"
7
+ t.test_files = FileList['spec/**/*_spec.rb']
8
+ t.verbose = true
9
+ end
10
+
11
+ task :default => :spec
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'heracles-wrapper/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "heracles-wrapper"
8
+ gem.version = Heracles::Wrapper::VERSION
9
+ gem.authors = [
10
+ "Jeremy Friesen"
11
+ ]
12
+ gem.email = [
13
+ "jeremy.n.friesen@gmail.com"
14
+ ]
15
+ gem.description = %q{API Wrapper for Heracles workflow manager}
16
+ gem.summary = %q{API Wrapper for Heracles workflow manager}
17
+ gem.homepage = "https://github.com/ndlib/heracles-wrapper"
18
+
19
+ gem.files = `git ls-files`.split($/)
20
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
21
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
22
+ gem.require_paths = ["lib"]
23
+
24
+ gem.add_dependency "rest-client"
25
+ gem.add_dependency "morphine"
26
+ gem.add_dependency "json" if RUBY_VERSION =~ /\A1\.8/
27
+ gem.add_dependency "method_decorators"
28
+ gem.add_development_dependency "webmock"
29
+ gem.add_development_dependency "debugger" if RUBY_VERSION !~ /\A1\.8/
30
+ gem.add_development_dependency "minitest"
31
+ gem.add_development_dependency "minitest-matchers"
32
+ gem.add_development_dependency "rails"
33
+
34
+ end
@@ -0,0 +1,17 @@
1
+ module Heracles
2
+ module Wrapper
3
+ HERACLES_BASE_URL = 'https://heracles.library.nd.edu'.freeze
4
+ class Config
5
+ attr_accessor :api_key
6
+ def initialize
7
+ yield(self) if block_given?
8
+ end
9
+
10
+ attr_writer :heracles_base_url
11
+ def heracles_base_url
12
+ @heracles_base_url || Heracles::Wrapper::HERACLES_BASE_URL
13
+ end
14
+ end
15
+ end
16
+ end
17
+
@@ -0,0 +1,15 @@
1
+ module Heracles
2
+ module Wrapper
3
+ class RequestFailure < RuntimeError
4
+ attr_reader :code, :messages, :response
5
+ def initialize(response)
6
+ @code = response.respond_to?(:code) ? response.code : 500
7
+ @messages = response.respond_to?(:body) ? response.body : ''
8
+ @response = response
9
+ super("code: #{@code}")
10
+ end
11
+ end
12
+ class ConfigurationError < RuntimeError
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ require 'method_decorators'
2
+ require 'method_decorators/decorators/precondition'
3
+
4
+ module Heracles
5
+ module Wrapper
6
+ end
7
+ end
8
+
9
+ class Heracles::Wrapper::NotificationResponse
10
+ extend MethodDecorators
11
+ attr_reader(
12
+ :job_id,
13
+ :job_status,
14
+ :notification_payload,
15
+ :one_time_notification_key
16
+ )
17
+ +Precondition.new { |params|
18
+ params[:job_id] &&
19
+ params[:job_status] &&
20
+ params[:notification_payload].respond_to?(:to_hash)
21
+ }
22
+ def initialize(params)
23
+ @notification_payload = params.fetch(:notification_payload).to_hash
24
+ @job_id = params.fetch(:job_id).to_i
25
+ @job_status = params.fetch(:job_status).to_sym
26
+ @one_time_notification_key = params.fetch(:one_time_notification_key, nil)
27
+ end
28
+
29
+ def method_missing(method_name, *args, &block)
30
+ super
31
+ rescue NoMethodError
32
+ @notification_payload.send(method_name, *args, &block)
33
+ end
34
+
35
+ def respond_to?(method_name)
36
+ super || @notification_payload.respond_to?(method_name)
37
+ end
38
+ end
@@ -0,0 +1,63 @@
1
+ require 'uri'
2
+ require 'json'
3
+ require 'rest-client'
4
+ require File.expand_path("../exceptions", File.dirname(__FILE__))
5
+ require File.expand_path("../request_success", File.dirname(__FILE__))
6
+
7
+
8
+ module Heracles
9
+ module Wrapper
10
+ module Request
11
+ end
12
+ end
13
+ end
14
+
15
+ class Heracles::Wrapper::Request::CreateJob
16
+ attr_reader(
17
+ :config,
18
+ :workflow_name,
19
+ :parent_job_id,
20
+ :parameters,
21
+ :url
22
+ )
23
+ def initialize(config, options = {})
24
+ @config = config
25
+ @workflow_name = options.fetch(:workflow_name)
26
+ @parent_job_id = options.fetch(:parent_job_id, nil)
27
+ @parameters = options.fetch(:parameters, {})
28
+ @url = URI.parse(File.join(config.heracles_base_url, 'jobs'))
29
+ end
30
+
31
+ def as_json
32
+ {
33
+ :api_key => config.api_key,
34
+ :workflow_name => workflow_name,
35
+ :parameters => parameters
36
+ }.tap {|hash|
37
+ hash[:parent_job_id] = parent_job_id if parent_job_id
38
+ }
39
+ end
40
+
41
+ # Need to accept a self-signed cert.
42
+ # Hits a given URL
43
+ # Syncrhonously waits for response.
44
+ def call
45
+ decorate_response(
46
+ RestClient.post(
47
+ url.to_s,
48
+ as_json,
49
+ {
50
+ :content_type => :json,
51
+ :accept => :json,
52
+ :verify_ssl => OpenSSL::SSL::VERIFY_NONE
53
+ }
54
+ )
55
+ )
56
+ rescue RestClient::Exception => e
57
+ raise Heracles::Wrapper::RequestFailure.new(e.response)
58
+ end
59
+ protected
60
+ def decorate_response(response)
61
+ Heracles::Wrapper::RequestSuccess.new(response)
62
+ end
63
+ end
@@ -0,0 +1,6 @@
1
+ module Heracles
2
+ module Wrapper
3
+ module Request
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,25 @@
1
+ require File.expand_path("exceptions", File.dirname(__FILE__))
2
+ require 'rest-client'
3
+ require 'json'
4
+ require 'delegate'
5
+
6
+ module Heracles
7
+ module Wrapper
8
+ class RequestSuccess < DelegateClass(RestClient::Response)
9
+ attr_reader(
10
+ :job_id,
11
+ :location,
12
+ :messages,
13
+ :code
14
+ )
15
+ def initialize(http_response)
16
+ super(http_response)
17
+ @json = JSON.parse(http_response.body)
18
+ @job_id = @json.fetch('job_id').to_i
19
+ @messages = @json.fetch('messages',[]).to_a
20
+ @location = http_response.headers.fetch(:location)
21
+ @code = http_response.code
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,67 @@
1
+ require File.expand_path("../heracles-wrapper", File.dirname(__FILE__))
2
+ require File.expand_path("exceptions", File.dirname(__FILE__))
3
+ require 'ostruct'
4
+ module Heracles::Wrapper
5
+ module TestHelper
6
+ RESPONSE_JOB_ID = 1234.freeze
7
+ RESPONSE_CODE = 201.freeze
8
+
9
+ def with_heracles_service_failure_stub(service_name, messages = [])
10
+ wrap_service_with_proxy(service_name) do
11
+ Heracles::Wrapper.send(
12
+ "#{service_name}_service=",
13
+ lambda { |config,options|
14
+ OpenStruct.new(
15
+ :config => config,
16
+ :workflow_name => options.fetch(:workflow_name),
17
+ :parent_job_id => options.fetch(:parent_job_id, nil),
18
+ :parameters => options.fetch(:parameters, {})
19
+ ).tap { |obj|
20
+ def obj.call
21
+ raise Heracles::Wrapper::RequestFailure.new(messages)
22
+ end
23
+ }
24
+ }
25
+ )
26
+ yield
27
+ end
28
+ end
29
+ # Presently I'm leaning on the implementation details of :create_job
30
+ # for returning the API.
31
+ def with_heracles_service_stub(service_name, response = {})
32
+ wrap_service_with_proxy(service_name) do |proxy|
33
+
34
+ response[:job_id] ||= RESPONSE_JOB_ID
35
+ response[:location] ||= File.join(
36
+ Heracles::Wrapper.config.heracles_base_url,
37
+ "/jobs/#{response[:job_id]}"
38
+ )
39
+ response[:code] ||= RESPONSE_CODE
40
+ response[:messages] ||= []
41
+
42
+ Heracles::Wrapper.send(
43
+ "#{service_name}_service=",
44
+ lambda { |config,options|
45
+ OpenStruct.new(
46
+ :config => config,
47
+ :workflow_name => options.fetch(:workflow_name),
48
+ :parent_job_id => options.fetch(:parent_job_id, nil),
49
+ :parameters => options.fetch(:parameters, {}),
50
+ :call => OpenStruct.new(response)
51
+ )
52
+ }
53
+ )
54
+ yield
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def wrap_service_with_proxy(service_name)
61
+ old_service = Heracles::Wrapper.send("#{service_name}_service")
62
+ yield
63
+ ensure
64
+ Heracles::Wrapper.send("#{service_name}_service=", old_service)
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,5 @@
1
+ module Heracles
2
+ module Wrapper
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,38 @@
1
+ require File.expand_path("heracles-wrapper/version", File.dirname(__FILE__))
2
+ require File.expand_path("heracles-wrapper/config", File.dirname(__FILE__))
3
+ require File.expand_path("heracles-wrapper/exceptions", File.dirname(__FILE__))
4
+ require File.expand_path("heracles-wrapper/request/create_job", File.dirname(__FILE__))
5
+ require 'morphine'
6
+ module Heracles
7
+ module Wrapper
8
+ module_function
9
+ def configure(&block)
10
+ @config = Config.new(&block)
11
+ end
12
+
13
+ def config
14
+ if @config.nil?
15
+ raise ConfigurationError.new("#{self}.config not set")
16
+ end
17
+ if @config.api_key.nil?
18
+ raise ConfigurationError.new("#{self}.config.api_key is invalid")
19
+ end
20
+ @config
21
+ end
22
+
23
+ def clear_config!
24
+ @config = nil
25
+ end
26
+
27
+ def service(service_name, options = {})
28
+ send("#{service_name}_service").call(config,options)
29
+ end
30
+ class << self
31
+ include Morphine
32
+ private
33
+ register :create_job_service do
34
+ Heracles::Wrapper::Request::CreateJob.method(:new)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Generate the config for Heracles
3
+
4
+ Example:
5
+ rails generate heracles:wrapper:install -k <API_KEY_FOR_PRODUCTION_HERACLES>
6
+
7
+ This will create:
8
+ config/initializers/heracles-wrapper.rb
@@ -0,0 +1,42 @@
1
+ require 'rails/generators'
2
+ module Heracles
3
+ module Wrapper
4
+ class InstallGenerator < Rails::Generators::Base
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ class_option(
8
+ :api_key,
9
+ :aliases => "-k",
10
+ :type => :string,
11
+ :desc => "Your Heracles API key",
12
+ :required => true
13
+ )
14
+
15
+ def install
16
+ ensure_api_key_was_configured
17
+ generate_config
18
+ end
19
+
20
+ private
21
+ def ensure_api_key_was_configured
22
+ if api_key_configured?
23
+ puts "Already configured"
24
+ exit
25
+ end
26
+ end
27
+
28
+ def generate_config
29
+ template 'config.rb', initializer_filename
30
+ end
31
+
32
+ def initializer_filename
33
+ 'config/initializers/heracles-wrapper.rb'
34
+ end
35
+
36
+ def api_key_configured?
37
+ File.exists?(initializer_filename)
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,11 @@
1
+ Heracles::Wrapper.configure do |config|
2
+ if Rails.env.production?
3
+ config.api_key = "<%= options[:api_key] %>"
4
+ elsif Rails.env.preproduction?
5
+ config.api_key = "change-me-as-needed"
6
+ config.heracles_base_url = 'https://heraclespprd.library.nd.edu'
7
+ else
8
+ config.api_key = "change-me-as-needed"
9
+ config.heracles_base_url = 'http://localhost:8765'
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ Description:
2
+ Generate a notification response for Heracles
3
+
4
+ Example:
5
+ rails generate heracles:wrapper:notification_response <NAME>
6
+
7
+ This will create:
8
+ app/models/<NAME>.rb
9
+ spec/models/<NAME>.rb
@@ -0,0 +1,21 @@
1
+ require 'rails/generators'
2
+ module Heracles
3
+ module Wrapper
4
+ class NotificationResponseGenerator < Rails::Generators::NamedBase
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ def create_model
8
+ template(
9
+ 'notification_response.rb.erb',
10
+ File.join('app/models/', "#{file_name}.rb")
11
+ )
12
+ end
13
+ def create_spec
14
+ template(
15
+ 'notification_response_spec.rb.erb',
16
+ File.join('spec/models/',"#{file_name}_spec.rb")
17
+ )
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ require 'heracles/wrapper/notification_response'
2
+ require 'delegate'
3
+
4
+ # Using the DelegateClass inheritance option so that the Preconditions of the
5
+ # base Heracles::Wrapper::NotificationResponse are preserved.
6
+ class <%= class_name %> < DelegateClass(Heracles::Wrapper::NotificationResponse)
7
+ def initialize(params)
8
+ super(Heracles::Wrapper::NotificationResponse.new(params))
9
+
10
+ # The following two lines are logically equivalent
11
+ # @pid = fetch(:pid)
12
+ # @pid = params.fetch(:notification_payload).fetch(:pid)
13
+ #
14
+ # You may also want to define, at the class level the following:
15
+ # attr_reader :pid
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe <%= class_name %> do
4
+ subject { <%= class_name %>.new(params) }
5
+ let(:params) {
6
+ {
7
+ :job_id => '1234',
8
+ :one_time_notification_key => 'abc',
9
+ :job_status => 'ok',
10
+ :notification_payload => expected_notification_payload
11
+ }
12
+ }
13
+ let(:expected_notification_payload) { {:hello => 'world'} }
14
+
15
+ describe 'standard behavior' do
16
+ it 'should have #job_id' do
17
+ subject.job_id.should == params.fetch(:job_id).to_i
18
+ end
19
+ it 'should have #job_status' do
20
+ subject.job_status.should == params.fetch(:job_status).to_sym
21
+ end
22
+ it 'should have #notification_payload' do
23
+ subject.notification_payload.should == params.
24
+ fetch(:notification_payload).to_sym
25
+ end
26
+ it 'should behave as a the :notification_payload hash' do
27
+ subject[:hello].should == params[:notification_payload][:hello]
28
+ subject.fetch(:hello).should == params[:notification_payload][:hello]
29
+ end
30
+ end
31
+ end