Use Rack::Test in all request specs

pull/5908/head
Oliver Günther 7 years ago
parent 4b83ac920a
commit cbb0d90fde
No known key found for this signature in database
GPG Key ID: 88872239EB414F99
  1. 3
      spec/rails_helper.rb
  2. 12
      spec/requests/api/v3/activities_by_work_package_resource_spec.rb
  3. 65
      spec/requests/api/v3/authentication_spec.rb
  4. 8
      spec/requests/api/v3/queries/create_form_api_spec.rb
  5. 22
      spec/requests/api/v3/queries/create_query_spec.rb
  6. 9
      spec/requests/api/v3/queries/update_form_api_spec.rb
  7. 24
      spec/requests/api/v3/queries/update_query_spec.rb
  8. 17
      spec/requests/api/v3/rack_deflater_spec.rb
  9. 53
      spec/requests/api/v3/relations/relations_api_spec.rb
  10. 5
      spec/requests/api/v3/relations/relations_index_spec.rb
  11. 8
      spec/requests/api/v3/support/api_helper.rb
  12. 4
      spec/requests/api/v3/support/api_v3_collection_response.rb
  13. 35
      spec/requests/api/v3/user/create_user_resource_spec.rb
  14. 4
      spec/requests/api/v3/user/filters_spec.rb
  15. 21
      spec/requests/api/v3/user/update_user_resource_spec.rb
  16. 4
      spec/requests/api/v3/work_packages/available_projects_on_create_api_spec.rb
  17. 6
      spec/requests/api/v3/work_packages/available_projects_on_edit_api_spec.rb
  18. 2
      spec/requests/api/v3/work_packages/available_relation_candidates_spec.rb
  19. 6
      spec/requests/api/v3/work_packages/form/work_package_form_resource_spec.rb
  20. 6
      spec/requests/attachments_routes_spec.rb
  21. 13
      spec/requests/auth/api_v2_spec.rb
  22. 2
      spec/requests/current_user_spec.rb
  23. 10
      spec/requests/old_issue_2_wp_spec.rb
  24. 10
      spec/requests/short_uri_wp_spec.rb
  25. 59
      spec/support/request_with_header.rb
  26. 18
      spec/support/request_with_session_header.rb
  27. 16
      spec/support/rspec_request_specs.rb

@ -74,9 +74,6 @@ RSpec.configure do |config|
# Filter lines from Rails gems in backtraces. # Filter lines from Rails gems in backtraces.
config.filter_rails_from_backtrace! config.filter_rails_from_backtrace!
# include spec/api for API request specs
config.include RSpec::Rails::RequestExampleGroup, type: :request
# Add helpers to parse json-responses # Add helpers to parse json-responses
config.include JsonSpec::Helpers config.include JsonSpec::Helpers

@ -52,14 +52,14 @@ describe API::V3::Activities::ActivitiesByWorkPackageAPI, type: :request do
end end
it 'succeeds' do it 'succeeds' do
expect(response.status).to eql 200 expect(last_response.status).to eql 200
end end
context 'not allowed to see work package' do context 'not allowed to see work package' do
let(:current_user) { FactoryGirl.create(:user) } let(:current_user) { FactoryGirl.create(:user) }
it 'fails with HTTP Not Found' do it 'fails with HTTP Not Found' do
expect(response.status).to eql 404 expect(last_response.status).to eql 404
end end
end end
end end
@ -69,9 +69,9 @@ describe API::V3::Activities::ActivitiesByWorkPackageAPI, type: :request do
shared_context 'create activity' do shared_context 'create activity' do
before do before do
header "Content-Type", "application/json"
post api_v3_paths.work_package_activities(work_package.id), post api_v3_paths.work_package_activities(work_package.id),
params: { comment: { raw: comment } }.to_json, { comment: { raw: comment } }.to_json
headers: { 'CONTENT_TYPE' => 'application/json' }
end end
end end
@ -96,11 +96,11 @@ describe API::V3::Activities::ActivitiesByWorkPackageAPI, type: :request do
include_context 'create activity' include_context 'create activity'
it 'responds with error' do it 'responds with error' do
expect(response.status).to eql 422 expect(last_response.status).to eql 422
end end
it 'notes the error' do it 'notes the error' do
expect(response.body) expect(last_response.body)
.to be_json_eql("Subject can't be blank.".to_json) .to be_json_eql("Subject can't be blank.".to_json)
.at_path('message') .at_path('message')
end end

