diff --git a/app/models/series.rb b/app/models/series.rb index 1d6bbab1..b50a38ee 100644 --- a/app/models/series.rb +++ b/app/models/series.rb @@ -33,10 +33,6 @@ class Series start_date: start_date, end_date: end_date, interval: interval, - trend: Trend.new( - current: ordered.last[:value], - previous: ordered.first[:value] - ), values: [ nil, *ordered ].each_cons(2).map do |prev_value, curr_value| Value.new( date: curr_value[:date], diff --git a/test/controllers/onboardings_controller_test.rb b/test/controllers/onboardings_controller_test.rb new file mode 100644 index 00000000..129aaecf --- /dev/null +++ b/test/controllers/onboardings_controller_test.rb @@ -0,0 +1,167 @@ +require "test_helper" + +class OnboardingsControllerTest < ActionDispatch::IntegrationTest + setup do + @user = users(:family_admin) + @family = @user.family + + # Reset onboarding state + @user.update!(set_onboarding_preferences_at: nil) + + sign_in @user + end + + test "should get show" do + get onboarding_url + assert_response :success + assert_select "h1", text: /set up your account/i + end + + test "should get preferences" do + get preferences_onboarding_url + assert_response :success + assert_select "h1", text: /preferences/i + end + + test "preferences page renders Series chart data without errors" do + get preferences_onboarding_url + assert_response :success + + # This test specifically targets the Series model bug + # The page should render without throwing the "unknown keyword: :trend" error + assert_select "[data-controller='time-series-chart']" + assert_select "#previewChart" + + # Verify that the Series.from_raw_values call in the view works + # If the Series bug existed, this would raise an ActionView::Template::Error + assert_no_match /unknown keyword: :trend/, response.body + end + + test "preferences page includes chart with valid JSON data" do + get preferences_onboarding_url + assert_response :success + + # Extract the chart data from the response + chart_data_match = response.body.match(/data-time-series-chart-data-value="([^"]*)"/) + assert chart_data_match, "Chart data attribute should be present" + + # Decode HTML entities and parse JSON + chart_data_json = CGI.unescapeHTML(chart_data_match[1]) + + # Should be valid JSON + assert_nothing_raised do + chart_data = JSON.parse(chart_data_json) + + # Verify expected structure + assert chart_data.key?("start_date") + assert chart_data.key?("end_date") + assert chart_data.key?("interval") + assert chart_data.key?("trend") + assert chart_data.key?("values") + + # Verify trend has expected structure + trend = chart_data["trend"] + assert trend.key?("value") + assert trend.key?("percent") + assert trend.key?("current") + assert trend.key?("previous") + + # Verify values array has expected structure + values = chart_data["values"] + assert values.is_a?(Array) + assert values.length > 0 + + values.each do |value| + assert value.key?("date") + assert value.key?("value") + assert value.key?("trend") + end + end + end + + test "should get goals" do + get goals_onboarding_url + assert_response :success + assert_select "h1", text: /What brings you to Maybe/i + end + + test "should get trial" do + get trial_onboarding_url + assert_response :success + end + + test "preferences page shows currency formatting example" do + get preferences_onboarding_url + assert_response :success + + # Should show formatted currency example + assert_select "p", text: /\$2,325\.25/ + assert_select "span", text: /\+\$78\.90/ + end + + test "preferences page shows date formatting example" do + get preferences_onboarding_url + assert_response :success + + # Should show formatted date example (checking for the specific format shown) + assert_match /10-23-2024/, response.body +end + + test "preferences page includes all required form fields" do + get preferences_onboarding_url + assert_response :success + + # Verify all form fields are present + assert_select "select[name='user[family_attributes][locale]']" + assert_select "select[name='user[family_attributes][currency]']" + assert_select "select[name='user[family_attributes][date_format]']" + assert_select "select[name='user[theme]']" + assert_select "button[type='submit']" +end + + test "preferences page includes JavaScript controllers" do + get preferences_onboarding_url + assert_response :success + + # Should include onboarding controller for dynamic updates + assert_select "[data-controller*='onboarding']" + assert_select "[data-controller*='time-series-chart']" + end + + test "all onboarding pages set correct layout" do + # Test that all onboarding pages use the wizard layout + get onboarding_url + assert_response :success + + get preferences_onboarding_url + assert_response :success + + get goals_onboarding_url + assert_response :success + + get trial_onboarding_url + assert_response :success + end + + test "onboarding pages require authentication" do + sign_out + + get onboarding_url + assert_redirected_to new_session_url + + get preferences_onboarding_url + assert_redirected_to new_session_url + + get goals_onboarding_url + assert_redirected_to new_session_url + + get trial_onboarding_url + assert_redirected_to new_session_url +end + + private + + def sign_out + delete session_path(@user.sessions.last) if @user.sessions.any? +end +end diff --git a/test/system/onboardings_test.rb b/test/system/onboardings_test.rb new file mode 100644 index 00000000..dd1c93c9 --- /dev/null +++ b/test/system/onboardings_test.rb @@ -0,0 +1,192 @@ +require "application_system_test_case" + +class OnboardingsTest < ApplicationSystemTestCase + setup do + @user = users(:family_admin) + @family = @user.family + + # Reset onboarding state + @user.update!(set_onboarding_preferences_at: nil) + + sign_in @user + end + + test "can complete the full onboarding flow" do + # Start at the main onboarding page + visit onboarding_path + + assert_text "Let's set up your account" + assert_button "Get started" + + # Navigate to preferences + click_button "Get started" + + assert_current_path preferences_onboarding_path + assert_text "Set your preferences" + + # Test that the chart renders without errors (this would catch the Series bug) + assert_selector "[data-controller='time-series-chart']" + + # Fill out preferences form + select "English", from: "user_family_attributes_locale" + select "United States Dollar (USD)", from: "user_family_attributes_currency" + select "MM/DD/YYYY", from: "user_family_attributes_date_format" + select "Light", from: "user_theme" + + # Submit preferences + click_button "Continue" + + # Should redirect to goals page + assert_current_path goals_onboarding_path + assert_text "What brings you to Maybe?" + end + + test "preferences page renders chart without errors" do + visit preferences_onboarding_path + + # This test specifically targets the Series model bug + # The chart should render without throwing JavaScript errors + assert_selector "[data-controller='time-series-chart']" + assert_selector "#previewChart" + + # Verify the chart data is properly formatted JSON + chart_element = find("[data-controller='time-series-chart']") + chart_data = chart_element["data-time-series-chart-data-value"] + + # Should be valid JSON + assert_nothing_raised do + JSON.parse(chart_data) + end + + # Verify the preview example shows + assert_text "Example" + assert_text "$2,325.25" + assert_text "+$78.90" + end + + test "can change currency and see preview update" do + visit preferences_onboarding_path + + # Change currency + select "Euro (EUR)", from: "user_family_attributes_currency" + + # The preview should update (this tests the JavaScript controller) + # Note: This would require the onboarding controller to handle currency changes + assert_text "Example" + end + + test "can change date format and see preview update" do + visit preferences_onboarding_path + + # Change date format + select "DD/MM/YYYY", from: "user_family_attributes_date_format" + + # The preview should update + assert_text "Example" + end + + test "can change theme" do + visit preferences_onboarding_path + + # Change theme + select "Dark", from: "user_theme" + + # Theme should be applied (this tests the JavaScript controller) + assert_text "Example" + end + + test "preferences form validation" do + visit preferences_onboarding_path + + # Clear required fields and try to submit + select "", from: "user_family_attributes_locale" + click_button "Continue" + + # Should stay on preferences page with validation errors + assert_current_path preferences_onboarding_path + end + + test "preferences form saves data correctly" do + visit preferences_onboarding_path + + # Fill out form with specific values + select "Spanish", from: "user_family_attributes_locale" + select "Euro (EUR)", from: "user_family_attributes_currency" + select "DD/MM/YYYY", from: "user_family_attributes_date_format" + select "Dark", from: "user_theme" + + click_button "Continue" + + # Verify data was saved + @family.reload + @user.reload + + assert_equal "es", @family.locale + assert_equal "EUR", @family.currency + assert_equal "DD/MM/YYYY", @family.date_format + assert_equal "dark", @user.theme + assert_not_nil @user.set_onboarding_preferences_at + end + + test "goals page renders correctly" do + # Complete preferences first + @user.update!(set_onboarding_preferences_at: Time.current) + + visit goals_onboarding_path + + assert_text "What brings you to Maybe?" + assert_button "Continue" + end + + test "trial page renders correctly" do + visit trial_onboarding_path + + assert_text "trial" # Adjust based on actual content + end + + test "navigation between onboarding steps" do + # Start at main onboarding + visit onboarding_path + click_button "Get started" + + # Should be at preferences + assert_current_path preferences_onboarding_path + + # Complete preferences + select "English", from: "user_family_attributes_locale" + select "United States Dollar (USD)", from: "user_family_attributes_currency" + select "MM/DD/YYYY", from: "user_family_attributes_date_format" + click_button "Continue" + + # Should be at goals + assert_current_path goals_onboarding_path + end + + test "onboarding nav shows correct steps" do + visit preferences_onboarding_path + + # Check that navigation shows current step + assert_selector ".onboarding-nav" # Adjust selector based on actual implementation + end + + test "logout option is available during onboarding" do + visit preferences_onboarding_path + + # Should have logout option + assert_link "Sign out" # Adjust based on actual implementation + end + + private + + def sign_in(user) + visit new_session_path + within "form" do + fill_in "Email", with: user.email + fill_in "Password", with: user_password_test + click_on "Log in" + end + + # Wait for successful login + assert_current_path root_path +end +end