endo 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +11 -14
- data/endo.gemspec +1 -0
- data/endo/sample.endo +10 -8
- data/lib/endo.rb +2 -0
- data/lib/endo/core.rb +54 -23
- data/lib/endo/error.rb +2 -1
- data/lib/endo/error/validation_error.rb +15 -0
- data/lib/endo/expectation_target.rb +32 -0
- data/lib/endo/matchers.rb +11 -0
- data/lib/endo/matchers/base_matcher.rb +15 -0
- data/lib/endo/matchers/eq.rb +12 -0
- data/lib/endo/version.rb +1 -1
- metadata +22 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 90b76cfad1ab5f415e15a9b7f661c451844a8c18
         | 
| 4 | 
            +
              data.tar.gz: 4d858870cf13514bec7e1fdc6460def568f6d93b
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: fe230bbd9feb1d12d59eae5ced3de6ffa5011a233336acce5234ada09a66038c2622559fa2e023b07748488325968bfd82a579b72d809879595159b74cfb4279
         | 
| 7 | 
            +
              data.tar.gz: 82fb6f79d151d610f39a1a317fca3fd3c55b1b1fe908337ba2c77b8b9d4f9327c5b78b9c75c549c3fde6614373186976b52f859b2b927200ac7689ced7c14db4
         | 
    
        data/README.md
    CHANGED
    
    | @@ -11,30 +11,27 @@ ex. endo/sample.endo | |
| 11 11 | 
             
            ```ruby
         | 
| 12 12 | 
             
            set :base_url, 'http://endo-sample.maruware.com'
         | 
| 13 13 |  | 
| 14 | 
            -
            get '/articles'
         | 
| 14 | 
            +
            get '/articles' do
         | 
| 15 | 
            +
              expect(body: ->{ at(0)[:title] }).to eq 'good'
         | 
| 16 | 
            +
            end
         | 
| 15 17 |  | 
| 16 18 | 
             
            get '/articles/:article_id' do
         | 
| 17 | 
            -
              param  | 
| 18 | 
            -
                from :get, '/articles'  | 
| 19 | 
            -
                  articles.first[:id]
         | 
| 20 | 
            -
                end
         | 
| 19 | 
            +
              param :article_id do
         | 
| 20 | 
            +
                from :get, '/articles', ->{ first[:id] }
         | 
| 21 21 | 
             
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              expect(header: 'Content-Type').to eq 'application/json; charset=utf-8'
         | 
| 22 24 | 
             
            end
         | 
| 23 25 |  | 
| 24 | 
            -
            post '/ | 
| 25 | 
            -
              param  | 
| 26 | 
            -
              param  | 
| 26 | 
            +
            post '/articless' do
         | 
| 27 | 
            +
              param :title, 'hello'
         | 
| 28 | 
            +
              param :text, 'Hello, world!'
         | 
| 27 29 | 
             
            end
         | 
| 28 30 | 
             
            ```
         | 
| 29 31 |  | 
| 30 32 | 
             
            Exec endo command.
         | 
| 31 33 |  | 
| 32 | 
            -
             | 
| 33 | 
            -
            $ endo exec endo/sample.endo
         | 
| 34 | 
            -
            🍺 /articles [142ms]
         | 
| 35 | 
            -
            🍺 /articles/1 [31ms]
         | 
| 36 | 
            -
            🍺 /articles [28ms]
         | 
