179 lines
6.4 KiB
Ruby
179 lines
6.4 KiB
Ruby
require 'rails_helper'
|
|
|
|
RSpec.describe 'Api::V1::CrewMemberships', type: :request do
|
|
let(:user) { create(:user) }
|
|
let(:access_token) do
|
|
Doorkeeper::AccessToken.create!(resource_owner_id: user.id, expires_in: 30.days, scopes: 'public')
|
|
end
|
|
let(:auth_headers) { { 'Authorization' => "Bearer #{access_token.token}" } }
|
|
|
|
let(:crew) { create(:crew) }
|
|
let(:target_user) { create(:user) }
|
|
let!(:target_membership) { create(:crew_membership, crew: crew, user: target_user, role: :member) }
|
|
|
|
describe 'PUT /api/v1/crews/:crew_id/memberships/:id' do
|
|
context 'as captain' do
|
|
let!(:captain_membership) { create(:crew_membership, crew: crew, user: user, role: :captain) }
|
|
|
|
it 'updates member role' do
|
|
put "/api/v1/crews/#{crew.id}/memberships/#{target_membership.id}",
|
|
params: { membership: { role: 'vice_captain' } },
|
|
headers: auth_headers
|
|
|
|
expect(response).to have_http_status(:ok)
|
|
json = JSON.parse(response.body)
|
|
expect(json['membership']['role']).to eq('vice_captain')
|
|
end
|
|
end
|
|
|
|
context 'as vice captain' do
|
|
let!(:vc_membership) { create(:crew_membership, crew: crew, user: user, role: :vice_captain) }
|
|
|
|
it 'cannot change role but request succeeds' do
|
|
put "/api/v1/crews/#{crew.id}/memberships/#{target_membership.id}",
|
|
params: { membership: { role: 'vice_captain' } },
|
|
headers: auth_headers
|
|
|
|
# Vice captains can access update endpoint (for joined_at) but role param is ignored
|
|
expect(response).to have_http_status(:ok)
|
|
expect(target_membership.reload.role).to eq('member') # Role not changed
|
|
end
|
|
|
|
it 'can update joined_at' do
|
|
put "/api/v1/crews/#{crew.id}/memberships/#{target_membership.id}",
|
|
params: { membership: { joined_at: '2024-01-15' } },
|
|
headers: auth_headers
|
|
|
|
expect(response).to have_http_status(:ok)
|
|
json = JSON.parse(response.body)
|
|
expect(json['membership']['joined_at']).to include('2024-01-15')
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'DELETE /api/v1/crews/:crew_id/memberships/:id' do
|
|
context 'as captain' do
|
|
let!(:captain_membership) { create(:crew_membership, crew: crew, user: user, role: :captain) }
|
|
|
|
it 'removes a member' do
|
|
delete "/api/v1/crews/#{crew.id}/memberships/#{target_membership.id}",
|
|
headers: auth_headers
|
|
|
|
expect(response).to have_http_status(:no_content)
|
|
expect(target_membership.reload.retired).to be true
|
|
end
|
|
|
|
it 'cannot remove self (captain)' do
|
|
delete "/api/v1/crews/#{crew.id}/memberships/#{captain_membership.id}",
|
|
headers: auth_headers
|
|
|
|
expect(response).to have_http_status(:unprocessable_entity)
|
|
json = JSON.parse(response.body)
|
|
expect(json['code']).to eq('cannot_remove_captain')
|
|
end
|
|
end
|
|
|
|
context 'as vice captain' do
|
|
let!(:vc_membership) { create(:crew_membership, crew: crew, user: user, role: :vice_captain) }
|
|
|
|
it 'can remove regular members' do
|
|
delete "/api/v1/crews/#{crew.id}/memberships/#{target_membership.id}",
|
|
headers: auth_headers
|
|
|
|
expect(response).to have_http_status(:no_content)
|
|
end
|
|
end
|
|
|
|
context 'as regular member' do
|
|
let!(:membership) { create(:crew_membership, crew: crew, user: user, role: :member) }
|
|
|
|
it 'returns unauthorized' do
|
|
delete "/api/v1/crews/#{crew.id}/memberships/#{target_membership.id}",
|
|
headers: auth_headers
|
|
|
|
expect(response).to have_http_status(:unauthorized)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'POST /api/v1/crews/:crew_id/memberships/:id/promote' do
|
|
context 'as captain' do
|
|
let!(:captain_membership) { create(:crew_membership, crew: crew, user: user, role: :captain) }
|
|
|
|
it 'promotes member to vice captain' do
|
|
post "/api/v1/crews/#{crew.id}/memberships/#{target_membership.id}/promote",
|
|
headers: auth_headers
|
|
|
|
expect(response).to have_http_status(:ok)
|
|
json = JSON.parse(response.body)
|
|
expect(json['membership']['role']).to eq('vice_captain')
|
|
end
|
|
|
|
it 'returns error when VC limit reached' do
|
|
3.times { create(:crew_membership, crew: crew, role: :vice_captain) }
|
|
|
|
post "/api/v1/crews/#{crew.id}/memberships/#{target_membership.id}/promote",
|
|
headers: auth_headers
|
|
|
|
expect(response).to have_http_status(:unprocessable_entity)
|
|
json = JSON.parse(response.body)
|
|
expect(json['code']).to eq('vice_captain_limit')
|
|
end
|
|
|
|
it 'cannot promote captain' do
|
|
post "/api/v1/crews/#{crew.id}/memberships/#{captain_membership.id}/promote",
|
|
headers: auth_headers
|
|
|
|
expect(response).to have_http_status(:unprocessable_entity)
|
|
end
|
|
end
|
|
|
|
context 'as vice captain' do
|
|
let!(:vc_membership) { create(:crew_membership, crew: crew, user: user, role: :vice_captain) }
|
|
|
|
it 'returns unauthorized' do
|
|
post "/api/v1/crews/#{crew.id}/memberships/#{target_membership.id}/promote",
|
|
headers: auth_headers
|
|
|
|
expect(response).to have_http_status(:unauthorized)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'POST /api/v1/crews/:crew_id/memberships/:id/demote' do
|
|
let!(:vc_target) { create(:crew_membership, crew: crew, role: :vice_captain) }
|
|
|
|
context 'as captain' do
|
|
let!(:captain_membership) { create(:crew_membership, crew: crew, user: user, role: :captain) }
|
|
|
|
it 'demotes vice captain to member' do
|
|
post "/api/v1/crews/#{crew.id}/memberships/#{vc_target.id}/demote",
|
|
headers: auth_headers
|
|
|
|
expect(response).to have_http_status(:ok)
|
|
json = JSON.parse(response.body)
|
|
expect(json['membership']['role']).to eq('member')
|
|
end
|
|
|
|
it 'cannot demote captain' do
|
|
post "/api/v1/crews/#{crew.id}/memberships/#{captain_membership.id}/demote",
|
|
headers: auth_headers
|
|
|
|
expect(response).to have_http_status(:unprocessable_entity)
|
|
json = JSON.parse(response.body)
|
|
expect(json['code']).to eq('cannot_demote_captain')
|
|
end
|
|
end
|
|
|
|
context 'as vice captain' do
|
|
let!(:vc_membership) { create(:crew_membership, crew: crew, user: user, role: :vice_captain) }
|
|
|
|
it 'returns unauthorized' do
|
|
post "/api/v1/crews/#{crew.id}/memberships/#{vc_target.id}/demote",
|
|
headers: auth_headers
|
|
|
|
expect(response).to have_http_status(:unauthorized)
|
|
end
|
|
end
|
|
end
|
|
end
|