diff --git a/app/controllers/concerns/user_courses.rb b/app/controllers/concerns/user_courses.rb index 87811e6d..7a7fecc4 100644 --- a/app/controllers/concerns/user_courses.rb +++ b/app/controllers/concerns/user_courses.rb @@ -11,13 +11,6 @@ def authorized_courses courses end - def load_category_courses - @category_ids = current_organization.categories.enabled.map(&:id) - @disabled_category_ids = current_organization.categories.disabled.map(&:id) - @disabled_category_courses = @courses.where(category_id: @disabled_category_ids) - @uncategorized_courses = @courses.where(category_id: nil) + @disabled_category_courses - end - def current_language_id english_id = Language.find_by(name: 'English').id || 1 spanish_id = Language.find_by(name: 'Spanish').id || 2 diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index de8355b7..5fd2b03e 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -20,8 +20,6 @@ def index @courses = @courses.merge(published_results) end - load_category_courses - respond_to do |format| format.html { render :index } format.json { render json: @courses } diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 12fd29b3..83a27f73 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -7,7 +7,6 @@ class HomeController < ApplicationController def index @courses = authorized_courses - load_category_courses end def language_toggle diff --git a/app/controllers/my_courses_controller.rb b/app/controllers/my_courses_controller.rb index b9faf8b4..d03058d6 100644 --- a/app/controllers/my_courses_controller.rb +++ b/app/controllers/my_courses_controller.rb @@ -2,6 +2,7 @@ class MyCoursesController < ApplicationController before_action :authenticate_user! + include UserCourses def index tracked_course_ids = current_user.course_progresses.tracked.collect(&:course_id) @@ -14,11 +15,6 @@ def index @courses = params[:search].blank? ? Course.where(id: tracked_course_ids) : @results @skip_quiz = current_user.profile.opt_out_of_recommendations - @category_ids = current_organization.categories.enabled.map(&:id) - @disabled_category_ids = current_organization.categories.disabled.map(&:id) - @disabled_category_courses = @courses.where(category_id: @disabled_category_ids) - @uncategorized_courses = @courses.where(category_id: nil) + @disabled_category_courses - respond_to do |format| format.html { render :index } format.json { render json: @courses } diff --git a/app/helpers/courses_helper.rb b/app/helpers/courses_helper.rb index 8b9774d9..6a1139b6 100644 --- a/app/helpers/courses_helper.rb +++ b/app/helpers/courses_helper.rb @@ -36,4 +36,18 @@ def percent_complete_without_user(course, _lesson_id) percent = 100 if percent > 100 percent.round end + + def courses_completed + user_signed_in? ? current_user.completed_course_ids : [] + end + + def categorized_courses(courses) + courses.group_by do |course| + if course.category&.enabled? + course.category.name + else + 'Uncategorized' + end + end + end end diff --git a/app/views/courses/index.html.erb b/app/views/courses/index.html.erb index 67463334..af7328c1 100644 --- a/app/views/courses/index.html.erb +++ b/app/views/courses/index.html.erb @@ -1,7 +1,7 @@ <%= render "shared/course_intro_text" %> <% if @courses.count > 0 %> - <%= render partial: "shared/courses/listing", locals: { courses_completed: [] } %> + <%= render "shared/courses/listing" %> <% else %>

No courses match your search. <%= link_to "View all courses", courses_path %>

<% end %> diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb index 07d3cdf1..9b4455d5 100644 --- a/app/views/home/index.html.erb +++ b/app/views/home/index.html.erb @@ -1,2 +1,2 @@ <%= render "shared/course_intro_text" %> -<%= render partial: "shared/courses/listing", locals: { courses_completed: [] } %> +<%= render "shared/courses/listing" %> diff --git a/app/views/my_courses/index.html.erb b/app/views/my_courses/index.html.erb index 7d0b890b..bd1b3e93 100644 --- a/app/views/my_courses/index.html.erb +++ b/app/views/my_courses/index.html.erb @@ -11,7 +11,7 @@ <% end %>