@ -45,20 +45,21 @@ describe API::V3, type: :request do
strategies = OpenProject::Authentication::Strategies::Warden strategies = OpenProject::Authentication::Strategies::Warden
def basic_auth(user, password) def set_basic_auth_header(user, password)
credentials = ActionController::HttpAuthentication::Basic.encode_credentials user, password credentials = ActionController::HttpAuthentication::Basic.encode_credentials user, password
{ 'Authorization' => credentials } header 'Authorization', credentials
end end
shared_examples 'it is basic auth protected' do shared_examples 'it is basic auth protected' do
context 'when not allowed', with_config: { apiv3_enable_basic_auth: false } do context 'when not allowed', with_config: { apiv3_enable_basic_auth: false } do
context 'with valid credentials' do context 'with valid credentials' do
before do before do
get resource, params: {}, headers: basic_auth(username, password) set_basic_auth_header(username, password)
get resource
end end
it 'should return 401 unauthorized' do it 'should return 401 unauthorized' do
expect(response.status).to eq 401 expect(last_response.status).to eq 401
end end
end end
end end
@ -69,15 +70,15 @@ describe API::V3, type: :request do
end end
it 'should return 401 unauthorized' do it 'should return 401 unauthorized' do
expect(response.status).to eq 401 expect(last_response.status).to eq 401
end end
it 'should return the correct JSON response' do it 'should return the correct JSON response' do
expect(JSON.parse(response.body)).to eq response_401 expect(JSON.parse(last_response.body)).to eq response_401
end end
it 'should return the WWW-Authenticate header' do it 'should return the WWW-Authenticate header' do
expect(response.header['WWW-Authenticate']) expect(last_response.header['WWW-Authenticate'])
.to include 'Basic realm="OpenProject API"' .to include 'Basic realm="OpenProject API"'
end end
end end
@ -86,64 +87,63 @@ describe API::V3, type: :request do
let(:expected_message) { 'You did not provide the correct credentials.' } let(:expected_message) { 'You did not provide the correct credentials.' }
before do before do
get resource, params: {}, headers: basic_auth(username, password.reverse) set_basic_auth_header(username, password.reverse)
get resource
end end
it 'should return 401 unauthorized' do it 'should return 401 unauthorized' do
expect(response.status).to eq 401 expect(last_response.status).to eq 401
end end
it 'should return the correct JSON response' do it 'should return the correct JSON response' do
expect(JSON.parse(response.body)).to eq response_401 expect(JSON.parse(last_response.body)).to eq response_401
end end
it 'should return the correct content type header' do it 'should return the correct content type header' do
expect(response.headers['Content-Type']).to eq 'application/hal+json; charset=utf-8' expect(last_response.headers['Content-Type']).to eq 'application/hal+json; charset=utf-8'
end end
it 'should return the WWW-Authenticate header' do it 'should return the WWW-Authenticate header' do
expect(response.header['WWW-Authenticate']) expect(last_response.header['WWW-Authenticate'])
.to include 'Basic realm="OpenProject API"' .to include 'Basic realm="OpenProject API"'
end end
end end
context 'with invalid credentials an X-Authentication-Scheme "Session"' do context 'with invalid credentials an X-Authentication-Scheme "Session"' do
let(:expected_message) { 'You did not provide the correct credentials.' } let(:expected_message) { 'You did not provide the correct credentials.' }
let(:headers) do
auth = basic_auth(username, password.reverse)
auth.merge('X-Authentication-Scheme' => 'Session')
end
before do before do
get resource, params: {}, headers: headers set_basic_auth_header(username, password.reverse)
header 'X-Authentication-Scheme', 'Session'
get resource
end end
it 'should return 401 unauthorized' do it 'should return 401 unauthorized' do
expect(response.status).to eq 401 expect(last_response.status).to eq 401
end end
it 'should return the correct JSON response' do it 'should return the correct JSON response' do
expect(JSON.parse(response.body)).to eq response_401 expect(JSON.parse(last_response.body)).to eq response_401
end end
it 'should return the correct content type header' do it 'should return the correct content type header' do
expect(response.headers['Content-Type']).to eq 'application/hal+json; charset=utf-8' expect(last_response.headers['Content-Type']).to eq 'application/hal+json; charset=utf-8'
end end
it 'should return the WWW-Authenticate header' do it 'should return the WWW-Authenticate header' do
expect(response.header['WWW-Authenticate']) expect(last_response.header['WWW-Authenticate'])
.to include 'Session realm="OpenProject API"' .to include 'Session realm="OpenProject API"'
end end
end end
context 'with valid credentials' do context 'with valid credentials' do
before do before do
get resource, params: {}, headers: basic_auth(username, password) set_basic_auth_header(username, password)
get resource
end end
it 'should return 200 OK' do it 'should return 200 OK' do
expect(response.status).to eq 200 expect(last_response.status).to eq 200
end end
end end
end end
@ -212,7 +212,7 @@ describe API::V3, type: :request do
end end
it 'should return 200 OK' do it 'should return 200 OK' do
expect(response.status).to eq 200 expect(last_response.status).to eq 200
end end
it 'should "login" the anonymous user' do it 'should "login" the anonymous user' do
@ -222,21 +222,23 @@ describe API::V3, type: :request do
context 'with invalid credentials' do context 'with invalid credentials' do
before do before do
get resource, params: {}, headers: basic_auth(username, password) set_basic_auth_header(username, password)
get resource
end end
it 'should return 401 unauthorized' do it 'should return 401 unauthorized' do
expect(response.status).to eq 401 expect(last_response.status).to eq 401
end end
end end
context 'with valid global credentials' do context 'with valid global credentials' do
before do before do
get resource, params: {}, headers: basic_auth('global_account', 'global_password') set_basic_auth_header('global_account', 'global_password')
get resource
end end
it 'should return 200 OK' do it 'should return 200 OK' do
expect(response.status).to eq 200 expect(last_response.status).to eq 200
end end
it 'should login an admin system user' do it 'should login an admin system user' do
@ -247,11 +249,12 @@ describe API::V3, type: :request do
context 'with valid user credentials' do context 'with valid user credentials' do
before do before do
get resource, params: {}, headers: basic_auth('apikey', api_key.value) set_basic_auth_header('apikey', api_key.value)
get resource
end end
it 'should return 200 OK' do it 'should return 200 OK' do
expect(response.status).to eq 200 expect(last_response.status).to eq 200
end end
it 'should login user' do it 'should login user' do

