From 0a3a619c42c05b042da03a9e10d61fbe78c17d6f Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Tue, 19 Mar 2024 08:39:19 -0400 Subject: [PATCH] FI-2495: Create sessions via form POST (#459) * add controller for creating test sessions via form post * add spec for creating sessions via form post * add specs for for unhappy paths * remove old constant --- .../test_session_form_post_controller.rb | 39 ++++++++ lib/inferno/apps/web/router.rb | 2 + spec/requests/test_sessions_form_post_spec.rb | 93 +++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 lib/inferno/apps/web/controllers/test_session_form_post_controller.rb create mode 100644 spec/requests/test_sessions_form_post_spec.rb diff --git a/lib/inferno/apps/web/controllers/test_session_form_post_controller.rb b/lib/inferno/apps/web/controllers/test_session_form_post_controller.rb new file mode 100644 index 000000000..6af96e579 --- /dev/null +++ b/lib/inferno/apps/web/controllers/test_session_form_post_controller.rb @@ -0,0 +1,39 @@ +module Inferno + module Web + module Controllers + class TestSessionFormPostController < Hanami::Action + def self.call(...) + new.call(...) + end + + def handle(req, res) + test_suite_id = req.params[:test_suite_id] + + test_suite = Inferno::Repositories::TestSuites.new.find(test_suite_id) + halt 404, "Unable to find test suite with id #{test_suite_id}" if test_suite.nil? + + params = { test_suite_id: } + suite_option_keys = test_suite.suite_options.map(&:id) + options = req.params.to_h.slice(*suite_option_keys) + + params[:suite_options] = options.map { |key, value| { id: key, value: } } if options.present? + + repo = Inferno::Repositories::TestSessions.new + session = repo.create(params) + + preset_id = req.params[:preset_id] + + if preset_id.present? + preset = Inferno::Repositories::Presets.new.find(preset_id) + + halt 422, "Unable to find preset with id #{preset_id} for test suite #{test_suite_id}" if preset.nil? + + repo.apply_preset(session, preset_id) + end + + res.redirect_to "#{Inferno::Application['base_url']}/#{test_suite_id}/#{session.id}" + end + end + end + end +end diff --git a/lib/inferno/apps/web/router.rb b/lib/inferno/apps/web/router.rb index a954c6fc4..5cf28217f 100644 --- a/lib/inferno/apps/web/router.rb +++ b/lib/inferno/apps/web/router.rb @@ -72,6 +72,8 @@ module Web get '/test_sessions/:id', to: Inferno::Web::Controllers::TestSessions::ClientShow, as: :client_session_show get '/:test_suite_id/:id', to: Inferno::Web::Controllers::TestSessions::ClientShow, as: :client_suite_session_show + + post '/:test_suite_id', to: Inferno::Web::Controllers::TestSessionFormPostController, as: :session_form_post end Router = # rubocop:disable Naming/ConstantName diff --git a/spec/requests/test_sessions_form_post_spec.rb b/spec/requests/test_sessions_form_post_spec.rb new file mode 100644 index 000000000..dd1f5be3a --- /dev/null +++ b/spec/requests/test_sessions_form_post_spec.rb @@ -0,0 +1,93 @@ +require 'request_helper' +require_relative '../../lib/inferno/apps/web/router' +require_relative '../../lib/inferno/apps/web/controllers/test_session_form_post_controller' + +RSpec.describe 'POST /:test_suite_id' do + let(:router) { Inferno::Web::Router } + let(:repo) { Inferno::Repositories::TestSessions.new } + + context 'with valid params' do + let(:test_suite_id) { 'options' } + + it 'redirects the user to the created test session' do + post router.path(:session_form_post, test_suite_id:) + + expect(last_response.status).to eq(302) + + location = last_response.headers['Location'] + expect(location).to match(%r{\A#{Inferno::Application['base_url']}/#{test_suite_id}/[\d\w]+\z}) + end + + it 'applies supplied options' do + options = + { + ig_version: '1', + other_option: '2' + } + + post( + router.path(:session_form_post, test_suite_id:), + URI.encode_www_form(options), + 'Content-Type' => 'application/x-www-form-urlencoded' + ) + + expect(last_response.status).to eq(302) + + location = last_response.headers['Location'] + + session_id = location.split('/').last + session = repo.find(session_id) + + expect(session).to be_present + + options.each do |key, value| + option = session.suite_options.find { |suite_option| suite_option.id == key } + expect(option.value).to eq(value) + end + end + + it 'applies supplied preset' do + preset_id = 'demo_preset' + + post( + router.path(:session_form_post, test_suite_id: 'demo'), + URI.encode_www_form(preset_id:), + 'Content-Type' => 'application/x-www-form-urlencoded' + ) + + expect(last_response.status).to eq(302) + + location = last_response.headers['Location'] + + session_id = location.split('/').last + session = repo.find(session_id) + + expect(session).to be_present + + session_data_repo = Inferno::Repositories::SessionData.new + + expect(session_data_repo.load(test_session_id: session.id, name: 'patient_id')).to eq('85') + expect(session_data_repo.load(test_session_id: session.id, name: 'bearer_token')).to eq('SAMPLE_TOKEN') + end + end + + context 'with invalid params' do + it 'returns a 404 when the suite can not be found' do + post router.path(:session_form_post, test_suite_id: 'bad_suite_id') + + expect(last_response.status).to eq(404) + end + + it 'returns a 422 when the preset can not be found' do + preset_id = 'bad_preset_id' + + post( + router.path(:session_form_post, test_suite_id: 'demo'), + URI.encode_www_form(preset_id:), + 'Content-Type' => 'application/x-www-form-urlencoded' + ) + + expect(last_response.status).to eq(422) + end + end +end