alephant-broker 1.2.1 → 1.3.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.
- checksums.yaml +4 -4
- data/Rakefile +1 -2
- data/alephant-broker.gemspec +2 -2
- data/lib/alephant/broker.rb +11 -11
- data/lib/alephant/broker/component.rb +20 -67
- data/lib/alephant/broker/component_factory.rb +30 -0
- data/lib/alephant/broker/component_meta.rb +51 -0
- data/lib/alephant/broker/error_component.rb +42 -0
- data/lib/alephant/broker/errors/content_not_found.rb +7 -0
- data/lib/alephant/broker/errors/invalid_cache_key.rb +1 -3
- data/lib/alephant/broker/load_strategy/s3.rb +88 -0
- data/lib/alephant/broker/request/asset.rb +2 -3
- data/lib/alephant/broker/request/batch.rb +4 -5
- data/lib/alephant/broker/request/factory.rb +23 -18
- data/lib/alephant/broker/request/handler.rb +5 -10
- data/lib/alephant/broker/response/asset.rb +17 -10
- data/lib/alephant/broker/response/base.rb +5 -53
- data/lib/alephant/broker/response/batch.rb +12 -9
- data/lib/alephant/broker/response/factory.rb +4 -0
- data/lib/alephant/broker/version.rb +1 -1
- data/spec/fixtures/json/batch.json +1 -0
- data/spec/fixtures/json/batch_compiled.json +1 -0
- data/spec/integration/spec_helper.rb +1 -0
- data/spec/rack_spec.rb +97 -96
- data/spec/spec_helper.rb +4 -0
- metadata +57 -46
| @@ -1,18 +1,18 @@ | |
| 1 1 | 
             
            require 'alephant/logger'
         | 
| 2 2 | 
             
            require 'alephant/broker/component'
         | 
| 3 3 |  | 
| 4 | 
            -
             | 
| 5 4 | 
             
            module Alephant
         | 
| 6 5 | 
             
              module Broker
         | 
| 7 6 | 
             
                module Request
         | 
| 8 7 | 
             
                  class Batch
         | 
| 9 8 | 
             
                    include Logger
         | 
| 10 9 |  | 
| 11 | 
            -
                    attr_reader :batch_id, :components
         | 
| 10 | 
            +
                    attr_reader :batch_id, :components, :load_strategy
         | 
| 12 11 |  | 
| 13 | 
            -
                    def initialize(env)
         | 
| 12 | 
            +
                    def initialize(component_factory, env)
         | 
| 14 13 | 
             
                      logger.debug("Request::Batch#initialize(#{env.settings})")
         | 
| 15 14 |  | 
| 15 | 
            +
                      @component_factory = component_factory
         | 
| 16 16 | 
             
                      @batch_id   = env.data['batch_id']
         | 
| 17 17 | 
             
                      @components = components_for env
         | 
| 18 18 |  | 
| @@ -23,14 +23,13 @@ module Alephant | |
| 23 23 |  | 
| 24 24 | 
             
                    def components_for(env)
         | 
| 25 25 | 
             
                      env.data['components'].map do |c|
         | 
| 26 | 
            -
                         | 
| 26 | 
            +
                        @component_factory.create(
         | 
| 27 27 | 
             
                          c['component'],
         | 
| 28 28 | 
             
                          batch_id,
         | 
| 29 29 | 
             
                          c['options']
         | 
| 30 30 | 
             
                        )
         | 
| 31 31 | 
             
                      end
         | 
| 32 32 | 
             
                    end
         | 
| 33 | 
            -
             | 
| 34 33 | 
             
                  end
         | 
| 35 34 | 
             
                end
         | 
| 36 35 | 
             
              end
         | 
| @@ -1,26 +1,31 @@ | |
| 1 1 | 
             
            require 'alephant/broker/request'
         | 
| 2 | 
            +
            require 'alephant/broker/component_factory'
         | 
| 2 3 |  | 
| 3 | 
            -
            module Alephant | 
| 4 | 
            -
               | 
| 4 | 
            +
            module Alephant
         | 
