From 50256cacceacb7c5a9ff799d48404e7b78ce753e Mon Sep 17 00:00:00 2001 From: rebuilt Date: Fri, 3 Jun 2022 04:30:55 +0200 Subject: [PATCH] Create academic year checkbox selectors. Refresh page with years selected on checkbox change. Draw bar graphs for each academic year selected. Center bar graphs in their column. Color the columns to match the sample colors on the checkboxes. Add scores on beta to top of graph. Automatically display the most recent year of data for the district. Modify logic for the insufficient data message or the 'measure not based on student/teacher surveys' message so it only shows if there are no bars with data to display. --- app/helpers/analyze_helper.rb | 18 +- app/helpers/color_helper.rb | 2 + app/models/measure.rb | 14 +- app/models/scale.rb | 2 +- app/models/subcategory.rb | 4 +- app/models/survey_item.rb | 7 +- app/presenters/analyze_bar_presenter.rb | 63 ++++++ .../grouped_bar_column_presenter.rb | 118 ++++++---- .../student_grouped_bar_column_presenter.rb | 12 +- .../teacher_grouped_bar_column_presenter.rb | 12 +- app/views/analyze/_grouped_bar_chart.html.erb | 15 +- .../analyze/_grouped_bar_column.html.erb | 35 +-- app/views/analyze/index.html.erb | 4 +- .../grouped_bar_column_presenter_spec.rb | 212 ++++++++++++------ spec/views/analyze/index.html.erb_spec.rb | 7 +- 15 files changed, 353 insertions(+), 172 deletions(-) create mode 100644 app/helpers/color_helper.rb create mode 100644 app/presenters/analyze_bar_presenter.rb diff --git a/app/helpers/analyze_helper.rb b/app/helpers/analyze_helper.rb index 9a6968af..5ec40629 100644 --- a/app/helpers/analyze_helper.rb +++ b/app/helpers/analyze_helper.rb @@ -27,20 +27,20 @@ module AnalyzeHelper 1 end - def grouped_chart_width + def grouped_chart_column_width graph_width / data_sources end - def grouped_chart_divider_x(position) - zone_label_width + (grouped_chart_width * position) + def column_end_x(position) + zone_label_width + (grouped_chart_column_width * position) end - def bar_label_height - (100 - ((100 - analyze_graph_height) / 2)) + def column_start_x(position) + column_end_x(position - 1) end - def bar_label_x(position) - zone_label_width + (grouped_chart_width * position) - (grouped_chart_width / 2) + def bar_label_height + (100 - ((100 - analyze_graph_height) / 2)) end def analyze_zone_height @@ -66,4 +66,8 @@ module AnalyzeHelper def analyze_subcategory_link(district:, school:, academic_year:, category:, subcategory:) "/districts/#{district.slug}/schools/#{school.slug}/analyze?year=#{academic_year.range}&category=#{category.category_id}&subcategory=#{subcategory.subcategory_id}" end + + def colors + @colors ||= ['#49416D', '#FFC857', '#920020', '#00B0B3', '#B2D236', '#595959'] + end end diff --git a/app/helpers/color_helper.rb b/app/helpers/color_helper.rb new file mode 100644 index 00000000..8acffe49 --- /dev/null +++ b/app/helpers/color_helper.rb @@ -0,0 +1,2 @@ +module ColorHelper +end diff --git a/app/models/measure.rb b/app/models/measure.rb index 5eb54800..6a0da1b5 100644 --- a/app/models/measure.rb +++ b/app/models/measure.rb @@ -47,7 +47,7 @@ class Measure < ActiveRecord::Base end def score(school:, academic_year:) - @score ||= Hash.new do |memo| + @score ||= Hash.new do |memo, (school, academic_year)| meets_student_threshold = sufficient_student_data?(school:, academic_year:) meets_teacher_threshold = sufficient_teacher_data?(school:, academic_year:) meets_admin_data_threshold = all_admin_data_collected?(school:, academic_year:) @@ -73,23 +73,27 @@ class Measure < ActiveRecord::Base end def student_score(school:, academic_year:) - @student_score ||= begin + @student_score ||= Hash.new do |memo, (school, academic_year)| meets_student_threshold = sufficient_student_data?(school:, academic_year:) meets_teacher_threshold = sufficient_teacher_data?(school:, academic_year:) meets_admin_data_threshold = all_admin_data_collected?(school:, academic_year:) average = collect_survey_scale_average(student_scales, school, academic_year) if meets_student_threshold - Score.new(average, meets_teacher_threshold, meets_student_threshold, meets_admin_data_threshold) + memo[[school, academic_year]] = Score.new(average, meets_teacher_threshold, meets_student_threshold, meets_admin_data_threshold) end + + @student_score[[school, academic_year]] end def teacher_score(school:, academic_year:) - @teacher_score ||= begin + @teacher_score ||= Hash.new do |memo, (school, academic_year)| meets_student_threshold = sufficient_student_data?(school:, academic_year:) meets_teacher_threshold = sufficient_teacher_data?(school:, academic_year:) meets_admin_data_threshold = all_admin_data_collected?(school:, academic_year:) average = collect_survey_scale_average(teacher_scales, school, academic_year) if meets_teacher_threshold - Score.new(average, meets_teacher_threshold, meets_student_threshold, meets_admin_data_threshold) + memo[[school, academic_year]] = Score.new(average, meets_teacher_threshold, meets_student_threshold, meets_admin_data_threshold) end + + @teacher_score[[school, academic_year]] end def warning_low_benchmark diff --git a/app/models/scale.rb b/app/models/scale.rb index 98a2d596..7a6415d3 100644 --- a/app/models/scale.rb +++ b/app/models/scale.rb @@ -5,7 +5,7 @@ class Scale < ApplicationRecord has_many :admin_data_items def score(school:, academic_year:) - @score ||= Hash.new do |memo| + @score ||= Hash.new do |memo, (school, academic_year)| memo[[school, academic_year]] = begin items = [] items << collect_survey_item_average(student_survey_items(school:, academic_year:), school, academic_year) diff --git a/app/models/subcategory.rb b/app/models/subcategory.rb index 975e9607..0fcb44d0 100644 --- a/app/models/subcategory.rb +++ b/app/models/subcategory.rb @@ -12,7 +12,7 @@ class Subcategory < ActiveRecord::Base end def student_response_rate(school:, academic_year:) - @student_response_rate ||= Hash.new do |memo| + @student_response_rate ||= Hash.new do |memo, (school, academic_year)| memo[[school, academic_year]] = StudentResponseRate.new(subcategory: self, school:, academic_year:) end @@ -20,7 +20,7 @@ class Subcategory < ActiveRecord::Base end def teacher_response_rate(school:, academic_year:) - @teacher_response_rate ||= Hash.new do |memo| + @teacher_response_rate ||= Hash.new do |memo, (school, academic_year)| memo[[school, academic_year]] = TeacherResponseRate.new(subcategory: self, school:, academic_year:) end diff --git a/app/models/survey_item.rb b/app/models/survey_item.rb index 243b83ce..944d35a9 100644 --- a/app/models/survey_item.rb +++ b/app/models/survey_item.rb @@ -6,11 +6,10 @@ class SurveyItem < ActiveRecord::Base has_many :survey_item_responses def score(school:, academic_year:) - @score ||= Hash.new do |memo| - memo[[school, academic_year]] = survey_item_responses.where(school:, - academic_year:).exclude_boston.average(:likert_score).to_f + @score ||= Hash.new do |memo, (school, academic_year)| + memo[[school, academic_year]] = + survey_item_responses.exclude_boston.where(school:, academic_year:).average(:likert_score).to_f end - @score[[school, academic_year]] end diff --git a/app/presenters/analyze_bar_presenter.rb b/app/presenters/analyze_bar_presenter.rb new file mode 100644 index 00000000..aeef2908 --- /dev/null +++ b/app/presenters/analyze_bar_presenter.rb @@ -0,0 +1,63 @@ +class AnalyzeBarPresenter + include AnalyzeHelper + attr_reader :score, :x_position, :academic_year, :measure_id, :measure, :color + + def initialize(measure:, academic_year:, score:, x_position:, color:) + @score = score + @x_position = x_position + @academic_year = academic_year + @measure = measure + @measure_id = measure.measure_id + @color = color + end + + def y_offset + case zone.type + when :ideal, :approval + (analyze_zone_height * 2) - bar_height_percentage + else + (analyze_zone_height * 2) + end + end + + def bar_color + "fill-#{zone.type}" + end + + def bar_height_percentage + case zone.type + when :ideal + (percentage * zone_height_percentage + zone_height_percentage) * 100 + when :approval + (percentage * zone_height_percentage) * 100 + when :growth + ((1 - percentage) * zone_height_percentage) * 100 + when :watch + ((1 - percentage) * zone_height_percentage + zone_height_percentage) * 100 + when :warning + ((1 - percentage) * zone_height_percentage + zone_height_percentage + zone_height_percentage) * 100 + else + 0.0 + end + end + + def percentage + (score.average - zone.low_benchmark) / (zone.high_benchmark - zone.low_benchmark) + end + + def zone + zones = Zones.new( + watch_low_benchmark: measure.watch_low_benchmark, + growth_low_benchmark: measure.growth_low_benchmark, + approval_low_benchmark: measure.approval_low_benchmark, + ideal_low_benchmark: measure.ideal_low_benchmark + ) + zones.zone_for_score(score.average) + end + + def average + return 0 if score.average.nil? + + score.average.round(2) + end +end diff --git a/app/presenters/grouped_bar_column_presenter.rb b/app/presenters/grouped_bar_column_presenter.rb index d3e94346..e75795b8 100644 --- a/app/presenters/grouped_bar_column_presenter.rb +++ b/app/presenters/grouped_bar_column_presenter.rb @@ -1,78 +1,102 @@ class GroupedBarColumnPresenter include AnalyzeHelper - attr_reader :score, :measure_name, :measure_id, :category, :position, :measure, :school, :academic_year + include ColorHelper - def initialize(measure:, school:, academic_year:, position:) + attr_reader :measure_name, :measure_id, :category, :position, :measure, :school, :academic_years + + def initialize(measure:, school:, academic_years:, position:) @measure = measure @measure_name = @measure.name @measure_id = @measure.measure_id @category = @measure.subcategory.category @school = school - @academic_year = academic_year + @academic_years = academic_years @position = position end - def score - measure.score(school:, academic_year:) + def score(year_index) + measure.score(school:, academic_year: academic_years[year_index]) end - def y_offset - case zone.type - when :ideal, :approval - (analyze_zone_height * 2) - bar_height_percentage - else - (analyze_zone_height * 2) + def bars + @bars ||= yearly_scores.map.each_with_index do |item, index| + year = item[0] + score = item[1] + AnalyzeBarPresenter.new(measure:, academic_year: year, score:, x_position: bar_x(index), + color: bar_color(year)) end end - def bar_color - "fill-#{zone.type}" - end - - def bar_height_percentage - case zone.type - when :ideal - (percentage * zone_height_percentage + zone_height_percentage) * 100 - when :approval - (percentage * zone_height_percentage) * 100 - when :growth - ((1 - percentage) * zone_height_percentage) * 100 - when :watch - ((1 - percentage) * zone_height_percentage + zone_height_percentage) * 100 - when :warning - ((1 - percentage) * zone_height_percentage + zone_height_percentage + zone_height_percentage) * 100 - else - 0.0 + def label + 'All Survey Data' + end + + def basis + '' + end + + def show_irrelevancy_message? + !measure.includes_teacher_survey_items? && !measure.includes_student_survey_items? + end + + def show_insufficient_data_message? + scores = academic_years.map do |year| + measure.score(school:, academic_year: year) end + + scores.all? { |score| !score.meets_teacher_threshold? && !score.meets_student_threshold? } end - def percentage - (score.average - zone.low_benchmark) / (zone.high_benchmark - zone.low_benchmark) + def column_midpoint + zone_label_width + (grouped_chart_column_width * (position + 1)) - (grouped_chart_column_width / 2) end - def zone - zones = Zones.new( - watch_low_benchmark: @measure.watch_low_benchmark, - growth_low_benchmark: @measure.growth_low_benchmark, - approval_low_benchmark: @measure.approval_low_benchmark, - ideal_low_benchmark: @measure.ideal_low_benchmark - ) - zones.zone_for_score(score.average) + def bar_width + 3.5 end - def label - 'All Survey Data' + def message_x + column_midpoint - message_width / 2 end - def basis - '' + def message_y + 17 end - def show_irrelevancy_message? - !@measure.includes_teacher_survey_items? && !@measure.includes_student_survey_items? + def message_width + 20 end - def show_insufficient_data_message? - !score.meets_teacher_threshold? && !score.meets_student_threshold? + def message_height + 34 + end + + def column_end_x + zone_label_width + (grouped_chart_column_width * (position + 1)) + end + + def column_start_x + zone_label_width + (grouped_chart_column_width * position) + end + + private + + def yearly_scores + yearly_scores = academic_years.each_with_index.map do |year, index| + [year, score(index)] + end + yearly_scores.reject do |yearly_score| + score = yearly_score[1] + score.average.nil? || score.average.zero? || score.average.nan? + end + end + + def bar_color(year) + @available_academic_years ||= AcademicYear.order(:range).all + colors[@available_academic_years.find_index(year)] + end + + def bar_x(index) + column_start_x + (index * bar_width * 1.2) + ((column_end_x - column_start_x) - (yearly_scores.size * bar_width * 1.2)) / 2 end end diff --git a/app/presenters/student_grouped_bar_column_presenter.rb b/app/presenters/student_grouped_bar_column_presenter.rb index edf3267e..1d4f3a94 100644 --- a/app/presenters/student_grouped_bar_column_presenter.rb +++ b/app/presenters/student_grouped_bar_column_presenter.rb @@ -8,14 +8,18 @@ class StudentGroupedBarColumnPresenter < GroupedBarColumnPresenter end def show_irrelevancy_message? - !@measure.includes_student_survey_items? + !measure.includes_student_survey_items? end def show_insufficient_data_message? - !score.meets_student_threshold? + scores = academic_years.map do |year| + measure.score(school:, academic_year: year) + end + + scores.all? { |score| !score.meets_student_threshold? } end - def score - measure.student_score(school:, academic_year:) + def score(year_index) + measure.student_score(school:, academic_year: academic_years[year_index]) end end diff --git a/app/presenters/teacher_grouped_bar_column_presenter.rb b/app/presenters/teacher_grouped_bar_column_presenter.rb index c43883f4..85f1f40b 100644 --- a/app/presenters/teacher_grouped_bar_column_presenter.rb +++ b/app/presenters/teacher_grouped_bar_column_presenter.rb @@ -8,14 +8,18 @@ class TeacherGroupedBarColumnPresenter < GroupedBarColumnPresenter end def show_irrelevancy_message? - !@measure.includes_teacher_survey_items? + !measure.includes_teacher_survey_items? end def show_insufficient_data_message? - !score.meets_teacher_threshold? + scores = academic_years.map do |year| + measure.score(school:, academic_year: year) + end + + scores.all? { |score| !score.meets_teacher_threshold? } end - def score - measure.teacher_score(school:, academic_year:) + def score(year_index) + measure.teacher_score(school:, academic_year: academic_years[year_index]) end end diff --git a/app/views/analyze/_grouped_bar_chart.html.erb b/app/views/analyze/_grouped_bar_chart.html.erb index 79643a86..acfe5e10 100644 --- a/app/views/analyze/_grouped_bar_chart.html.erb +++ b/app/views/analyze/_grouped_bar_chart.html.erb @@ -3,8 +3,8 @@ - - + + @@ -31,11 +31,10 @@ -<% presenter = StudentGroupedBarColumnPresenter.new(measure: measure, school: @school, academic_year: @academic_year, position: 1) %> - <%= render partial: "grouped_bar_column", locals: {presenter: presenter} %> -<% presenter = TeacherGroupedBarColumnPresenter.new(measure: measure, school: @school, academic_year: @academic_year, position: 2) %> - <%= render partial: "grouped_bar_column", locals: {presenter: presenter} %> -<% presenter = GroupedBarColumnPresenter.new(measure: measure, school: @school, academic_year: @academic_year, position: 3) %> - <%= render partial: "grouped_bar_column", locals: {presenter: presenter} %> + <% presenters = [StudentGroupedBarColumnPresenter, TeacherGroupedBarColumnPresenter, GroupedBarColumnPresenter] %> + <% presenters.each_with_index do |presenter, index| %> + <% p = presenter.new(measure: measure, school: @school, academic_years: @selected_academic_years, position: index ) %> + <%= render partial: "grouped_bar_column", locals: {presenter: p} %> + <% end %> diff --git a/app/views/analyze/_grouped_bar_column.html.erb b/app/views/analyze/_grouped_bar_column.html.erb index 4b3666e9..63d0f00e 100644 --- a/app/views/analyze/_grouped_bar_column.html.erb +++ b/app/views/analyze/_grouped_bar_column.html.erb @@ -1,30 +1,33 @@ - - + + <% presenter.bars.each_with_index do |bar, index| %> + - <% if ENV["SCORES"].present? && ENV["SCORES"].upcase == "SHOW" %> - - <%= presenter.score.average %> - + <% if ENV["SCORES"].present? && ENV["SCORES"].upcase == "SHOW" %> + + <%= bar.average %> + + <% end %> <% end %> - + + <%= presenter.label %> <% if presenter.show_irrelevancy_message? %> - + - - measure not - based on - <%= presenter.basis %> surveys + + measure not + based on + <%= presenter.basis %> surveys <% elsif presenter.show_insufficient_data_message? %> - + - - survey response - rate below 25% + + survey response + rate below 25% <% end %> diff --git a/app/views/analyze/index.html.erb b/app/views/analyze/index.html.erb index 1581fdcf..4a408894 100644 --- a/app/views/analyze/index.html.erb +++ b/app/views/analyze/index.html.erb @@ -25,11 +25,11 @@

