class Mock5::Api

A class representing an API mock

Attributes

app[R]

@return [Sinatra::Base] a Sinatra app mocking the API

endpoint[R]

@return [Regexp] a regexp to match the API request urls

Public Class Methods

new(endpoint=nil, &block) click to toggle source

Returns an instance of Mock5::Api

@example

my_mock_api = Mock5::Api.new("http://example.com") do
  get "posts" do
    [
      {id: 1, body: "a posy body"},
      {id: 2, body: "another post body"}
    ].to_json
  end

  post "posts" do
    halt 201, "The post was created successfully"
  end
end

@param endpoint [String, Regexp] a url of the API service to

endpoint to mock. Can only contain schema and hostname, path
should be empty.

@yield a block passed to Sinatra to initialize an app

@return [Mock5::Api]

# File lib/mock5/api.rb, line 38
def initialize(endpoint=nil, &block)
  @app = Sinatra.new(&block)
  @endpoint = normalize_endpoint(endpoint)
end

Public Instance Methods

request_stub() click to toggle source

Returns webmock request stub built with Sinatra app and enpoint url

@return [WebMock::RequestStub]

# File lib/mock5/api.rb, line 46
def request_stub
  @request_stub ||= WebMock::RequestStub.new(:any, endpoint).tap{ |s| s.to_rack(app) }
end

Private Instance Methods

app_paths_regex() click to toggle source
# File lib/mock5/api.rb, line 80
def app_paths_regex
  regexes = app.routes.values.flatten.select{ |v| Regexp === v }
  paths = regexes.map{ |regex| regex.source[3..-3] }

  return ".*" if paths.empty?

  paths = paths.one?? paths.first : %{(?:#{paths.join("|")})}

  "#{paths}(?:\\?.*)?"
end
normalize_endpoint(endpoint) click to toggle source
# File lib/mock5/api.rb, line 52
def normalize_endpoint(endpoint)
  case endpoint
  when nil
    /.*/
  when String
    normalize_string_endpoint(endpoint)
  when Regexp
    endpoint
  else
    raise ArgumentError, "Endpoint should be string or regexp"
  end
end
normalize_string_endpoint(endpoint) click to toggle source
# File lib/mock5/api.rb, line 65
def normalize_string_endpoint(endpoint)
  uri = URI.parse(endpoint)

  if uri.scheme !~ /\Ahttps?/
    raise ArgumentError, "Endpoint should be a valid URL"
  elsif uri.path != ?/ && !uri.path.empty?
    raise ArgumentError, "Endpoint URL should not include path"
  end

  uri.path = ""
  endpoint = Regexp.escape(uri.to_s)

  Regexp.new("\\A#{endpoint}\/#{app_paths_regex}\\z")
end