Add Overall Response Rate

rpp-main
rebuilt 3 years ago committed by Gabe Farrell
parent 435bc4a5be
commit a71ebbc4e4

@ -1,107 +1,107 @@
source "https://rubygems.org"
ruby "3.2.1"
source 'https://rubygems.org'
ruby '3.2.1'
git_source(:github) do |repo_name|
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?('/')
"https://github.com/#{repo_name}.git"
end
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem "rails", "~> 7.0.4"
gem "sprockets-rails"
gem 'rails', '~> 7.0.4'
gem 'sprockets-rails'
gem "pg"
gem 'pg'
# Use Puma as the app server
gem "puma", ">= 5.6.4"
gem 'puma', '>= 5.6.4'
# Use Uglifier as compressor for JavaScript assets
gem "uglifier", ">= 1.3.0"
gem 'uglifier', '>= 1.3.0'
# See https://github.com/rails/execjs#readme for more supported runtimes
# Use jquery as the JavaScript library
gem "jquery-rails"
gem 'jquery-rails'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem "jbuilder", "~> 2.5"
gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
gem "redis", "~> 3.0"
gem 'redis', '~> 3.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
gem "nokogiri", ">= 1.13.4"
gem 'nokogiri', '>= 1.13.4'
gem "bootsnap", require: false
gem 'bootsnap', require: false
gem "haml"
gem 'haml'
gem "friendly_id", "~> 5.1.0"
gem 'friendly_id', '~> 5.1.0'
gem "newrelic_rpm"
gem 'newrelic_rpm'
gem "devise"
gem 'devise'
gem "omniauth"
gem 'omniauth'
gem "twilio-ruby", "~> 4.11.1"
gem 'twilio-ruby', '~> 4.11.1'
gem "activerecord-import"
gem 'activerecord-import'
gem "jsbundling-rails"
gem 'jsbundling-rails'
gem "cssbundling-rails"
gem 'cssbundling-rails'
gem "turbo-rails"
gem 'turbo-rails'
gem "stimulus-rails"
gem 'stimulus-rails'
gem "watir"
gem 'watir'
gem "selenium-webdriver", "~> 4.4"
gem "net-sftp"
gem "ed25519"
gem "bcrypt_pbkdf"
gem 'selenium-webdriver', '~> 4.4'
gem 'net-sftp'
gem 'ed25519'
gem 'bcrypt_pbkdf'
gem "standard_deviation"
gem 'standard_deviation'
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem "byebug", platform: :mri
gem "factory_bot_rails"
gem "parallel_tests"
gem "rack-mini-profiler"
gem "rspec-rails", "~> 5.1.0"
gem "debug", platforms: %i[mri mingw x64_mingw]
gem 'byebug', platform: :mri
gem 'factory_bot_rails'
gem 'parallel_tests'
gem 'rack-mini-profiler'
gem 'rspec-rails', '~> 5.1.0'
gem 'debug', platforms: %i[mri mingw x64_mingw]
end
group :development do
# Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
gem "brakeman"
gem "bullet"
gem "erb_lint", require: false
gem "erblint-github"
gem "guard"
gem "guard-rspec", require: false
gem "guard-livereload", "~> 2.5", require: false
gem "rack-livereload"
gem "listen", "~> 3.0.5"
gem "nested_scaffold"
gem 'brakeman'
gem 'bullet'
gem 'erb_lint', require: false
gem 'erblint-github'
gem 'guard'
gem 'guard-rspec', require: false
gem 'guard-livereload', '~> 2.5', require: false
gem 'rack-livereload'
gem 'listen', '~> 3.0.5'
gem 'nested_scaffold'
# gem 'reek', require: false
gem "rubocop", require: false
gem "seed_dump"
gem "solargraph-reek"
gem "spring"
gem "web-console"
gem 'rubocop', require: false
gem 'seed_dump'
gem 'solargraph-reek'
gem 'spring'
gem 'web-console'
end
group "test" do
gem "apparition", github: "twalpole/apparition", ref: "ca86be4d54af835d531dbcd2b86e7b2c77f85f34"
gem "capybara"
gem "database_cleaner"
gem "launchy"
gem "rails-controller-testing"
gem "simplecov", require: false
gem "timecop"
group 'test' do
gem 'apparition', github: 'twalpole/apparition', ref: 'ca86be4d54af835d531dbcd2b86e7b2c77f85f34'
gem 'capybara'
gem 'database_cleaner'
gem 'launchy'
gem 'rails-controller-testing'
gem 'simplecov', require: false
gem 'timecop'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem "tzinfo-data", platforms: %i[mingw mswin x64_mingw jruby]
gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby]
gem "reline", "~> 0.3.2"
gem 'reline', '~> 0.3.2'