School Years

- <% @available_academic_years.each do | year | %> + <% @available_academic_years.each_with_index do | year, index | %>
data-action="click->analyze#refresh">
-
+
<% end %> diff --git a/spec/presenters/grouped_bar_column_presenter_spec.rb b/spec/presenters/grouped_bar_column_presenter_spec.rb index de690588..23d02572 100644 --- a/spec/presenters/grouped_bar_column_presenter_spec.rb +++ b/spec/presenters/grouped_bar_column_presenter_spec.rb @@ -1,8 +1,12 @@ require 'rails_helper' +include AnalyzeHelper describe GroupedBarColumnPresenter do let(:school) { create(:school) } - let(:academic_year) { create(:academic_year) } + let(:academic_year) { create(:academic_year, range: '1900-01') } + let(:another_academic_year) { create(:academic_year, range: '2000-01') } + let(:academic_years) { [academic_year, another_academic_year] } + let(:year_index) { academic_years.find_index(academic_year) } let(:watch_low_benchmark) { 2 } let(:growth_low_benchmark) { 3 } let(:approval_low_benchmark) { 4 } @@ -58,18 +62,18 @@ describe GroupedBarColumnPresenter do end let(:student_presenter) do - StudentGroupedBarColumnPresenter.new measure: measure_with_student_survey_items, school:, academic_year:, - position: 1 + StudentGroupedBarColumnPresenter.new measure: measure_with_student_survey_items, school:, academic_years:, + position: 0 end let(:teacher_presenter) do - TeacherGroupedBarColumnPresenter.new measure: measure_with_teacher_survey_items, school:, academic_year:, - position: 1 + TeacherGroupedBarColumnPresenter.new measure: measure_with_teacher_survey_items, school:, academic_years:, + position: 0 end let(:all_data_presenter) do - GroupedBarColumnPresenter.new measure: measure_composed_of_student_and_teacher_items, school:, academic_year:, - position: 1 + GroupedBarColumnPresenter.new measure: measure_composed_of_student_and_teacher_items, school:, academic_years:, + position: 0 end before do @@ -83,132 +87,198 @@ describe GroupedBarColumnPresenter do end end - context 'when a measure is based on student survey items' do - context 'when the score is in the Ideal zone' do + shared_examples_for 'column_midpoint' do + it 'return an x position centered in the width of the column' do + expect(student_presenter.column_midpoint).to eq 29 + end + end + + shared_examples_for 'bar_color' do + it 'returns the correct color' do + expect(student_presenter.bars[year_index].color).to eq colors[year_index] + end + end + + shared_examples_for 'y_offset' do + it 'bar will be based on the approval low benchmark boundary' do + expect(student_presenter.bars[year_index].y_offset).to be_within(0.01).of(34) + end + end + + context 'for a grouped column presenter with both student and teacher responses' do + context 'with a single year' + before do + create(:survey_item_response, survey_item: student_survey_item_for_composite_measure, school:, + academic_year:, likert_score: 4) + create(:survey_item_response, survey_item: student_survey_item_for_composite_measure, school:, + academic_year:, likert_score: 5) + end + + it 'returns a score that is an average of the likert scores ' do + expect(all_data_presenter.score(0).average).to eq 4.5 + expect(all_data_presenter.score(1).average).to eq nil + expect(all_data_presenter.academic_years[0].range).to be academic_year.range + expect(all_data_presenter.academic_years[1].range).to be another_academic_year.range + end + context 'when more than one year exists' do before do - create(:survey_item_response, survey_item: student_survey_item, school:, - academic_year:, likert_score: 5) - create(:survey_item_response, survey_item: student_survey_item, school:, - academic_year:, likert_score: 4) + create(:survey_item_response, survey_item: student_survey_item_for_composite_measure, school:, + academic_year: another_academic_year, likert_score: 5) + create(:survey_item_response, survey_item: student_survey_item_for_composite_measure, school:, + academic_year: another_academic_year, likert_score: 3) + end + it 'returns independent scores for each year of data' do + expect(all_data_presenter.score(0).average).to eq 4.5 + expect(all_data_presenter.score(1).average).to eq 4 end + end + end + context 'when a measure is based on student survey items' do + before do + year_index = academic_years.find_index(academic_year) + end + + context 'when there is insufficient data to show a score' do it_behaves_like 'measure_name' + it_behaves_like 'column_midpoint' - it 'returns the correct color' do - expect(student_presenter.bar_color).to eq 'fill-ideal' + it 'returns an emtpy set of bars' do + expect(student_presenter.bars).to eq [] end - it 'returns a bar width equal to the approval zone width plus the proportionate ideal zone width' do - expect(student_presenter.bar_height_percentage).to be_within(0.01).of(17) + it 'returns an emty score' do + expect(student_presenter.score(year_index).average).to eq nil end - it 'returns a y_offset equal to the ' do - expect(student_presenter.y_offset).to be_within(0.01).of(17) + it 'shows the irrelevancy message ' do + expect(student_presenter.show_irrelevancy_message?).to eq true + end + + it 'shows the insufficient data message' do + expect(student_presenter.show_insufficient_data_message?).to eq true end end - context 'when the score is in the Approval zone' do + context 'when the score is in the Ideal zone' do before do + create(:survey_item_response, survey_item: student_survey_item, school:, + academic_year:, likert_score: 5) create(:survey_item_response, survey_item: student_survey_item, school:, academic_year:, likert_score: 4) end it_behaves_like 'measure_name' + it_behaves_like 'column_midpoint' + it_behaves_like 'bar_color' - it 'returns the correct color' do - expect(student_presenter.bar_color).to eq 'fill-approval' + it 'returns a bar width equal to the approval zone width plus the proportionate ideal zone width' do + expect(student_presenter.bars[year_index].bar_height_percentage).to be_within(0.01).of(17) end - it 'returns a bar width equal to the proportionate approval zone width' do - expect(student_presenter.bar_height_percentage).to be_within(0.01).of(0) + it 'returns a y_offset equal to the ' do + expect(student_presenter.bars[0].y_offset).to be_within(0.01).of(17) end - it 'returns an x-offset of 60%' do - expect(student_presenter.y_offset).to be_within(0.01).of(34) + it 'returns a text representation of the type of survey the bars are based on' do + expect(student_presenter.basis).to eq 'student' end - end - context 'when the score is in the Growth zone' do - before do - create(:survey_item_response, survey_item: student_survey_item, school:, - academic_year:, likert_score: 3) + it 'returns only bars that have a numeric score' do + expect(student_presenter.bars.count).to be 1 end - it_behaves_like 'measure_name' + it 'returns an explanatory bar label' do + expect(student_presenter.label).to eq 'All Students' + end - it 'returns the correct color' do - expect(student_presenter.bar_color).to eq 'fill-growth' + it 'does not show a message that the data source is irrelevant for this measure' do + expect(student_presenter.show_irrelevancy_message?).to be false end - it 'returns a bar width equal to the proportionate growth zone width' do - expect(student_presenter.bar_height_percentage).to be_within(0.01).of(17) + it 'does not show a message about insufficient responses' do + expect(student_presenter.show_insufficient_data_message?).to be false end - context 'in order to achieve the visual effect' do - it 'returns an x-offset equal to 60% minus the bar width' do - expect(student_presenter.y_offset).to eq 34 + context 'when there is more than one years worth of data to show' do + before do + create(:survey_item_response, survey_item: student_survey_item, school:, + academic_year: another_academic_year, likert_score: 3) + create(:survey_item_response, survey_item: student_survey_item, school:, + academic_year: another_academic_year, likert_score: 4) + end + + it 'returns only bars that have a numeric score' do + expect(student_presenter.bars.count).to be 2 end end end - context 'when the score is in the Watch zone' do + context 'when the score is in the Approval zone' do before do create(:survey_item_response, survey_item: student_survey_item, school:, - academic_year:, likert_score: 2) + academic_year:, likert_score: 4) end it_behaves_like 'measure_name' + it_behaves_like 'column_midpoint' + it_behaves_like 'bar_color' + it_behaves_like 'y_offset' - it 'returns the correct color' do - expect(student_presenter.bar_color).to eq 'fill-watch' - end - - it 'returns a bar width equal to the proportionate watch zone width plus the growth zone width' do - expect(student_presenter.bar_height_percentage).to eq 34 - end + context 'and the score is right at the approval low benchmark' do + it 'bar will have a height of 0' do + expect(student_presenter.bars[year_index].bar_height_percentage).to be_within(0.01).of(0) + end - context 'in order to achieve the visual effect' do - it 'returns an x-offset equal to 60% minus the bar width' do - expect(student_presenter.y_offset).to eq 34 + it 'bar will be based on the approval low benchmark boundary' do + expect(student_presenter.bars[year_index].y_offset).to be_within(0.01).of(34) end end end - - context 'when the score is in the Warning zone' do + context 'when the score is in the Growth zone' do before do create(:survey_item_response, survey_item: student_survey_item, school:, - academic_year:, likert_score: 1) + academic_year:, likert_score: 3) end it_behaves_like 'measure_name' + it_behaves_like 'column_midpoint' + it_behaves_like 'bar_color' + it_behaves_like 'y_offset' - it 'returns the correct color' do - expect(student_presenter.bar_color).to eq 'fill-warning' + it 'returns a bar width equal to the proportionate growth zone width' do + expect(student_presenter.bars[year_index].bar_height_percentage).to be_within(0.01).of(17) end + end - it 'returns a bar width equal to the proportionate warning zone width plus the watch & growth zone widths' do - expect(student_presenter.bar_height_percentage).to eq 51 + context 'when the score is in the Watch zone' do + before do + create(:survey_item_response, survey_item: student_survey_item, school:, + academic_year:, likert_score: 2) end - context 'in order to achieve the visual effect' do - it 'returns an y-offset equal to 60% minus the bar width' do - expect(student_presenter.y_offset).to eq 34 - end - end - end + it_behaves_like 'measure_name' + it_behaves_like 'column_midpoint' + it_behaves_like 'bar_color' + it_behaves_like 'y_offset' - context 'when there are insufficient responses to calculate a score' do - it 'indicates it should show the insufficient data message' do - expect(student_presenter.show_insufficient_data_message?).to eq true + it 'returns a bar width equal to the proportionate watch zone width plus the growth zone width' do + expect(student_presenter.bars[year_index].bar_height_percentage).to eq 34 end end - context 'when there are enough responses to calculate a score' do + context 'when the score is in the Warning zone' do before do create(:survey_item_response, survey_item: student_survey_item, school:, - academic_year:) + academic_year:, likert_score: 1) end - it 'indicates it should show the insufficient data message' do - expect(student_presenter.show_insufficient_data_message?).to eq false + + it_behaves_like 'measure_name' + it_behaves_like 'column_midpoint' + it_behaves_like 'bar_color' + it_behaves_like 'y_offset' + + it 'returns a bar width equal to the proportionate warning zone width plus the watch & growth zone widths' do + expect(student_presenter.bars[year_index].bar_height_percentage).to eq 51 end end end diff --git a/spec/views/analyze/index.html.erb_spec.rb b/spec/views/analyze/index.html.erb_spec.rb index 6d5a1902..8b37c00c 100644 --- a/spec/views/analyze/index.html.erb_spec.rb +++ b/spec/views/analyze/index.html.erb_spec.rb @@ -78,10 +78,15 @@ describe 'analyze/index' do # end it 'displays a set of grouped bars for each presenter' do + displayed_variance_columns = subject.css('.grouped-bar-column') + expect(displayed_variance_columns.count).to eq 9 + displayed_variance_rows = subject.css('[data-for-measure-id]') - expect(displayed_variance_rows.count).to eq 9 expect(displayed_variance_rows.first.attribute('data-for-measure-id').value).to eq '1A-I' + # displayed_variance_rows = subject.css('data-for-academic-year') + # expect(displayed_variance_rows.count).to eq 9 + displayed_variance_labels = subject.css('[data-grouped-bar-label]') expect(displayed_variance_labels.count).to eq 9 expect(displayed_variance_labels.first.inner_text).to include 'All Students'