refinerycms-api 1.0.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.rbenv-gemsets +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +12 -0
- data/Gemfile +57 -0
- data/LICENSE +27 -0
- data/Rakefile +21 -0
- data/app/controllers/refinery/api/base_controller.rb +174 -0
- data/app/controllers/refinery/api/v1/blog/posts_controller.rb +78 -0
- data/app/controllers/refinery/api/v1/images_controller.rb +76 -0
- data/app/controllers/refinery/api/v1/inquiries/inquiries_controller.rb +69 -0
- data/app/controllers/refinery/api/v1/pages_controller.rb +77 -0
- data/app/controllers/refinery/api/v1/resources_controller.rb +66 -0
- data/app/decorators/models/refinery/authentication/devise/user_decorator.rb +5 -0
- data/app/helpers/refinery/api/api_helpers.rb +54 -0
- data/app/models/concerns/refinery/user_api_authentication.rb +19 -0
- data/app/models/refinery/ability.rb +59 -0
- data/app/views/refinery/api/errors/gateway_error.v1.rabl +2 -0
- data/app/views/refinery/api/errors/invalid_api_key.v1.rabl +2 -0
- data/app/views/refinery/api/errors/invalid_resource.v1.rabl +3 -0
- data/app/views/refinery/api/errors/must_specify_api_key.v1.rabl +2 -0
- data/app/views/refinery/api/errors/not_found.v1.rabl +2 -0
- data/app/views/refinery/api/errors/unauthorized.v1.rabl +2 -0
- data/app/views/refinery/api/v1/blog/posts/index.v1.rabl +5 -0
- data/app/views/refinery/api/v1/blog/posts/new.v1.rabl +3 -0
- data/app/views/refinery/api/v1/blog/posts/show.v1.rabl +5 -0
- data/app/views/refinery/api/v1/images/index.v1.rabl +5 -0
- data/app/views/refinery/api/v1/images/new.v1.rabl +3 -0
- data/app/views/refinery/api/v1/images/show.v1.rabl +6 -0
- data/app/views/refinery/api/v1/inquiries/inquiries/index.v1.rabl +5 -0
- data/app/views/refinery/api/v1/inquiries/inquiries/new.v1.rabl +3 -0
- data/app/views/refinery/api/v1/inquiries/inquiries/show.v1.rabl +5 -0
- data/app/views/refinery/api/v1/pages/index.v1.rabl +8 -0
- data/app/views/refinery/api/v1/pages/new.v1.rabl +3 -0
- data/app/views/refinery/api/v1/pages/pages.v1.rabl +5 -0
- data/app/views/refinery/api/v1/pages/show.v1.rabl +9 -0
- data/app/views/refinery/api/v1/resources/index.v1.rabl +5 -0
- data/app/views/refinery/api/v1/resources/new.v1.rabl +3 -0
- data/app/views/refinery/api/v1/resources/show.v1.rabl +6 -0
- data/bin/rails +5 -0
- data/bin/rake +21 -0
- data/bin/rspec +22 -0
- data/bin/spring +18 -0
- data/config/initializers/metal_load_paths.rb +1 -0
- data/config/locales/en.yml +27 -0
- data/config/routes.rb +24 -0
- data/db/migrate/20160501141738_add_api_key_to_refinery_authentication_devise_users.rb +8 -0
- data/lib/generators/refinery/api/api_generator.rb +16 -0
- data/lib/generators/refinery/api/templates/config/initializers/refinery/api.rb.erb +7 -0
- data/lib/refinery/api.rb +29 -0
- data/lib/refinery/api/configuration.rb +32 -0
- data/lib/refinery/api/controller_helpers/auth.rb +76 -0
- data/lib/refinery/api/controller_helpers/strong_parameters.rb +37 -0
- data/lib/refinery/api/controller_setup.rb +20 -0
- data/lib/refinery/api/engine.rb +52 -0
- data/lib/refinery/api/responders.rb +11 -0
- data/lib/refinery/api/responders/rabl_template.rb +30 -0
- data/lib/refinery/api/testing_support/caching.rb +10 -0
- data/lib/refinery/api/testing_support/helpers.rb +44 -0
- data/lib/refinery/api/testing_support/setup.rb +16 -0
- data/lib/refinery/permitted_attributes.rb +40 -0
- data/lib/refinery/responder.rb +45 -0
- data/lib/refinerycms-api.rb +3 -0
- data/readme.md +69 -0
- data/refinerycms_api.gemspec +22 -0
- data/script/rails +9 -0
- data/spec/controllers/refinery/api/base_controller_spec.rb +73 -0
- data/spec/controllers/refinery/api/v1/blog/posts_controller_spec.rb +140 -0
- data/spec/controllers/refinery/api/v1/images_controller_spec.rb +93 -0
- data/spec/controllers/refinery/api/v1/inquiries/inquiries_controller_spec.rb +126 -0
- data/spec/controllers/refinery/api/v1/pages_controller_spec.rb +150 -0
- data/spec/controllers/refinery/api/v1/resources_controller_spec.rb +94 -0
- data/spec/fixtures/refinery_is_awesome.txt +1 -0
- data/spec/fixtures/thinking-cat.jpg +0 -0
- data/spec/models/refinery/user_spec.rb +23 -0
- data/spec/requests/rabl_cache_spec.rb +17 -0
- data/spec/requests/ransackable_attributes_spec.rb +80 -0
- data/spec/requests/version_spec.rb +23 -0
- data/spec/shared_examples/protect_product_actions.rb +17 -0
- data/spec/spec_helper.rb +77 -0
- data/spec/support/controller_hacks.rb +33 -0
- data/spec/support/database_cleaner.rb +14 -0
- data/spec/support/have_attributes_matcher.rb +9 -0
- data/tasks/refinery_api.rake +14 -0
- data/tasks/rspec.rake +4 -0
- metadata +240 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
module Refinery
|
2
|
+
module Api
|
3
|
+
module Responders
|
4
|
+
module RablTemplate
|
5
|
+
def to_format
|
6
|
+
if template
|
7
|
+
render template, :status => options[:status] || 200
|
8
|
+
else
|
9
|
+
super
|
10
|
+
end
|
11
|
+
rescue ActionView::MissingTemplate => e
|
12
|
+
api_behavior
|
13
|
+
end
|
14
|
+
|
15
|
+
def template
|
16
|
+
options[:default_template]
|
17
|
+
end
|
18
|
+
|
19
|
+
def api_behavior
|
20
|
+
if controller.params[:action] == "destroy"
|
21
|
+
# Render a blank template
|
22
|
+
super
|
23
|
+
else
|
24
|
+
# Do nothing and fallback to the default template
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Refinery
|
2
|
+
module Api
|
3
|
+
module TestingSupport
|
4
|
+
module Helpers
|
5
|
+
def json_response
|
6
|
+
case body = JSON.parse(response.body)
|
7
|
+
when Hash
|
8
|
+
body.with_indifferent_access
|
9
|
+
when Array
|
10
|
+
body
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def assert_not_found!
|
15
|
+
expect(json_response).to eq({ "error" => "The resource you were looking for could not be found." })
|
16
|
+
expect(response.status).to eq 404
|
17
|
+
end
|
18
|
+
|
19
|
+
def assert_unauthorized!
|
20
|
+
expect(json_response).to eq({ "error" => "You are not authorized to perform that action." })
|
21
|
+
expect(response.status).to eq 401
|
22
|
+
end
|
23
|
+
|
24
|
+
def stub_authentication!
|
25
|
+
allow(Refinery::Api.user_class).to receive(:find_by).with(hash_including(:refinery_api_key)) { current_api_user }
|
26
|
+
end
|
27
|
+
|
28
|
+
# This method can be overriden (with a let block) inside a context
|
29
|
+
# For instance, if you wanted to have an admin user instead.
|
30
|
+
def current_api_user
|
31
|
+
@current_api_user ||= stub_model(Refinery::Api.user_class, email: "refinery@example.com")
|
32
|
+
end
|
33
|
+
|
34
|
+
def file_path(filename)
|
35
|
+
File.open(Refinery::Api::Engine.root + "spec/fixtures" + filename)
|
36
|
+
end
|
37
|
+
|
38
|
+
def upload_file(filename, mime_type)
|
39
|
+
fixture_file_upload(file_path(filename).path, mime_type)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Refinery
|
2
|
+
module Api
|
3
|
+
module TestingSupport
|
4
|
+
module Setup
|
5
|
+
def sign_in_as_admin!
|
6
|
+
let!(:current_api_user) do
|
7
|
+
user = stub_model(Refinery::Api.user_class)
|
8
|
+
allow(user).to receive_message_chain(:roles, :pluck).and_return(["superuser"])
|
9
|
+
allow(user).to receive(:has_role?).with("superuser").and_return(true)
|
10
|
+
user
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Refinery
|
2
|
+
module PermittedAttributes
|
3
|
+
ATTRIBUTES = [
|
4
|
+
:image_attributes,
|
5
|
+
:page_attributes,
|
6
|
+
:page_part_attributes,
|
7
|
+
:resource_attributes,
|
8
|
+
:blog_post_attributes,
|
9
|
+
:inquiries_inquiry_attributes
|
10
|
+
]
|
11
|
+
|
12
|
+
mattr_reader *ATTRIBUTES
|
13
|
+
|
14
|
+
@@image_attributes = [
|
15
|
+
{ image: [] }, :image_size, :image_title, :image_alt
|
16
|
+
]
|
17
|
+
|
18
|
+
@@page_attributes = [
|
19
|
+
:browser_title, :draft, :link_url, :menu_title, :meta_description,
|
20
|
+
:parent_id, :skip_to_first_child, :show_in_menu, :title, :view_template,
|
21
|
+
:layout_template, :custom_slug, parts_attributes: [:id, :title, :slug, :body, :position]
|
22
|
+
]
|
23
|
+
|
24
|
+
@@page_part_attributes = [
|
25
|
+
:title, :slug, :body, :locale
|
26
|
+
]
|
27
|
+
|
28
|
+
@@resource_attributes = [
|
29
|
+
:resource_title, { file: [] }
|
30
|
+
]
|
31
|
+
|
32
|
+
@@blog_post_attributes = [
|
33
|
+
:title, :body, :custom_teaser, :tag_list,
|
34
|
+
:draft, :published_at, :custom_url, :user_id, :username, :browser_title,
|
35
|
+
:meta_description, :source_url, :source_url_title, category_ids: []
|
36
|
+
]
|
37
|
+
|
38
|
+
@@inquiries_inquiry_attributes = [:name, :phone, :message, :email]
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Refinery
|
2
|
+
class Responder < ::ActionController::Responder #:nodoc:
|
3
|
+
|
4
|
+
attr_accessor :on_success, :on_failure
|
5
|
+
|
6
|
+
def initialize(controller, resources, options={})
|
7
|
+
super
|
8
|
+
|
9
|
+
class_name = controller.class.name.to_sym
|
10
|
+
action_name = options.delete(:action_name)
|
11
|
+
|
12
|
+
if result = Refinery::BaseController.refinery_responders[class_name].try(:[], action_name).try(:[], self.format.to_sym)
|
13
|
+
self.on_success = handler(controller, result, :success)
|
14
|
+
self.on_failure = handler(controller, result, :failure)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_html
|
19
|
+
super and return if !(on_success || on_failure)
|
20
|
+
has_errors? ? controller.instance_exec(&on_failure) : controller.instance_exec(&on_success)
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_format
|
24
|
+
super and return if !(on_success || on_failure)
|
25
|
+
has_errors? ? controller.instance_exec(&on_failure) : controller.instance_exec(&on_success)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def handler(controller, result, status)
|
31
|
+
return result if result.respond_to? :call
|
32
|
+
|
33
|
+
case result
|
34
|
+
when Hash
|
35
|
+
if result[status].is_a? Symbol
|
36
|
+
controller.method(result[status])
|
37
|
+
else
|
38
|
+
result[status]
|
39
|
+
end
|
40
|
+
when Symbol
|
41
|
+
controller.method(result)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/readme.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# Refinery CMS Api
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/refinerycms-contrib/refinerycms-api.svg?branch=master)](https://travis-ci.org/refinerycms-contrib/refinerycms-api)
|
4
|
+
|
5
|
+
This extension allows you to use a Rest API with Refinery CMS 3.0 and later.
|
6
|
+
|
7
|
+
## TODO
|
8
|
+
* [ ] Check Abilities
|
9
|
+
* [ ] Fix specs
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Simply put this in the Gemfile of your Refinery application:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'refinerycms-api', github: 'refinerycms-contrib/refinerycms-api', master: 'branch'
|
17
|
+
```
|
18
|
+
|
19
|
+
Then run `bundle install` to install it.
|
20
|
+
|
21
|
+
|
22
|
+
### Generate and run migrations
|
23
|
+
|
24
|
+
```sh
|
25
|
+
$ rails g refinery:api # Generate initializer
|
26
|
+
$ rake db:migrate
|
27
|
+
```
|
28
|
+
|
29
|
+
Then restart your server.
|
30
|
+
|
31
|
+
## Usage
|
32
|
+
|
33
|
+
### Create an API Token for your user
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
$ rake refinery_api:user:api_token:generate EMAIL=refinery@example.org
|
37
|
+
```
|
38
|
+
|
39
|
+
### Pages
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
$ curl --header "X-Refinery-Token: YOUR_API_TOKEN" http://localhost:3000/api/v1/pages
|
43
|
+
$ curl --header "X-Refinery-Token: YOUR_API_TOKEN" http://localhost:3000/api/v1/pages/1
|
44
|
+
$ curl --header "X-Refinery-Token: YOUR_API_TOKEN" http://localhost:3000/api/v1/pages/new
|
45
|
+
|
46
|
+
$ curl -X POST --header "X-Refinery-Token: YOUR_API_TOKEN" "http://localhost:3000/api/v1/pages" -d 'page[title]=test'
|
47
|
+
$ curl -X PUT --header "X-Refinery-Token: YOUR_API_TOKEN" "http://localhost:3000/api/v1/pages/1" -d 'page[title]=test2'
|
48
|
+
$ curl -X DELETE -H "X-Refinery-Token: YOUR_API_TOKEN" http://localhost:3000/api/v1/pages/1
|
49
|
+
```
|
50
|
+
|
51
|
+
### Images
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
$ curl --header "X-Refinery-Token: YOUR_API_TOKEN" http://localhost:3000/api/v1/images
|
55
|
+
$ curl --header "X-Refinery-Token: YOUR_API_TOKEN" http://localhost:3000/api/v1/images/1
|
56
|
+
$ curl --header "X-Refinery-Token: YOUR_API_TOKEN" http://localhost:3000/api/v1/images/new
|
57
|
+
```
|
58
|
+
|
59
|
+
### Resources
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
$ curl --header "X-Refinery-Token: YOUR_API_TOKEN" http://localhost:3000/api/v1/resources
|
63
|
+
$ curl --header "X-Refinery-Token: YOUR_API_TOKEN" http://localhost:3000/api/v1/resources/1
|
64
|
+
$ curl --header "X-Refinery-Token: YOUR_API_TOKEN" http://localhost:3000/api/v1/resources/new
|
65
|
+
```
|
66
|
+
|
67
|
+
## Contributing
|
68
|
+
|
69
|
+
Please see the [contributing.md](contributing.md) file for instructions.
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Encoding: UTF-8
|
2
|
+
Gem::Specification.new do |s|
|
3
|
+
s.authors = ["Brice Sanchez", "Ryan Bigg"]
|
4
|
+
s.description = %q{Refinery CMS's API}
|
5
|
+
s.summary = %q{Refinery CMS's API}
|
6
|
+
s.homepage = 'http://www.refinerycms.com'
|
7
|
+
s.license = 'BSD-3'
|
8
|
+
|
9
|
+
s.files = `git ls-files`.split($\)
|
10
|
+
s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
11
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
12
|
+
s.name = %q{refinerycms-api}
|
13
|
+
s.require_paths = ["lib"]
|
14
|
+
s.version = %q{1.0.0.beta}
|
15
|
+
|
16
|
+
s.add_dependency 'refinerycms-core', ['~> 3.0', '>= 3.0.0']
|
17
|
+
s.add_dependency 'cancancan', '~> 1.10.1'
|
18
|
+
s.add_dependency 'decorators', '~> 2.0'
|
19
|
+
s.add_dependency 'rabl', '~> 0.12.0'
|
20
|
+
s.add_dependency 'versioncake', '~> 2.3.1'
|
21
|
+
s.add_dependency 'responders'
|
22
|
+
end
|
data/script/rails
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
|
3
|
+
|
4
|
+
ENGINE_ROOT = File.expand_path('../..', __FILE__)
|
5
|
+
ENGINE_PATH = File.expand_path('../../lib/refinery/api/engine', __FILE__)
|
6
|
+
|
7
|
+
require 'rails/all'
|
8
|
+
require 'rails/engine/commands'
|
9
|
+
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class FakesController < Refinery::Api::BaseController
|
4
|
+
end
|
5
|
+
|
6
|
+
describe Refinery::Api::BaseController, type: :controller do
|
7
|
+
render_views
|
8
|
+
controller(Refinery::Api::BaseController) do
|
9
|
+
def index
|
10
|
+
render text: { "pages": [] }.to_json
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
@routes = ActionDispatch::Routing::RouteSet.new.tap do |r|
|
16
|
+
r.draw { get 'index', to: 'refinery/api/base#index' }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "cannot make a request to the API" do
|
21
|
+
it "without an API key" do
|
22
|
+
api_get :index
|
23
|
+
expect(json_response).to eq({ "error" => "You must specify an API key." })
|
24
|
+
expect(response.status).to eq(401)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "with an invalid API key" do
|
28
|
+
request.headers["X-Refinery-Token"] = "fake_key"
|
29
|
+
get :index, {}
|
30
|
+
expect(json_response).to eq({ "error" => "Invalid API key (fake_key) specified." })
|
31
|
+
expect(response.status).to eq(401)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "using an invalid token param" do
|
35
|
+
get :index, token: "fake_key"
|
36
|
+
expect(json_response).to eq({ "error" => "Invalid API key (fake_key) specified." })
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'handles parameter missing exceptions' do
|
41
|
+
expect(subject).to receive(:authenticate_user).and_return(true)
|
42
|
+
expect(subject).to receive(:load_user_roles).and_return(true)
|
43
|
+
expect(subject).to receive(:index).and_raise(ActionController::ParameterMissing.new('foo'))
|
44
|
+
get :index, token: 'exception-message'
|
45
|
+
expect(json_response).to eql('exception' => 'param is missing or the value is empty: foo')
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'handles record invalid exceptions' do
|
49
|
+
expect(subject).to receive(:authenticate_user).and_return(true)
|
50
|
+
expect(subject).to receive(:load_user_roles).and_return(true)
|
51
|
+
resource = Refinery::Page.new
|
52
|
+
resource.valid? # get some errors
|
53
|
+
expect(subject).to receive(:index).and_raise(ActiveRecord::RecordInvalid.new(resource))
|
54
|
+
get :index, token: 'exception-message'
|
55
|
+
expect(json_response).to eql('exception' => "Validation failed: Title can't be blank")
|
56
|
+
end
|
57
|
+
|
58
|
+
it "maps semantic keys to nested_attributes keys" do
|
59
|
+
klass = double(nested_attributes_options: { line_items: {},
|
60
|
+
bill_address: {} })
|
61
|
+
attributes = { 'line_items': { id: 1 },
|
62
|
+
'bill_address': { id: 2 },
|
63
|
+
'name': 'test order' }
|
64
|
+
|
65
|
+
mapped = subject.map_nested_attributes_keys(klass, attributes)
|
66
|
+
expect(mapped.has_key?('line_items_attributes')).to be true
|
67
|
+
expect(mapped.has_key?('name')).to be true
|
68
|
+
end
|
69
|
+
|
70
|
+
it "lets a subclass override the product associations that are eager-loaded" do
|
71
|
+
expect(controller.respond_to?(:product_includes, true)).to be
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Refinery
|
4
|
+
describe Api::V1::Blog::PostsController, type: :controller do
|
5
|
+
render_views
|
6
|
+
|
7
|
+
let!(:post) { FactoryGirl.create(:blog_post, :title => "Ruby") }
|
8
|
+
|
9
|
+
let!(:attributes_new) { [ "title", "body", "custom_teaser", "tag_list", "draft", "published_at", "custom_url", "user_id", "username", "browser_title", "meta_description", "source_url", "source_url_title", {"category_ids"=>[]} ] }
|
10
|
+
let!(:attributes) { [ "title", "body", "custom_teaser", "tag_list", "draft", "published_at", "custom_url", "user_id", "username", "browser_title", "meta_description", "source_url", "source_url_title", "category_ids" ] }
|
11
|
+
|
12
|
+
before do
|
13
|
+
stub_authentication!
|
14
|
+
end
|
15
|
+
|
16
|
+
context "as a normal user" do
|
17
|
+
it "can get a list of blog posts" do
|
18
|
+
api_get :index
|
19
|
+
|
20
|
+
expect(response.status).to eq(200)
|
21
|
+
expect(json_response).to have_key("posts")
|
22
|
+
attributes.delete("category_ids")
|
23
|
+
expect(json_response["posts"].first.keys).to eq(attributes)
|
24
|
+
end
|
25
|
+
|
26
|
+
# it "paginates through taxons" do
|
27
|
+
# new_taxon = create(:taxon, :name => "Go", :taxonomy => taxonomy)
|
28
|
+
# taxonomy.root.children << new_taxon
|
29
|
+
# expect(taxonomy.root.children.count).to eql(2)
|
30
|
+
# api_get :index, :taxonomy_id => taxonomy.id, :page => 1, :per_page => 1
|
31
|
+
# expect(json_response["count"]).to eql(1)
|
32
|
+
# expect(json_response["total_count"]).to eql(2)
|
33
|
+
# expect(json_response["current_page"]).to eql(1)
|
34
|
+
# expect(json_response["per_page"]).to eql(1)
|
35
|
+
# expect(json_response["pages"]).to eql(2)
|
36
|
+
# end
|
37
|
+
|
38
|
+
# describe 'searching' do
|
39
|
+
# context 'with a name' do
|
40
|
+
# before do
|
41
|
+
# api_get :index, :q => { :name_cont => name }
|
42
|
+
# end
|
43
|
+
|
44
|
+
# context 'with one result' do
|
45
|
+
# let(:name) { "Ruby" }
|
46
|
+
|
47
|
+
# it "returns an array including the matching taxon" do
|
48
|
+
# expect(json_response['taxons'].count).to eq(1)
|
49
|
+
# expect(json_response['taxons'].first['name']).to eq "Ruby"
|
50
|
+
# end
|
51
|
+
# end
|
52
|
+
|
53
|
+
# context 'with no results' do
|
54
|
+
# let(:name) { "Imaginary" }
|
55
|
+
|
56
|
+
# it 'returns an empty array of taxons' do
|
57
|
+
# expect(json_response.keys).to include('taxons')
|
58
|
+
# expect(json_response['taxons'].count).to eq(0)
|
59
|
+
# end
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
|
63
|
+
# context 'with no filters' do
|
64
|
+
# it "gets all taxons" do
|
65
|
+
# api_get :index
|
66
|
+
|
67
|
+
# expect(json_response['taxons'].first['name']).to eq taxonomy.root.name
|
68
|
+
# children = json_response['taxons'].first['taxons']
|
69
|
+
# expect(children.count).to eq 1
|
70
|
+
# expect(children.first['name']).to eq taxon.name
|
71
|
+
# expect(children.first['taxons'].count).to eq 1
|
72
|
+
# end
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
|
76
|
+
it "gets a single blog post" do
|
77
|
+
api_get :show, id: post.id
|
78
|
+
|
79
|
+
expect(json_response['title']).to eq post.title
|
80
|
+
expect(json_response['posts']).to be_nil
|
81
|
+
end
|
82
|
+
|
83
|
+
it "can learn how to create a new blog post" do
|
84
|
+
api_get :new
|
85
|
+
expect(json_response["attributes"]).to eq(attributes_new)
|
86
|
+
required_attributes = json_response["required_attributes"]
|
87
|
+
expect(required_attributes).to include("title")
|
88
|
+
end
|
89
|
+
|
90
|
+
it "cannot create a new blog post if not an admin" do
|
91
|
+
api_post :create, blog_post: { title: "Location" }
|
92
|
+
assert_unauthorized!
|
93
|
+
end
|
94
|
+
|
95
|
+
it "cannot update a blog post" do
|
96
|
+
api_put :update, id: post.id, post: { title: "I hacked your website!" }
|
97
|
+
assert_unauthorized!
|
98
|
+
end
|
99
|
+
|
100
|
+
it "cannot delete a blog post" do
|
101
|
+
api_delete :destroy, id: post.id
|
102
|
+
assert_unauthorized!
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "as an admin" do
|
107
|
+
sign_in_as_admin!
|
108
|
+
|
109
|
+
it "can create" do
|
110
|
+
expect do
|
111
|
+
api_post :create, post: { title: "Colors", body: "Colors of life", published_at: Time.now, username: "John Doe" }
|
112
|
+
attributes.delete("category_ids")
|
113
|
+
expect(json_response.keys).to eq(attributes)
|
114
|
+
expect(response.status).to eq(201)
|
115
|
+
end.to change(Blog::Post, :count).by(1)
|
116
|
+
end
|
117
|
+
|
118
|
+
it "can update the title" do
|
119
|
+
api_put :update, id: post.id, post: { title: "I update your website!" }
|
120
|
+
expect(response.status).to eq(200)
|
121
|
+
expect(Blog::Post.last.title).to eql "I update your website!"
|
122
|
+
end
|
123
|
+
|
124
|
+
it "cannot create a new blog post with invalid attributes" do
|
125
|
+
api_post :create, post: {}
|
126
|
+
expect(response.status).to eq(422)
|
127
|
+
expect(json_response["error"]).to eq("Invalid resource. Please fix errors and try again.")
|
128
|
+
errors = json_response["errors"]
|
129
|
+
|
130
|
+
expect(Blog::Post.count).to eq 1
|
131
|
+
end
|
132
|
+
|
133
|
+
it "can destroy" do
|
134
|
+
api_delete :destroy, :id => post.id
|
135
|
+
expect(response.status).to eq(204)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|