@ -39,7 +39,7 @@ describe "POST /api/v3/queries/form", type: :request do
let(:parameters) { {} } let(:parameters) { {} }
let(:override_params) { {} } let(:override_params) { {} }
let(:form) { JSON.parse response.body } let(:form) { JSON.parse last_response.body }
let(:static_columns_json) do let(:static_columns_json) do
%w(id project assignee author %w(id project assignee author
@ -97,13 +97,13 @@ describe "POST /api/v3/queries/form", type: :request do
additional_setup additional_setup
header "Content-Type", "application/json"
post path, post path,
params: parameters.merge(override_params).to_json, parameters.merge(override_params).to_json
headers: { 'CONTENT_TYPE' => 'application/json' }
end end
it 'should return 200(OK)' do it 'should return 200(OK)' do
expect(response.status).to eq(200) expect(last_response.status).to eq(200)
end end
it 'should be of type form' do it 'should be of type form' do

@ -97,17 +97,16 @@ describe "POST /api/v3/queries", type: :request do
describe "creating a query" do describe "creating a query" do
before do before do
post "/api/v3/queries", header "Content-Type", "application/json"
params: params.to_json, post "/api/v3/queries", params.to_json
headers: { "Content-Type": "application/json" }
end end
it 'should return 201 (created)' do it 'should return 201 (created)' do
expect(response.status).to eq(201) expect(last_response.status).to eq(201)
end end
it 'should render the created query' do it 'should render the created query' do
json = JSON.parse(response.body) json = JSON.parse(last_response.body)
expect(json["_type"]).to eq "Query" expect(json["_type"]).to eq "Query"
expect(json["name"]).to eq "Dummy Query" expect(json["name"]).to eq "Dummy Query"
@ -133,13 +132,12 @@ describe "POST /api/v3/queries", type: :request do
context "with invalid parameters" do context "with invalid parameters" do
def post! def post!
post "/api/v3/queries", header "Content-Type", "application/json"
params: params.to_json, post "/api/v3/queries", params.to_json
headers: { "Content-Type": "application/json" }
end end
def json def json
JSON.parse response.body JSON.parse last_response.body
end end
it "yields a 422 error given an unknown project" do it "yields a 422 error given an unknown project" do
@ -147,7 +145,7 @@ describe "POST /api/v3/queries", type: :request do
post! post!
expect(response.status).to eq 422 expect(last_response.status).to eq 422
expect(json["message"]).to eq "Project not found" expect(json["message"]).to eq "Project not found"
end end
@ -156,7 +154,7 @@ describe "POST /api/v3/queries", type: :request do
post! post!
expect(response.status).to eq 422 expect(last_response.status).to eq 422
expect(json["message"]).to eq "Status Operator is not included in the list" expect(json["message"]).to eq "Status Operator is not included in the list"
end end
@ -165,7 +163,7 @@ describe "POST /api/v3/queries", type: :request do
post! post!
expect(response.status).to eq 422 expect(last_response.status).to eq 422
expect(json["message"]).to eq "Statuz does not exist." expect(json["message"]).to eq "Statuz does not exist."
end end
end end

@ -53,7 +53,7 @@ describe "POST /api/v3/queries/form", type: :request do
let(:parameters) { {} } let(:parameters) { {} }
let(:override_params) { {} } let(:override_params) { {} }
let(:form) { JSON.parse response.body } let(:form) { JSON.parse last_response.body }
before do before do
project.add_member! user, role project.add_member! user, role
@ -62,13 +62,12 @@ describe "POST /api/v3/queries/form", type: :request do
additional_setup additional_setup
post path, header 'CONTENT_TYPE', 'application/json'
params: parameters.merge(override_params).to_json, post path, parameters.merge(override_params).to_json
headers: { 'CONTENT_TYPE' => 'application/json' }
end end
it 'should return 200(OK)' do it 'should return 200(OK)' do
expect(response.status).to eq(200) expect(last_response.status).to eq(200)
end end
it 'should be of type form' do it 'should be of type form' do

@ -34,7 +34,7 @@ describe "PATCH /api/v3/queries/:id", type: :request do
let(:project) { FactoryGirl.create :project } let(:project) { FactoryGirl.create :project }
def json def json
JSON.parse response.body JSON.parse last_response.body
end end
let!(:query) do let!(:query) do
@ -113,17 +113,16 @@ describe "PATCH /api/v3/queries/:id", type: :request do
describe "updating a query" do describe "updating a query" do
before do before do
patch "/api/v3/queries/#{query.id}", header "Content-Type", "application/json"
params: params.to_json, patch "/api/v3/queries/#{query.id}", params.to_json
headers: { "Content-Type": "application/json" }
end end
it 'should return 200 (ok)' do it 'should return 200 (ok)' do
expect(response.status).to eq(200) expect(last_response.status).to eq(200)
end end
it 'should render the updated query' do it 'should render the updated query' do
json = JSON.parse(response.body) json = JSON.parse(last_response.body)
expect(json["_type"]).to eq "Query" expect(json["_type"]).to eq "Query"
expect(json["name"]).to eq "Dummy Query" expect(json["name"]).to eq "Dummy Query"
@ -151,7 +150,7 @@ describe "PATCH /api/v3/queries/:id", type: :request do
let(:params) { {} } let(:params) { {} }
it "should not change anything" do it "should not change anything" do
json = JSON.parse(response.body) json = JSON.parse(last_response.body)
expect(json["_type"]).to eq "Query" expect(json["_type"]).to eq "Query"
expect(json["name"]).to eq "A Query" expect(json["name"]).to eq "A Query"
@ -161,9 +160,8 @@ describe "PATCH /api/v3/queries/:id", type: :request do
context "with invalid parameters" do context "with invalid parameters" do
def post! def post!
patch "/api/v3/queries/#{query.id}", header "Content-Type", "application/json"
params: params.to_json, patch "/api/v3/queries/#{query.id}", params.to_json
headers: { "Content-Type": "application/json" }
end end
it "yields a 422 error given an unknown project" do it "yields a 422 error given an unknown project" do
@ -171,7 +169,7 @@ describe "PATCH /api/v3/queries/:id", type: :request do
post! post!
expect(response.status).to eq 422 expect(last_response.status).to eq 422
expect(json["message"]).to eq "Project not found" expect(json["message"]).to eq "Project not found"
end end
@ -180,7 +178,7 @@ describe "PATCH /api/v3/queries/:id", type: :request do
post! post!
expect(response.status).to eq 422 expect(last_response.status).to eq 422
expect(json["message"]).to eq "Status Operator is not included in the list" expect(json["message"]).to eq "Status Operator is not included in the list"
end end
@ -189,7 +187,7 @@ describe "PATCH /api/v3/queries/:id", type: :request do
post! post!
expect(response.status).to eq 422 expect(last_response.status).to eq 422
expect(json["message"]).to eq "Statuz does not exist." expect(json["message"]).to eq "Statuz does not exist."
end end
end end

@ -38,17 +38,16 @@ describe Rack::Deflater, type: :request do
# It could be any endpoint really. # It could be any endpoint really.
get api_v3_paths.configuration get api_v3_paths.configuration
expect(response.headers['Content-Encoding']).to be_nil expect(last_response.headers['Content-Encoding']).to be_nil
etag = response.headers['Etag'] etag = last_response.headers['Etag']
content_length = response.headers['Content-Length'].to_i content_length = last_response.headers['Content-Length'].to_i
get api_v3_paths.configuration, header "Accept-Encoding", "gzip"
params: {}, get api_v3_paths.configuration
headers: { 'Accept-Encoding' => 'gzip' }
expect(response.headers['Etag']).to eql etag expect(last_response.headers['Etag']).to eql etag
expect(response.headers['Content-Length'].to_i).to_not eql content_length expect(last_response.headers['Content-Length'].to_i).to_not eql content_length
expect(response.headers['Content-Encoding']).to eql 'gzip' expect(last_response.headers['Content-Encoding']).to eql 'gzip'
end end
end end

@ -72,13 +72,12 @@ describe ::API::V3::Relations::RelationRepresenter, type: :request do
before do before do
expect(Relation.count).to eq 0 expect(Relation.count).to eq 0
post "/api/v3/work_packages/#{from.id}/relations", header "Content-Type", "application/json"
params: params.to_json, post "/api/v3/work_packages/#{from.id}/relations", params.to_json
headers: { "Content-Type": "application/json" }
end end
it 'should return 201 (created)' do it 'should return 201 (created)' do
expect(response.status).to eq(201) expect(last_response.status).to eq(201)
end end
it 'should have created a new relation' do it 'should have created a new relation' do
@ -86,7 +85,7 @@ describe ::API::V3::Relations::RelationRepresenter, type: :request do
end end
it 'should have created the relation correctly' do it 'should have created the relation correctly' do
rel = described_class.new(Relation.new, current_user: user).from_json response.body rel = described_class.new(Relation.new, current_user: user).from_json last_response.body
expect(rel.from).to eq from expect(rel.from).to eq from
expect(rel.to).to eq to expect(rel.to).to eq to
@ -110,13 +109,12 @@ describe ::API::V3::Relations::RelationRepresenter, type: :request do
before do before do
relation relation
patch "/api/v3/relations/#{relation.id}", header "Content-Type", "application/json"
params: update.to_json, patch "/api/v3/relations/#{relation.id}", update.to_json
headers: { "Content-Type": "application/json" }
end end
it "should return 200 (ok)" do it "should return 200 (ok)" do
expect(response.status).to eq 200 expect(last_response.status).to eq 200
end end
it "updates the relation's description" do it "updates the relation's description" do
@ -128,7 +126,7 @@ describe ::API::V3::Relations::RelationRepresenter, type: :request do
end end
it "should return the updated relation" do it "should return the updated relation" do
rel = described_class.new(Relation.new, current_user: user).from_json response.body rel = described_class.new(Relation.new, current_user: user).from_json last_response.body
expect(rel).to eq relation.reload expect(rel).to eq relation.reload
end end
@ -141,11 +139,11 @@ describe ::API::V3::Relations::RelationRepresenter, type: :request do
end end
it "should return 422" do it "should return 422" do
expect(response.status).to eq 422 expect(last_response.status).to eq 422
end end
it "should indicate an error with the type attribute" do it "should indicate an error with the type attribute" do
attr = JSON.parse(response.body).dig "_embedded", "details", "attribute" attr = JSON.parse(last_response.body).dig "_embedded", "details", "attribute"
expect(attr).to eq "type" expect(attr).to eq "type"
end end
@ -165,17 +163,17 @@ describe ::API::V3::Relations::RelationRepresenter, type: :request do
end end
it "should return 422" do it "should return 422" do
expect(response.status).to eq 422 expect(last_response.status).to eq 422
end end
it "should indicate an error with the `from` attribute" do it "should indicate an error with the `from` attribute" do
attr = JSON.parse(response.body).dig "_embedded", "details", "attribute" attr = JSON.parse(last_response.body).dig "_embedded", "details", "attribute"
expect(attr).to eq "from" expect(attr).to eq "from"
end end
it "should let the user know the attribute is read-only" do it "should let the user know the attribute is read-only" do
msg = JSON.parse(response.body)["message"] msg = JSON.parse(last_response.body)["message"]
expect(msg).to include 'read-only' expect(msg).to include 'read-only'
end end
@ -199,14 +197,13 @@ describe ::API::V3::Relations::RelationRepresenter, type: :request do
before do before do
project.add_member! user, role project.add_member! user, role
post "/api/v3/work_packages/#{from.id}/relations", header "Content-Type", "application/json"
params: params.to_json, post "/api/v3/work_packages/#{from.id}/relations", params.to_json
headers: { "Content-Type": "application/json" }
end end
context "with the required permissions" do context "with the required permissions" do
it "works" do it "works" do
expect(response.status).to eq 201 expect(last_response.status).to eq 201
end end
end end
@ -214,7 +211,7 @@ describe ::API::V3::Relations::RelationRepresenter, type: :request do
let(:permissions) { [:view_work_packages] } let(:permissions) { [:view_work_packages] }
it "is forbidden" do it "is forbidden" do
expect(response.status).to eq 403 expect(last_response.status).to eq 403
end end
end end
@ -226,17 +223,17 @@ describe ::API::V3::Relations::RelationRepresenter, type: :request do
let!(:to) { FactoryGirl.create :work_package } let!(:to) { FactoryGirl.create :work_package }
it "should return 422" do it "should return 422" do
expect(response.status).to eq 422 expect(last_response.status).to eq 422
end end
it "should indicate an error with the `to` attribute" do it "should indicate an error with the `to` attribute" do
attr = JSON.parse(response.body).dig "_embedded", "details", "attribute" attr = JSON.parse(last_response.body).dig "_embedded", "details", "attribute"
expect(attr).to eq "to" expect(attr).to eq "to"
end end
it "should have a localized error message" do it "should have a localized error message" do
message = JSON.parse(response.body)["message"] message = JSON.parse(last_response.body)["message"]
expect(message).not_to include "translation missing" expect(message).not_to include "translation missing"
end end
@ -251,7 +248,7 @@ describe ::API::V3::Relations::RelationRepresenter, type: :request do
end end
it "should return 204 and destroy the relation" do it "should return 204 and destroy the relation" do
expect(response.status).to eq 204 expect(last_response.status).to eq 204
expect(Relation.exists?(relation.id)).to eq false expect(Relation.exists?(relation.id)).to eq false
end end
end end
@ -305,19 +302,19 @@ describe ::API::V3::Relations::RelationRepresenter, type: :request do
end end
it 'returns 200' do it 'returns 200' do
expect(response.status).to eql 200 expect(last_response.status).to eql 200
end end
it 'returns the visible relation (and only the visible one) satisfying the filter' do it 'returns the visible relation (and only the visible one) satisfying the filter' do
expect(response.body) expect(last_response.body)
.to be_json_eql('1') .to be_json_eql('1')
.at_path('total') .at_path('total')
expect(response.body) expect(last_response.body)
.to be_json_eql('1') .to be_json_eql('1')
.at_path('count') .at_path('count')
expect(response.body) expect(last_response.body)
.to be_json_eql(relation.id.to_json) .to be_json_eql(relation.id.to_json)
.at_path('_embedded/elements/0/id') .at_path('_embedded/elements/0/id')
end end

@ -69,9 +69,10 @@ describe 'GET /api/v3/relations', type: :request do
filters: [filter].to_json filters: [filter].to_json
} }
get "/api/v3/relations", params: params header "Content-Type", "application/json"
get "/api/v3/relations", params
json = JSON.parse response.body json = JSON.parse last_response.body
Array(Hash(json).dig("_embedded", "elements")).map { |e| e["id"] } Array(Hash(json).dig("_embedded", "elements")).map { |e| e["id"] }
end end