| 5 | 
            +
              module Broker
         | 
| 6 | 
            +
                module Request
         | 
| 7 | 
            +
                  class Factory
         | 
| 8 | 
            +
                    def self.request_type_from(env)
         | 
| 9 | 
            +
                      env.path.split('/')[1]
         | 
| 10 | 
            +
                    end
         | 
| 5 11 |  | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
                end
         | 
| 12 | 
            +
                    def self.request_for(load_strategy, env)
         | 
| 13 | 
            +
                      component_factory = ComponentFactory.new load_strategy
         | 
| 9 14 |  | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 15 | 
            +
                      case request_type_from(env)
         | 
| 16 | 
            +
                      when 'multi'
         | 
| 17 | 
            +
                        Multi.new(env)
         | 
| 18 | 
            +
                      when 'component'
         | 
| 19 | 
            +
                        Asset.new(component_factory, env)
         | 
| 20 | 
            +
                      when 'components'
         | 
| 21 | 
            +
                        Batch.new(component_factory, env)
         | 
| 22 | 
            +
                      when 'status'
         | 
| 23 | 
            +
                        Status.new
         | 
| 24 | 
            +
                      else
         | 
| 25 | 
            +
                        NotFound.new
         | 
| 26 | 
            +
                      end
         | 
| 27 | 
            +
                    end
         | 
| 22 28 | 
             
                  end
         | 
| 23 29 | 
             
                end
         | 
| 24 30 | 
             
              end
         | 
| 25 31 | 
             
            end
         | 
| 26 | 
            -
             | 
| @@ -4,6 +4,7 @@ require 'alephant/broker/request' | |
| 4 4 | 
             
            require 'alephant/broker/response'
         | 
| 5 5 | 
             
            require 'alephant/broker/request/factory'
         | 
| 6 6 | 
             
            require 'alephant/broker/response/factory'
         | 
| 7 | 
            +
            require 'alephant/broker/errors/content_not_found'
         | 
| 7 8 |  | 
| 8 9 | 
             
            module Alephant
         | 
| 9 10 | 
             
              module Broker
         | 
| @@ -11,23 +12,17 @@ module Alephant | |
| 11 12 | 
             
                  class Handler
         | 
| 12 13 | 
             
                    extend Logger
         | 
| 13 14 |  | 
| 14 | 
            -
                    def self.request_for(env)
         | 
| 15 | 
            -
                      Request::Factory.request_for env
         | 
| 15 | 
            +
                    def self.request_for(load_strategy, env)
         | 
| 16 | 
            +
                      Request::Factory.request_for(load_strategy, env)
         | 
| 16 17 | 
             
                    end
         | 
| 17 18 |  | 
| 18 19 | 
             
                    def self.response_for(request)
         | 
| 19 20 | 
             
                      Response::Factory.response_for request
         | 
| 20 21 | 
             
                    end
         | 
| 21 22 |  | 
| 22 | 
            -
                    def self.process(env)
         | 
| 23 | 
            -
                       | 
| 24 | 
            -
                        response_for request_for(env)
         | 
| 25 | 
            -
                      rescue Exception => e
         | 
| 26 | 
            -
                        logger.warn("Broker.requestHandler.process: Exception raised (#{e.message}, #{e.backtrace.join('\n')})")
         | 
| 27 | 
            -
                        Response::Factory.error
         | 
| 28 | 
            -
                      end
         | 
| 23 | 
            +
                    def self.process(load_strategy, env)
         | 
| 24 | 
            +
                      response_for request_for(load_strategy, env)
         | 
| 29 25 | 
             
                    end
         | 
| 30 | 
            -
             | 
| 31 26 | 
             
                  end
         | 
| 32 27 | 
             
                end
         | 
| 33 28 | 
             
              end
         | 
| @@ -1,4 +1,3 @@ | |
| 1 | 
            -
            require 'alephant/broker/errors/invalid_cache_key'
         | 
| 2 1 | 
             
            require 'alephant/logger'
         | 
| 3 2 |  | 
| 4 3 | 
             
            module Alephant
         | 
