Refactor GridSummonsController
- Refactors controller - Adds YARD documentation - Adds Rspec tests
This commit is contained in:
parent
9a54363a7f
commit
7b16fdc112
2 changed files with 466 additions and 48 deletions
|
|
@ -3,17 +3,19 @@
|
||||||
module Api
|
module Api
|
||||||
module V1
|
module V1
|
||||||
##
|
##
|
||||||
# Controller responsible for managing grid summons for a party.
|
# Controller handling API requests related to grid summons within a party.
|
||||||
# Provides actions to create, update, and destroy grid summons.
|
|
||||||
#
|
#
|
||||||
# @note All actions assume that the request has been authorized.
|
# This controller provides endpoints for creating, updating, resolving conflicts, and deleting grid summons.
|
||||||
|
# It ensures that the correct party and summons are found and that the current user (or edit key) is authorized.
|
||||||
|
#
|
||||||
|
# @see Api::V1::ApiController for shared API behavior.
|
||||||
class GridSummonsController < Api::V1::ApiController
|
class GridSummonsController < Api::V1::ApiController
|
||||||
attr_reader :party, :incoming_summon
|
attr_reader :party, :incoming_summon
|
||||||
|
|
||||||
before_action :set, only: %w[update update_uncap_level update_quick_summon]
|
before_action :find_grid_summon, only: %i[update update_uncap_level update_quick_summon resolve destroy]
|
||||||
before_action :find_party, only: :create
|
before_action :find_party, only: %i[create update update_uncap_level update_quick_summon resolve destroy]
|
||||||
before_action :find_incoming_summon, only: :create
|
before_action :find_incoming_summon, only: :create
|
||||||
before_action :authorize, only: %i[create update update_uncap_level update_quick_summon destroy]
|
before_action :authorize_party_edit!, only: %i[create update update_uncap_level update_quick_summon destroy]
|
||||||
|
|
||||||
##
|
##
|
||||||
# Creates a new grid summon.
|
# Creates a new grid summon.
|
||||||
|
|
@ -52,11 +54,11 @@ module Api
|
||||||
#
|
#
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def update
|
def update
|
||||||
@summon.attributes = summon_params
|
@grid_summon.attributes = summon_params
|
||||||
|
|
||||||
return render json: GridSummonBlueprint.render(@summon, view: :nested, root: :grid_summon) if @summon.save
|
return render json: GridSummonBlueprint.render(@grid_summon, view: :nested, root: :grid_summon) if @grid_summon.save
|
||||||
|
|
||||||
render_validation_error_response(@summon)
|
render_validation_error_response(@grid_summon)
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
@ -68,7 +70,7 @@ module Api
|
||||||
#
|
#
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def update_uncap_level
|
def update_uncap_level
|
||||||
summon = @summon.summon
|
summon = @grid_summon.summon
|
||||||
max_level = max_uncap_level(summon)
|
max_level = max_uncap_level(summon)
|
||||||
|
|
||||||
greater_than_max_uncap = summon_params[:uncap_level].to_i > max_level
|
greater_than_max_uncap = summon_params[:uncap_level].to_i > max_level
|
||||||
|
|
@ -79,10 +81,10 @@ module Api
|
||||||
new_uncap_level = greater_than_max_uncap || can_be_transcended ? max_level : summon_params[:uncap_level]
|
new_uncap_level = greater_than_max_uncap || can_be_transcended ? max_level : summon_params[:uncap_level]
|
||||||
new_transcendence_step = summon.transcendence && summon_params[:transcendence_step].present? ? summon_params[:transcendence_step] : 0
|
new_transcendence_step = summon.transcendence && summon_params[:transcendence_step].present? ? summon_params[:transcendence_step] : 0
|
||||||
|
|
||||||
if @summon.update(uncap_level: new_uncap_level, transcendence_step: new_transcendence_step)
|
if @grid_summon.update(uncap_level: new_uncap_level, transcendence_step: new_transcendence_step)
|
||||||
render json: GridSummonBlueprint.render(@summon, view: :nested, root: :grid_summon)
|
render json: GridSummonBlueprint.render(@grid_summon, view: :nested, root: :grid_summon)
|
||||||
else
|
else
|
||||||
render_validation_error_response(@summon)
|
render_validation_error_response(@grid_summon)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -95,19 +97,19 @@ module Api
|
||||||
#
|
#
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def update_quick_summon
|
def update_quick_summon
|
||||||
return if [4, 5, 6].include?(@summon.position)
|
return if [4, 5, 6].include?(@grid_summon.position)
|
||||||
|
|
||||||
quick_summons = @summon.party.summons.select(&:quick_summon)
|
quick_summons = @grid_summon.party.summons.select(&:quick_summon)
|
||||||
|
|
||||||
quick_summons.each do |summon|
|
quick_summons.each do |summon|
|
||||||
summon.update!(quick_summon: false)
|
summon.update!(quick_summon: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
@summon.update!(quick_summon: summon_params[:quick_summon])
|
@grid_summon.update!(quick_summon: summon_params[:quick_summon])
|
||||||
return unless @summon.persisted?
|
return unless @grid_summon.persisted?
|
||||||
|
|
||||||
quick_summons -= [@summon]
|
quick_summons -= [@grid_summon]
|
||||||
summons = [@summon] + quick_summons
|
summons = [@grid_summon] + quick_summons
|
||||||
|
|
||||||
render json: GridSummonBlueprint.render(summons, view: :nested, root: :summons)
|
render json: GridSummonBlueprint.render(summons, view: :nested, root: :summons)
|
||||||
end
|
end
|
||||||
|
|
@ -124,7 +126,6 @@ module Api
|
||||||
grid_summon = GridSummon.find_by('id = ?', params[:id])
|
grid_summon = GridSummon.find_by('id = ?', params[:id])
|
||||||
|
|
||||||
return render_not_found_response('grid_summon') if grid_summon.nil?
|
return render_not_found_response('grid_summon') if grid_summon.nil?
|
||||||
return render_unauthorized_response if grid_summon.party.user != current_user
|
|
||||||
|
|
||||||
render json: GridSummonBlueprint.render(grid_summon, view: :destroyed), status: :ok if grid_summon.destroy
|
render json: GridSummonBlueprint.render(grid_summon, view: :destroyed), status: :ok if grid_summon.destroy
|
||||||
end
|
end
|
||||||
|
|
@ -182,10 +183,28 @@ module Api
|
||||||
# user is not the owner of the party.
|
# user is not the owner of the party.
|
||||||
#
|
#
|
||||||
# @return [void]
|
# @return [void]
|
||||||
|
|
||||||
|
##
|
||||||
|
# Finds and sets the party based on parameters.
|
||||||
|
#
|
||||||
|
# Renders an unauthorized response if the current user is not the owner.
|
||||||
|
#
|
||||||
|
# @return [void]
|
||||||
def find_party
|
def find_party
|
||||||
# BUG: I can create grid weapons even when I'm not logged in on an authenticated party
|
@party = Party.find_by(id: params.dig(:summon, :party_id)) || Party.find_by(id: params[:party_id]) || @grid_summon&.party
|
||||||
@party = Party.find(summon_params[:party_id])
|
render_not_found_response('party') unless @party
|
||||||
render_unauthorized_response if current_user && (party.user != current_user)
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Finds and sets the GridSummon based on the provided parameters.
|
||||||
|
#
|
||||||
|
# Searches for a grid summon using various parameter keys and renders a not found response if it is absent.
|
||||||
|
#
|
||||||
|
# @return [void]
|
||||||
|
def find_grid_summon
|
||||||
|
grid_summon_id = params[:id] || params.dig(:summon, :id) || params.dig(:resolve, :conflicting)
|
||||||
|
@grid_summon = GridSummon.find_by(id: grid_summon_id)
|
||||||
|
render_not_found_response('grid_summon') unless @grid_summon
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
@ -198,31 +217,6 @@ module Api
|
||||||
@incoming_summon = Summon.find_by(id: summon_params[:summon_id])
|
@incoming_summon = Summon.find_by(id: summon_params[:summon_id])
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
|
||||||
# Finds and sets the grid summon for update actions.
|
|
||||||
#
|
|
||||||
# Sets the @summon instance variable using the provided id parameter.
|
|
||||||
#
|
|
||||||
# @return [void]
|
|
||||||
def set
|
|
||||||
@summon = GridSummon.find_by('id = ?', summon_params[:id])
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Authorizes the current request based on the party or grid summon ownership and edit key.
|
|
||||||
#
|
|
||||||
# Checks if the current user is authorized to create or update the party or grid summon.
|
|
||||||
# Renders an unauthorized response if the authorization fails.
|
|
||||||
#
|
|
||||||
# @return [void]
|
|
||||||
def authorize
|
|
||||||
# Create
|
|
||||||
unauthorized_create = @party && (@party.user != current_user || @party.edit_key != edit_key)
|
|
||||||
unauthorized_update = @summon && @summon.party && (@summon.party.user != current_user || @summon.party.edit_key != edit_key)
|
|
||||||
|
|
||||||
render_unauthorized_response if unauthorized_create || unauthorized_update
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Builds a new GridSummon instance using permitted parameters.
|
# Builds a new GridSummon instance using permitted parameters.
|
||||||
#
|
#
|
||||||
|
|
@ -282,6 +276,61 @@ module Api
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Authorizes the current action by ensuring that the current user or provided edit key matches the party's owner.
|
||||||
|
#
|
||||||
|
# For parties associated with a user, it verifies that the current_user is the owner.
|
||||||
|
# For anonymous parties, it checks that the provided edit key matches the party's edit key.
|
||||||
|
#
|
||||||
|
# @return [void]
|
||||||
|
def authorize_party_edit!
|
||||||
|
if @party.user.present?
|
||||||
|
authorize_user_party
|
||||||
|
else
|
||||||
|
authorize_anonymous_party
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Authorizes an action for a party that belongs to a user.
|
||||||
|
#
|
||||||
|
# Renders an unauthorized response unless the current user is present and
|
||||||
|
# matches the party's user.
|
||||||
|
#
|
||||||
|
# @return [void]
|
||||||
|
def authorize_user_party
|
||||||
|
return if current_user.present? && @party.user == current_user
|
||||||
|
|
||||||
|
render_unauthorized_response
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Authorizes an action for an anonymous party using an edit key.
|
||||||
|
#
|
||||||
|
# Retrieves and normalizes the provided edit key and compares it with the party's edit key.
|
||||||
|
# Renders an unauthorized response unless the keys are valid.
|
||||||
|
#
|
||||||
|
# @return [void]
|
||||||
|
def authorize_anonymous_party
|
||||||
|
provided_edit_key = edit_key.to_s.strip.force_encoding('UTF-8')
|
||||||
|
party_edit_key = @party.edit_key.to_s.strip.force_encoding('UTF-8')
|
||||||
|
return if valid_edit_key?(provided_edit_key, party_edit_key)
|
||||||
|
|
||||||
|
render_unauthorized_response
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Validates that the provided edit key matches the party's edit key.
|
||||||
|
#
|
||||||
|
# @param provided_edit_key [String] the edit key provided in the request.
|
||||||
|
# @param party_edit_key [String] the edit key associated with the party.
|
||||||
|
# @return [Boolean] true if the edit keys match; false otherwise.
|
||||||
|
def valid_edit_key?(provided_edit_key, party_edit_key)
|
||||||
|
provided_edit_key.present? &&
|
||||||
|
provided_edit_key.bytesize == party_edit_key.bytesize &&
|
||||||
|
ActiveSupport::SecurityUtils.secure_compare(provided_edit_key, party_edit_key)
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Defines and permits the whitelisted parameters for a grid summon.
|
# Defines and permits the whitelisted parameters for a grid summon.
|
||||||
#
|
#
|
||||||
|
|
|
||||||
369
spec/requests/grid_summons_controller_spec.rb
Normal file
369
spec/requests/grid_summons_controller_spec.rb
Normal file
|
|
@ -0,0 +1,369 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
# This request spec tests the GridSummons API endpoints using modern RSpec techniques.
|
||||||
|
RSpec.describe 'GridSummons API', type: :request do
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
let(:party) { create(:party, user: user, edit_key: 'secret') }
|
||||||
|
let(:summon) { Summon.find_by(granblue_id: '2040433000') }
|
||||||
|
let(:access_token) do
|
||||||
|
Doorkeeper::AccessToken.create!(
|
||||||
|
resource_owner_id: user.id,
|
||||||
|
expires_in: 30.days,
|
||||||
|
scopes: 'public'
|
||||||
|
)
|
||||||
|
end
|
||||||
|
let(:headers) do
|
||||||
|
{
|
||||||
|
'Authorization' => "Bearer #{access_token.token}",
|
||||||
|
'Content-Type' => 'application/json'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
RSpec::Matchers.define :have_json_error_message do |expected_message|
|
||||||
|
match do |response|
|
||||||
|
JSON.parse(response.body)['error'].to_s.include?(expected_message)
|
||||||
|
end
|
||||||
|
|
||||||
|
failure_message do |response|
|
||||||
|
"expected error message to include '#{expected_message}', but got: #{JSON.parse(response.body)['error']}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST /api/v1/summons' do
|
||||||
|
let(:valid_params) do
|
||||||
|
{
|
||||||
|
summon: {
|
||||||
|
party_id: party.id,
|
||||||
|
summon_id: summon.id,
|
||||||
|
position: 0,
|
||||||
|
main: true,
|
||||||
|
friend: false,
|
||||||
|
quick_summon: false,
|
||||||
|
uncap_level: 3,
|
||||||
|
transcendence_step: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with valid parameters' do
|
||||||
|
it 'creates a grid summon and returns status created' do
|
||||||
|
expect do
|
||||||
|
post '/api/v1/summons', params: valid_params.to_json, headers: headers
|
||||||
|
end.to change(GridSummon, :count).by(1)
|
||||||
|
expect(response).to have_http_status(:created)
|
||||||
|
json_response = JSON.parse(response.body)
|
||||||
|
expect(json_response).to have_key('grid_summon')
|
||||||
|
expect(json_response['grid_summon']).to include('position' => 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with invalid parameters' do
|
||||||
|
# Revised: use a non-numeric uncap_level so the grid summon is built but fails validation.
|
||||||
|
let(:invalid_params) do
|
||||||
|
{
|
||||||
|
summon: {
|
||||||
|
party_id: party.id,
|
||||||
|
summon_id: summon.id,
|
||||||
|
position: 0,
|
||||||
|
main: true,
|
||||||
|
friend: false,
|
||||||
|
quick_summon: false,
|
||||||
|
uncap_level: 'invalid',
|
||||||
|
transcendence_step: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns unprocessable entity status with error details' do
|
||||||
|
post '/api/v1/summons', params: invalid_params.to_json, headers: headers
|
||||||
|
expect(response).to have_http_status(:unprocessable_entity)
|
||||||
|
json_response = JSON.parse(response.body)
|
||||||
|
expect(json_response).to have_key('errors')
|
||||||
|
expect(json_response['errors']).to include('uncap_level')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'PUT /api/v1/grid_summons/:id' do
|
||||||
|
before do
|
||||||
|
@grid_summon = create(:grid_summon,
|
||||||
|
party: party,
|
||||||
|
summon: summon,
|
||||||
|
position: 1,
|
||||||
|
uncap_level: 3,
|
||||||
|
transcendence_step: 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with valid parameters' do
|
||||||
|
let(:update_params) do
|
||||||
|
{
|
||||||
|
summon: {
|
||||||
|
id: @grid_summon.id,
|
||||||
|
party_id: party.id,
|
||||||
|
summon_id: summon.id,
|
||||||
|
position: 1,
|
||||||
|
main: true,
|
||||||
|
friend: false,
|
||||||
|
quick_summon: false,
|
||||||
|
uncap_level: 4,
|
||||||
|
transcendence_step: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates the grid summon and returns the updated record' do
|
||||||
|
put "/api/v1/grid_summons/#{@grid_summon.id}", params: update_params.to_json, headers: headers
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
json_response = JSON.parse(response.body)
|
||||||
|
expect(json_response).to have_key('grid_summon')
|
||||||
|
expect(json_response['grid_summon']).to include('uncap_level' => 4)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with invalid parameters' do
|
||||||
|
let(:invalid_update_params) do
|
||||||
|
{
|
||||||
|
summon: {
|
||||||
|
id: @grid_summon.id,
|
||||||
|
party_id: party.id,
|
||||||
|
summon_id: summon.id,
|
||||||
|
position: 1,
|
||||||
|
main: true,
|
||||||
|
friend: false,
|
||||||
|
quick_summon: false,
|
||||||
|
uncap_level: 'invalid',
|
||||||
|
transcendence_step: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns unprocessable entity status with error details' do
|
||||||
|
put "/api/v1/grid_summons/#{@grid_summon.id}", params: invalid_update_params.to_json, headers: headers
|
||||||
|
expect(response).to have_http_status(:unprocessable_entity)
|
||||||
|
json_response = JSON.parse(response.body)
|
||||||
|
expect(json_response).to have_key('errors')
|
||||||
|
expect(json_response['errors']).to include('uncap_level')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST /api/v1/summons/update_uncap' do
|
||||||
|
context 'when summon has flb true, ulb false, transcendence false (max uncap 4)' do
|
||||||
|
before do
|
||||||
|
@grid_summon = create(:grid_summon,
|
||||||
|
party: party,
|
||||||
|
summon: summon,
|
||||||
|
position: 2,
|
||||||
|
uncap_level: 3,
|
||||||
|
transcendence_step: 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:update_uncap_params) do
|
||||||
|
{
|
||||||
|
summon: {
|
||||||
|
id: @grid_summon.id,
|
||||||
|
party_id: party.id,
|
||||||
|
summon_id: summon.id,
|
||||||
|
uncap_level: 5, # attempt above allowed; should be capped at 4
|
||||||
|
transcendence_step: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
summon.update!(flb: true, ulb: false, transcendence: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'caps the uncap level at 4 for the summon' do
|
||||||
|
post '/api/v1/summons/update_uncap', params: update_uncap_params.to_json, headers: headers
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
json_response = JSON.parse(response.body)
|
||||||
|
expect(json_response).to have_key('grid_summon')
|
||||||
|
expect(json_response['grid_summon']).to include('uncap_level' => 4)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when summon has ulb true, transcendence false (max uncap 5)' do
|
||||||
|
before do
|
||||||
|
@grid_summon = create(:grid_summon,
|
||||||
|
party: party,
|
||||||
|
summon: summon,
|
||||||
|
position: 2,
|
||||||
|
uncap_level: 3,
|
||||||
|
transcendence_step: 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:update_uncap_params) do
|
||||||
|
{
|
||||||
|
summon: {
|
||||||
|
id: @grid_summon.id,
|
||||||
|
party_id: party.id,
|
||||||
|
summon_id: summon.id,
|
||||||
|
uncap_level: 6, # attempt above allowed; should be capped at 5
|
||||||
|
transcendence_step: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
summon.update!(flb: true, ulb: true, transcendence: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates the uncap level to 5' do
|
||||||
|
post '/api/v1/summons/update_uncap', params: update_uncap_params.to_json, headers: headers
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
json_response = JSON.parse(response.body)
|
||||||
|
expect(json_response).to have_key('grid_summon')
|
||||||
|
expect(json_response['grid_summon']).to include('uncap_level' => 5)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when summon can be transcended (max uncap 6)' do
|
||||||
|
before do
|
||||||
|
@grid_summon = create(:grid_summon,
|
||||||
|
party: party,
|
||||||
|
summon: summon,
|
||||||
|
position: 2,
|
||||||
|
uncap_level: 3,
|
||||||
|
transcendence_step: 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:update_uncap_params) do
|
||||||
|
{
|
||||||
|
summon: {
|
||||||
|
id: @grid_summon.id,
|
||||||
|
party_id: party.id,
|
||||||
|
summon_id: summon.id,
|
||||||
|
uncap_level: 7, # attempt above allowed; should be capped at 6
|
||||||
|
transcendence_step: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
summon.update!(flb: true, ulb: true, transcendence: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates the uncap level to 6' do
|
||||||
|
post '/api/v1/summons/update_uncap', params: update_uncap_params.to_json, headers: headers
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
json_response = JSON.parse(response.body)
|
||||||
|
expect(json_response).to have_key('grid_summon')
|
||||||
|
expect(json_response['grid_summon']).to include('uncap_level' => 6)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST /api/v1/summons/update_quick_summon' do
|
||||||
|
context 'when grid summon position is not in [4,5,6]' do
|
||||||
|
let!(:grid_summon) do
|
||||||
|
create(:grid_summon,
|
||||||
|
party: party,
|
||||||
|
summon: summon,
|
||||||
|
position: 2,
|
||||||
|
quick_summon: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:update_quick_params) do
|
||||||
|
{
|
||||||
|
summon: {
|
||||||
|
id: grid_summon.id,
|
||||||
|
party_id: party.id,
|
||||||
|
summon_id: summon.id,
|
||||||
|
quick_summon: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates the quick summon flag and returns the updated summons array' do
|
||||||
|
post '/api/v1/summons/update_quick_summon', params: update_quick_params.to_json, headers: headers
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
json_response = JSON.parse(response.body)
|
||||||
|
expect(json_response).to have_key('summons')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when grid summon position is in [4,5,6]' do
|
||||||
|
let!(:grid_summon) do
|
||||||
|
create(:grid_summon,
|
||||||
|
party: party,
|
||||||
|
summon: summon,
|
||||||
|
position: 4,
|
||||||
|
quick_summon: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:update_quick_params) do
|
||||||
|
{
|
||||||
|
summon: {
|
||||||
|
id: grid_summon.id,
|
||||||
|
party_id: party.id,
|
||||||
|
summon_id: summon.id,
|
||||||
|
quick_summon: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns no content when position is in [4,5,6]' do
|
||||||
|
post '/api/v1/summons/update_quick_summon', params: update_quick_params.to_json, headers: headers
|
||||||
|
expect(response).to have_http_status(:no_content)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'DELETE /api/v1/grid_summons/:id (destroy action)' do
|
||||||
|
context 'when the party is owned by a logged in user' do
|
||||||
|
let!(:grid_summon) do
|
||||||
|
create(:grid_summon,
|
||||||
|
party: party,
|
||||||
|
summon: summon,
|
||||||
|
position: 3,
|
||||||
|
uncap_level: 3,
|
||||||
|
transcendence_step: 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'destroys the grid summon and returns a success response' do
|
||||||
|
expect { delete "/api/v1/grid_summons/#{grid_summon.id}", headers: headers }
|
||||||
|
.to change(GridSummon, :count).by(-1)
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns not found when trying to delete a non-existent grid summon' do
|
||||||
|
delete '/api/v1/grid_summons/00000000-0000-0000-0000-000000000000', headers: headers
|
||||||
|
expect(response).to have_http_status(:not_found)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the party is anonymous (no user)' do
|
||||||
|
# For anonymous users, override the party and header edit key.
|
||||||
|
let(:headers) { super().merge('X-Edit-Key' => 'anonsecret') }
|
||||||
|
let(:party) { create(:party, user: nil, edit_key: 'anonsecret') }
|
||||||
|
let!(:grid_summon) do
|
||||||
|
create(:grid_summon,
|
||||||
|
party: party,
|
||||||
|
summon: summon,
|
||||||
|
position: 3,
|
||||||
|
uncap_level: 3,
|
||||||
|
transcendence_step: 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'allows anonymous user to destroy grid summon when current_user is nil' do
|
||||||
|
# To simulate an anonymous request, we remove the Authorization header.
|
||||||
|
anonymous_headers = headers.except('Authorization')
|
||||||
|
expect { delete "/api/v1/grid_summons/#{grid_summon.id}", headers: anonymous_headers }
|
||||||
|
.to change(GridSummon, :count).by(-1)
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prevents deletion when a logged in user attempts to delete an anonymous grid summon' do
|
||||||
|
# When a logged in user (with an access token) tries to delete a grid summon
|
||||||
|
# that belongs to an anonymous party, authorization should fail.
|
||||||
|
auth_headers = headers.except('X-Edit-Key')
|
||||||
|
expect { delete "/api/v1/grid_summons/#{grid_summon.id}", headers: auth_headers }
|
||||||
|
.not_to change(GridSummon, :count)
|
||||||
|
expect(response).to have_http_status(:unauthorized)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Reference in a new issue