From 0e047d2dfa6d0fe7fa1634aea88d61bd7bf52b6b Mon Sep 17 00:00:00 2001
From: Colby Endres <70925616+colbyendres@users.noreply.github.com>
Date: Wed, 23 Oct 2024 18:20:25 -0500
Subject: [PATCH] Migrate home page and CSV parsing logic (#32)
* Migrate homepage to schedule index
* Fixed RSpec failures
* Migrate CSV logic to separate service
* Update Cucumber scenarios
* Change class name to satisfy autoloader
* Remove unused require
---
app/controllers/csv_controller.rb | 41 --------
app/controllers/schedules_controller.rb | 98 +++----------------
app/controllers/welcome_controller.rb | 4 +-
app/services/csv_handler.rb | 89 +++++++++++++++++
app/views/schedules/show.html.erb | 2 +-
app/views/users/show.html.erb | 23 -----
config/routes.rb | 5 +-
features/csv_upload.feature | 26 -----
features/schedules.feature | 20 +++-
features/step_definitions/csv_upload_steps.rb | 19 ----
features/step_definitions/schedules_steps.rb | 16 +++
features/step_definitions/welcome.rb | 2 +-
features/welcome.feature | 5 +-
.../application_controller_spec.rb | 1 -
spec/controllers/csv_controller_spec.rb | 37 -------
spec/controllers/schedules_controller_spec.rb | 5 +-
spec/controllers/welcome_controller_spec.rb | 7 +-
.../instructors_missing_headers.csv | 5 +
spec/services/csv_handler_spec.rb | 72 ++++++++++++++
19 files changed, 225 insertions(+), 252 deletions(-)
delete mode 100644 app/controllers/csv_controller.rb
create mode 100644 app/services/csv_handler.rb
delete mode 100644 app/views/users/show.html.erb
delete mode 100644 features/csv_upload.feature
delete mode 100644 features/step_definitions/csv_upload_steps.rb
delete mode 100644 spec/controllers/csv_controller_spec.rb
create mode 100644 spec/fixtures/instructors/instructors_missing_headers.csv
create mode 100644 spec/services/csv_handler_spec.rb
diff --git a/app/controllers/csv_controller.rb b/app/controllers/csv_controller.rb
deleted file mode 100644
index 73b3e6d..0000000
--- a/app/controllers/csv_controller.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-# app/controllers/csv_controller.rb
-class CsvController < ApplicationController
- require 'csv'
-
- def upload
- if csv_file_present?
- process_csv_file
- else
- flash[:error] = 'Please upload a CSV file.'
- end
- redirect_to user_path(@current_user)
- end
-
- private
-
- def csv_file_present?
- params[:csv_file].present?
- end
-
- def process_csv_file
- file = params[:csv_file].path
- parse_and_handle_csv(file)
- end
-
- def parse_and_handle_csv(file)
- parse_csv(file)
- flash[:notice] = 'CSV file uploaded successfully.'
- rescue CSV::MalformedCSVError => e
- flash[:error] = "Cannot parse CSV file: #{e.message}"
- end
-
- def parse_csv(file)
- csv = CSV.read(file, headers: true)
- Rails.logger.debug { "CSV Headers: #{csv.headers}" }
- csv.each do |row|
- Rails.logger.debug row.to_hash
- end
- end
-end
diff --git a/app/controllers/schedules_controller.rb b/app/controllers/schedules_controller.rb
index 78dcde8..d6dfce7 100644
--- a/app/controllers/schedules_controller.rb
+++ b/app/controllers/schedules_controller.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require 'csv'
-
# app/controllers/schedules_controller.rb
class SchedulesController < ApplicationController
before_action :set_schedule, only: %i[show destroy upload_rooms upload_instructors]
@@ -46,96 +44,28 @@ def destroy
def upload_rooms
if params[:room_file].present?
- begin
- ActiveRecord::Base.transaction do
- room_data = CSV.read(params[:room_file].path, headers: true)
-
- @schedule.rooms.destroy_all
-
- room_data.each do |row|
- Room.create!(
- schedule_id: @schedule.id,
- campus: row['campus'],
- building_code: row['building_code'],
- room_number: row['room_number'],
- capacity: row['capacity'],
- is_lecture_hall: row['is_lecture_hall'] == 'True',
- is_learning_studio: row['is_learning_studio'] == 'True',
- is_lab: row['is_lab'] == 'True',
- is_active: row['is_active'] == 'True',
- comments: row['comments']
- )
- end
- end
- flash[:notice] = 'Rooms successfully uploaded.'
- rescue StandardError => e
- flash[:alert] = "There was an error uploading the CSV file: #{e.message}"
- raise e
- end
+ # FIXME: What if the input file is malformed?
+ # We've erased our past data with no way to restore it
+ # We probably need to create a back up and restore if parsing gives an alert
+ @schedule.rooms.destroy_all
+ csv_handler = CsvHandler.new
+ csv_handler.upload(params[:room_file])
+ flash_result = csv_handler.parse_room_csv(@schedule.id)
+ flash[flash_result.keys.first] = flash_result.values.first
else
flash[:alert] = 'Please upload a CSV file.'
end
-
redirect_to schedule_path(@schedule)
end
def upload_instructors
if params[:instructor_file].present?
- begin
- ActiveRecord::Base.transaction do
- instructor_data = CSV.read(params[:instructor_file].path)
-
- @schedule.instructors.destroy_all
- actual_headers = instructor_data[1]
-
- required_headers = [
- 'anonimized ID',
- 'First Name',
- 'Last Name',
- 'Email',
- 'Teaching before 9:00 am.',
- 'Teaching after 3:00 pm.',
- 'Middle Name',
- 'Is there anything else we should be aware of regarding your teaching load (special course reduction, ...)' # Optional: Include if needed
- ]
-
- missing_headers = required_headers - actual_headers
- unless missing_headers.empty?
- flash[:alert] = "Missing required headers: #{missing_headers.join(', ')}"
- redirect_to schedule_path(@schedule) and return
- end
-
- instructor_data[2..].each do |row|
- # Extracting values and checking for nulls
- id_number = row[actual_headers.index('anonimized ID')]
- first_name = row[actual_headers.index('First Name')]
- last_name = row[actual_headers.index('Last Name')]
- middle_name = row[actual_headers.index('Middle Name')]
- email = row[actual_headers.index('Email')]
- before_9 = row[actual_headers.index('Teaching before 9:00 am.')]
- after_3 = row[actual_headers.index('Teaching after 3:00 pm.')]
- beaware_of = row[actual_headers.index('Is there anything else we should be aware of regarding your teaching load (special course reduction, ...)')]
-
- instructor_data = {
- schedule_id: @schedule.id,
- id_number: id_number,
- first_name: first_name,
- last_name: last_name,
- middle_name: middle_name,
- email: email,
- before_9: before_9,
- after_3: after_3,
- beaware_of: beaware_of
- }
-
- Instructor.create(instructor_data)
- end
- end
- flash[:notice] = 'Instructors successfully uploaded.'
- rescue StandardError => e
- flash[:alert] = "There was an error uploading the CSV file: #{e.message}"
- raise e
- end
+ # FIXME: See concern in upload_rooms
+ @schedule.instructors.destroy_all
+ csv_handler = CsvHandler.new
+ csv_handler.upload(params[:instructor_file])
+ flash_result = csv_handler.parse_instructor_csv(@schedule.id)
+ flash[flash_result.keys.first] = flash_result.values.first
else
flash[:alert] = 'Please upload a CSV file.'
end
diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb
index 9f7ffcf..7e1beda 100644
--- a/app/controllers/welcome_controller.rb
+++ b/app/controllers/welcome_controller.rb
@@ -9,8 +9,6 @@ class WelcomeController < ApplicationController
def index
return unless logged_in?
-
- flash[:notice] = "Welcome back, #{@current_user.first_name}!" unless flash[:notice] || flash[:error]
- redirect_to user_path(@current_user)
+ redirect_to schedules_path
end
end
diff --git a/app/services/csv_handler.rb b/app/services/csv_handler.rb
new file mode 100644
index 0000000..a1f1cd2
--- /dev/null
+++ b/app/services/csv_handler.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+class CsvHandler
+ require 'csv'
+
+ def upload(file)
+ @file = file
+ end
+
+ def parse_room_csv(schedule_id)
+ begin
+ ActiveRecord::Base.transaction do
+ room_data = CSV.parse(@file.read, headers: true)
+ room_data.each do |row|
+ Room.create!(
+ schedule_id: schedule_id,
+ campus: row['campus'],
+ building_code: row['building_code'],
+ room_number: row['room_number'],
+ capacity: row['capacity'].to_i,
+ is_lecture_hall: row['is_lecture_hall'] == 'True',
+ is_learning_studio: row['is_learning_studio'] == 'True',
+ is_lab: row['is_lab'] == 'True',
+ is_active: row['is_active'] == 'True',
+ comments: row['comments']
+ )
+ end
+ end
+ # Flash data to be received by controller
+ return { notice: 'Rooms successfully uploaded.' }
+ rescue StandardError => e
+ return { alert: "There was an error uploading the CSV file: #{e.message}" }
+ end
+ end
+
+ def parse_instructor_csv(schedule_id)
+ begin
+ ActiveRecord::Base.transaction do
+ instructor_data = CSV.parse(@file.read)
+ actual_headers = instructor_data[1]
+ required_headers = [
+ 'anonimized ID',
+ 'First Name',
+ 'Last Name',
+ 'Email',
+ 'Teaching before 9:00 am.',
+ 'Teaching after 3:00 pm.',
+ 'Middle Name',
+ 'Is there anything else we should be aware of regarding your teaching load (special course reduction, ...)' # Optional: Include if needed
+ ]
+
+ missing_headers = required_headers - actual_headers
+ unless missing_headers.empty?
+ return {alert: "Missing required headers: #{missing_headers.join(', ')}"}
+ end
+
+ instructor_data[2..].each do |row|
+ # Extracting values and checking for nulls
+ id_number = row[actual_headers.index('anonimized ID')]
+ first_name = row[actual_headers.index('First Name')]
+ last_name = row[actual_headers.index('Last Name')]
+ middle_name = row[actual_headers.index('Middle Name')]
+ email = row[actual_headers.index('Email')]
+ before_9 = row[actual_headers.index('Teaching before 9:00 am.')]
+ after_3 = row[actual_headers.index('Teaching after 3:00 pm.')]
+ beaware_of = row[actual_headers.index('Is there anything else we should be aware of regarding your teaching load (special course reduction, ...)')]
+
+ instructor_data = {
+ schedule_id: schedule_id,
+ id_number: id_number,
+ first_name: first_name,
+ last_name: last_name,
+ middle_name: middle_name,
+ email: email,
+ before_9: before_9,
+ after_3: after_3,
+ beaware_of: beaware_of
+ }
+
+ Instructor.create(instructor_data)
+ end
+ end
+ return {notice: 'Instructors successfully uploaded.'}
+ rescue StandardError => e
+ return {alert: "There was an error uploading the CSV file: #{e.message}"}
+ end
+ end
+
+end
diff --git a/app/views/schedules/show.html.erb b/app/views/schedules/show.html.erb
index b526559..34e83be 100644
--- a/app/views/schedules/show.html.erb
+++ b/app/views/schedules/show.html.erb
@@ -16,7 +16,7 @@ Semester:<%= @schedule.semester_name %>
<%= form_with url: upload_instructors_schedule_path(@schedule), multipart: true, method: :post, local: true do |f| %>
- <%= f.label :instructor_file, "Select Instructors Data (CSV)", class: "form-label fw-bold" %>
+ <%= f.label :instructor_file, "Select Instructor Data (CSV)", class: "form-label fw-bold" %>
<%= f.file_field :instructor_file, class: "form-control" %>
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb
deleted file mode 100644
index b36bf8a..0000000
--- a/app/views/users/show.html.erb
+++ /dev/null
@@ -1,23 +0,0 @@
-
Howdy <%= @current_user.first_name %>!
-
-
- Email:
- <%= @current_user.email %>
-
-
-
- First Name:
- <%= @current_user.first_name %>
-
-
-
- Last Name:
- <%= @current_user.last_name %>
-
-
-
Upload CSV File
- <%= form_with url: upload_csv_path, method: :post, local: true, data: { turbo: false } do |form| %>
- <%= form.file_field :csv_file %>
- <%= form.submit "Submit" %>
- <% end %>
-
diff --git a/config/routes.rb b/config/routes.rb
index 7067725..9c6bf50 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -17,11 +17,8 @@
get 'manifest' => 'rails/pwa#manifest', as: :pwa_manifest
# Defines the root path route ("/")
- root 'welcome#index'
get 'welcome/index', to: 'welcome#index', as: 'welcome'
-
- # Show user
- get '/users/:id', to: 'users#show', as: 'user'
+ root 'welcome#index'
# Login/logout
get '/logout', to: 'sessions#logout', as: 'logout'
diff --git a/features/csv_upload.feature b/features/csv_upload.feature
deleted file mode 100644
index 446d15c..0000000
--- a/features/csv_upload.feature
+++ /dev/null
@@ -1,26 +0,0 @@
-# features/csv_upload.feature
-Feature: CSV Upload
- As a user
- I want to upload a CSV file
- So that I can process data from the file
-
- Background:
- Given I am logged in as a user
-
- Scenario: Successfully upload a valid CSV file
- Given I am on my profile page
- When I attach a valid CSV file to the upload form
- And I click the "Submit" button
- Then I should see "CSV file uploaded successfully."
-
- Scenario: Upload an invalid CSV file
- Given I am on my profile page
- When I attach an invalid CSV file to the upload form
- And I click the "Submit" button
- Then I should see "Cannot parse CSV file"
-
- Scenario: Upload without selecting a file
- Given I am on my profile page
- When I do not attach any file to the upload form
- And I click the "Submit" button
- Then I should see "Please upload a CSV file."
\ No newline at end of file
diff --git a/features/schedules.feature b/features/schedules.feature
index 77cc153..b4b9e39 100644
--- a/features/schedules.feature
+++ b/features/schedules.feature
@@ -37,4 +37,22 @@ Feature: Schedules page
When I visit the schedules index page
When I search for "ABCD"
Then I should not see "Test Schedule 1"
- And I should not see "Another Schedule"
\ No newline at end of file
+ And I should not see "Another Schedule"
+
+ Scenario: User can upload room CSV
+ Given I am logged in as a user with first name "Test"
+ When I visit the schedules index page
+ And I click on the card for "Test Schedule 1"
+ Then I should see "Select Room Data (CSV)"
+ When I upload a valid room file
+ And I click the "Upload Room Data" button
+ Then I should see "Rooms successfully uploaded"
+
+ Scenario: User can upload instructor CSV
+ Given I am logged in as a user with first name "Test"
+ When I visit the schedules index page
+ And I click on the card for "Test Schedule 1"
+ Then I should see "Select Instructor Data (CSV)"
+ When I upload a valid instructor file
+ And I click the "Upload Instructor Data" button
+ Then I should see "Instructors successfully uploaded"
\ No newline at end of file
diff --git a/features/step_definitions/csv_upload_steps.rb b/features/step_definitions/csv_upload_steps.rb
deleted file mode 100644
index 3952f82..0000000
--- a/features/step_definitions/csv_upload_steps.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-# features/step_definitions/csv_upload_steps.rb
-
-Given('I am on my profile page') do
- visit user_path(User.first)
-end
-
-When('I attach a valid CSV file to the upload form') do
- attach_file('csv_file', Rails.root.join('spec/fixtures/files/test.csv'))
-end
-
-When('I attach an invalid CSV file to the upload form') do
- attach_file('csv_file', Rails.root.join('spec/fixtures/files/invalid.csv'))
-end
-
-When('I do not attach any file to the upload form') do
- # No file attached
-end
diff --git a/features/step_definitions/schedules_steps.rb b/features/step_definitions/schedules_steps.rb
index f974aeb..1bc5066 100644
--- a/features/step_definitions/schedules_steps.rb
+++ b/features/step_definitions/schedules_steps.rb
@@ -38,3 +38,19 @@
fill_in 'search_by_name', with: search_term
click_button 'Search'
end
+
+When('I upload a valid instructor file') do
+ valid_instructor_csv = File.read(Rails.root.join('spec', 'fixtures', 'instructors', 'instructors_valid.csv'))
+ @instructor_file = Tempfile.new(['instructors_valid', '.csv'])
+ @instructor_file.write(valid_instructor_csv)
+ @instructor_file.rewind
+ attach_file('Select Instructor Data (CSV)', @instructor_file.path)
+end
+
+When('I upload a valid room file') do
+ valid_room_csv = File.read(Rails.root.join('spec', 'fixtures', 'rooms', 'rooms_valid.csv'))
+ @room_file = Tempfile.new(['rooms_valid', '.csv'])
+ @room_file.write(valid_room_csv)
+ @room_file.rewind
+ attach_file('Select Room Data (CSV)', @room_file.path)
+end
diff --git a/features/step_definitions/welcome.rb b/features/step_definitions/welcome.rb
index 777a0d0..e29a31b 100644
--- a/features/step_definitions/welcome.rb
+++ b/features/step_definitions/welcome.rb
@@ -8,4 +8,4 @@
When(/^I visit the welcome page$/) do
visit welcome_path
-end
+end
\ No newline at end of file
diff --git a/features/welcome.feature b/features/welcome.feature
index 7e74fec..b420b63 100644
--- a/features/welcome.feature
+++ b/features/welcome.feature
@@ -1,7 +1,6 @@
Feature: Welcome Page
- Scenario: Logged-in user is redirected to their profile with a welcome notice
+ Scenario: Logged-in user is redirected to their schedules page
Given I am logged in as a user with first name "Test"
When I visit the welcome page
- Then I should be on my profile page
- And I should see "Welcome back, Test!"
+ Then I should be on my schedules page
\ No newline at end of file
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 0ba9eae..bf4d466 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -10,7 +10,6 @@
@user = User.create!(uid: '12345', provider: 'google_oauth2', email: 'test@example.com', first_name: 'John',
last_name: 'Doe')
session[:user_id] = @user.id
- puts "session[:user_id] = #{session[:user_id]}"
end
it 'returns the current user' do
diff --git a/spec/controllers/csv_controller_spec.rb b/spec/controllers/csv_controller_spec.rb
deleted file mode 100644
index c61644e..0000000
--- a/spec/controllers/csv_controller_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-# spec/controllers/csv_controller_spec.rb
-require 'rails_helper'
-
-RSpec.describe CsvController, type: :controller do
- before do
- # Create a user and set session user_id as done in your application_controller_spec.rb
- @user = User.create!(uid: '12345', provider: 'google_oauth2', email: 'test@example.com', first_name: 'John',
- last_name: 'Doe')
- session[:user_id] = @user.id
- end
-
- let(:file) { fixture_file_upload(Rails.root.join('spec/fixtures/files/test.csv'), 'text/csv') }
-
- describe 'POST #upload' do
- context 'with a valid CSV file' do
- it "processes the CSV file, sets a success flash, and redirects to the user's page" do
- post :upload, params: { csv_file: file }
-
- expect(response).to have_http_status(:redirect)
- expect(response).to redirect_to(user_path(@user)) # Redirect to the current user's page
- expect(flash[:notice]).to eq('CSV file uploaded successfully.')
- end
- end
-
- context 'when no CSV file is selected' do
- it "sets an error flash and redirects to the user's page" do
- post :upload, params: { csv_file: nil }
-
- expect(response).to have_http_status(:redirect)
- expect(response).to redirect_to(user_path(@user)) # Redirect to the current user's page
- expect(flash[:error]).to eq('Please upload a CSV file.')
- end
- end
- end
-end
diff --git a/spec/controllers/schedules_controller_spec.rb b/spec/controllers/schedules_controller_spec.rb
index 53b9eef..d0db2f9 100644
--- a/spec/controllers/schedules_controller_spec.rb
+++ b/spec/controllers/schedules_controller_spec.rb
@@ -115,10 +115,7 @@
context 'when invalid CSV file is selected' do
it "sets an error flash and redirects to the user's page" do
- expect do
- post :upload_rooms, params: { id: schedule1.id, room_file: file_invalid }
- end.to raise_error(ArgumentError, /'1' is not a valid campus/)
-
+ post :upload_rooms, params: { id: schedule1.id, room_file: file_invalid }
expect(flash[:alert]).to include('There was an error uploading the CSV file')
end
end
diff --git a/spec/controllers/welcome_controller_spec.rb b/spec/controllers/welcome_controller_spec.rb
index 6170480..55e4447 100644
--- a/spec/controllers/welcome_controller_spec.rb
+++ b/spec/controllers/welcome_controller_spec.rb
@@ -13,10 +13,9 @@
controller.instance_variable_set(:@current_user, @user)
end
- it 'redirects to the user path with a welcome notice' do
+ it 'redirects to the schedule path with a welcome notice' do
get :index
- expect(response).to redirect_to(user_path(@user))
- expect(flash[:notice]).to eq('Welcome back, John!')
+ expect(response).to redirect_to(schedules_path)
end
end
@@ -25,7 +24,7 @@
allow(controller).to receive(:logged_in?).and_return(false)
end
- it 'renders the index template' do
+ it 'renders the welcome template' do
get :index
expect(response).to render_template(:index)
end
diff --git a/spec/fixtures/instructors/instructors_missing_headers.csv b/spec/fixtures/instructors/instructors_missing_headers.csv
new file mode 100644
index 0000000..cdbeaac
--- /dev/null
+++ b/spec/fixtures/instructors/instructors_missing_headers.csv
@@ -0,0 +1,5 @@
+Q20_1,Q20_2,Q20_3,Q20_4,Q20_5,Q20_6,Q20_7,Q20_8,Q20_9,Q20_10,Q20_11,Q20_12,Q20_13,Q20_14,Q20_15,Q20_16,Q20_17,Q20_18,Q20_19,Q20_20,Q20_21,Q20_22,Q20_23,Q20_24,Q20_25,Q20_26,Q20_27,Q20_28,Q20_29,Q20_30,Q20_31,Q20_32,Q20_33,Q20_34,Q20_35,Q20_36,Q20_37,Q20_38,Q20_39,Q20_40,Q20_41,Q20_42,Q20_43,Q20_44,Q20_45,Q20_46,Q20_47,Q20_48,Q20_49,Q20_50,Q20_51,Q20_52,Q20_53,Q20_54,Q20_55,Q20_56,Q20_57,Q20_58,Q5_1,Q5_2,Q5_3,Q5_4,Q5_5,Q5_6,Q5_7,Q5_8,Q5_9,Q5_10,Q5_11,Q5_12,Q5_65,Q5_13,Q5_14,Q5_15,Q5_16,Q5_17,Q5_18,Q5_19,Q5_20,Q5_21,Q5_22,Q5_23,Q5_24,Q5_25,Q5_90,Q5_26,Q5_27,Q5_28,Q5_29,Q5_30,Q5_66,Q5_32,Q5_33,Q5_87,Q5_34,Q5_35,Q5_36,Q5_37,Q5_38,Q5_39,Q5_40,Q5_67,Q5_67,Q5_41,Q5_42,Q5_43,Q5_44,Q5_45,Q5_46,Q5_47,Q5_48,Q5_49,Q5_50,Q5_51,Q5_52,Q5_53,Q5_54,Q5_55,Q5_56,Q5_57,Q5_58,Q5_59,Q5_67,Q5_61,Q5_68,Q5_69,Q5_72,Q5_62,Q5_63,Q5_88,Q5_77,Q5_71,Q5_70,Q5_79,Q5_75,Q5_81,Q5_74,Q5_80,Q5_76,Q5_82,Q5_83,Q5_84,Q5_85,Q5_86,Q5_89,Q7,Q21,Q12,Q13,Q17,Q18,,,,,
+2755728,ABCD,Abcd,X,acb@gmail.com,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,1,2,2,2,2,1,2,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,2,2,2,5,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,2,1,2,1,1,2,2,2,1,2,2,2,2,2,2,1,2,2,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,2,2,1,2,2,1,1,1,1,1,2,2,1,1,2,2,2,2,2,2,1,1,2,1,2,1,1,1,2,1,1,2,,,,,
+672598,EFGH,efgh,Y,hij@gmail.com,2,2,2,2,1,2,2,2,2,1,2,2,1,5,2,2,1,1,2,1,1,1,2,4,2,2,2,1,1,1,2,1,1,1,1,1,1,2,1,1,3,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,3,2,1,3,1,2,3,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,4,2,1,1,2,2,1,1,2,1,2,1,5,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,,,,,1
+670246,IJKL,Ijkl,Z,lmo@gmail.com,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,1,1,2,1,1,1,2,1,1,2,2,1,1,1,3,1,1,1,1,1,1,1,5,1,4,1,1,1,1,1,1,1,1,1,1,1,1,2,1,3,2,2,1,1,1,1,1,2,1,3,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,2,2,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,5,1,1,1,1,1,1,1,1,1,1,2,1,1,2,3,5,3,1,1,4,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,,1,,3,2
+2476413,MNOP,Mop,N,xyz@gmail.com,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,,1,,3,
\ No newline at end of file
diff --git a/spec/services/csv_handler_spec.rb b/spec/services/csv_handler_spec.rb
new file mode 100644
index 0000000..1a1b1fd
--- /dev/null
+++ b/spec/services/csv_handler_spec.rb
@@ -0,0 +1,72 @@
+# spec/services/csv_handler_spec.rb
+require 'rails_helper'
+
+RSpec.describe CsvHandler do
+ let(:schedule) { create(:schedule) }
+ let(:valid_room_csv) { File.read(Rails.root.join('spec', 'fixtures', 'rooms', 'rooms_valid.csv')) }
+ let(:invalid_room_csv) { File.read(Rails.root.join('spec', 'fixtures', 'rooms', 'rooms_invalid.csv')) }
+ let(:valid_instructor_csv) { File.read(Rails.root.join('spec', 'fixtures', 'instructors', 'instructors_valid.csv')) }
+ let(:invalid_instructor_csv) { File.read(Rails.root.join('spec', 'fixtures', 'instructors', 'instructors_missing_headers.csv')) }
+
+ describe '#initialize' do
+ it 'initializes with a file' do
+ handler = CsvHandler.new
+ handler.upload(valid_room_csv)
+ expect(handler.instance_variable_get(:@file)).to eq(valid_room_csv)
+ end
+ end
+
+ describe '#parse_room_csv' do
+ context 'with valid data' do
+ it 'creates room records' do
+ handler = CsvHandler.new
+ handler.upload(StringIO.new(valid_room_csv))
+ handler.parse_room_csv(schedule.id)
+ expect(Room.count).to eq(10)
+ end
+
+ it 'returns a success message' do
+ handler = CsvHandler.new
+ handler.upload(StringIO.new(valid_room_csv))
+ result = handler.parse_room_csv(schedule.id)
+ expect(result[:notice]).to eq('Rooms successfully uploaded.')
+ end
+ end
+
+ context 'with invalid data' do
+ it 'prints an alert' do
+ handler = CsvHandler.new
+ handler.upload(StringIO.new(invalid_room_csv))
+ result = handler.parse_room_csv(schedule.id)
+ expect(result[:alert]).to include('There was an error uploading the CSV file')
+ end
+ end
+ end
+
+ describe '#parse_instructor_csv' do
+ context 'with valid data' do
+ it 'creates instructor records' do
+ handler = CsvHandler.new
+ handler.upload(StringIO.new(valid_instructor_csv))
+ handler.parse_instructor_csv(schedule.id)
+ expect(Instructor.count).to eq(4)
+ end
+
+ it 'returns a success message' do
+ handler = CsvHandler.new
+ handler.upload(StringIO.new(valid_instructor_csv))
+ result = handler.parse_instructor_csv(schedule.id)
+ expect(result[:notice]).to eq('Instructors successfully uploaded.')
+ end
+ end
+
+ context 'with missing header data' do
+ it 'prints an alert' do
+ handler = CsvHandler.new
+ handler.upload(StringIO.new(invalid_instructor_csv))
+ result = handler.parse_instructor_csv(schedule.id)
+ expect(result[:alert]).to include('Missing required headers')
+ end
+ end
+ end
+end
\ No newline at end of file