| @@ -7,23 +6,31 @@ module Alephant | |
| 7 6 | 
             
                  class Asset < Base
         | 
| 8 7 | 
             
                    include Logger
         | 
| 9 8 |  | 
| 10 | 
            -
                    attr_reader :component
         | 
| 11 | 
            -
             | 
| 12 9 | 
             
                    def initialize(component)
         | 
| 13 10 | 
             
                      @component = component
         | 
| 14 | 
            -
                      super | 
| 11 | 
            +
                      super component.status
         | 
| 15 12 | 
             
                    end
         | 
| 16 13 |  | 
| 17 14 | 
             
                    def setup
         | 
| 18 | 
            -
                       | 
| 15 | 
            +
                      @headers  = @component.headers
         | 
| 16 | 
            +
                      @content  = @component.content
         | 
| 17 | 
            +
                      log if @component.is_a? Component
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    private
         | 
| 19 21 |  | 
| 20 | 
            -
             | 
| 21 | 
            -
                      @ | 
| 22 | 
            -
                      @status       = loaded_content[:status]
         | 
| 23 | 
            -
                      @sequence     = component.version.nil? ? 'not available' : component.version
         | 
| 24 | 
            -
                      @cached       = component.cached
         | 
| 22 | 
            +
                    def batched
         | 
| 23 | 
            +
                      @component.batch_id.nil? ? '' : 'batched'
         | 
| 25 24 | 
             
                    end
         | 
| 26 25 |  | 
| 26 | 
            +
                    def details
         | 
| 27 | 
            +
                      c = @component
         | 
| 28 | 
            +
                      "#{c.id}/#{c.opts_hash}/#{c.headers} #{batched} #{c.options}"
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    def log
         | 
| 32 | 
            +
                      logger.info "Broker: Component loaded! #{details} (200)"
         | 
| 33 | 
            +
                    end
         | 
| 27 34 | 
             
                  end
         | 
| 28 35 | 
             
                end
         | 
| 29 36 | 
             
              end
         | 
| @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            require 'alephant/broker/errors/invalid_cache_key'
         | 
| 1 2 | 
             
            require 'aws-sdk'
         | 
| 2 3 | 
             
            require 'ostruct'
         | 
| 3 4 |  | 
| @@ -5,8 +6,7 @@ module Alephant | |
| 5 6 | 
             
              module Broker
         | 
| 6 7 | 
             
                module Response
         | 
| 7 8 | 
             
                  class Base
         | 
| 8 | 
            -
                    attr_reader :headers
         | 
| 9 | 
            -
                    attr_accessor :status, :content, :content_type, :version, :sequence, :cached
         | 
| 9 | 
            +
                    attr_reader :content, :headers, :status
         | 
| 10 10 |  | 
| 11 11 | 
             
                    STATUS_CODE_MAPPING = {
         | 
| 12 12 | 
             
                      200 => 'ok',
         | 
| @@ -15,64 +15,16 @@ module Alephant | |
| 15 15 | 
             
                    }
         | 
| 16 16 |  | 
| 17 17 | 
             
                    def initialize(status = 200, content_type = "text/html")
         | 
| 18 | 
            -
                      @ | 
| 19 | 
            -
                      @ | 
| 20 | 
            -
                      @ | 
| 21 | 
            -
                      @cached       = false
         | 
| 22 | 
            -
                      @content_type = content_type
         | 
| 23 | 
            -
                      @status       = status
         | 
| 24 | 
            -
                      @content      = STATUS_CODE_MAPPING[status]
         | 
| 18 | 
            +
                      @content = STATUS_CODE_MAPPING[status]
         | 
| 19 | 
            +
                      @headers = { "Content-Type" => content_type }
         | 
| 20 | 
            +
                      @status  = status
         | 
| 25 21 |  | 
| 26 22 | 
             
                      setup
         | 
| 27 23 | 
             
                    end
         | 
| 28 24 |  | 
| 29 | 
            -
                    def to_h
         | 