@ -89,6 +89,26 @@
width: 20px;
}
.overall-response-rate-row {
width: 55%;
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: -23px;
}
.overall-response-rate-container {
padding: 0.4em 0.7em;
width: 48%;
display: flex;
justify-content: space-between;
align-items: center;
color: $gray-1;
@extend .bg-color-gray-3;
@extend .border-radius-8;
@extend .font-size-14
}
@media only screen and (min-width: 768px){
.measure-row-label {
width: 170px;

@ -7,6 +7,10 @@ class OverviewController < SqmApplicationController
def index
@variance_chart_row_presenters = measures.map(&method(:presenter_for_measure))
@category_presenters = Category.sorted.map { |category| CategoryPresenter.new(category:) }
@student_response_rate_presenter = ResponseRatePresenter.new(focus: :student, school: @school,
academic_year: @academic_year)
@teacher_response_rate_presenter = ResponseRatePresenter.new(focus: :teacher, school: @school,
academic_year: @academic_year)
end
private

@ -0,0 +1,45 @@
class ResponseRatePresenter
attr_reader :focus, :academic_year, :school, :survey_items
def initialize(focus:, academic_year:, school:)
@focus = focus
@academic_year = academic_year
@school = school
@survey_items = SurveyItem.student_survey_items if focus == :student
@survey_items = SurveyItem.teacher_survey_items if focus == :teacher
end
def date
SurveyItemResponse.where(survey_item: survey_items, school:).order(updated_at: :DESC).first&.updated_at || Date.new
end
def percentage
cap_at_100(actual_count.to_f / respondents_count.to_f * 100).round
end
def color
# Problem: the color (either $gold or $purple) is determined by the scss variable, but the
# percentage is decided by the presenter. Therefore the class style must be generated
# within this file and not the scss file.
# TODO: Fix this.
percentage > 75 ? '#49416D' : '#FFC857'
end
private
def cap_at_100(value)
value > 100 ? 100 : value
end
def actual_count
SurveyItemResponse.where(school:, academic_year:,
survey_item: survey_items).select(:response_id).distinct.count
end
def respondents_count
respondents = Respondent.find_by(school:, academic_year:)
count = respondents.total_students if focus == :student
count = respondents.total_teachers if focus == :teacher
count
end
end

@ -8,6 +8,8 @@ module Sftp
uri = URI.parse(sftptogo_url)
Net::SFTP.start(uri.host, uri.user, password: uri.password) do |sftp|
sftp.dir.foreach(path) do |entry|
next unless entry.file?
filename = entry.name
puts filename

@ -13,15 +13,15 @@ class SurveyItemValues
dese_id.present?
end
def response_date
@response_date ||= begin
def recorded_date
@recorded_date ||= begin
recorded_date = value_from(pattern: /Recorded\s*Date/i)
Date.parse(recorded_date)
end
end
def academic_year
@academic_year ||= AcademicYear.find_by_date response_date
@academic_year ||= AcademicYear.find_by_date recorded_date
end
def survey_item_response(survey_item:)

@ -77,11 +77,11 @@ class SurveyResponsesDataLoader
gender = row.gender
grade = row.grade
if survey_item_response.present?
survey_item_response.update!(likert_score:, grade:, gender:)
survey_item_response.update!(likert_score:, grade:, gender:, recorded_date: row.recorded_date)
[]
else
SurveyItemResponse.new(response_id: row.response_id, academic_year: row.academic_year, school: row.school, survey_item:,
likert_score:, grade:, gender:)
likert_score:, grade:, gender:, recorded_date: row.recorded_date)
end
end

@ -0,0 +1,8 @@
<div class="overall-response-rate-container">
<div>Response Rates as of <%= response_rate_presenter.date.to_date.strftime("%m/%d/%y") %> </div>
<div style="display: flex; justify-content:space-between; width: 100px;">
<div><%= response_rate_presenter.focus.capitalize %> </div>
<%= render partial: "response_rate_graphic", locals: {response_rate_presenter: response_rate_presenter}, cached: true %>
<div><%= response_rate_presenter.percentage %>% </div>
</div>
</div>

@ -0,0 +1,35 @@
<style>
/*
For some reason, none of the sizing in the pie class works, and it always
fills 100% of the containing frame, so the size has to be dictated by .prog
*/
.prog {
width: 16px;
height: 16px;
position: relative;
border: 1px solid black;
border-radius: 50%;
margin-top: 0.2em;
}
.pie {
aspect-ratio: 1;
display: inline-grid;
place-content: center;
margin: 5px;
font-size: 25px;
font-weight: bold;
font-family: sans-serif;
}
#response-rate-pie-<%= response_rate_presenter.focus %>:before{
content: "";
position: absolute;
border-radius: 50%;
inset: 0;
background: conic-gradient(<%= response_rate_presenter.color %> calc(<%= response_rate_presenter.percentage %>*1%),#0000 0);
}
</style>
<div class="prog">
<div id="response-rate-pie-<%= response_rate_presenter.focus %>" class="pie"></div>
</div>

@ -81,6 +81,12 @@
</div>
</div>
<%= render partial: "quality_framework_indicators", locals: { category_presenters: @category_presenters }, cached: true %>
<div class="overall-response-rate-row">
<%= render partial: "response_rate", locals: {response_rate_presenter: @student_response_rate_presenter}, cached: true %>
<%= render partial: "response_rate", locals: {response_rate_presenter: @teacher_response_rate_presenter}, cached: true %>
</div>
</div>
<div class="card">
<h2 class="sub-header-2 mb-4">Distance From Benchmark</h2>

@ -0,0 +1,5 @@
class AddRecordedDateToSurveyItemResponse < ActiveRecord::Migration[7.0]
def change
add_column :survey_item_responses, :recorded_date, :datetime
end
end

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2023_04_21_034505) do
ActiveRecord::Schema[7.0].define(version: 2023_05_17_191736) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -444,6 +444,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_04_21_034505) do
t.bigint "student_id"
t.integer "grade"
t.bigint "gender_id"
t.datetime "recorded_date"
t.index ["academic_year_id"], name: "index_survey_item_responses_on_academic_year_id"
t.index ["gender_id"], name: "index_survey_item_responses_on_gender_id"
t.index ["response_id"], name: "index_survey_item_responses_on_response_id"

@ -4,6 +4,6 @@ Start Date,End Date,Response Type,IP Address,Progress,Duration (in seconds),Fini
2021-03-31 9:50:19,2021-03-31 9:59:01,0,108.7.17.250,100,522,1,2021-03-31T09:59:02,student_survey_response_3,345678,,,,,42.53340149,-70.96530151,anonymous,EN,3,2,1500505,12,4,108,3300,7,1,,,,,,,,,,,,,,2,4,2,1,4,3,3,,,,,3,3,3,3,,,,,NA,,,,,,,,,3,2,3,3,2,1,3,3,4,1,3,3,4,4,2,4,3,3,4,3,3,3,4,3,3,3,3,3,,,,,,,,,,3,4,4,2,3,3,1,,3,,EN,Math teacher,,,,6,888,8,2
2021-03-31 9:50:09,2021-03-31 10:00:16,0,67.186.188.168,100,607,1,2021-03-31T10:00:17,student_survey_response_4,456789,,,,,42.63510132,-71.30139923,anonymous,EN,3,2,1500505,12,18,108,2064,7,1,,2,2,1,,,,,,,,,,,,,,,,,,,,,,,,,3,5,3,3,,,,,,,,,,4,4,3,4,5,1,,1,5,1,3,2,4,4,1,2,1,3,2,3,3,3,4,2,5,3,4,5,5,3,3,4,3,,,,,4,4,4,4,3,5,2,,2,,EN,,,,English teacher,7,888,8,3
2021-03-31 9:51:39,2021-03-31 10:01:36,0,73.47.153.77,100,596,1,2021-03-31T10:01:36,student_survey_response_5,567890,,,,,42.65820313,-71.30580139,anonymous,EN,3,2,1500505,6,15,109,3710,7,1,,2,2,2,,,,,,,,,,3,3,4,3,3,3,3,4,3,4,3,4,4,5,4,3,4,3,5,2,2,3,,,,,,,,,,,,1,,2,5,1,3,3,2,4,3,5,4,,,,,,,,,,,,5,4,3,4,4,4,4,4,4,,,,,,,2,,2,,EN,,,Social Studies teacher,,"1,2,3,4,5,8,6,7",888,7,4
2021-03-31 9:51:39,2021-03-31 10:01:36,0,73.47.153.77,100,596,1,2021-03-31T10:01:36,student_survey_response_6,,,,,,42.65820313,-71.30580139,anonymous,EN,3,2,1500505,6,15,109,3710,7,1,,2,2,2,,,,,,,,,,3,3,4,3,3,3,3,4,3,4,3,4,4,5,4,3,4,3,5,2,2,3,,,,,,,,,,,,1,,2,5,1,3,3,2,4,3,5,4,,,,,,,,,,,,5,4,3,4,4,4,4,4,4,,,,,,,2,,2,,EN,,,Social Studies teacher,,"1,2,3,4,5,8",888,3,NA
2021-03-31 9:51:39,2021-03-31 10:01:36,0,73.47.153.77,100,596,1,2021-03-31T10:01:36,student_survey_response_7,,,,,,42.65820313,-71.30580139,anonymous,EN,3,2,1500505,6,15,109,3710,7,1,,2,2,2,,,,,,,,,,3,3,4,3,3,3,3,4,3,4,3,4,4,5,4,3,4,3,5,2,2,3,,,,,,,,,,,,1,,2,5,1,3,3,2,4,3,5,4,,,,,,,,,,,,5,4,3,4,4,4,4,4,4,,,,,,,2,,2,,EN,,,Social Studies teacher,,,,4,
2021-03-31 9:51:39,2021-03-31 10:01:36,0,73.47.153.77,100,596,1,2021-03-31T10:01:37,student_survey_response_6,,,,,,42.65820313,-71.30580139,anonymous,EN,3,2,1500505,6,15,109,3710,7,1,,2,2,2,,,,,,,,,,3,3,4,3,3,3,3,4,3,4,3,4,4,5,4,3,4,3,5,2,2,3,,,,,,,,,,,,1,,2,5,1,3,3,2,4,3,5,4,,,,,,,,,,,,5,4,3,4,4,4,4,4,4,,,,,,,2,,2,,EN,,,Social Studies teacher,,"1,2,3,4,5,8",888,3,NA
2021-03-31 9:51:39,2021-03-31 10:01:36,0,73.47.153.77,100,596,1,2021-03-31T10:01:38,student_survey_response_7,,,,,,42.65820313,-71.30580139,anonymous,EN,3,2,1500505,6,15,109,3710,7,1,,2,2,2,,,,,,,,,,3,3,4,3,3,3,3,4,3,4,3,4,4,5,4,3,4,3,5,2,2,3,,,,,,,,,,,,1,,2,5,1,3,3,2,4,3,5,4,,,,,,,,,,,,5,4,3,4,4,4,4,4,4,,,,,,,2,,2,,EN,,,Social Studies teacher,,,,4,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"1,2,3,4,5,8",,,