@ -27,7 +27,7 @@
#++ #++
shared_examples_for 'safeguarded API' do shared_examples_for 'safeguarded API' do
it { expect(response.response_code).to eq(404) } it { expect(last_response.status).to eq(404) }
end end
shared_examples_for 'valid activity request' do shared_examples_for 'valid activity request' do
@ -38,10 +38,10 @@ shared_examples_for 'valid activity request' do
allow(User).to receive(:current).and_return(admin) allow(User).to receive(:current).and_return(admin)
end end
it { expect(response.response_code).to eq(status_code) } it { expect(last_response.status).to eq(status_code) }
describe 'response body' do describe 'response body' do
subject { response.body } subject { last_response.body }
it { is_expected.to be_json_eql('Activity::Comment'.to_json).at_path('_type') } it { is_expected.to be_json_eql('Activity::Comment'.to_json).at_path('_type') }
@ -55,5 +55,5 @@ shared_examples_for 'invalid activity request' do
allow(User).to receive(:current).and_return(admin) allow(User).to receive(:current).and_return(admin)
end end
it { expect(response.response_code).to eq(422) } it { expect(last_response.status).to eq(422) }
end end

@ -29,9 +29,9 @@
require 'spec_helper' require 'spec_helper'
shared_examples_for 'API V3 collection response' do |total, count, type| shared_examples_for 'API V3 collection response' do |total, count, type|
subject { response.body } subject { last_response.body }
it { expect(response.status).to eql(200) } it { expect(last_response.status).to eql(200) }
it { is_expected.to be_json_eql('Collection'.to_json).at_path('_type') } it { is_expected.to be_json_eql('Collection'.to_json).at_path('_type') }

