diff --git a/spec/presenters/grouped_bar_column_presenter_spec.rb b/spec/presenters/grouped_bar_column_presenter_spec.rb
new file mode 100644
index 00000000..97d0886f
--- /dev/null
+++ b/spec/presenters/grouped_bar_column_presenter_spec.rb
@@ -0,0 +1,187 @@
+require 'rails_helper'
+
+describe GroupedBarColumnPresenter do
+ let(:watch_low_benchmark) { 2.9 }
+ let(:growth_low_benchmark) { 3.1 }
+ let(:approval_low_benchmark) { 3.6 }
+ let(:ideal_low_benchmark) { 3.8 }
+
+ let(:measure) do
+ measure = create(
+ :measure,
+ name: 'Some Title'
+ )
+ scale = create(:scale, measure:)
+
+ create(:student_survey_item, scale:,
+ watch_low_benchmark:,
+ growth_low_benchmark:,
+ approval_low_benchmark:,
+ ideal_low_benchmark:)
+
+ measure
+ end
+
+ let(:measure_without_admin_data_items) do
+ create(
+ :measure,
+ name: 'Some Title'
+ )
+ end
+
+ let(:presenter) do
+ GroupedBarColumnPresenter.new measure:, score:, position: 1, type: :all
+ end
+
+ shared_examples_for 'measure_name' do
+ it 'returns the measure name' do
+ expect(presenter.measure_name).to eq 'Some Title'
+ end
+ end
+
+ context 'when the score is in the Ideal zone' do
+ let(:score) { Score.new(4.4, true, true) }
+
+ it_behaves_like 'measure_name'
+
+ it 'returns the correct color' do
+ expect(presenter.bar_color).to eq 'fill-ideal'
+ end
+
+ it 'returns a bar width equal to the approval zone width plus the proportionate ideal zone width' do
+ expect(presenter.bar_height_percentage).to be_within(0.01).of(25.5)
+ end
+
+ it 'returns a y_offset equal to the ' do
+ expect(presenter.y_offset).to be_within(0.01).of(8.5)
+ end
+ end
+
+ context 'when the score is in the Approval zone' do
+ let(:score) { Score.new(3.7, true, true) }
+
+ it_behaves_like 'measure_name'
+
+ it 'returns the correct color' do
+ expect(presenter.bar_color).to eq 'fill-approval'
+ end
+
+ it 'returns a bar width equal to the proportionate approval zone width' do
+ expect(presenter.bar_height_percentage).to be_within(0.01).of(8.5)
+ end
+
+ it 'returns an x-offset of 60%' do
+ expect(presenter.y_offset).to be_within(0.01).of(25.5)
+ end
+ end
+
+ context 'when the score is in the Growth zone' do
+ let(:score) { Score.new(3.2, true, true) }
+
+ it_behaves_like 'measure_name'
+
+ it 'returns the correct color' do
+ expect(presenter.bar_color).to eq 'fill-growth'
+ end
+
+ it 'returns a bar width equal to the proportionate growth zone width' do
+ expect(presenter.bar_height_percentage).to be_within(0.01).of(13.59)
+ end
+
+ context 'in order to achieve the visual effect' do
+ it 'returns an x-offset equal to 60% minus the bar width' do
+ expect(presenter.y_offset).to eq 34
+ end
+ end
+ end
+
+ context 'when the score is in the Watch zone' do
+ let(:score) { Score.new(2.9, true, true) }
+
+ it_behaves_like 'measure_name'
+
+ it 'returns the correct color' do
+ expect(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(presenter.bar_height_percentage).to eq 34
+ end
+
+ context 'in order to achieve the visual effect' do
+ it 'returns an x-offset equal to 60% minus the bar width' do
+ expect(presenter.y_offset).to eq 34
+ end
+ end
+ end
+
+ context 'when the score is in the Warning zone' do
+ let(:score) { Score.new(1.0, true, true) }
+
+ it_behaves_like 'measure_name'
+
+ it 'returns the correct color' do
+ expect(presenter.bar_color).to eq 'fill-warning'
+ end
+
+ it 'returns a bar width equal to the proportionate warning zone width plus the watch & growth zone widths' do
+ expect(presenter.bar_height_percentage).to eq 51
+ end
+
+ context 'in order to achieve the visual effect' do
+ it 'returns an y-offset equal to 60% minus the bar width' do
+ expect(presenter.y_offset).to eq 34
+ end
+ end
+ end
+
+ # context 'when a measure contains teacher survey items' do
+ # before :each do
+ # scale = create(:scale, measure:)
+ # create :teacher_survey_item, scale:
+ # end
+
+ # context 'when there are insufficient teacher survey item responses' do
+ # let(:score) { Score.new(nil, false, true) }
+ # it 'shows a message saying there are insufficient responses' do
+ # expect(presenter.insufficient_teacher_responses?).to be true
+ # end
+ # end
+
+ # context 'when there are sufficient teacher survey item responses' do
+ # let(:score) { Score.new(nil, true, true) }
+ # it 'does not show a partial data indicator' do
+ # expect(presenter.show_teacher_inapplicability_message?).to be true
+ # end
+ # end
+ # end
+
+ # context 'when a measure does not contain teacher survey items' do
+ # context 'when there are insufficient teacher survey item responses' do
+ # let(:score) { Score.new(nil, false, true) }
+ # it 'shows a message saying the measure is not based on teacher survey items' do
+ # expect(presenter.show_teacher_inapplicability_message?).to be false
+ # end
+ # end
+ # end
+
+ # context 'when a measure contains student survey items' do
+ # before :each do
+ # scale = create(:scale, measure:)
+ # create :student_survey_item, scale:
+ # end
+
+ # context 'when there are insufficient student survey item responses' do
+ # let(:score) { Score.new(nil, true, false) }
+ # it 'shows a partial data indicator' do
+ # expect(presenter.show_student_inapplicability_message?).to be true
+ # end
+ # end
+ # context 'when there are sufficient student survey item responses' do
+ # let(:score) { Score.new(nil, true, true) }
+ # it 'shows a partial data indicator' do
+ # expect(presenter.show_student_inapplicability_message?).to be true
+ # end
+ # end
+ # end
+end
diff --git a/spec/system/journey_spec.rb b/spec/system/journey_spec.rb
index 18914351..7da750fd 100644
--- a/spec/system/journey_spec.rb
+++ b/spec/system/journey_spec.rb
@@ -1,4 +1,5 @@
require 'rails_helper'
+include AnalyzeHelper
describe 'District Admin', js: true do
let(:district) { District.find_by_slug 'winchester' }
diff --git a/spec/views/analyze/index.html.erb_spec.rb b/spec/views/analyze/index.html.erb_spec.rb
new file mode 100644
index 00000000..3079994f
--- /dev/null
+++ b/spec/views/analyze/index.html.erb_spec.rb
@@ -0,0 +1,87 @@
+require 'rails_helper'
+include AnalyzeHelper
+
+describe 'analyze/index' do
+ subject { Nokogiri::HTML(rendered) }
+ let(:category) { create(:category) }
+ let(:subcategory) { create(:subcategory, category:) }
+
+ let(:support_for_teaching) do
+ measure = create(:measure, name: 'Support For Teaching Development & Growth', measure_id: '1', subcategory:)
+ 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)
+ measure
+ end
+
+ let(:effective_leadership) do
+ measure = create(:measure, name: 'Effective Leadership', measure_id: '2', subcategory:)
+ 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)
+ measure
+ end
+
+ let(:professional_qualifications) do
+ measure = create(:measure, name: 'Professional Qualifications', measure_id: '3', subcategory:)
+ 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)
+ measure
+ end
+ let(:academic_year) { create(:academic_year) }
+
+ before :each do
+ # assign :category_presenters, []
+ # assign :grouped_bar_column_presenters, grouped_bar_column_presenters
+ assign :academic_year, academic_year
+ # assign :academic_years, [academic_year]
+ assign :district, create(:district)
+ assign :school, create(:school)
+ assign :category, category
+ assign :subcategory, subcategory
+ assign :measure, support_for_teaching
+
+ render
+ end
+
+ context 'when all the presenters have a non-nil score' do
+ # let(:grouped_bar_column_presenters) do
+ # 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)
+ # [
+ # GroupedBarColumnPresenter.new(measure:,
+ # score: Score.new(rand))
+ # ]
+ # end
+
+ it 'displays a set of grouped bars for each presenter' do
+ displayed_variance_rows = subject.css('[data-for-measure-id]')
+ expect(displayed_variance_rows.count).to eq 3
+ expect(displayed_variance_rows.first.attribute('data-for-measure-id').value).to eq '1'
+
+ displayed_variance_labels = subject.css('[data-grouped-bar-label]')
+ expect(displayed_variance_labels.count).to eq 3
+ expect(displayed_variance_labels.first.inner_text).to include 'All Students'
+ expect(displayed_variance_labels.last.inner_text).to include 'All Survey Data'
+ end
+ end
+end