1 Start Date End Date Response Type IP Address Progress Duration (in seconds) Finished RecordedDate ResponseId LASID Recipient Last Name Recipient First Name Recipient Email External Data Reference Location Latitude Location Longitude Distribution Channel User Language district school DESE ID #N/A #N/A #N/A #N/A #N/A #N/A #N/A s-emsa-q1 s-emsa-q2 s-emsa-q3 s-tint-q1 s-tint-q2 #N/A s-tint-q4 s-tint-q5 s-acpr-q1 s-acpr-q2 s-acpr-q3 s-acpr-q4 #N/A #N/A s-cure-q3 s-cure-q4 #N/A s-sten-q2 s-sten-q3 s-sper-q1 s-sper-q2 s-sper-q3 s-sper-q4 s-civp-q1 s-civp-q2 s-civp-q3 s-civp-q4 s-grmi-q1 #N/A #N/A s-grmi-q4 s-appa-q1 s-appa-q2 #N/A s-peff-q1 s-peff-q2 s-peff-q3 s-peff-q4 s-peff-q5 s-peff-q6 s-sbel-q1 s-sbel-q2 s-sbel-q3 s-sbel-q4 s-sbel-q5 s-phys-q1 s-phys-q1-1 s-phys-q2 s-phys-q3 s-phys-q4 s-vale-q1 s-vale-q2 s-vale-q3 s-vale-q4 s-acst-q1 s-acst-q2 s-acst-q3 s-acst-q4 s-acst-q5 s-grit-q1 s-grit-q2 s-grit-q3 s-grit-q4 #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A race What is your race/ethnicity?(Please select all that apply) - Selected Choice grade gender
4 2021-03-31 9:50:19 2021-03-31 9:59:01 0 108.7.17.250 100 522 1 2021-03-31T09:59:02 student_survey_response_3 345678 42.53340149 -70.96530151 anonymous EN 3 2 1500505 12 4 108 3300 7 1 2 4 2 1 4 3 3 3 3 3 3 NA 3 2 3 3 2 1 3 3 4 1 3 3 4 4 2 4 3 3 4 3 3 3 4 3 3 3 3 3 3 4 4 2 3 3 1 3 EN Math teacher 6 888 8 2
5 2021-03-31 9:50:09 2021-03-31 10:00:16 0 67.186.188.168 100 607 1 2021-03-31T10:00:17 student_survey_response_4 456789 42.63510132 -71.30139923 anonymous EN 3 2 1500505 12 18 108 2064 7 1 2 2 1 3 5 3 3 4 4 3 4 5 1 1 5 1 3 2 4 4 1 2 1 3 2 3 3 3 4 2 5 3 4 5 5 3 3 4 3 4 4 4 4 3 5 2 2 EN English teacher 7 888 8 3
6 2021-03-31 9:51:39 2021-03-31 10:01:36 0 73.47.153.77 100 596 1 2021-03-31T10:01:36 student_survey_response_5 567890 42.65820313 -71.30580139 anonymous EN 3 2 1500505 6 15 109 3710 7 1 2 2 2 3 3 4 3 3 3 3 4 3 4 3 4 4 5 4 3 4 3 5 2 2 3 1 2 5 1 3 3 2 4 3 5 4 5 4 3 4 4 4 4 4 4 2 2 EN Social Studies teacher 1,2,3,4,5,8,6,7 888 7 4
7 2021-03-31 9:51:39 2021-03-31 10:01:36 0 73.47.153.77 100 596 1 2021-03-31T10:01:36 2021-03-31T10:01:37 student_survey_response_6 42.65820313 -71.30580139 anonymous EN 3 2 1500505 6 15 109 3710 7 1 2 2 2 3 3 4 3 3 3 3 4 3 4 3 4 4 5 4 3 4 3 5 2 2 3 1 2 5 1 3 3 2 4 3 5 4 5 4 3 4 4 4 4 4 4 2 2 EN Social Studies teacher 1,2,3,4,5,8 888 3 NA
8 2021-03-31 9:51:39 2021-03-31 10:01:36 0 73.47.153.77 100 596 1 2021-03-31T10:01:36 2021-03-31T10:01:38 student_survey_response_7 42.65820313 -71.30580139 anonymous EN 3 2 1500505 6 15 109 3710 7 1 2 2 2 3 3 4 3 3 3 3 4 3 4 3 4 4 5 4 3 4 3 5 2 2 3 1 2 5 1 3 3 2 4 3 5 4 5 4 3 4 4 4 4 4 4 2 2 EN Social Studies teacher 4
9 1,2,3,4,5,8

@ -0,0 +1,160 @@
require 'rails_helper'
describe ResponseRatePresenter do
let(:academic_year) { create(:academic_year, range: '2022-23') }
let(:school) { create(:school, name: 'A school') }
let(:respondents) { create(:respondent, school:, academic_year:, total_students: 40, total_teachers: 40) }
let(:wrong_school) { create(:school, name: 'Wrong school') }
let(:wrong_academic_year) { create(:academic_year) }
let(:wrong_respondents) do
create(:respondent, school: wrong_school, academic_year: wrong_academic_year, total_students: 40,
total_teachers: 40)
end
let(:student_survey_item) { create(:student_survey_item) }
let(:teacher_survey_item) { create(:teacher_survey_item) }
let(:oldest_student_survey_response) do
create(:survey_item_response, school:, academic_year:, survey_item: student_survey_item)
end
let(:newest_student_survey_response) do
create(:survey_item_response, school:, academic_year:, survey_item: student_survey_item)
end
let(:oldest_teacher_survey_response) do
create(:survey_item_response, school:, academic_year:, survey_item: teacher_survey_item)
end
let(:newest_teacher_survey_response) do
create(:survey_item_response, school:, academic_year:, survey_item: teacher_survey_item)
end
let(:wrong_student_survey_response) do
create(:survey_item_response, school: wrong_school, academic_year: wrong_academic_year,
survey_item: student_survey_item)
end
let(:wrong_teacher_survey_response) do
create(:survey_item_response, school: wrong_school, academic_year: wrong_academic_year,
survey_item: teacher_survey_item)
end
context '.date' do
context 'when focus is student' do
before :each do
oldest_student_survey_response
newest_student_survey_response
wrong_student_survey_response
wrong_teacher_survey_response
end
it 'ignores all teacher items and only gets the modified date of the last student item' do
rdate = ResponseRatePresenter.new(focus: :student, academic_year:, school:).date
expect(rdate).to eq(newest_student_survey_response.updated_at)
end
end
context 'when focus is teacher' do
before :each do
oldest_teacher_survey_response
newest_teacher_survey_response
wrong_student_survey_response
wrong_teacher_survey_response
end
it 'ignores all student responses and only gets the modified date of the last teacher item' do
rdate = ResponseRatePresenter.new(focus: :teacher, academic_year:, school:).date
expect(rdate).to eq(newest_teacher_survey_response.updated_at)
end
end
end
context '.percentage' do
before :each do
respondents
wrong_respondents
end
context 'when no survey responses are found for a school' do
it 'returns a response rate of 0' do
rdate = ResponseRatePresenter.new(focus: :teacher, academic_year:, school:).percentage
expect(rdate).to eq(0)
end
end
context 'when there all possible teacher respondents answered questions' do
before :each do
create_list(:survey_item_response, 40, school:, academic_year:,
survey_item: teacher_survey_item)
end
it 'returns a response rate of 100' do
rdate = ResponseRatePresenter.new(focus: :teacher, academic_year:, school:).percentage
expect(rdate).to eq(100)
end
end
context 'when more teachers responded than staff the school' do
before :each do
create_list(:survey_item_response, 80, school:, academic_year:,
survey_item: teacher_survey_item)
end
it 'returns a response rate of 100' do
rdate = ResponseRatePresenter.new(focus: :teacher, academic_year:, school:).percentage
expect(rdate).to eq(100)
end
end
context 'when three quarters of the teachers responded to the survey' do
before :each do
create_list(:survey_item_response, 30, school:, academic_year:,
survey_item: teacher_survey_item)
end
it 'returns a response rate of 75' do
rdate = ResponseRatePresenter.new(focus: :teacher, academic_year:, school:).percentage
expect(rdate).to eq(75)
end
end
context 'when one quarter of the teachers responded to the survey' do
before :each do
create_list(:survey_item_response, 10, school:, academic_year:,
survey_item: teacher_survey_item)
end
it 'returns a response rate of 25' do
rdate = ResponseRatePresenter.new(focus: :teacher, academic_year:, school:).percentage
expect(rdate).to eq(25)
end
end
context 'When the percentage is not a round number' do
before :each do
create_list(:survey_item_response, 9, school:, academic_year:,
survey_item: teacher_survey_item)
end
it 'its rounded to the nearest integer' do
rdate = ResponseRatePresenter.new(focus: :teacher, academic_year:, school:).percentage
expect(rdate).to eq(23)
end
end
context 'when there all possible student respondents answered questions' do
before :each do
create_list(:survey_item_response, 40, school:, academic_year:,
survey_item: student_survey_item)
end
it 'returns a response rate of 100' do
rdate = ResponseRatePresenter.new(focus: :student, academic_year:, school:).percentage
expect(rdate).to eq(100)
end
end
context 'when half of all students responded' do
before :each do
create_list(:survey_item_response, 20, school:, academic_year:,
survey_item: student_survey_item)
end
it 'returns a response rate of 50' do
rdate = ResponseRatePresenter.new(focus: :student, academic_year:, school:).percentage
expect(rdate).to eq(50)
end
end
end
end