-<%= render partial: "shared/courses/listing" %> +<%= render "shared/courses/listing" %> <% if @results && @results.blank? %>

No courses match your search. <%= link_to "View all your courses", my_courses_path %>

diff --git a/app/views/shared/_search_box.html.erb b/app/views/shared/_search_box.html.erb index b681ea8e..fd1233d6 100644 --- a/app/views/shared/_search_box.html.erb +++ b/app/views/shared/_search_box.html.erb @@ -2,7 +2,7 @@ diff --git a/app/views/shared/courses/_course_widget.html.erb b/app/views/shared/courses/_course_widget.html.erb new file mode 100644 index 00000000..00a57d0d --- /dev/null +++ b/app/views/shared/courses/_course_widget.html.erb @@ -0,0 +1,12 @@ + +
+

<%= course.title %>

+
+
+

<%= course.summary %>

+
<%= percent_complete(course) %>
+
+ <%= course.duration %> +
+
+
\ No newline at end of file diff --git a/app/views/shared/courses/_listing.html.erb b/app/views/shared/courses/_listing.html.erb index 202fccb8..4ea82a66 100644 --- a/app/views/shared/courses/_listing.html.erb +++ b/app/views/shared/courses/_listing.html.erb @@ -1,49 +1,8 @@ -<% if user_signed_in? %> - <% courses_completed = current_user.completed_course_ids %> -<% else %> - <% courses_completed = [] %> -<% end %> - -<% (@category_ids || []).each do |category_id| %> - <% unless @courses.with_category(category_id).blank? %> -

<%= Category.find_by_id(category_id).name %>

- <% end %> -
- <% @courses.with_category(category_id).each do |c| %> - -
-

<%= c.title %>

-
-
-

<%= c.summary %>

-
<%= percent_complete(c) %>
-
- <%= c.duration %> -
-
-
- <% end %> -
-<% end %> - -<% if @uncategorized_courses.present? %> -

Uncategorized

+<% categorized_courses(@courses).each do |category_name, courses| %> +

<%= category_name %>

- <% @uncategorized_courses.each do |c| %> - -
-

<%= c.title %>

-
-
-

<%= c.summary %>

