From 5051122bcd5dbef5d538eb789b5a745089cb5f1f Mon Sep 17 00:00:00 2001 From: barbie-bot Date: Sat, 4 Apr 2026 09:55:31 +0000 Subject: [PATCH] Refactor charts: dedicated nav tab, JSON data transport, tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the toggle-view approach and hidden DOM data carrier with a proper dedicated Charts page: - Move Charts out of Measurements view toggles into its own nav tab and route (GET /charts) - ChartsController serializes readout data as JSON (ordered by taken_at); the view embeds it in a diff --git a/app/views/measurements/index.html.erb b/app/views/measurements/index.html.erb index 5d4d00c..fc1e4c5 100644 --- a/app/views/measurements/index.html.erb +++ b/app/views/measurements/index.html.erb @@ -11,9 +11,7 @@ <%= image_button_tag '', 'view-columns', name: nil, type: 'button', class: 'view-toggle', title: t('.view_wide'), data: {view: 'wide'}, onclick: "setMeasurementsView('wide')" %> - <%= image_button_tag '', 'chart-line', name: nil, type: 'button', - class: 'view-toggle', title: t('.view_charts'), - data: {view: 'charts'}, onclick: "setMeasurementsView('charts')" %> +
@@ -37,6 +35,6 @@
-
+
diff --git a/config/locales/en.yml b/config/locales/en.yml index d5589c0..355e768 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -89,6 +89,8 @@ en: readouts: form: set_default_unit: Set as default unit + charts: + navigation: Charts measurements: navigation: Measurements no_items: There are no measurements taken. You can Add some now. diff --git a/config/routes.rb b/config/routes.rb index 1d3f7b3..997eae2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,6 @@ Rails.application.routes.draw do resources :measurements + resources :charts, only: [:index] resources :readouts, only: [:new] do collection {get 'new/:id/discard', action: :discard, as: :discard} diff --git a/test/controllers/charts_controller_test.rb b/test/controllers/charts_controller_test.rb new file mode 100644 index 0000000..d201b1e --- /dev/null +++ b/test/controllers/charts_controller_test.rb @@ -0,0 +1,63 @@ +require "test_helper" + +class ChartsControllerTest < ActionDispatch::IntegrationTest + setup do + host! '127.0.0.1' + @user = users(:alice) + post new_user_session_path, params: { user: { email: @user.email, password: 'alice' } } + @quantity = @user.quantities.create!(name: 'Weight') + @unit = @user.units.create!(symbol: 'kg') + end + + test "requires authentication" do + delete destroy_user_session_path + get charts_path + assert_response :redirect + end + + test "index returns ok" do + get charts_path + assert_response :success + end + + test "embeds readout data as JSON in script tag" do + users(:alice).readouts.create!(quantity: @quantity, unit: @unit, value: 82.5, taken_at: 1.day.ago) + + get charts_path + + assert_select 'script#charts-data[type="application/json"]' do |elements| + data = JSON.parse(elements.first.children.first.to_s) + assert_equal 1, data.size + assert_equal 'Weight', data.first['quantityName'] + assert_in_delta 82.5, data.first['value'] + assert_equal 'kg', data.first['unit'] + assert_not_nil data.first['takenAt'] + end + end + + test "orders readouts by taken_at ascending" do + older = users(:alice).readouts.create!(quantity: @quantity, unit: @unit, value: 80.0, taken_at: 2.days.ago) + newer = users(:alice).readouts.create!(quantity: @quantity, unit: @unit, value: 82.5, taken_at: 1.day.ago) + + get charts_path + + assert_select 'script#charts-data[type="application/json"]' do |elements| + data = JSON.parse(elements.first.children.first.to_s) + assert_equal older.taken_at.iso8601, data.first['takenAt'] + assert_equal newer.taken_at.iso8601, data.last['takenAt'] + end + end + + test "does not expose other users readouts" do + bob_quantity = users(:bob).quantities.create!(name: 'Steps') + bob_unit = users(:bob).units.create!(symbol: 'steps') + users(:bob).readouts.create!(quantity: bob_quantity, unit: bob_unit, value: 5000, taken_at: 1.day.ago) + + get charts_path + + assert_select 'script#charts-data[type="application/json"]' do |elements| + data = JSON.parse(elements.first.children.first.to_s) + assert data.none? { |r| r['quantityName'] == 'Steps' }, "Bob's data must not appear" + end + end +end diff --git a/test/system/charts_test.rb b/test/system/charts_test.rb new file mode 100644 index 0000000..62ca9da --- /dev/null +++ b/test/system/charts_test.rb @@ -0,0 +1,26 @@ +require "application_system_test_case" + +class ChartsTest < ApplicationSystemTestCase + setup do + @user = sign_in(user: users(:alice)) + @quantity = @user.quantities.create!(name: 'Weight') + @unit = @user.units.create!(symbol: 'kg') + @user.readouts.create!(quantity: @quantity, unit: @unit, value: 82.5, taken_at: 1.day.ago) + @user.readouts.create!(quantity: @quantity, unit: @unit, value: 83.1, taken_at: Time.now) + visit charts_path + end + + test "charts page is reachable from navigation" do + visit root_path + click_on t('charts.navigation') + assert_current_path charts_path + end + + test "renders Plotly chart panel" do + assert_selector '#measurements-charts .chart-panel', wait: 5 + end + + test "chart legend shows quantity name with unit" do + assert_text 'Weight (kg)', wait: 5 + end +end