diff --git a/.gitignore b/.gitignore index 3f826b56..091c325f 100644 --- a/.gitignore +++ b/.gitignore @@ -84,3 +84,4 @@ node_modules/ /playwright-report/ /blob-report/ /playwright/.cache/ +/e2e/temp/ diff --git a/app/controllers/api/v1/points_controller.rb b/app/controllers/api/v1/points_controller.rb index b2618c6d..08f7097c 100644 --- a/app/controllers/api/v1/points_controller.rb +++ b/app/controllers/api/v1/points_controller.rb @@ -48,10 +48,7 @@ class Api::V1::PointsController < ApiController def bulk_destroy point_ids = bulk_destroy_params[:point_ids] - if point_ids.blank? - render json: { error: 'No points selected' }, status: :unprocessable_entity - return - end + render json: { error: 'No points selected' }, status: :unprocessable_entity and return if point_ids.blank? deleted_count = current_api_user.points.where(id: point_ids).destroy_all.count diff --git a/e2e/temp/.auth/user.json b/e2e/temp/.auth/user.json deleted file mode 100644 index 339bb50e..00000000 --- a/e2e/temp/.auth/user.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "cookies": [ - { - "name": "_dawarich_session", - "value": "nE8XtV%2FHfX8CsqZBe1QAQhkkPEZ7qf9kmdmWoGK54d5wo0Nddlnwr4FyCeNcZ2yTRCJl318iWzJgfPxDNVXvkMCRloueKh45K8jAmER08h6t6Z6zXPlIq93OomMeSxcpudmD7rVBVuXgPHYnBKr2LBS6624Iz20BtXQVnF63EabM6bpBufCoWzlD7uRjzy20bN%2BdYCofavYkgHaZQc9IX%2FmN%2BrJEH88%2BcSCukNRHl1b8VhSNIfYTYoqwaXV1DjPnNdfFhBXcytyUuH9BqkkEZQTYzBXWZijAnmtJpcBTzXTCl6q3wdBDBlQ9OKkzurG1ykIH9tCVwMTHv695GxGUbiDTI86AudDwU7HSQnQzJK5gDNbCK%2Fxrc8ngdgDrGJkL23AJK9Ue7uzG--FQMhYrNeTDFIPVKV--WFIyRKwPplKvoujIn1omBA%3D%3D", - "domain": "localhost", - "path": "/", - "expires": -1, - "httpOnly": true, - "secure": false, - "sameSite": "Lax" - } - ], - "origins": [ - { - "origin": "http://localhost:3000", - "localStorage": [ - { - "name": "dawarich_onboarding_shown", - "value": "true" - }, - { - "name": "mapRouteMode", - "value": "routes" - } - ] - } - ] -} \ No newline at end of file diff --git a/spec/requests/api/v1/points_spec.rb b/spec/requests/api/v1/points_spec.rb index 50d3397e..4880daab 100644 --- a/spec/requests/api/v1/points_spec.rb +++ b/spec/requests/api/v1/points_spec.rb @@ -198,4 +198,113 @@ RSpec.describe 'Api::V1::Points', type: :request do end end end + + describe 'DELETE /bulk_destroy' do + let(:point_ids) { points.first(5).map(&:id) } + + it 'returns a successful response' do + delete "/api/v1/points/bulk_destroy?api_key=#{user.api_key}", + params: { point_ids: } + + expect(response).to have_http_status(:ok) + end + + it 'deletes multiple points' do + expect do + delete "/api/v1/points/bulk_destroy?api_key=#{user.api_key}", + params: { point_ids: } + end.to change { user.points.count }.by(-5) + end + + it 'returns the count of deleted points' do + delete "/api/v1/points/bulk_destroy?api_key=#{user.api_key}", + params: { point_ids: } + + json_response = JSON.parse(response.body) + + expect(json_response['message']).to eq('Points were successfully destroyed') + expect(json_response['count']).to eq(5) + end + + it 'only deletes points belonging to the current user' do + other_user = create(:user) + other_points = create_list(:point, 3, user: other_user) + all_point_ids = point_ids + other_points.map(&:id) + + expect do + delete "/api/v1/points/bulk_destroy?api_key=#{user.api_key}", + params: { point_ids: all_point_ids } + end.to change { user.points.count }.by(-5) + .and change { other_user.points.count }.by(0) + end + + context 'when no point_ids are provided' do + it 'returns success with zero count' do + delete "/api/v1/points/bulk_destroy?api_key=#{user.api_key}", + params: { point_ids: [] } + + expect(response).to have_http_status(:ok) + + json_response = JSON.parse(response.body) + expect(json_response['count']).to eq(0) + end + end + + context 'when point_ids parameter is missing' do + it 'returns an error' do + delete "/api/v1/points/bulk_destroy?api_key=#{user.api_key}" + + expect(response).to have_http_status(:unprocessable_entity) + + json_response = JSON.parse(response.body) + expect(json_response['error']).to eq('No points selected') + end + end + + context 'when user is inactive' do + before do + user.update(status: :inactive, active_until: 1.day.ago) + end + + it 'returns an unauthorized response' do + delete "/api/v1/points/bulk_destroy?api_key=#{user.api_key}", + params: { point_ids: } + + expect(response).to have_http_status(:unauthorized) + end + + it 'does not delete any points' do + expect do + delete "/api/v1/points/bulk_destroy?api_key=#{user.api_key}", + params: { point_ids: } + end.not_to(change { user.points.count }) + end + end + + context 'when deleting all user points' do + it 'successfully deletes all points' do + all_point_ids = points.map(&:id) + + expect do + delete "/api/v1/points/bulk_destroy?api_key=#{user.api_key}", + params: { point_ids: all_point_ids } + end.to change { user.points.count }.from(15).to(0) + end + end + + context 'when some point_ids do not exist' do + it 'deletes only existing points' do + non_existent_ids = [999_999, 888_888] + mixed_ids = point_ids + non_existent_ids + + expect do + delete "/api/v1/points/bulk_destroy?api_key=#{user.api_key}", + params: { point_ids: mixed_ids } + end.to change { user.points.count }.by(-5) + + json_response = JSON.parse(response.body) + expect(json_response['count']).to eq(5) + end + end + end end diff --git a/tmp/storage/.keep b/tmp/storage/.keep new file mode 100644 index 00000000..e69de29b