From 6320d5633f5ecefc67a06608c001adcebe9abcf5 Mon Sep 17 00:00:00 2001 From: rebuilt Date: Fri, 8 Oct 2021 22:56:37 +0200 Subject: [PATCH] Add JS tests to verify school and district dropdowns. --- Gemfile | 1 + Gemfile.lock | 18 +- app/assets/javascripts/dashboard.js | 17 +- app/assets/javascripts/home.js | 25 +++ app/controllers/home_controller.rb | 6 + app/helpers/header_helper.rb | 8 + app/views/home/index.html.erb | 6 + app/views/layouts/home.html.erb | 12 ++ config/routes.rb | 1 + .../features/school_dashboard_feature_spec.rb | 178 +++++++++++------- spec/spec_helper.rb | 4 + spec/views/home/index.html.erb_spec.rb | 17 ++ 12 files changed, 219 insertions(+), 74 deletions(-) create mode 100644 app/assets/javascripts/home.js create mode 100644 app/controllers/home_controller.rb create mode 100644 app/views/home/index.html.erb create mode 100644 app/views/layouts/home.html.erb create mode 100644 spec/views/home/index.html.erb_spec.rb diff --git a/Gemfile b/Gemfile index 9d6fd3a6..30c68795 100644 --- a/Gemfile +++ b/Gemfile @@ -71,6 +71,7 @@ group 'test' do gem 'rspec-rails', '~> 4.1.2' gem 'rails-controller-testing' gem 'capybara' + gem 'apparition', github: 'twalpole/apparition', ref: 'ca86be4d54af835d531dbcd2b86e7b2c77f85f34' gem 'launchy' gem 'database_cleaner' gem 'timecop' diff --git a/Gemfile.lock b/Gemfile.lock index 8f25f087..54780e0f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,12 @@ +GIT + remote: https://github.com/twalpole/apparition.git + revision: ca86be4d54af835d531dbcd2b86e7b2c77f85f34 + ref: ca86be4d54af835d531dbcd2b86e7b2c77f85f34 + specs: + apparition (0.6.0) + capybara (~> 3.13, < 4) + websocket-driver (>= 0.6.5) + GEM remote: https://rubygems.org/ specs: @@ -112,19 +121,19 @@ GEM mail (2.7.1) mini_mime (>= 0.1.1) method_source (1.0.0) - mini_mime (1.1.1) + mini_mime (1.1.2) mini_portile2 (2.6.1) minitest (5.14.4) multi_json (1.15.0) nested_scaffold (1.1.0) newrelic_rpm (8.0.0) nio4r (2.5.8) - nokogiri (1.12.4) + nokogiri (1.12.5) mini_portile2 (~> 2.6.1) racc (~> 1.4) - nokogiri (1.12.4-x86_64-darwin) + nokogiri (1.12.5-x86_64-darwin) racc (~> 1.4) - nokogiri (1.12.4-x86_64-linux) + nokogiri (1.12.5-x86_64-linux) racc (~> 1.4) omniauth (2.0.4) hashie (>= 3.4.6) @@ -251,6 +260,7 @@ PLATFORMS DEPENDENCIES activerecord-import + apparition! bootstrap byebug capybara diff --git a/app/assets/javascripts/dashboard.js b/app/assets/javascripts/dashboard.js index 82f4985a..dbcad599 100644 --- a/app/assets/javascripts/dashboard.js +++ b/app/assets/javascripts/dashboard.js @@ -1,9 +1,12 @@ -document.addEventListener("DOMContentLoaded", function() { - document.querySelector('#select-school').addEventListener('change', (event) => { - window.location = event.target.value; - }); +document.addEventListener("turbolinks:load", function() { + const schoolDropdown = document.querySelector('#select-school'); + if (schoolDropdown) { + document.querySelector('#select-school').addEventListener('change', (event) => { + window.location = event.target.value; + }); - document.querySelector('#select-district').addEventListener('change', (event) => { - window.location = event.target.value; - }); + document.querySelector('#select-district').addEventListener('change', (event) => { + window.location = event.target.value; + }); + } }); diff --git a/app/assets/javascripts/home.js b/app/assets/javascripts/home.js new file mode 100644 index 00000000..47d80f08 --- /dev/null +++ b/app/assets/javascripts/home.js @@ -0,0 +1,25 @@ +document.addEventListener('DOMContentLoaded', () => { + const districtDropdown = document.querySelector('#district-dropdown'); + if (districtDropdown) { + districtDropdown.addEventListener('change', event => { + const schoolDropdown = document.querySelector('#school-dropdown'); + + const districtId = Number(event.target.value); + + const schoolsInDistrict = window.schools.filter(school => school.district_id === districtId); + + schoolsInDistrict.forEach(school => { + const optionElem = document.createElement('option'); + optionElem.setAttribute('value', school.url); + const schoolNameNode = document.createTextNode(school.name); + optionElem.appendChild(schoolNameNode); + schoolDropdown.appendChild(optionElem); + }); + }); + + document.querySelector('button[data-id="go-to-school"]').addEventListener('click', event => { + const selectedSchoolURL = document.querySelector('#school-dropdown').value; + window.location = selectedSchoolURL; + }); + } +}); diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb new file mode 100644 index 00000000..d53a1e76 --- /dev/null +++ b/app/controllers/home_controller.rb @@ -0,0 +1,6 @@ +class HomeController < ActionController::Base + def index + @districts = District.all.order(:name) + @schools = School.all + end +end diff --git a/app/helpers/header_helper.rb b/app/helpers/header_helper.rb index e9bd6192..3fa8a1e9 100644 --- a/app/helpers/header_helper.rb +++ b/app/helpers/header_helper.rb @@ -16,6 +16,14 @@ module HeaderHelper dashboard_link(district_slug: school.district.slug, school_slug: school.slug, academic_year_range: academic_year.range, uri_path: request.fullpath) end + def school_mapper(school) + { + name: school.name, + district_id: school.district_id, + url: district_school_dashboard_index_path(school.district, school, {year: AcademicYear.first.range}) + } + end + def link_weight(path:) active?(path: path) ? 'weight-700' : 'weight-400' end diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb new file mode 100644 index 00000000..d4eb7ff3 --- /dev/null +++ b/app/views/home/index.html.erb @@ -0,0 +1,6 @@ +<%= collection_select(:district, :id, @districts, :id, :name, {}, {id: 'district-dropdown'}) %> + + + + diff --git a/app/views/layouts/home.html.erb b/app/views/layouts/home.html.erb new file mode 100644 index 00000000..8266f150 --- /dev/null +++ b/app/views/layouts/home.html.erb @@ -0,0 +1,12 @@ + + + Our new layout + <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> + + + <%= yield %> + + + diff --git a/config/routes.rb b/config/routes.rb index a9d8f7b4..6b5c6ea6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -34,5 +34,6 @@ Rails.application.routes.draw do get '/admin', to: 'admin#index', as: 'admin' post '/twilio', to: 'attempts#twilio' + get '/welcome', to: 'home#index' root to: "welcome#index" end diff --git a/spec/features/school_dashboard_feature_spec.rb b/spec/features/school_dashboard_feature_spec.rb index 3dc82535..b7dab844 100644 --- a/spec/features/school_dashboard_feature_spec.rb +++ b/spec/features/school_dashboard_feature_spec.rb @@ -1,7 +1,85 @@ require 'rails_helper' +# include Rails.application.routes.url_helpers + +def district_admin_sees_student_physical_safety + expect(page).to have_text('Student Physical Safety') + student_physical_safety_row = measure_row_bars.find { |item| item['data-for-measure-id'] == '2A-i' } + expect(student_physical_safety_row['width']).to eq '40.0%' + expect(student_physical_safety_row['x']).to eq '60%' +end + +def district_admin_sees_problem_solving_emphasis + expect(page).to have_text('Problem Solving Emphasis') + problem_solving_emphasis_row = measure_row_bars.find { |item| item['data-for-measure-id'] == '4C-i' } + expect(problem_solving_emphasis_row['width']).to eq '60.0%' + expect(problem_solving_emphasis_row['x']).to eq '0.0%' +end + +def district_admin_sees_professional_qualifications + expect(page).to have_text('Professional Qualifications') + professional_qualifications_row = measure_row_bars.find { |item| item['data-for-measure-id'] == '1A-i' } + expect(professional_qualifications_row['width']).to eq '8.26%' + expect(professional_qualifications_row['x']).to eq '60%' +end + +def go_to_school_dashboard_from_welcome_page(district, school) + select district.name, from: 'district-dropdown' + select school.name, from: 'school-dropdown' + click_on 'Go' +end + +def go_to_different_school_in_same_district(school) + select school.name, from: 'select-school' +end + +def go_to_different_district(district) + select district.name, from: 'select-district' +end + +def district_admin_sees_schools_change + expected_path = "/districts/#{school_in_same_district.district.slug}/schools/#{school_in_same_district.slug}/browse/#{SqmCategory.first.slug}?year=2020-21" + expect(page).to have_current_path(expected_path) +end + +def district_admin_sees_district_change + expected_path = "/districts/#{different_district.slug}/schools/#{different_district.schools.alphabetic.first.slug}/browse/#{SqmCategory.first.slug}?year=2020-21" + expect(page).to have_current_path(expected_path) +end + +def district_admin_sees_measures_in_correct_order + professional_qualifications_row_index = measure_row_bars.find_index { |item| item['data-for-measure-id'] == '1A-i' } + student_physical_safety_row_index = measure_row_bars.find_index { |item| item['data-for-measure-id'] == '2A-i' } + problem_solving_emphasis_row_index = measure_row_bars.find_index { |item| item['data-for-measure-id'] == '4C-i' } + expect(student_physical_safety_row_index).to be < professional_qualifications_row_index + expect(professional_qualifications_row_index).to be < problem_solving_emphasis_row_index +end + +def district_admin_sees_dashboard_content + expect(page).to have_select('academic-year', selected: '2020 – 2021') + expect(page).to have_select('district', selected: 'Winchester') + expect(page).to have_select('school', selected: 'Winchester High School') + expect(page).to have_text(school.name) + + district_admin_sees_professional_qualifications + district_admin_sees_student_physical_safety + district_admin_sees_problem_solving_emphasis + + measure_row_bar_with_no_responses = measure_row_bars.find { |item| item['data-for-measure-id'] == '3A-i' } + expect(measure_row_bar_with_no_responses['width']).to eq '0.0%' + + page.assert_selector('.measure-row-bar', count: Measure.count) + + district_admin_sees_measures_in_correct_order +end + +def district_admin_sees_browse_content + expect(page).to have_text('Teachers & Leadership') + expect(page).to have_text('Approval') +end feature 'School dashboard', type: feature do let(:district) { District.find_by_slug 'winchester' } + let(:different_district) { District.find_by_slug 'boston' } let(:school) { School.find_by_slug 'winchester-high-school' } let(:school_in_same_district) { School.find_by_slug 'muraco-elementary-school' } @@ -31,19 +109,23 @@ feature 'School dashboard', type: feature do before :each do survey_items_for_measure_1A_i.each do |survey_item| - SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school, survey_item: survey_item, likert_score: 4 + SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school, + survey_item: survey_item, likert_score: 4 end survey_items_for_measure_2A_i.each do |survey_item| - SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school, survey_item: survey_item, likert_score: 5 + SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school, + survey_item: survey_item, likert_score: 5 end survey_items_for_measure_4C_i.each do |survey_item| - SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school, survey_item: survey_item, likert_score: 1 + SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school, + survey_item: survey_item, likert_score: 1 end survey_items_for_subcategory.each do |survey_item| - SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school, survey_item: survey_item, likert_score: 4 + SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school, + survey_item: survey_item, likert_score: 4 end end @@ -55,58 +137,25 @@ feature 'School dashboard', type: feature do expect(page).not_to have_text(school.name) end - scenario 'User views a school dashboard' do - page.driver.browser.basic_authorize(username, password) - - visit "/districts/#{district.slug}/schools/#{school.slug}/dashboard?year=#{ay_2020_21.range}" - - expect(page).to have_select('academic-year', selected: '2020 – 2021') - expect(page).to have_select('district', selected: 'Winchester') - expect(page).to have_select('school', selected: 'Winchester High School') - - expect(page).to have_text(school.name) - - expect(page).to have_text('Professional Qualifications') - professional_qualifications_row = measure_row_bars.find { |item| item['data-for-measure-id'] == '1A-i' } - expect(professional_qualifications_row['width']).to eq '8.26%' - expect(professional_qualifications_row['x']).to eq '60%' - - expect(page).to have_text('Student Physical Safety') - student_physical_safety_row = measure_row_bars.find { |item| item['data-for-measure-id'] == '2A-i' } - expect(student_physical_safety_row['width']).to eq '40.0%' - expect(student_physical_safety_row['x']).to eq '60%' - - expect(page).to have_text('Problem Solving Emphasis') - problem_solving_emphasis_row = measure_row_bars.find { |item| item['data-for-measure-id'] == '4C-i' } - expect(problem_solving_emphasis_row['width']).to eq '60.0%' - expect(problem_solving_emphasis_row['x']).to eq '0.0%' + scenario 'District Admin views a school dashboard', js: true do + page.driver.basic_authorize(username, password) - measure_row_bar_with_no_responses = measure_row_bars.find { |item| item['data-for-measure-id'] == '3A-i' } + visit '/welcome' + go_to_school_dashboard_from_welcome_page(district, school) - # puts measure_with_no_survey_responses.id - # puts measure_with_no_survey_responses.measure_id - # survey_item_responses = SurveyItemResponse.for_measure(measure_with_no_survey_responses) - # responses_count = SurveyItemResponse.count - - # expect(responses_count).to eq survey_item_responses.count - # expect(survey_item_responses.count).to eq 0 - expect(measure_row_bar_with_no_responses['width']).to eq '0.0%' - - page.assert_selector('.measure-row-bar', count: Measure.count) - professional_qualifications_row_index = measure_row_bars.find_index { |item| item['data-for-measure-id'] == '1A-i' } - student_physical_safety_row_index = measure_row_bars.find_index { |item| item['data-for-measure-id'] == '2A-i' } - problem_solving_emphasis_row_index = measure_row_bars.find_index { |item| item['data-for-measure-id'] == '4C-i' } - expect(student_physical_safety_row_index).to be < professional_qualifications_row_index - expect(professional_qualifications_row_index).to be < problem_solving_emphasis_row_index + district_admin_sees_dashboard_content click_on 'Browse' - - expect(page).to have_text('Teachers & Leadership') - expect(page).to have_text('Approval') + district_admin_sees_browse_content click_on 'School Culture' - expect(page).to have_text('This category measures the degree to which the school environment is safe, caring, and academically-oriented.') + + go_to_different_school_in_same_district(school_in_same_district) + district_admin_sees_schools_change + + go_to_different_district(different_district) + district_admin_sees_district_change end scenario 'user sees schools in the same district' do @@ -120,9 +169,10 @@ feature 'School dashboard', type: feature do expect(page.all('.school-options[selected]')[0].value).to eq "/districts/#{district.slug}/schools/#{school.slug}/dashboard?year=#{ay_2020_21.range}" school_options = page.all('.school-options') - school_options.each_with_index do |school , index| - break if index == school_options.length-1 - expect(school.text).to be < school_options[index+1].text + school_options.each_with_index do |school, index| + break if index == school_options.length - 1 + + expect(school.text).to be < school_options[index + 1].text end visit "/districts/#{district.slug}/schools/#{school.slug}/browse/teachers-and-leadership?year=#{ay_2020_21.range}" @@ -134,13 +184,14 @@ feature 'School dashboard', type: feature do expect(page.all('.school-options[selected]')[0].value).to eq "/districts/#{district.slug}/schools/#{school.slug}/browse/teachers-and-leadership?year=#{ay_2020_21.range}" school_options = page.all('.school-options') - school_options.each_with_index do |school , index| - break if index == school_options.length-1 - expect(school.text).to be < school_options[index+1].text + school_options.each_with_index do |school, index| + break if index == school_options.length - 1 + + expect(school.text).to be < school_options[index + 1].text end end - scenario 'user sees all districts in dropdown menu' do + scenario 'user sees all districts in dropdown menu' do page.driver.browser.basic_authorize(username, password) visit "/districts/#{district.slug}/schools/#{school.slug}/dashboard?year=#{ay_2020_21.range}" @@ -151,9 +202,10 @@ feature 'School dashboard', type: feature do expect(page.all('.district-options[selected]')[0].value).to eq "/districts/#{district.slug}/schools/#{district.schools.alphabetic.first.slug}/dashboard?year=#{ay_2020_21.range}" district_options = page.all('.district-options') - district_options.each_with_index do |district , index| - break if index == district_options.length-1 - expect(district.text).to be < district_options[index+1].text + district_options.each_with_index do |district, index| + break if index == district_options.length - 1 + + expect(district.text).to be < district_options[index + 1].text end visit "/districts/#{district.slug}/schools/#{school.slug}/browse/teachers-and-leadership?year=#{ay_2020_21.range}" @@ -165,10 +217,10 @@ feature 'School dashboard', type: feature do expect(page.all('.district-options[selected]')[0].value).to eq "/districts/#{district.slug}/schools/#{district.schools.alphabetic.first.slug}/browse/teachers-and-leadership?year=#{ay_2020_21.range}" district_options = page.all('.district-options') - district_options.each_with_index do |district , index| - break if index == district_options.length-1 - expect(district.text).to be < district_options[index+1].text + district_options.each_with_index do |district, index| + break if index == district_options.length - 1 + + expect(district.text).to be < district_options[index + 1].text end end - end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b173bec3..8dc7f1f4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,4 +1,5 @@ require 'capybara/rspec' +require 'capybara/apparition' # This file was generated by the `rails generate rspec:install` command. Conventionally, all # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. # The generated `.rspec` file contains `--require spec_helper` which will cause @@ -17,6 +18,9 @@ require 'capybara/rspec' # users commonly want. # # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration + +Capybara.javascript_driver = :apparition + RSpec.configure do |config| # rspec-expectations config goes here. You can use an alternate # assertion/expectation library such as wrong or the stdlib/minitest diff --git a/spec/views/home/index.html.erb_spec.rb b/spec/views/home/index.html.erb_spec.rb new file mode 100644 index 00000000..e7881547 --- /dev/null +++ b/spec/views/home/index.html.erb_spec.rb @@ -0,0 +1,17 @@ +require 'rails_helper' + +describe 'home/index.html.erb' do + subject { Nokogiri::HTML(rendered) } + + before :each do + assign :districts, [create(:district), create(:district)] + # assign :schools, [create(:school), create(:school), create(:school)] + + render + end + + it 'renders a dropdown with districts' do + expect(subject.css('#district-dropdown option').count).to eq 2 + end + +end