From 0147e1aee1f8d526af3fc837a81618f8bc9ec4eb Mon Sep 17 00:00:00 2001 From: Oleksii Kriuchykhin Date: Wed, 16 Sep 2020 23:15:24 +0200 Subject: [PATCH] Add Create and Update endpoints for experiments [SCI-4999] --- .../api/v1/experiments_controller.rb | 42 +++++ config/routes.rb | 2 +- .../api/v1/experiments_controller_spec.rb | 147 ++++++++++++++++++ 3 files changed, 190 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/v1/experiments_controller.rb b/app/controllers/api/v1/experiments_controller.rb index f2b6aa824..761eff5e9 100644 --- a/app/controllers/api/v1/experiments_controller.rb +++ b/app/controllers/api/v1/experiments_controller.rb @@ -8,6 +8,7 @@ module Api before_action only: :show do load_experiment(:id) end + before_action :load_experiment_for_managing, only: %i(update) def index experiments = @project.experiments @@ -19,6 +20,47 @@ module Api def show render jsonapi: @experiment, serializer: ExperimentSerializer end + + def create + raise PermissionError.new(Experiment, :create) unless can_create_experiments?(@project) + + experiment = @project.experiments.create!(experiment_params.merge!(created_by: current_user, + last_modified_by: current_user)) + + render jsonapi: experiment, serializer: ExperimentSerializer, status: :created + end + + def update + @experiment.assign_attributes(experiment_params) + + return render body: nil, status: :no_content unless @experiment.changed? + + if @experiment.archived_changed? + if @experiment.archived? + @experiment.archived_by = current_user + @experiment.archived_on = DateTime.now + else + @experiment.restored_by = current_user + @experiment.restored_on = DateTime.now + end + end + @experiment.last_modified_by = current_user + @experiment.save! + render jsonapi: @experiment, serializer: ExperimentSerializer, status: :ok + end + + private + + def experiment_params + raise TypeError unless params.require(:data).require(:type) == 'experiments' + + params.require(:data).require(:attributes).permit(:name, :description, :archived) + end + + def load_experiment_for_managing + @experiment = @project.experiments.find(params.require(:id)) + raise PermissionError.new(Experiment, :manage) unless can_manage_experiment?(@experiment) + end end end end diff --git a/config/routes.rb b/config/routes.rb index 8e603000e..2977f1a5a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -704,7 +704,7 @@ Rails.application.routes.draw do get 'activities', to: 'projects#activities' resources :reports, only: %i(index show), path: 'reports', as: :reports - resources :experiments, only: %i(index show) do + resources :experiments, only: %i(index show create update) do resources :task_groups, only: %i(index show) resources :connections, only: %i(index show) resources :tasks, only: %i(index show create update) do diff --git a/spec/requests/api/v1/experiments_controller_spec.rb b/spec/requests/api/v1/experiments_controller_spec.rb index ad3cbc792..b9a88fa14 100644 --- a/spec/requests/api/v1/experiments_controller_spec.rb +++ b/spec/requests/api/v1/experiments_controller_spec.rb @@ -11,6 +11,8 @@ RSpec.describe "Api::V1::ExperimentsController", type: :request do @valid_project = create(:project, name: Faker::Name.unique.name, created_by: @user, team: @teams.first) + create(:user_project, :owner, user: @user, project: @valid_project) + @unaccessible_project = create(:project, name: Faker::Name.unique.name, created_by: @user, team: @teams.second) @@ -126,4 +128,149 @@ RSpec.describe "Api::V1::ExperimentsController", type: :request do expect(hash_body['errors'][0]).to include('status': 404) end end + + describe 'POST experiment, #create' do + before :all do + @valid_headers['Content-Type'] = 'application/json' + end + + let(:action) do + post( + api_v1_team_project_experiments_path( + team_id: @valid_project.team.id, + project_id: @valid_project + ), + params: request_body.to_json, + headers: @valid_headers + ) + end + + context 'when has valid params' do + let(:request_body) do + { + data: { + type: 'experiments', + attributes: { + name: 'Experiment name', + description: 'Experiment description' + } + } + } + end + + it 'creates new experiment' do + expect { action }.to change { Experiment.count }.by(1) + end + + it 'returns status 201' do + action + + expect(response).to have_http_status 201 + end + + it 'returns well formated response' do + action + + expect(json).to match( + hash_including( + data: hash_including( + type: 'experiments', + attributes: hash_including(name: 'Experiment name', description: 'Experiment description') + ) + ) + ) + end + end + + context 'when has missing param' do + let(:request_body) do + { + data: { + type: 'experiments', + attributes: { + } + } + } + end + + it 'renders 400' do + action + + expect(response).to have_http_status(400) + end + end + end + + describe 'PATCH experiment, #update' do + before :all do + @valid_headers['Content-Type'] = 'application/json' + @experiment = @valid_project.experiments.first + end + + let(:action) do + patch( + api_v1_team_project_experiment_path( + team_id: @valid_project.team.id, + project_id: @valid_project.id, + id: @experiment.id + ), + params: request_body.to_json, + headers: @valid_headers + ) + end + + context 'when has valid params' do + let(:request_body) do + { + data: { + type: 'experiments', + attributes: { + name: 'New experiment name', + description: 'New experiment description', + archived: true + } + } + } + end + + it 'returns status 200' do + action + + expect(response).to have_http_status 200 + end + + it 'returns well formated response' do + action + + expect(json).to match( + hash_including( + data: hash_including( + type: 'experiments', + attributes: hash_including( + name: 'New experiment name', description: 'New experiment description', archived: true + ) + ) + ) + ) + end + end + + context 'when has missing param' do + let(:request_body) do + { + data: { + type: 'experiments', + attributes: { + } + } + } + end + + it 'renders 400' do + action + + expect(response).to have_http_status(400) + end + end + end end