| 30 | 
            -
                      {
         | 
| 31 | 
            -
                        :status       => @status,
         | 
| 32 | 
            -
                        :content      => @content,
         | 
| 33 | 
            -
                        :content_type => @content_type,
         | 
| 34 | 
            -
                        :version      => @version,
         | 
| 35 | 
            -
                        :sequence     => @sequence,
         | 
| 36 | 
            -
                        :cached       => @cached
         | 
| 37 | 
            -
                      }
         | 
| 38 | 
            -
                    end
         | 
| 39 | 
            -
             | 
| 40 25 | 
             
                    protected
         | 
| 41 26 |  | 
| 42 27 | 
             
                    def setup; end
         | 
| 43 | 
            -
             | 
| 44 | 
            -
                    def load(component)
         | 
| 45 | 
            -
                      begin
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                        data = OpenStruct.new(:status => 200, :content_type => content_type)
         | 
| 48 | 
            -
                        component.load
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                        data.content_type = component.content_type
         | 
| 51 | 
            -
                        data.body         = component.content.force_encoding('UTF-8')
         | 
| 52 | 
            -
                      rescue AWS::S3::Errors::NoSuchKey, InvalidCacheKey => e
         | 
| 53 | 
            -
                        data.body   = "Not found"
         | 
| 54 | 
            -
                        data.status = 404
         | 
| 55 | 
            -
                      rescue StandardError => e
         | 
| 56 | 
            -
                        data.body   = "#{error_for(e)}"
         | 
| 57 | 
            -
                        data.status = 500
         | 
| 58 | 
            -
                      end
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                      log(component, data.status, e)
         | 
| 61 | 
            -
                      data.marshal_dump
         | 
| 62 | 
            -
                    end
         | 
| 63 | 
            -
             | 
| 64 | 
            -
                    def log(c, status, e = nil)
         | 
| 65 | 
            -
                      logger.info("Broker: Component loaded: #{details_for(c)} (#{status}) #{error_for(e)}")
         | 
| 66 | 
            -
                    end
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                    def details_for(c)
         | 
| 69 | 
            -
                      "#{c.id}/#{c.opts_hash}/#{c.version} #{c.batch_id.nil? ? '' : "batched"} (#{c.options})"
         | 
| 70 | 
            -
                    end
         | 
| 71 | 
            -
             | 
| 72 | 
            -
                    def error_for(e)
         | 
| 73 | 
            -
                      e.nil? ? nil : "#{e.message}\n#{e.backtrace.join('\n')}"
         | 
| 74 | 
            -
                    end
         | 
| 75 | 
            -
             | 
| 76 28 | 
             
                  end
         | 
| 77 29 | 
             
                end
         | 
| 78 30 | 
             
              end
         | 
| @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            require 'alephant/logger'
         | 
| 2 | 
            -
            require ' | 
| 2 | 
            +
            require 'pmap'
         | 
| 3 3 |  | 
| 4 4 | 
             
            module Alephant
         | 
| 5 5 | 
             
              module Broker
         | 
| @@ -18,22 +18,25 @@ module Alephant | |
| 18 18 |  | 
| 19 19 | 
             
                    def setup
         | 
| 20 20 | 
             
                      @content = JSON.generate({
         | 
| 21 | 
            -
                         | 
| 22 | 
            -
                         | 
| 21 | 
            +
                        'batch_id' => batch_id,
         | 
| 22 | 
            +
                        'components' => json
         | 
| 23 23 | 
             
                      })
         | 
| 24 24 | 
             
                    end
         | 
| 25 25 |  | 
| 26 26 | 
             
                    private
         | 
| 27 27 |  | 
| 28 28 | 
             
                    def json
         | 
| 29 | 
            -
                      logger.info | 
| 30 | 
            -
                      result = components.pmap do | | 
| 29 | 
            +
                      logger.info "Broker: Batch load started (#{batch_id})"
         | 
| 30 | 
            +
                      result = components.pmap do |component|
         | 
