alephant-publisher-request 0.0.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9cfd32b39a5fcdd4d15d0d24925f861614a57bde
4
+ data.tar.gz: e8fb3770ab80f2bcd4b8e972909c23d03d20b449
5
+ SHA512:
6
+ metadata.gz: e2576063f21c41344fb0b74bbc32192fa7e6585e5f0a58212bff778c215cfad2da400ccf30f1ab36ae2bfb0617ca5c7e9ea580cd2dc0ce8276f63b5dce299332
7
+ data.tar.gz: 33794b02c484149ac16b821b65b026fd199ab3054d2feb7df3c9928ca442e4c01b86923169cb221297a497aa26d7e2a40e8ebc069931bc490d435adc7f881cca
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .rspec
19
+ .ruby-version
20
+ /config/*.yaml
21
+ /config/*.yml
22
+ /components
23
+ *.swp
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ rvm:
3
+ - "jruby"
4
+ script:
5
+ - bundle exec rake all
6
+ notifications:
7
+ email:
8
+ recipients:
9
+ - stevenmajack@gmail.com
10
+ - mark.mxdc@gmail.com
11
+ on_failure: change
12
+ on_success: never
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in alephant-publishing.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,10 @@
1
+ guard 'rake', :task => 'spec' do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/.+\.rb$})
4
+ watch('spec/spec_helper.rb')
5
+ watch('spec/fixtures/.+')
6
+ end
7
+
8
+ guard 'rake', :task => 'integration' do
9
+ watch(%r{^spec/integration/.+_spec\.rb$})
10
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 BBC News
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,190 @@
1
+ # Alephant::Publisher::Request
2
+
3
+ Dynamic publishing based on data from an API.
4
+
5
+ [![Build Status](https://travis-ci.org/BBC-News/alephant-publisher-request.png?branch=master)](https://travis-ci.org/BBC-News/alephant-publisher-request) [![Dependency Status](https://gemnasium.com/BBC-News/alephant-publisher-request.png)](https://gemnasium.com/BBC-News/alephant-publisher-request) [![Gem Version](https://badge.fury.io/rb/alephant-publisher-request.png)](http://badge.fury.io/rb/alephant-publisher-request)
6
+
7
+ ## Dependencies
8
+
9
+ - JRuby 1.7.8
10
+
11
+ ## Migrating from [Alephant::Publisher](https://github.com/BBC-News/alephant-publisher)
12
+
13
+ 1. Add the new gem in your Gemfile (`gem 'alephant-publisher-request'`).
14
+ 2. Run `bundle install`.
15
+ 3. Require the new gem in your app (`require 'alephant/publisher/queue'`).
16
+ 4. Note that the namespace has changed from `Alephant::Publisher` to `Alephant::Publisher::Request`.
17
+
18
+ ## Installation
19
+
20
+ Add this line to your application's Gemfile:
21
+
22
+ gem 'alephant-publisher-request'
23
+
24
+ And then execute:
25
+
26
+ $ bundle
27
+
28
+ Or install it yourself as:
29
+
30
+ $ gem install alephant-publisher-request
31
+
32
+ ## Setup
33
+
34
+ You need to run the gem as a rack application, and pass it the nessasary dependencies. Below is a simple example of the minimum needed to run the server:
35
+
36
+ ### Folder structure
37
+
38
+ ```bash
39
+ src
40
+ ├── components
41
+ │ ├── my_test_component
42
+ │ │ ├── fixtures
43
+ │ │ │ ├── responsive.json
44
+ │ │ ├── templates
45
+ │ │ │ ├── my_test_component.mustache
46
+ │ │ ├── models
47
+ │ │ │ ├── my_test_component.rb
48
+ │ │ ├── mapper.rb
49
+ ```
50
+
51
+ #### Model example
52
+
53
+ The model must extend either the JSON or HTML base from the [alephant-renderer](https://www.github.com/BBC-News/alephant-renderer) `Alephant::Renderer::Views::Html` or `Alephant::Renderer::Views::Json`.
54
+
55
+ ```ruby
56
+ require 'alephant/renderer/views/html'
57
+
58
+ module SomeNameSpace
59
+ class MyTestComponent Alephant::Renderer::Views::Html
60
+
61
+ def some_method
62
+ @body.some_method
63
+ end
64
+
65
+ end
66
+ end
67
+ ```
68
+
69
+ #### Data mapper
70
+
71
+ When getting data from an API, we use data mappers that give us access to the query string parameters allowing us to construct the correct API path.
72
+
73
+ An example of a mapper for an example component would be:
74
+
75
+ > components/my_test_component/mapper.rb
76
+
77
+ ```ruby
78
+ class MyTestComponentMapper < Alephant::Publisher::Request::DataMapper
79
+ def data
80
+ #we have a variable 'context' available that gives us access to the query string params passed to the request.
81
+ #There's a 'get' method available that is passed the constructed API uri and will return the parsed JSON data.
82
+ get "/some/endpoint/#{context['qs_param']}"
83
+
84
+ end
85
+ end
86
+ ```
87
+
88
+ ### Application
89
+
90
+ > config.ru
91
+
92
+ ```ruby
93
+ require 'lib/application'
94
+ run Application.create
95
+ ```
96
+
97
+ > lib/application.rb
98
+
99
+ ```ruby
100
+ module Application
101
+
102
+ def self.create
103
+ Alephant::Publisher::Request.create(processor, data_mapper_factory)
104
+ end
105
+
106
+ def self.processor
107
+ Alephant::Publisher::Request::Processor.new(base_path)
108
+ end
109
+
110
+ def self.base_path
111
+ File.absolute_path(File.join(File.dirname(__FILE__), '..', 'components'))
112
+ end
113
+
114
+ def self.data_mapper_factory
115
+ Alephant::Publisher::Request::DataMapperFactory.new(connection, base_path)
116
+ end
117
+
118
+ def self.connection
119
+ Faraday.new(:url => 'http://www.some-api-endpoint.com')
120
+ end
121
+
122
+ end
123
+ ```
124
+
125
+ ## Usage
126
+
127
+ The server is a simple rack server, so you just need to run:
128
+
129
+ ```bash
130
+ $: rackup
131
+ ```
132
+
133
+ in the `src` directory where the `config.ru` file is.
134
+
135
+ To view components, use the name (the name of the component in the components folder) and any params in the browser:
136
+
137
+ ```bash
138
+ curl http://localhost:9292/my_test_component?some=param
139
+ ```
140
+
141
+ ## Preview Server
142
+
143
+ `alephant preview`
144
+
145
+ The included preview server allows you to see the html generated by your
146
+ templates, both standalone and in the context of a page.
147
+
148
+ **Standalone**
149
+
150
+ `/component/:id/?:fixture?`
151
+
152
+ ### Full page preview
153
+
154
+ When viewing the component in the context of a page, you'll need to retrieve a
155
+ mustache template to provide the page context.
156
+
157
+ When performing an update a regex is applied to replace the static hostnames in
158
+ the retrieved html.
159
+
160
+ **Environment Variables**
161
+
162
+ ```sh
163
+ STATIC_HOST_REGEX="static.(sandbox.dev|int|test|stage|live).yourapp(i)?.com\/"
164
+ PREVIEW_TEMPLATE_URL="http://yourapp.com/template"
165
+ ```
166
+
167
+ **Example Remote Template**
168
+
169
+ `id` is the component/folder name
170
+
171
+ `template` is the mustache template file name
172
+
173
+ `location_in_page` should be something like (for example) `page_head` (specified within a `preview.mustache` file that the consuming application needs to create).
174
+
175
+ - `http://localhost:4567/component/id/template`
176
+ - `http://localhost:4567/preview/id/template/location_in_page`
177
+
178
+ `alephant update`
179
+
180
+ **In page**
181
+
182
+ `/preview/:id/:region/?:fixture?`
183
+
184
+ ## Contributing
185
+
186
+ 1. [Fork it!](http://github.com/BBC-News/alephant-publisher-request/fork)
187
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
188
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
189
+ 4. Push to the branch (`git push origin my-new-feature`)
190
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
2
+
3
+ require 'rspec/core/rake_task'
4
+ require 'rake/rspec'
5
+ require 'bundler/gem_tasks'
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'alephant/publisher/request/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "alephant-publisher-request"
8
+ spec.version = Alephant::Publisher::Request::VERSION
9
+ spec.authors = ["Integralist"]
10
+ spec.email = ["mark.mcdx@gmail.com"]
11
+ spec.summary = "..."
12
+ spec.description = "..."
13
+ spec.homepage = "https://github.com/BBC-News/alephant-publisher-request"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
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.5"
22
+ spec.add_development_dependency "rspec"
23
+ spec.add_development_dependency "rspec-nc"
24
+ spec.add_development_dependency "guard"
25
+ spec.add_development_dependency "guard-rake"
26
+ spec.add_development_dependency "pry"
27
+ spec.add_development_dependency "rack-test"
28
+ spec.add_development_dependency "spurious-ruby-awssdk-helper"
29
+ spec.add_development_dependency "rake-rspec"
30
+
31
+ spec.add_runtime_dependency 'rack'
32
+ spec.add_runtime_dependency 'rake'
33
+ spec.add_runtime_dependency 'faraday'
34
+ spec.add_runtime_dependency 'aws-sdk', '~> 1.0'
35
+ spec.add_runtime_dependency 'mustache', '>= 0.99.5'
36
+ spec.add_runtime_dependency 'alephant-logger'
37
+ spec.add_runtime_dependency 'alephant-renderer'
38
+ end
@@ -0,0 +1,75 @@
1
+ require 'alephant/logger'
2
+ require 'alephant/publisher/request/version'
3
+ require 'alephant/publisher/request/processor'
4
+ require 'rack/request'
5
+ require 'rack/response'
6
+ require 'alephant/publisher/request/error'
7
+
8
+ module Alephant
9
+ module Publisher
10
+ module Request
11
+ include Logger
12
+
13
+ def self.create(processor, data_mapper_factory, opts = {})
14
+ Request.new(processor, data_mapper_factory, opts)
15
+ end
16
+
17
+ class Request
18
+ attr_reader :processor, :data_mapper_factory, :opts
19
+
20
+ DEFAULT_CONTENT_TYPE = { "Content-Type" => "text/html" }
21
+
22
+ def initialize(processor, data_mapper_factory, opts)
23
+ @processor = processor
24
+ @data_mapper_factory = data_mapper_factory
25
+ @opts = opts
26
+ end
27
+
28
+ def call(env)
29
+ req = Rack::Request.new(env)
30
+ response = Rack::Response.new("<h1>Not Found</h1>", 404, DEFAULT_CONTENT_TYPE)
31
+
32
+ case req.path_info
33
+ when /status$/
34
+ response = Rack::Response.new('', 204, DEFAULT_CONTENT_TYPE)
35
+ when /component\/(?<id>[^\/]+)$/
36
+ response = Rack::Response.new(
37
+ template_data($~['id'], req.params),
38
+ 200,
39
+ DEFAULT_CONTENT_TYPE
40
+ )
41
+ end
42
+
43
+ response.finish
44
+ rescue ApiError, ConnectionFailed => e
45
+ error_response(e, 502)
46
+ rescue InvalidComponent => e
47
+ error_response(e, 404)
48
+ rescue Exception => e
49
+ error_response e
50
+ end
51
+
52
+ protected
53
+
54
+ def render_component(component_id, params)
55
+ Rack::Response.new(
56
+ template_data(component_id, params),
57
+ 200,
58
+ { "Content-Type" => "text/html" }
59
+ )
60
+ end
61
+
62
+ def template_data(component_id, params)
63
+ mapper = data_mapper_factory.create(component_id, params)
64
+ processor.consume(mapper.data, component_id)
65
+ end
66
+
67
+ def error_response(e = '', code = 500)
68
+ message = opts.fetch(:debug, false) ? e.message : ''
69
+ Rack::Response.new(message, code, DEFAULT_CONTENT_TYPE).finish
70
+ end
71
+
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,35 @@
1
+ require 'json'
2
+
3
+ module Alephant
4
+ module Publisher
5
+ module Request
6
+ class DataMapper
7
+ attr_reader :connection, :context
8
+
9
+ def initialize(connection, context = {})
10
+ @connection = connection
11
+ @context = context
12
+ end
13
+
14
+ def data
15
+ raise NotImplementedError
16
+ end
17
+
18
+ protected
19
+
20
+ def get(uri)
21
+ response = connection.get(uri)
22
+ raise InvalidApiResponse, "Status: #{response.status}" unless response.status == 200
23
+ JSON::parse(response.body, :symbolize_names => true)
24
+ rescue Faraday::ConnectionFailed
25
+ raise ConnectionFailed
26
+ rescue JSON::ParserError
27
+ raise InvalidApiResponse, "JSON parsing error: #{response.body}"
28
+ rescue StandardError => e
29
+ raise ApiError, e.message
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,43 @@
1
+ module Alephant
2
+ module Publisher
3
+ module Request
4
+ class DataMapperFactory
5
+ attr_reader :connection, :base_path
6
+
7
+ def initialize(connection, base_path)
8
+ @connection = connection
9
+ @base_path = base_path
10
+ raise InvalidComponentBasePath, base_path unless File.directory? base_path
11
+ end
12
+
13
+ def create(component_id, context = {})
14
+ require base_path_for component_id
15
+
16
+ klass = mapper_class_for(component_id)
17
+ klass.new(connection, context)
18
+ rescue LoadError
19
+ raise InvalidComponentName, "Invalid component name: #{component_id}"
20
+ rescue NameError
21
+ raise InvalidComponentClassName, "Invalid class name #{klass}"
22
+ rescue
23
+ raise InvalidComponent, "Name: #{component_id}, Class: #{klass}"
24
+ end
25
+
26
+ protected
27
+
28
+ def base_path_for(component_id)
29
+ "#{base_path}/#{component_id}/mapper"
30
+ end
31
+
32
+ def camalize(snake_case)
33
+ "#{snake_case.split('_').collect(&:capitalize).join}"
34
+ end
35
+
36
+ def mapper_class_for(component_id)
37
+ Object.const_get("#{camalize component_id}Mapper")
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,15 @@
1
+ module Alephant
2
+ module Publisher
3
+ module Request
4
+ class Error < StandardError; end
5
+ class ConnectionFailed < Error; end
6
+ class InvalidComponent < Error; end
7
+ class ApiError < Error; end
8
+ class InvalidApiResponse < ApiError; end
9
+ class InvalidComponentBasePath < InvalidComponent; end
10
+ class InvalidComponentName < InvalidComponent; end
11
+ class InvalidComponentClassName < InvalidComponent; end
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,34 @@
1
+ require 'alephant/publisher/request/processor/base'
2
+
3
+ module Alephant
4
+ module Publisher
5
+ module Request
6
+ class Processor < BaseProcessor
7
+ attr_reader :base_path
8
+
9
+ def initialize(base_path)
10
+ @base_path = base_path
11
+ end
12
+
13
+ def consume(data, component)
14
+ config = config_for component
15
+ renderer_for(config, data).views[component].render
16
+ end
17
+
18
+ def renderer_for(config, data)
19
+ Alephant::Renderer.create(config, data)
20
+ end
21
+
22
+ protected
23
+
24
+ def config_for(component)
25
+ {
26
+ :renderer_id => component,
27
+ :view_path => base_path
28
+ }
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,11 @@
1
+ module Alephant
2
+ module Publisher
3
+ module Request
4
+ class BaseProcessor
5
+ def consume(data)
6
+ raise NotImplementedError.new("You must implement the #consume(data) method")
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ module Alephant
2
+ module Publisher
3
+ module Request
4
+ VERSION = "0.0.2"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Alephant::Publisher::Request::DataMapperFactory do
4
+ let (:connection) { instance_double(Faraday::Connection) }
5
+ let (:base_path) { File.join(File.dirname(__FILE__), 'fixtures', 'components') }
6
+
7
+ subject { described_class.new(connection, base_path) }
8
+
9
+ describe ".create" do
10
+ let (:context) do
11
+ {
12
+ :foo => :bar
13
+ }
14
+ end
15
+
16
+ context "using valid parameters" do
17
+ let (:component_id) { 'foo' }
18
+ let (:expected) { FooMapper }
19
+
20
+ specify { expect(subject.create(component_id, context)).to be_a expected }
21
+ end
22
+
23
+ context "using invalid path" do
24
+ let (:base_path) { File.join(File.dirname(__FILE__), 'non_existent_path') }
25
+ let (:expected_exception) { Alephant::Publisher::Request::InvalidComponentBasePath }
26
+
27
+ specify { expect{ subject.create(component_id, context) }.to raise_error expected_exception }
28
+ end
29
+
30
+ context "using invalid component name" do
31
+ let (:component_id) { 'bar' }
32
+ let (:expected_exception) { Alephant::Publisher::Request::InvalidComponentName }
33
+
34
+ specify { expect{ subject.create(component_id, context) }.to raise_error expected_exception }
35
+ end
36
+
37
+ context "using invalid class name" do
38
+ let (:component_id) { 'invalid' }
39
+ let (:expected_exception) { Alephant::Publisher::Request::InvalidComponentClassName }
40
+
41
+ specify { expect{ subject.create(component_id, context) }.to raise_error expected_exception }
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,41 @@
1
+ require "spec_helper"
2
+
3
+ describe FooMapper do
4
+ let (:connection) { instance_double(Faraday::Connection, :get => nil) }
5
+ let (:context) do
6
+ {
7
+ :foo => :bar
8
+ }
9
+ end
10
+
11
+ subject { described_class.new(connection, context) }
12
+
13
+ describe "#data" do
14
+ let (:expected_raw_data) do
15
+ {
16
+ :some => 'data'
17
+ }
18
+ end
19
+ let (:expected_data) { JSON::generate(expected_raw_data, :symbolize_names => true) }
20
+ let (:expected_response) { instance_double(Faraday::Response, :body => expected_data, :status => 200) }
21
+
22
+ context "with a valid endpoint" do
23
+ before(:each) do
24
+ allow(connection).to receive(:get).with("/some/test/endpoint/#{context.values[0]}").and_return(expected_response)
25
+ end
26
+
27
+ specify { expect(subject.data).to eq expected_raw_data }
28
+ end
29
+
30
+ context "invalid hostname" do
31
+ let (:expected_exception) { Alephant::Publisher::Request::ConnectionFailed }
32
+ let (:faraday_exception) { Faraday::ConnectionFailed.new(StandardError) }
33
+
34
+ before(:each) do
35
+ allow(connection).to receive(:get).and_raise(faraday_exception)
36
+ end
37
+
38
+ specify { expect{ subject.data }.to raise_error expected_exception }
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,6 @@
1
+ class FooMapper < Alephant::Publisher::Request::DataMapper
2
+
3
+ def data
4
+ get "/some/test/endpoint/#{context[:foo]}"
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ require 'alephant/renderer/views/html'
2
+
3
+ module MyApp
4
+ class Foo < Alephant::Renderer::Views::Html
5
+ def content
6
+ @data[:content]
7
+ end
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ {{content}}
@@ -0,0 +1,4 @@
1
+ class SomInvalidNameMapper < Alephant::Publisher::Request::DataMapper
2
+
3
+ def data; end
4
+ end
@@ -0,0 +1,62 @@
1
+ require_relative "./spec_helper"
2
+
3
+ describe Alephant::Publisher::Request do
4
+ include Rack::Test::Methods
5
+ let (:response) { instance_double(Faraday::Response, :status => 200, :body => nil) }
6
+ let (:base_path) { File.join(File.dirname(__FILE__), '..', 'fixtures', 'components') }
7
+ let (:processor) { Alephant::Publisher::Request::Processor.new(base_path) }
8
+ let (:connection) { instance_double(Faraday::Connection, :get => response) }
9
+ let (:data_mapper_factory) { Alephant::Publisher::Request::DataMapperFactory.new(connection, base_path) }
10
+ let (:app) { subject.create(processor, data_mapper_factory, { :debug => true }) }
11
+
12
+ describe "status endpoint (/status)" do
13
+ before(:each) do
14
+ get "/status"
15
+ end
16
+
17
+ context "status code" do
18
+ specify { expect(last_response.status).to eq 204 }
19
+ end
20
+ end
21
+
22
+ describe "component endpoint (/component/{component_id}?foo=bar)" do
23
+ let (:component_id) { "foo" }
24
+
25
+ describe "content" do
26
+
27
+ context "with a valid component id" do
28
+ let (:api_response) { "{\"content\":\"#{component_id}\"}" }
29
+ before(:each) do
30
+ allow(response).to receive(:body).and_return(api_response)
31
+ get "/component/#{component_id}"
32
+ end
33
+
34
+ specify { expect(last_response.body.chomp).to eq component_id }
35
+ end
36
+
37
+ end
38
+
39
+ describe "status code" do
40
+
41
+ context "with an invalid component id" do
42
+ let (:component_id) { "foo_invalid" }
43
+ before(:each) do
44
+ get "/component/#{component_id}"
45
+ end
46
+
47
+ specify { expect(last_response.status).to eq 404 }
48
+ end
49
+
50
+ context "with an invalid API endpoint" do
51
+ let (:expected_exception) { Alephant::Publisher::Request::InvalidApiResponse }
52
+ before(:each) do
53
+ allow(connection).to receive(:get).and_raise expected_exception
54
+ get "/component/#{component_id}"
55
+ end
56
+
57
+ specify { expect(last_response.status).to eq 502 }
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,5 @@
1
+ ENV["RACK_ENV"] = "test"
2
+
3
+ require_relative '../spec_helper'
4
+ require 'spurious/ruby/awssdk/helper'
5
+ require "rack/test"
@@ -0,0 +1,19 @@
1
+ require "spec_helper"
2
+
3
+ describe Alephant::Publisher::Request::DataMapper do
4
+ let (:context) { { :key => :value } }
5
+ let (:connection) { instance_double(Faraday) }
6
+
7
+ subject { Alephant::Publisher::Request::DataMapper.new(connection, context) }
8
+
9
+ describe ".new" do
10
+ specify { expect(subject).to be_a Alephant::Publisher::Request::DataMapper }
11
+ end
12
+
13
+ describe "#data" do
14
+ context "not overridden" do
15
+ specify { expect { subject.data } .to raise_error NotImplementedError }
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,25 @@
1
+ require "spec_helper"
2
+
3
+ describe Alephant::Publisher::Request::Processor do
4
+ let (:base_path) { File.join(File.dirname(__FILE__), 'fixtures', 'components') }
5
+ subject { described_class.new(base_path) }
6
+
7
+ describe ".new" do
8
+ specify { expect(subject).to be_a described_class }
9
+ end
10
+
11
+ describe "#consume" do
12
+ let (:data) do
13
+ {
14
+ :content => "Foo Bar"
15
+ }
16
+ end
17
+
18
+ context "using valid data" do
19
+ let (:component) { "foo" }
20
+
21
+ specify { expect(subject.consume(data, component)).to eq "#{data.values.first}\n" }
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ require "spec_helper"
2
+
3
+ describe Alephant::Publisher::Request do
4
+ let (:processor) { instance_double(Alephant::Publisher::Request::Processor, :consume => nil) }
5
+ let (:data_mapper_factory) { instance_double(Alephant::Publisher::Request::DataMapperFactory, :create => nil) }
6
+
7
+ describe ".create" do
8
+ context "Using valid params" do
9
+ let (:expected) { Alephant::Publisher::Request::Request }
10
+
11
+ specify { expect(subject.create(processor, data_mapper_factory)).to be_a expected }
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,11 @@
1
+ require 'pry'
2
+
3
+ require 'aws-sdk'
4
+ require 'faraday'
5
+ require 'alephant/renderer'
6
+ require 'alephant/publisher/request'
7
+ require 'alephant/publisher/request/error'
8
+ require 'alephant/publisher/request/data_mapper'
9
+ require 'alephant/publisher/request/data_mapper_factory'
10
+
11
+ require_relative './fixtures/components/foo/mapper'
metadata ADDED
@@ -0,0 +1,307 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: alephant-publisher-request
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Integralist
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec-nc
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard-rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rack-test
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: spurious-ruby-awssdk-helper
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rake-rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rack
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rake
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - '>='
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: faraday
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - '>='
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: aws-sdk
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ~>
186
+ - !ruby/object:Gem::Version
187
+ version: '1.0'
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ~>
193
+ - !ruby/object:Gem::Version
194
+ version: '1.0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: mustache
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - '>='
200
+ - !ruby/object:Gem::Version
201
+ version: 0.99.5
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - '>='
207
+ - !ruby/object:Gem::Version
208
+ version: 0.99.5
209
+ - !ruby/object:Gem::Dependency
210
+ name: alephant-logger
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - '>='
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ type: :runtime
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - '>='
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: alephant-renderer
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - '>='
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ type: :runtime
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - '>='
235
+ - !ruby/object:Gem::Version
236
+ version: '0'
237
+ description: '...'
238
+ email:
239
+ - mark.mcdx@gmail.com
240
+ executables: []
241
+ extensions: []
242
+ extra_rdoc_files: []
243
+ files:
244
+ - .gitignore
245
+ - .travis.yml
246
+ - Gemfile
247
+ - Guardfile
248
+ - LICENSE.txt
249
+ - README.md
250
+ - Rakefile
251
+ - alephant-publisher-request.gemspec
252
+ - lib/alephant/publisher/request.rb
253
+ - lib/alephant/publisher/request/data_mapper.rb
254
+ - lib/alephant/publisher/request/data_mapper_factory.rb
255
+ - lib/alephant/publisher/request/error.rb
256
+ - lib/alephant/publisher/request/processor.rb
257
+ - lib/alephant/publisher/request/processor/base.rb
258
+ - lib/alephant/publisher/request/version.rb
259
+ - spec/data_mapper_factory_spec.rb
260
+ - spec/data_mapper_spec.rb
261
+ - spec/fixtures/components/foo/mapper.rb
262
+ - spec/fixtures/components/foo/models/foo.rb
263
+ - spec/fixtures/components/foo/templates/foo.mustache
264
+ - spec/fixtures/components/invalid/mapper.rb
265
+ - spec/integration/rack_server_spec.rb
266
+ - spec/integration/spec_helper.rb
267
+ - spec/not_implemented_mapper_spec.rb
268
+ - spec/processor_spec.rb
269
+ - spec/request_spec.rb
270
+ - spec/spec_helper.rb
271
+ homepage: https://github.com/BBC-News/alephant-publisher-request
272
+ licenses:
273
+ - MIT
274
+ metadata: {}
275
+ post_install_message:
276
+ rdoc_options: []
277
+ require_paths:
278
+ - lib
279
+ required_ruby_version: !ruby/object:Gem::Requirement
280
+ requirements:
281
+ - - '>='
282
+ - !ruby/object:Gem::Version
283
+ version: '0'
284
+ required_rubygems_version: !ruby/object:Gem::Requirement
285
+ requirements:
286
+ - - '>='
287
+ - !ruby/object:Gem::Version
288
+ version: '0'
289
+ requirements: []
290
+ rubyforge_project:
291
+ rubygems_version: 2.2.2
292
+ signing_key:
293
+ specification_version: 4
294
+ summary: '...'
295
+ test_files:
296
+ - spec/data_mapper_factory_spec.rb
297
+ - spec/data_mapper_spec.rb
298
+ - spec/fixtures/components/foo/mapper.rb
299
+ - spec/fixtures/components/foo/models/foo.rb
300
+ - spec/fixtures/components/foo/templates/foo.mustache
301
+ - spec/fixtures/components/invalid/mapper.rb
302
+ - spec/integration/rack_server_spec.rb
303
+ - spec/integration/spec_helper.rb
304
+ - spec/not_implemented_mapper_spec.rb
305
+ - spec/processor_spec.rb
306
+ - spec/request_spec.rb
307
+ - spec/spec_helper.rb