we have a gauge! next up, let's style the page

pull/1/head
Liam Morley 4 years ago committed by Alex Basson
parent 5d6c1000f4
commit 25578a896f

@ -0,0 +1,9 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_size = 2
indent_style = space
trim_trailing_whitespace = true

@ -54,6 +54,7 @@ gem 'activerecord-import'
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'
end
group :development do

@ -78,6 +78,11 @@ GEM
diff-lcs (1.4.4)
erubi (1.10.0)
execjs (2.8.1)
factory_bot (6.2.0)
activesupport (>= 5.0.0)
factory_bot_rails (6.2.0)
factory_bot (~> 6.2.0)
railties (>= 5.0.0)
ffi (1.15.4)
friendly_id (5.1.0)
activerecord (>= 4.0.0)
@ -258,6 +263,7 @@ DEPENDENCIES
capybara
database_cleaner
devise
factory_bot_rails
friendly_id (~> 5.1.0)
haml
jbuilder (~> 2.5)

@ -17,10 +17,14 @@ $growth: #E0BA9A;
$approval: #D0DD86;
$ideal: #C0FF73;
.red {
.color-red {
color: $red;
}
.color-black {
color: $black;
}
.bg-beige {
background-color: $beige;
}
@ -29,6 +33,10 @@ $ideal: #C0FF73;
background-color: $white;
}
.fill-black {
fill: $black;
}
.fill-warning {
fill: $warning;
}
@ -48,3 +56,15 @@ $ideal: #C0FF73;
.fill-ideal {
fill: $ideal;
}
.stroke-black {
stroke: $black;
}
.stroke-gray-1 {
stroke: $gray-1;
}
.stroke-gray-2 {
stroke: $gray-2;
}

@ -0,0 +1,23 @@
class BrowseController < ApplicationController
def show
@category = CategoryPresenter.new(
category: SqmCategory.find_by_name('Teachers & Leadership'),
academic_year: academic_year,
school: school,
)
end
private
def school
@school ||= School.find_by_slug school_slug
end
def school_slug
params[:school_id]
end
def academic_year
@academic_year ||= AcademicYear.find_by_range params[:year]
end
end

@ -1,44 +1,6 @@
class Measure < ActiveRecord::Base
belongs_to :subcategory
has_many :survey_items
Zone = Struct.new(:low_benchmark, :high_benchmark, :type) do
def includes_score?(score)
score > low_benchmark and score < high_benchmark
end
end
def warning_zone
Zone.new(1, watch_low_benchmark, :warning)
end
def watch_zone
Zone.new(watch_low_benchmark, growth_low_benchmark, :watch)
end
def growth_zone
Zone.new(growth_low_benchmark, approval_low_benchmark, :growth)
end
def approval_zone
Zone.new(approval_low_benchmark, ideal_low_benchmark, :approval)
end
def ideal_zone
Zone.new(ideal_low_benchmark, 5.0, :ideal)
end
def zone_for_score(score)
case score
when ideal_zone.low_benchmark..ideal_zone.high_benchmark
ideal_zone
when approval_zone.low_benchmark..approval_zone.high_benchmark
approval_zone
when growth_zone.low_benchmark..growth_zone.high_benchmark
growth_zone
when watch_zone.low_benchmark..watch_zone.high_benchmark
watch_zone
else
warning_zone
end
end
has_many :survey_item_responses, through: :survey_items
end

@ -1,3 +1,3 @@
class SqmCategory < ActiveRecord::Base
has_many :subcategories
end

@ -1,3 +1,5 @@
class Subcategory < ActiveRecord::Base
belongs_to :sqm_category
has_many :measures
end

@ -1,3 +1,4 @@
class SurveyItem < ActiveRecord::Base
belongs_to :measure
has_many :survey_item_responses
end

@ -2,4 +2,7 @@ class SurveyItemResponse < ActiveRecord::Base
belongs_to :academic_year
belongs_to :school
belongs_to :survey_item
scope :for_measures, ->(measures) { joins(:survey_item).where('survey_items.measure_id': measures.map(&:id)) }
scope :for_measure, ->(measure) { joins(:survey_item).where('survey_items.measure_id': measure.id) }
end

