From ba5b02c1fdfb371392b0bef8f38707a9040a47f9 Mon Sep 17 00:00:00 2001 From: Stefan Poindl Date: Thu, 4 Dec 2025 19:14:29 +0100 Subject: [PATCH 1/2] fix stale weight update message --- src/lib/component/weight/WeightScore.svelte | 46 +++++++-------------- src/routes/(app)/+page.svelte | 3 +- 2 files changed, 16 insertions(+), 33 deletions(-) diff --git a/src/lib/component/weight/WeightScore.svelte b/src/lib/component/weight/WeightScore.svelte index 21a37775..1544e65f 100644 --- a/src/lib/component/weight/WeightScore.svelte +++ b/src/lib/component/weight/WeightScore.svelte @@ -1,5 +1,5 @@
Current Weight
- {#if (weightTracker && 'id' in weightTracker) || lastWeightTracker} - {#if weightTracker && 'id' in weightTracker} - - {:else if lastWeightTracker} - - {/if} - {:else} - - - {/if} + kg @@ -57,15 +45,11 @@
- {#if weightTracker && 'id' in weightTracker} - - Last update: Today. - {:else if lastWeightTracker} - {@const lastEntryDayDiff = differenceInDays( - new Date(), - parseStringAsDate(lastWeightTracker.added) - )} - {#if lastEntryDayDiff > 2} + {#if lastWeightTracker} + {#if lastEntryDayDiff === 0} + + Last update: Today. + {:else if lastEntryDayDiff > 2} Last update was {lastEntryDayDiff} days ago! {:else} diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte index fd25c962..47b55b9a 100644 --- a/src/routes/(app)/+page.svelte +++ b/src/routes/(app)/+page.svelte @@ -32,7 +32,7 @@ let index: number = $state(0); let intake: Array = $state(dashboard.intakeTodayList); - let lastWeightTracker = $state(dashboard.weightMonthList[0]); + let lastWeightTracker: WeightTracker = $state(dashboard.weightMonthList[0]); const weightTarget: WeightTarget = dashboard.weightTarget; const intakeTarget: IntakeTarget = dashboard.intakeTarget; @@ -119,7 +119,6 @@
createWeightTrackerEntry({ newEntry: entry })} From f6bc99e206cc0da3e7b0dc95e5e3be3d71bbc104 Mon Sep 17 00:00:00 2001 From: Stefan Poindl Date: Sat, 6 Dec 2025 15:15:10 +0100 Subject: [PATCH 2/2] clean up unused props in WeightScore --- src/lib/component/weight/WeightScore.svelte | 37 ++-- src/lib/component/weight/WeightScore.test.ts | 208 ++++++------------- src/routes/(app)/+page.svelte | 8 +- 3 files changed, 81 insertions(+), 172 deletions(-) diff --git a/src/lib/component/weight/WeightScore.svelte b/src/lib/component/weight/WeightScore.svelte index 1544e65f..cea0b63a 100644 --- a/src/lib/component/weight/WeightScore.svelte +++ b/src/lib/component/weight/WeightScore.svelte @@ -1,30 +1,28 @@ @@ -32,7 +30,7 @@
Current Weight
- + kg @@ -45,20 +43,15 @@
- {#if lastWeightTracker} - {#if lastEntryDayDiff === 0} - - Last update: Today. - {:else if lastEntryDayDiff > 2} - - Last update was {lastEntryDayDiff} days ago! - {:else} - - Last update: {lastEntryDayDiff} days ago. - {/if} + {#if lastEntryDayDiff === 0} + + Last update: Today. + {:else if lastEntryDayDiff > 2} + + Last update was {lastEntryDayDiff} days ago! {:else} - - Nothing tracked yet. + + Last update: {lastEntryDayDiff} days ago. {/if} diff --git a/src/lib/component/weight/WeightScore.test.ts b/src/lib/component/weight/WeightScore.test.ts index 1c2110ac..e99dae0c 100644 --- a/src/lib/component/weight/WeightScore.test.ts +++ b/src/lib/component/weight/WeightScore.test.ts @@ -1,8 +1,42 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { render, screen, waitFor } from '@testing-library/svelte'; -import userEvent from '@testing-library/user-event'; +import { describe, it, expect, vi } from 'vitest'; +import { render, screen } from '@testing-library/svelte'; import type { WeightTarget, WeightTracker, NewWeightTracker } from '$lib/api/gen'; import WeightScore from './WeightScore.svelte'; +import { getDateAsStr } from '$lib/date'; +import { subDays } from 'date-fns'; + +// Mock NumberFlow as a simple component that renders the number +// For Svelte 5, components need $$render method for SSR and proper client-side mounting +vi.mock('@number-flow/svelte', () => { + const NumberFlowMock = function (anchor: any, props: any) { + const value = props?.value ?? 0; + const textNode = document.createTextNode(String(value)); + + // Insert the text node + if (anchor && anchor.parentNode) { + anchor.parentNode.insertBefore(textNode, anchor); + } + + return { + p: (newProps: any) => { + // update + if (newProps.value !== undefined) { + textNode.textContent = String(newProps.value); + } + }, + d: () => { + // destroy + if (textNode.parentNode) { + textNode.parentNode.removeChild(textNode); + } + } + }; + }; + + return { + default: NumberFlowMock + }; +}); describe('WeightScore', () => { const mockWeightTarget: WeightTarget = { @@ -17,12 +51,14 @@ describe('WeightScore', () => { const mockWeightTracker: WeightTracker = { id: 1, added: '2024-01-15', + time: '08:30:00', amount: 82 }; - const mockLastWeightTracker: WeightTracker = { + const mockWeightTrackerToday: WeightTracker = { id: 1, - added: '2024-01-10', + added: getDateAsStr(new Date()), + time: '12:00:00', amount: 83 }; @@ -36,27 +72,7 @@ describe('WeightScore', () => { }); // Check for kg unit and Last update message - expect(container.textContent).toContain('kg'); - expect(container.textContent).toContain('Last update: Today'); - }); - - it('should display last weight when only lastWeightTracker provided', () => { - const newEntry: NewWeightTracker = { - added: '2024-01-20', - amount: 81 - }; - - const { container } = render(WeightScore, { - props: { - weightTracker: newEntry, - lastWeightTracker: mockLastWeightTracker, - weightTarget: mockWeightTarget - } - }); - - // Check for kg unit and last update message - expect(container.textContent).toContain('kg'); - expect(container.textContent).toMatch(/Last update/i); + expect(container.textContent).toMatch(/82 kg/i); }); it('should show dash when no weight data', () => { @@ -77,26 +93,10 @@ describe('WeightScore', () => { }); describe('Status Messages', () => { - it('should show "Nothing tracked yet" when no data', () => { - const newEntry: NewWeightTracker = { - added: '2024-01-20', - amount: 81 - }; - - render(WeightScore, { - props: { - weightTracker: newEntry, - weightTarget: mockWeightTarget - } - }); - - expect(screen.getByText(/Nothing tracked yet/i)).toBeTruthy(); - }); - it('should show "Last update: Today" for current day entry', () => { render(WeightScore, { props: { - weightTracker: mockWeightTracker, + weightTracker: mockWeightTrackerToday, weightTarget: mockWeightTarget } }); @@ -106,20 +106,16 @@ describe('WeightScore', () => { it('should show days ago for old entries (warning < 2 days)', () => { // Create a tracker from 1 day ago - const yesterday = new Date(); - yesterday.setDate(yesterday.getDate() - 1); - const yesterdayStr = yesterday.toISOString().split('T')[0]; - const oldTracker: WeightTracker = { id: 1, - added: yesterdayStr, + added: getDateAsStr(subDays(new Date(), 1)), + time: '08:30:00', amount: 83 }; const { container } = render(WeightScore, { props: { - weightTracker: { added: '2024-01-20', amount: 81 } as NewWeightTracker, - lastWeightTracker: oldTracker, + weightTracker: oldTracker, weightTarget: mockWeightTarget } }); @@ -130,20 +126,16 @@ describe('WeightScore', () => { it('should show critical warning for very old entries (> 2 days)', () => { // Create a tracker from 5 days ago - const fiveDaysAgo = new Date(); - fiveDaysAgo.setDate(fiveDaysAgo.getDate() - 5); - const oldDate = fiveDaysAgo.toISOString().split('T')[0]; - const veryOldTracker: WeightTracker = { id: 1, - added: oldDate, + added: getDateAsStr(subDays(new Date(), 5)), + time: '08:30:00', amount: 83 }; const { container } = render(WeightScore, { props: { - weightTracker: { added: '2024-01-20', amount: 81 } as NewWeightTracker, - lastWeightTracker: veryOldTracker, + weightTracker: veryOldTracker, weightTarget: mockWeightTarget } }); @@ -157,7 +149,7 @@ describe('WeightScore', () => { it('should show success state with ShieldCheck for current day', () => { render(WeightScore, { props: { - weightTracker: mockWeightTracker, + weightTracker: mockWeightTrackerToday, weightTarget: mockWeightTarget } }); @@ -168,20 +160,16 @@ describe('WeightScore', () => { it('should show warning state for entries 1-2 days old', () => { // Create a tracker from 1 day ago - const yesterday = new Date(); - yesterday.setDate(yesterday.getDate() - 1); - const yesterdayStr = yesterday.toISOString().split('T')[0]; - const oldTracker: WeightTracker = { id: 1, - added: yesterdayStr, + added: getDateAsStr(subDays(new Date(), 1)), + time: '08:30:00', amount: 83 }; const { container } = render(WeightScore, { props: { - weightTracker: { added: '2024-01-20', amount: 81 } as NewWeightTracker, - lastWeightTracker: oldTracker, + weightTracker: oldTracker, weightTarget: mockWeightTarget } }); @@ -192,20 +180,16 @@ describe('WeightScore', () => { it('should show error state for entries older than 2 days', () => { // Create a tracker from 5 days ago - const fiveDaysAgo = new Date(); - fiveDaysAgo.setDate(fiveDaysAgo.getDate() - 5); - const oldDate = fiveDaysAgo.toISOString().split('T')[0]; - const veryOldTracker: WeightTracker = { id: 1, - added: oldDate, + added: getDateAsStr(subDays(new Date(), 5)), + time: '08:30:00', amount: 83 }; const { container } = render(WeightScore, { props: { - weightTracker: { added: '2024-01-20', amount: 81 } as NewWeightTracker, - lastWeightTracker: veryOldTracker, + weightTracker: veryOldTracker, weightTarget: mockWeightTarget } }); @@ -213,18 +197,6 @@ describe('WeightScore', () => { // ShieldWarning (error color) should show with "days ago!" (with exclamation) expect(container.textContent).toMatch(/Last update was.*5.*days ago!/i); }); - - it('should show neutral state with Shield icon when no data tracked', () => { - render(WeightScore, { - props: { - weightTracker: { added: '2024-01-20', amount: 81 } as NewWeightTracker, - weightTarget: mockWeightTarget - } - }); - - // Shield icon shows with "Nothing tracked yet" text - expect(screen.getByText(/Nothing tracked yet/i)).toBeTruthy(); - }); }); describe('Progress Information', () => { @@ -269,64 +241,12 @@ describe('WeightScore', () => { }); }); - describe('Callbacks', () => { - it('should call onAdd when provided', async () => { - const onaddMock = vi.fn().mockResolvedValue({ - id: 2, - added: '2024-01-20', - amount: 80 - }); - - render(WeightScore, { - props: { - weightTracker: mockWeightTracker, - weightTarget: mockWeightTarget, - onAdd: onaddMock - } - }); - - // Component should render without calling onadd immediately - expect(onaddMock).not.toHaveBeenCalled(); - }); - - it('should work without onAdd callback', () => { - expect(() => { - render(WeightScore, { - props: { - weightTracker: mockWeightTracker, - weightTarget: mockWeightTarget - } - }); - }).not.toThrow(); - }); - - it('should work without onEdit callback', () => { - expect(() => { - render(WeightScore, { - props: { - weightTracker: mockWeightTracker, - weightTarget: mockWeightTarget - } - }); - }).not.toThrow(); - }); - }); - describe('Edge Cases', () => { - it('should handle missing weightTracker', () => { - const { container } = render(WeightScore, { - props: { - weightTarget: mockWeightTarget - } - }); - - expect(container).toBeTruthy(); - }); - it('should handle very large weight values', () => { const heavyTracker: WeightTracker = { id: 1, - added: '2024-01-15', + added: getDateAsStr(new Date()), + time: '08:30:00', amount: 300 }; @@ -338,14 +258,15 @@ describe('WeightScore', () => { }); // Component should render without error - expect(container.textContent).toContain('kg'); + expect(container.textContent).toMatch(/300 kg/i); expect(container.textContent).toContain('Last update: Today'); }); it('should handle minimum weight values', () => { const lightTracker: WeightTracker = { id: 1, - added: '2024-01-15', + added: getDateAsStr(new Date()), + time: '08:30:00', amount: 30 }; @@ -356,14 +277,15 @@ describe('WeightScore', () => { } }); - expect(container.textContent).toContain('kg'); + expect(container.textContent).toMatch(/30 kg/i); expect(container.textContent).toContain('Last update: Today'); }); it('should handle fractional weight values', () => { const fractionalTracker: WeightTracker = { id: 1, - added: '2024-01-15', + added: getDateAsStr(new Date()), + time: '08:30:00', amount: 82.5 }; @@ -374,7 +296,7 @@ describe('WeightScore', () => { } }); - expect(container.textContent).toContain('kg'); + expect(container.textContent).toMatch(/82.5 kg/i); expect(container.textContent).toContain('Last update: Today'); }); }); diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte index 47b55b9a..4b191b80 100644 --- a/src/routes/(app)/+page.svelte +++ b/src/routes/(app)/+page.svelte @@ -118,13 +118,7 @@
- createWeightTrackerEntry({ newEntry: entry })} - onEdit={(id, entry: WeightTracker) => - updateWeightTrackerEntry({ trackerId: id, updatedEntry: entry })} - /> +