├── .rspec ├── lib ├── marvelite │ ├── version.rb │ └── api │ │ ├── response.rb │ │ ├── router.rb │ │ ├── config │ │ └── v1.yml │ │ └── client.rb └── marvelite.rb ├── .travis.yml ├── Gemfile ├── .hound.yml ├── Rakefile ├── .gitignore ├── spec ├── marvelite │ └── api │ │ ├── router_spec.rb │ │ ├── client_spec.rb │ │ ├── client_comics_endpoints_spec.rb │ │ ├── client_creators_endpoints_spec.rb │ │ ├── client_stories_endpoints_spec.rb │ │ ├── client_series_endpoints_spec.rb │ │ ├── client_characters_endpoints_spec.rb │ │ └── client_events_endpoints_spec.rb ├── spec_helper.rb └── fixtures │ ├── stories │ ├── story.json │ ├── story_comics.json │ ├── story_creators.json │ └── story_series.json │ ├── creators │ ├── creator_2.json │ └── creator.json │ ├── comics │ ├── comic_stories.json │ ├── comic.json │ ├── comic_characters.json │ └── comic_events.json │ ├── characters │ ├── character_2.json │ └── character.json │ └── series │ └── serie.json ├── LICENSE.txt ├── marvelite.gemspec ├── README.md └── CHANGELOG.md /.rspec: -------------------------------------------------------------------------------- 1 | --color -------------------------------------------------------------------------------- /lib/marvelite/version.rb: -------------------------------------------------------------------------------- 1 | module Marvelite 2 | VERSION = '0.1.3' 3 | end 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | 3 | rvm: 4 | - 1.9.2 5 | - 1.9.3 6 | - 2.0.0 7 | - 2.1.0 8 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in marvelite.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /.hound.yml: -------------------------------------------------------------------------------- 1 | LineLength: 2 | Description: 'Limit lines to 85 characters.' 3 | max: 85 4 | HashSyntax: 5 | EnforcedStyle: hash_rockets -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rspec/core/rake_task" 3 | 4 | RSpec::Core::RakeTask.new("spec") 5 | 6 | task :default => :spec 7 | 8 | task :console do 9 | require 'pry' 10 | require 'marvelite' 11 | ARGV.clear 12 | Pry.start 13 | end -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .ruby-gemset 6 | .ruby-version 7 | .yardoc 8 | Gemfile.lock 9 | InstalledFiles 10 | _yardoc 11 | coverage 12 | doc/ 13 | lib/bundler/man 14 | pkg 15 | rdoc 16 | spec/reports 17 | test/tmp 18 | test/version_tmp 19 | tmp 20 | -------------------------------------------------------------------------------- /lib/marvelite.rb: -------------------------------------------------------------------------------- 1 | require 'digest/md5' 2 | require 'httparty' 3 | require 'hashie' 4 | 5 | require "marvelite/version" 6 | require "marvelite/api/router" 7 | require "marvelite/api/client" 8 | require "marvelite/api/response" 9 | 10 | module Marvelite 11 | def self.router(attrs = {}) 12 | Marvelite::API::Router.new(attrs) 13 | end 14 | end -------------------------------------------------------------------------------- /spec/marvelite/api/router_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Marvelite::API::Router do 4 | context 'initialization' do 5 | it 'accepts an :api_version as param' do 6 | router = Marvelite::API::Router.new(:api_version => 'v1') 7 | expect(router.api_version).to eq('v1') 8 | end 9 | 10 | it ':api_version defaults to v1' do 11 | router = Marvelite::API::Router.new 12 | expect(router.api_version).to eq('v1') 13 | end 14 | 15 | it 'loads a YAML config file matching the :api_version attribute' 16 | 17 | it 'calls #add_route for each route defined in YAML routes file' 18 | 19 | it 'calls #map_routes' 20 | end 21 | 22 | describe '#add_route' do 23 | it 'adds a new route to the routes variable' 24 | end 25 | 26 | describe '#map_routes' do 27 | it 'adds all routes as methods to the router' 28 | end 29 | 30 | end -------------------------------------------------------------------------------- /lib/marvelite/api/response.rb: -------------------------------------------------------------------------------- 1 | module Marvelite 2 | module API 3 | class Response < Hash 4 | include Hashie::Extensions::MergeInitializer 5 | include Hashie::Extensions::KeyConversion 6 | include Hashie::Extensions::MethodAccess 7 | include Hashie::Extensions::IndifferentAccess 8 | 9 | attr_reader :raw_response 10 | 11 | def self.make(response) 12 | case response.code 13 | when 200 14 | Response.new(response) 15 | when 304 16 | NotModifiedResponse.new(response) 17 | else 18 | ErrorResponse.new(response) 19 | end 20 | end 21 | 22 | def initialize(raw) 23 | @raw_response = raw 24 | super(raw) 25 | end 26 | end 27 | 28 | class ErrorResponse < Response; end 29 | 30 | class NotModifiedResponse < Response 31 | def initialize(response) 32 | super({ 33 | status: 'Not Modified', 34 | code: 304, 35 | data: {}, 36 | etag: response.headers['etag'] 37 | }) 38 | end 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Antonio Antillon 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. 23 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'marvelite' 2 | require 'pry' 3 | require 'pathname' 4 | require 'json' 5 | require 'hashie' 6 | require 'fakeweb' 7 | 8 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) 9 | $LOAD_PATH.unshift(File.dirname(__FILE__)) 10 | 11 | RSpec.configure do |config| 12 | FakeWeb.allow_net_connect = false 13 | 14 | config.mock_with :rspec do |c| 15 | c.syntax = [:should, :expect] 16 | end 17 | 18 | def marvel_url(url) 19 | "http://gateway.marvel.com/v1/public/#{url}" 20 | end 21 | 22 | def marvelite_test_client 23 | client = Marvelite::API::Client.new(:public_key => '123456', :private_key => 'abcdef') 24 | client.stub(:ts).and_return('1') 25 | client.stub(:hash).and_return('d4f1bab013916a533ef31e3ad5fb0887') 26 | client 27 | end 28 | 29 | def json_response(filename) 30 | file = Pathname("./spec/fixtures/#{filename}") 31 | file.read 32 | end 33 | 34 | def stub_get(url, filename, options={}) 35 | opts = { 36 | :body => json_response(filename), 37 | :content_type => 'application/json; charset=utf-8' 38 | }.merge(options) 39 | FakeWeb.register_uri(:get, marvel_url(url), opts) 40 | end 41 | 42 | def stub_304(url, etag) 43 | FakeWeb.register_uri(:get, marvel_url(url), status: 304, body: '', etag: etag) 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /marvelite.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'marvelite/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "marvelite" 8 | spec.version = Marvelite::VERSION 9 | spec.authors = ["Antonio Antillon"] 10 | spec.email = ["antillas21@gmail.com"] 11 | spec.description = %q{Simple wrapper around the Marvel Comics API} 12 | spec.summary = %q{Simple wrapper around the Marvel Comics API} 13 | spec.homepage = "" 14 | spec.license = "MIT" 15 | spec.required_ruby_version = Gem::Requirement.new(">= 1.9.2") 16 | 17 | spec.files = Dir["{lib,spec}/**/*", "[A-Z]*"] - ["Gemfile.lock"] 18 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 19 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 20 | spec.require_path = "lib" 21 | 22 | if RUBY_VERSION == '1.9.2' 23 | spec.add_dependency "httparty", "0.8.3" 24 | else 25 | spec.add_dependency "httparty", "~> 0.12.0" 26 | end 27 | 28 | spec.add_dependency "hashie", "~> 2.0.5" 29 | 30 | spec.add_development_dependency "bundler", "~> 1.3" 31 | spec.add_development_dependency "rake" 32 | spec.add_development_dependency "pry" 33 | spec.add_development_dependency "rspec" 34 | spec.add_development_dependency "fakeweb", "~> 1.3" 35 | end 36 | -------------------------------------------------------------------------------- /lib/marvelite/api/router.rb: -------------------------------------------------------------------------------- 1 | module Marvelite 2 | module API 3 | class Router 4 | require 'yaml' 5 | attr_accessor :api_version 6 | 7 | def initialize(attrs = {}) 8 | @api_version = attrs.fetch(:api_version) { 'v1' } 9 | @routes = {} 10 | load_routes_from_file("#{api_version}.yml") 11 | end 12 | 13 | def inspect 14 | "#<#{self.class}:#{self.object_id}>" 15 | end 16 | 17 | def load_routes_from_file(filename) 18 | file_path = File.join(File.dirname(__FILE__), "config", filename) 19 | f = YAML.load(File.read(file_path)) 20 | f.each do |_, route| 21 | add_route(route['name'], route['path']) 22 | end 23 | end 24 | 25 | def routes 26 | @routes 27 | end 28 | 29 | def add_route(name, endpoint) 30 | routes["#{name}_path".to_sym] = { :name => name, :endpoint => endpoint } 31 | end 32 | 33 | def method_missing(method, *args, &block) 34 | if routes.keys.include?(method) 35 | endpoint = "#{routes[method][:endpoint]}" 36 | params = *args 37 | if params.any? 38 | params[0].each do |p_key, p_value| 39 | endpoint.gsub!(":#{p_key.to_s}", p_value.to_s) 40 | end 41 | end 42 | "/#{api_version}#{endpoint}" 43 | else 44 | super 45 | end 46 | end 47 | 48 | end 49 | end 50 | end -------------------------------------------------------------------------------- /lib/marvelite/api/config/v1.yml: -------------------------------------------------------------------------------- 1 | 1: 2 | name: 'characters' 3 | path: '/public/characters' 4 | 2: 5 | name: 'character' 6 | path: '/public/characters/:id' 7 | 3: 8 | name: 'character_comics' 9 | path: '/public/characters/:id/comics' 10 | 4: 11 | name: 'character_events' 12 | path: '/public/characters/:id/events' 13 | 5: 14 | name: 'character_series' 15 | path: '/public/characters/:id/series' 16 | 6: 17 | name: 'character_stories' 18 | path: '/public/characters/:id/stories' 19 | 7: 20 | name: 'comics' 21 | path: '/public/comics' 22 | 8: 23 | name: 'comic' 24 | path: '/public/comics/:id' 25 | 9: 26 | name: 'comic_characters' 27 | path: '/public/comics/:id/characters' 28 | 10: 29 | name: 'comic_creators' 30 | path: '/public/comics/:id/creators' 31 | 11: 32 | name: 'comic_events' 33 | path: '/public/comics/:id/events' 34 | 12: 35 | name: 'comic_stories' 36 | path: '/public/comics/:id/stories' 37 | 13: 38 | name: 'creators' 39 | path: '/public/creators' 40 | 14: 41 | name: 'creator' 42 | path: '/public/creators/:id' 43 | 15: 44 | name: 'creator_comics' 45 | path: '/public/creators/:id/comics' 46 | 16: 47 | name: 'creator_events' 48 | path: '/public/creators/:id/events' 49 | 17: 50 | name: 'creator_series' 51 | path: '/public/creators/:id/series' 52 | 18: 53 | name: 'creator_stories' 54 | path: '/public/creators/:id/stories' 55 | 19: 56 | name: 'events' 57 | path: '/public/events' 58 | 20: 59 | name: 'event' 60 | path: '/public/events/:id' 61 | 21: 62 | name: 'event_characters' 63 | path: '/public/events/:id/characters' 64 | 22: 65 | name: 'event_creators' 66 | path: '/public/events/:id/creators' 67 | 23: 68 | name: 'event_comics' 69 | path: '/public/events/:id/comics' 70 | 24: 71 | name: 'event_stories' 72 | path: '/public/events/:id/stories' 73 | 25: 74 | name: 'event_series' 75 | path: '/public/events/:id/series' 76 | 26: 77 | name: 'series' 78 | path: '/public/series' 79 | 27: 80 | name: 'serie' 81 | path: '/public/series/:id' 82 | 28: 83 | name: 'series_characters' 84 | path: '/public/series/:id/characters' 85 | 29: 86 | name: 'series_comics' 87 | path: '/public/series/:id/comics' 88 | 30: 89 | name: 'series_creators' 90 | path: '/public/series/:id/creators' 91 | 31: 92 | name: 'series_events' 93 | path: '/public/series/:id/events' 94 | 32: 95 | name: 'series_stories' 96 | path: '/public/series/:id/stories' 97 | 33: 98 | name: 'stories' 99 | path: '/public/stories' 100 | 34: 101 | name: 'story' 102 | path: '/public/stories/:id' 103 | 35: 104 | name: 'story_characters' 105 | path: '/public/stories/:id/characters' 106 | 36: 107 | name: 'story_comics' 108 | path: '/public/stories/:id/comics' 109 | 37: 110 | name: 'story_creators' 111 | path: '/public/stories/:id/creators' 112 | 38: 113 | name: 'story_events' 114 | path: '/public/stories/:id/events' 115 | 39: 116 | name: 'story_series' 117 | path: '/public/stories/:id/series' 118 | -------------------------------------------------------------------------------- /spec/fixtures/stories/story.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 200, 3 | "status": "Ok", 4 | "etag": "c24dc95f6fa891870eba57823dfaca6e7df279b6", 5 | "data": { 6 | "offset": 0, 7 | "limit": 20, 8 | "total": 1, 9 | "count": 1, 10 | "results": [ 11 | { 12 | "id": 2210, 13 | "title": "2 of 3 - House of M", 14 | "description": "", 15 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2210", 16 | "type": "cover", 17 | "modified": "2013-07-22T13:09:58-0400", 18 | "thumbnail": null, 19 | "creators": { 20 | "available": 1, 21 | "collectionURI": "http://gateway.marvel.com/v1/public/stories/2210/creators", 22 | "items": [ 23 | { 24 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/191", 25 | "name": "Kaare Andrews", 26 | "role": "penciller (cover)" 27 | } 28 | ], 29 | "returned": 1 30 | }, 31 | "characters": { 32 | "available": 3, 33 | "collectionURI": "http://gateway.marvel.com/v1/public/stories/2210/characters", 34 | "items": [ 35 | { 36 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1010954", 37 | "name": "Mystique (House of M)" 38 | }, 39 | { 40 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009570", 41 | "name": "Sentinel" 42 | }, 43 | { 44 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009718", 45 | "name": "Wolverine" 46 | } 47 | ], 48 | "returned": 3 49 | }, 50 | "series": { 51 | "available": 1, 52 | "collectionURI": { 53 | "service": "comic_storySeries", 54 | "id": 2210 55 | }, 56 | "items": [ 57 | { 58 | "resourceURI": "http://gateway.marvel.com/v1/public/series/632", 59 | "name": "Wolverine (2003 - 2009)" 60 | } 61 | ], 62 | "returned": 1 63 | }, 64 | "comics": { 65 | "available": 1, 66 | "collectionURI": "http://gateway.marvel.com/v1/public/stories/2210/comics", 67 | "items": [ 68 | { 69 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/2521", 70 | "name": "Wolverine (2003) #34" 71 | } 72 | ], 73 | "returned": 1 74 | }, 75 | "events": { 76 | "available": 1, 77 | "collectionURI": "http://gateway.marvel.com/v1/public/stories/2210/events", 78 | "items": [ 79 | { 80 | "resourceURI": "http://gateway.marvel.com/v1/public/events/251", 81 | "name": "House of M" 82 | } 83 | ], 84 | "returned": 1 85 | }, 86 | "originalIssue": { 87 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/2521", 88 | "name": "Wolverine (2003) #34" 89 | } 90 | } 91 | ] 92 | } 93 | } -------------------------------------------------------------------------------- /spec/fixtures/creators/creator_2.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 200, 3 | "status": "Ok", 4 | "etag": "9d8be822b30c623c68ba36a6faf3753991e244e3", 5 | "data": { 6 | "offset": 0, 7 | "limit": 20, 8 | "total": 1, 9 | "count": 1, 10 | "results": [ 11 | { 12 | "id": 4781, 13 | "firstName": "Barta", 14 | "middleName": "", 15 | "lastName": "", 16 | "suffix": "", 17 | "fullName": "Barta", 18 | "modified": "2007-01-02T00:00:00-0500", 19 | "thumbnail": { 20 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/b/40/image_not_available", 21 | "extension": "jpg" 22 | }, 23 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/4781", 24 | "comics": { 25 | "available": 3, 26 | "collectionURI": "http://gateway.marvel.com/v1/public/creators/4781/comics", 27 | "items": [ 28 | { 29 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/15137", 30 | "name": "Silver Surfer (1987) #137" 31 | }, 32 | { 33 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/15138", 34 | "name": "Silver Surfer (1987) #138" 35 | }, 36 | { 37 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/15139", 38 | "name": "Silver Surfer (1987) #139" 39 | } 40 | ], 41 | "returned": 3 42 | }, 43 | "series": { 44 | "available": 1, 45 | "collectionURI": "http://gateway.marvel.com/v1/public/creators/4781/series", 46 | "items": [ 47 | { 48 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2288", 49 | "name": "Silver Surfer (1987 - 1998)" 50 | } 51 | ], 52 | "returned": 1 53 | }, 54 | "stories": { 55 | "available": 3, 56 | "collectionURI": "http://gateway.marvel.com/v1/public/creators/4781/stories", 57 | "items": [ 58 | { 59 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/30743", 60 | "name": "the Resurrection", 61 | "type": "cover" 62 | }, 63 | { 64 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/30745", 65 | "name": "Cover #30745", 66 | "type": "cover" 67 | }, 68 | { 69 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/30747", 70 | "name": "Cover #30747", 71 | "type": "cover" 72 | } 73 | ], 74 | "returned": 3 75 | }, 76 | "events": { 77 | "available": 0, 78 | "collectionURI": "http://gateway.marvel.com/v1/public/creators/4781/events", 79 | "items": [], 80 | "returned": 0 81 | }, 82 | "urls": [ 83 | { 84 | "type": "detail", 85 | "url": "http://marvel.com/comics/creators/4781/barta?utm_campaign=apiRef&utm_source=c60a23f273a09387e7d1ad4e6f828211" 86 | } 87 | ] 88 | } 89 | ] 90 | } 91 | } -------------------------------------------------------------------------------- /lib/marvelite/api/client.rb: -------------------------------------------------------------------------------- 1 | module Marvelite 2 | module API 3 | class Client 4 | include HTTParty 5 | base_uri 'http://gateway.marvel.com' 6 | 7 | attr_accessor :public_key, :private_key, :router, :api_version 8 | 9 | class InvalidClientError < StandardError; end 10 | 11 | def initialize(attrs) 12 | check_for_errors(attrs) 13 | @public_key = attrs.fetch(:public_key) 14 | @private_key = attrs.fetch(:private_key) 15 | @api_version = attrs.fetch(:api_version) { 'v1' } 16 | @router = attrs.fetch(:router) { Marvelite.router(:api_version => @api_version) } 17 | build_methods 18 | end 19 | 20 | private 21 | def check_for_errors(attrs) 22 | [:public_key, :private_key].each do |key| 23 | raise InvalidClientError, "You need to provide a :#{key} param." unless attrs[key] 24 | end 25 | end 26 | 27 | def params(additional_params = {}) 28 | base_hash = { :apikey => public_key, :ts => ts, :hash => request_hash } 29 | additional_params.merge(base_hash) 30 | end 31 | 32 | def request_hash 33 | Digest::MD5.hexdigest("#{ts}#{private_key}#{public_key}") 34 | end 35 | 36 | def ts 37 | begin 38 | Time.now.to_i 39 | end 40 | end 41 | 42 | def build_response_object(response) 43 | Response.make(response) 44 | end 45 | 46 | def find_by_name_or_title(endpoint, column, value) 47 | response = self.send(endpoint, { column.to_sym => value }) 48 | return false unless response[:data][:count] > 0 49 | response[:id] = response[:data][:results][0][:id] 50 | response 51 | end 52 | 53 | def pull_headers(options) 54 | headers = options.delete(:headers) || {} 55 | headers.merge!({ 'Accept-Encoding' => 'gzip' }) unless headers['Accept-Encoding'] 56 | [options, headers] 57 | end 58 | 59 | def process_arguments(*args) 60 | temp_id, temp_options = *args 61 | if temp_id && temp_id.is_a?(Hash) 62 | id = nil 63 | options = temp_id || {} 64 | elsif temp_id 65 | id = temp_id 66 | options = temp_options || {} 67 | else 68 | options = {} 69 | end 70 | params, headers = pull_headers(options) 71 | [{ id: id, options: params}, headers] 72 | end 73 | 74 | def fetch_response(route, params_hash = {}, headers = {}) 75 | id = params_hash[:id] 76 | options = params_hash[:options] 77 | path = find_path(route, id) 78 | 79 | self.class.get(path, query: params(options), headers: headers) 80 | end 81 | 82 | def find_path(route, id) 83 | if id.nil? 84 | router.send("#{route}_path".to_sym) 85 | else 86 | id = fetch_resource_id(route, id) if id.is_a?(String) 87 | router.send("#{route}_path".to_sym, {:id => id}) 88 | end 89 | end 90 | 91 | def fetch_resource_id(route, id) 92 | endpoint = route.split("_")[0]+"s" 93 | resource = find_by_name_or_title(endpoint.to_sym, :name, id) 94 | return false unless resource 95 | resource[:id] 96 | end 97 | 98 | def build_methods 99 | @router.routes.each do |_, hash| 100 | name = hash[:name] 101 | self.class.send(:define_method, name) do |*args| 102 | params, headers = process_arguments(*args) 103 | response = fetch_response(name, params, headers) 104 | build_response_object(response) 105 | end 106 | end 107 | end 108 | 109 | end 110 | end 111 | end 112 | -------------------------------------------------------------------------------- /spec/marvelite/api/client_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Marvelite::API::Client do 4 | describe 'initialization' do 5 | it 'requires a :public_key to be set' do 6 | expect{ Marvelite::API::Client.new(:private_key => '12345') }.to raise_error( 7 | Marvelite::API::Client::InvalidClientError, "You need to provide a :public_key param." 8 | ) 9 | end 10 | 11 | it 'requires a :private_key to be set' do 12 | expect{ Marvelite::API::Client.new(:public_key => '1234') }.to raise_error( 13 | Marvelite::API::Client::InvalidClientError, "You need to provide a :private_key param." 14 | ) 15 | end 16 | 17 | context 'valid' do 18 | let(:client) { Marvelite::API::Client.new(:public_key => '1234', :private_key => 'abcd') } 19 | 20 | describe '#api_version' do 21 | it 'receives an :api_version optional param' do 22 | client = Marvelite::API::Client.new( 23 | :public_key => '1234', :private_key => 'abcd', :api_version => 'v1' 24 | ) 25 | expect(client.api_version).to eq('v1') 26 | end 27 | 28 | it 'defaults to v1' do 29 | expect(client.api_version).to eq('v1') 30 | end 31 | end 32 | 33 | it 'is an instance of Marvelite::Client' do 34 | expect{ client }.to_not raise_error 35 | expect(client).to be_a(Marvelite::API::Client) 36 | end 37 | 38 | it 'has an API Router instance in its config' do 39 | expect(client.router).to_not be_nil 40 | expect(client.router).to be_a(Marvelite::API::Router) 41 | end 42 | end 43 | end 44 | 45 | describe 'etags' do 46 | let(:client) { marvelite_test_client } 47 | let(:etag) { '64aceb407b735957130fce343bf4933ed21a7cfc' } 48 | 49 | before do 50 | stub_304('series?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', etag) 51 | end 52 | 53 | it 'returns a NotModifiedResponse' do 54 | headers = { 'If-None-Match' => "\"#{etag}\"" } 55 | response = client.series(headers: headers) 56 | 57 | expect(response).to be_a Marvelite::API::NotModifiedResponse 58 | expect(response.code).to eq(304) 59 | expect(response.status).to eq("Not Modified") 60 | expect(response.etag).to eq(etag) 61 | expect(response.data).to eq({}) 62 | end 63 | end 64 | 65 | describe 'gzip compression support' do 66 | let(:client) { marvelite_test_client } 67 | let(:options) { {:id => 123} } 68 | 69 | it 'is enabled by default' do 70 | expect(client.send(:pull_headers, options)).to eq( 71 | [{ :id => 123 }, { 'Accept-Encoding' => 'gzip' }] 72 | ) 73 | end 74 | 75 | it 'can be passed in explicitely' do 76 | gzip_options = { :id => 234, :headers => { 'Accept-Encoding' => 'gzip' } } 77 | expect(client.send(:pull_headers, gzip_options)).to eq( 78 | [{ :id => 234 }, { 'Accept-Encoding' => 'gzip' }] 79 | ) 80 | end 81 | end 82 | 83 | context "private methods" do 84 | describe '#ts' do 85 | let(:client) { Marvelite::API::Client.new(:public_key => '1234', :private_key => 'abcd') } 86 | 87 | it 'calls Time.now' do 88 | Time.should_receive(:now) 89 | client.send(:ts) 90 | end 91 | 92 | it 'represents a timestamp converted to integer' do 93 | expect(client.send(:ts)).to be_a(Integer) 94 | end 95 | end 96 | 97 | describe '#params' do 98 | let(:client) { Marvelite::API::Client.new(:public_key => '1234', :private_key => 'abcd') } 99 | 100 | it 'passes required API params to all requests' do 101 | client.stub(:ts).and_return('1') 102 | expect(client.send(:params)).to eq( 103 | {:apikey => client.public_key, :ts => '1', :hash => 'ffd275c5130566a2916217b101f26150'} 104 | ) 105 | end 106 | end 107 | end 108 | end 109 | -------------------------------------------------------------------------------- /spec/marvelite/api/client_comics_endpoints_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Marvelite::API::Client do 4 | context "Comics Endpoints" do 5 | let(:client) { marvelite_test_client } 6 | 7 | describe '#comics' do 8 | before do 9 | stub_get('comics?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'comics/comics.json') 10 | end 11 | 12 | it 'returns a Marvelite::API::Response object' do 13 | expect(client.comics).to be_a(Marvelite::API::Response) 14 | end 15 | 16 | it 'Response object is populated with JSON from the /comics endpoint' do 17 | expect(client.comics["status"]).to eq("Ok") 18 | expect(client.comics[:data][:results].size).to eq(20) 19 | end 20 | end 21 | 22 | describe '#comic' do 23 | before do 24 | stub_get('comics/40128?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'comics/comic.json') 25 | end 26 | it 'returns a Marvelite::API::Response object' do 27 | expect(client.comic(40128)).to be_a(Marvelite::API::Response) 28 | end 29 | 30 | it 'Response object is populated with JSON from the /comics/:id endpoint' do 31 | expect(client.comic(40128)[:data][:results][0][:title]).to eq('Amazing Spider-Man (1999) #700') 32 | end 33 | 34 | it 'accepts an Integer as comic id' do 35 | expect(client.comic(40128)[:data][:results][0][:title]).to eq('Amazing Spider-Man (1999) #700') 36 | end 37 | end 38 | 39 | describe '#comic_characters' do 40 | before do 41 | stub_get('comics/40128/characters?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'comics/comic_characters.json') 42 | end 43 | 44 | it 'returns a Marvelite::API::Response object' do 45 | expect(client.comic_characters(40128)).to be_a(Marvelite::API::Response) 46 | end 47 | 48 | it 'Response object is populated with JSON from the /comics/:id/characters endpoint' do 49 | expect(client.comic_characters(40128)["status"]).to eq("Ok") 50 | expect(client.comic_characters(40128)[:data][:results].size).to eq(1) 51 | end 52 | 53 | it 'accepts an Integer as comic id' do 54 | expect(client.comic_characters(40128)[:data][:results][0][:name]).to eq('Spider-Man') 55 | end 56 | end 57 | 58 | describe '#comic_events' do 59 | before do 60 | stub_get('comics/40128/events?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'comics/comic_events.json') 61 | end 62 | 63 | it 'returns a Marvelite::API::Response object' do 64 | expect(client.comic_events(40128)).to be_a(Marvelite::API::Response) 65 | end 66 | 67 | it 'Response object is populated with JSON from the /comics/:id/events endpoint' do 68 | expect(client.comic_events(40128)["status"]).to eq("Ok") 69 | expect(client.comic_events(40128)[:data][:results].size).to eq(1) 70 | end 71 | 72 | it 'accepts an Integer as comic id' do 73 | expect(client.comic_events(40128)[:data][:results][0][:title]).to eq('Avengers VS X-Men') 74 | end 75 | end 76 | 77 | describe '#comic_creators' do 78 | before do 79 | stub_get('comics/40128/creators?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'comics/comic_creators.json') 80 | end 81 | 82 | it 'returns a Marvelite::API::Response object' do 83 | expect(client.comic_creators(40128)).to be_a(Marvelite::API::Response) 84 | end 85 | 86 | it 'Response object is populated with JSON from the /comics/:id/creators endpoint' do 87 | expect(client.comic_creators(40128)["status"]).to eq("Ok") 88 | expect(client.comic_creators(40128)[:data][:results].size).to eq(12) 89 | end 90 | 91 | it 'accepts an Integer as comic id' do 92 | expect(client.comic_creators(40128)[:data][:results][0][:fullName]).to eq('Sal Buscema') 93 | end 94 | end 95 | 96 | describe '#comic_stories' do 97 | before do 98 | stub_get('comics/40128/stories?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'comics/comic_stories.json') 99 | end 100 | 101 | it 'returns a Marvelite::API::Response object' do 102 | expect(client.comic_stories(40128)).to be_a(Marvelite::API::Response) 103 | end 104 | 105 | it 'Response object is populated with JSON from the /comics/:id/stories endpoint' do 106 | expect(client.comic_stories(40128)["status"]).to eq("Ok") 107 | expect(client.comic_stories(40128)[:data][:results].size).to eq(2) 108 | end 109 | 110 | it 'accepts an Integer as comic id' do 111 | expect(client.comic_stories(40128)[:data][:results][0][:title]).to eq('Cover #91053') 112 | end 113 | end 114 | end 115 | end -------------------------------------------------------------------------------- /spec/marvelite/api/client_creators_endpoints_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Marvelite::API::Client do 4 | context "Creators Endpoints" do 5 | let(:client) { marvelite_test_client } 6 | 7 | describe '#creators' do 8 | before do 9 | stub_get('creators?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'creators/creators.json') 10 | end 11 | 12 | it 'returns a Marvelite::API::Response object' do 13 | expect(client.creators).to be_a(Marvelite::API::Response) 14 | end 15 | 16 | it 'Response object is populated with JSON from the /creators endpoint' do 17 | expect(client.creators["status"]).to eq("Ok") 18 | expect(client.creators[:data][:results].size).to eq(20) 19 | end 20 | end 21 | 22 | describe '#creator' do 23 | before do 24 | stub_get('creators/593?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'creators/creator.json') 25 | stub_get('creators/4781?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'creators/creator_2.json') 26 | end 27 | 28 | it 'returns a Marvelite::API::Response object' do 29 | expect(client.creator(593)).to be_a(Marvelite::API::Response) 30 | end 31 | 32 | it 'Response object is populated with JSON from the /creators/:id endpoint' do 33 | expect(client.creator(593)[:data][:results][0][:lastName]).to eq('Loughridge') 34 | end 35 | 36 | it 'accepts an Integer as creator id' do 37 | expect(client.creator(593)[:data][:results][0][:firstName]).to eq('Lee') 38 | expect(client.creator(4781)[:data][:results][0][:firstName]).to eq('Barta') 39 | end 40 | end 41 | 42 | describe '#creator_comics' do 43 | before do 44 | stub_get('creators/593/comics?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'creators/creator_comics.json') 45 | end 46 | 47 | it 'returns a Marvelite::API::Response object' do 48 | expect(client.creator_comics(593)).to be_a(Marvelite::API::Response) 49 | end 50 | 51 | it 'Response object is populated with JSON from the /creators/:id/comics endpoint' do 52 | expect(client.creator_comics(593)["status"]).to eq("Ok") 53 | expect(client.creator_comics(593)[:data][:results].size).to eq(20) 54 | end 55 | 56 | it 'accepts an Integer as creator id' do 57 | expect(client.creator_comics(593)[:data][:results][0][:title]).to eq('Venom (2011) #37') 58 | end 59 | end 60 | 61 | describe '#creator_events' do 62 | before do 63 | stub_get('creators/593/events?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'creators/creator_events.json') 64 | end 65 | 66 | it 'returns a Marvelite::API::Response object' do 67 | expect(client.creator_events(593)).to be_a(Marvelite::API::Response) 68 | end 69 | 70 | it 'Response object is populated with JSON from the /creators/:id/events endpoint' do 71 | expect(client.creator_events(593)["status"]).to eq("Ok") 72 | expect(client.creator_events(593)[:data][:results].size).to eq(2) 73 | end 74 | 75 | it 'accepts an Integer as creator id' do 76 | expect(client.creator_events(593)[:data][:results][0][:title]).to eq('Dark Reign') 77 | end 78 | end 79 | 80 | describe '#creator_series' do 81 | before do 82 | stub_get('creators/593/series?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'creators/creator_series.json') 83 | end 84 | 85 | it 'returns a Marvelite::API::Response object' do 86 | expect(client.creator_series(593)).to be_a(Marvelite::API::Response) 87 | end 88 | 89 | it 'Response object is populated with JSON from the /creators/:id/series endpoint' do 90 | expect(client.creator_series(593)["status"]).to eq("Ok") 91 | expect(client.creator_series(593)[:data][:results].size).to eq(20) 92 | end 93 | 94 | it 'accepts an Integer as creator id' do 95 | expect(client.creator_series(593)[:data][:results][0][:title]).to eq('Age of Apocalypse (2011 - Present)') 96 | end 97 | end 98 | 99 | describe '#creator_stories' do 100 | before do 101 | stub_get('creators/593/stories?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'creators/creator_stories.json') 102 | end 103 | 104 | it 'returns a Marvelite::API::Response object' do 105 | expect(client.creator_stories(593)).to be_a(Marvelite::API::Response) 106 | end 107 | 108 | it 'Response object is populated with JSON from the /creators/:id/stories endpoint' do 109 | expect(client.creator_stories(593)["status"]).to eq("Ok") 110 | expect(client.creator_stories(593)[:data][:results].size).to eq(20) 111 | end 112 | 113 | it 'accepts an Integer as creator id' do 114 | expect(client.creator_stories(593)[:data][:results][0][:title]).to eq('5 of 6 xLS') 115 | end 116 | end 117 | end 118 | end 119 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Marvelite 2 | 3 | [![Build Status](https://travis-ci.org/antillas21/marvelite.svg?branch=master)](https://travis-ci.org/antillas21/marvelite) 4 | 5 | Simple Ruby wrapper to communicate with the Marvel Comics API. 6 | 7 | ## Installation 8 | 9 | Add this line to your application's Gemfile: 10 | 11 | gem 'marvelite' 12 | 13 | And then execute: 14 | 15 | $ bundle 16 | 17 | Or install it yourself as: 18 | 19 | $ gem install marvelite 20 | 21 | ## Contents 22 | 23 | * [Usage](#usage) 24 | * [Responses](#responses) 25 | 26 | ## Usage 27 | 28 | Please register first in the [Marvel Comics Developer 29 | Portal](http://developer.marvel.com/) to get your API credentials (a public key 30 | and a private key, you'll need them both to configure and instantiate a client). 31 | 32 | ### Instantiate a client 33 | 34 | ```ruby 35 | client = Marvelite::API::Client.new( :public_key => 'abcd1234', :private_key => '5678efgh') 36 | 37 | # fetch a list of characters 38 | client.characters 39 | client.characters(:name => 'Spider-Man') 40 | client.characters(:limit => 10, :offset => 400, :orderBy => 'name') 41 | 42 | # fetch a single character 43 | client.character(1009610) 44 | client.character('Spider-Man') 45 | 46 | # fetch a list of comics 47 | client.comics 48 | client.comics(:format => 'graphic novel', :limit => 10, :offset => 20 }) 49 | 50 | # fetch a single comic 51 | client.comic(40128) 52 | 53 | # fetch a list of comic characters 54 | client.comic_characters(40128) 55 | client.comic_characters(40128, :orderBy => 'name', :limit => 30, :offset => 20) 56 | 57 | # fetch a list of creators 58 | client.creators 59 | client.creators(:lastName => 'Romita') 60 | 61 | # fetch a creator 62 | client.creators(214) 63 | 64 | # fetch a creator comics 65 | client.creator_comics(214) 66 | 67 | # fetch a list of events 68 | client.events 69 | client.events(:name => 'Acts of Vengeance') 70 | client.events(:orderBy => 'name') 71 | 72 | # fetch a single event 73 | client.event(116) 74 | client.event('Acts of Vengeance!') 75 | 76 | # fetch a list of comics in an event 77 | client.event_comics(116) 78 | client.event_comics('Acts of Vengeance!') 79 | client.event_comics(116, :format => 'graphic novel', :orderBy => 'title', :limit => 10) 80 | client.event_comics('Acts of Vengeance!', :format => 'graphic novel', :orderBy => 'title', :limit => 10) 81 | 82 | # fetch a list of series 83 | client.series 84 | client.series(:title => 'Spider-Man') 85 | client.series(:orderBy => 'title') 86 | 87 | # fetch a single serie 88 | client.serie(2069) 89 | 90 | # fetch a list of comics in a serie 91 | client.series_comics(2069) 92 | client.series_comics(2069, :format => 'graphic novel', :orderBy => 'title', :limit => 10) 93 | 94 | # fetch a list of stories 95 | client.stories 96 | client.stories(:limit => 50, :offset => 100) 97 | client.stories(:orderBy => 'id') 98 | 99 | # fetch a single story 100 | client.story(2210) 101 | 102 | # fetch a list of comics in a story 103 | client.story_comics(2210) 104 | client.story_comics(2210, :format => 'graphic novel', :orderBy => 'title', :limit => 10) 105 | ``` 106 | 107 | See the list of [available 108 | methods](https://github.com/antillas21/marvelite/wiki/Documentation) in the 109 | wiki. 110 | 111 | ## Responses 112 | 113 | Most requests to the API, return a `Marvelite::API::Response` object if 114 | successful or a `Marvelite::API::ErrorResponse` if API response returns an 115 | error. These objects are nothing more than the raw API response enhanced with 116 | Hashie methods. 117 | 118 | This way you gain several adavantages to manipulate the response, like: 119 | 120 | ```ruby 121 | # HashWithIndifferentAccess like functionality 122 | response[:data][:results][0][:name] 123 | response["data"]["results"][0]["name"] 124 | 125 | # Top level methods 126 | response.data 127 | response.data[:results] 128 | ``` 129 | 130 | You can always access the raw response returned by the API by calling the 131 | `#raw_response` attribute of the response. Example: 132 | 133 | ```ruby 134 | hero = client.character(1009610) 135 | hero.raw_response 136 | #=> { "code"=>200, "status"=>"Ok", "copyright"=>"© 2014 MARVEL", ... } 137 | ``` 138 | Difference between `response` and `raw_reponse`, is that `raw_response` does 139 | not include `Hashie` helpers, and thus you need to navigate it as a plain old 140 | Hash. 141 | ```ruby 142 | hero.raw_response['data'][0]['name'] 143 | #=> "Spider-Man" 144 | ``` 145 | 146 | ## Etags and Gzip support 147 | 148 | Support for Etags is built into every endpoint: 149 | 150 | ```ruby 151 | first_response = client.series 152 | first_response.status # => 200 153 | 154 | second_response = client.series headers: { 'If-None-Match' => first_response.etag } 155 | second_response.status # => 304 156 | ``` 157 | 158 | Gzip compressed responses are enabled by default. But if you feel more 159 | comfortable passing it explicitely, you can do it like this: 160 | 161 | ```ruby 162 | gzipped_response = client.series(:headers => {'Accept-Encoding' => 'gzip'}) 163 | #=> Faster response hash from Marvel's API series endpoint. :) 164 | ``` 165 | 166 | 167 | ## Contributing 168 | 169 | 1. Fork it 170 | 2. Create your feature branch (`git checkout -b my-new-feature`) 171 | 3. Commit your changes (`git commit -am 'Add some feature'`) 172 | 4. Push to the branch (`git push origin my-new-feature`) 173 | 5. Create new Pull Request 174 | -------------------------------------------------------------------------------- /spec/marvelite/api/client_stories_endpoints_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Marvelite::API::Client do 4 | context "Stories Endpoints" do 5 | let(:client) { marvelite_test_client } 6 | 7 | describe '#stories' do 8 | before do 9 | stub_get('stories?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'stories/stories.json') 10 | end 11 | 12 | it 'returns a Marvelite::API::Response object' do 13 | expect(client.stories).to be_a(Marvelite::API::Response) 14 | end 15 | 16 | it 'Response object is populated with JSON from the /stories endpoint' do 17 | expect(client.stories["status"]).to eq("Ok") 18 | expect(client.stories[:data][:results].size).to eq(20) 19 | end 20 | end 21 | 22 | describe '#story' do 23 | before do 24 | stub_get('stories/2210?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'stories/story.json') 25 | end 26 | it 'returns a Marvelite::API::Response object' do 27 | expect(client.story(2210)).to be_a(Marvelite::API::Response) 28 | end 29 | 30 | it 'Response object is populated with JSON from the /stories/:id endpoint' do 31 | expect(client.story(2210)[:data][:results][0][:title]).to eq('2 of 3 - House of M') 32 | end 33 | 34 | it 'accepts an Integer as story id' do 35 | expect(client.story(2210)[:data][:results][0][:title]).to eq('2 of 3 - House of M') 36 | end 37 | end 38 | 39 | describe '#story_characters' do 40 | before do 41 | stub_get('stories/2210/characters?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'stories/story_characters.json') 42 | end 43 | 44 | it 'returns a Marvelite::API::Response object' do 45 | expect(client.story_characters(2210)).to be_a(Marvelite::API::Response) 46 | end 47 | 48 | it 'Response object is populated with JSON from the /stories/:id/characters endpoint' do 49 | expect(client.story_characters(2210)["status"]).to eq("Ok") 50 | expect(client.story_characters(2210)[:data][:results].size).to eq(3) 51 | end 52 | 53 | it 'accepts an Integer as story id' do 54 | expect(client.story_characters(2210)[:data][:results][0][:name]).to eq('Mystique (House of M)') 55 | end 56 | end 57 | 58 | describe '#story_comics' do 59 | before do 60 | stub_get('stories/2210/comics?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'stories/story_comics.json') 61 | end 62 | 63 | it 'returns a Marvelite::API::Response object' do 64 | expect(client.story_comics(2210)).to be_a(Marvelite::API::Response) 65 | end 66 | 67 | it 'Response object is populated with JSON from the /stories/:id/comics endpoint' do 68 | expect(client.story_comics(2210)["status"]).to eq("Ok") 69 | expect(client.story_comics(2210)[:data][:results].size).to eq(1) 70 | end 71 | 72 | it 'accepts an Integer as story id' do 73 | expect(client.story_comics(2210)[:data][:results][0][:title]).to eq('Wolverine (2003) #34') 74 | end 75 | end 76 | 77 | describe '#story_creators' do 78 | before do 79 | stub_get('stories/2210/creators?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'stories/story_creators.json') 80 | end 81 | 82 | it 'returns a Marvelite::API::Response object' do 83 | expect(client.story_creators(2210)).to be_a(Marvelite::API::Response) 84 | end 85 | 86 | it 'Response object is populated with JSON from the /stories/:id/creators endpoint' do 87 | expect(client.story_creators(2210)["status"]).to eq("Ok") 88 | expect(client.story_creators(2210)[:data][:results].size).to eq(1) 89 | end 90 | 91 | it 'accepts an Integer as story id' do 92 | expect(client.story_creators(2210)[:data][:results][0][:fullName]).to eq('Kaare Andrews') 93 | end 94 | end 95 | 96 | describe '#story_events' do 97 | before do 98 | stub_get('stories/2210/events?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'stories/story_events.json') 99 | end 100 | 101 | it 'returns a Marvelite::API::Response object' do 102 | expect(client.story_events(2210)).to be_a(Marvelite::API::Response) 103 | end 104 | 105 | it 'Response object is populated with JSON from the /stories/:id/events endpoint' do 106 | expect(client.story_events(2210)["status"]).to eq("Ok") 107 | expect(client.story_events(2210)[:data][:results].size).to eq(1) 108 | end 109 | 110 | it 'accepts an Integer as story id' do 111 | expect(client.story_events(2210)[:data][:results][0][:title]).to eq('House of M') 112 | end 113 | end 114 | 115 | describe '#story_series' do 116 | before do 117 | stub_get('stories/2210/series?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'stories/story_series.json') 118 | end 119 | 120 | it 'returns a Marvelite::API::Response object' do 121 | expect(client.story_series(2210)).to be_a(Marvelite::API::Response) 122 | end 123 | 124 | it 'Response object is populated with JSON from the /stories/:id/series endpoint' do 125 | expect(client.story_series(2210)["status"]).to eq("Ok") 126 | expect(client.story_series(2210)[:data][:results].size).to eq(1) 127 | end 128 | 129 | it 'accepts an Integer as story id' do 130 | expect(client.story_series(2210)[:data][:results][0][:title]).to eq('Wolverine (2003 - 2009)') 131 | end 132 | end 133 | end 134 | end -------------------------------------------------------------------------------- /spec/marvelite/api/client_series_endpoints_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Marvelite::API::Client do 4 | context "Series Endpoints" do 5 | let(:client) { marvelite_test_client } 6 | 7 | describe '#series' do 8 | before do 9 | stub_get('series?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'series/series.json') 10 | end 11 | 12 | it 'returns a Marvelite::API::Response object' do 13 | expect(client.series).to be_a(Marvelite::API::Response) 14 | end 15 | 16 | it 'Response object is populated with JSON from the /series endpoint' do 17 | expect(client.series["status"]).to eq("Ok") 18 | expect(client.series[:data][:results].size).to eq(20) 19 | end 20 | end 21 | 22 | describe '#serie' do 23 | before do 24 | stub_get('series/2069?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'series/serie.json') 25 | stub_get('series?title=Spider-Man!&apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'series/serie.json') 26 | end 27 | it 'returns a Marvelite::API::Response object' do 28 | expect(client.serie(2069)).to be_a(Marvelite::API::Response) 29 | end 30 | 31 | it 'Response object is populated with JSON from the /series/:id endpoint' do 32 | expect(client.serie(2069)[:data][:results][0][:title]).to eq('Spider-Man (1990 - 1998)') 33 | end 34 | 35 | it 'accepts an Integer as series id' do 36 | expect(client.serie(2069)[:data][:results][0][:title]).to eq('Spider-Man (1990 - 1998)') 37 | end 38 | end 39 | 40 | describe '#series_characters' do 41 | before do 42 | stub_get('series/2069/characters?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'series/series_characters.json') 43 | end 44 | 45 | it 'returns a Marvelite::API::Response object' do 46 | expect(client.series_characters(2069)).to be_a(Marvelite::API::Response) 47 | end 48 | 49 | it 'Response object is populated with JSON from the /series/:id/characters endpoint' do 50 | expect(client.series_characters(2069)["status"]).to eq("Ok") 51 | expect(client.series_characters(2069)[:data][:results].size).to eq(16) 52 | end 53 | 54 | it 'accepts an Integer as series id' do 55 | expect(client.series_characters(2069)[:data][:results][0][:name]).to eq('Adam Warlock') 56 | end 57 | end 58 | 59 | describe '#series_comics' do 60 | before do 61 | stub_get('series/2069/comics?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'series/series_comics.json') 62 | end 63 | 64 | it 'returns a Marvelite::API::Response object' do 65 | expect(client.series_comics(2069)).to be_a(Marvelite::API::Response) 66 | end 67 | 68 | it 'Response object is populated with JSON from the /series/:id/comics endpoint' do 69 | expect(client.series_comics(2069)["status"]).to eq("Ok") 70 | expect(client.series_comics(2069)[:data][:results].size).to eq(20) 71 | end 72 | 73 | it 'accepts an Integer as series id' do 74 | expect(client.series_comics(2069)[:data][:results][0][:title]).to eq('Spider-Man (1990) #98') 75 | end 76 | end 77 | 78 | describe '#series_creators' do 79 | before do 80 | stub_get('series/2069/creators?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'series/series_creators.json') 81 | end 82 | 83 | it 'returns a Marvelite::API::Response object' do 84 | expect(client.series_creators(2069)).to be_a(Marvelite::API::Response) 85 | end 86 | 87 | it 'Response object is populated with JSON from the /series/:id/creators endpoint' do 88 | expect(client.series_creators(2069)["status"]).to eq("Ok") 89 | expect(client.series_creators(2069)[:data][:results].size).to eq(20) 90 | end 91 | 92 | it 'accepts an Integer as series id' do 93 | expect(client.series_creators(2069)[:data][:results][0][:fullName]).to eq('Comicraft') 94 | end 95 | end 96 | 97 | describe '#series_events' do 98 | before do 99 | stub_get('series/2069/events?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'series/series_events.json') 100 | end 101 | 102 | it 'returns a Marvelite::API::Response object' do 103 | expect(client.series_events(2069)).to be_a(Marvelite::API::Response) 104 | end 105 | 106 | it 'Response object is populated with JSON from the /series/:id/events endpoint' do 107 | expect(client.series_events(2069)["status"]).to eq("Ok") 108 | expect(client.series_events(2069)[:data][:results].size).to eq(3) 109 | end 110 | 111 | it 'accepts an Integer as series id' do 112 | expect(client.series_events(2069)[:data][:results][0][:title]).to eq('Infinity War') 113 | end 114 | end 115 | 116 | describe '#series_stories' do 117 | before do 118 | stub_get('series/2069/stories?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'series/series_stories.json') 119 | end 120 | 121 | it 'returns a Marvelite::API::Response object' do 122 | expect(client.series_stories(2069)).to be_a(Marvelite::API::Response) 123 | end 124 | 125 | it 'Response object is populated with JSON from the /series/:id/stories endpoint' do 126 | expect(client.series_stories(2069)["status"]).to eq("Ok") 127 | expect(client.series_stories(2069)[:data][:results].size).to eq(20) 128 | end 129 | 130 | it 'accepts an Integer as series id' do 131 | expect(client.series_stories(2069)[:data][:results][0][:title]).to eq('Cover #23741') 132 | end 133 | end 134 | end 135 | end -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Changelog 2 | 3 | ### 0.1.3 4 | * retrieve story series by connecting to the API's `/stories/:id/series` endpoint 5 | (contributed by [O-I](https://github.com/O-I)). 6 | * Spec cleaning courtesy of [O-I](https://github.com/O-I). 7 | * Removed Rubinius from `.travis.yml`. 8 | 9 | 10 | ### 0.1.2 11 | * Adds `#raw_response` to store the original response from the API inside 12 | a `Marvelite::API::Response` instance. Author: [Jon Allured](https://github.com/jonallured) 13 | 14 | ### 0.1.1 15 | * Gzipped responses are enabled by default. 16 | * All API requests include `{ 'Accept-Encoding' = 'gzip' }` which translates 17 | in faster and band-width conscious responses. 18 | 19 | ### 0.1.0 20 | * Adds Travis CI support. 21 | * Support for Etags and Gzip compression. Infinite thanks to [Jon Allured](https://github.com/jonallured) for this contribution. 22 | * Refactorings and cleanups, courtesy of [Jon Allured](https://github.com/jonallured) 23 | 24 | ### 0.0.9 25 | * Adds the following endpoints (contributed by: [Patrick Hereford (@phereford)](https://github.com/phereford)): 26 | * retrieve creators by connecting to the API's `/creators` endpoint 27 | * retieve a creator by connecting to the API's `/creators/:id` enpoint 28 | * retrieve creator connecting to the API's `/creators/:id/comics` endpoint. 29 | * retrieve creator events by connecting to the API's `/creators/:id/events` endpoint. 30 | * retrieve creator series by connecting to the API's `/creators/:id/series` endpoint. 31 | * retrieve creator stories by connecting to the API's `/creators/:id/stories` endpoint. 32 | * Pinpoints dependencies versions. 33 | 34 | 35 | ### 0.0.8 36 | * Fixes a problem where the `Marvelite::API::Router` was replacing the value of its return path string when asked for a route. Thanks to [Patrick Hereford (@phereford)](https://github.com/phereford) for reporting the issue. 37 | 38 | ### 0.0.7 39 | * Adds the following endpoints: 40 | * retrieve stories by connecting to the API's `/stories` endpoint 41 | * retieve a story by connecting to the API's `/stories/:id` enpoint 42 | * retrieve story characters by connecting to the API's `/stories/:id/characters` endpoint. 43 | * retrieve story comics by connecting to the API's `/stories/:id/comics` endpoint. 44 | * retrieve story creators by connecting to the API's `/stories/:id/creators` endpoint. 45 | * retrieve story events by connecting to the API's `/stories/:id/events` endpoint. 46 | 47 | ### 0.0.6 48 | * Rewrites `Marvelite::API::Client` to allow for self discovery of available methods, depending on the `Marvelite::API::Router` injected at initialization. 49 | * Adds the following endpoints: 50 | * retrieve series by connecting to the API's `/series` endpoint 51 | * retieve a serie by connecting to the API's `/series/:id` enpoint 52 | * retrieve serie characters by connecting to the API's `/series/:id/characters` endpoint. 53 | * retrieve serie comics by connecting to the API's `/series/:id/comics` endpoint. 54 | * retrieve serie creators by connecting to the API's `/series/:id/creators` endpoint. 55 | * retrieve serie events by connecting to the API's `/series/:id/events` endpoint. 56 | * retrieve serie stories by connecting to the API's `/series/:id/stories` endpoint. 57 | 58 | 59 | ### 0.0.5 60 | * Rewrites `Marvelite::API::Router` class to make flexible to future API versioning changes from Marvel. 61 | * Adds the following endpoints: 62 | * retrieve events by connecting to the API's `/events` endpoint 63 | * retieve a event by connecting to the API's `/events/:id` enpoint 64 | * retrieve event characters by connecting to the API's `/events/:id/characters` endpoint. 65 | * retrieve event comics by connecting to the API's `/events/:id/comics` endpoint. 66 | * retrieve event creators by connecting to the API's `/events/:id/creators` endpoint. 67 | * retrieve event series by connecting to the API's `/events/:id/series` endpoint. 68 | * retrieve event stories by connecting to the API's `/events/:id/stories` endpoint. 69 | * Adds helper method to retrieve event sub-resources passing an event name instead of a numeric id. 70 | 71 | 72 | ### 0.0.4 73 | * Adds the following endpoints: 74 | * retrieve comics by connecting to the API's `/comics` endpoint 75 | * retieve a comic by connecting to the API's `/comics/:id` enpoint 76 | * retrieve comic characters by connecting to the API's `/comics/:id/characters` endpoint. 77 | * retrieve comic creators by connecting to the API's `/comics/:id/creators` endpoint. 78 | * retrieve comic events by connecting to the API's `/comics/:id/events` endpoint. 79 | * retrieve comic stories by connecting to the API's `/comics/:id/stories` endpoint. 80 | 81 | ### 0.0.3 82 | * Adds basic testing setup 83 | * Adds the ability to retrieve: 84 | * character comics by passing a character name instead of a numeric id 85 | * character events by passing a character name instead of a numeric id 86 | * character series by passing a character name instead of a numeric id 87 | * character stories by passing a character name instead of a numeric id 88 | 89 | ### 0.0.2 90 | * Adds the following endpoints: 91 | * retrieve character comics by connecting to the API's `/characters/:id/comics` endpoint 92 | * retrieve character events by connecting to the API's `/characters/:id/events` endpoint 93 | * retrieve character series by connecting to the API's `/characters/:id/series` endpoint 94 | * retrieve character stories by connecting to the API's `/characters/:id/stories` endpoint 95 | 96 | ### 0.0.1 97 | * Initial release and just two endpoints: 98 | * retrieve characters by connecting to the API's `/characters` endpoint 99 | * retrieve a character by connecting to the API's `/characters/:id` endpoint 100 | -------------------------------------------------------------------------------- /spec/marvelite/api/client_characters_endpoints_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Marvelite::API::Client do 4 | context "Characters Endpoints" do 5 | let(:client) { marvelite_test_client } 6 | 7 | describe '#characters' do 8 | before do 9 | stub_get('characters?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'characters/characters.json') 10 | end 11 | 12 | it 'returns a Marvelite::API::Response object' do 13 | expect(client.characters).to be_a(Marvelite::API::Response) 14 | end 15 | 16 | it 'Response object is populated with JSON from the /characters endpoint' do 17 | expect(client.characters["status"]).to eq("Ok") 18 | expect(client.characters[:data][:results].size).to eq(20) 19 | end 20 | end 21 | 22 | describe '#character' do 23 | before do 24 | stub_get('characters?name=Spider-Man&apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'characters/character.json') 25 | stub_get('characters/1009610?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'characters/character.json') 26 | stub_get('characters/1009227?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'characters/character_2.json') 27 | end 28 | it 'returns a Marvelite::API::Response object' do 29 | expect(client.character(1009610)).to be_a(Marvelite::API::Response) 30 | end 31 | 32 | it 'Response object is populated with JSON from the /characters/:id endpoint' do 33 | expect(client.character(1009610)[:data][:results][0][:name]).to eq('Spider-Man') 34 | end 35 | 36 | it 'accepts an Integer as character id' do 37 | expect(client.character(1009610)[:data][:results][0][:name]).to eq('Spider-Man') 38 | expect(client.character(1009227)[:data][:results][0][:name]).to eq('Carnage') 39 | end 40 | 41 | it 'accepts a String as character name' do 42 | expect(client.character('Spider-Man')[:data][:results][0][:name]).to eq('Spider-Man') 43 | end 44 | end 45 | 46 | describe '#character_comics' do 47 | before do 48 | stub_get('characters/1009610/comics?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'characters/character_comics.json') 49 | end 50 | 51 | it 'returns a Marvelite::API::Response object' do 52 | expect(client.character_comics(1009610)).to be_a(Marvelite::API::Response) 53 | end 54 | 55 | it 'Response object is populated with JSON from the /characters/:id/comics endpoint' do 56 | expect(client.character_comics(1009610)["status"]).to eq("Ok") 57 | expect(client.character_comics(1009610)[:data][:results].size).to eq(20) 58 | end 59 | 60 | it 'accepts an Integer as character id' do 61 | expect(client.character_comics(1009610)[:data][:results][0][:title]).to eq('Superior Spider-Man (2013) #22') 62 | end 63 | 64 | it 'accepts a String as character id' do 65 | expect(client.character_comics('Spider-Man')["status"]).to eq("Ok") 66 | expect(client.character_comics('Spider-Man')[:data][:results].size).to eq(20) 67 | end 68 | end 69 | 70 | describe '#character_events' do 71 | before do 72 | stub_get('characters/1009610/events?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'characters/character_events.json') 73 | end 74 | 75 | it 'returns a Marvelite::API::Response object' do 76 | expect(client.character_events(1009610)).to be_a(Marvelite::API::Response) 77 | end 78 | 79 | it 'Response object is populated with JSON from the /characters/:id/events endpoint' do 80 | expect(client.character_events(1009610)["status"]).to eq("Ok") 81 | expect(client.character_events(1009610)[:data][:results].size).to eq(20) 82 | end 83 | 84 | it 'accepts an Integer as character id' do 85 | expect(client.character_events(1009610)[:data][:results][0][:title]).to eq('Acts of Vengeance!') 86 | end 87 | 88 | it 'accepts a String as character id' do 89 | expect(client.character_comics('Spider-Man')["status"]).to eq("Ok") 90 | expect(client.character_comics('Spider-Man')[:data][:results].size).to eq(20) 91 | end 92 | end 93 | 94 | describe '#character_series' do 95 | before do 96 | stub_get('characters/1009610/series?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'characters/character_series.json') 97 | end 98 | 99 | it 'returns a Marvelite::API::Response object' do 100 | expect(client.character_series(1009610)).to be_a(Marvelite::API::Response) 101 | end 102 | 103 | it 'Response object is populated with JSON from the /characters/:id/series endpoint' do 104 | expect(client.character_series(1009610)["status"]).to eq("Ok") 105 | expect(client.character_series(1009610)[:data][:results].size).to eq(20) 106 | end 107 | 108 | it 'accepts an Integer as character id' do 109 | expect(client.character_series(1009610)[:data][:results][0][:title]).to eq('A+X (2012 - Present)') 110 | end 111 | 112 | it 'accepts a String as character id' do 113 | expect(client.character_comics('Spider-Man')["status"]).to eq("Ok") 114 | expect(client.character_comics('Spider-Man')[:data][:results].size).to eq(20) 115 | end 116 | end 117 | 118 | describe '#character_stories' do 119 | before do 120 | stub_get('characters?name=Spider-Man&apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'characters/character.json') 121 | stub_get('characters/1009610/stories?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'characters/character_stories.json') 122 | end 123 | 124 | it 'returns a Marvelite::API::Response object' do 125 | expect(client.character_stories(1009610)).to be_a(Marvelite::API::Response) 126 | end 127 | 128 | it 'Response object is populated with JSON from the /characters/:id/stories endpoint' do 129 | expect(client.character_stories(1009610)["status"]).to eq("Ok") 130 | expect(client.character_stories(1009610)[:data][:results].size).to eq(20) 131 | end 132 | 133 | it 'accepts an Integer as character id' do 134 | expect(client.character_stories(1009610)[:data][:results][0][:title]).to eq('Interior #483') 135 | end 136 | 137 | it 'accepts a String as character id' do 138 | expect(client.character_comics('Spider-Man')["status"]).to eq("Ok") 139 | expect(client.character_comics('Spider-Man')[:data][:results].size).to eq(20) 140 | end 141 | end 142 | end 143 | end -------------------------------------------------------------------------------- /spec/marvelite/api/client_events_endpoints_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Marvelite::API::Client do 4 | context "Events Endpoints" do 5 | let(:client) { marvelite_test_client } 6 | 7 | describe '#events' do 8 | before do 9 | stub_get('events?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'events/events.json') 10 | end 11 | 12 | it 'returns a Marvelite::API::Response object' do 13 | expect(client.events).to be_a(Marvelite::API::Response) 14 | end 15 | 16 | it 'Response object is populated with JSON from the /events endpoint' do 17 | expect(client.events["status"]).to eq("Ok") 18 | expect(client.events[:data][:results].size).to eq(20) 19 | end 20 | end 21 | 22 | describe '#event' do 23 | before do 24 | stub_get('events/116?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'events/event.json') 25 | stub_get('events?name=Acts%20of%20Vengeance!&apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'events/event.json') 26 | end 27 | it 'returns a Marvelite::API::Response object' do 28 | expect(client.event(116)).to be_a(Marvelite::API::Response) 29 | end 30 | 31 | it 'Response object is populated with JSON from the /events/:id endpoint' do 32 | expect(client.event(116)[:data][:results][0][:title]).to eq('Acts of Vengeance!') 33 | end 34 | 35 | it 'accepts an Integer as event id' do 36 | expect(client.event(116)[:data][:results][0][:title]).to eq('Acts of Vengeance!') 37 | end 38 | 39 | it 'accepts a String as event name' do 40 | expect(client.event('Acts of Vengeance!')[:data][:results][0][:title]).to eq('Acts of Vengeance!') 41 | end 42 | end 43 | 44 | describe '#event_characters' do 45 | before do 46 | stub_get('events/116/characters?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'events/event_characters.json') 47 | end 48 | 49 | it 'returns a Marvelite::API::Response object' do 50 | expect(client.event_characters(116)).to be_a(Marvelite::API::Response) 51 | end 52 | 53 | it 'Response object is populated with JSON from the /events/:id/characters endpoint' do 54 | expect(client.event_characters(116)["status"]).to eq("Ok") 55 | expect(client.event_characters(116)[:data][:results].size).to eq(20) 56 | end 57 | 58 | it 'accepts an Integer as event id' do 59 | expect(client.event_characters(116)[:data][:results][0][:name]).to eq('Alpha Flight') 60 | end 61 | 62 | it 'accepts a String as event id' do 63 | expect(client.event_characters('Acts of Vengeance!')[:data][:results][0][:name]).to eq('Alpha Flight') 64 | end 65 | end 66 | 67 | describe '#event_comics' do 68 | before do 69 | stub_get('events/116/comics?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'events/event_comics.json') 70 | end 71 | 72 | it 'returns a Marvelite::API::Response object' do 73 | expect(client.event_comics(116)).to be_a(Marvelite::API::Response) 74 | end 75 | 76 | it 'Response object is populated with JSON from the /events/:id/comics endpoint' do 77 | expect(client.event_comics(116)["status"]).to eq("Ok") 78 | expect(client.event_comics(116)[:data][:results].size).to eq(20) 79 | end 80 | 81 | it 'accepts an Integer as event id' do 82 | expect(client.event_comics(116)[:data][:results][0][:title]).to eq('Avengers West Coast: Darker than Scarlet (Trade Paperback)') 83 | end 84 | 85 | it 'accepts a String as event id' do 86 | expect(client.event_comics('Acts of Vengeance!')[:data][:results][0][:title]).to eq('Avengers West Coast: Darker than Scarlet (Trade Paperback)') 87 | end 88 | end 89 | 90 | describe '#event_creators' do 91 | before do 92 | stub_get('events/116/creators?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'events/event_creators.json') 93 | end 94 | 95 | it 'returns a Marvelite::API::Response object' do 96 | expect(client.event_creators(116)).to be_a(Marvelite::API::Response) 97 | end 98 | 99 | it 'Response object is populated with JSON from the /events/:id/creators endpoint' do 100 | expect(client.event_creators(116)["status"]).to eq("Ok") 101 | expect(client.event_creators(116)[:data][:results].size).to eq(20) 102 | end 103 | 104 | it 'accepts an Integer as event id' do 105 | expect(client.event_creators(116)[:data][:results][0][:fullName]).to eq('Jeff Albrecht') 106 | end 107 | 108 | it 'accepts a String as event id' do 109 | expect(client.event_creators('Acts of Vengeance!')[:data][:results][0][:fullName]).to eq('Jeff Albrecht') 110 | end 111 | end 112 | 113 | describe '#event_series' do 114 | before do 115 | stub_get('events/116/series?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'events/event_stories.json') 116 | end 117 | 118 | it 'returns a Marvelite::API::Response object' do 119 | expect(client.event_series(116)).to be_a(Marvelite::API::Response) 120 | end 121 | 122 | it 'Response object is populated with JSON from the /events/:id/series endpoint' do 123 | expect(client.event_series(116)["status"]).to eq("Ok") 124 | expect(client.event_series(116)[:data][:results].size).to eq(20) 125 | end 126 | 127 | it 'accepts an Integer as event id' do 128 | expect(client.event_series(116)[:data][:results][0][:title]).to eq('Cover #12960') 129 | end 130 | 131 | it 'accepts a String as event id' do 132 | expect(client.event_series('Acts of Vengeance!')[:data][:results][0][:title]).to eq('Cover #12960') 133 | end 134 | end 135 | 136 | describe '#event_stories' do 137 | before do 138 | stub_get('events/116/stories?apikey=123456&ts=1&hash=d4f1bab013916a533ef31e3ad5fb0887', 'events/event_stories.json') 139 | end 140 | 141 | it 'returns a Marvelite::API::Response object' do 142 | expect(client.event_stories(116)).to be_a(Marvelite::API::Response) 143 | end 144 | 145 | it 'Response object is populated with JSON from the /events/:id/stories endpoint' do 146 | expect(client.event_stories(116)["status"]).to eq("Ok") 147 | expect(client.event_stories(116)[:data][:results].size).to eq(20) 148 | end 149 | 150 | it 'accepts an Integer as event id' do 151 | expect(client.event_stories(116)[:data][:results][0][:title]).to eq('Cover #12960') 152 | end 153 | 154 | it 'accepts a String as event id' do 155 | expect(client.event_stories('Acts of Vengeance!')[:data][:results][0][:title]).to eq('Cover #12960') 156 | end 157 | end 158 | end 159 | end -------------------------------------------------------------------------------- /spec/fixtures/comics/comic_stories.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 200, 3 | "status": "Ok", 4 | "etag": "3978488a0cc6811a335363cf2072b66ca911f7f8", 5 | "data": { 6 | "offset": 0, 7 | "limit": 20, 8 | "total": 2, 9 | "count": 2, 10 | "results": [ 11 | { 12 | "id": 91053, 13 | "title": "Cover #91053", 14 | "description": "", 15 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/91053", 16 | "type": "cover", 17 | "modified": "2013-02-01T15:45:47-0500", 18 | "thumbnail": null, 19 | "creators": { 20 | "available": 1, 21 | "collectionURI": "http://gateway.marvel.com/v1/public/stories/91053/creators", 22 | "items": [ 23 | { 24 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/11879", 25 | "name": "Stephen Wacker", 26 | "role": "editor" 27 | } 28 | ], 29 | "returned": 1 30 | }, 31 | "characters": { 32 | "available": 1, 33 | "collectionURI": "http://gateway.marvel.com/v1/public/stories/91053/characters", 34 | "items": [ 35 | { 36 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009610", 37 | "name": "Spider-Man" 38 | } 39 | ], 40 | "returned": 1 41 | }, 42 | "series": { 43 | "available": 1, 44 | "collectionURI": { 45 | "service": "comic_storySeries", 46 | "id": 91053 47 | }, 48 | "items": [ 49 | { 50 | "resourceURI": "http://gateway.marvel.com/v1/public/series/454", 51 | "name": "Amazing Spider-Man (1999 - 2013)" 52 | } 53 | ], 54 | "returned": 1 55 | }, 56 | "comics": { 57 | "available": 1, 58 | "collectionURI": "http://gateway.marvel.com/v1/public/stories/91053/comics", 59 | "items": [ 60 | { 61 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/40128", 62 | "name": "Amazing Spider-Man (1999) #700" 63 | } 64 | ], 65 | "returned": 1 66 | }, 67 | "events": { 68 | "available": 0, 69 | "collectionURI": "http://gateway.marvel.com/v1/public/stories/91053/events", 70 | "items": [], 71 | "returned": 0 72 | }, 73 | "originalIssue": { 74 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/40128", 75 | "name": "Amazing Spider-Man (1999) #700" 76 | } 77 | }, 78 | { 79 | "id": 91054, 80 | "title": "Interior #91054", 81 | "description": "", 82 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/91054", 83 | "type": "story", 84 | "modified": "2011-04-08T01:30:13-0400", 85 | "thumbnail": null, 86 | "creators": { 87 | "available": 12, 88 | "collectionURI": "http://gateway.marvel.com/v1/public/stories/91054/creators", 89 | "items": [ 90 | { 91 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/105", 92 | "name": "Sal Buscema", 93 | "role": "inker" 94 | }, 95 | { 96 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/447", 97 | "name": "Victor Olazaba", 98 | "role": "inker" 99 | }, 100 | { 101 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/9461", 102 | "name": "Stephanie Buscema", 103 | "role": "artist" 104 | }, 105 | { 106 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/1141", 107 | "name": "Giuseppe Camuncoli", 108 | "role": "penciler" 109 | }, 110 | { 111 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/72", 112 | "name": "Humberto Ramos", 113 | "role": "penciler" 114 | }, 115 | { 116 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/430", 117 | "name": "Edgar Delgado", 118 | "role": "colorist" 119 | }, 120 | { 121 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/428", 122 | "name": "Antonio Fabela", 123 | "role": "colorist" 124 | }, 125 | { 126 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/6986", 127 | "name": "J. M. DeMatteis", 128 | "role": "writer" 129 | }, 130 | { 131 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/626", 132 | "name": "Dan Slott", 133 | "role": "writer" 134 | }, 135 | { 136 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/11788", 137 | "name": "Jennifer Van Meter", 138 | "role": "writer" 139 | }, 140 | { 141 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/452", 142 | "name": "Chris Eliopoulos", 143 | "role": "letterer" 144 | }, 145 | { 146 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/11879", 147 | "name": "Stephen Wacker", 148 | "role": "editor" 149 | } 150 | ], 151 | "returned": 12 152 | }, 153 | "characters": { 154 | "available": 0, 155 | "collectionURI": "http://gateway.marvel.com/v1/public/stories/91054/characters", 156 | "items": [], 157 | "returned": 0 158 | }, 159 | "series": { 160 | "available": 1, 161 | "collectionURI": { 162 | "service": "comic_storySeries", 163 | "id": 91054 164 | }, 165 | "items": [ 166 | { 167 | "resourceURI": "http://gateway.marvel.com/v1/public/series/454", 168 | "name": "Amazing Spider-Man (1999 - 2013)" 169 | } 170 | ], 171 | "returned": 1 172 | }, 173 | "comics": { 174 | "available": 1, 175 | "collectionURI": "http://gateway.marvel.com/v1/public/stories/91054/comics", 176 | "items": [ 177 | { 178 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/40128", 179 | "name": "Amazing Spider-Man (1999) #700" 180 | } 181 | ], 182 | "returned": 1 183 | }, 184 | "events": { 185 | "available": 0, 186 | "collectionURI": "http://gateway.marvel.com/v1/public/stories/91054/events", 187 | "items": [], 188 | "returned": 0 189 | }, 190 | "originalIssue": { 191 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/40128", 192 | "name": "Amazing Spider-Man (1999) #700" 193 | } 194 | } 195 | ] 196 | } 197 | } -------------------------------------------------------------------------------- /spec/fixtures/stories/story_comics.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 200, 3 | "status": "Ok", 4 | "etag": "1385865fc6ced47faf5406a2ad282de5cb99a889", 5 | "data": { 6 | "offset": 0, 7 | "limit": 20, 8 | "total": 1, 9 | "count": 1, 10 | "results": [ 11 | { 12 | "id": 2521, 13 | "digitalId": 2783, 14 | "title": "Wolverine (2003) #34", 15 | "issueNumber": 34, 16 | "variantDescription": "", 17 | "description": "He's one of the most crucial players in the House of M world, and for a good reason: Wolverine carries burdens too great for even the most powerful mutants to bear. Has it caused him to finally snap? ", 18 | "modified": "2013-07-01T14:56:59-0400", 19 | "isbn": "", 20 | "upc": "5960605458-03411", 21 | "diamondCode": "", 22 | "ean": "", 23 | "issn": "", 24 | "format": "Comic", 25 | "pageCount": 0, 26 | "textObjects": [ 27 | { 28 | "type": "issue_preview_text", 29 | "language": "en-us", 30 | "text": "He's one of the most crucial players in the House of M world, and for a good reason: Wolverine carries burdens too great for even the most powerful mutants to bear. Has it caused him to finally snap? " 31 | }, 32 | { 33 | "type": "issue_solicit_text", 34 | "language": "en-us", 35 | "text": "He's one of the most crucial players in the House of M world, and for a good reason: Wolverine carries burdens too great for even the most powerful mutants to bear. Has it caused him to finally snap? All the details you need to know about Wolverine's mysterious past and his place in the House of M can be found right here! The simmering war between Logan, Agent of S.H.I.E.L.D., and the leader of the human resistance movement, Nick Fury, comes to a boil. And only one of them’s going to come out alive. Parts 2 & 3 (of 3).\r
\r
32 PGS. (each)/ PARENTAL ADVISORY …$2.50 (each)\r
" 36 | } 37 | ], 38 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/2521", 39 | "urls": [ 40 | { 41 | "type": "detail", 42 | "url": "http://marvel.com/comics/issue/2521/wolverine_2003_34?utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 43 | }, 44 | { 45 | "type": "purchase", 46 | "url": "http://comicstore.marvel.com/Wolverine-34/digital-comic/2783?utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 47 | }, 48 | { 49 | "type": "reader", 50 | "url": "http://marvel.com/digitalcomics/view.htm?iid=2783&utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 51 | }, 52 | { 53 | "type": "inAppLink", 54 | "url": "http://applink.marvel.com/issue/2783?utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 55 | } 56 | ], 57 | "series": { 58 | "resourceURI": "http://gateway.marvel.com/v1/public/series/632", 59 | "name": "Wolverine (2003 - 2009)" 60 | }, 61 | "variants": [], 62 | "collections": [ 63 | { 64 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/3512", 65 | "name": "House of M: World of M (Trade Paperback)" 66 | } 67 | ], 68 | "collectedIssues": [], 69 | "dates": [ 70 | { 71 | "type": "onsaleDate", 72 | "date": "2005-10-12T00:00:00-0400" 73 | }, 74 | { 75 | "type": "focDate", 76 | "date": "-0001-11-30T00:00:00-0500" 77 | }, 78 | { 79 | "type": "unlimitedDate", 80 | "date": "2007-11-13T00:00:00-0500" 81 | }, 82 | { 83 | "type": "digitalPurchaseDate", 84 | "date": "2009-12-31T00:00:00-0500" 85 | } 86 | ], 87 | "prices": [ 88 | { 89 | "type": "printPrice", 90 | "price": 2.5 91 | }, 92 | { 93 | "type": "digitalPurchasePrice", 94 | "price": 1.99 95 | } 96 | ], 97 | "thumbnail": { 98 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/5/f0/4d24f5c53431b", 99 | "extension": "jpg" 100 | }, 101 | "images": [ 102 | { 103 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/c/40/4bc61e39c26eb", 104 | "extension": "jpg" 105 | } 106 | ], 107 | "creators": { 108 | "available": 6, 109 | "collectionURI": "http://gateway.marvel.com/v1/public/comics/2521/creators", 110 | "items": [ 111 | { 112 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/191", 113 | "name": "Kaare Andrews", 114 | "role": "penciller (cover)" 115 | }, 116 | { 117 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/8635", 118 | "name": "Randy Gentile", 119 | "role": "letterer" 120 | }, 121 | { 122 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/479", 123 | "name": "Paul Mounts", 124 | "role": "colorist" 125 | }, 126 | { 127 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/641", 128 | "name": "Javier Saltares", 129 | "role": "penciller" 130 | }, 131 | { 132 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/11501", 133 | "name": "Mark Texeira", 134 | "role": "inker" 135 | }, 136 | { 137 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/344", 138 | "name": "Daniel Way", 139 | "role": "writer" 140 | } 141 | ], 142 | "returned": 6 143 | }, 144 | "characters": { 145 | "available": 4, 146 | "collectionURI": "http://gateway.marvel.com/v1/public/comics/2521/characters", 147 | "items": [ 148 | { 149 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009368", 150 | "name": "Iron Man" 151 | }, 152 | { 153 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1010954", 154 | "name": "Mystique (House of M)" 155 | }, 156 | { 157 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009570", 158 | "name": "Sentinel" 159 | }, 160 | { 161 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009718", 162 | "name": "Wolverine" 163 | } 164 | ], 165 | "returned": 4 166 | }, 167 | "stories": { 168 | "available": 2, 169 | "collectionURI": { 170 | "service": "comic_issueStories", 171 | "id": 2521 172 | }, 173 | "items": [ 174 | { 175 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2210", 176 | "name": "2 of 3 - House of M", 177 | "type": "cover" 178 | }, 179 | { 180 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2211", 181 | "name": "2 of 3 - House of M", 182 | "type": "interiorStory" 183 | } 184 | ], 185 | "returned": 2 186 | }, 187 | "events": { 188 | "available": 1, 189 | "collectionURI": "http://gateway.marvel.com/v1/public/comics/2521/events", 190 | "items": [ 191 | { 192 | "resourceURI": "http://gateway.marvel.com/v1/public/events/251", 193 | "name": "House of M" 194 | } 195 | ], 196 | "returned": 1 197 | } 198 | } 199 | ] 200 | } 201 | } -------------------------------------------------------------------------------- /spec/fixtures/comics/comic.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 200, 3 | "status": "Ok", 4 | "etag": "7dff68517455de2200bde0216974bf20ae7f3dc3", 5 | "data": { 6 | "offset": 0, 7 | "limit": 20, 8 | "total": 1, 9 | "count": 1, 10 | "results": [ 11 | { 12 | "id": 40128, 13 | "digitalId": 28117, 14 | "title": "Amazing Spider-Man (1999) #700", 15 | "issueNumber": 700, 16 | "variantDescription": "", 17 | "description": null, 18 | "modified": "2013-02-01T15:45:55-0500", 19 | "isbn": "", 20 | "upc": 75960604716170000, 21 | "diamondCode": "OCT120626", 22 | "ean": "", 23 | "issn": "0274-5232", 24 | "format": "Comic", 25 | "pageCount": 104, 26 | "textObjects": [], 27 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/40128", 28 | "urls": [ 29 | { 30 | "type": "detail", 31 | "url": "http://marvel.com/comics/issue/40128/amazing_spider-man_1999_700?utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 32 | }, 33 | { 34 | "type": "purchase", 35 | "url": "http://comicstore.marvel.com/Amazing-Spider-Man-700/digital-comic/28117?utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 36 | }, 37 | { 38 | "type": "reader", 39 | "url": "http://marvel.com/digitalcomics/view.htm?iid=28117&utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 40 | }, 41 | { 42 | "type": "inAppLink", 43 | "url": "http://applink.marvel.com/issue/28117?utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 44 | } 45 | ], 46 | "series": { 47 | "resourceURI": "http://gateway.marvel.com/v1/public/series/454", 48 | "name": "Amazing Spider-Man (1999 - 2013)" 49 | }, 50 | "variants": [ 51 | { 52 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/49353", 53 | "name": "Amazing Spider-Man (1999) #700 (Ramos 5th Printing Variant)" 54 | }, 55 | { 56 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/47884", 57 | "name": "Amazing Spider-Man (1999) #700 (4th Printing Variant)" 58 | }, 59 | { 60 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/47631", 61 | "name": "Amazing Spider-Man (1999) #700 (Camuncoli 3rd Printing Variant)" 62 | }, 63 | { 64 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/47350", 65 | "name": "Amazing Spider-Man (1999) #700 (Ramos 2nd Printing Variant)" 66 | }, 67 | { 68 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/44623", 69 | "name": "Amazing Spider-Man (1999) #700 (Martin Variant)" 70 | }, 71 | { 72 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/42440", 73 | "name": "Amazing Spider-Man (1999) #700 (Asm 50th Anniversary Variant)" 74 | }, 75 | { 76 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/44620", 77 | "name": "Amazing Spider-Man (1999) #700 (Ramos Wraparound Variant)" 78 | }, 79 | { 80 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/44621", 81 | "name": "Amazing Spider-Man (1999) #700 (Quesada Wraparound Variant)" 82 | }, 83 | { 84 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/44622", 85 | "name": "Amazing Spider-Man (1999) #700 (Ditko Variant)" 86 | }, 87 | { 88 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/44624", 89 | "name": "Amazing Spider-Man (1999) #700 (Coipel Variant)" 90 | }, 91 | { 92 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/46995", 93 | "name": "Amazing Spider-Man (1999) #700 (Quesada Wraparound Sketch Variant)" 94 | } 95 | ], 96 | "collections": [], 97 | "collectedIssues": [], 98 | "dates": [ 99 | { 100 | "type": "onsaleDate", 101 | "date": "2012-12-26T00:00:00-0500" 102 | }, 103 | { 104 | "type": "focDate", 105 | "date": "2012-12-04T00:00:00-0500" 106 | }, 107 | { 108 | "type": "unlimitedDate", 109 | "date": "2013-06-24T13:04:49-0400" 110 | }, 111 | { 112 | "type": "digitalPurchaseDate", 113 | "date": "2012-12-26T00:00:00-0500" 114 | } 115 | ], 116 | "prices": [ 117 | { 118 | "type": "printPrice", 119 | "price": 7.99 120 | }, 121 | { 122 | "type": "digitalPurchasePrice", 123 | "price": 3.99 124 | } 125 | ], 126 | "thumbnail": { 127 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/3/b0/510c2957c9b75", 128 | "extension": "jpg" 129 | }, 130 | "images": [ 131 | { 132 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/3/b0/510c2957c9b75", 133 | "extension": "jpg" 134 | }, 135 | { 136 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/3/60/508841f5f024d", 137 | "extension": "jpg" 138 | }, 139 | { 140 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/e/60/504fb308babca", 141 | "extension": "jpg" 142 | }, 143 | { 144 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/9/b0/504fb2946ee9a", 145 | "extension": "jpg" 146 | }, 147 | { 148 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/5/f0/504fb1d794b20", 149 | "extension": "jpg" 150 | } 151 | ], 152 | "creators": { 153 | "available": 12, 154 | "collectionURI": "http://gateway.marvel.com/v1/public/comics/40128/creators", 155 | "items": [ 156 | { 157 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/105", 158 | "name": "Sal Buscema", 159 | "role": "inker" 160 | }, 161 | { 162 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/447", 163 | "name": "Victor Olazaba", 164 | "role": "inker" 165 | }, 166 | { 167 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/9461", 168 | "name": "Stephanie Buscema", 169 | "role": "artist" 170 | }, 171 | { 172 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/1141", 173 | "name": "Giuseppe Camuncoli", 174 | "role": "penciler" 175 | }, 176 | { 177 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/72", 178 | "name": "Humberto Ramos", 179 | "role": "penciler" 180 | }, 181 | { 182 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/430", 183 | "name": "Edgar Delgado", 184 | "role": "colorist" 185 | }, 186 | { 187 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/428", 188 | "name": "Antonio Fabela", 189 | "role": "colorist" 190 | }, 191 | { 192 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/6986", 193 | "name": "J. M. DeMatteis", 194 | "role": "writer" 195 | }, 196 | { 197 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/626", 198 | "name": "Dan Slott", 199 | "role": "writer" 200 | }, 201 | { 202 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/11788", 203 | "name": "Jennifer Van Meter", 204 | "role": "writer" 205 | }, 206 | { 207 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/452", 208 | "name": "Chris Eliopoulos", 209 | "role": "letterer" 210 | }, 211 | { 212 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/11879", 213 | "name": "Stephen Wacker", 214 | "role": "editor" 215 | } 216 | ], 217 | "returned": 12 218 | }, 219 | "characters": { 220 | "available": 1, 221 | "collectionURI": "http://gateway.marvel.com/v1/public/comics/40128/characters", 222 | "items": [ 223 | { 224 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009610", 225 | "name": "Spider-Man" 226 | } 227 | ], 228 | "returned": 1 229 | }, 230 | "stories": { 231 | "available": 2, 232 | "collectionURI": { 233 | "service": "comic_issueStories", 234 | "id": 40128 235 | }, 236 | "items": [ 237 | { 238 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/91053", 239 | "name": "Cover #91053", 240 | "type": "cover" 241 | }, 242 | { 243 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/91054", 244 | "name": "Interior #91054", 245 | "type": "interiorStory" 246 | } 247 | ], 248 | "returned": 2 249 | }, 250 | "events": { 251 | "available": 0, 252 | "collectionURI": "http://gateway.marvel.com/v1/public/comics/40128/events", 253 | "items": [], 254 | "returned": 0 255 | } 256 | } 257 | ] 258 | } 259 | } -------------------------------------------------------------------------------- /spec/fixtures/characters/character_2.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 200, 3 | "status": "Ok", 4 | "etag": "0008d7adbeae74e36a2196b902d36aba282c8ca2", 5 | "data": { 6 | "offset": 0, 7 | "limit": 20, 8 | "total": 1, 9 | "count": 1, 10 | "results": [ 11 | { 12 | "id": 1009227, 13 | "name": "Carnage", 14 | "description": "", 15 | "modified": "2011-11-09T17:46:06-0500", 16 | "thumbnail": { 17 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/c/20/4ebb024c894db", 18 | "extension": "jpg" 19 | }, 20 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009227", 21 | "comics": { 22 | "available": 21, 23 | "collectionURI": "http://gateway.marvel.com/v1/public/characters/1009227/comics", 24 | "items": [ 25 | { 26 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/6809", 27 | "name": "Amazing Spider-Man (1963) #394" 28 | }, 29 | { 30 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/34628", 31 | "name": "Carnage (2010) #1" 32 | }, 33 | { 34 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/36404", 35 | "name": "Carnage (2010) #1" 36 | }, 37 | { 38 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/39011", 39 | "name": "Carnage (2010) #1 (2nd Printing Variant)" 40 | }, 41 | { 42 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/37072", 43 | "name": "Carnage (2010) #1 (ADAMS VARIANT)" 44 | }, 45 | { 46 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/36271", 47 | "name": "Carnage (2010) #2" 48 | }, 49 | { 50 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/39010", 51 | "name": "Carnage (2010) #2 (2nd Printing Variant)" 52 | }, 53 | { 54 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/34623", 55 | "name": "Carnage (2010) #3" 56 | }, 57 | { 58 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/39650", 59 | "name": "Carnage (2010) #3 (2nd Printing Variant)" 60 | }, 61 | { 62 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/36273", 63 | "name": "Carnage (2010) #4" 64 | }, 65 | { 66 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/36269", 67 | "name": "Carnage (2010) #5" 68 | }, 69 | { 70 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/40355", 71 | "name": "Carnage, U.S.A. (2011) #1" 72 | }, 73 | { 74 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/40353", 75 | "name": "Carnage, U.S.A. (2011) #2" 76 | }, 77 | { 78 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/14656", 79 | "name": "Peter Parker, the Spectacular Spider-Man (1976) #201" 80 | }, 81 | { 82 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/14657", 83 | "name": "Peter Parker, the Spectacular Spider-Man (1976) #202" 84 | }, 85 | { 86 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/14658", 87 | "name": "Peter Parker, the Spectacular Spider-Man (1976) #203" 88 | }, 89 | { 90 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/14691", 91 | "name": "Peter Parker, the Spectacular Spider-Man (1976) #233" 92 | }, 93 | { 94 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10518", 95 | "name": "Peter Parker: Spider-Man (1999) #10" 96 | }, 97 | { 98 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10521", 99 | "name": "Peter Parker: Spider-Man (1999) #13" 100 | }, 101 | { 102 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/5396", 103 | "name": "Spider-Man Family Featuring Spider-Clan (2006) #1" 104 | } 105 | ], 106 | "returned": 20 107 | }, 108 | "series": { 109 | "available": 7, 110 | "collectionURI": "http://gateway.marvel.com/v1/public/characters/1009227/series", 111 | "items": [ 112 | { 113 | "resourceURI": "http://gateway.marvel.com/v1/public/series/1987", 114 | "name": "Amazing Spider-Man (1963 - 1998)" 115 | }, 116 | { 117 | "resourceURI": "http://gateway.marvel.com/v1/public/series/11942", 118 | "name": "Carnage (2010 - 2011)" 119 | }, 120 | { 121 | "resourceURI": "http://gateway.marvel.com/v1/public/series/14984", 122 | "name": "Carnage, U.S.A. (2011 - 2012)" 123 | }, 124 | { 125 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2271", 126 | "name": "Peter Parker, the Spectacular Spider-Man (1976 - 1998)" 127 | }, 128 | { 129 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2060", 130 | "name": "Peter Parker: Spider-Man (1999 - 2003)" 131 | }, 132 | { 133 | "resourceURI": "http://gateway.marvel.com/v1/public/series/1091", 134 | "name": "Spider-Man Family Featuring Spider-Clan (2006)" 135 | }, 136 | { 137 | "resourceURI": "http://gateway.marvel.com/v1/public/series/13532", 138 | "name": "Spider-Man: With Great Power Comes Great Responsibility (2010 - 2011)" 139 | } 140 | ], 141 | "returned": 7 142 | }, 143 | "stories": { 144 | "available": 23, 145 | "collectionURI": "http://gateway.marvel.com/v1/public/characters/1009227/stories", 146 | "items": [ 147 | { 148 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/5990", 149 | "name": "Cover #5990", 150 | "type": "cover" 151 | }, 152 | { 153 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/14248", 154 | "name": "Carnage", 155 | "type": "profile" 156 | }, 157 | { 158 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/25562", 159 | "name": "Venom Triumphant!", 160 | "type": "interiorStory" 161 | }, 162 | { 163 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/25569", 164 | "name": "When Carnage comes calling!", 165 | "type": "cover" 166 | }, 167 | { 168 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/29779", 169 | "name": "Maximum Carnage, Part 5 of 14", 170 | "type": "cover" 171 | }, 172 | { 173 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/29782", 174 | "name": "Maximum Carnage, Part 9 of 14", 175 | "type": "cover" 176 | }, 177 | { 178 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/29785", 179 | "name": "Maximum Carnage, Part 13 of 14", 180 | "type": "cover" 181 | }, 182 | { 183 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/29914", 184 | "name": "Web of Carnage, Part 4 of 4", 185 | "type": "cover" 186 | }, 187 | { 188 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/76812", 189 | "name": "Carnage #3", 190 | "type": "cover" 191 | }, 192 | { 193 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/76813", 194 | "name": "Carnage #3", 195 | "type": "interiorStory" 196 | }, 197 | { 198 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/80312", 199 | "name": "Carnage #5", 200 | "type": "interiorStory" 201 | }, 202 | { 203 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/80318", 204 | "name": "Interior #80318", 205 | "type": "interiorStory" 206 | }, 207 | { 208 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/80322", 209 | "name": "Interior #80322", 210 | "type": "interiorStory" 211 | }, 212 | { 213 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/80326", 214 | "name": "Carnage (2010) #4", 215 | "type": "interiorStory" 216 | }, 217 | { 218 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/80823", 219 | "name": "Interior #80823", 220 | "type": "interiorStory" 221 | }, 222 | { 223 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/80825", 224 | "name": "Interior #80825", 225 | "type": "interiorStory" 226 | }, 227 | { 228 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/80827", 229 | "name": "Interior #80827", 230 | "type": "interiorStory" 231 | }, 232 | { 233 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/80829", 234 | "name": "Interior #80829", 235 | "type": "interiorStory" 236 | }, 237 | { 238 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/82181", 239 | "name": "Interior #82181", 240 | "type": "interiorStory" 241 | }, 242 | { 243 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/89988", 244 | "name": "CARNAGE 3 2ND PRINTING VARIANT", 245 | "type": "interiorStory" 246 | } 247 | ], 248 | "returned": 20 249 | }, 250 | "events": { 251 | "available": 1, 252 | "collectionURI": "http://gateway.marvel.com/v1/public/characters/1009227/events", 253 | "items": [ 254 | { 255 | "resourceURI": "http://gateway.marvel.com/v1/public/events/151", 256 | "name": "Maximum Carnage" 257 | } 258 | ], 259 | "returned": 1 260 | }, 261 | "urls": [ 262 | { 263 | "type": "detail", 264 | "url": "http://marvel.com/comics/characters/1009227/carnage?utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 265 | }, 266 | { 267 | "type": "wiki", 268 | "url": "http://marvel.com/universe/Carnage_(Cletus_Kasady)?utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 269 | } 270 | ] 271 | } 272 | ] 273 | } 274 | } -------------------------------------------------------------------------------- /spec/fixtures/creators/creator.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 200, 3 | "status": "Ok", 4 | "etag": "7f63fd3b02630c642c7d64894247ada4f2e60669", 5 | "data": { 6 | "offset": 0, 7 | "limit": 20, 8 | "total": 1, 9 | "count": 1, 10 | "results": [ 11 | { 12 | "id": 593, 13 | "firstName": "Lee", 14 | "middleName": "", 15 | "lastName": "Loughridge", 16 | "suffix": "", 17 | "fullName": "Lee Loughridge", 18 | "modified": "2012-12-31T09:41:15-0500", 19 | "thumbnail": { 20 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/6/70/4bc470880fb91", 21 | "extension": "jpg" 22 | }, 23 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/593", 24 | "comics": { 25 | "available": 131, 26 | "collectionURI": "http://gateway.marvel.com/v1/public/creators/593/comics", 27 | "items": [ 28 | { 29 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/41265", 30 | "name": "Age of Apocalypse (2011) #9" 31 | }, 32 | { 33 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/41271", 34 | "name": "Age of Apocalypse (2011) #10" 35 | }, 36 | { 37 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/21513", 38 | "name": "Black Panther (2005) #39" 39 | }, 40 | { 41 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/21716", 42 | "name": "Black Panther (2005) #40" 43 | }, 44 | { 45 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/21943", 46 | "name": "Black Panther (2005) #41" 47 | }, 48 | { 49 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/45966", 50 | "name": "Captain America (2012) #3" 51 | }, 52 | { 53 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/46011", 54 | "name": "Daredevil: Dark Nights (2013) #2" 55 | }, 56 | { 57 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/2399", 58 | "name": "Daredevil: Redemption (Trade Paperback)" 59 | }, 60 | { 61 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/1645", 62 | "name": "Daredevil: Redemption (2005) #2" 63 | }, 64 | { 65 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/1739", 66 | "name": "Daredevil: Redemption (2005) #3" 67 | }, 68 | { 69 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/1847", 70 | "name": "Daredevil: Redemption (2005) #4" 71 | }, 72 | { 73 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/1953", 74 | "name": "Daredevil: Redemption (2005) #5" 75 | }, 76 | { 77 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/2059", 78 | "name": "Daredevil: Redemption (2005) #6" 79 | }, 80 | { 81 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/24947", 82 | "name": "Deadpool (2008) #13" 83 | }, 84 | { 85 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/24948", 86 | "name": "Deadpool (2008) #14" 87 | }, 88 | { 89 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/29820", 90 | "name": "Deadpool (2008) #14 (2ND PRINTING VARIANT)" 91 | }, 92 | { 93 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/28621", 94 | "name": "Deadpool (1997) #900" 95 | }, 96 | { 97 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/33959", 98 | "name": "Deadpool Pulp (Hardcover)" 99 | }, 100 | { 101 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/33695", 102 | "name": "Deadpool Pulp (2010) #1" 103 | }, 104 | { 105 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/33694", 106 | "name": "Deadpool Pulp (2010) #2" 107 | } 108 | ], 109 | "returned": 20 110 | }, 111 | "series": { 112 | "available": 53, 113 | "collectionURI": "http://gateway.marvel.com/v1/public/creators/593/series", 114 | "items": [ 115 | { 116 | "resourceURI": "http://gateway.marvel.com/v1/public/series/15331", 117 | "name": "Age of Apocalypse (2011 - Present)" 118 | }, 119 | { 120 | "resourceURI": "http://gateway.marvel.com/v1/public/series/784", 121 | "name": "Black Panther (2005 - 2008)" 122 | }, 123 | { 124 | "resourceURI": "http://gateway.marvel.com/v1/public/series/16516", 125 | "name": "Captain America (2012 - Present)" 126 | }, 127 | { 128 | "resourceURI": "http://gateway.marvel.com/v1/public/series/17354", 129 | "name": "Daredevil: Dark Nights (2013 - Present)" 130 | }, 131 | { 132 | "resourceURI": "http://gateway.marvel.com/v1/public/series/791", 133 | "name": "Daredevil: Redemption (2005)" 134 | }, 135 | { 136 | "resourceURI": "http://gateway.marvel.com/v1/public/series/1332", 137 | "name": "Daredevil: Redemption (2005)" 138 | }, 139 | { 140 | "resourceURI": "http://gateway.marvel.com/v1/public/series/5701", 141 | "name": "Deadpool (2008 - 2012)" 142 | }, 143 | { 144 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2005", 145 | "name": "Deadpool (1997 - 2002)" 146 | }, 147 | { 148 | "resourceURI": "http://gateway.marvel.com/v1/public/series/11063", 149 | "name": "Deadpool Pulp (2010 - Present)" 150 | }, 151 | { 152 | "resourceURI": "http://gateway.marvel.com/v1/public/series/11602", 153 | "name": "Deadpool Pulp (2010)" 154 | }, 155 | { 156 | "resourceURI": "http://gateway.marvel.com/v1/public/series/9045", 157 | "name": "Deadpool Team-Up (2009 - 2011)" 158 | }, 159 | { 160 | "resourceURI": "http://gateway.marvel.com/v1/public/series/877", 161 | "name": "Friendly Neighborhood Spider-Man (2005 - 2007)" 162 | }, 163 | { 164 | "resourceURI": "http://gateway.marvel.com/v1/public/series/1895", 165 | "name": "Friendly Neighborhood Spider-Man Vol. 2: Mystery Date (2007)" 166 | }, 167 | { 168 | "resourceURI": "http://gateway.marvel.com/v1/public/series/14248", 169 | "name": "Fury Max (2011 - Present)" 170 | }, 171 | { 172 | "resourceURI": "http://gateway.marvel.com/v1/public/series/7821", 173 | "name": "Ghost Riders: Heavens on Fire (2009)" 174 | }, 175 | { 176 | "resourceURI": "http://gateway.marvel.com/v1/public/series/6412", 177 | "name": "Hulk Family (2008)" 178 | }, 179 | { 180 | "resourceURI": "http://gateway.marvel.com/v1/public/series/167", 181 | "name": "Hulk/Wolverine: 6 Hours (2003)" 182 | }, 183 | { 184 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2574", 185 | "name": "Hulk/Wolverine: 6 Hours (2003)" 186 | }, 187 | { 188 | "resourceURI": "http://gateway.marvel.com/v1/public/series/7427", 189 | "name": "Hulk: Broken Worlds Book (2009)" 190 | }, 191 | { 192 | "resourceURI": "http://gateway.marvel.com/v1/public/series/3762", 193 | "name": "Incredible Hercules (2008 - 2010)" 194 | } 195 | ], 196 | "returned": 20 197 | }, 198 | "stories": { 199 | "available": 134, 200 | "collectionURI": "http://gateway.marvel.com/v1/public/creators/593/stories", 201 | "items": [ 202 | { 203 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1726", 204 | "name": "5 of 6 xLS", 205 | "type": "interiorStory" 206 | }, 207 | { 208 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1728", 209 | "name": "4 of 6 xLS", 210 | "type": "interiorStory" 211 | }, 212 | { 213 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1730", 214 | "name": "6 of 6 xLS", 215 | "type": "interiorStory" 216 | }, 217 | { 218 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3529", 219 | "name": "Interior #3529", 220 | "type": "interiorStory" 221 | }, 222 | { 223 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3531", 224 | "name": "Interior #3531", 225 | "type": "interiorStory" 226 | }, 227 | { 228 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3533", 229 | "name": "The Man-Thing movie prequel concludes with a horrific showdown with Man-Thing as you’ve never seen it before! Check out an incar", 230 | "type": "interiorStory" 231 | }, 232 | { 233 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3783", 234 | "name": "6 of 6 - 6XLS", 235 | "type": "interiorStory" 236 | }, 237 | { 238 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3785", 239 | "name": "Interior #3785", 240 | "type": "interiorStory" 241 | }, 242 | { 243 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3787", 244 | "name": "Interior #3787", 245 | "type": "interiorStory" 246 | }, 247 | { 248 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3789", 249 | "name": "Interior #3789", 250 | "type": "interiorStory" 251 | }, 252 | { 253 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3791", 254 | "name": "With great power must come great responsibility… but when the entire Marvel Universe is recast as a world that is powerless… are", 255 | "type": "interiorStory" 256 | }, 257 | { 258 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3793", 259 | "name": "Powerless nears its climactic conclusion as events surrounding Logan, Peter Parker, and Matt Murdock cause each of them to reach", 260 | "type": "interiorStory" 261 | }, 262 | { 263 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3931", 264 | "name": "2 of 6", 265 | "type": "interiorStory" 266 | }, 267 | { 268 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3933", 269 | "name": "3 of 6", 270 | "type": "interiorStory" 271 | }, 272 | { 273 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3935", 274 | "name": "4 of 6", 275 | "type": "interiorStory" 276 | }, 277 | { 278 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3937", 279 | "name": "5 of 6", 280 | "type": "interiorStory" 281 | }, 282 | { 283 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3939", 284 | "name": "6 of 6", 285 | "type": "interiorStory" 286 | }, 287 | { 288 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/4679", 289 | "name": "3 of 3 - I Hate a Mystery", 290 | "type": "interiorStory" 291 | }, 292 | { 293 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/4981", 294 | "name": "1 of 1 - Hulk", 295 | "type": "interiorStory" 296 | }, 297 | { 298 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/4983", 299 | "name": "1 of 1", 300 | "type": "interiorStory" 301 | } 302 | ], 303 | "returned": 20 304 | }, 305 | "events": { 306 | "available": 2, 307 | "collectionURI": "http://gateway.marvel.com/v1/public/creators/593/events", 308 | "items": [ 309 | { 310 | "resourceURI": "http://gateway.marvel.com/v1/public/events/318", 311 | "name": "Dark Reign" 312 | }, 313 | { 314 | "resourceURI": "http://gateway.marvel.com/v1/public/events/269", 315 | "name": "Secret Invasion" 316 | } 317 | ], 318 | "returned": 2 319 | }, 320 | "urls": [ 321 | { 322 | "type": "detail", 323 | "url": "http://marvel.com/comics/creators/593/lee_loughridge?utm_campaign=apiRef&utm_source=c60a23f273a09387e7d1ad4e6f828211" 324 | } 325 | ] 326 | } 327 | ] 328 | } 329 | } -------------------------------------------------------------------------------- /spec/fixtures/stories/story_creators.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 200, 3 | "status": "Ok", 4 | "etag": "e3c32050409cc2ff17b7b5847a8d9d21ee9bdcad", 5 | "data": { 6 | "offset": 0, 7 | "limit": 20, 8 | "total": 1, 9 | "count": 1, 10 | "results": [ 11 | { 12 | "id": 191, 13 | "firstName": "Kaare", 14 | "middleName": "", 15 | "lastName": "Andrews", 16 | "suffix": "", 17 | "fullName": "Kaare Andrews", 18 | "modified": "2013-03-15T17:04:18-0400", 19 | "thumbnail": { 20 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/d/20/4bc5fb5688ed7", 21 | "extension": "jpg" 22 | }, 23 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/191", 24 | "comics": { 25 | "available": 174, 26 | "collectionURI": "http://gateway.marvel.com/v1/public/creators/191/comics", 27 | "items": [ 28 | { 29 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/43495", 30 | "name": "A+X (2012) #2" 31 | }, 32 | { 33 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/43501", 34 | "name": "A+X (2012) #4" 35 | }, 36 | { 37 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/24348", 38 | "name": "Adam: Legend of the Blue Marvel (Trade Paperback)" 39 | }, 40 | { 41 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/22461", 42 | "name": "Adam: Legend of the Blue Marvel (2008) #1" 43 | }, 44 | { 45 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/2212", 46 | "name": "Amazing Spider-Man (1999) #522" 47 | }, 48 | { 49 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/3019", 50 | "name": "Amazing Spider-Man Vol. 10: New Avengers (Trade Paperback)" 51 | }, 52 | { 53 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/22572", 54 | "name": "Astonishing X-Men: Ghost Boxes (2008) #2" 55 | }, 56 | { 57 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/29320", 58 | "name": "Astonishing X-Men: Xenogenesis (Hardcover)" 59 | }, 60 | { 61 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/32864", 62 | "name": "Astonishing X-Men: Xenogenesis (2010) #1" 63 | }, 64 | { 65 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/32867", 66 | "name": "Astonishing X-Men: Xenogenesis (2010) #2" 67 | }, 68 | { 69 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/32869", 70 | "name": "Astonishing X-Men: Xenogenesis (2010) #3" 71 | }, 72 | { 73 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/32871", 74 | "name": "Astonishing X-Men: Xenogenesis (2010) #4" 75 | }, 76 | { 77 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/32874", 78 | "name": "Astonishing X-Men: Xenogenesis (2010) #5" 79 | }, 80 | { 81 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/42486", 82 | "name": "Avengers Vs. X-Men: Versus (Trade Paperback)" 83 | }, 84 | { 85 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/42489", 86 | "name": "Avengers Vs. X-Men: Versus (2011) #4" 87 | }, 88 | { 89 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/43014", 90 | "name": "Avengers Vs. X-Men: Versus (2011) #4 (Fight Poster Variant)" 91 | }, 92 | { 93 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/2165", 94 | "name": "Black Panther (2005) #6" 95 | }, 96 | { 97 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/2323", 98 | "name": "Black Panther (2005) #7" 99 | }, 100 | { 101 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/3964", 102 | "name": "Black Panther: Who Is the Black Panther (Trade Paperback)" 103 | }, 104 | { 105 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/23971", 106 | "name": "Cable (2008) #13" 107 | } 108 | ], 109 | "returned": 20 110 | }, 111 | "series": { 112 | "available": 80, 113 | "collectionURI": "http://gateway.marvel.com/v1/public/creators/191/series", 114 | "items": [ 115 | { 116 | "resourceURI": "http://gateway.marvel.com/v1/public/series/16450", 117 | "name": "A+X (2012 - Present)" 118 | }, 119 | { 120 | "resourceURI": "http://gateway.marvel.com/v1/public/series/7524", 121 | "name": "Adam: Legend of the Blue Marvel (2008)" 122 | }, 123 | { 124 | "resourceURI": "http://gateway.marvel.com/v1/public/series/6079", 125 | "name": "Adam: Legend of the Blue Marvel (2008)" 126 | }, 127 | { 128 | "resourceURI": "http://gateway.marvel.com/v1/public/series/454", 129 | "name": "Amazing Spider-Man (1999 - 2013)" 130 | }, 131 | { 132 | "resourceURI": "http://gateway.marvel.com/v1/public/series/1489", 133 | "name": "Amazing Spider-Man Vol. 10: New Avengers (2005)" 134 | }, 135 | { 136 | "resourceURI": "http://gateway.marvel.com/v1/public/series/5998", 137 | "name": "Astonishing X-Men: Ghost Boxes (2008)" 138 | }, 139 | { 140 | "resourceURI": "http://gateway.marvel.com/v1/public/series/10029", 141 | "name": "Astonishing X-Men: Xenogenesis (2011)" 142 | }, 143 | { 144 | "resourceURI": "http://gateway.marvel.com/v1/public/series/9781", 145 | "name": "Astonishing X-Men: Xenogenesis (2010)" 146 | }, 147 | { 148 | "resourceURI": "http://gateway.marvel.com/v1/public/series/16229", 149 | "name": "Avengers Vs. X-Men: Versus (2011 - Present)" 150 | }, 151 | { 152 | "resourceURI": "http://gateway.marvel.com/v1/public/series/16230", 153 | "name": "Avengers Vs. X-Men: Versus (2011 - 2012)" 154 | }, 155 | { 156 | "resourceURI": "http://gateway.marvel.com/v1/public/series/784", 157 | "name": "Black Panther (2005 - 2008)" 158 | }, 159 | { 160 | "resourceURI": "http://gateway.marvel.com/v1/public/series/1682", 161 | "name": "Black Panther: Who Is the Black Panther (2006)" 162 | }, 163 | { 164 | "resourceURI": "http://gateway.marvel.com/v1/public/series/4002", 165 | "name": "Cable (2008 - 2010)" 166 | }, 167 | { 168 | "resourceURI": "http://gateway.marvel.com/v1/public/series/449", 169 | "name": "Daredevil (1998 - 2011)" 170 | }, 171 | { 172 | "resourceURI": "http://gateway.marvel.com/v1/public/series/5705", 173 | "name": "Dead of Night Featuring Devil-Slayer (2008)" 174 | }, 175 | { 176 | "resourceURI": "http://gateway.marvel.com/v1/public/series/3836", 177 | "name": "Dead of Night Featuring Man-Thing (2008)" 178 | }, 179 | { 180 | "resourceURI": "http://gateway.marvel.com/v1/public/series/15487", 181 | "name": "Deadpool Kills the Marvel Universe (2011 - 2012)" 182 | }, 183 | { 184 | "resourceURI": "http://gateway.marvel.com/v1/public/series/15223", 185 | "name": "Hulk: Boiling Point Premiere HC (2011 - Present)" 186 | }, 187 | { 188 | "resourceURI": "http://gateway.marvel.com/v1/public/series/1140", 189 | "name": "Immortal Iron Fist (2006 - 2009)" 190 | }, 191 | { 192 | "resourceURI": "http://gateway.marvel.com/v1/public/series/5738", 193 | "name": "Immortal Iron Fist: Orson Randall and the Death Queen of California (2008)" 194 | } 195 | ], 196 | "returned": 20 197 | }, 198 | "stories": { 199 | "available": 203, 200 | "collectionURI": "http://gateway.marvel.com/v1/public/creators/191/stories", 201 | "items": [ 202 | { 203 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/218", 204 | "name": "Student by day, masked ninja by night: Peter Parker is not your average teenager. When Peter puts on that Spider-Man costume, th", 205 | "type": "interiorStory" 206 | }, 207 | { 208 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1169", 209 | "name": "4 of 5 - New Avengers", 210 | "type": "cover" 211 | }, 212 | { 213 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1298", 214 | "name": "Cover #1298", 215 | "type": "cover" 216 | }, 217 | { 218 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2206", 219 | "name": "1 of 1", 220 | "type": "cover" 221 | }, 222 | { 223 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2207", 224 | "name": "1 of 1", 225 | "type": "interiorStory" 226 | }, 227 | { 228 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2210", 229 | "name": "2 of 3 - House of M", 230 | "type": "cover" 231 | }, 232 | { 233 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2212", 234 | "name": "3 of 3 - House of M", 235 | "type": "cover" 236 | }, 237 | { 238 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2217", 239 | "name": "2 of 5 - Origins & Endings, Vol. 1", 240 | "type": "cover" 241 | }, 242 | { 243 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2219", 244 | "name": "3 of 5 - Origins & Endings, Vol. 1", 245 | "type": "cover" 246 | }, 247 | { 248 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2221", 249 | "name": "4 of 5 - Origins & Endings, Vol. 1", 250 | "type": "cover" 251 | }, 252 | { 253 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2223", 254 | "name": "5 of 5 - Origins & Endings, Vol. 1", 255 | "type": "cover" 256 | }, 257 | { 258 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3194", 259 | "name": "Cover #3194", 260 | "type": "cover" 261 | }, 262 | { 263 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3195", 264 | "name": "Interior #3195", 265 | "type": "interiorStory" 266 | }, 267 | { 268 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3196", 269 | "name": "Cover #3196", 270 | "type": "cover" 271 | }, 272 | { 273 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3197", 274 | "name": "Interior #3197", 275 | "type": "interiorStory" 276 | }, 277 | { 278 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3198", 279 | "name": "Cover #3198", 280 | "type": "cover" 281 | }, 282 | { 283 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3199", 284 | "name": "Interior #3199", 285 | "type": "interiorStory" 286 | }, 287 | { 288 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3200", 289 | "name": "As poisonous radiation courses through his bloodstream, a vicious Doctor Octopus cracks the secret of Spider-Man and prepares fo", 290 | "type": "cover" 291 | }, 292 | { 293 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3201", 294 | "name": "As poisonous radiation courses through his bloodstream, a vicious Doctor Octopus cracks the secret of Spider-Man and prepares fo", 295 | "type": "interiorStory" 296 | }, 297 | { 298 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/3202", 299 | "name": "The brutal conclusion to the fantastic series, featuring the first epic battle between The Amazing Spider-Man and Doctor Octopus", 300 | "type": "cover" 301 | } 302 | ], 303 | "returned": 20 304 | }, 305 | "events": { 306 | "available": 3, 307 | "collectionURI": "http://gateway.marvel.com/v1/public/creators/191/events", 308 | "items": [ 309 | { 310 | "resourceURI": "http://gateway.marvel.com/v1/public/events/251", 311 | "name": "House of M" 312 | }, 313 | { 314 | "resourceURI": "http://gateway.marvel.com/v1/public/events/37", 315 | "name": "Maximum Security" 316 | }, 317 | { 318 | "resourceURI": "http://gateway.marvel.com/v1/public/events/298", 319 | "name": "Messiah War" 320 | } 321 | ], 322 | "returned": 3 323 | }, 324 | "urls": [ 325 | { 326 | "type": "detail", 327 | "url": "http://marvel.com/comics/creators/191/kaare_andrews?utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 328 | } 329 | ] 330 | } 331 | ] 332 | } 333 | } -------------------------------------------------------------------------------- /spec/fixtures/series/serie.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 200, 3 | "status": "Ok", 4 | "etag": "e1f5354666749c33122b4b634ebf1a0d528cfcf0", 5 | "data": { 6 | "offset": 0, 7 | "limit": 20, 8 | "total": 1, 9 | "count": 1, 10 | "results": [ 11 | { 12 | "id": 2069, 13 | "title": "Spider-Man (1990 - 1998)", 14 | "description": null, 15 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2069", 16 | "urls": [ 17 | { 18 | "type": "detail", 19 | "url": "http://marvel.com/comics/series/2069/spider-man_1990_-_1998?utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 20 | } 21 | ], 22 | "startYear": 1990, 23 | "endYear": 1998, 24 | "rating": "", 25 | "type": "", 26 | "modified": "2013-03-19T16:14:02-0400", 27 | "thumbnail": { 28 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/7/10/5148c670b8fe9", 29 | "extension": "jpg" 30 | }, 31 | "creators": { 32 | "available": 69, 33 | "collectionURI": "http://gateway.marvel.com/v1/public/series/2069/creators", 34 | "items": [ 35 | { 36 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/807", 37 | "name": "Comicraft", 38 | "role": "letterer" 39 | }, 40 | { 41 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/2529", 42 | "name": "Liz Agraphiotis", 43 | "role": "letterer" 44 | }, 45 | { 46 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/452", 47 | "name": "Chris Eliopoulos", 48 | "role": "letterer" 49 | }, 50 | { 51 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/1950", 52 | "name": "Joe Andreani", 53 | "role": "editor" 54 | }, 55 | { 56 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/1945", 57 | "name": "Mark Bernardo", 58 | "role": "editor" 59 | }, 60 | { 61 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/3395", 62 | "name": "Dan Cuddy", 63 | "role": "editor" 64 | }, 65 | { 66 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/1918", 67 | "name": "Danny Fingeroth", 68 | "role": "editor" 69 | }, 70 | { 71 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/87", 72 | "name": "Mark Bagley", 73 | "role": "penciller" 74 | }, 75 | { 76 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/5764", 77 | "name": "Ron Frenz", 78 | "role": "penciller" 79 | }, 80 | { 81 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/1827", 82 | "name": "John Byrne", 83 | "role": "penciller (cover)" 84 | }, 85 | { 86 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/200", 87 | "name": "Claudio Castellini", 88 | "role": "penciller (cover)" 89 | }, 90 | { 91 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/3916", 92 | "name": "Dan Fraga", 93 | "role": "penciller (cover)" 94 | }, 95 | { 96 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/3074", 97 | "name": "Ralph Cabrera", 98 | "role": "inker" 99 | }, 100 | { 101 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/2386", 102 | "name": "Harry Candelario", 103 | "role": "inker" 104 | }, 105 | { 106 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/2427", 107 | "name": "Sam DeLaRosa", 108 | "role": "inker" 109 | }, 110 | { 111 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/440", 112 | "name": "Mark Farmer", 113 | "role": "inker" 114 | }, 115 | { 116 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/3927", 117 | "name": "But Not on an actual published Comic", 118 | "role": "colorist" 119 | }, 120 | { 121 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/9565", 122 | "name": "Tom DeFalco", 123 | "role": "writer" 124 | }, 125 | { 126 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/6986", 127 | "name": "J. M. DeMatteis", 128 | "role": "writer" 129 | }, 130 | { 131 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/1293", 132 | "name": "Steven Grant", 133 | "role": "writer" 134 | } 135 | ], 136 | "returned": 20 137 | }, 138 | "characters": { 139 | "available": 16, 140 | "collectionURI": "http://gateway.marvel.com/v1/public/series/2069/characters", 141 | "items": [ 142 | { 143 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1010354", 144 | "name": "Adam Warlock" 145 | }, 146 | { 147 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009218", 148 | "name": "Calypso" 149 | }, 150 | { 151 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009220", 152 | "name": "Captain America" 153 | }, 154 | { 155 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009243", 156 | "name": "Colossus" 157 | }, 158 | { 159 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009254", 160 | "name": "Crusher Hogan" 161 | }, 162 | { 163 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009318", 164 | "name": "Ghost Rider (Johnny Blaze)" 165 | }, 166 | { 167 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009347", 168 | "name": "Hobgoblin (Roderick Kingsley)" 169 | }, 170 | { 171 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009351", 172 | "name": "Hulk" 173 | }, 174 | { 175 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009391", 176 | "name": "Kraven the Hunter" 177 | }, 178 | { 179 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009404", 180 | "name": "Lizard" 181 | }, 182 | { 183 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009459", 184 | "name": "Mr. Fantastic" 185 | }, 186 | { 187 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009325", 188 | "name": "Norman Osborn" 189 | }, 190 | { 191 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009592", 192 | "name": "Silver Surfer" 193 | }, 194 | { 195 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009610", 196 | "name": "Spider-Man" 197 | }, 198 | { 199 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009718", 200 | "name": "Wolverine" 201 | }, 202 | { 203 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009719", 204 | "name": "Wonder Man" 205 | } 206 | ], 207 | "returned": 16 208 | }, 209 | "stories": { 210 | "available": 249, 211 | "collectionURI": "http://gateway.marvel.com/v1/public/series/2069/stories", 212 | "items": [ 213 | { 214 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23741", 215 | "name": "Cover #23741", 216 | "type": "cover" 217 | }, 218 | { 219 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23742", 220 | "name": "A Prelude in Red", 221 | "type": "interiorStory" 222 | }, 223 | { 224 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23743", 225 | "name": "Post It to Peter!", 226 | "type": "letters" 227 | }, 228 | { 229 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23744", 230 | "name": "Cover #23744", 231 | "type": "cover" 232 | }, 233 | { 234 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23745", 235 | "name": "Torment Part 1", 236 | "type": "interiorStory" 237 | }, 238 | { 239 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23746", 240 | "name": "", 241 | "type": "" 242 | }, 243 | { 244 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23747", 245 | "name": "", 246 | "type": "" 247 | }, 248 | { 249 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23748", 250 | "name": "", 251 | "type": "" 252 | }, 253 | { 254 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23749", 255 | "name": "", 256 | "type": "" 257 | }, 258 | { 259 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23750", 260 | "name": "", 261 | "type": "" 262 | }, 263 | { 264 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23751", 265 | "name": "", 266 | "type": "" 267 | }, 268 | { 269 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23752", 270 | "name": "", 271 | "type": "" 272 | }, 273 | { 274 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23753", 275 | "name": "", 276 | "type": "" 277 | }, 278 | { 279 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23754", 280 | "name": "", 281 | "type": "" 282 | }, 283 | { 284 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23755", 285 | "name": "", 286 | "type": "" 287 | }, 288 | { 289 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23756", 290 | "name": "Torment, Part 2 of 5: Blood Lust of the Lizard!", 291 | "type": "cover" 292 | }, 293 | { 294 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23757", 295 | "name": "Torment, Part 2", 296 | "type": "interiorStory" 297 | }, 298 | { 299 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23758", 300 | "name": "Spider Mania", 301 | "type": "text article" 302 | }, 303 | { 304 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23759", 305 | "name": "", 306 | "type": "" 307 | }, 308 | { 309 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/23760", 310 | "name": "", 311 | "type": "" 312 | } 313 | ], 314 | "returned": 20 315 | }, 316 | "comics": { 317 | "available": 99, 318 | "collectionURI": "http://gateway.marvel.com/v1/public/series/2069/comics", 319 | "items": [ 320 | { 321 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10766", 322 | "name": "Spider-Man (1990)" 323 | }, 324 | { 325 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10767", 326 | "name": "Spider-Man (1990) #1" 327 | }, 328 | { 329 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10778", 330 | "name": "Spider-Man (1990) #2" 331 | }, 332 | { 333 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10789", 334 | "name": "Spider-Man (1990) #3" 335 | }, 336 | { 337 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10800", 338 | "name": "Spider-Man (1990) #4" 339 | }, 340 | { 341 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10811", 342 | "name": "Spider-Man (1990) #5" 343 | }, 344 | { 345 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10822", 346 | "name": "Spider-Man (1990) #6" 347 | }, 348 | { 349 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10833", 350 | "name": "Spider-Man (1990) #7" 351 | }, 352 | { 353 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10844", 354 | "name": "Spider-Man (1990) #8" 355 | }, 356 | { 357 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10855", 358 | "name": "Spider-Man (1990) #9" 359 | }, 360 | { 361 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10768", 362 | "name": "Spider-Man (1990) #10" 363 | }, 364 | { 365 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10769", 366 | "name": "Spider-Man (1990) #11" 367 | }, 368 | { 369 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10770", 370 | "name": "Spider-Man (1990) #12" 371 | }, 372 | { 373 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10771", 374 | "name": "Spider-Man (1990) #13" 375 | }, 376 | { 377 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10772", 378 | "name": "Spider-Man (1990) #14" 379 | }, 380 | { 381 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10773", 382 | "name": "Spider-Man (1990) #15" 383 | }, 384 | { 385 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10774", 386 | "name": "Spider-Man (1990) #16" 387 | }, 388 | { 389 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10775", 390 | "name": "Spider-Man (1990) #17" 391 | }, 392 | { 393 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10776", 394 | "name": "Spider-Man (1990) #18" 395 | }, 396 | { 397 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/10777", 398 | "name": "Spider-Man (1990) #19" 399 | } 400 | ], 401 | "returned": 20 402 | }, 403 | "events": { 404 | "available": 3, 405 | "collectionURI": "http://gateway.marvel.com/v1/public/series/2069/events", 406 | "items": [ 407 | { 408 | "resourceURI": "http://gateway.marvel.com/v1/public/events/29", 409 | "name": "Infinity War" 410 | }, 411 | { 412 | "resourceURI": "http://gateway.marvel.com/v1/public/events/151", 413 | "name": "Maximum Carnage" 414 | }, 415 | { 416 | "resourceURI": "http://gateway.marvel.com/v1/public/events/154", 417 | "name": "Onslaught" 418 | } 419 | ], 420 | "returned": 3 421 | }, 422 | "next": null, 423 | "previous": null 424 | } 425 | ] 426 | } 427 | } -------------------------------------------------------------------------------- /spec/fixtures/characters/character.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 200, 3 | "status": "Ok", 4 | "etag": "fc7e1550fb882c0f509568d508e1864742e7dbdb", 5 | "data": { 6 | "offset": 0, 7 | "limit": 20, 8 | "total": 1, 9 | "count": 1, 10 | "results": [ 11 | { 12 | "id": 1009610, 13 | "name": "Spider-Man", 14 | "description": "Bitten by a radioactive spider, high school student Peter Parker gained the speed, strength and powers of a spider. Adopting the name Spider-Man, Peter hoped to start a career using his new abilities. Taught that with great power comes great responsibility, Spidey has vowed to use his powers to help people.", 15 | "modified": "2013-10-24T13:52:13-0400", 16 | "thumbnail": { 17 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/3/50/526548a343e4b", 18 | "extension": "jpg" 19 | }, 20 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009610", 21 | "comics": { 22 | "available": 2576, 23 | "collectionURI": "http://gateway.marvel.com/v1/public/characters/1009610/comics", 24 | "items": [ 25 | { 26 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/43495", 27 | "name": "A+X (2012) #2" 28 | }, 29 | { 30 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/320", 31 | "name": "Actor Presents Spider-Man and the Incredible Hulk (2003) #1" 32 | }, 33 | { 34 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/30885", 35 | "name": "Age of Heroes (Trade Paperback)" 36 | }, 37 | { 38 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/37257", 39 | "name": "Alias (2003) #10" 40 | }, 41 | { 42 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/37262", 43 | "name": "Alias (2003) #15" 44 | }, 45 | { 46 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/37255", 47 | "name": "Alias Omnibus (Hardcover)" 48 | }, 49 | { 50 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/12637", 51 | "name": "Alpha Flight (1983) #1" 52 | }, 53 | { 54 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/12668", 55 | "name": "Alpha Flight (1983) #127" 56 | }, 57 | { 58 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/6233", 59 | "name": "Alpha Flight Classic Vol. 1 (Trade Paperback)" 60 | }, 61 | { 62 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/16926", 63 | "name": "Amazing Fantasy (1962) #15" 64 | }, 65 | { 66 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/16214", 67 | "name": "Amazing Fantasy Omnibus (Hardcover)" 68 | }, 69 | { 70 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/5286", 71 | "name": "Amazing Spider-Girl (2006)" 72 | }, 73 | { 74 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/16151", 75 | "name": "Amazing Spider-Girl (2006) #11" 76 | }, 77 | { 78 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/13519", 79 | "name": "Amazing Spider-Girl Vol. 1: Whatever Happened to the Daughter of Spider-Man (Trade Paperback)" 80 | }, 81 | { 82 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/17305", 83 | "name": "Amazing Spider-Girl Vol. 2: Comes the Carnage! (Trade Paperback)" 84 | }, 85 | { 86 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/6481", 87 | "name": "Amazing Spider-Man (1963)" 88 | }, 89 | { 90 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/6482", 91 | "name": "Amazing Spider-Man (1963) #1" 92 | }, 93 | { 94 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/37894", 95 | "name": "Amazing Spider-Man (1999) #1" 96 | }, 97 | { 98 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/37895", 99 | "name": "Amazing Spider-Man (1999) #2" 100 | }, 101 | { 102 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/6593", 103 | "name": "Amazing Spider-Man (1963) #2" 104 | } 105 | ], 106 | "returned": 20 107 | }, 108 | "series": { 109 | "available": 530, 110 | "collectionURI": "http://gateway.marvel.com/v1/public/characters/1009610/series", 111 | "items": [ 112 | { 113 | "resourceURI": "http://gateway.marvel.com/v1/public/series/16450", 114 | "name": "A+X (2012 - Present)" 115 | }, 116 | { 117 | "resourceURI": "http://gateway.marvel.com/v1/public/series/458", 118 | "name": "Actor Presents Spider-Man and the Incredible Hulk (2003)" 119 | }, 120 | { 121 | "resourceURI": "http://gateway.marvel.com/v1/public/series/10235", 122 | "name": "Age of Heroes (2011)" 123 | }, 124 | { 125 | "resourceURI": "http://gateway.marvel.com/v1/public/series/672", 126 | "name": "Alias (2003)" 127 | }, 128 | { 129 | "resourceURI": "http://gateway.marvel.com/v1/public/series/13383", 130 | "name": "Alias Omnibus (2006)" 131 | }, 132 | { 133 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2116", 134 | "name": "Alpha Flight (1983 - 1994)" 135 | }, 136 | { 137 | "resourceURI": "http://gateway.marvel.com/v1/public/series/1983", 138 | "name": "Alpha Flight Classic Vol. 1 (2007)" 139 | }, 140 | { 141 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2987", 142 | "name": "Amazing Fantasy (1962)" 143 | }, 144 | { 145 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2707", 146 | "name": "Amazing Fantasy Omnibus (2007)" 147 | }, 148 | { 149 | "resourceURI": "http://gateway.marvel.com/v1/public/series/1126", 150 | "name": "Amazing Spider-Girl (2006 - 2009)" 151 | }, 152 | { 153 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2234", 154 | "name": "Amazing Spider-Girl Vol. 1: Whatever Happened to the Daughter of Spider-Man (2007)" 155 | }, 156 | { 157 | "resourceURI": "http://gateway.marvel.com/v1/public/series/3101", 158 | "name": "Amazing Spider-Girl Vol. 2: Comes the Carnage! (2007)" 159 | }, 160 | { 161 | "resourceURI": "http://gateway.marvel.com/v1/public/series/1987", 162 | "name": "Amazing Spider-Man (1963 - 1998)" 163 | }, 164 | { 165 | "resourceURI": "http://gateway.marvel.com/v1/public/series/454", 166 | "name": "Amazing Spider-Man (1999 - 2013)" 167 | }, 168 | { 169 | "resourceURI": "http://gateway.marvel.com/v1/public/series/9802", 170 | "name": "Amazing Spider-Man Annual (2010)" 171 | }, 172 | { 173 | "resourceURI": "http://gateway.marvel.com/v1/public/series/5958", 174 | "name": "Amazing Spider-Man Annual (2008 - Present)" 175 | }, 176 | { 177 | "resourceURI": "http://gateway.marvel.com/v1/public/series/13205", 178 | "name": "Amazing Spider-Man Annual (2010 - Present)" 179 | }, 180 | { 181 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2984", 182 | "name": "Amazing Spider-Man Annual (1964 - Present)" 183 | }, 184 | { 185 | "resourceURI": "http://gateway.marvel.com/v1/public/series/5376", 186 | "name": "Amazing Spider-Man Family (2008 - 2009)" 187 | }, 188 | { 189 | "resourceURI": "http://gateway.marvel.com/v1/public/series/9917", 190 | "name": "Amazing Spider-Man MGC (2010)" 191 | } 192 | ], 193 | "returned": 20 194 | }, 195 | "stories": { 196 | "available": 4164, 197 | "collectionURI": "http://gateway.marvel.com/v1/public/characters/1009610/stories", 198 | "items": [ 199 | { 200 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/483", 201 | "name": "Interior #483", 202 | "type": "interiorStory" 203 | }, 204 | { 205 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/486", 206 | "name": "Cover #486", 207 | "type": "cover" 208 | }, 209 | { 210 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/487", 211 | "name": "Interior #487", 212 | "type": "interiorStory" 213 | }, 214 | { 215 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/499", 216 | "name": "Interior #499", 217 | "type": "interiorStory" 218 | }, 219 | { 220 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/599", 221 | "name": "Interior #599", 222 | "type": "interiorStory" 223 | }, 224 | { 225 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/805", 226 | "name": "Interior #805", 227 | "type": "interiorStory" 228 | }, 229 | { 230 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/824", 231 | "name": "Cover #824", 232 | "type": "cover" 233 | }, 234 | { 235 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/838", 236 | "name": "3 of 3 - Family Business", 237 | "type": "cover" 238 | }, 239 | { 240 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/842", 241 | "name": "1 of 1 - Secret of the Spider Shop", 242 | "type": "cover" 243 | }, 244 | { 245 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/867", 246 | "name": "Interior #867", 247 | "type": "interiorStory" 248 | }, 249 | { 250 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1018", 251 | "name": "Cover #1018", 252 | "type": "cover" 253 | }, 254 | { 255 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1019", 256 | "name": "Interior #1019", 257 | "type": "interiorStory" 258 | }, 259 | { 260 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1020", 261 | "name": "Cover #1020", 262 | "type": "cover" 263 | }, 264 | { 265 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1021", 266 | "name": "Interior #1021", 267 | "type": "interiorStory" 268 | }, 269 | { 270 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1022", 271 | "name": "Cover #1022", 272 | "type": "cover" 273 | }, 274 | { 275 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1023", 276 | "name": "Interior #1023", 277 | "type": "interiorStory" 278 | }, 279 | { 280 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1076", 281 | "name": "4 of 4 - Golden Age", 282 | "type": "cover" 283 | }, 284 | { 285 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1125", 286 | "name": "6 of 6 - Sins Past", 287 | "type": "cover" 288 | }, 289 | { 290 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1126", 291 | "name": "6 of 6 - Sins Past", 292 | "type": "interiorStory" 293 | }, 294 | { 295 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1134", 296 | "name": "Interior #1134", 297 | "type": "interiorStory" 298 | } 299 | ], 300 | "returned": 20 301 | }, 302 | "events": { 303 | "available": 29, 304 | "collectionURI": "http://gateway.marvel.com/v1/public/characters/1009610/events", 305 | "items": [ 306 | { 307 | "resourceURI": "http://gateway.marvel.com/v1/public/events/116", 308 | "name": "Acts of Vengeance!" 309 | }, 310 | { 311 | "resourceURI": "http://gateway.marvel.com/v1/public/events/233", 312 | "name": "Atlantis Attacks" 313 | }, 314 | { 315 | "resourceURI": "http://gateway.marvel.com/v1/public/events/234", 316 | "name": "Avengers Disassembled" 317 | }, 318 | { 319 | "resourceURI": "http://gateway.marvel.com/v1/public/events/310", 320 | "name": "Avengers VS X-Men" 321 | }, 322 | { 323 | "resourceURI": "http://gateway.marvel.com/v1/public/events/296", 324 | "name": "Chaos War" 325 | }, 326 | { 327 | "resourceURI": "http://gateway.marvel.com/v1/public/events/238", 328 | "name": "Civil War" 329 | }, 330 | { 331 | "resourceURI": "http://gateway.marvel.com/v1/public/events/318", 332 | "name": "Dark Reign" 333 | }, 334 | { 335 | "resourceURI": "http://gateway.marvel.com/v1/public/events/240", 336 | "name": "Days of Future Present" 337 | }, 338 | { 339 | "resourceURI": "http://gateway.marvel.com/v1/public/events/246", 340 | "name": "Evolutionary War" 341 | }, 342 | { 343 | "resourceURI": "http://gateway.marvel.com/v1/public/events/302", 344 | "name": "Fear Itself" 345 | }, 346 | { 347 | "resourceURI": "http://gateway.marvel.com/v1/public/events/251", 348 | "name": "House of M" 349 | }, 350 | { 351 | "resourceURI": "http://gateway.marvel.com/v1/public/events/252", 352 | "name": "Inferno" 353 | }, 354 | { 355 | "resourceURI": "http://gateway.marvel.com/v1/public/events/253", 356 | "name": "Infinity Gauntlet" 357 | }, 358 | { 359 | "resourceURI": "http://gateway.marvel.com/v1/public/events/255", 360 | "name": "Initiative" 361 | }, 362 | { 363 | "resourceURI": "http://gateway.marvel.com/v1/public/events/258", 364 | "name": "Kraven's Last Hunt" 365 | }, 366 | { 367 | "resourceURI": "http://gateway.marvel.com/v1/public/events/151", 368 | "name": "Maximum Carnage" 369 | }, 370 | { 371 | "resourceURI": "http://gateway.marvel.com/v1/public/events/37", 372 | "name": "Maximum Security" 373 | }, 374 | { 375 | "resourceURI": "http://gateway.marvel.com/v1/public/events/154", 376 | "name": "Onslaught" 377 | }, 378 | { 379 | "resourceURI": "http://gateway.marvel.com/v1/public/events/266", 380 | "name": "Other - Evolve or Die" 381 | }, 382 | { 383 | "resourceURI": "http://gateway.marvel.com/v1/public/events/269", 384 | "name": "Secret Invasion" 385 | } 386 | ], 387 | "returned": 20 388 | }, 389 | "urls": [ 390 | { 391 | "type": "detail", 392 | "url": "http://marvel.com/comics/characters/1009610/spider-man?utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 393 | }, 394 | { 395 | "type": "wiki", 396 | "url": "http://marvel.com/universe/Spider-Man_(Peter_Parker)?utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 397 | } 398 | ] 399 | } 400 | ] 401 | } 402 | } -------------------------------------------------------------------------------- /spec/fixtures/comics/comic_characters.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 200, 3 | "status": "Ok", 4 | "etag": "582f9fce3ee333c22d947fc3b74cf3a96d63ed24", 5 | "data": { 6 | "offset": 0, 7 | "limit": 20, 8 | "total": 1, 9 | "count": 1, 10 | "results": [ 11 | { 12 | "id": 1009610, 13 | "name": "Spider-Man", 14 | "description": "Bitten by a radioactive spider, high school student Peter Parker gained the speed, strength and powers of a spider. Adopting the name Spider-Man, Peter hoped to start a career using his new abilities. Taught that with great power comes great responsibility, Spidey has vowed to use his powers to help people.", 15 | "modified": "2013-10-24T13:52:13-0400", 16 | "thumbnail": { 17 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/3/50/526548a343e4b", 18 | "extension": "jpg" 19 | }, 20 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009610", 21 | "comics": { 22 | "available": 2576, 23 | "collectionURI": "http://gateway.marvel.com/v1/public/characters/1009610/comics", 24 | "items": [ 25 | { 26 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/43495", 27 | "name": "A+X (2012) #2" 28 | }, 29 | { 30 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/320", 31 | "name": "Actor Presents Spider-Man and the Incredible Hulk (2003) #1" 32 | }, 33 | { 34 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/30885", 35 | "name": "Age of Heroes (Trade Paperback)" 36 | }, 37 | { 38 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/37257", 39 | "name": "Alias (2003) #10" 40 | }, 41 | { 42 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/37262", 43 | "name": "Alias (2003) #15" 44 | }, 45 | { 46 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/37255", 47 | "name": "Alias Omnibus (Hardcover)" 48 | }, 49 | { 50 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/12637", 51 | "name": "Alpha Flight (1983) #1" 52 | }, 53 | { 54 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/12668", 55 | "name": "Alpha Flight (1983) #127" 56 | }, 57 | { 58 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/6233", 59 | "name": "Alpha Flight Classic Vol. 1 (Trade Paperback)" 60 | }, 61 | { 62 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/16926", 63 | "name": "Amazing Fantasy (1962) #15" 64 | }, 65 | { 66 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/16214", 67 | "name": "Amazing Fantasy Omnibus (Hardcover)" 68 | }, 69 | { 70 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/5286", 71 | "name": "Amazing Spider-Girl (2006)" 72 | }, 73 | { 74 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/16151", 75 | "name": "Amazing Spider-Girl (2006) #11" 76 | }, 77 | { 78 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/13519", 79 | "name": "Amazing Spider-Girl Vol. 1: Whatever Happened to the Daughter of Spider-Man (Trade Paperback)" 80 | }, 81 | { 82 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/17305", 83 | "name": "Amazing Spider-Girl Vol. 2: Comes the Carnage! (Trade Paperback)" 84 | }, 85 | { 86 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/6481", 87 | "name": "Amazing Spider-Man (1963)" 88 | }, 89 | { 90 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/6482", 91 | "name": "Amazing Spider-Man (1963) #1" 92 | }, 93 | { 94 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/37894", 95 | "name": "Amazing Spider-Man (1999) #1" 96 | }, 97 | { 98 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/37895", 99 | "name": "Amazing Spider-Man (1999) #2" 100 | }, 101 | { 102 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/6593", 103 | "name": "Amazing Spider-Man (1963) #2" 104 | } 105 | ], 106 | "returned": 20 107 | }, 108 | "series": { 109 | "available": 530, 110 | "collectionURI": "http://gateway.marvel.com/v1/public/characters/1009610/series", 111 | "items": [ 112 | { 113 | "resourceURI": "http://gateway.marvel.com/v1/public/series/16450", 114 | "name": "A+X (2012 - Present)" 115 | }, 116 | { 117 | "resourceURI": "http://gateway.marvel.com/v1/public/series/458", 118 | "name": "Actor Presents Spider-Man and the Incredible Hulk (2003)" 119 | }, 120 | { 121 | "resourceURI": "http://gateway.marvel.com/v1/public/series/10235", 122 | "name": "Age of Heroes (2011)" 123 | }, 124 | { 125 | "resourceURI": "http://gateway.marvel.com/v1/public/series/672", 126 | "name": "Alias (2003)" 127 | }, 128 | { 129 | "resourceURI": "http://gateway.marvel.com/v1/public/series/13383", 130 | "name": "Alias Omnibus (2006)" 131 | }, 132 | { 133 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2116", 134 | "name": "Alpha Flight (1983 - 1994)" 135 | }, 136 | { 137 | "resourceURI": "http://gateway.marvel.com/v1/public/series/1983", 138 | "name": "Alpha Flight Classic Vol. 1 (2007)" 139 | }, 140 | { 141 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2987", 142 | "name": "Amazing Fantasy (1962)" 143 | }, 144 | { 145 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2707", 146 | "name": "Amazing Fantasy Omnibus (2007)" 147 | }, 148 | { 149 | "resourceURI": "http://gateway.marvel.com/v1/public/series/1126", 150 | "name": "Amazing Spider-Girl (2006 - 2009)" 151 | }, 152 | { 153 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2234", 154 | "name": "Amazing Spider-Girl Vol. 1: Whatever Happened to the Daughter of Spider-Man (2007)" 155 | }, 156 | { 157 | "resourceURI": "http://gateway.marvel.com/v1/public/series/3101", 158 | "name": "Amazing Spider-Girl Vol. 2: Comes the Carnage! (2007)" 159 | }, 160 | { 161 | "resourceURI": "http://gateway.marvel.com/v1/public/series/1987", 162 | "name": "Amazing Spider-Man (1963 - 1998)" 163 | }, 164 | { 165 | "resourceURI": "http://gateway.marvel.com/v1/public/series/454", 166 | "name": "Amazing Spider-Man (1999 - 2013)" 167 | }, 168 | { 169 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2984", 170 | "name": "Amazing Spider-Man Annual (1964 - Present)" 171 | }, 172 | { 173 | "resourceURI": "http://gateway.marvel.com/v1/public/series/9802", 174 | "name": "Amazing Spider-Man Annual (2010)" 175 | }, 176 | { 177 | "resourceURI": "http://gateway.marvel.com/v1/public/series/13205", 178 | "name": "Amazing Spider-Man Annual (2010 - Present)" 179 | }, 180 | { 181 | "resourceURI": "http://gateway.marvel.com/v1/public/series/5958", 182 | "name": "Amazing Spider-Man Annual (2008 - Present)" 183 | }, 184 | { 185 | "resourceURI": "http://gateway.marvel.com/v1/public/series/5376", 186 | "name": "Amazing Spider-Man Family (2008 - 2009)" 187 | }, 188 | { 189 | "resourceURI": "http://gateway.marvel.com/v1/public/series/9917", 190 | "name": "Amazing Spider-Man MGC (2010)" 191 | } 192 | ], 193 | "returned": 20 194 | }, 195 | "stories": { 196 | "available": 4164, 197 | "collectionURI": "http://gateway.marvel.com/v1/public/characters/1009610/stories", 198 | "items": [ 199 | { 200 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/483", 201 | "name": "Interior #483", 202 | "type": "interiorStory" 203 | }, 204 | { 205 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/486", 206 | "name": "Cover #486", 207 | "type": "cover" 208 | }, 209 | { 210 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/487", 211 | "name": "Interior #487", 212 | "type": "interiorStory" 213 | }, 214 | { 215 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/499", 216 | "name": "Interior #499", 217 | "type": "interiorStory" 218 | }, 219 | { 220 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/599", 221 | "name": "Interior #599", 222 | "type": "interiorStory" 223 | }, 224 | { 225 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/805", 226 | "name": "Interior #805", 227 | "type": "interiorStory" 228 | }, 229 | { 230 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/824", 231 | "name": "Cover #824", 232 | "type": "cover" 233 | }, 234 | { 235 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/838", 236 | "name": "3 of 3 - Family Business", 237 | "type": "cover" 238 | }, 239 | { 240 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/842", 241 | "name": "1 of 1 - Secret of the Spider Shop", 242 | "type": "cover" 243 | }, 244 | { 245 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/867", 246 | "name": "Interior #867", 247 | "type": "interiorStory" 248 | }, 249 | { 250 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1018", 251 | "name": "Cover #1018", 252 | "type": "cover" 253 | }, 254 | { 255 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1019", 256 | "name": "Interior #1019", 257 | "type": "interiorStory" 258 | }, 259 | { 260 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1020", 261 | "name": "Cover #1020", 262 | "type": "cover" 263 | }, 264 | { 265 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1021", 266 | "name": "Interior #1021", 267 | "type": "interiorStory" 268 | }, 269 | { 270 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1022", 271 | "name": "Cover #1022", 272 | "type": "cover" 273 | }, 274 | { 275 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1023", 276 | "name": "Interior #1023", 277 | "type": "interiorStory" 278 | }, 279 | { 280 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1076", 281 | "name": "4 of 4 - Golden Age", 282 | "type": "cover" 283 | }, 284 | { 285 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1125", 286 | "name": "6 of 6 - Sins Past", 287 | "type": "cover" 288 | }, 289 | { 290 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1126", 291 | "name": "6 of 6 - Sins Past", 292 | "type": "interiorStory" 293 | }, 294 | { 295 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1134", 296 | "name": "Interior #1134", 297 | "type": "interiorStory" 298 | } 299 | ], 300 | "returned": 20 301 | }, 302 | "events": { 303 | "available": 29, 304 | "collectionURI": "http://gateway.marvel.com/v1/public/characters/1009610/events", 305 | "items": [ 306 | { 307 | "resourceURI": "http://gateway.marvel.com/v1/public/events/116", 308 | "name": "Acts of Vengeance!" 309 | }, 310 | { 311 | "resourceURI": "http://gateway.marvel.com/v1/public/events/233", 312 | "name": "Atlantis Attacks" 313 | }, 314 | { 315 | "resourceURI": "http://gateway.marvel.com/v1/public/events/234", 316 | "name": "Avengers Disassembled" 317 | }, 318 | { 319 | "resourceURI": "http://gateway.marvel.com/v1/public/events/310", 320 | "name": "Avengers VS X-Men" 321 | }, 322 | { 323 | "resourceURI": "http://gateway.marvel.com/v1/public/events/296", 324 | "name": "Chaos War" 325 | }, 326 | { 327 | "resourceURI": "http://gateway.marvel.com/v1/public/events/238", 328 | "name": "Civil War" 329 | }, 330 | { 331 | "resourceURI": "http://gateway.marvel.com/v1/public/events/318", 332 | "name": "Dark Reign" 333 | }, 334 | { 335 | "resourceURI": "http://gateway.marvel.com/v1/public/events/240", 336 | "name": "Days of Future Present" 337 | }, 338 | { 339 | "resourceURI": "http://gateway.marvel.com/v1/public/events/246", 340 | "name": "Evolutionary War" 341 | }, 342 | { 343 | "resourceURI": "http://gateway.marvel.com/v1/public/events/302", 344 | "name": "Fear Itself" 345 | }, 346 | { 347 | "resourceURI": "http://gateway.marvel.com/v1/public/events/251", 348 | "name": "House of M" 349 | }, 350 | { 351 | "resourceURI": "http://gateway.marvel.com/v1/public/events/252", 352 | "name": "Inferno" 353 | }, 354 | { 355 | "resourceURI": "http://gateway.marvel.com/v1/public/events/253", 356 | "name": "Infinity Gauntlet" 357 | }, 358 | { 359 | "resourceURI": "http://gateway.marvel.com/v1/public/events/255", 360 | "name": "Initiative" 361 | }, 362 | { 363 | "resourceURI": "http://gateway.marvel.com/v1/public/events/258", 364 | "name": "Kraven's Last Hunt" 365 | }, 366 | { 367 | "resourceURI": "http://gateway.marvel.com/v1/public/events/151", 368 | "name": "Maximum Carnage" 369 | }, 370 | { 371 | "resourceURI": "http://gateway.marvel.com/v1/public/events/37", 372 | "name": "Maximum Security" 373 | }, 374 | { 375 | "resourceURI": "http://gateway.marvel.com/v1/public/events/154", 376 | "name": "Onslaught" 377 | }, 378 | { 379 | "resourceURI": "http://gateway.marvel.com/v1/public/events/266", 380 | "name": "Other - Evolve or Die" 381 | }, 382 | { 383 | "resourceURI": "http://gateway.marvel.com/v1/public/events/269", 384 | "name": "Secret Invasion" 385 | } 386 | ], 387 | "returned": 20 388 | }, 389 | "urls": [ 390 | { 391 | "type": "detail", 392 | "url": "http://marvel.com/comics/characters/1009610/spider-man?utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 393 | }, 394 | { 395 | "type": "wiki", 396 | "url": "http://marvel.com/universe/Spider-Man_(Peter_Parker)?utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 397 | } 398 | ] 399 | } 400 | ] 401 | } 402 | } -------------------------------------------------------------------------------- /spec/fixtures/stories/story_series.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 200, 3 | "status": "Ok", 4 | "copyright": "© 2014 MARVEL", 5 | "attributionText": "Data provided by Marvel. © 2014 MARVEL", 6 | "attributionHTML": "Data provided by Marvel. © 2014 MARVEL", 7 | "etag": "3b5201c90a6e0a421588e242f9b4f9fdcce9f870", 8 | "data": { 9 | "offset": 0, 10 | "limit": 20, 11 | "total": 1, 12 | "count": 1, 13 | "results": [ 14 | { 15 | "id": 632, 16 | "title": "Wolverine (2003 - 2009)", 17 | "description": "A new decade means new mayhem for the X-Men's wildest member! Revisit memorable stories like Mark Millar and John Romita Jr.'s \"Enemy of the State,\" featuring Logan as the Marvel Universe's worst nightmare, and \"Evolution\" by Jeph Loeb and Simone Bianchi, exploring the true history of Wolverine!", 18 | "resourceURI": "http://gateway.marvel.com/v1/public/series/632", 19 | "urls": [ 20 | { 21 | "type": "detail", 22 | "url": "http://marvel.com/comics/series/632/wolverine_2003_-_2009?utm_campaign=apiRef&utm_source=94f945fe8833c9a96e6f761b60562a45" 23 | } 24 | ], 25 | "startYear": 2003, 26 | "endYear": 2009, 27 | "rating": "Parental Advisory", 28 | "type": "", 29 | "modified": "2013-03-01T15:53:32-0500", 30 | "thumbnail": { 31 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/2/f0/513114d9f116d", 32 | "extension": "jpg" 33 | }, 34 | "creators": { 35 | "available": 64, 36 | "collectionURI": "http://gateway.marvel.com/v1/public/series/632/creators", 37 | "items": [ 38 | { 39 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/11463", 40 | "name": "Jason Aaron", 41 | "role": "writer" 42 | }, 43 | { 44 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/644", 45 | "name": "Marc Guggenheim", 46 | "role": "writer" 47 | }, 48 | { 49 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/4014", 50 | "name": "Axel Alonso", 51 | "role": "editor" 52 | }, 53 | { 54 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/191", 55 | "name": "Kaare Andrews", 56 | "role": "penciller" 57 | }, 58 | { 59 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/648", 60 | "name": "Simone Bianchi", 61 | "role": "penciller" 62 | }, 63 | { 64 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/645", 65 | "name": "Laurence Campbell", 66 | "role": "penciller" 67 | }, 68 | { 69 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/10288", 70 | "name": "Marko Djurdjevic", 71 | "role": "penciller" 72 | }, 73 | { 74 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/273", 75 | "name": "Leandro Fernandez", 76 | "role": "penciller" 77 | }, 78 | { 79 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/808", 80 | "name": "Howard Chaykin", 81 | "role": "inker" 82 | }, 83 | { 84 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/429", 85 | "name": "Carlos Alberto cruz Cuevas", 86 | "role": "inker" 87 | }, 88 | { 89 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/589", 90 | "name": "Nelson DeCastro", 91 | "role": "inker" 92 | }, 93 | { 94 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/440", 95 | "name": "Mark Farmer", 96 | "role": "inker" 97 | }, 98 | { 99 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/638", 100 | "name": "Edgar Clement", 101 | "role": "colorist" 102 | }, 103 | { 104 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/430", 105 | "name": "Edgar Delgado", 106 | "role": "colorist" 107 | }, 108 | { 109 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/236", 110 | "name": "Tommy Lee Edwards", 111 | "role": "colorist" 112 | }, 113 | { 114 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/4258", 115 | "name": "Studio F", 116 | "role": "colorist" 117 | }, 118 | { 119 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/10454", 120 | "name": "Nathan Fairbairn", 121 | "role": "colorist" 122 | }, 123 | { 124 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/452", 125 | "name": "Chris Eliopoulos", 126 | "role": "letterer" 127 | }, 128 | { 129 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/8635", 130 | "name": "Randy Gentile", 131 | "role": "letterer" 132 | }, 133 | { 134 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/120", 135 | "name": "Ron Garney", 136 | "role": "artist" 137 | } 138 | ], 139 | "returned": 20 140 | }, 141 | "characters": { 142 | "available": 17, 143 | "collectionURI": "http://gateway.marvel.com/v1/public/series/632/characters", 144 | "items": [ 145 | { 146 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009144", 147 | "name": "A.I.M." 148 | }, 149 | { 150 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009175", 151 | "name": "Beast" 152 | }, 153 | { 154 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009257", 155 | "name": "Cyclops" 156 | }, 157 | { 158 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009288", 159 | "name": "Elektra" 160 | }, 161 | { 162 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009310", 163 | "name": "Emma Frost" 164 | }, 165 | { 166 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009324", 167 | "name": "Gorgon" 168 | }, 169 | { 170 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009368", 171 | "name": "Iron Man" 172 | }, 173 | { 174 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009508", 175 | "name": "Kitty Pryde" 176 | }, 177 | { 178 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1010954", 179 | "name": "Mystique (House of M)" 180 | }, 181 | { 182 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009471", 183 | "name": "Nick Fury" 184 | }, 185 | { 186 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1010797", 187 | "name": "Nitro" 188 | }, 189 | { 190 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009430", 191 | "name": "Rachel Grey" 192 | }, 193 | { 194 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009554", 195 | "name": "Sabretooth" 196 | }, 197 | { 198 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009570", 199 | "name": "Sentinel" 200 | }, 201 | { 202 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009629", 203 | "name": "Storm" 204 | }, 205 | { 206 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009718", 207 | "name": "Wolverine" 208 | }, 209 | { 210 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009726", 211 | "name": "X-Men" 212 | } 213 | ], 214 | "returned": 17 215 | }, 216 | "stories": { 217 | "available": 210, 218 | "collectionURI": "http://gateway.marvel.com/v1/public/series/632/stories", 219 | "items": [ 220 | { 221 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1050", 222 | "name": "Cover #1050", 223 | "type": "cover" 224 | }, 225 | { 226 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1051", 227 | "name": "Interior #1051", 228 | "type": "interiorStory" 229 | }, 230 | { 231 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1498", 232 | "name": "Cover #1498", 233 | "type": "cover" 234 | }, 235 | { 236 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1499", 237 | "name": "Interior #1499", 238 | "type": "interiorStory" 239 | }, 240 | { 241 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1766", 242 | "name": "Cover #1766", 243 | "type": "cover" 244 | }, 245 | { 246 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1767", 247 | "name": "Interior #1767", 248 | "type": "interiorStory" 249 | }, 250 | { 251 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1802", 252 | "name": "Cover #1802", 253 | "type": "cover" 254 | }, 255 | { 256 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1803", 257 | "name": "Interior #1803", 258 | "type": "interiorStory" 259 | }, 260 | { 261 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1911", 262 | "name": "Cover #1911", 263 | "type": "cover" 264 | }, 265 | { 266 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/1912", 267 | "name": "Interior #1912", 268 | "type": "interiorStory" 269 | }, 270 | { 271 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2153", 272 | "name": "3 of 6 - Enemy of the State", 273 | "type": "cover" 274 | }, 275 | { 276 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2154", 277 | "name": "3 of 6 - Enemy of the State", 278 | "type": "interiorStory" 279 | }, 280 | { 281 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2166", 282 | "name": "Cover #2166", 283 | "type": "cover" 284 | }, 285 | { 286 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2167", 287 | "name": "Interior #2167", 288 | "type": "interiorStory" 289 | }, 290 | { 291 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2168", 292 | "name": "Cover #2168", 293 | "type": "cover" 294 | }, 295 | { 296 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2169", 297 | "name": "Interior #2169", 298 | "type": "interiorStory" 299 | }, 300 | { 301 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2170", 302 | "name": "Cover #2170", 303 | "type": "cover" 304 | }, 305 | { 306 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2171", 307 | "name": "Interior #2171", 308 | "type": "interiorStory" 309 | }, 310 | { 311 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2172", 312 | "name": "Cover #2172", 313 | "type": "cover" 314 | }, 315 | { 316 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/2173", 317 | "name": "Interior #2173", 318 | "type": "interiorStory" 319 | } 320 | ], 321 | "returned": 20 322 | }, 323 | "comics": { 324 | "available": 95, 325 | "collectionURI": "http://gateway.marvel.com/v1/public/series/632/comics", 326 | "items": [ 327 | { 328 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/14225", 329 | "name": "Wolverine (2003) #1" 330 | }, 331 | { 332 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/14236", 333 | "name": "Wolverine (2003) #2" 334 | }, 335 | { 336 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/14247", 337 | "name": "Wolverine (2003) #3" 338 | }, 339 | { 340 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/14259", 341 | "name": "Wolverine (2003) #4" 342 | }, 343 | { 344 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/14264", 345 | "name": "Wolverine (2003) #5" 346 | }, 347 | { 348 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/234", 349 | "name": "Wolverine (2003) #6" 350 | }, 351 | { 352 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/233", 353 | "name": "Wolverine (2003) #7" 354 | }, 355 | { 356 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/268", 357 | "name": "Wolverine (2003) #8" 358 | }, 359 | { 360 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/231", 361 | "name": "Wolverine (2003) #9" 362 | }, 363 | { 364 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/237", 365 | "name": "Wolverine (2003) #10" 366 | }, 367 | { 368 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/236", 369 | "name": "Wolverine (2003) #11" 370 | }, 371 | { 372 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/427", 373 | "name": "Wolverine (2003) #12" 374 | }, 375 | { 376 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/464", 377 | "name": "Wolverine (2003) #13" 378 | }, 379 | { 380 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/490", 381 | "name": "Wolverine (2003) #14" 382 | }, 383 | { 384 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/658", 385 | "name": "Wolverine (2003) #15" 386 | }, 387 | { 388 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/718", 389 | "name": "Wolverine (2003) #16" 390 | }, 391 | { 392 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/527", 393 | "name": "Wolverine (2003) #17" 394 | }, 395 | { 396 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/760", 397 | "name": "Wolverine (2003) #18" 398 | }, 399 | { 400 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/828", 401 | "name": "Wolverine (2003) #19" 402 | }, 403 | { 404 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/860", 405 | "name": "Wolverine (2003) #20" 406 | } 407 | ], 408 | "returned": 20 409 | }, 410 | "events": { 411 | "available": 3, 412 | "collectionURI": "http://gateway.marvel.com/v1/public/series/632/events", 413 | "items": [ 414 | { 415 | "resourceURI": "http://gateway.marvel.com/v1/public/events/238", 416 | "name": "Civil War" 417 | }, 418 | { 419 | "resourceURI": "http://gateway.marvel.com/v1/public/events/245", 420 | "name": "Enemy of the State" 421 | }, 422 | { 423 | "resourceURI": "http://gateway.marvel.com/v1/public/events/251", 424 | "name": "House of M" 425 | } 426 | ], 427 | "returned": 3 428 | }, 429 | "next": { 430 | "resourceURI": "http://gateway.marvel.com/v1/public/series/7057", 431 | "name": "Wolverine: Weapon X (2009 - Present)" 432 | }, 433 | "previous": { 434 | "resourceURI": "http://gateway.marvel.com/v1/public/series/2262", 435 | "name": "Wolverine (1988 - 2003)" 436 | } 437 | } 438 | ] 439 | } 440 | } -------------------------------------------------------------------------------- /spec/fixtures/comics/comic_events.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 200, 3 | "status": "Ok", 4 | "etag": "bf71234f85f371a1b0c9a05b567f252745471eb6", 5 | "data": { 6 | "offset": 0, 7 | "limit": 20, 8 | "total": 1, 9 | "count": 1, 10 | "results": [ 11 | { 12 | "id": 310, 13 | "title": "Avengers VS X-Men", 14 | "description": "A 12-issue event written by the unprecedented team of Brian Michael Bendis, Jason Aaron, Jonathan Hickman, Ed Brubaker and Matt Fraction with art by the blockbuster trio of John Romita Jr., Olivier Coipel and Adam Kubert, Avengers VS X-Men brings Marvel's biggest characters up against the greatest threat they've ever faced: each other!", 15 | "resourceURI": "http://gateway.marvel.com/v1/public/events/310", 16 | "urls": [ 17 | { 18 | "type": "detail", 19 | "url": "http://marvel.com/comics/events/310/avengers_vs_x-men?utm_campaign=apiRef&utm_source=85ec0830b5958f4f46ea2fa898a76ef2" 20 | } 21 | ], 22 | "modified": "2013-07-01T21:41:57-0400", 23 | "start": "2012-04-04 00:00:00", 24 | "end": "2012-09-19 00:00:00", 25 | "thumbnail": { 26 | "path": "http://i.annihil.us/u/prod/marvel/i/mg/3/20/5109a1f93b543", 27 | "extension": "jpg" 28 | }, 29 | "creators": { 30 | "available": 68, 31 | "collectionURI": "http://gateway.marvel.com/v1/public/events/310/creators", 32 | "items": [ 33 | { 34 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/8571", 35 | "name": "Guru-eFX", 36 | "role": "Colorist" 37 | }, 38 | { 39 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/520", 40 | "name": "Rainier Beredo", 41 | "role": "Colorist" 42 | }, 43 | { 44 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/11494", 45 | "name": "Bettie Breitweiser", 46 | "role": "Colorist" 47 | }, 48 | { 49 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/2133", 50 | "name": "Tom Brevoort", 51 | "role": "Colorist" 52 | }, 53 | { 54 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/9937", 55 | "name": "Jim Charalampidis", 56 | "role": "Colorist" 57 | }, 58 | { 59 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/11463", 60 | "name": "Jason Aaron", 61 | "role": "Writer" 62 | }, 63 | { 64 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/24", 65 | "name": "Brian Michael Bendis", 66 | "role": "Writer" 67 | }, 68 | { 69 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/1004", 70 | "name": "Daniel Acuna", 71 | "role": "Penciller" 72 | }, 73 | { 74 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/11798", 75 | "name": "Matteo Buffagni", 76 | "role": "Penciller" 77 | }, 78 | { 79 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/16", 80 | "name": "Alan Davis", 81 | "role": "Penciller" 82 | }, 83 | { 84 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/232", 85 | "name": "Chris Bachalo", 86 | "role": "artist" 87 | }, 88 | { 89 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/9799", 90 | "name": "David Baldeon", 91 | "role": "artist" 92 | }, 93 | { 94 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/1192", 95 | "name": "Ian Churchill", 96 | "role": "artist" 97 | }, 98 | { 99 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/6170", 100 | "name": "Olivier Coipel", 101 | "role": "artist" 102 | }, 103 | { 104 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/11875", 105 | "name": "Nick Bradshaw", 106 | "role": "penciller (cover)" 107 | }, 108 | { 109 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/694", 110 | "name": "Mark Brooks", 111 | "role": "penciller (cover)" 112 | }, 113 | { 114 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/1141", 115 | "name": "Giuseppe Camuncoli", 116 | "role": "penciller (cover)" 117 | }, 118 | { 119 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/357", 120 | "name": "Jim Cheung", 121 | "role": "penciller (cover)" 122 | }, 123 | { 124 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/367", 125 | "name": "Ed Brubaker", 126 | "role": "writer" 127 | }, 128 | { 129 | "resourceURI": "http://gateway.marvel.com/v1/public/creators/5251", 130 | "name": "Joe Caramagna", 131 | "role": "letterer" 132 | } 133 | ], 134 | "returned": 20 135 | }, 136 | "characters": { 137 | "available": 34, 138 | "collectionURI": "http://gateway.marvel.com/v1/public/events/310/characters", 139 | "items": [ 140 | { 141 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009165", 142 | "name": "Avengers" 143 | }, 144 | { 145 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009175", 146 | "name": "Beast" 147 | }, 148 | { 149 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009189", 150 | "name": "Black Widow" 151 | }, 152 | { 153 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009214", 154 | "name": "Cable" 155 | }, 156 | { 157 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009220", 158 | "name": "Captain America" 159 | }, 160 | { 161 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009223", 162 | "name": "Captain Britain" 163 | }, 164 | { 165 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1010338", 166 | "name": "Captain Marvel (Carol Danvers)" 167 | }, 168 | { 169 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009243", 170 | "name": "Colossus" 171 | }, 172 | { 173 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009257", 174 | "name": "Cyclops" 175 | }, 176 | { 177 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009282", 178 | "name": "Doctor Strange" 179 | }, 180 | { 181 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009310", 182 | "name": "Emma Frost" 183 | }, 184 | { 185 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009313", 186 | "name": "Gambit" 187 | }, 188 | { 189 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009338", 190 | "name": "Hawkeye" 191 | }, 192 | { 193 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1011428", 194 | "name": "Hope Summers" 195 | }, 196 | { 197 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009351", 198 | "name": "Hulk" 199 | }, 200 | { 201 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009367", 202 | "name": "Iron Fist (Danny Rand)" 203 | }, 204 | { 205 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009368", 206 | "name": "Iron Man" 207 | }, 208 | { 209 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009538", 210 | "name": "Iron Patriot (James Rhodes)" 211 | }, 212 | { 213 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009382", 214 | "name": "Juggernaut" 215 | }, 216 | { 217 | "resourceURI": "http://gateway.marvel.com/v1/public/characters/1009215", 218 | "name": "Luke Cage" 219 | } 220 | ], 221 | "returned": 20 222 | }, 223 | "stories": { 224 | "available": 128, 225 | "collectionURI": "http://gateway.marvel.com/v1/public/events/310/stories", 226 | "items": [ 227 | { 228 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/77811", 229 | "name": "Cover #77811", 230 | "type": "cover" 231 | }, 232 | { 233 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/77812", 234 | "name": "Interior #77812", 235 | "type": "interiorStory" 236 | }, 237 | { 238 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/84703", 239 | "name": "Cover #84703", 240 | "type": "cover" 241 | }, 242 | { 243 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/84704", 244 | "name": "Interior #84704", 245 | "type": "interiorStory" 246 | }, 247 | { 248 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/90279", 249 | "name": "Cover #90279", 250 | "type": "cover" 251 | }, 252 | { 253 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/90281", 254 | "name": "Avengers: X-​Sanction (2011) #3", 255 | "type": "cover" 256 | }, 257 | { 258 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/90282", 259 | "name": "Interior #90282", 260 | "type": "interiorStory" 261 | }, 262 | { 263 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/90331", 264 | "name": "Interior #90331", 265 | "type": "interiorStory" 266 | }, 267 | { 268 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/90964", 269 | "name": "Cover #90964", 270 | "type": "cover" 271 | }, 272 | { 273 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/90965", 274 | "name": "Interior #90965", 275 | "type": "interiorStory" 276 | }, 277 | { 278 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/91099", 279 | "name": "Cover #91099", 280 | "type": "cover" 281 | }, 282 | { 283 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/91100", 284 | "name": "Interior #91100", 285 | "type": "interiorStory" 286 | }, 287 | { 288 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/91101", 289 | "name": "Cover #91101", 290 | "type": "cover" 291 | }, 292 | { 293 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/91102", 294 | "name": "Interior #91102", 295 | "type": "interiorStory" 296 | }, 297 | { 298 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/91103", 299 | "name": "Cover #91103", 300 | "type": "cover" 301 | }, 302 | { 303 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/91104", 304 | "name": "Interior #91104", 305 | "type": "interiorStory" 306 | }, 307 | { 308 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/91107", 309 | "name": "Cover #91107", 310 | "type": "cover" 311 | }, 312 | { 313 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/91108", 314 | "name": "Interior #91108", 315 | "type": "interiorStory" 316 | }, 317 | { 318 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/91117", 319 | "name": "Cover #91117", 320 | "type": "cover" 321 | }, 322 | { 323 | "resourceURI": "http://gateway.marvel.com/v1/public/stories/91118", 324 | "name": "Interior #91118", 325 | "type": "interiorStory" 326 | } 327 | ], 328 | "returned": 20 329 | }, 330 | "comics": { 331 | "available": 44, 332 | "collectionURI": "http://gateway.marvel.com/v1/public/events/310/comics", 333 | "items": [ 334 | { 335 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/35232", 336 | "name": "Avengers (2010) #24" 337 | }, 338 | { 339 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/40405", 340 | "name": "Avengers (2010) #25" 341 | }, 342 | { 343 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/40410", 344 | "name": "Avengers (2010) #26" 345 | }, 346 | { 347 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/40249", 348 | "name": "Avengers Academy (2010) #26" 349 | }, 350 | { 351 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/40251", 352 | "name": "Avengers Academy (2010) #29" 353 | }, 354 | { 355 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/40250", 356 | "name": "Avengers Academy (2010) #30" 357 | }, 358 | { 359 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/40253", 360 | "name": "Avengers Academy (2010) #31" 361 | }, 362 | { 363 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/40254", 364 | "name": "Avengers Academy (2010) #32" 365 | }, 366 | { 367 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/40264", 368 | "name": "Avengers Academy (2010) #33" 369 | }, 370 | { 371 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/40258", 372 | "name": "Avengers Academy (2010) #34" 373 | }, 374 | { 375 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/41188", 376 | "name": "Avengers VS X-Men (2012) #1" 377 | }, 378 | { 379 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/41191", 380 | "name": "Avengers VS X-Men (2012) #2" 381 | }, 382 | { 383 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/41187", 384 | "name": "Avengers VS X-Men (2012) #3" 385 | }, 386 | { 387 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/41193", 388 | "name": "Avengers VS X-Men (2012) #4" 389 | }, 390 | { 391 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/41190", 392 | "name": "Avengers VS X-Men (2012) #5" 393 | }, 394 | { 395 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/41189", 396 | "name": "Avengers VS X-Men (2012) #6" 397 | }, 398 | { 399 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/41192", 400 | "name": "Avengers VS X-Men (2012) #7" 401 | }, 402 | { 403 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/41275", 404 | "name": "Avengers VS X-Men (2012) #8" 405 | }, 406 | { 407 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/41277", 408 | "name": "Avengers VS X-Men (2012) #9" 409 | }, 410 | { 411 | "resourceURI": "http://gateway.marvel.com/v1/public/comics/41276", 412 | "name": "Avengers VS X-Men (2012) #10" 413 | } 414 | ], 415 | "returned": 20 416 | }, 417 | "series": { 418 | "available": 9, 419 | "collectionURI": "http://gateway.marvel.com/v1/public/events/310/series", 420 | "items": [ 421 | { 422 | "resourceURI": "http://gateway.marvel.com/v1/public/series/9085", 423 | "name": "Avengers (2010 - 2012)" 424 | }, 425 | { 426 | "resourceURI": "http://gateway.marvel.com/v1/public/series/9086", 427 | "name": "Avengers Academy (2010 - 2012)" 428 | }, 429 | { 430 | "resourceURI": "http://gateway.marvel.com/v1/public/series/15305", 431 | "name": "Avengers VS X-Men (2012)" 432 | }, 433 | { 434 | "resourceURI": "http://gateway.marvel.com/v1/public/series/14703", 435 | "name": "Avengers: X-Sanction (2011 - 2012)" 436 | }, 437 | { 438 | "resourceURI": "http://gateway.marvel.com/v1/public/series/9922", 439 | "name": "New Avengers (2010 - 2012)" 440 | }, 441 | { 442 | "resourceURI": "http://gateway.marvel.com/v1/public/series/9799", 443 | "name": "Secret Avengers (2010 - 2012)" 444 | }, 445 | { 446 | "resourceURI": "http://gateway.marvel.com/v1/public/series/14914", 447 | "name": "Uncanny X-Men (2011 - 2012)" 448 | }, 449 | { 450 | "resourceURI": "http://gateway.marvel.com/v1/public/series/13910", 451 | "name": "Wolverine & the X-Men (2011 - Present)" 452 | }, 453 | { 454 | "resourceURI": "http://gateway.marvel.com/v1/public/series/3754", 455 | "name": "X-Men Legacy (2008 - 2012)" 456 | } 457 | ], 458 | "returned": 9 459 | }, 460 | "next": { 461 | "resourceURI": "http://gateway.marvel.com/v1/public/events/311", 462 | "name": "Marvel NOW!" 463 | }, 464 | "previous": { 465 | "resourceURI": "http://gateway.marvel.com/v1/public/events/309", 466 | "name": "Shattered Heroes" 467 | } 468 | } 469 | ] 470 | } 471 | } --------------------------------------------------------------------------------