@ -0,0 +1,21 @@
class CategoryPresenter
def initialize(category:, academic_year:, school:)
@category = category
@academic_year = academic_year
@school = school
end
def name
@category.name
end
def subcategories
@category.subcategories.map do |subcategory|
SubcategoryPresenter.new(
subcategory: subcategory,
academic_year: @academic_year,
school: @school,
)
end
end
end

@ -0,0 +1,34 @@
class GaugePresenter
def initialize(scale:, score:)
@scale = scale
@score = score
end
def title
zone.type.to_s.capitalize
end
def color_class
"fill-#{zone.type}"
end
def score_percentage
percentage_for @score
end
def key_benchmark_percentage
percentage_for @scale.approval_zone.low_benchmark
end
private
def zone
@scale.zone_for_score(@score)
end
def percentage_for(number)
scale_minimum = @scale.warning_zone.low_benchmark
scale_maximum = @scale.ideal_zone.high_benchmark
(number - scale_minimum) / (scale_maximum - scale_minimum)
end
end

@ -26,7 +26,7 @@ class MeasureGraphRowPresenter
when :ideal, :approval
"50%"
else
"#{((0.5 - bar_width_percentage) * 100).round(2)}%"
"#{((0.5 - bar_width_percentage) * 100).abs.round(2)}%"
end
end
@ -66,6 +66,12 @@ class MeasureGraphRowPresenter
end
def zone
@measure.zone_for_score(@score)
scale = Scale.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,
)
scale.zone_for_score(@score)
end
end

@ -0,0 +1,45 @@
class Scale
def initialize(watch_low_benchmark:, growth_low_benchmark:, approval_low_benchmark:, ideal_low_benchmark:)
@watch_low_benchmark = watch_low_benchmark
@growth_low_benchmark = growth_low_benchmark
@approval_low_benchmark = approval_low_benchmark
@ideal_low_benchmark = ideal_low_benchmark
end
Zone = Struct.new(:low_benchmark, :high_benchmark, :type)
def warning_zone
Zone.new(1, @watch_low_benchmark, :warning)
end
def watch_zone
Zone.new(@watch_low_benchmark, @growth_low_benchmark, :watch)
end
def growth_zone
Zone.new(@growth_low_benchmark, @approval_low_benchmark, :growth)
end
def approval_zone
Zone.new(@approval_low_benchmark, @ideal_low_benchmark, :approval)
end
def ideal_zone
Zone.new(@ideal_low_benchmark, 5.0, :ideal)
end
def zone_for_score(score)
case score
when ideal_zone.low_benchmark..ideal_zone.high_benchmark
ideal_zone
when approval_zone.low_benchmark..approval_zone.high_benchmark
approval_zone
when growth_zone.low_benchmark..growth_zone.high_benchmark
growth_zone
when watch_zone.low_benchmark..watch_zone.high_benchmark
watch_zone
else
warning_zone
end
end
end

@ -0,0 +1,34 @@
class SubcategoryPresenter
def initialize(subcategory:, academic_year:, school:)
@subcategory = subcategory
@academic_year = academic_year
@school = school
end
def name
@subcategory.name
end
def gauge_presenter
average_score = SurveyItemResponse.for_measures(measures)
.where(academic_year: @academic_year, school: @school)
.average(:likert_score)
GaugePresenter.new(scale: scale, score: average_score)
end
private
def scale
Scale.new(
watch_low_benchmark: measures.map(&:watch_low_benchmark).average,
growth_low_benchmark: measures.map(&:growth_low_benchmark).average,
approval_low_benchmark: measures.map(&:approval_low_benchmark).average,
ideal_low_benchmark: measures.map(&:ideal_low_benchmark).average,
)
end
def measures
@measures ||= @subcategory.measures
end
end