@ -23,7 +23,7 @@ RSpec.describe Cleaner do
end
let(:common_headers) do
['Recorded Date', 'DeseID', 'ResponseID']
['Recorded Date', 'Dese ID', 'ResponseID']
end
let(:standard_survey_items) do

@ -1,9 +1,9 @@
require "rails_helper"
require 'rails_helper'
RSpec.describe SurveyItemValues, type: :model do
let(:headers) do
["StartDate", "EndDate", "Status", "IPAddress", "Progress", "Duration (in seconds)", "Finished", "RecordedDate",
"ResponseId", "RecipientLastName", "RecipientFirstName", "RecipientEmail", "ExternalReference", "LocationLatitude", "LocationLongitude", "DistributionChannel", "UserLanguage", "District", "School- Lee", "School- Maynard", "LASID", "Grade", "s-emsa-q1", "s-emsa-q2", "s-emsa-q3", "s-tint-q1", "s-tint-q2", "s-tint-q3", "s-tint-q4", "s-tint-q5", "s-acpr-q1", "s-acpr-q2", "s-acpr-q3", "s-acpr-q4", "s-cure-q1", "s-cure-q2", "s-cure-q3", "s-cure-q4", "s-sten-q1", "s-sten-q2", "s-sten-q3", "s-sper-q1", "s-sper-q2", "s-sper-q3", "s-sper-q4", "s-civp-q1", "s-civp-q2", "s-civp-q3", "s-civp-q4", "s-grmi-q1", "s-grmi-q2", "s-grmi-q3", "s-grmi-q4", "s-appa-q1", "s-appa-q2", "s-appa-q3", "s-peff-q1", "s-peff-q2", "s-peff-q3", "s-peff-q4", "s-peff-q5", "s-peff-q6", "s-sbel-q1", "s-sbel-q2", "s-sbel-q3", "s-sbel-q4", "s-sbel-q5", "s-phys-q1", "s-phys-q2", "s-phys-q3", "s-phys-q4", "s-vale-q1", "s-vale-q2", "s-vale-q3", "s-vale-q4", "s-acst-q1", "s-acst-q2", "s-acst-q3", "s-sust-q1", "s-sust-q2", "s-grit-q1", "s-grit-q2", "s-grit-q3", "s-grit-q4", "s-expa-q1", "s-poaf-q1", "s-poaf-q2", "s-poaf-q3", "s-poaf-q4", "s-tint-q1-1", "s-tint-q2-1", "s-tint-q3-1", "s-tint-q4-1", "s-tint-q5-1", "s-acpr-q1-1", "s-acpr-q2-1", "s-acpr-q3-1", "s-acpr-q4-1", "s-peff-q1-1", "s-peff-q2-1", "s-peff-q3-1", "s-peff-q4-1", "s-peff-q5-1", "s-peff-q6-1", "Gender", "Race"]
['StartDate', 'EndDate', 'Status', 'IPAddress', 'Progress', 'Duration (in seconds)', 'Finished', 'RecordedDate',
'ResponseId', 'RecipientLastName', 'RecipientFirstName', 'RecipientEmail', 'ExternalReference', 'LocationLatitude', 'LocationLongitude', 'DistributionChannel', 'UserLanguage', 'District', 'School- Lee', 'School- Maynard', 'LASID', 'Grade', 's-emsa-q1', 's-emsa-q2', 's-emsa-q3', 's-tint-q1', 's-tint-q2', 's-tint-q3', 's-tint-q4', 's-tint-q5', 's-acpr-q1', 's-acpr-q2', 's-acpr-q3', 's-acpr-q4', 's-cure-q1', 's-cure-q2', 's-cure-q3', 's-cure-q4', 's-sten-q1', 's-sten-q2', 's-sten-q3', 's-sper-q1', 's-sper-q2', 's-sper-q3', 's-sper-q4', 's-civp-q1', 's-civp-q2', 's-civp-q3', 's-civp-q4', 's-grmi-q1', 's-grmi-q2', 's-grmi-q3', 's-grmi-q4', 's-appa-q1', 's-appa-q2', 's-appa-q3', 's-peff-q1', 's-peff-q2', 's-peff-q3', 's-peff-q4', 's-peff-q5', 's-peff-q6', 's-sbel-q1', 's-sbel-q2', 's-sbel-q3', 's-sbel-q4', 's-sbel-q5', 's-phys-q1', 's-phys-q2', 's-phys-q3', 's-phys-q4', 's-vale-q1', 's-vale-q2', 's-vale-q3', 's-vale-q4', 's-acst-q1', 's-acst-q2', 's-acst-q3', 's-sust-q1', 's-sust-q2', 's-grit-q1', 's-grit-q2', 's-grit-q3', 's-grit-q4', 's-expa-q1', 's-poaf-q1', 's-poaf-q2', 's-poaf-q3', 's-poaf-q4', 's-tint-q1-1', 's-tint-q2-1', 's-tint-q3-1', 's-tint-q4-1', 's-tint-q5-1', 's-acpr-q1-1', 's-acpr-q2-1', 's-acpr-q3-1', 's-acpr-q4-1', 's-peff-q1-1', 's-peff-q2-1', 's-peff-q3-1', 's-peff-q4-1', 's-peff-q5-1', 's-peff-q6-1', 'Gender', 'Race']
end
let(:genders) do
create(:gender, qualtrics_code: 1)
@ -16,55 +16,81 @@ RSpec.describe SurveyItemValues, type: :model do
end
let(:survey_items) { [] }
let(:attleboro) do
create(:school, name: "Attleboro", dese_id: 1234)
create(:school, name: 'Attleboro', dese_id: 1234)
end
let(:attleboro_respondents) do
create(:respondent, school: attleboro, academic_year: ay_2022_23, nine: 40, ten: 40, eleven: 40, twelve: 40)
end
let(:schools) { School.school_hash }
let(:recorded_date) { "2023-04-01" }
let(:recorded_date) { '2023-04-01' }
let(:ay_2022_23) do
create(:academic_year, range: "2022-23")
create(:academic_year, range: '2022-23')
end
context ".response_date" do
it "returns the recorded date" do
row = {"RecordedDate" => "2017-01-01"}
context '.recorded_date' do
it 'returns the recorded date' do
row = { 'RecordedDate' => '2017-01-01' }
values = SurveyItemValues.new(row:, headers:, genders:, survey_items:, schools:)
expect(values.response_date).to eq Date.parse("2017-01-01")
expect(values.recorded_date).to eq Date.parse('2017-01-01')
headers = ['Recorded Date']
row = { 'Recorded Date' => '2017-01-02' }
values = SurveyItemValues.new(row:, headers:, genders:, survey_items:, schools:)
expect(values.recorded_date).to eq Date.parse('2017-01-02')
end
end
context ".school" do
it "returns the school that maps to the dese id provided" do
context '.school' do
it 'returns the school that maps to the dese id provided' do
attleboro
row = {"Dese ID" => "1234"}
headers = ['Dese ID']
row = { 'Dese ID' => '1234' }
values = SurveyItemValues.new(row:, headers:, genders:, survey_items:, schools:)
expect(values.school).to eq attleboro
headers = ['School']
row = { 'School' => '1234' }
values = SurveyItemValues.new(row:, headers:, genders:, survey_items:, schools:)
expect(values.school).to eq attleboro
row = {"DeseID" => "1234"}
headers = ['School- Attleboro']
row = { 'School- Attleboro' => '1234' }
values = SurveyItemValues.new(row:, headers:, genders:, survey_items:, schools:)
expect(values.school).to eq attleboro
end
end
context ".grade" do
it "returns the grade that maps to the grade provided" do
row = {"Grade" => "1"}
context '.grade' do
it 'returns the grade that maps to the grade provided' do
row = { 'Grade' => '1' }
values = SurveyItemValues.new(row:, headers:, genders:, survey_items:, schools:)
expect(values.grade).to eq 1
end
end
context ".gender" do
it "returns the grade that maps to the grade provided" do
row = {"Gender" => "1"}
context '.gender' do
it 'returns the grade that maps to the grade provided' do
row = { 'Gender' => '1' }
values = SurveyItemValues.new(row:, headers:, genders:, survey_items:, schools:)
expect(values.gender.qualtrics_code).to eq 1
end
end
context ".survey_type" do
it "reads header to find the survey type" do
context '.dese_id' do
it 'returns the dese id for the id provided' do
headers = ['Dese ID']
row = { 'Dese ID' => '11' }
values = SurveyItemValues.new(row:, headers:, genders:, survey_items:, schools:)
expect(values.dese_id).to eq 11
headers = ['School']
row = { 'School' => '22' }
values = SurveyItemValues.new(row:, headers:, genders:, survey_items:, schools:)
expect(values.dese_id).to eq 22
end
end
context '.survey_type' do
it 'reads header to find the survey type' do
headers = %w[s-sbel-q5 s-phys-q2 RecordedDate]
values = SurveyItemValues.new(row: {}, headers:, genders:, survey_items:, schools:)
expect(values.survey_type).to eq :student
@ -75,118 +101,118 @@ RSpec.describe SurveyItemValues, type: :model do
end
end
context ".valid_duration" do
context "when duration is valid" do
it "returns true" do
headers = ["s-sbel-q5", "s-phys-q2", "RecordedDate", "Duration (in seconds)"]
values = SurveyItemValues.new(row: {"Duration (in seconds)" => "240"}, headers:, genders:, survey_items:,
schools:)
context '.valid_duration' do
context 'when duration is valid' do
it 'returns true' do
headers = ['s-sbel-q5', 's-phys-q2', 'RecordedDate', 'Duration (in seconds)']
values = SurveyItemValues.new(row: { 'Duration (in seconds)' => '240' }, headers:, genders:, survey_items:,
schools:)
expect(values.valid_duration?).to eq true
headers = ["t-sbel-q5", "t-phys-q2", "Duration (in seconds)"]
values = SurveyItemValues.new(row: {"Duration (in seconds)" => "300"}, headers:, genders:, survey_items:,
schools:)
headers = ['t-sbel-q5', 't-phys-q2', 'Duration (in seconds)']
values = SurveyItemValues.new(row: { 'Duration (in seconds)' => '300' }, headers:, genders:, survey_items:,
schools:)
expect(values.valid_duration?).to eq true
end
end
context "when duration is invalid" do
it "returns false" do
headers = ["s-sbel-q5", "s-phys-q2", "RecordedDate", "Duration (in seconds)"]
values = SurveyItemValues.new(row: {"Duration (in seconds)" => "239"}, headers:, genders:, survey_items:,
schools:)
context 'when duration is invalid' do
it 'returns false' do
headers = ['s-sbel-q5', 's-phys-q2', 'RecordedDate', 'Duration (in seconds)']
values = SurveyItemValues.new(row: { 'Duration (in seconds)' => '239' }, headers:, genders:, survey_items:,
schools:)
expect(values.valid_duration?).to eq false
headers = ["t-sbel-q5", "t-phys-q2", "Duration (in seconds)"]
values = SurveyItemValues.new(row: {"Duration (in seconds)" => "299"}, headers:, genders:, survey_items:,
schools:)
headers = ['t-sbel-q5', 't-phys-q2', 'Duration (in seconds)']
values = SurveyItemValues.new(row: { 'Duration (in seconds)' => '299' }, headers:, genders:, survey_items:,
schools:)
expect(values.valid_duration?).to eq false
end
end
end
context ".valid_progress" do
context "when progress is valid" do
it "returns true" do
context '.valid_progress' do
context 'when progress is valid' do
it 'returns true' do
headers = %w[s-sbel-q5 s-phys-q2 RecordedDate]
values = SurveyItemValues.new(row: {"Progress" => "25"}, headers:, genders:, survey_items:,
schools:)
values = SurveyItemValues.new(row: { 'Progress' => '25' }, headers:, genders:, survey_items:,
schools:)
expect(values.valid_progress?).to eq true
end
end
context "when progress is invalid" do
it "returns false" do
context 'when progress is invalid' do
it 'returns false' do
headers = %w[s-sbel-q5 s-phys-q2 RecordedDate]
values = SurveyItemValues.new(row: {"Progress" => "24"}, headers:, genders:, survey_items:,
schools:)
values = SurveyItemValues.new(row: { 'Progress' => '24' }, headers:, genders:, survey_items:,
schools:)
expect(values.valid_progress?).to eq false
end
end
end
context ".valid_grade?" do
context "when grade is valid" do
xcontext '.valid_grade?' do
context 'when grade is valid' do
before :each do
attleboro
attleboro_respondents
end
it "returns true for students" do
it 'returns true for students' do
headers = %w[s-sbel-q5 s-phys-q2 grade RecordedDate]
values = SurveyItemValues.new(row: {"grade" => "9", "RecordedDate" => recorded_date, "Dese ID" => "1234"}, headers:, genders:, survey_items:,
schools:)
values = SurveyItemValues.new(row: { 'grade' => '9', 'RecordedDate' => recorded_date, 'Dese ID' => '1234' }, headers:, genders:, survey_items:,
schools:)
expect(values.valid_grade?).to eq true
end
it "returns true for teachers" do
xit 'returns true for teachers' do
headers = %w[t-sbel-q5 t-phys-q2 grade RecordedDate]
values = SurveyItemValues.new(row: {"RecordedDate" => recorded_date, "Dese ID" => "1234"}, headers:, genders:, survey_items:,
schools:)
values = SurveyItemValues.new(row: { 'RecordedDate' => recorded_date, 'Dese ID' => '1234' }, headers:, genders:, survey_items:,
schools:)
expect(values.valid_grade?).to eq true
end
end
context "when grade is invalid" do
xcontext 'when grade is invalid' do
before :each do
attleboro
attleboro_respondents
end
it "returns false" do
it 'returns false' do
headers = %w[s-sbel-q5 s-phys-q2 grade RecordedDate]
values = SurveyItemValues.new(row: {"grade" => "2", "RecordedDate" => recorded_date, "Dese ID" => "1234"}, headers:, genders:, survey_items:,
schools: School.school_hash)
values = SurveyItemValues.new(row: { 'grade' => '2', 'RecordedDate' => recorded_date, 'Dese ID' => '1234' }, headers:, genders:, survey_items:,
schools: School.school_hash)
expect(values.valid_grade?).to eq false
end
end
end
context ".valid_sd?" do
context "when the standard deviation is valid" do
it "returns true for student questions" do
context '.valid_sd?' do
context 'when the standard deviation is valid' do
it 'returns true for student questions' do
headers = %w[s-sbel-q5 s-phys-q1 s-phys-q2 RecordedDate]
values = SurveyItemValues.new(row: {"RecordedDate" => recorded_date, "Dese ID" => "1234", "s-sbel-q5" => "1", "s-phys-q1" => "", "s-phys-q2" => "5"}, headers:, genders:, survey_items:,
schools: School.school_hash)
values = SurveyItemValues.new(row: { 'RecordedDate' => recorded_date, 'Dese ID' => '1234', 's-sbel-q5' => '1', 's-phys-q1' => '', 's-phys-q2' => '5' }, headers:, genders:, survey_items:,
schools: School.school_hash)
expect(values.valid_sd?).to eq true
end
it "returns true for teacher questions" do
it 'returns true for teacher questions' do
headers = %w[t-sbel-q5 t-phys-q2]
values = SurveyItemValues.new(row: {"RecordedDate" => recorded_date, "Dese ID" => "1234", "t-sbel-q5" => "1", "t-phys-q2" => "5"}, headers:, genders:, survey_items:,
schools: School.school_hash)
values = SurveyItemValues.new(row: { 'RecordedDate' => recorded_date, 'Dese ID' => '1234', 't-sbel-q5' => '1', 't-phys-q2' => '5' }, headers:, genders:, survey_items:,
schools: School.school_hash)
expect(values.valid_sd?).to eq true
end
end
context "when the standard deviation is invalid" do
it "returns false for student questions" do
context 'when the standard deviation is invalid' do
it 'returns false for student questions' do
headers = %w[s-sbel-q5 s-phys-q1 s-phys-q2 RecordedDate]
values = SurveyItemValues.new(row: {"RecordedDate" => recorded_date, "Dese ID" => "1234", "s-sbel-q5" => "1", "s-phys-q2" => "", "s-phys-q2" => "1"}, headers:, genders:, survey_items:,
schools: School.school_hash)
values = SurveyItemValues.new(row: { 'RecordedDate' => recorded_date, 'Dese ID' => '1234', 's-sbel-q5' => '1', 's-phys-q2' => '', 's-phys-q3' => '1' }, headers:, genders:, survey_items:,
schools: School.school_hash)
expect(values.valid_sd?).to eq false
end
it "returns false for teacher questions" do
it 'returns false for teacher questions' do
headers = %w[t-sbel-q5 t-phys-q1 t-phys-q2 RecordedDate]
values = SurveyItemValues.new(row: {"RecordedDate" => recorded_date, "Dese ID" => "1234", "t-sbel-q5" => "1", "t-phys-q2" => "", "t-phys-q2" => "1"}, headers:, genders:, survey_items:,
schools: School.school_hash)
values = SurveyItemValues.new(row: { 'RecordedDate' => recorded_date, 'Dese ID' => '1234', 't-sbel-q5' => '1', 't-phys-q2' => '', 't-phys-q3' => '1' }, headers:, genders:, survey_items:,
schools: School.school_hash)
expect(values.valid_sd?).to eq false
end
end

