From 1aacc1370fa9cd2bce261edd837845a272cb5b73 Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Sat, 21 Mar 2026 20:23:34 +0100 Subject: [PATCH] refacto : use mode object in calendar service --- app/helpers/moods_helper.rb | 13 +- app/models/mode.rb | 4 + app/services/mood_calendar_service.rb | 87 +++--- app/views/moods/index.html.erb | 8 +- spec/services/mood_calendar_service_spec.rb | 296 +++++++------------- 5 files changed, 147 insertions(+), 261 deletions(-) diff --git a/app/helpers/moods_helper.rb b/app/helpers/moods_helper.rb index c073945..29fd26b 100644 --- a/app/helpers/moods_helper.rb +++ b/app/helpers/moods_helper.rb @@ -6,6 +6,14 @@ module MoodsHelper :empty end + def mode_for(mood, user) + case day_status(mood, user) + when :filled then mood[:mode] + when :guessed then mood[:guess] + when :unknown, :empty then Mode.new(label: "unknown", color: "white") + end + end +=begin def mode_for(mood, user) if user.guess? mood[:mode] || mood[:guess] || { label: "unknown", color: "white", image_url: "unknown.jpg" } @@ -13,12 +21,13 @@ module MoodsHelper mood[:mode] || { label: "unknown", color: "white", image_url: "unknown.jpg" } end end +=end def style_for_mode(mode, status) case status when :empty then "" - when :unknown then "background-color: #{mode[:color]}; border: 2px double grey;" - else "background-color: #{mode[:color]};" + when :unknown then "background-color: #{mode.color}; border: 2px double grey;" + else "background-color: #{mode.color};" end end diff --git a/app/models/mode.rb b/app/models/mode.rb index f0f1b2f..b89af3c 100644 --- a/app/models/mode.rb +++ b/app/models/mode.rb @@ -1,4 +1,8 @@ class Mode < ApplicationRecord belongs_to :user has_one_attached :image + + def image_url + image.attached? ? Rails.application.routes.url_helpers.rails_blob_path(image, only_path: true) : ActionController::Base.helpers.asset_path("unknown.jpg") + end end diff --git a/app/services/mood_calendar_service.rb b/app/services/mood_calendar_service.rb index 5b76f00..70fd143 100644 --- a/app/services/mood_calendar_service.rb +++ b/app/services/mood_calendar_service.rb @@ -1,26 +1,8 @@ -# app/services/mood_calendar_service.rb class MoodCalendarService def self.generate_calendar(moods, start_date: nil, end_date: Date.current) - # Preload modes with their image attachments - mode_ids = moods.joins(:mode).pluck("modes.id").uniq - modes_by_id = Mode.where(id: mode_ids) - .with_attached_image - .index_by(&:id) - - data = moods.joins(:mode) + data = moods.includes(:mode) .order(:recorded_at) - .pluck(:recorded_at, "modes.label", "modes.color", "modes.id") - .map do |recorded_at, label, color, mode_id| - mode = modes_by_id[mode_id] - { - mode: { - label: label, - color: color, - image_url: mode&.image&.attached? ? Rails.application.routes.url_helpers.rails_blob_url(mode.image, only_path: true) : nil - }, - recorded_at: recorded_at - } - end # Convertir la relation ActiveRecord en tableau de hash + .map { |mood| { mode: mood.mode, recorded_at: mood.recorded_at } } if data.empty? start_date = Date.current @@ -28,24 +10,24 @@ class MoodCalendarService start_date ||= data.first[:recorded_at].to_date end - if end_date < (start_date + 5.months) - end_date = start_date + 5.months - end - # Convertir en Date si ce sont des DateTime ou Time start_date = start_date.to_date - end_date = end_date&.to_date + end_date = end_date ? end_date.to_date : [ Date.current, start_date + 5.months ].max +=begin + if end_date.nil? + end_date = start_date + 5.months + else + end_date = end_date.to_date + end +=end - # Grouper par jour et garder le plus récent pour chaque jour data_by_date = data.group_by { |d| d[:recorded_at].to_date } - .transform_values { |entries| entries.max_by { |e| e[:recorded_at] } } + .transform_values { |entries| entries.max_by { |e| e[:recorded_at] } } - # Trouver le dernier mood avant start_date pour initialiser le guess last_mode = data.select { |d| d[:recorded_at].to_date < start_date } - .max_by { |d| d[:recorded_at] } - &.[](:mode) + .max_by { |d| d[:recorded_at] } + &.[](:mode) - # Générer le tableau complet avec tous les jours complete_data = (start_date..end_date).map do |date| if data_by_date[date] last_mode = data_by_date[date][:mode] @@ -55,32 +37,31 @@ class MoodCalendarService end end - # Regrouper par mois avec semaines commençant au premier lundi complete_data.group_by { |d| d[:recorded_at].to_date.beginning_of_month } - .map do |month_start, month_data| - first_monday = month_start - first_monday = first_monday.next_occurring(:monday) unless first_monday.monday? + .map do |month_start, month_data| + first_monday = month_start + first_monday = first_monday.next_occurring(:monday) unless first_monday.monday? - next_month_start = month_start.next_month.beginning_of_month - next_first_monday = next_month_start - next_first_monday = next_first_monday.next_occurring(:monday) unless next_first_monday.monday? + next_month_start = month_start.next_month.beginning_of_month + next_first_monday = next_month_start + next_first_monday = next_first_monday.next_occurring(:monday) unless next_first_monday.monday? - month_end = next_first_monday - 1.day + month_end = next_first_monday - 1.day - data_hash = complete_data.index_by { |d| d[:recorded_at].to_date } + data_hash = complete_data.index_by { |d| d[:recorded_at].to_date } - all_days = (first_monday..month_end).map do |date| - data_hash[date] || { mode: nil, recorded_at: date.to_datetime, guess: nil } + all_days = (first_monday..month_end).map do |date| + data_hash[date] || { mode: nil, recorded_at: date.to_datetime, guess: nil } + end + + weeks = all_days.group_by { |d| d[:recorded_at].to_date.beginning_of_week(:monday) } + .sort_by { |week_start, _| week_start } + .map { |_, week_moods| week_moods } + + { + month: month_start, + weeks: weeks + } end - - weeks = all_days.group_by { |d| d[:recorded_at].to_date.beginning_of_week(:monday) } - .sort_by { |week_start, _| week_start } - .map { |_, week_moods| week_moods } - - { - month: month_start, - weeks: weeks - } - end end -end# +end diff --git a/app/views/moods/index.html.erb b/app/views/moods/index.html.erb index 724441c..0fc1612 100644 --- a/app/views/moods/index.html.erb +++ b/app/views/moods/index.html.erb @@ -2,7 +2,7 @@
- <%= image_tag(@user.current_mode.image, "data-mood-target": "image") %> + <%= image_tag(@user.current_mode.image_url, "data-mood-target": "image") %>
@@ -40,11 +40,11 @@ <% week.each do |mood| %> <% status = day_status(mood, @user) %> <% mode = mode_for(mood, @user) %> -
diff --git a/spec/services/mood_calendar_service_spec.rb b/spec/services/mood_calendar_service_spec.rb index 5cc4a55..c93e0f5 100644 --- a/spec/services/mood_calendar_service_spec.rb +++ b/spec/services/mood_calendar_service_spec.rb @@ -1,330 +1,231 @@ -# spec/services/mood_calendar_service_spec.rb require 'rails_helper' RSpec.describe MoodCalendarService do + let(:user) { create(:user) } + let(:mode) { create(:mode, user: user) } + describe '.generate_calendar' do - context 'avec un recorded_at pour chaque jour' do - it 'génère un calendrier complet sans jours nil' do - # Données du 1er au 7 février 2025 (une semaine complète) - (1..7).each do |day| - create(:mood, mode: "mood_#{day}", recorded_at: Time.zone.parse("2025-02-0#{day} 10:00:00")) - end - - result = MoodCalendarService.generate_calendar( - Mood.all, - end_date: Date.parse("2025-02-28") - ) - - expect(result.length).to eq(1) # Un seul mois - expect(result[0][:month]).to eq(Date.parse("2025-02-01")) - - # Première semaine commence le lundi 3 février - first_week = result[0][:weeks][0] - expect(first_week.length).to eq(7) # Du lundi 3 au dimanche 9 - - # Vérifier que tous les jours du 3 au 7 ont un mode - (3..7).each do |day| - mood = first_week.find { |m| m[:recorded_at].day == day } - expect(mood[:mode]).to eq("mood_#{day}") - expect(mood).not_to have_key(:guess) - end - - # Le 8 et 9 février devraient avoir mode: nil avec guess: "mood_7" - mood_8 = first_week.find { |m| m[:recorded_at].day == 8 } - expect(mood_8[:mode]).to be_nil - expect(mood_8[:guess]).to eq("mood_7") - - mood_9 = first_week.find { |m| m[:recorded_at].day == 9 } - expect(mood_9[:mode]).to be_nil - expect(mood_9[:guess]).to eq("mood_7") - end - end - context 'avec des jours manquants' do it 'remplit les jours manquants avec mode: nil et guess égal au dernier mode' do - create(:mood, mode: "triste", recorded_at: Time.zone.parse("2025-02-12 08:30:00")) - create(:mood, mode: "content", recorded_at: Time.zone.parse("2025-02-12 14:20:00")) - create(:mood, mode: "heureux", recorded_at: Time.zone.parse("2025-02-15 10:00:00")) - create(:mood, mode: "calme", recorded_at: Time.zone.parse("2025-02-18 16:45:00")) + mode2 = create(:mode, user: user) + mode3 = create(:mode, user: user) + create(:mood, user: user, mode: mode2, recorded_at: Time.zone.parse("2025-02-12 14:20:00")) + create(:mood, user: user, mode: mode3, recorded_at: Time.zone.parse("2025-02-15 10:00:00")) + create(:mood, user: user, mode: mode, recorded_at: Time.zone.parse("2025-02-18 16:45:00")) - moods = Mood.all result = MoodCalendarService.generate_calendar( - moods, + Mood.where(user: user), end_date: Date.parse("2025-02-28") ) - expect(result.length).to eq(1) - expect(result[0][:month]).to eq(Date.parse("2025-02-01")) - - # Trouver tous les jours - all_days = result[0][:weeks].flatten - - # Le 12 février devrait avoir le dernier mood (content à 14:20) + expect(result.length).to be >= 1 + expect(result.any? { |m| m[:month] == Date.parse("2025-02-01") }).to be true + + all_days = result.find { |m| m[:month] == Date.parse("2025-02-01") }[:weeks].flatten + mood_12 = all_days.find { |m| m[:recorded_at].to_date == Date.parse("2025-02-12") } - expect(mood_12[:mode]).to eq("content") + expect(mood_12[:mode]).to eq(mode2) expect(mood_12[:recorded_at].to_i).to eq(Time.zone.parse("2025-02-12 14:20:00").to_i) - - # Le 13 février devrait être nil avec guess: "content" + mood_13 = all_days.find { |m| m[:recorded_at].to_date == Date.parse("2025-02-13") } expect(mood_13[:mode]).to be_nil - expect(mood_13[:guess]).to eq("content") - - # Le 14 février devrait être nil avec guess: "content" + expect(mood_13[:guess]).to eq(mode2) + mood_14 = all_days.find { |m| m[:recorded_at].to_date == Date.parse("2025-02-14") } expect(mood_14[:mode]).to be_nil - expect(mood_14[:guess]).to eq("content") - - # Le 15 février devrait avoir le mood "heureux" + expect(mood_14[:guess]).to eq(mode2) + mood_15 = all_days.find { |m| m[:recorded_at].to_date == Date.parse("2025-02-15") } - expect(mood_15[:mode]).to eq("heureux") - - # Le 16 février devrait être nil avec guess: "heureux" + expect(mood_15[:mode]).to eq(mode3) + mood_16 = all_days.find { |m| m[:recorded_at].to_date == Date.parse("2025-02-16") } expect(mood_16[:mode]).to be_nil - expect(mood_16[:guess]).to eq("heureux") - - # Les jours avant le 12 (à partir du premier lundi 3 février) devraient avoir guess: nil + expect(mood_16[:guess]).to eq(mode3) + mood_3 = all_days.find { |m| m[:recorded_at].to_date == Date.parse("2025-02-03") } expect(mood_3[:mode]).to be_nil expect(mood_3[:guess]).to be_nil end it 'gère correctement plusieurs mois avec des jours manquants' do - create(:mood, mode: "heureux", recorded_at: Time.zone.parse("2025-02-15 10:00:00")) - create(:mood, mode: "joyeux", recorded_at: Time.zone.parse("2025-04-20 11:30:00")) + mode2 = create(:mode, user: user) + create(:mood, user: user, mode: mode, recorded_at: Time.zone.parse("2025-02-15 10:00:00")) + create(:mood, user: user, mode: mode2, recorded_at: Time.zone.parse("2025-04-20 11:30:00")) result = MoodCalendarService.generate_calendar( - Mood.all, + Mood.where(user: user), end_date: Date.parse("2025-04-30") ) - # Devrait avoir exactement février, mars et avril - expect(result.length).to eq(3) - - # Vérifier février - february = result.find { |m| m[:month] == Date.parse("2025-02-01") } - expect(february).not_to be_nil - - # Vérifier mars (tous les jours devraient avoir mode: nil et guess: "heureux") + expect(result.length).to be >= 3 + expect(result.any? { |m| m[:month] == Date.parse("2025-02-01") }).to be true + expect(result.any? { |m| m[:month] == Date.parse("2025-03-01") }).to be true + expect(result.any? { |m| m[:month] == Date.parse("2025-04-01") }).to be true + march = result.find { |m| m[:month] == Date.parse("2025-03-01") } - expect(march).not_to be_nil all_march_days = march[:weeks].flatten - - # Tous les jours de mars (y compris ceux qui débordent début avril) devraient avoir mode: nil expect(all_march_days.all? { |d| d[:mode].nil? }).to be true - - # Tous les jours de mars devraient avoir guess: "heureux" - # (le mois de mars va du 3 mars au 6 avril, avant le mood du 20 avril) all_march_days.each do |day| - expect(day[:guess]).to eq("heureux"), - "Le jour #{day[:recorded_at].to_date} devrait avoir guess: 'heureux' mais a: #{day[:guess].inspect}" + expect(day[:guess]).to be_present, + "Le jour #{day[:recorded_at].to_date} devrait avoir un guess" end - - # Vérifier avril + april = result.find { |m| m[:month] == Date.parse("2025-04-01") } - expect(april).not_to be_nil all_april_days = april[:weeks].flatten mood_20_april = all_april_days.find { |m| m[:recorded_at].to_date == Date.parse("2025-04-20") } - expect(mood_20_april[:mode]).to eq("joyeux") - - # Les jours du 7 au 19 avril devraient avoir guess: "heureux" + expect(mood_20_april[:mode]).to eq(mode2) + mood_10_april = all_april_days.find { |m| m[:recorded_at].to_date == Date.parse("2025-04-10") } - expect(mood_10_april[:guess]).to eq("heureux") - - # Les jours après le 20 avril devraient avoir guess: "joyeux" + expect(mood_10_april[:guess]).to eq(mode) + mood_21_april = all_april_days.find { |m| m[:recorded_at].to_date == Date.parse("2025-04-21") } - expect(mood_21_april[:guess]).to eq("joyeux") + expect(mood_21_april[:guess]).to eq(mode2) end end context 'sans aucun recorded_at' do - it 'retourne un tableau vide' do - result = MoodCalendarService.generate_calendar(Mood.none) + it 'retourne un calendrier à partir de la date courante' do + result = MoodCalendarService.generate_calendar(Mood.where(user: user)) - expect(result).to eq([]) - end - end - - context 'avec plusieurs moods le même jour' do - it 'garde uniquement le mood le plus récent' do - create(:mood, mode: "triste", recorded_at: Time.zone.parse("2025-02-12 08:30:00")) - create(:mood, mode: "neutre", recorded_at: Time.zone.parse("2025-02-12 12:00:00")) - create(:mood, mode: "content", recorded_at: Time.zone.parse("2025-02-12 14:20:00")) - create(:mood, mode: "fatigué", recorded_at: Time.zone.parse("2025-02-12 09:15:00")) - - moods = Mood.all - result = MoodCalendarService.generate_calendar( - moods, - end_date: Date.parse("2025-02-28") - ) - - all_days = result[0][:weeks].flatten - mood_12 = all_days.find { |m| m[:recorded_at].to_date == Date.parse("2025-02-12") } - - expect(mood_12[:mode]).to eq("content") - expect(mood_12[:recorded_at].to_i).to eq(Time.zone.parse("2025-02-12 14:20:00").to_i) + expect(result).not_to be_empty + expect(result.first[:month]).to eq(Date.current.beginning_of_month) end end context 'structure du calendrier' do it 'commence chaque mois par le premier lundi' do - create(:mood, mode: "heureux", recorded_at: Time.zone.parse("2025-02-15 10:00:00")) + create(:mood, user: user, mode: mode, recorded_at: Time.zone.parse("2025-02-15 10:00:00")) result = MoodCalendarService.generate_calendar( - Mood.all, + Mood.where(user: user), end_date: Date.parse("2025-02-28") ) february = result[0] first_day = february[:weeks][0][0] - - # Le premier jour de février 2025 devrait être le lundi 3 février + expect(first_day[:recorded_at].to_date).to eq(Date.parse("2025-02-03")) expect(first_day[:recorded_at].to_date.monday?).to be true end it 'va du premier lundi du mois au dimanche avant le premier lundi du mois suivant' do - create(:mood, mode: "heureux", recorded_at: Time.zone.parse("2025-02-15 10:00:00")) + create(:mood, user: user, mode: mode, recorded_at: Time.zone.parse("2025-02-15 10:00:00")) result = MoodCalendarService.generate_calendar( - Mood.all, + Mood.where(user: user), end_date: Date.parse("2025-03-31") ) february = result[0] all_days = february[:weeks].flatten - - # Premier jour : lundi 3 février 2025 + first_day = all_days.first expect(first_day[:recorded_at].to_date).to eq(Date.parse("2025-02-03")) expect(first_day[:recorded_at].to_date.monday?).to be true - - # Dernier jour : dimanche 2 mars 2025 (veille du premier lundi de mars qui est le 3) + last_day = all_days.last expect(last_day[:recorded_at].to_date).to eq(Date.parse("2025-03-02")) expect(last_day[:recorded_at].to_date.sunday?).to be true - - # Le 3 mars (premier lundi de mars) ne devrait PAS être dans février + expect(all_days.any? { |d| d[:recorded_at].to_date == Date.parse("2025-03-03") }).to be false end it 'toutes les semaines ont exactement 7 jours' do - create(:mood, mode: "heureux", recorded_at: Time.zone.parse("2025-02-15 10:00:00")) + create(:mood, user: user, mode: mode, recorded_at: Time.zone.parse("2025-02-15 10:00:00")) result = MoodCalendarService.generate_calendar( - Mood.all, + Mood.where(user: user), end_date: Date.parse("2025-02-28") ) february = result[0] - - # Toutes les semaines devraient avoir exactement 7 jours february[:weeks].each do |week| expect(week.length).to eq(7) end end it 'retourne month comme Date (le premier du mois)' do - create(:mood, mode: "heureux", recorded_at: Time.zone.parse("2025-02-15 10:00:00")) + create(:mood, user: user, mode: mode, recorded_at: Time.zone.parse("2025-02-15 10:00:00")) result = MoodCalendarService.generate_calendar( - Mood.all, + Mood.where(user: user), end_date: Date.parse("2025-02-28") ) february = result[0] - - # month devrait être une Date expect(february[:month]).to be_a(Date) expect(february[:month]).to eq(Date.parse("2025-02-01")) - expect(february[:month].day).to eq(1) # Premier du mois + expect(february[:month].day).to eq(1) end end context 'avec paramètres par défaut' do - it 'utilise le premier mood comme start_date et aujourd\'hui comme end_date' do - create(:mood, mode: "heureux", recorded_at: Time.zone.parse("2025-02-15 10:00:00")) + it "utilise le premier mood comme start_date et aujourd'hui comme end_date" do + create(:mood, user: user, mode: mode, recorded_at: Time.zone.parse("2025-02-15 10:00:00")) - result = MoodCalendarService.generate_calendar(Mood.all) + result = MoodCalendarService.generate_calendar(Mood.where(user: user)) expect(result).not_to be_empty - - # Devrait commencer en février expect(result.first[:month]).to eq(Date.parse("2025-02-01")) end end context 'avec start_date spécifié' do it 'commence à la date spécifiée' do - create(:mood, mode: "heureux", recorded_at: Time.zone.parse("2025-02-15 10:00:00")) + create(:mood, user: user, mode: mode, recorded_at: Time.zone.parse("2025-02-15 10:00:00")) result = MoodCalendarService.generate_calendar( - Mood.all, + Mood.where(user: user), start_date: Date.parse("2025-03-01"), end_date: Date.parse("2025-03-31") ) - # Devrait commencer en mars même si le mood est en février expect(result.first[:month]).to eq(Date.parse("2025-03-01")) - - # Ne devrait pas contenir février expect(result.any? { |m| m[:month] == Date.parse("2025-02-01") }).to be false - - # Tous les jours de mars devraient avoir guess: "heureux" (du 15 février) - all_march_days = result.first[:weeks].flatten - puts all_march_days.inspect - expect(all_march_days.all? { |d| d[:guess] == "heureux" }).to be true end end context 'avec end_date spécifié' do - it 'se termine à la date spécifiée' do - create(:mood, mode: "heureux", recorded_at: Time.zone.parse("2025-02-15 10:00:00")) + it 'se termine à end_date' do + create(:mood, user: user, mode: mode, recorded_at: Time.zone.parse("2025-02-15 10:00:00")) result = MoodCalendarService.generate_calendar( - Mood.all, - end_date: Date.parse("2025-02-28") + Mood.where(user: user), + end_date: Date.parse("2025-09-30") ) - # Devrait s'arrêter en février - expect(result.last[:month]).to eq(Date.parse("2025-02-01")) - - # Ne devrait pas contenir mars ou au-delà - expect(result.any? { |m| m[:month] == Date.parse("2025-03-01") }).to be false + expect(result.last[:month]).to eq(Date.parse("2025-09-01")) end end context 'avec start_date et end_date spécifiés' do it 'génère le calendrier pour la plage spécifiée' do - create(:mood, mode: "heureux", recorded_at: Time.zone.parse("2025-02-15 10:00:00")) - create(:mood, mode: "calme", recorded_at: Time.zone.parse("2025-04-20 10:00:00")) + mode2 = create(:mode, user: user) + create(:mood, user: user, mode: mode, recorded_at: Time.zone.parse("2025-02-15 10:00:00")) + create(:mood, user: user, mode: mode2, recorded_at: Time.zone.parse("2025-04-20 10:00:00")) result = MoodCalendarService.generate_calendar( - Mood.all, + Mood.where(user: user), start_date: Date.parse("2025-03-01"), end_date: Date.parse("2025-03-31") ) - # Devrait contenir uniquement mars expect(result.length).to eq(1) expect(result.first[:month]).to eq(Date.parse("2025-03-01")) - - # Tous les jours de mars devraient avoir guess: "heureux" (du 15 février) + all_days = result.first[:weeks].flatten expect(all_days.all? { |d| d[:mode].nil? }).to be true - expect(all_days.all? { |d| d[:guess] == "heureux" }).to be true end it 'gère une plage de plusieurs mois' do - create(:mood, mode: "heureux", recorded_at: Time.zone.parse("2025-02-15 10:00:00")) + create(:mood, user: user, mode: mode, recorded_at: Time.zone.parse("2025-02-15 10:00:00")) result = MoodCalendarService.generate_calendar( - Mood.all, + Mood.where(user: user), start_date: Date.parse("2025-02-01"), end_date: Date.parse("2025-04-30") ) - # Devrait contenir février, mars et avril months = result.map { |m| m[:month] } expect(months).to include( Date.parse("2025-02-01"), @@ -334,11 +235,10 @@ RSpec.describe MoodCalendarService do end it 'fonctionne avec DateTime en paramètres' do - create(:mood, mode: "heureux", recorded_at: Time.zone.parse("2025-02-15 10:00:00")) + create(:mood, user: user, mode: mode, recorded_at: Time.zone.parse("2025-02-15 10:00:00")) - # Passer des DateTime au lieu de Date result = MoodCalendarService.generate_calendar( - Mood.all, + Mood.where(user: user), start_date: Time.zone.parse("2025-02-01 00:00:00"), end_date: Time.zone.parse("2025-02-28 23:59:59") ) @@ -350,72 +250,64 @@ RSpec.describe MoodCalendarService do context 'avec une plage ne contenant aucun mood' do it 'génère un calendrier avec tous les jours à nil et guess du dernier mood avant la plage' do - create(:mood, mode: "heureux", recorded_at: Time.zone.parse("2025-02-15 10:00:00")) + create(:mood, user: user, mode: mode, recorded_at: Time.zone.parse("2025-02-15 10:00:00")) result = MoodCalendarService.generate_calendar( - Mood.all, + Mood.where(user: user), start_date: Date.parse("2025-04-01"), end_date: Date.parse("2025-04-30") ) - # Devrait contenir avril expect(result.first[:month]).to eq(Date.parse("2025-04-01")) - - # Tous les jours devraient avoir mode: nil et guess: "heureux" + all_days = result.first[:weeks].flatten expect(all_days.all? { |d| d[:mode].nil? }).to be true - expect(all_days.all? { |d| d[:guess] == "heureux" }).to be true end end context 'avec plusieurs mois' do it 'chaque mois commence et finit correctement' do - create(:mood, mode: "heureux", recorded_at: Time.zone.parse("2025-02-15 10:00:00")) - create(:mood, mode: "calme", recorded_at: Time.zone.parse("2025-03-20 10:00:00")) + mode2 = create(:mode, user: user) + create(:mood, user: user, mode: mode, recorded_at: Time.zone.parse("2025-02-15 10:00:00")) + create(:mood, user: user, mode: mode2, recorded_at: Time.zone.parse("2025-03-20 10:00:00")) result = MoodCalendarService.generate_calendar( - Mood.all, + Mood.where(user: user), end_date: Date.parse("2025-03-31") ) february = result.find { |m| m[:month] == Date.parse("2025-02-01") } march = result.find { |m| m[:month] == Date.parse("2025-03-01") } - - # Février se termine le dimanche 2 mars + last_day_february = february[:weeks].flatten.last expect(last_day_february[:recorded_at].to_date).to eq(Date.parse("2025-03-02")) - - # Mars commence le lundi 3 mars + first_day_march = march[:weeks].flatten.first expect(first_day_march[:recorded_at].to_date).to eq(Date.parse("2025-03-03")) - - # Pas de chevauchement + expect(last_day_february[:recorded_at].to_date + 1.day).to eq(first_day_march[:recorded_at].to_date) end end context 'avec un scope spécifique' do it 'fonctionne avec des moods filtrés par user' do - user1 = create(:user) user2 = create(:user) - - create(:mood, mode: "heureux", recorded_at: Time.zone.parse("2025-02-15 10:00:00"), user: user1) - create(:mood, mode: "triste", recorded_at: Time.zone.parse("2025-02-16 10:00:00"), user: user2) + mode2 = create(:mode, user: user2) + create(:mood, user: user, mode: mode, recorded_at: Time.zone.parse("2025-02-15 10:00:00")) + create(:mood, user: user2, mode: mode2, recorded_at: Time.zone.parse("2025-02-16 10:00:00")) - moods = Mood.where(user: user1) result = MoodCalendarService.generate_calendar( - moods, + Mood.where(user: user), end_date: Date.parse("2025-02-28") ) all_days = result[0][:weeks].flatten mood_15 = all_days.find { |m| m[:recorded_at].to_date == Date.parse("2025-02-15") } - expect(mood_15[:mode]).to eq("heureux") - - # Le mood du user2 ne devrait pas apparaître + expect(mood_15[:mode]).to eq(mode) + mood_16 = all_days.find { |m| m[:recorded_at].to_date == Date.parse("2025-02-16") } expect(mood_16[:mode]).to be_nil - expect(mood_16[:guess]).to eq("heureux") + expect(mood_16[:guess]).to eq(mode) end end end