Skip to content

Commit

Permalink
[Add]: set up flow to add lms to course (#41)
Browse files Browse the repository at this point in the history
* Add models for course_to_lms

* Implement creating association in course_to_lms

* Test for creating association in course_to_lms

* added space in schema for canvas data

* Replace the external_course_id from courses table to course_to_lmss table

* Take external_course_id into consideration

* test coverage badge update

* test coverage badge update 2

* code climate yml file updated

* code climate yml file updated 2

* badge fix to linux

* added codeclimate test reporter

* added gems

* simple cov version downgraded

* simplecov v17

* secret added

* secret added2

* secret added3

* secret added4

* initial changes to create user

* drafted

* validation email added

* chnages added: new+save, has many asso for extension

* Merge latest main into feature branch and resolve conflict

* Refactor the controller and add integer validation

* Fix potential issue in  lmss_controller

* Add validation check for lms

* Use validation helper

* Amend minor comments

---------

Co-authored-by: Evan Kandell <[email protected]>
Co-authored-by: Sepehr Behmanesh Fard <[email protected]>
  • Loading branch information
3 people authored Apr 28, 2024
1 parent 6b89523 commit cd1ed11
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 31 deletions.
69 changes: 53 additions & 16 deletions app/controllers/api/v1/lmss_controller.rb
Original file line number Diff line number Diff line change
@@ -1,30 +1,67 @@
module Api
module V1
class LmssController < BaseController
before_action :validate_name!, only: [:create]

def create
render :json => 'not yet implemented'.to_json, status: 501
end
include CanvasValidationHelper
before_action :validate_ids!, only: [:create]

def index
render :json => 'not yet implemented'.to_json, status: 501
render json: { message: 'not yet implemented'}, status: 501
end

def destroy
render :json => 'not yet implemented'.to_json, status: 501
render json: { message: 'not yet implemented'}, status: 501
end

##
# Validator definitions.
# TODO: this should be exported to its own (validator) class.
# TODO: this validation should also check the config file for the name of lms's.
#
def validate_name!
if params['name'].blank?
render :json => 'name parameter is required', status: 401
# POST /courses/:course_id/lmss
def create
course_id = params[:course_id]
lms_id = params[:lms_id]
external_course_id = params[:external_course_id]

# Ensure that the course and LMS exist
unless Course.exists?(course_id)
render json: { error: 'Course not found' }, status: :not_found
return
end
unless Lms.exists?(lms_id)
render json: { error: 'Lms not found' }, status: :not_found
return
end
# Ensure that the association does not already exist
existing_entry = CourseToLms.find_by(course_id: course_id, lms_id: lms_id, external_course_id: external_course_id)
if existing_entry
render json: { message: 'The association between the specified course and LMS already exists.' }, status: :ok
return
end
# Create the association
course_to_lms = CourseToLms.new(
course_id: course_id,
lms_id: lms_id,
external_course_id: external_course_id
)

if course_to_lms.save
render json: course_to_lms, status: :created
else
render json: course_to_lms.errors, status: :unprocessable_entity
end
end

private

def validate_ids!
begin
params.require([:course_id, :lms_id, :external_course_id])
rescue ActionController::ParameterMissing => e
render json: { error: e.message }, status: :bad_request
return
else
unless is_valid_course_id(params[:course_id].to_i) && is_valid_lms_id(params[:lms_id].to_i)
render json: { error: 'Invalid course_id or lms_id' }, status: :bad_request
return
end
end
end
end
end
end
end
9 changes: 9 additions & 0 deletions app/helpers/canvas_validation_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ def is_valid_lms_id(lmsId)
lmsId.is_a?(Integer) && lmsId > 0
end

##
# Checks if the provided lms id is valid.
#
# @param [Integer] lmsId the lms id to check.
# @return [Boolean] whether the provided id is valid.
def is_valid_lms_id(lmsId)
lmsId.is_a?(Integer) && lmsId > 0
end

##
# Checks if the provided assignment id is valid.
#
Expand Down
97 changes: 82 additions & 15 deletions spec/controllers/api/v1/lmss_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,93 @@
module Api
module V1
describe LmssController do
let(:mock_course_id) { 16 }
let(:mock_course_name) { 'testCourseName' }
describe 'create' do
it 'throws a 501 error' do
post :create, params: {
course_id: :mock_course_id,
name: :mock_course_name,
}
expect(response.status).to eq(501)
def json_response
JSON.parse(response.body)
end

before do
# Manually create a course and LMS in the database
@course = Course.create!(course_name: "Mock CS169 Course")
@lms = Lms.create!(lms_name: "Mock Canvas", use_auth_token: true)
@external_course_id = "mock_external_course_id"
end

after do
# Clean up the specifically created data
CourseToLms.delete_all
Course.delete_all
Lms.delete_all
end

describe 'POST #create' do

context 'when lms_id is missing' do
it 'returns status :bad_request' do
post :create, params: { course_id: @course.id, external_course_id: @external_course_id}
expect(response).to have_http_status(:bad_request)
expect(response.body).to include('param is missing or the value is empty: lms_id')
end
end

context 'when course_id and lms_id are not invalid' do
it 'returns status :bad_request' do
post :create, params: { course_id: '-1', lms_id: '-1', external_course_id: @external_course_id }
expect(response).to have_http_status(:bad_request)
expect(response.body).to include('Invalid course_id or lms_id')
end
end

context 'when valid parameters are provided' do
it 'creates a new course_to_lms association and returns status :created' do
post :create, params: { course_id: @course.id, lms_id: @lms.id, external_course_id: @external_course_id}
expect(response).to have_http_status(:created)
expect(json_response['course_id']).to eq(@course.id)
expect(json_response['lms_id']).to eq(@lms.id)
end
end
context 'when course_to_lms fails to save' do
it 'returns status :unprocessable_entity' do
allow_any_instance_of(CourseToLms).to receive(:save).and_return(false)
post :create, params: { course_id: @course.id, lms_id: @lms.id, external_course_id: @external_course_id}
expect(response).to have_http_status(:unprocessable_entity)
end
end

context 'when course does not exist' do
it 'returns status :not_found' do
# Ensure that the course does not exist
selected_course = Course.find_by(id: @course.id)
selected_course.destroy if selected_course
post :create, params: { course_id: @course.id, lms_id: @lms.id, external_course_id: @external_course_id}
expect(response).to have_http_status(:not_found)
expect(response.body).to include('Course not found')
end
end

it 'throws a 401 error if the name is not specified' do
post :create, params: {
course_id: :mock_course_id,
}
expect(response.status).to eq(401)
expect(response.body).to eq('name parameter is required')
context 'when lms does not exist' do
it 'returns status :not_found' do
# Ensure that the LMS does not exist
selected_lms = Lms.find_by(id: @lms.id)
selected_lms.destroy if selected_lms

post :create, params: { course_id: @course.id, lms_id: 1, external_course_id: @external_course_id}
expect(response).to have_http_status(:not_found)
expect(response.body).to include('Lms not found')
end
end

context 'when the association already exists' do
it 'returns status :ok' do
CourseToLms.create!(course_id: @course.id, lms_id: @lms.id, external_course_id: @external_course_id)
post :create, params: { course_id: @course.id, lms_id: @lms.id, external_course_id: @external_course_id}
expect(response).to have_http_status(:ok)
expect(response.body).to include('The association between the specified course and LMS already exists.')
end
end
end



describe 'index' do
it 'throws a 501 error' do
get :index, params: { course_id: :mock_course_id }
Expand Down

0 comments on commit cd1ed11

Please sign in to comment.