@ -41,18 +41,19 @@ describe ::API::V3::Users::UsersAPI, type: :request do
end end
def send_request def send_request
post path, params: parameters.to_json, headers: { 'Content-Type' => 'application/json' } header "Content-Type", "application/json"
post path, parameters.to_json
end end
let(:errors) { parse_json(response.body)['_embedded']['errors'] } let(:errors) { parse_json(last_response.body)['_embedded']['errors'] }
shared_context 'represents the created user' do |expected_attributes| shared_context 'represents the created user' do |expected_attributes|
it 'returns the represented user' do it 'returns the represented user' do
send_request send_request
expect(response.status).to eq(201) expect(last_response.status).to eq(201)
expect(response.body).to have_json_type(Object).at_path('_links') expect(last_response.body).to have_json_type(Object).at_path('_links')
expect(response.body) expect(last_response.body)
.to be_json_eql('User'.to_json) .to be_json_eql('User'.to_json)
.at_path('_type') .at_path('_type')
@ -69,13 +70,13 @@ describe ::API::V3::Users::UsersAPI, type: :request do
it 'returns an erroneous response' do it 'returns an erroneous response' do
send_request send_request
expect(response.status).to eq(422) expect(last_response.status).to eq(422)
expect(errors.count).to eq(5) expect(errors.count).to eq(5)
expect(errors.collect { |el| el['_embedded']['details']['attribute'] }) expect(errors.collect { |el| el['_embedded']['details']['attribute'] })
.to contain_exactly('password', 'login', 'firstname', 'lastname', 'email') .to contain_exactly('password', 'login', 'firstname', 'lastname', 'email')
expect(response.body) expect(last_response.body)
.to be_json_eql('urn:openproject-org:api:v3:errors:MultipleErrors'.to_json) .to be_json_eql('urn:openproject-org:api:v3:errors:MultipleErrors'.to_json)
.at_path('errorIdentifier') .at_path('errorIdentifier')
end end
@ -150,9 +151,9 @@ describe ::API::V3::Users::UsersAPI, type: :request do
it 'returns an error for the authSource attribute' do it 'returns an error for the authSource attribute' do
send_request send_request
attr = JSON.parse(response.body).dig "_embedded", "details", "attribute" attr = JSON.parse(last_response.body).dig "_embedded", "details", "attribute"
expect(response.status).to eq 422 expect(last_response.status).to eq 422
expect(attr).to eq "authSource" expect(attr).to eq "authSource"
end end
end end
@ -186,9 +187,9 @@ describe ::API::V3::Users::UsersAPI, type: :request do
it 'returns the represented user' do it 'returns the represented user' do
send_request send_request
expect(response.body).not_to have_json_path("_embedded/errors") expect(last_response.body).not_to have_json_path("_embedded/errors")
expect(response.body).to have_json_type(Object).at_path('_links') expect(last_response.body).to have_json_type(Object).at_path('_links')
expect(response.body) expect(last_response.body)
.to be_json_eql('User'.to_json) .to be_json_eql('User'.to_json)
.at_path('_type') .at_path('_type')
end end
@ -255,10 +256,10 @@ describe ::API::V3::Users::UsersAPI, type: :request do
it 'marks the mail as missing' do it 'marks the mail as missing' do
send_request send_request
expect(response.body) expect(last_response.body)
.to be_json_eql('urn:openproject-org:api:v3:errors:PropertyConstraintViolation'.to_json) .to be_json_eql('urn:openproject-org:api:v3:errors:PropertyConstraintViolation'.to_json)
.at_path('errorIdentifier') .at_path('errorIdentifier')
expect(response.body) expect(last_response.body)
.to be_json_eql('email'.to_json) .to be_json_eql('email'.to_json)
.at_path('_embedded/details/attribute') .at_path('_embedded/details/attribute')
end end
@ -271,10 +272,10 @@ describe ::API::V3::Users::UsersAPI, type: :request do
it 'returns an erroneous response' do it 'returns an erroneous response' do
send_request send_request
expect(response.status).to eq(422) expect(last_response.status).to eq(422)
expect(errors).not_to be_empty expect(errors).not_to be_empty
expect(response.body) expect(last_response.body)
.to be_json_eql('urn:openproject-org:api:v3:errors:MultipleErrors'.to_json) .to be_json_eql('urn:openproject-org:api:v3:errors:MultipleErrors'.to_json)
.at_path('errorIdentifier') .at_path('errorIdentifier')
@ -289,7 +290,7 @@ describe ::API::V3::Users::UsersAPI, type: :request do
it 'returns an erroneous response' do it 'returns an erroneous response' do
send_request send_request
expect(response.status).to eq(403) expect(last_response.status).to eq(403)
end end
end end
end end