@ -97,6 +97,7 @@ describe SurveyResponsesDataLoader do
it "ensures teacher responses load correctly" do
assigns_academic_year_to_survey_item_responses
assigns_school_to_the_survey_item_responses
assigns_recorded_date_to_teacher_responses
loads_survey_item_responses_for_a_given_survey_response
loads_all_survey_item_responses_for_a_given_survey_item
captures_likert_scores_for_survey_item_responses
@ -112,6 +113,7 @@ describe SurveyResponsesDataLoader do
it "ensures student responses load correctly" do
assigns_academic_year_to_student_survey_item_responses
assigns_school_to_student_survey_item_responses
assigns_recorded_date_to_student_responses
loads_student_survey_item_response_values
student_survey_item_response_count_matches_expected
captures_likert_scores_for_student_survey_item_responses
@ -298,3 +300,24 @@ def assigns_gender_to_responses
end
end
def assigns_recorded_date_to_student_responses
results = {"student_survey_response_1" => "2020-09-30T18:48:50",
"student_survey_response_3" => "2021-03-31T09:59:02",
"student_survey_response_4" => "2021-03-31T10:00:17",
"student_survey_response_5" => "2021-03-31T10:01:36",
"student_survey_response_6" => "2021-03-31T10:01:37",
"student_survey_response_7" => "2021-03-31T10:01:38"}
results.each do |key, value|
expect(SurveyItemResponse.find_by_response_id(key).recorded_date).to eq Date.parse(value)
end
end
def assigns_recorded_date_to_teacher_responses
results = {"teacher_survey_response_1" => "2020-10-16 11:09:03",
"teacher_survey_response_3" => "2020-12-06 8:36:52",
"teacher_survey_response_4" => "2020-12-06 8:51:25",
"teacher_survey_response_5" => "2020-12-06 8:55:58"}
results.each do |key, value|
expect(SurveyItemResponse.find_by_response_id(key).recorded_date).to eq Date.parse(value)
end
end