| 31 31 | 
             
                        {
         | 
| 32 | 
            -
                          'component' | 
| 33 | 
            -
                          'options' | 
| 34 | 
            -
             | 
| 32 | 
            +
                          'component'    => component.id,
         | 
| 33 | 
            +
                          'options'      => component.options,
         | 
| 34 | 
            +
                          'status'       => component.status,
         | 
| 35 | 
            +
                          'content_type' => component.content_type,
         | 
| 36 | 
            +
                          'body'         => component.content
         | 
| 37 | 
            +
                        }
         | 
| 35 38 | 
             
                      end
         | 
| 36 | 
            -
                      logger.info | 
| 39 | 
            +
                      logger.info "Broker: Batch load done (#{batch_id})"
         | 
| 37 40 |  | 
| 38 41 | 
             
                      result
         | 
| 39 42 | 
             
                    end
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            {"batch_id":"baz","components":[{"component":"ni_council_results_table"},{"component":"ni_council_results_table"}]}
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            {"batch_id":"baz","components":[{"component":"ni_council_results_table","options":{},"status":200,"content_type":"foo/bar","body":"Test"},{"component":"ni_council_results_table","options":{},"status":200,"content_type":"foo/bar","body":"Test"}]}
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            require_relative '../spec_helper'
         | 
    
        data/spec/rack_spec.rb
    CHANGED
    
    | @@ -1,23 +1,37 @@ | |
| 1 | 
            -
            ENV['RACK_ENV'] = 'test'
         | 
| 2 | 
            -
             | 
| 3 1 | 
             
            require 'spec_helper'
         | 
| 4 | 
            -
            require 'rack/test'
         | 
| 5 | 
            -
            require 'alephant/broker'
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            RSpec.configure do |conf|
         | 
| 8 | 
            -
              conf.include Rack::Test::Methods
         | 
| 9 | 
            -
            end
         | 
| 10 2 |  | 
| 11 | 
            -
            describe  | 
| 12 | 
            -
               | 
| 13 | 
            -
             | 
| 3 | 
            +
            describe Alephant::Broker::Application do
         | 
| 4 | 
            +
              include Rack::Test::Methods
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              let(:app) do
         | 
| 7 | 
            +
                described_class.new(
         | 
| 8 | 
            +
                  Alephant::Broker::LoadStrategy::S3.new,
         | 
| 9 | 
            +
                  {
         | 
| 10 | 
            +
                    :lookup_table_name => 'test_table',
         | 
| 11 | 
            +
                    :bucket_id         => 'test_bucket',
         | 
| 12 | 
            +
                    :path              => 'bucket_path'
         | 
| 13 | 
            +
                  }
         | 
| 14 | 
            +
                )
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
              let(:cache_hash) do
         | 
| 17 | 
            +
                {
         | 
| 14 18 | 
             
                  :content_type => 'test/content',
         | 
| 15 19 | 
             
                  :content      => 'Test'
         | 
| 16 20 | 
             
                }
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
              let(:sequencer_double) do
         | 
| 23 | 
            +
                instance_double(
         | 
| 24 | 
            +
                  'Alephant::Sequencer::Sequencer',
         | 
| 25 | 
            +
                  :get_last_seen => '111'
         | 
| 26 | 
            +
                )
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              before do
         | 
| 30 | 
            +
                allow_any_instance_of(Logger).to receive(:info)
         | 
| 31 | 
            +
                allow_any_instance_of(Logger).to receive(:debug)
         | 
| 17 32 |  | 
| 18 33 | 
             
                allow_any_instance_of(Alephant::Broker::Cache::Client)
         | 
| 19 | 
            -
                  .to receive(:get)
         | 
| 20 | 
            -
                  .and_return(cache_hash)
         | 
| 34 | 
            +
                  .to receive(:get).and_return(cache_hash)
         | 
| 21 35 |  | 
| 22 36 | 
             
                allow_any_instance_of(Alephant::Broker::Component)
         | 
| 23 37 | 
             
                  .to receive_messages(
         | 
| @@ -27,97 +41,84 @@ describe 'Broker Rack Application' do | |
| 27 41 | 
             
                  )
         | 
| 28 42 |  | 
| 29 43 | 
             
                allow_any_instance_of(Alephant::Broker::Response::Asset)
         | 