@ -54,9 +54,9 @@ describe 'GET /api/v3/users', type: :request do
filters: [filter].to_json filters: [filter].to_json
} }
get "/api/v3/users", params: params get "/api/v3/users", params
json = JSON.parse response.body json = JSON.parse last_response.body
Array(Hash(json).dig("_embedded", "elements")).map { |e| e["login"] } Array(Hash(json).dig("_embedded", "elements")).map { |e| e["login"] }
end end

@ -43,16 +43,17 @@ describe ::API::V3::Users::UsersAPI, type: :request do
end end
def send_request def send_request
patch path, params: parameters.to_json, headers: { 'Content-Type' => 'application/json' } header "Content-Type", "application/json"
patch path, parameters.to_json
end end
shared_context 'successful update' do |expected_attributes| shared_context 'successful update' do |expected_attributes|
it 'responds with the represented updated user' do it 'responds with the represented updated user' do
send_request send_request
expect(response.status).to eq(200) expect(last_response.status).to eq(200)
expect(response.body).to have_json_type(Object).at_path('_links') expect(last_response.body).to have_json_type(Object).at_path('_links')
expect(response.body) expect(last_response.body)
.to be_json_eql('User'.to_json) .to be_json_eql('User'.to_json)
.at_path('_type') .at_path('_type')
@ -78,7 +79,7 @@ describe ::API::V3::Users::UsersAPI, type: :request do
it 'updates the users password correctly' do it 'updates the users password correctly' do
send_request send_request
expect(response.status).to eq(200) expect(last_response.status).to eq(200)
updated_user = User.find(user.id) updated_user = User.find(user.id)
matches = updated_user.check_password?(password) matches = updated_user.check_password?(password)
@ -96,13 +97,13 @@ describe ::API::V3::Users::UsersAPI, type: :request do
it 'returns an erroneous response' do it 'returns an erroneous response' do
send_request send_request
expect(response.status).to eq(422) expect(last_response.status).to eq(422)
expect(response.body) expect(last_response.body)
.to be_json_eql('email'.to_json) .to be_json_eql('email'.to_json)
.at_path('_embedded/details/attribute') .at_path('_embedded/details/attribute')
expect(response.body) expect(last_response.body)
.to be_json_eql('urn:openproject-org:api:v3:errors:PropertyConstraintViolation'.to_json) .to be_json_eql('urn:openproject-org:api:v3:errors:PropertyConstraintViolation'.to_json)
.at_path('errorIdentifier') .at_path('errorIdentifier')
end end
@ -114,7 +115,7 @@ describe ::API::V3::Users::UsersAPI, type: :request do
it 'responds with 404' do it 'responds with 404' do
send_request send_request
expect(response.status).to eql(404) expect(last_response.status).to eql(404)
end end
end end
@ -124,7 +125,7 @@ describe ::API::V3::Users::UsersAPI, type: :request do
it 'returns an erroneous response' do it 'returns an erroneous response' do
send_request send_request
expect(response.status).to eq(403) expect(last_response.status).to eq(403)
end end
end end
end end

