1- import { describe , it , expect , vi , beforeEach } from "vitest" ;
2- import { render , screen } from "@testing-library/react" ;
1+ import type { DashboardData } from "@/lib/dashboard/dashboard-context" ;
32import { LocalDate } from "@js-joda/core" ;
3+ import { render , screen } from "@testing-library/react" ;
4+ import { beforeEach , describe , expect , it , vi } from "vitest" ;
45import Deltas from "./deltas" ;
5- import type { DashboardData } from "@/lib/dashboard/dashboard-context" ;
66
7- // Mock the dashboard hooks
87vi . mock ( "@/lib/dashboard/hooks" , ( ) => ( {
98 useDashboardData : vi . fn ( ) ,
109} ) ) ;
@@ -33,15 +32,32 @@ describe("Deltas", () => {
3332 } as any ,
3433 } ;
3534
35+ const withDeltas = ( overrides : Partial < DashboardData > = { } ) =>
36+ ( {
37+ ...defaultMockData ,
38+ deltas : [
39+ { period : "week" , description : "1 week ago" , delta : - 2 } ,
40+ { period : "month" , description : "1 month ago" , delta : - 5 } ,
41+ ] ,
42+ activeSlope : - 0.1 ,
43+ ...overrides ,
44+ } ) as any ;
45+
3646 beforeEach ( ( ) => {
3747 vi . clearAllMocks ( ) ;
3848 } ) ;
3949
40- it ( "returns null when no deltas" , ( ) => {
41- mockUseDashboardData . mockReturnValue ( defaultMockData as any ) ;
42-
43- const { container } = render ( < Deltas /> ) ;
44- expect ( container . firstChild ) . toBeNull ( ) ;
50+ it ( "shows weekly rate but no deltas when no deltas" , ( ) => {
51+ mockUseDashboardData . mockReturnValue ( {
52+ ...defaultMockData ,
53+ activeSlope : - 0.1 ,
54+ isMe : true ,
55+ } as any ) ;
56+ render ( < Deltas /> ) ;
57+ expect ( screen . getByText ( "Weight Changes Over Time" ) ) . toBeInTheDocument ( ) ;
58+ expect ( screen . getByText ( / Y o u a r e l o s i n g / ) ) . toBeInTheDocument ( ) ;
59+ expect ( screen . getByText ( / p e r w e e k / ) ) . toBeInTheDocument ( ) ;
60+ expect ( screen . queryByText ( / S i n c e .* a g o : / ) ) . not . toBeInTheDocument ( ) ;
4561 } ) ;
4662
4763 it ( "renders weight deltas with correct intended direction" , ( ) => {
@@ -52,9 +68,7 @@ describe("Deltas", () => {
5268 { period : "month" , description : "1 month ago" , delta : - 5 } ,
5369 ] ,
5470 } as any ) ;
55-
5671 render ( < Deltas /> ) ;
57-
5872 expect ( screen . getByText ( "Weight Changes Over Time" ) ) . toBeInTheDocument ( ) ;
5973 expect ( screen . getByText ( / S i n c e 1 w e e k a g o : / ) ) . toBeInTheDocument ( ) ;
6074 expect ( screen . getByText ( / S i n c e 1 m o n t h a g o : / ) ) . toBeInTheDocument ( ) ;
@@ -63,39 +77,33 @@ describe("Deltas", () => {
6377 it ( "renders fat percent deltas with negative intended direction" , ( ) => {
6478 mockUseDashboardData . mockReturnValue ( {
6579 ...defaultMockData ,
66- mode : [ "fatpercent" ] ,
80+ mode : [ "fatpercent" , ( ) => { } ] ,
6781 deltas : [
6882 { period : "week" , description : "1 week ago" , delta : - 0.5 } ,
6983 { period : "month" , description : "1 month ago" , delta : - 1.2 } ,
7084 ] ,
7185 } as any ) ;
72-
7386 render ( < Deltas /> ) ;
74-
7587 expect ( screen . getByText ( "Fat % Changes Over Time" ) ) . toBeInTheDocument ( ) ;
7688 } ) ;
7789
7890 it ( "renders fat mass deltas with negative intended direction" , ( ) => {
7991 mockUseDashboardData . mockReturnValue ( {
8092 ...defaultMockData ,
81- mode : [ "fatmass" ] ,
93+ mode : [ "fatmass" , ( ) => { } ] ,
8294 deltas : [ { period : "week" , description : "1 week ago" , delta : - 2.5 } ] ,
8395 } as any ) ;
84-
8596 render ( < Deltas /> ) ;
86-
8797 expect ( screen . getByText ( "Fat Mass Changes Over Time" ) ) . toBeInTheDocument ( ) ;
8898 } ) ;
8999
90100 it ( "renders lean mass deltas with positive intended direction" , ( ) => {
91101 mockUseDashboardData . mockReturnValue ( {
92102 ...defaultMockData ,
93- mode : [ "leanmass" ] ,
103+ mode : [ "leanmass" , ( ) => { } ] ,
94104 deltas : [ { period : "week" , description : "1 week ago" , delta : 1.5 } ] ,
95105 } as any ) ;
96-
97106 render ( < Deltas /> ) ;
98-
99107 expect ( screen . getByText ( "Lean Mass Changes Over Time" ) ) . toBeInTheDocument ( ) ;
100108 } ) ;
101109
@@ -118,10 +126,7 @@ describe("Deltas", () => {
118126 ] ,
119127 deltas : [ { period : "week" , description : "1 week ago" , delta : - 2 } ] ,
120128 } as any ) ;
121-
122129 render ( < Deltas /> ) ;
123-
124- // Should calculate intended direction as negative (160 - 180 = -20)
125130 expect ( screen . getByText ( / S i n c e 1 w e e k a g o : / ) ) . toBeInTheDocument ( ) ;
126131 } ) ;
127132
@@ -135,9 +140,7 @@ describe("Deltas", () => {
135140 } as any ,
136141 deltas : [ { period : "week" , description : "1 week ago" , delta : - 2 } ] ,
137142 } as any ) ;
138-
139143 render ( < Deltas /> ) ;
140-
141144 expect ( screen . getByText ( / S i n c e 1 w e e k a g o : / ) ) . toBeInTheDocument ( ) ;
142145 } ) ;
143146
@@ -151,10 +154,7 @@ describe("Deltas", () => {
151154 } as any ,
152155 deltas : [ { period : "week" , description : "1 week ago" , delta : - 0.9 } ] ,
153156 } as any ) ;
154-
155157 render ( < Deltas /> ) ;
156-
157- // formatMeasurement should be called with metric: true
158158 expect ( screen . getByText ( / S i n c e 1 w e e k a g o : / ) ) . toBeInTheDocument ( ) ;
159159 } ) ;
160160
@@ -168,14 +168,85 @@ describe("Deltas", () => {
168168 { period : "year" , description : "1 year ago" , delta : - 30 } ,
169169 ] ,
170170 } as any ) ;
171-
172171 render ( < Deltas /> ) ;
173-
174172 const deltas = screen . getAllByText ( / S i n c e .* a g o : / ) ;
175173 expect ( deltas ) . toHaveLength ( 4 ) ;
176174 expect ( deltas [ 0 ] ) . toHaveTextContent ( "Since 1 week ago:" ) ;
177175 expect ( deltas [ 1 ] ) . toHaveTextContent ( "Since 1 month ago:" ) ;
178176 expect ( deltas [ 2 ] ) . toHaveTextContent ( "Since 3 months ago:" ) ;
179177 expect ( deltas [ 3 ] ) . toHaveTextContent ( "Since 1 year ago:" ) ;
180178 } ) ;
179+
180+ it ( "shows weekly rate sentence for weight" , ( ) => {
181+ mockUseDashboardData . mockReturnValue (
182+ withDeltas ( {
183+ mode : [ "weight" , ( ) => { } ] ,
184+ isMe : true ,
185+ activeSlope : - 0.1 ,
186+ profile : { ...( defaultMockData . profile as any ) , useMetric : false } as any ,
187+ } ) as any ,
188+ ) ;
189+ render ( < Deltas /> ) ;
190+ expect ( screen . getByText ( / Y o u a r e l o s i n g / ) ) . toBeInTheDocument ( ) ;
191+ expect ( screen . getByText ( "0.7 lb" ) ) . toBeInTheDocument ( ) ;
192+ expect ( screen . getAllByText ( ( content ) => content . includes ( "per week" ) ) . length ) . toBeGreaterThan ( 0 ) ;
193+ } ) ;
194+
195+ it ( "shows weekly rate sentence for fat percent" , ( ) => {
196+ mockUseDashboardData . mockReturnValue (
197+ withDeltas ( {
198+ mode : [ "fatpercent" , ( ) => { } ] ,
199+ isMe : true ,
200+ activeSlope : 0.02 ,
201+ profile : { ...( defaultMockData . profile as any ) , useMetric : false } as any ,
202+ } ) as any ,
203+ ) ;
204+ render ( < Deltas /> ) ;
205+ expect ( screen . getByText ( / Y o u a r e g a i n i n g / ) ) . toBeInTheDocument ( ) ;
206+ expect ( screen . getByText ( ( _ , node ) => ! ! node && node . tagName === "STRONG" && / % $ / . test ( node . textContent || "" ) ) ) . toBeInTheDocument ( ) ;
207+ expect ( screen . getAllByText ( ( content ) => content . includes ( "per week" ) ) . length ) . toBeGreaterThan ( 0 ) ;
208+ expect ( screen . getByText ( / o f b o d y f a t / ) ) . toBeInTheDocument ( ) ;
209+ } ) ;
210+
211+ it ( "shows weekly rate sentence for fat mass (metric)" , ( ) => {
212+ mockUseDashboardData . mockReturnValue (
213+ withDeltas ( {
214+ mode : [ "fatmass" , ( ) => { } ] ,
215+ isMe : true ,
216+ activeSlope : - 0.05 ,
217+ profile : { ...( defaultMockData . profile as any ) , useMetric : true } as any ,
218+ } ) as any ,
219+ ) ;
220+ render ( < Deltas /> ) ;
221+ expect ( screen . getByText ( / Y o u a r e l o s i n g / ) ) . toBeInTheDocument ( ) ;
222+ expect ( screen . getByText ( ( _ , node ) => ! ! node && node . tagName === "STRONG" && / k g $ / . test ( node . textContent || "" ) ) ) . toBeInTheDocument ( ) ;
223+ expect ( screen . getAllByText ( ( content ) => content . includes ( "per week" ) ) . length ) . toBeGreaterThan ( 0 ) ;
224+ expect ( screen . getByText ( / o f f a t m a s s / ) ) . toBeInTheDocument ( ) ;
225+ } ) ;
226+
227+ it ( "shows weekly rate sentence for lean mass (metric)" , ( ) => {
228+ mockUseDashboardData . mockReturnValue (
229+ withDeltas ( {
230+ mode : [ "leanmass" , ( ) => { } ] ,
231+ isMe : true ,
232+ activeSlope : 0.03 ,
233+ profile : { ...( defaultMockData . profile as any ) , useMetric : true } as any ,
234+ } ) as any ,
235+ ) ;
236+ render ( < Deltas /> ) ;
237+ expect ( screen . getByText ( / Y o u a r e g a i n i n g / ) ) . toBeInTheDocument ( ) ;
238+ expect ( screen . getByText ( / o f l e a n m a s s / ) ) . toBeInTheDocument ( ) ;
239+ } ) ;
240+
241+ it ( "uses third-person wording when not viewing own profile" , ( ) => {
242+ mockUseDashboardData . mockReturnValue (
243+ withDeltas ( {
244+ isMe : false ,
245+ activeSlope : - 0.1 ,
246+ profile : { ...( defaultMockData . profile as any ) , firstName : "Test" , useMetric : false } as any ,
247+ } ) as any ,
248+ ) ;
249+ render ( < Deltas /> ) ;
250+ expect ( screen . getByText ( / T e s t i s l o s i n g / ) ) . toBeInTheDocument ( ) ;
251+ } ) ;
181252} ) ;
0 commit comments