@ -1,40 +1,40 @@
require 'rails_helper'
require "rails_helper"
include AnalyzeHelper
describe 'District Admin', js: true do
let(:district) { District.find_by_slug 'winchester' }
let(:different_district) { District.find_by_slug 'wareham' }
let(:school) { School.find_by_slug 'winchester-high-school' }
let(:school_in_same_district) { School.find_by_slug 'muraco-elementary-school' }
let(:first_school_in_wareham) { School.find_by_slug 'john-william-decas-elementary-school' }
let(:category) { Category.find_by_name('Teachers & Leadership') }
let(:different_category) { Category.find_by_name('School Culture') }
let(:subcategory) { Subcategory.find_by_name('Teachers & The Teaching Environment') }
let(:different_subcategory) { Subcategory.find_by_name('Relationships') }
describe "District Admin", js: true do
let(:district) { District.find_by_slug "winchester" }
let(:different_district) { District.find_by_slug "wareham" }
let(:school) { School.find_by_slug "winchester-high-school" }
let(:school_in_same_district) { School.find_by_slug "muraco-elementary-school" }
let(:first_school_in_wareham) { School.find_by_slug "john-william-decas-elementary-school" }
let(:category) { Category.find_by_name("Teachers & Leadership") }
let(:different_category) { Category.find_by_name("School Culture") }
let(:subcategory) { Subcategory.find_by_name("Teachers & The Teaching Environment") }
let(:different_subcategory) { Subcategory.find_by_name("Relationships") }
let(:measures_for_subcategory) { Measure.where(subcategory:) }
let(:scales_for_subcategory) { Scale.where(measure: measures_for_subcategory) }
let(:survey_items_for_subcategory) { SurveyItem.where(scale: scales_for_subcategory) }
let(:measure_1A_i) { Measure.find_by_measure_id('1A-i') }
let(:measure_2A_i) { Measure.find_by_measure_id('2A-i') }
let(:measure_2A_ii) { Measure.find_by_measure_id('2A-ii') }
let(:measure_4C_i) { Measure.find_by_measure_id('4C-i') }
let(:measure_with_no_survey_responses) { Measure.find_by_measure_id('3A-i') }
let(:measure_1A_i) { Measure.find_by_measure_id("1A-i") }
let(:measure_2A_i) { Measure.find_by_measure_id("2A-i") }
let(:measure_2A_ii) { Measure.find_by_measure_id("2A-ii") }
let(:measure_4C_i) { Measure.find_by_measure_id("4C-i") }
let(:measure_with_no_survey_responses) { Measure.find_by_measure_id("3A-i") }
let(:survey_items_for_measure_1A_i) { measure_1A_i.survey_items }
let(:survey_items_for_measure_2A_i) { measure_2A_i.survey_items }
let(:survey_items_for_measure_2A_ii) { measure_2A_ii.survey_items }
let(:survey_items_for_measure_4C_i) { measure_4C_i.survey_items }
let(:ay_2021_22) { AcademicYear.find_by_range '2021-22' }
let(:ay_2019_20) { AcademicYear.find_by_range '2019-20' }
let(:ay_2021_22) { AcademicYear.find_by_range "2021-22" }
let(:ay_2019_20) { AcademicYear.find_by_range "2019-20" }
let(:response_rates) do
[ay_2021_22, ay_2019_20].each do |academic_year|
[school, school_in_same_district, first_school_in_wareham].each do |school|
[subcategory, different_subcategory].each do |subcategory|
ResponseRate.create!(subcategory:, school:, academic_year:, student_response_rate: 100, teacher_response_rate: 100,
meets_student_threshold: true, meets_teacher_threshold: true)
meets_student_threshold: true, meets_teacher_threshold: true)
end
end
end
@ -66,35 +66,35 @@ describe 'District Admin', js: true do
survey_items_for_measure_1A_i.each do |survey_item|
SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD.times do
survey_item_responses << SurveyItemResponse.new(response_id: rand.to_s, academic_year: ay_2021_22,
school:, survey_item:, likert_score: 4)
school:, survey_item:, likert_score: 4)
end
end
survey_items_for_measure_2A_i.each do |survey_item|
SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD.times do
survey_item_responses << SurveyItemResponse.new(response_id: rand.to_s, academic_year: ay_2021_22,
school:, survey_item:, likert_score: 5, grade: 1)
school:, survey_item:, likert_score: 5, grade: 1)
end
end
survey_items_for_measure_2A_ii.each do |survey_item|
SurveyItemResponse::STUDENT_RESPONSE_THRESHOLD.times do
survey_item_responses << SurveyItemResponse.new(response_id: rand.to_s, academic_year: ay_2021_22,
school:, survey_item:, likert_score: 5, grade: 1)
school:, survey_item:, likert_score: 5, grade: 1)
end
end
survey_items_for_measure_4C_i.each do |survey_item|
SurveyItemResponse::TEACHER_RESPONSE_THRESHOLD.times do
survey_item_responses << SurveyItemResponse.new(response_id: rand.to_s, academic_year: ay_2021_22,
school:, survey_item:, likert_score: 1, grade: 1)
school:, survey_item:, likert_score: 1, grade: 1)
end
end
survey_items_for_subcategory.each do |survey_item|
2.times do
survey_item_responses << SurveyItemResponse.new(response_id: rand.to_s, academic_year: ay_2021_22,
school:, survey_item:, likert_score: 4, grade: 1)
school:, survey_item:, likert_score: 4, grade: 1)
end
end
@ -105,22 +105,22 @@ describe 'District Admin', js: true do
DatabaseCleaner.clean
end
it 'navigates through the site' do
it "navigates through the site" do
# page.driver.basic_authorize(username, password)
visit '/welcome'
expect(page).to have_text('Teachers & Leadership')
visit "/welcome"
expect(page).to have_text("Teachers & Leadership")
go_to_school_overview_from_welcome_page(district, school)
district_admin_sees_overview_content
click_on 'Teachers & Leadership'
click_on "Teachers & Leadership"
district_admin_sees_browse_content
click_on 'Overview'
click_on "Overview"
district_admin_sees_overview_content
click_on 'Analyze'
click_on "Analyze"
district_admin_sees_analyze_content
go_to_different_category(different_category)
@ -129,11 +129,11 @@ describe 'District Admin', js: true do
go_to_different_subcategory(different_subcategory)
district_admin_sees_subcategory_change
click_on 'Browse'
click_on "Browse"
district_admin_sees_browse_content
click_on 'School Culture'
expect(page).to have_text('Measures the degree to which the school environment is safe, caring, and academically-oriented. It considers factors like bullying, student-teacher relationships, and student valuing of learning.')
click_on "School Culture"
expect(page).to have_text("Measures the degree to which the school environment is safe, caring, and academically-oriented. It considers factors like bullying, student-teacher relationships, and student valuing of learning.")
go_to_different_school_in_same_district(school_in_same_district)
district_admin_sees_schools_change
@ -149,7 +149,7 @@ end
private
def district_admin_sees_professional_qualifications
expect(page).to have_text('Professional Qualifications')
expect(page).to have_text("Professional Qualifications")
expect(page).to have_css("[data-for-measure-id='1A-i']")
# TODO: cutpoints in source of truth have changed so the cutpoints have moved and '2.99%' is no longer a valid value for this cutpoint.
@ -157,39 +157,40 @@ def district_admin_sees_professional_qualifications
end
def district_admin_sees_student_physical_safety
expect(page).to have_text('Student Physical Safety')
expect(page).to have_text("Student Physical Safety")
expect(page).to have_css("[data-for-measure-id='2A-i'][width='40.0%'][x='60%']")
end
def district_admin_sees_problem_solving_emphasis
expect(page).to have_text('Problem Solving')
expect(page).to have_text("Problem Solving")
expect(page).to have_css("[data-for-measure-id='4C-i'][width='60.0%'][x='0.0%']")
end
def go_to_school_overview_from_welcome_page(district, school)
expect(page).to have_select('district', selected: 'Select a District')
select district.name, from: 'district-dropdown'
expect(page).to have_select('school', selected: 'Select a School')
select school.name, from: 'school-dropdown'
expect(page).to have_select('school', selected: 'Winchester High School')
expect(page).to have_select("district", selected: "Select a District")
select district.name, from: "district-dropdown"
expect(page).to have_select("school", selected: "Select a School")
select school.name, from: "school-dropdown"
expect(page).to have_select("school", selected: "Winchester High School")
click_on 'Go'
click_on "Go"
end
def go_to_different_school_in_same_district(school)
select school.name, from: 'select-school'
select school.name, from: "select-school"
end
def go_to_different_district(district)
select district.name, from: 'select-district'
select district.name, from: "select-district"
end
def go_to_different_year(year)
select year.formatted_range, from: 'select-academic-year'
select year.formatted_range, from: "select-academic-year"
end
def got_to_analyze_page; end
def got_to_analyze_page
end
def district_admin_sees_schools_change
expected_path = "/districts/#{school_in_same_district.district.slug}/schools/#{school_in_same_district.slug}/browse/teachers-and-leadership?year=#{ay_2021_22.range}"
@ -207,39 +208,39 @@ def district_admin_sees_year_change
end
def district_admin_sees_overview_content
expect(page).to have_select('academic-year', selected: '2021 2022')
expect(page).to have_select('district', selected: 'Winchester')
expect(page).to have_select('school', selected: 'Winchester High School')
expect(page).to have_select("academic-year", selected: "2021 2022")
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
page.assert_selector('.measure-row-bar', count: 6)
page.assert_selector(".measure-row-bar", count: 6)
end
def district_admin_sees_browse_content
expect(page).to have_text('Teachers & Leadership')
expect(page).to have_text('Approval')
expect(page).to have_text("Teachers & Leadership")
expect(page).to have_text("Approval")
end
def district_admin_sees_analyze_content
expect(page).to have_text('1:Teachers & Leadership > 1A:Teachers & The Teaching Environment')
expect(page).to have_text("1:Teachers & Leadership > 1A:Teachers & The Teaching Environment")
end
def go_to_different_category(category)
select category.name, from: 'select-category'
select category.name, from: "select-category"
end
def district_admin_sees_category_change
expect(page).to have_text '2A:Safety'
expect(page).to have_text "2A:Safety"
end
def go_to_different_subcategory(subcategory)
select subcategory.name, from: 'select-subcategory'
select subcategory.name, from: "select-subcategory"
end
def district_admin_sees_subcategory_change
expect(page).to have_text('Relationships')
expect(page).to have_text("Relationships")
end