@ -53,7 +53,7 @@ describe API::V3::WorkPackages::AvailableProjectsOnCreateAPI, type: :request do
it_behaves_like 'API V3 collection response', 1, 1, 'Project' it_behaves_like 'API V3 collection response', 1, 1, 'Project'
it 'has the project for which the add_work_packages permission exists' do it 'has the project for which the add_work_packages permission exists' do
expect(response.body).to be_json_eql(project.id).at_path('_embedded/elements/0/id') expect(last_response.body).to be_json_eql(project.id).at_path('_embedded/elements/0/id')
end end
end end
@ -62,6 +62,6 @@ describe API::V3::WorkPackages::AvailableProjectsOnCreateAPI, type: :request do
FactoryGirl.create(:role, permissions: []) FactoryGirl.create(:role, permissions: [])
end end
it { expect(response.status).to eq(403) } it { expect(last_response.status).to eq(403) }
end end
end end

@ -64,7 +64,7 @@ describe 'API::V3::WorkPackages::AvailableProjectsOnEditAPI', type: :request do
it_behaves_like 'API V3 collection response', 1, 1, 'Project' it_behaves_like 'API V3 collection response', 1, 1, 'Project'
it 'has the project for which the move_work_packages permission exists' do it 'has the project for which the move_work_packages permission exists' do
expect(response.body).to be_json_eql(target_project.id).at_path('_embedded/elements/0/id') expect(last_response.body).to be_json_eql(target_project.id).at_path('_embedded/elements/0/id')
end end
end end
@ -73,7 +73,7 @@ describe 'API::V3::WorkPackages::AvailableProjectsOnEditAPI', type: :request do
FactoryGirl.create(:role, permissions: [:view_work_packages]) FactoryGirl.create(:role, permissions: [:view_work_packages])
end end
it { expect(response.status).to eq(403) } it { expect(last_response.status).to eq(403) }
end end
context 'w/o the view_work_packages permission' do context 'w/o the view_work_packages permission' do
@ -81,6 +81,6 @@ describe 'API::V3::WorkPackages::AvailableProjectsOnEditAPI', type: :request do
FactoryGirl.create(:role, permissions: [:edit_work_packages]) FactoryGirl.create(:role, permissions: [:edit_work_packages])
end end
it { expect(response.status).to eq(404) } it { expect(last_response.status).to eq(404) }
end end
end end

@ -61,7 +61,7 @@ describe ::API::V3::Relations::RelationRepresenter, type: :request do
let(:request) { get href } let(:request) { get href }
let(:result) do let(:result) do
request request
JSON.parse response.body JSON.parse last_response.body
end end
let(:subjects) { work_packages.map { |e| e["subject"] } } let(:subjects) { work_packages.map { |e| e["subject"] } }

@ -91,9 +91,9 @@ describe 'API v3 Work package form resource', type: :request do
context 'existing work package' do context 'existing work package' do
shared_examples_for 'valid payload' do shared_examples_for 'valid payload' do
subject { response.body } subject { last_response.body }
it { expect(response.status).to eq(200) } it { expect(last_response.status).to eq(200) }
it { is_expected.to have_json_path('_embedded/payload') } it { is_expected.to have_json_path('_embedded/payload') }
@ -207,7 +207,7 @@ describe 'API v3 Work package form resource', type: :request do
include_context 'post request' include_context 'post request'
it { expect(response.status).to eq(409) } it { expect(last_response.status).to eq(409) }
it_behaves_like 'update conflict' it_behaves_like 'update conflict'
end end

@ -36,13 +36,15 @@ describe 'attachments routes', type: :request do
it 'redirects /attachments/download with filename to attachments#download' do it 'redirects /attachments/download with filename to attachments#download' do
get '/attachments/download/42/foo.png' get '/attachments/download/42/foo.png'
expect(response).to redirect_to('/attachments/42/foo.png') expect(last_response).to be_redirect
expect(last_response.location).to end_with '/attachments/42/foo.png'
end end
it 'redirects /attachments/download without filename to attachments#download' do it 'redirects /attachments/download without filename to attachments#download' do
get '/attachments/download/42' get '/attachments/download/42'
expect(response).to redirect_to('/attachments/42') expect(last_response).to be_redirect
expect(last_response.location).to end_with '/attachments/42'
end end
end end
end end