| 37 | 
            -
            ```
         | 
| 34 | 
            +
            
         | 
| 38 35 |  | 
| 39 36 | 
             
            ## Installation
         | 
| 40 37 |  | 
    
        data/endo.gemspec
    CHANGED
    
    
    
        data/endo/sample.endo
    CHANGED
    
    | @@ -1,16 +1,18 @@ | |
| 1 1 | 
             
            set :base_url, 'http://endo-sample.maruware.com'
         | 
| 2 2 |  | 
| 3 | 
            -
            get '/articles'
         | 
| 3 | 
            +
            get '/articles' do
         | 
| 4 | 
            +
              expect(body: ->{ at(0)[:title] }).to eq 'good'
         | 
| 5 | 
            +
            end
         | 
| 4 6 |  | 
| 5 7 | 
             
            get '/articles/:article_id' do
         | 
| 6 | 
            -
              param  | 
| 7 | 
            -
                from :get, '/articles'  | 
| 8 | 
            -
                  articles.first[:id]
         | 
| 9 | 
            -
                end
         | 
| 8 | 
            +
              param :article_id do
         | 
| 9 | 
            +
                from :get, '/articles', ->{ first[:id] }
         | 
| 10 10 | 
             
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              expect(header: 'Content-Type').to eq 'application/json; charset=utf-8'
         | 
| 11 13 | 
             
            end
         | 
| 12 14 |  | 
| 13 | 
            -
            post '/ | 
| 14 | 
            -
              param  | 
| 15 | 
            -
              param  | 
| 15 | 
            +
            post '/articless' do
         | 
| 16 | 
            +
              param :title, 'hello'
         | 
| 17 | 
            +
              param :text, 'Hello, world!'
         | 
| 16 18 | 
             
            end
         | 
    
        data/lib/endo.rb
    CHANGED
    
    
    
        data/lib/endo/core.rb
    CHANGED
    
    | @@ -1,12 +1,16 @@ | |
| 1 1 | 
             
            require 'open-uri'
         | 
| 2 2 | 
             
            require 'json'
         | 
| 3 3 | 
             
            require 'net/http'
         | 
| 4 | 
            +
            require 'colorize'
         | 
| 4 5 |  | 
| 5 6 | 
             
            module Endo
         | 
| 6 7 | 
             
              class Core
         | 
| 8 | 
            +
                include Endo::Matchers
         | 
| 9 | 
            +
             | 
| 7 10 | 
             
                def initialize
         | 
| 8 11 | 
             
                  @props = {}
         | 
| 9 12 | 
             
                  @responses = {}
         | 
| 13 | 
            +
                  @expect_alls = {}
         | 
| 10 14 | 
             
                end
         | 
| 11 15 |  | 
| 12 16 | 
             
                def set(key, val)
         | 
| @@ -28,7 +32,7 @@ module Endo | |
| 28 32 | 
             
                    raise ArgumentError.new('DupValue')
         | 
| 29 33 | 
             
                  end
         | 
| 30 34 |  | 
| 31 | 
            -
                  @params[key] = if val
         | 
| 35 | 
            +
                  @params[key.to_s] = if val
         | 
| 32 36 | 
             
                    val
         | 
| 33 37 | 
             
                  else
         | 
| 34 38 | 
             
                    block.call
         | 
| @@ -37,18 +41,21 @@ module Endo | |
| 37 41 | 
             
                end
         | 
| 38 42 |  | 
| 39 43 | 
             
                #TODO: Limit scope
         | 
| 40 | 
            -
                def from(method, endpoint, &block)
         | 
| 44 | 
            +
                def from(method, endpoint, lmd=nil, &block)
         | 
| 41 45 | 
             
                  key = build_response_key(method, endpoint)
         | 
| 42 46 | 
             
                  unless @responses.has_key? key
         | 
| 43 47 | 
             
                    raise RuntimeError.new("NotFoundKey [#{key}]")
         | 
| 44 48 | 
             
                  end
         | 
| 45 49 |  | 
| 46 | 
            -
                   | 
| 50 | 
            +
                  res = @responses[key]
         | 
| 51 | 
            +
                  val = if lmd
         | 
| 52 | 
            +
                    res.instance_exec &lmd
         | 
| 53 | 
            +
                  elsif block
         | 
| 54 | 
            +
                    block.call(res)
         | 
| 55 | 
            +
                  else
         | 
| 47 56 | 
             
                    raise ArgumentError.new('UndefinedBlock')
         | 
| 48 57 | 
             
                  end
         | 
| 49 58 |  | 
| 50 | 
            -
                  res = @responses[key]
         | 
| 51 | 
            -
                  val = block.call(res)
         | 
| 52 59 | 
             
                  unless val.is_a?(String) || val.is_a?(Integer) || val.is_a?(Numeric)
         | 
| 53 60 | 
             
                    raise RuntimeError.new('BadValueType')
         | 
| 54 61 | 
             
                  end
         | 
| @@ -61,25 +68,31 @@ module Endo | |
| 61 68 | 
             
                  org_endpoint = endpoint.clone
         | 
| 62 69 |  | 
| 63 70 | 
             
                  @params = {}
         | 
| 71 | 
            +
                  @expects = []
         | 
| 64 72 | 
             
                  block.call if block
         | 
| 65 73 |  | 
| 66 74 | 
             
                  endpoint = apply_pattern_vars(endpoint, @params)
         | 
| 67 75 |  | 
| 68 76 | 
             
                  url = @props[:base_url] + endpoint
         | 
| 69 77 |  | 
| 70 | 
            -
                   | 
| 78 | 
            +
                  begin
         | 
| 71 79 | 
             
                    t_start = Time.now.instance_eval { self.to_i * 1000 + (usec/1000) }
         | 
| 72 | 
            -
                    res =  | 
| 80 | 
            +
                    res = http_request(url, @params, method: method)
         | 
| 73 81 | 
             
                    t_end = Time.now.instance_eval { self.to_i * 1000 + (usec/1000) }
         | 
| 74 82 |  | 
| 75 | 
            -
                     | 
| 76 | 
            -
                     | 
| 83 | 
            +
                    res_data = parse_body_json(res)
         | 
| 84 | 
            +
                    @responses[build_response_key(method, endpoint)] = res_data
         | 
| 85 | 
            +
                    validate_expects(res) unless @expect_alls.empty? && @expects.empty?
         | 
| 86 | 
            +
                    message = "🍺 #{endpoint} [#{t_end-t_start}ms]"
         | 
| 77 87 | 
             
                  rescue Error::HttpError=>e
         | 
| 78 | 
            -
                    "💩 #{endpoint} [code: #{e.code}]"
         | 
| 88 | 
            +
                    message = "💩 #{endpoint} [code: #{e.code}]".red
         | 
| 89 | 
            +
                    exit 1
         | 
| 90 | 
            +
                  rescue Error::ValidationError => e
         | 
| 91 | 
            +
                    message = "👮 #{endpoint} [expected: \"#{e.expected}\" actual: \"#{e.actual}\"]".yellow
         | 
| 92 | 
            +
                  ensure
         | 
| 93 | 
            +
                    puts message
         | 
| 79 94 | 
             
                  end
         | 
| 80 95 |  | 
| 81 | 
            -
             | 
| 82 | 
            -
                  puts message
         | 
| 83 96 | 
             
                end
         | 
| 84 97 |  | 
| 85 98 | 
             
                def apply_pattern_vars(endpoint, params)
         | 
| @@ -101,33 +114,51 @@ module Endo | |
| 101 114 | 
             
                  endpoint
         | 
| 102 115 | 
             
                end
         | 
| 103 116 |  | 
| 104 | 
            -
                def  | 
| 105 | 
            -
                  res = http_request(url, params, method)
         | 
| 106 | 
            -
                  JSON.parse(res, symbolize_names: symbolize_names)
         | 
| 107 | 
            -
                end
         | 
| 108 | 
            -
             | 
| 109 | 
            -
                def http_request(url, params, method)
         | 
| 117 | 
            +
                def http_request(url, params, method: :get)
         | 
| 110 118 | 
             
                  uri = URI.parse url
         | 
| 111 119 |  | 
| 112 | 
            -
                  if method == :get
         | 
| 120 | 
            +
                  req = if method == :get
         | 
| 113 121 | 
             
                    uri.query = URI.encode_www_form(params)
         | 
| 114 122 | 
             
                    req = Net::HTTP::Get.new uri
         | 
| 115 | 
            -
                   | 
| 116 | 
            -
             | 
| 117 | 
            -
                  if method == :post
         | 
| 123 | 
            +
                  elsif method == :post
         | 
| 118 124 | 
             
                    req = Net::HTTP::Post.new uri.path
         | 
| 119 125 | 
             
                    req.set_form_data(params)
         | 
| 126 | 
            +
                    req
         | 
| 120 127 | 
             
                  end
         | 
| 121 128 |  | 
| 122 129 | 
             
                  res = Net::HTTP.start(uri.host, uri.port) {|http| http.request req }
         | 
| 123 130 | 
             
                  raise Error::HttpError.new("HTTP Bad Status[#{res.code}] #{res.body}", res.code, res.body) unless /^20[0-8]$/ =~ res.code
         | 
| 124 131 |  | 
| 125 | 
            -
                  return res | 
| 132 | 
            +
                  return res
         | 
| 133 | 
            +
                end
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                def parse_body_json(res)
         | 
| 136 | 
            +
                  JSON.parse(res.body, symbolize_names: true)
         | 
| 126 137 | 
             
                end
         | 
| 127 138 |  | 
| 128 139 | 
             
                def build_response_key(method, endpoint)
         | 
| 129 140 | 
             
                  "#{method}:#{endpoint}"
         | 
| 130 141 | 
             
                end
         | 
| 131 142 |  | 
| 143 | 
            +
                def expect(header: nil, body: nil)
         | 
| 144 | 
            +
                  expectation = if header
         | 
| 145 | 
            +
                    ExpectationTarget.new(:header, header)
         | 
| 146 | 
            +
                  elsif(body)
         | 
| 147 | 
            +
                    ExpectationTarget.new(:body, body)
         | 
| 148 | 
            +
                  else
         | 
| 149 | 
            +
                    raise 'TODO'
         | 
| 150 | 
            +
                  end
         | 
| 151 | 
            +
                  @expects << expectation
         | 
| 152 | 
            +
                  return expectation
         | 
| 153 | 
            +
                end
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                def validate_expects(res)
         | 
| 156 | 
            +
                  @expects.each do |expectation|
         | 
| 157 | 
            +
                    unless expectation.matches?(res)
         | 
| 158 | 
            +
                      raise Error::ValidationError.new(expectation.expected, expectation.actual)
         | 
| 159 | 
            +
                    end
         | 
| 160 | 
            +
                  end
         | 
| 161 | 
            +
                end
         | 
| 162 | 
            +
             | 
| 132 163 | 
             
              end
         | 
| 133 164 | 
             
            end
         | 
    
        data/lib/endo/error.rb
    CHANGED
    
    | @@ -1 +1,2 @@ | |
| 1 | 
            -
            require 'endo/error/http_error'
         | 
| 1 | 
            +
            require 'endo/error/http_error'
         | 
| 2 | 
            +
            require 'endo/error/validation_error'
         | 
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            module Endo
         | 
| 3 | 
            +
              module Error
         | 
| 4 | 
            +
                class ValidationError < StandardError
         | 
| 5 | 
            +
                  attr_reader :expected, :actual
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def initialize(expected, actual)
         | 
| 8 | 
            +
                    super("expected: #{expected}\n actual: #{actual}")
         | 
| 9 | 
            +
                    @expected = expected
         | 
| 10 | 
            +
                    @actual = actual
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
            end
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            module Endo
         | 
| 2 | 
            +
              class ExpectationTarget
         | 
| 3 | 
            +
                attr_reader :actual
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize(target, query)
         | 
| 6 | 
            +
                  @target = target
         | 
| 7 | 
            +
                  @query = query
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def to(matcher)
         | 
| 11 | 
            +
                  @matcher = matcher
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def matches?(res)
         | 
| 15 | 
            +
                  @actual = case @target
         | 
| 16 | 
            +
                  when :header
         | 
| 17 | 
            +
                    res.header[@query]
         | 
| 18 | 
            +
                  when :body
         | 
| 19 | 
            +
                    obj = JSON.parse res.body, symbolize_names: true
         | 
| 20 | 
            +
                    obj.instance_exec(&@query)
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                  @matcher.matches?(@actual)
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
             | 
| 26 | 
            +
                def expected
         | 
| 27 | 
            +
                  @matcher.expected
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
             | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
            end
         | 
    
        data/lib/endo/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: endo
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.2.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - maruware
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2016-03-07 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: thor
         | 
| @@ -24,6 +24,20 @@ dependencies: | |
| 24 24 | 
             
                - - ">="
         | 
| 25 25 | 
             
                  - !ruby/object:Gem::Version
         | 
| 26 26 | 
             
                    version: '0'
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: colorize
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - ">="
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: '0'
         | 
| 34 | 
            +
              type: :runtime
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - ">="
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: '0'
         | 
| 27 41 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 28 42 | 
             
              name: bundler
         | 
| 29 43 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -86,6 +100,11 @@ files: | |
| 86 100 | 
             
            - lib/endo/core.rb
         | 
| 87 101 | 
             
            - lib/endo/error.rb
         | 
| 88 102 | 
             
            - lib/endo/error/http_error.rb
         | 
| 103 | 
            +
            - lib/endo/error/validation_error.rb
         | 
| 104 | 
            +
            - lib/endo/expectation_target.rb
         | 
| 105 | 
            +
            - lib/endo/matchers.rb
         | 
| 106 | 
            +
            - lib/endo/matchers/base_matcher.rb
         | 
| 107 | 
            +
            - lib/endo/matchers/eq.rb
         | 
| 89 108 | 
             
            - lib/endo/version.rb
         | 
| 90 109 | 
             
            homepage: https://github.com/maruware/endo
         | 
| 91 110 | 
             
            licenses: []
         | 
| @@ -106,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 106 125 | 
             
                  version: '0'
         | 
| 107 126 | 
             
            requirements: []
         | 
| 108 127 | 
             
            rubyforge_project: 
         | 
| 109 | 
            -
            rubygems_version: 2.4.5
         | 
| 128 | 
            +
            rubygems_version: 2.4.5.1
         | 
| 110 129 | 
             
            signing_key: 
         | 
| 111 130 | 
             
            specification_version: 4
         | 
| 112 131 | 
             
            summary: Testing api endpoints tool
         |