@ -1,42 +1,42 @@
require "rails_helper"
require 'rails_helper'
include VarianceHelper
describe "overview/index" do
describe 'overview/index' do
subject { Nokogiri::HTML(rendered) }
let(:support_for_teaching) do
measure = create(:measure, name: "Support For Teaching Development & Growth", measure_id: "1")
measure = create(:measure, name: 'Support For Teaching Development & Growth', measure_id: '1')
scale = create(:scale, measure:)
create(:student_survey_item,
scale:,
watch_low_benchmark: 1.5,
growth_low_benchmark: 2.5,
approval_low_benchmark: 3.5,
ideal_low_benchmark: 4.5)
scale:,
watch_low_benchmark: 1.5,
growth_low_benchmark: 2.5,
approval_low_benchmark: 3.5,
ideal_low_benchmark: 4.5)
measure
end
let(:effective_leadership) do
measure = create(:measure, name: "Effective Leadership", measure_id: "2")
measure = create(:measure, name: 'Effective Leadership', measure_id: '2')
scale = create(:scale, measure:)
create(:teacher_survey_item,
scale:,
watch_low_benchmark: 1.5,
growth_low_benchmark: 2.5,
approval_low_benchmark: 3.5,
ideal_low_benchmark: 4.5)
scale:,
watch_low_benchmark: 1.5,
growth_low_benchmark: 2.5,
approval_low_benchmark: 3.5,
ideal_low_benchmark: 4.5)
measure
end
let(:professional_qualifications) do
measure = create(:measure, name: "Professional Qualifications", measure_id: "3")
measure = create(:measure, name: 'Professional Qualifications', measure_id: '3')
scale = create(:scale, measure:)
create(:admin_data_item,
scale:,
watch_low_benchmark: 1.5,
growth_low_benchmark: 2.5,
approval_low_benchmark: 3.5,
ideal_low_benchmark: 4.5)
scale:,
watch_low_benchmark: 1.5,
growth_low_benchmark: 2.5,
approval_low_benchmark: 3.5,
ideal_low_benchmark: 4.5)
measure
end
@ -47,14 +47,19 @@ describe "overview/index" do
assign :academic_years, [@academic_year]
@district = create(:district)
@school = create(:school)
@student_response_rate_presenter = ResponseRatePresenter.new(focus: :student, school: @school,
academic_year: @academic_year)
@teacher_response_rate_presenter = ResponseRatePresenter.new(focus: :teacher, school: @school,
academic_year: @academic_year)
Respondent.create!(school: @school, academic_year: @academic_year, total_students: 40, total_teachers: 40)
ResponseRate.create!(subcategory: Subcategory.first, school: @school, academic_year: @academic_year,
student_response_rate: 100, teacher_response_rate: 100, meets_student_threshold: true, meets_teacher_threshold: true)
student_response_rate: 100, teacher_response_rate: 100, meets_student_threshold: true, meets_teacher_threshold: true)
render
end
context "when some presenters have a nil score" do
context 'when some presenters have a nil score' do
let(:variance_chart_row_presenters) do
[
VarianceChartRowPresenter.new(measure: support_for_teaching, score: Score.new),
@ -63,49 +68,49 @@ describe "overview/index" do
]
end
it "displays a note detailing which measures have insufficient responses for the given school & academic year" do
it 'displays a note detailing which measures have insufficient responses for the given school & academic year' do
expect(rendered).to match %r{Note: The following measures are not displayed due to limited availability of school data and/or low survey response rates: Support For Teaching Development &amp; Growth; Professional Qualifications.}
end
it "displays a variance row and label only those presenters for which the score is not nil" do
displayed_variance_rows = subject.css("[data-for-measure-id]")
it 'displays a variance row and label only those presenters for which the score is not nil' do
displayed_variance_rows = subject.css('[data-for-measure-id]')
expect(displayed_variance_rows.count).to eq 1
expect(displayed_variance_rows.first.attribute("data-for-measure-id").value).to eq "2"
expect(displayed_variance_rows.first.attribute('data-for-measure-id').value).to eq '2'
displayed_variance_labels = subject.css("[data-variance-row-label]")
displayed_variance_labels = subject.css('[data-variance-row-label]')
expect(displayed_variance_labels.count).to eq 1
expect(displayed_variance_labels.first.inner_text).to include "Effective Leadership"
expect(displayed_variance_labels.first.inner_text).to include 'Effective Leadership'
end
end
context "when all the presenters have a non-nil score" do
context 'when all the presenters have a non-nil score' do
let(:variance_chart_row_presenters) do
measure = create(:measure, name: "Display Me", measure_id: "display-me")
measure = create(:measure, name: 'Display Me', measure_id: 'display-me')
scale = create(:scale, measure:)
create(:student_survey_item,
scale:,
watch_low_benchmark: 1.5,
growth_low_benchmark: 2.5,
approval_low_benchmark: 3.5,
ideal_low_benchmark: 4.5)
scale:,
watch_low_benchmark: 1.5,
growth_low_benchmark: 2.5,
approval_low_benchmark: 3.5,
ideal_low_benchmark: 4.5)
[
VarianceChartRowPresenter.new(measure:,
score: Score.new(average: rand))
score: Score.new(average: rand))
]
end
it "does not display a note detailing which measures have insufficient responses for the given school & academic year" do
it 'does not display a note detailing which measures have insufficient responses for the given school & academic year' do
expect(rendered).not_to match %r{Note: The following measures are not displayed due to limited availability of school data and/or low survey response rates}
end
it "displays a variance row for each presenter" do
displayed_variance_rows = subject.css("[data-for-measure-id]")
it 'displays a variance row for each presenter' do
displayed_variance_rows = subject.css('[data-for-measure-id]')
expect(displayed_variance_rows.count).to eq 1
expect(displayed_variance_rows.first.attribute("data-for-measure-id").value).to eq "display-me"
expect(displayed_variance_rows.first.attribute('data-for-measure-id').value).to eq 'display-me'
displayed_variance_labels = subject.css("[data-variance-row-label]")
displayed_variance_labels = subject.css('[data-variance-row-label]')
expect(displayed_variance_labels.count).to eq 1
expect(displayed_variance_labels.first.inner_text).to include "Display Me"
expect(displayed_variance_labels.first.inner_text).to include 'Display Me'
end
end
end

Loading…
Cancel
Save