| 30 | 
            -
                  .to receive(:status)
         | 
| 31 | 
            -
                  .and_return(200)
         | 
| 32 | 
            -
              end
         | 
| 33 | 
            -
             | 
| 34 | 
            -
              def app
         | 
| 35 | 
            -
                Alephant::Broker::Application.new({
         | 
| 36 | 
            -
                  :lookup_table_name  => 'test_table',
         | 
| 37 | 
            -
                  :bucket_id          => 'test_bucket',
         | 
| 38 | 
            -
                  :path               => 'bucket_path'
         | 
| 39 | 
            -
                })
         | 
| 40 | 
            -
              end
         | 
| 41 | 
            -
             | 
| 42 | 
            -
              it 'Tests status page' do
         | 
| 43 | 
            -
                get '/status'
         | 
| 44 | 
            -
                expect(last_response).to be_ok
         | 
| 45 | 
            -
                expect(last_response.body).to eq('ok')
         | 
| 46 | 
            -
              end
         | 
| 47 | 
            -
             | 
| 48 | 
            -
              it "Tests not found page" do
         | 
| 49 | 
            -
                get '/some/non-existent-page'
         | 
| 50 | 
            -
                expect(last_response.status).to eq(404)
         | 
| 51 | 
            -
                expect(last_response.body).to eq('Not found')
         | 
| 52 | 
            -
              end
         | 
| 53 | 
            -
             | 
| 54 | 
            -
              it "Test asset data is returned" do
         | 
| 55 | 
            -
                get '/component/test_component'
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                expect(last_response).to be_ok
         | 
| 58 | 
            -
                expect(last_response.body).to eq('Test')
         | 
| 59 | 
            -
              end
         | 
| 44 | 
            +
                  .to receive(:status).and_return(200)
         | 
| 60 45 |  | 
| 61 | 
            -
             | 
| 62 | 
            -
                get '/component/test_component?variant=test_variant'
         | 
| 63 | 
            -
             | 
| 64 | 
            -
                expect(last_response).to be_ok
         | 
| 65 | 
            -
                expect(last_response.body).to eq('Test')
         | 
| 46 | 
            +
                allow(Alephant::Sequencer).to receive(:create) { sequencer_double }
         | 
| 66 47 | 
             
              end
         | 
| 67 48 |  | 
| 68 | 
            -
               | 
| 69 | 
            -
                 | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
                get '/component/test_component'
         | 
| 74 | 
            -
             | 
| 75 | 
            -
                expect(last_response.status).to eq(404)
         | 
| 49 | 
            +
              describe 'Status endpoint `/status`' do
         | 
| 50 | 
            +
                before { get '/status' }
         | 
| 51 | 
            +
                specify { expect(last_response.status).to eql 200 }
         | 
| 52 | 
            +
                specify { expect(last_response.body).to eql 'ok' }
         | 
| 76 53 | 
             
              end
         | 
| 77 54 |  | 
| 78 | 
            -
               | 
| 79 | 
            -
                 | 
| 80 | 
            -
             | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
                get '/component/test_component'
         | 
| 84 | 
            -
             | 
| 85 | 
            -
                expect(last_response.status).to eq(500)
         | 
| 55 | 
            +
              describe '404 endpoint `/banana`' do 
         | 
| 56 | 
            +
                before { get '/banana' }
         | 
| 57 | 
            +
                specify { expect(last_response.status).to eql 404 }
         | 
| 58 | 
            +
                specify { expect(last_response.body).to eq 'Not found' }
         | 
| 86 59 | 
             
              end
         | 
| 87 60 |  | 
| 88 | 
            -
               | 
| 89 | 
            -
                 | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
                 | 
| 93 | 
            -
             | 
| 94 | 
            -
                 | 
| 95 | 
            -
             | 
| 61 | 
            +
              describe 'Component endpoint `/component/...`' do
         | 
| 62 | 
            +
                let(:batch_json) do
         | 