@ -55,13 +55,13 @@ describe 'API v2', type: :request do
context 'invalid' do context 'invalid' do
before { get "#{request_url}?key=invalid_key" } before { get "#{request_url}?key=invalid_key" }
it { expect(response.status).to eq(401) } it { expect(last_response.status).to eq(401) }
end end
context 'valid' do context 'valid' do
before { get "#{request_url}?key=#{api_key}" } before { get "#{request_url}?key=#{api_key}" }
it { expect(response.status).to eq(200) } it { expect(last_response.status).to eq(200) }
end end
end end
@ -73,25 +73,26 @@ describe 'API v2', type: :request do
before do before do
allow(OpenProject::Configuration).to receive(:apiv2_enable_basic_auth?).and_return(enabled) allow(OpenProject::Configuration).to receive(:apiv2_enable_basic_auth?).and_return(enabled)
get request_url, headers: { 'Authorization' => credentials } header 'Authorization', credentials
get request_url
end end
context 'when enabled' do context 'when enabled' do
let(:enabled) { true } let(:enabled) { true }
context 'valid' do context 'valid' do
it { expect(response.status).to eq(200) } it { expect(last_response.status).to eq(200) }
end end
context 'invalid' do context 'invalid' do
let(:used_password) { 'foobar' } let(:used_password) { 'foobar' }
it { expect(response.status).to eq(401) } it { expect(last_response.status).to eq(401) }
end end
end end
context 'when disabled' do context 'when disabled' do
let(:enabled) { false } let(:enabled) { false }
it { expect(response.status).to eq(401) } it { expect(last_response.status).to eq(401) }
end end
end end

@ -48,7 +48,7 @@ module ResetCurrentUserCallback
end end
end end
describe ResetCurrentUser, type: :request do describe ResetCurrentUser, type: :rails_request do
let!(:user) { FactoryGirl.create :user } let!(:user) { FactoryGirl.create :user }
before do before do

@ -39,7 +39,10 @@ describe 'routes for old issue uris', type: :request do
get('/issues') get('/issues')
end end
it { expect(response).to redirect_to('/work_packages') } it do
expect(last_response).to be_redirect
expect(last_response.location).to end_with '/work_packages'
end
end end
describe 'with specific id' do describe 'with specific id' do
@ -47,6 +50,9 @@ describe 'routes for old issue uris', type: :request do
get('/issues/1234') get('/issues/1234')
end end
it { expect(response).to redirect_to('/work_packages/1234') } it do
expect(last_response).to be_redirect
expect(last_response.location).to end_with '/work_packages/1234'
end
end end
end end

@ -39,7 +39,10 @@ describe 'routes for old issue uris', type: :request do
get('/wp') get('/wp')
end end
it { expect(response).to redirect_to('/work_packages') } it do
expect(last_response).to be_redirect
expect(last_response.location).to end_with '/work_packages'
end
end end
describe 'with specific id' do describe 'with specific id' do
@ -47,6 +50,9 @@ describe 'routes for old issue uris', type: :request do
get('/wp/1234') get('/wp/1234')
end end
it { expect(response).to redirect_to('/work_packages/1234') } it do
expect(last_response).to be_redirect
expect(last_response.location).to end_with '/work_packages/1234'
end
end end
end end

@ -1,59 +0,0 @@
module APISessionAuthentication
def merge_with_header(args = {})
# Can't get example. in here
metadata = self.class.metadata
headers = args.fetch(:headers) { {} }
unless metadata[:skip_xhr_header]
headers.merge!('X-Requested-With' => 'XMLHttpRequest')
end
headers
end
def get(path, args = {})
args[:headers] = merge_with_header args
super
end
def post(path, args = {})
args[:headers] = merge_with_header args
super
end
def put(path, args = {})
args[:headers] = merge_with_header args
super
end
def delete(path, args = {})
args[:headers] = merge_with_header args
super
end
def patch(path, args = {})
args[:headers] = merge_with_header args
super
end
def head(path, args = {})
args[:headers] = merge_with_header args
super
end
end
RSpec.configure do |c|
##
# Session-based API authentication requires the X-requested-with header to be present.
# Since Integration tests of Rails do not offer adding a header to all requests as
# Capybara or Rack::Test does, we simply extend the request helpers to do so.
c.include APISessionAuthentication, type: :request
c.before(:each, type: :feature) do |ex|
unless ex.metadata[:skip_xhr_header] || ex.metadata[:js]
page.driver.header('X-Requested-With', 'XMLHttpRequest')
end
end
end

@ -0,0 +1,18 @@
RSpec.configure do |c|
##
# Session-based API authentication requires the X-requested-with header to be present.
c.before(:each, type: :request) do |ex|
unless ex.metadata[:skip_xhr_header]
header('X-Requested-With', 'XMLHttpRequest')
end
end
c.before(:each, type: :feature) do |ex|
unless ex.metadata[:skip_xhr_header] || ex.metadata[:js]
page.driver.header('X-Requested-With', 'XMLHttpRequest')
end
end
end

@ -0,0 +1,16 @@
module RackTestHelper
include Rack::Test::Methods
def app
Rails.application
end
end
RSpec.configure do |config|
# Use Rack::Test for regular request specs (esp. API requests)
config.include RackTestHelper, type: :request
# If desired, we can use the Rails IntegrationTest request spec
# (more like a feature spec) with this type.
config.include RSpec::Rails::RequestExampleGroup, type: :rails_request
end
Loading…
Cancel
Save