@ -1,11 +1,10 @@
# TODO inline me pls
class SurveyResponseAggregator
# Returns an average score for all SurveyItemResponses for the given AcademicYear, School, and Measure
def self.score(academic_year:, school:, measure:)
SurveyItemResponse
SurveyItemResponse.for_measure(measure)
.where(academic_year: academic_year, school: school)
.joins(:survey_item).where('survey_items.measure_id': measure.id)
.map { |survey_item_response| survey_item_response.likert_score }
.average
.average(:likert_score)
end
# Returns an array of SurveyItemResponses for the given AcademicYear, School, and Measure

@ -0,0 +1,60 @@
<% outer_radius = 100 %>
<% inner_radius = 50 %>
<% stroke_width = 1 %>
<% key_benchmark_indicator_height = 10 %>
<% scale = -Math::PI %>
<svg
viewBox="<%= -(outer_radius + stroke_width) %> <%= -(outer_radius + stroke_width) %> <%= 2*(outer_radius + stroke_width) %> <%= outer_radius + 2*stroke_width + key_benchmark_indicator_height %>"
width="400"
height="200"
>
<path
class="gauge-fill <%= gauge.color_class %>"
d="M <%= -outer_radius %> <%= key_benchmark_indicator_height %>
A <%= outer_radius %> <%= outer_radius %> 0 0 1 <%= outer_radius * Math.cos((1 - gauge.score_percentage) * scale) %> <%= outer_radius * Math.sin((1 - gauge.score_percentage) * scale) + key_benchmark_indicator_height %>
L <%= inner_radius * Math.cos((1 - gauge.score_percentage) * scale) %> <%= inner_radius * Math.sin((1 - gauge.score_percentage) * scale) + key_benchmark_indicator_height %>
A <%= inner_radius %> <%= inner_radius %> 0 0 0 <%= -inner_radius %> <%= key_benchmark_indicator_height %>
L <%= -outer_radius %> <%= key_benchmark_indicator_height %>"
fill="none"
stroke="none"
/>
<text
class="gauge-title font-bitter fill-black"
x="0"
y="<% -10 + key_benchmark_indicator_height %>"
text-anchor="middle"
dominant-baseline="middle"
>
<%= gauge.title %>
</text>
<path
class="gauge-outline stroke-gray-2"
d="M <%= -outer_radius %> <%= key_benchmark_indicator_height %>
A <%= outer_radius %> <%= outer_radius %> 0 0 1 <%= outer_radius * Math.cos(0) %> <%= outer_radius * Math.sin(0) + key_benchmark_indicator_height %>
L <%= inner_radius * Math.cos(0) %> <%= inner_radius * Math.sin(0) + key_benchmark_indicator_height %>
A <%= inner_radius %> <%= inner_radius %> 0 0 0 <%= -inner_radius %> <%= key_benchmark_indicator_height %>
L <%= -outer_radius %> <%= key_benchmark_indicator_height %>"
fill="none"
stroke-width="<%= stroke_width %>"
/>
<line
class="zone-benchmark stroke-gray-2"
x1="<%= outer_radius * Math.cos((1 - gauge.key_benchmark_percentage) * scale) %>" y1="<%= outer_radius * Math.sin((1 - gauge.key_benchmark_percentage) * scale) + key_benchmark_indicator_height %>"
x2="<%= inner_radius * Math.cos((1 - gauge.key_benchmark_percentage) * scale) %>" y2="<%= inner_radius * Math.sin((1 - gauge.key_benchmark_percentage) * scale) + key_benchmark_indicator_height %>"
stroke-width="<%= stroke_width %>"
/>
<path
class="key-benchmark-indicator fill-black"
d="M 0 <%= -(outer_radius - key_benchmark_indicator_height + 2) %>
L <%= key_benchmark_indicator_height/Math.sqrt(3) %> <%= -outer_radius %>
L <%= -key_benchmark_indicator_height/Math.sqrt(3) %> <%= -outer_radius %>
L 0 <%= -(outer_radius - key_benchmark_indicator_height + 2) %>"
transform="rotate(<%= 180.0 * gauge.key_benchmark_percentage - 90 %> 0 <%= key_benchmark_indicator_height %>)"
stroke="none"
/>
</svg>