| 63 | 
            +
                  IO.read("#{File.dirname(__FILE__)}/fixtures/json/batch.json").strip
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
                let(:batch_compiled_json) do
         | 
| 66 | 
            +
                  IO.read("#{File.dirname(__FILE__)}/fixtures/json/batch_compiled.json").strip
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                context 'for a valid component ID' do
         | 
| 70 | 
            +
                  before { get '/component/test_component' }
         | 
| 71 | 
            +
                  specify { expect(last_response.status).to eql 200 }
         | 
| 72 | 
            +
                  specify { expect(last_response.body).to eql 'Test' }
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                context 'for valid URL parameters in request' do
         | 
| 76 | 
            +
                  before { get '/component/test_component?variant=test_variant' }
         | 
| 77 | 
            +
                  specify { expect(last_response.status).to eq 200 }
         | 
| 78 | 
            +
                  specify { expect(last_response.body).to eq 'Test' }
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
               
         | 
| 81 | 
            +
                context 'when using valid batch asset data' do
         | 
| 82 | 
            +
                  before { post '/components/batch', batch_json, 'CONTENT_TYPE' => 'application/json' }
         | 
| 83 | 
            +
                  specify { expect(last_response.status).to eql 200 }
         | 
| 84 | 
            +
                  specify { expect(JSON.parse last_response.body).to eq JSON.parse(batch_compiled_json) }
         | 
| 85 | 
            +
                end
         | 
| 96 86 | 
             
              end
         | 
| 97 87 |  | 
| 98 | 
            -
               | 
| 99 | 
            -
                 | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
                   | 
| 108 | 
            -
             | 
| 109 | 
            -
                 | 
| 110 | 
            -
                   | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
             | 
| 114 | 
            -
             | 
| 115 | 
            -
             | 
| 116 | 
            -
             | 
| 117 | 
            -
             | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 88 | 
            +
              describe 'Cached data' do
         | 
| 89 | 
            +
                let(:cache_double) do
         | 
| 90 | 
            +
                  instance_double(
         | 
| 91 | 
            +
                    'Alephant::Broker::Cache::Client',
         | 
| 92 | 
            +
                    :set => { 
         | 
| 93 | 
            +
                      :content_type => 'test/html',
         | 
| 94 | 
            +
                      :content => '<p>Some data</p>' 
         | 
| 95 | 
            +
                    }, 
         | 
| 96 | 
            +
                    :get => '<p>Some data</p>'
         | 
| 97 | 
            +
                  )
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
                let(:lookup_location_double) do
         | 
| 100 | 
            +
                  instance_double('Alephant::Lookup::Location', location: 'test/location')
         | 
| 101 | 
            +
                end
         | 
| 102 | 
            +
                let(:lookup_helper_double) do
         | 
| 103 | 
            +
                  instance_double('Alephant::Lookup::LookupHelper', read: lookup_location_double)
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
                let(:s3_cache_double) do
         | 
| 106 | 
            +
                  instance_double(
         | 
| 107 | 
            +
                    'Alephant::Cache',
         | 
| 108 | 
            +
                    :get => 'test_content'
         | 
| 109 | 
            +
                  )
         | 
| 110 | 
            +
                end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                context 'which is old' do
         | 
| 113 | 
            +
                  before do
         | 
| 114 | 
            +
                    allow(Alephant::Lookup).to receive(:create) { lookup_helper_double }
         | 
| 115 | 
            +
                    allow(Alephant::Broker::Cache::Client).to receive(:new) { cache_double }
         | 
| 116 | 
            +
                    allow(Alephant::Cache).to receive(:new) { s3_cache_double }
         | 
| 117 | 
            +
                  end
         | 
| 118 | 
            +
                  it 'should update the cache (call `.set`)' do
         | 
| 119 | 
            +
                    expect(cache_double).to receive(:set).once
         | 
| 120 | 
            +
                  end 
         | 
| 121 | 
            +
                  after { get '/component/test_component' }
         | 
| 122 | 
            +
                end
         | 
| 121 123 | 
             
              end
         | 
| 122 | 
            -
             | 
| 123 124 | 
             
            end
         |