-
<%= percent_complete(c) %>
-
- <%= c.duration %> -
-
-
+ <% courses.each do |course| %> + <%= render partial: 'shared/courses/course_widget', locals: { course: course } %> <% end %>
<% end %> diff --git a/spec/controllers/courses_controller_spec.rb b/spec/controllers/courses_controller_spec.rb index b61c952d..fc940957 100644 --- a/spec/controllers/courses_controller_spec.rb +++ b/spec/controllers/courses_controller_spec.rb @@ -45,21 +45,6 @@ get :index, format: :json expect(response).to have_http_status(:success) end - - it 'assigns categories' do - get :index - expect(assigns(:category_ids)).to eq([@category1.id]) - end - - it 'assigns uncategorized courses' do - get :index - expect(assigns(:uncategorized_courses)).to include(@course2, @course3, @disabled_category_course) - end - - it 'has correct number of uncategorized courses' do - get :index - expect(assigns(:uncategorized_courses).count).to eq(3) - end end describe 'GET #show' do diff --git a/spec/controllers/home_controller_spec.rb b/spec/controllers/home_controller_spec.rb index 55af0903..aa14c951 100644 --- a/spec/controllers/home_controller_spec.rb +++ b/spec/controllers/home_controller_spec.rb @@ -36,22 +36,6 @@ it 'responds successfully' do expect(response).to have_http_status(:success) end - - it 'assigns enabled category ids' do - expect(assigns(:category_ids)).to include(category1.id, category2.id) - end - - it 'only assigns enabled category ids' do - expect(assigns(:category_ids).length).to eq(2) - end - - it 'assigns uncategorized and disabled category courses to uncategorized' do - expect(assigns(:uncategorized_courses)).to include(disabled_category_course, uncategorized_course) - end - - it 'assigns correct number of uncategorized courses' do - expect(assigns(:uncategorized_courses).count).to eq(2) - end end describe 'GET #home_language_toggle' do diff --git a/spec/controllers/my_courses_controller_spec.rb b/spec/controllers/my_courses_controller_spec.rb index a8dccf88..fe9ef8f6 100644 --- a/spec/controllers/my_courses_controller_spec.rb +++ b/spec/controllers/my_courses_controller_spec.rb @@ -45,18 +45,7 @@ get :index, params: { search: 'java' } expect(assigns(:courses)).to eq([course1]) end - - it 'assigns categories' do - get :index - expect(assigns(:category_ids)).to eq([category.id]) - end - - it 'assigns uncategorized courses including courses with a disabled category' do - get :index - expect(assigns(:uncategorized_courses)).to include(course3, course4) - end end - end context 'non-authenticated user' do diff --git a/spec/factories/course_progresses.rb b/spec/factories/course_progresses.rb index e05a1c99..d332527a 100644 --- a/spec/factories/course_progresses.rb +++ b/spec/factories/course_progresses.rb @@ -5,12 +5,4 @@ user course end - - factory(:course_progress_with_completed_lessons) do - after(:create) do |course_progress| - create(:completed_lesson, course_progress: course_progress) - create(:completed_lesson, course_progress: course_progress) - create(:completed_lesson, course_progress: course_progress) - end - end end diff --git a/spec/features/admin/admin_logs_in_spec.rb b/spec/features/admin/admin_logs_in_spec.rb index 3c249304..3a66e3c7 100644 --- a/spec/features/admin/admin_logs_in_spec.rb +++ b/spec/features/admin/admin_logs_in_spec.rb @@ -13,7 +13,7 @@ end context 'with valid profile' do - scenario 'is sent to admin home page' do + scenario 'is sent to admin dashboard page' do log_in_with @user.email, @user.password expect(current_path).to eq(admin_dashboard_index_path) end diff --git a/spec/features/admin/admin_walkthrough_spec.rb b/spec/features/admin/admin_walkthrough_spec.rb index 473df7ef..d160742e 100644 --- a/spec/features/admin/admin_walkthrough_spec.rb +++ b/spec/features/admin/admin_walkthrough_spec.rb @@ -21,6 +21,12 @@ click_link 'Account' expect(current_path).to eq(profile_path) + within('.main-logo') do + find('a').click + end + expect(current_path).to eq(root_path) + expect(page).to have_content('Edit a course by clicking on a course below,') + click_link 'Sign Out' expect(current_path).to eq(root_path) expect(page).to have_content('Signed out successfully.') diff --git a/spec/features/anonymous_visits_static_pages_spec.rb b/spec/features/anonymous_user_walkthrough_spec.rb similarity index 89% rename from spec/features/anonymous_visits_static_pages_spec.rb rename to spec/features/anonymous_user_walkthrough_spec.rb index 6369fe84..1d92977a 100644 --- a/spec/features/anonymous_visits_static_pages_spec.rb +++ b/spec/features/anonymous_user_walkthrough_spec.rb @@ -7,6 +7,11 @@ create(:default_organization) end + scenario 'visits root path' do + visit root_path + expect(page).to have_content('Choose a course below to start learning or search courses.') + end + scenario 'can visit the customization page' do page = create(:cms_page, title: 'Pricing & Features') visit cms_page_path(page) diff --git a/spec/features/user/account_settings_spec.rb b/spec/features/user/account_settings_spec.rb index b83b29e9..3a24febe 100644 --- a/spec/features/user/account_settings_spec.rb +++ b/spec/features/user/account_settings_spec.rb @@ -59,11 +59,6 @@ expect(page).to have_content 'Profile was successfully updated.' expect(page).to have_content 'Preferred Language' end - - scenario 'can view completed courses' do - # visit courses_completed_path - end - end context 'belongs to program subdomain' do diff --git a/spec/features/user/search_spec.rb b/spec/features/user/search_spec.rb new file mode 100644 index 00000000..d951c880 --- /dev/null +++ b/spec/features/user/search_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'feature_helper' + +feature 'User searches for courses' do + let(:org) { FactoryBot.create(:organization) } + let(:user) { FactoryBot.create(:user, organization: org) } + let!(:course) { FactoryBot.create(:course, organization: org) } + + before do + switch_to_subdomain(org.subdomain) + login_as(user) + visit root_path + end + + scenario 'no courses found' do + fill_in 'Search', with: 'foobar' + click_on('submit-search') + expect(page).to have_content('No courses match your search.') + expect(page).to have_link('View all courses', href: courses_path) + end + + scenario 'course found' do + fill_in 'Search', with: course.title + click_on('submit-search') + expect(page).to have_content(course.summary) + end +end diff --git a/spec/features/user/user_walkthrough_spec.rb b/spec/features/user/user_walkthrough_spec.rb index 9c7dadcf..49518789 100644 --- a/spec/features/user/user_walkthrough_spec.rb +++ b/spec/features/user/user_walkthrough_spec.rb @@ -20,6 +20,12 @@ expect(current_path).to eq(my_courses_path) expect(page).to_not have_link('Profile') + within('.main-logo') do + find('a').click + end + expect(current_path).to eq(root_path) + expect(page).to have_content('Choose a course below to start learning') + click_link 'Sign Out' expect(current_path).to eq(root_path) expect(page).to have_content('Signed out successfully.') diff --git a/spec/helpers/courses_helper_spec.rb b/spec/helpers/courses_helper_spec.rb index 7f9ca8ea..c6018bc4 100644 --- a/spec/helpers/courses_helper_spec.rb +++ b/spec/helpers/courses_helper_spec.rb @@ -3,47 +3,92 @@ require 'rails_helper' describe CoursesHelper do - - before(:each) do - @course = FactoryBot.create(:course) - end + let(:user) { FactoryBot.create(:user) } + let(:organization) { user.organization } + let!(:course) { FactoryBot.create(:course, organization: organization) } describe '#pub_status_str' do it 'returns the full name for a given status' do - @course.pub_status = 'D' - expect(helper.pub_status_str(@course)).to eq('Draft') - @course.pub_status = 'P' - expect(helper.pub_status_str(@course)).to eq('Published') - @course.pub_status = 'T' - expect(helper.pub_status_str(@course)).to eq('Trashed') + course.pub_status = 'D' + expect(helper.pub_status_str(course)).to eq('Draft') + course.pub_status = 'P' + expect(helper.pub_status_str(course)).to eq('Published') + course.pub_status = 'T' + expect(helper.pub_status_str(course)).to eq('Trashed') end end describe '#percent_complete' do + let!(:course2) { FactoryBot.create(:course, title: 'Course 2') } + let!(:course_progress) { FactoryBot.create(:course_progress, user: user, course: course) } before(:each) do - @course2 = FactoryBot.create(:course, title: 'Course 2') - @user = FactoryBot.create(:user) - sign_in @user - @course_progress = FactoryBot.create(:course_progress, course_id: @course.id) - @user.course_progresses << @course_progress + sign_in user end it "returns an empty string if the user isn't logged in" do - sign_out @user - expect(helper.percent_complete(@course)).to eq('') + sign_out user + expect(helper.percent_complete(course)).to eq('') end it 'returns an empty string if the user doesnt have a course progress for the course' do - expect(helper.percent_complete(@course2)).to eq('0% Complete') + expect(helper.percent_complete(course2)).to eq('0% Complete') end it 'returns the course progress' do - expect(helper.percent_complete(@course)).to eq('0% Complete') + expect(helper.percent_complete(course)).to eq('0% Complete') end it 'returns the course progress without a user' do - expect(helper.percent_complete_without_user(@course, 1)).to eq(0) + expect(helper.percent_complete_without_user(course, 1)).to eq(0) + end + end + + describe '#courses_completed' do + context 'no authenticated user' do + it 'should return empty array for completed courses if no session completions' do + expect(helper.courses_completed).to eq([]) + end + end + + context 'with authenticated user' do + let!(:completion) { FactoryBot.create(:course_progress, user: user, course: course, completed_at: Time.zone.now) } + let!(:unfinished_course) { FactoryBot.create(:course_progress, user: user, course: course) } + + before do + sign_in user + end + + it 'should return completed courses for user' do + expect(helper.courses_completed).to contain_exactly(course.id) + end + end + end + + describe '#categorized_courses' do + let(:category) { FactoryBot.create(:category, organization: organization) } + let(:disabled_category) { FactoryBot.create(:category, :disabled, organization: organization) } + let!(:course_with_category) { FactoryBot.create(:course, category: category, organization: organization) } + let!(:uncategorized_course) { FactoryBot.create(:course, organization: organization) } + let!(:course_with_disabled_category) { FactoryBot.create(:course, category: disabled_category, organization: organization) } + + let(:result) { helper.categorized_courses(organization.courses) } + + before do + @request.host = "#{organization.subdomain}.test.host" + sign_in user + end + + it 'should return courses by category' do + expect(result[category.name]).to contain_exactly(course_with_category) + end + + it 'should return uncategorized courses' do + expect(result['Uncategorized']).to include(uncategorized_course) + end + + it 'should return courses with disabled category as uncategorized' do + expect(result['Uncategorized']).to include(course_with_disabled_category) end end end diff --git a/spec/views/courses/index.html.erb_spec.rb b/spec/views/courses/index.html.erb_spec.rb deleted file mode 100644 index 9dabf4e2..00000000 --- a/spec/views/courses/index.html.erb_spec.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -describe 'courses/index.html.erb' do - - before(:each) do - @organization = create(:organization) - allow(view).to receive(:current_organization).and_return(@organization) - allow(view).to receive(:subdomain?).and_return(false) - allow(view).to receive(:top_level_domain?).and_return(false) - switch_to_subdomain('chipublib') - @course = create(:course, title: 'Searched Title') - end - - it 'shows the appropriate message when no courses are returned' do - assign(:courses, []) - render - expect(rendered).to have_content 'No courses match your search.' - expect(rendered).to have_link 'View all courses', href: courses_path - end - - it 'shows the appropriate message when at least one course is returned' do - assign(:courses, [@course]) - assign(:uncategorized_courses, [@course]) - render - expect(rendered).to have_content 'Searched Title' - end - -end diff --git a/spec/views/home/index.html.erb_spec.rb b/spec/views/home/index.html.erb_spec.rb deleted file mode 100644 index 5acd411d..00000000 --- a/spec/views/home/index.html.erb_spec.rb +++ /dev/null @@ -1,42 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -describe 'home/index.html.erb' do - - before(:each) do - @org = create(:default_organization) - allow(view).to receive(:current_organization).and_return(@org) - allow(view).to receive(:subdomain?).and_return(false) - allow(view).to receive(:top_level_domain?).and_return(true) - @course = create(:course) - @courses = [@course] - assign(:course, @course) - @admin = create(:user, :admin, organization: @org) - @user = create(:user) - end - - context 'when logged in as an admin' do - it 'displays the admin message' do - sign_in @admin - render - expect(rendered).to have_content('Edit a course by clicking on a course below,') - end - end - - context 'when logged in as a normal user' do - it 'displays the user message' do - sign_in @user - render - expect(rendered).to have_content('Choose a course below to start learning') - end - end - - context 'when not logged in' do - it 'displays the default message' do - render - expect(rendered).to have_content('Choose a course below to start learning or search courses.') - end - end - -end