apress-api 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.drone.yml +30 -0
- data/.gitignore +15 -0
- data/.rspec +4 -0
- data/Appraisals +31 -0
- data/CHANGELOG.md +227 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +2 -0
- data/app/controllers/apress/api/deprecated_versions_controller.rb +15 -0
- data/app/controllers/apress/api/v1/callbacks_controller.rb +30 -0
- data/app/controllers/apress/api/v1/tokens_controller.rb +24 -0
- data/app/docs/schema/api/v1/types/apress/api/link.rb +29 -0
- data/app/docs/schema/api/v1/types/apress/api/links.rb +24 -0
- data/app/docs/swagger/v1/controllers/apress/api/tokens_controller.rb +64 -0
- data/app/docs/swagger/v1/default_responses/bad_request.rb +16 -0
- data/app/docs/swagger/v1/default_responses/not_found.rb +16 -0
- data/app/docs/swagger/v1/default_responses/unauthenticated.rb +16 -0
- data/app/docs/swagger/v1/default_responses/unauthorized.rb +16 -0
- data/app/docs/swagger/v1/default_responses/unprocessable.rb +16 -0
- data/app/docs/swagger/v1/default_responses/updates_locked.rb +13 -0
- data/app/docs/swagger/v1/models/apress/api/client.rb +53 -0
- data/app/docs/swagger/v1/models/apress/api/simple_error.rb +27 -0
- data/app/docs/swagger/v1/models/apress/api/unproccesable_error.rb +16 -0
- data/app/docs/swagger/v1/models/apress/api/unprocessable_error.rb +37 -0
- data/app/docs/swagger/v1/root.rb +28 -0
- data/app/interactors/apress/api/callbacks/base_callback.rb +42 -0
- data/app/interactors/apress/api/delayed_fire_callback.rb +25 -0
- data/app/jobs/apress/api/event_handler_enqueueing_job.rb +19 -0
- data/app/jobs/apress/api/fire_callback_job.rb +25 -0
- data/app/models/apress/api/client.rb +60 -0
- data/app/policies/apress/api/callback_policy.rb +15 -0
- data/app/services/apress/api/auth_service.rb +37 -0
- data/app/views/apress/api/shared/_exception.json.jbuilder +4 -0
- data/app/views/apress/api/shared/error.json.jbuilder +5 -0
- data/app/views/apress/api/shared/parameter_missing_errors.json.jbuilder +9 -0
- data/app/views/apress/api/shared/unprocessable_errors.json.jbuilder +9 -0
- data/app/views/apress/api/v1/clients/_client.json.jbuilder +2 -0
- data/app/views/apress/api/v1/tokens/create.json.jbuilder +4 -0
- data/apress-api.gemspec +46 -0
- data/config/routes.rb +17 -0
- data/db/migrate/20150716000000_create_api_clients.rb +38 -0
- data/dip.yml +48 -0
- data/docker-compose.development.yml +18 -0
- data/docker-compose.drone.yml +7 -0
- data/docker-compose.yml +20 -0
- data/lib/apress-api.rb +1 -0
- data/lib/apress/api.rb +25 -0
- data/lib/apress/api/api_controller/authentification.rb +33 -0
- data/lib/apress/api/api_controller/base.rb +63 -0
- data/lib/apress/api/api_controller/compatibility.rb +26 -0
- data/lib/apress/api/api_controller/pagination.rb +60 -0
- data/lib/apress/api/api_controller/pagination_helper.rb +55 -0
- data/lib/apress/api/api_controller/rescue.rb +89 -0
- data/lib/apress/api/api_controller/responds.rb +25 -0
- data/lib/apress/api/callbacks/config.rb +56 -0
- data/lib/apress/api/callbacks/fire_callback_error.rb +12 -0
- data/lib/apress/api/callbacks/integration.rb +28 -0
- data/lib/apress/api/callbacks/repeat_callback_error.rb +12 -0
- data/lib/apress/api/engine.rb +33 -0
- data/lib/apress/api/extensions/jbuilder/jbuilder_template.rb +41 -0
- data/lib/apress/api/rspec.rb +48 -0
- data/lib/apress/api/rspec/utils.rb +17 -0
- data/lib/apress/api/testing/json_matcher.rb +9 -0
- data/lib/apress/api/version.rb +5 -0
- data/lib/tasks/docs.rake +12 -0
- data/spec/controllers/api_controller/authentification_spec.rb +79 -0
- data/spec/controllers/api_controller/pagination_spec.rb +199 -0
- data/spec/controllers/api_controller/rescue_spec.rb +167 -0
- data/spec/controllers/deprecated_versions_controller_spec.rb +10 -0
- data/spec/controllers/v1/callbacks_controller_spec.rb +50 -0
- data/spec/controllers/v1/tokens_controller_spec.rb +53 -0
- data/spec/factories/client_factory.rb +4 -0
- data/spec/helpers/paginating_cache_spec.rb +72 -0
- data/spec/interactors/apress/api/delayed_fire_callback_spec.rb +43 -0
- data/spec/internal/app/integrations/error_client/fire_callback.rb +14 -0
- data/spec/internal/app/integrations/service_client/fire_callback.rb +7 -0
- data/spec/internal/app/jobs/handler_job.rb +5 -0
- data/spec/internal/app/jobs/second_handler_job.rb +5 -0
- data/spec/internal/app/models/dummy_model.rb +15 -0
- data/spec/internal/config/database.yml +5 -0
- data/spec/internal/config/environments/test.rb +5 -0
- data/spec/internal/config/initializers/api.rb +10 -0
- data/spec/internal/config/routes.rb +3 -0
- data/spec/internal/db/schema.rb +5 -0
- data/spec/internal/log/.gitignore +1 -0
- data/spec/jobs/apress/api/event_handler_equeueing_job_spec.rb +31 -0
- data/spec/jobs/apress/api/fire_callback_job_spec.rb +34 -0
- data/spec/lib/apress/api/callbacks/integration_spec.rb +24 -0
- data/spec/models/client_spec.rb +25 -0
- data/spec/services/auth_service_spec.rb +64 -0
- data/spec/spec_helper.rb +34 -0
- metadata +518 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'rails/engine'
|
|
2
|
+
|
|
3
|
+
module Apress
|
|
4
|
+
module Api
|
|
5
|
+
class Engine < Rails::Engine
|
|
6
|
+
config.autoload_paths << config.root.join("lib")
|
|
7
|
+
config.paths.add 'app/docs', eager_load: false
|
|
8
|
+
|
|
9
|
+
Apress::Documentation.add_load_path(config.root.join('app/docs'))
|
|
10
|
+
|
|
11
|
+
initializer "apress-api", before: :load_init_rb do |app|
|
|
12
|
+
app.config.paths["db/migrate"].concat(config.paths["db/migrate"].expanded)
|
|
13
|
+
|
|
14
|
+
app.config.api = {
|
|
15
|
+
secret_token_ttl: 1.hour,
|
|
16
|
+
refresh_token_ttl: 1.week,
|
|
17
|
+
v1_doc_path: 'docs/swagger/v1.json'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
::MultiJson.use :oj
|
|
21
|
+
|
|
22
|
+
require 'jbuilder/jbuilder_template'
|
|
23
|
+
JbuilderTemplate.send :include, Apress::Api::Extensions::Jbuilder::JbuilderTemplate
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
initializer "apress-api-factories", after: "factory_girl.set_factory_paths" do
|
|
27
|
+
if defined?(FactoryGirl)
|
|
28
|
+
FactoryGirl.definition_file_paths.unshift root.join("spec", "factories")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Apress
|
|
2
|
+
module Api
|
|
3
|
+
module Extensions
|
|
4
|
+
module Jbuilder
|
|
5
|
+
module JbuilderTemplate
|
|
6
|
+
def paginating_cache!(collection, key = nil, options = nil)
|
|
7
|
+
if @context.controller.perform_caching
|
|
8
|
+
result = Rails.cache.fetch(_cache_key(key || collection, options), options) do
|
|
9
|
+
{
|
|
10
|
+
headers: _pagination_headers(collection),
|
|
11
|
+
content: _scope { yield self }
|
|
12
|
+
}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
_set_pagination_headers(result[:headers])
|
|
16
|
+
|
|
17
|
+
merge! result[:content]
|
|
18
|
+
else
|
|
19
|
+
_set_pagination_headers(_pagination_headers(collection))
|
|
20
|
+
|
|
21
|
+
yield
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def _set_pagination_headers(headers)
|
|
28
|
+
@context.controller.response.headers.merge!(headers)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def _pagination_headers(collection)
|
|
32
|
+
::Apress::Api::ApiController::PaginationHelper.headers(
|
|
33
|
+
collection,
|
|
34
|
+
@context.controller.request.url
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
require 'rspec/core'
|
|
3
|
+
require 'rspec/expectations'
|
|
4
|
+
require 'swagger'
|
|
5
|
+
|
|
6
|
+
require_relative 'rspec/utils'
|
|
7
|
+
|
|
8
|
+
RSpec::Matchers.define :correspond_to_schema do |schema, options|
|
|
9
|
+
match do |response|
|
|
10
|
+
if schema.present?
|
|
11
|
+
options ||= {}
|
|
12
|
+
JSON::Validator.validate!(schema, response.body.to_s, options)
|
|
13
|
+
else
|
|
14
|
+
true
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# NOTE: Для того, чтобы находить нужную спецификацию ресурса по конкретному запросу (request.path),
|
|
20
|
+
# нужно уметь находить соответсвие Path -> URITemplatePath
|
|
21
|
+
RSpec.shared_examples 'an api response' do |status|
|
|
22
|
+
let(:method) { request.method.downcase.to_sym }
|
|
23
|
+
let(:schema) do
|
|
24
|
+
begin
|
|
25
|
+
schema = @api.paths[resource][method].responses[response.code].schema
|
|
26
|
+
schema.definitions = @api.definitions if schema.present?
|
|
27
|
+
schema
|
|
28
|
+
rescue
|
|
29
|
+
fail "Swagger schema does not exist: #{dump_response}"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it { expect(response).to have_http_status(status).and correspond_to_schema(schema) }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
RSpec.configure do |c|
|
|
37
|
+
c.include Apress::Api::Rspec::Utils, type: :request
|
|
38
|
+
|
|
39
|
+
c.before(:context, :api) do
|
|
40
|
+
classes = Apress::Api::Swagger::Schema.swagger_classes
|
|
41
|
+
@swagger_schema = ::Swagger::Blocks.build_root_json(classes)
|
|
42
|
+
@api = Swagger.build(@swagger_schema.to_json, format: :json)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
c.after(:example, :verbose, type: :request) do
|
|
46
|
+
puts dump_response
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
module Apress
|
|
4
|
+
module Api
|
|
5
|
+
module Rspec
|
|
6
|
+
module Utils
|
|
7
|
+
def dump_response
|
|
8
|
+
<<-EOS.strip_heredoc
|
|
9
|
+
Request: #{request.method} #{request.original_url}
|
|
10
|
+
Status: #{response.code}
|
|
11
|
+
#{JSON.pretty_generate(JSON.parse(response.body.to_s))}
|
|
12
|
+
EOS
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/tasks/docs.rake
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
namespace :docs do
|
|
2
|
+
desc 'Generate api documentation'
|
|
3
|
+
task generate: :environment do
|
|
4
|
+
filename = 'swagger_v1.json'
|
|
5
|
+
path = Rails.application.config.api[:v1_doc_path]
|
|
6
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
7
|
+
|
|
8
|
+
Apress::Api::Swagger::Generator.new(path).generate_file
|
|
9
|
+
|
|
10
|
+
puts 'Done.'
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Apress::Api::ApiController::Base, type: :controller do
|
|
4
|
+
let(:client) { create "api/client" }
|
|
5
|
+
|
|
6
|
+
context "when api client is required, by default" do
|
|
7
|
+
controller do
|
|
8
|
+
def index
|
|
9
|
+
render json: {status: "ok"}
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe "#authenticate" do
|
|
14
|
+
before do
|
|
15
|
+
class_double(Apress::Api::AuthService, new: auth_service).as_stubbed_const
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context "when auth successfull" do
|
|
19
|
+
let(:auth_service) { double("auth_service", call: true, client: client) }
|
|
20
|
+
|
|
21
|
+
it "assigns current_api_client" do
|
|
22
|
+
get :index
|
|
23
|
+
expect(response.status).to eq 200
|
|
24
|
+
expect(controller.current_api_client).to eq client
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context "when auth failed" do
|
|
29
|
+
let(:auth_service) { double("auth_service", call: false, client: nil) }
|
|
30
|
+
|
|
31
|
+
it "returns 403" do
|
|
32
|
+
get :index
|
|
33
|
+
expect(response.status).to eq 403
|
|
34
|
+
expect(controller.current_api_client).to be nil
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context "when api client is optional" do
|
|
41
|
+
controller do
|
|
42
|
+
if (Rails::VERSION::MAJOR == 4 && Rails::VERSION::MINOR == 2) || Rails::VERSION::MAJOR > 4
|
|
43
|
+
skip_before_action :authenticate
|
|
44
|
+
else
|
|
45
|
+
skip_before_filter :authenticate
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def index
|
|
49
|
+
render json: {status: "ok"}
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe "#authenticate" do
|
|
54
|
+
before do
|
|
55
|
+
class_double(Apress::Api::AuthService, new: auth_service).as_stubbed_const
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context "when auth successfull" do
|
|
59
|
+
let(:auth_service) { double("auth_service", call: true, client: client) }
|
|
60
|
+
|
|
61
|
+
it "assigns current_api_client" do
|
|
62
|
+
get :index
|
|
63
|
+
expect(response.status).to eq 200
|
|
64
|
+
expect(controller.current_api_client).to eq client
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
context "when auth failed" do
|
|
69
|
+
let(:auth_service) { double("auth_service", call: false, client: nil) }
|
|
70
|
+
|
|
71
|
+
it "returns 200 and not assign current_api_client" do
|
|
72
|
+
get :index
|
|
73
|
+
expect(response.status).to eq 200
|
|
74
|
+
expect(controller.current_api_client).to be nil
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
def form_params(p)
|
|
4
|
+
if Rails::VERSION::MAJOR > 4
|
|
5
|
+
{params: p}
|
|
6
|
+
else
|
|
7
|
+
p
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe Apress::Api::ApiController::Base, type: :controller do
|
|
12
|
+
describe '#prepare_pagination' do
|
|
13
|
+
controller do
|
|
14
|
+
if (Rails::VERSION::MAJOR == 4 && Rails::VERSION::MINOR == 2) || Rails::VERSION::MAJOR > 4
|
|
15
|
+
skip_before_action :authenticate
|
|
16
|
+
else
|
|
17
|
+
skip_before_filter :authenticate
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def index
|
|
21
|
+
prepare_pagination(per_page: {max: 100, default: 40})
|
|
22
|
+
head 204
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'when params present' do
|
|
27
|
+
context 'when params are valid' do
|
|
28
|
+
it 'sets variables' do
|
|
29
|
+
get :index, form_params(page: 2, per_page: 5)
|
|
30
|
+
|
|
31
|
+
expect(assigns(:page)).to eq 2
|
|
32
|
+
expect(assigns(:per_page)).to eq 5
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context 'when params are invalid' do
|
|
37
|
+
it 'returns 400 for negative page' do
|
|
38
|
+
get :index, form_params(page: -1)
|
|
39
|
+
|
|
40
|
+
expect(response.status).to eq 400
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'returns 400 for > max per_page value' do
|
|
44
|
+
get :index, form_params(per_page: 101)
|
|
45
|
+
|
|
46
|
+
expect(response.status).to eq 400
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context 'when no params are set' do
|
|
52
|
+
it 'sets defaults' do
|
|
53
|
+
get :index
|
|
54
|
+
|
|
55
|
+
expect(assigns(:page)).to eq 1
|
|
56
|
+
expect(assigns(:per_page)).to eq 40
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe "#pagination_headers" do
|
|
62
|
+
let(:current_page) { 1 }
|
|
63
|
+
let(:collection) do
|
|
64
|
+
double(
|
|
65
|
+
total_entries: 30,
|
|
66
|
+
total_pages: 3,
|
|
67
|
+
per_page: 10,
|
|
68
|
+
current_page: current_page
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context 'when there are no other values in Link header' do
|
|
73
|
+
controller do
|
|
74
|
+
if (Rails::VERSION::MAJOR == 4 && Rails::VERSION::MINOR == 2) || Rails::VERSION::MAJOR > 4
|
|
75
|
+
skip_before_action :authenticate
|
|
76
|
+
else
|
|
77
|
+
skip_before_filter :authenticate
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def index
|
|
81
|
+
pagination_headers(collection)
|
|
82
|
+
render json: {status: 'ok'}
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
before do
|
|
87
|
+
allow(controller).to receive(:collection).and_return(collection)
|
|
88
|
+
get :index
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'sets correct X-Total-Count header' do
|
|
92
|
+
expect(response.header['X-Total-Count']).to eq '30'
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'sets correct X-Total-Pages header' do
|
|
96
|
+
expect(response.header['X-Total-Pages']).to eq '3'
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it 'sets correct X-Per-Page header' do
|
|
100
|
+
expect(response.header['X-Per-Page']).to eq '10'
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context 'when current page is a first page' do
|
|
104
|
+
it 'sets correct X-Page header' do
|
|
105
|
+
expect(response.header['X-Page']).to eq '1'
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it 'does not add pagination links for first and previous pages to Link header' do
|
|
109
|
+
expect(response.header['Link'].to_s).not_to include('rel="first"', 'rel="prev"')
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it 'adds pagination links for next and last pages to Link header' do
|
|
113
|
+
expect(response.header['Link'].to_s.split(', ')).to include(
|
|
114
|
+
%(<#{request.url}?page=2>; rel="next"),
|
|
115
|
+
%(<#{request.url}?page=3>; rel="last")
|
|
116
|
+
)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
context 'when current page is somewhere in the middle' do
|
|
121
|
+
let(:current_page) { 2 }
|
|
122
|
+
|
|
123
|
+
it 'sets correct X-Page header' do
|
|
124
|
+
expect(response.header['X-Page']).to eq '2'
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it 'adds pagination links for first, previous, next and last pages to Link header' do
|
|
128
|
+
expect(response.header['Link'].to_s.split(', ')).to include(
|
|
129
|
+
%(<#{request.url}?page=1>; rel="first"),
|
|
130
|
+
%(<#{request.url}?page=1>; rel="prev"),
|
|
131
|
+
%(<#{request.url}?page=3>; rel="next"),
|
|
132
|
+
%(<#{request.url}?page=3>; rel="last")
|
|
133
|
+
)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
context 'when current page is a last page' do
|
|
138
|
+
it 'sets correct X-Page header' do
|
|
139
|
+
expect(response.header['X-Page']).to eq '3'
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
let(:current_page) { 3 }
|
|
143
|
+
|
|
144
|
+
it 'does not add pagination links for next and last pages to Link header' do
|
|
145
|
+
expect(response.header['Link'].to_s).not_to include('rel="next"', 'rel="last"')
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it 'adds pagination links for first and previous pages to Link header' do
|
|
149
|
+
expect(response.header['Link'].to_s.split(', ')).to include(
|
|
150
|
+
%(<#{request.url}?page=1>; rel="first"),
|
|
151
|
+
%(<#{request.url}?page=2>; rel="prev")
|
|
152
|
+
)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
context 'when there is only one page' do
|
|
157
|
+
let(:collection) do
|
|
158
|
+
double(
|
|
159
|
+
total_entries: 9,
|
|
160
|
+
total_pages: 1,
|
|
161
|
+
per_page: 10,
|
|
162
|
+
current_page: 1
|
|
163
|
+
)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it 'does not add pagination links to Link header' do
|
|
167
|
+
expect(response.header['Link'].to_s).not_to include('rel="first"', 'rel="prev"', 'rel="last"', 'rel="next"')
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
context 'when Link header already has some values' do
|
|
173
|
+
controller do
|
|
174
|
+
if (Rails::VERSION::MAJOR == 4 && Rails::VERSION::MINOR == 2) || Rails::VERSION::MAJOR > 4
|
|
175
|
+
skip_before_action :authenticate
|
|
176
|
+
else
|
|
177
|
+
skip_before_filter :authenticate
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def index
|
|
181
|
+
headers['Link'] = '<http://test.host/help>; rel="help"'
|
|
182
|
+
|
|
183
|
+
pagination_headers(collection)
|
|
184
|
+
render json: {status: 'ok'}
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
let(:current_page) { 2 }
|
|
189
|
+
|
|
190
|
+
before do
|
|
191
|
+
allow(controller).to receive(:collection).and_return(collection)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it do
|
|
195
|
+
expect { get :index }.to raise_error(Apress::Api::ApiController::Pagination::LinkHeaderAppendNotImplemented)
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|