@ -0,0 +1,7 @@
<h1><%= @category.name %></h1>
<% @category.subcategories.each do |subcategory| %>
<h2><%= subcategory.name %></h2>
<%= render partial: "gauge_graph", locals: { gauge: subcategory.gauge_presenter } %>
<% end %>

@ -1,3 +1,5 @@
<a href="/districts/<%= @district.slug %>/schools/<%= @school.slug %>/browse/teachers-and-leadership?year=2020-21">Browse</a>
<h1><%= @school.name %></h1>
<div class="fdr fjb fac">
@ -28,7 +30,7 @@
<div class="bg-beige mt-4 p-5">
<div>
<h2 class="h1 red">Distance from benchmark</h2>
<h2 class="h1 color-red">Distance from benchmark</h2>
<p class="body-large">This graph shows how much a score is above or below the benchmark of any given scale.</p>
</div>

@ -5,6 +5,7 @@ Rails.application.routes.draw do
resources :districts do
resources :schools, only: [:index, :show] do
resources :dashboard, only: [:index]
resources :browse, only: [:show]
end
end

@ -0,0 +1,50 @@
FactoryBot.define do
factory :sqm_category do
name { "A category" }
end
factory :subcategory do
name { "A subcategory" }
sqm_category
factory :subcategory_with_measures do
transient do
measures_count { 2 }
end
after(:create) do |subcategory, evaluator|
create_list(:measure, evaluator.measures_count, subcategory: subcategory)
end
end
end
factory :measure do
measure_id { rand.to_s }
name { 'A Measure' }
watch_low_benchmark { 2.0 }
growth_low_benchmark { 3.0 }
approval_low_benchmark { 4.0 }
ideal_low_benchmark { 4.5 }
subcategory
end
factory :survey_item do
survey_item_id { rand.to_s }
measure
end
factory :academic_year do
range { '2050-51' }
end
factory :school do
name { "#{rand} School" }
end
factory :survey_item_response do
likert_score { 3 }
response_id { rand.to_s }
academic_year
school
survey_item
end
end

@ -5,16 +5,21 @@ feature 'School dashboard', type: feature do
let(:school) { School.find_by_slug 'winchester-high-school' }
let(:school_in_same_district) { School.find_by_slug 'muraco-elementary-school' }
let(:category) { SqmCategory.find_by_name('Teachers & Leadership') }
let(:subcategory) { Subcategory.find_by_name('Teachers & The Teaching Environment') }
let(:measures_for_subcategory) { Measure.where(subcategory: subcategory) }
let(:survey_items_for_subcategory) { SurveyItem.where(measure: measures_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_4C_i) { Measure.find_by_measure_id('4C-i') }
let(:survey_item_1_for_measure_1A_i) { SurveyItem.create measure: measure_1A_i, survey_item_id: rand.to_s }
let(:survey_item_2_for_measure_1A_i) { SurveyItem.create measure: measure_1A_i, survey_item_id: rand.to_s }
let(:survey_item_1_for_measure_2A_i) { SurveyItem.create measure: measure_2A_i, survey_item_id: rand.to_s }
let(:survey_item_2_for_measure_2A_i) { SurveyItem.create measure: measure_2A_i, survey_item_id: rand.to_s }
let(:survey_item_1_for_measure_4C_i) { SurveyItem.create measure: measure_4C_i, survey_item_id: rand.to_s }
let(:survey_item_2_for_measure_4C_i) { SurveyItem.create measure: measure_4C_i, survey_item_id: rand.to_s }
let(:survey_items_for_measure_1A_i) { SurveyItem.where(measure: measure_1A_i) }
let(:survey_items_for_measure_2A_i) { SurveyItem.where(measure: measure_2A_i) }
let(:survey_items_for_measure_4C_i) { SurveyItem.where(measure: measure_4C_i) }
let(:measure_row_bars) { page.all('rect.measure-row-bar') }
@ -24,24 +29,27 @@ feature 'School dashboard', type: feature do
let(:password) { 'winchester!' }
before :each do
SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school,
survey_item: survey_item_1_for_measure_1A_i, likert_score: 4
SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school,
survey_item: survey_item_2_for_measure_1A_i, likert_score: 5
SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school,
survey_item: survey_item_1_for_measure_2A_i, likert_score: 5
SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school,
survey_item: survey_item_2_for_measure_2A_i, likert_score: 5
SurveyItemResponse.create response_id: rand.to_s, academic_year: ay_2020_21, school: school,
survey_item: survey_item_1_for_measure_4C_i, likert_score: 1
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
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
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
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
end
end
scenario 'User authentication fails' do
page.driver.browser.basic_authorize('wrong username', 'wrong password')
visit "/districts/winchester/schools/#{school.slug}/dashboard?year=2020-21"
visit "/districts/#{district.slug}/schools/#{school.slug}/dashboard?year=2020-21"
expect(page).not_to have_text(school.name)
end
@ -59,7 +67,7 @@ feature 'School dashboard', type: feature do
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 '20.66%'
expect(professional_qualifications_row['width']).to eq '10.33%'
expect(professional_qualifications_row['x']).to eq '50%'
expect(page).to have_text('Student Physical Safety')
@ -78,6 +86,11 @@ feature 'School dashboard', type: feature do
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
click_on 'Browse'
expect(page).to have_text('Teachers & Leadership')
expect(page).to have_text('Approval')
end
# visit photos_path

@ -1,45 +0,0 @@
require 'rails_helper'
describe Measure, type: :model do
it('has all the measures') do
expect(Measure.count).to eq 30
end
it 'returns the measure for the given measure id' do
measure = Measure.find_by_measure_id('1A-i')
expect(measure.name).to eq 'Professional Qualifications'
expect(measure.warning_zone).to eq Measure::Zone.new(1.0, 2.49, :warning)
expect(measure.watch_zone).to eq Measure::Zone.new(2.49, 3.0, :watch)
expect(measure.growth_zone).to eq Measure::Zone.new(3.0, 3.5, :growth)
expect(measure.approval_zone).to eq Measure::Zone.new(3.5, 4.71, :approval)
expect(measure.ideal_zone).to eq Measure::Zone.new(4.71, 5.0, :ideal)
end
describe '#zone_for_score' do
let(:measure) {
Measure.new watch_low_benchmark: 1.5, growth_low_benchmark: 2.5, approval_low_benchmark: 3.5, ideal_low_benchmark: 4.5
}
context 'when the score is 1.0' do
it 'returns the warning zone' do
expect(measure.zone_for_score(1.0)).to eq measure.warning_zone
end
end
context 'when the score is 5.0' do
it 'returns the ideal zone' do
expect(measure.zone_for_score(5.0)).to eq measure.ideal_zone
end
end
context 'when the score is right on the benchmark' do
it 'returns the higher zone' do
expect(measure.zone_for_score(1.5)).to eq measure.watch_zone
expect(measure.zone_for_score(2.5)).to eq measure.growth_zone
expect(measure.zone_for_score(3.5)).to eq measure.approval_zone
expect(measure.zone_for_score(4.5)).to eq measure.ideal_zone
end
end
end
end

@ -0,0 +1,19 @@
require 'rails_helper'
describe CategoryPresenter do
let(:category_presenter) do
subcategory1 = Subcategory.new(name: 'A subcategory')
subcategory2 = Subcategory.new(name: 'Another subcategory')
category = SqmCategory.new(name: 'Some Category', subcategories: [subcategory1, subcategory2])
return CategoryPresenter.new(category: category, academic_year: AcademicYear.new, school: School.new)
end
it 'returns the name of the category' do
expect(category_presenter.name).to eq 'Some Category'
end
it 'maps subcategories to subcategory presenters' do
expect(category_presenter.subcategories.map(&:name)).to eq ['A subcategory', 'Another subcategory']
end
end

@ -0,0 +1,120 @@
require 'rails_helper'
describe GaugePresenter do
# let(:academic_year) { create(:academic_year, range: '1989-90') }
# let(:school) { create(:school, name: 'Best School') }
# let(:subcategory_presenter) do
# subcategory = create(:subcategory, name: 'A great subcategory')
# measure1 = create(:measure, watch_low_benchmark: 4, growth_low_benchmark: 4.25, approval_low_benchmark: 4.5, ideal_low_benchmark: 4.75, subcategory: subcategory)
# survey_item1 = create(:survey_item, measure: measure1)
# create(:survey_item_response, survey_item: survey_item1, academic_year: academic_year, school: school, likert_score: 1)
# create(:survey_item_response, survey_item: survey_item1, academic_year: academic_year, school: school, likert_score: 5)
# measure2 = create(:measure, watch_low_benchmark: 1.25, growth_low_benchmark: 1.5, approval_low_benchmark: 1.75, ideal_low_benchmark: 2.0, subcategory: subcategory)
# survey_item2 = create(:survey_item, measure: measure2)
# create(:survey_item_response, survey_item: survey_item2, academic_year: academic_year, school: school, likert_score: 1)
# create(:survey_item_response, survey_item: survey_item2, academic_year: academic_year, school: school, likert_score: 5)
# create_survey_item_responses_for_different_years_and_schools(survey_item1)
# return SubcategoryPresenter.new(subcategory: subcategory, academic_year: academic_year, school: school)
# end
let(:scale) do
Scale.new(
watch_low_benchmark: 1.5,
growth_low_benchmark: 2.5,
approval_low_benchmark: 3.5,
ideal_low_benchmark: 4.5,
)
end
let(:score) { 3 }
let(:gauge_presenter) { GaugePresenter.new(scale: scale, score: score) }
it 'returns the key benchmark percentage for the gauge' do
expect(gauge_presenter.key_benchmark_percentage).to eq 0.625
end
context 'when the given score is in the Warning zone for the given scale' do
let(:score) { 1 }
it 'returns the title of the zone' do
expect(gauge_presenter.title).to eq 'Warning'
end
it 'returns the color class for the gauge' do
expect(gauge_presenter.color_class).to eq 'fill-warning'
end
it 'returns the score percentage for the gauge' do
expect(gauge_presenter.score_percentage).to eq 0.0
end
end
context 'when the given score is in the Watch zone for the given scale' do
let(:score) { 2 }
it 'returns the title of the zone' do
expect(gauge_presenter.title).to eq 'Watch'
end
it 'returns the color class for the gauge' do
expect(gauge_presenter.color_class).to eq 'fill-watch'
end
it 'returns the score percentage for the gauge' do
expect(gauge_presenter.score_percentage).to eq 0.25
end
end
context 'when the given score is in the Growth zone for the given scale' do
let(:score) { 3 }
it 'returns the title of the zone' do
expect(gauge_presenter.title).to eq 'Growth'
end
it 'returns the color class for the gauge' do
expect(gauge_presenter.color_class).to eq 'fill-growth'
end
it 'returns the score percentage for the gauge' do
expect(gauge_presenter.score_percentage).to eq 0.5
end
end
context 'when the given score is in the Approval zone for the given scale' do
let(:score) { 4 }
it 'returns the title of the zone' do
expect(gauge_presenter.title).to eq 'Approval'
end
it 'returns the color class for the gauge' do
expect(gauge_presenter.color_class).to eq 'fill-approval'
end
it 'returns the score percentage for the gauge' do
expect(gauge_presenter.score_percentage).to eq 0.75
end
end
context 'when the given score is in the Ideal zone for the given scale' do
let(:score) { 5 }
it 'returns the title of the zone' do
expect(gauge_presenter.title).to eq 'Ideal'
end
it 'returns the color class for the gauge' do
expect(gauge_presenter.color_class).to eq 'fill-ideal'
end
it 'returns the score percentage for the gauge' do
expect(gauge_presenter.score_percentage).to eq 1.0
end
end
end

@ -0,0 +1,30 @@
require 'rails_helper'
describe Scale do
describe '#zone_for_score' do
let(:scale) {
Scale.new watch_low_benchmark: 1.5, growth_low_benchmark: 2.5, approval_low_benchmark: 3.5, ideal_low_benchmark: 4.5
}
context 'when the score is 1.0' do
it 'returns the warning zone' do
expect(scale.zone_for_score(1.0)).to eq scale.warning_zone
end
end
context 'when the score is 5.0' do
it 'returns the ideal zone' do
expect(scale.zone_for_score(5.0)).to eq scale.ideal_zone
end
end
context 'when the score is right on the benchmark' do
it 'returns the higher zone' do
expect(scale.zone_for_score(1.5)).to eq scale.watch_zone
expect(scale.zone_for_score(2.5)).to eq scale.growth_zone
expect(scale.zone_for_score(3.5)).to eq scale.approval_zone
expect(scale.zone_for_score(4.5)).to eq scale.ideal_zone
end
end
end
end

@ -0,0 +1,37 @@
require 'rails_helper'
describe SubcategoryPresenter do
let(:academic_year) { create(:academic_year, range: '1989-90') }
let(:school) { create(:school, name: 'Best School') }
let(:subcategory_presenter) do
subcategory = create(:subcategory, name: 'A great subcategory')
measure1 = create(:measure, watch_low_benchmark: 4, growth_low_benchmark: 4.25, approval_low_benchmark: 4.5, ideal_low_benchmark: 4.75, subcategory: subcategory)
survey_item1 = create(:survey_item, measure: measure1)
create(:survey_item_response, survey_item: survey_item1, academic_year: academic_year, school: school, likert_score: 1)
create(:survey_item_response, survey_item: survey_item1, academic_year: academic_year, school: school, likert_score: 5)
measure2 = create(:measure, watch_low_benchmark: 1.25, growth_low_benchmark: 1.5, approval_low_benchmark: 1.75, ideal_low_benchmark: 2.0, subcategory: subcategory)
survey_item2 = create(:survey_item, measure: measure2)
create(:survey_item_response, survey_item: survey_item2, academic_year: academic_year, school: school, likert_score: 1)
create(:survey_item_response, survey_item: survey_item2, academic_year: academic_year, school: school, likert_score: 5)
create_survey_item_responses_for_different_years_and_schools(survey_item1)
return SubcategoryPresenter.new(subcategory: subcategory, academic_year: academic_year, school: school)
end
it 'returns the name of the subcategory' do
expect(subcategory_presenter.name).to eq 'A great subcategory'
end
it 'returns a gauge presenter responsible for the aggregate survey item response likert scores' do
expect(subcategory_presenter.gauge_presenter.title).to eq 'Growth'
end
def create_survey_item_responses_for_different_years_and_schools(survey_item)
create(:survey_item_response, survey_item: survey_item, school: school, likert_score: 1)
create(:survey_item_response, survey_item: survey_item, academic_year: academic_year, likert_score: 1)
end
end

@ -0,0 +1,3 @@
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end

@ -0,0 +1,39 @@
require 'rails_helper'
describe 'browse/show.html.erb' do
before :each do
academic_year = create(:academic_year, range: '1989-90')
school = create(:school, name: 'Best School')
category = create(:sqm_category, name: 'Some Category')
subcategory1 = create(:subcategory, sqm_category: category, name: 'A subcategory')
subcategory2 = create(:subcategory_with_measures, sqm_category: category, name: 'Another subcategory')
measure1 = create(:measure, subcategory: subcategory1, watch_low_benchmark: 1.5, growth_low_benchmark: 2.5, approval_low_benchmark: 3.5, ideal_low_benchmark: 4.5)
survey_item1 = create(:survey_item, measure: measure1)
survey_item_response1 = create(:survey_item_response, survey_item: survey_item1, academic_year: academic_year, school: school, likert_score: 3)
assign :category, CategoryPresenter.new(category: category, academic_year: academic_year, school: school)
render
end
it 'renders the category name' do
expect(rendered).to match /Some Category/
end
context 'for each subcategory' do
it 'renders the subcategory name' do
expect(rendered).to match /A subcategory/
expect(rendered).to match /Another subcategory/
end
it 'renders the zone title and fill color for the gauge graph' do
expect(rendered).to match /Growth/
expect(rendered).to match /fill-growth/
end
end
end
Loading…
Cancel
Save