Fix intensity goal defaults for PocketBase 0 values
All checks were successful
Deploy / deploy (push) Successful in 2m39s
All checks were successful
Deploy / deploy (push) Successful in 2m39s
PocketBase number fields default to 0, not null. Using ?? (nullish coalescing) caused 0 to be preserved instead of using the default value. Changed to || so 0 is treated as falsy and falls back to defaults. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,9 +4,11 @@ import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import {
|
||||
createPocketBaseClient,
|
||||
DEFAULT_INTENSITY_GOALS,
|
||||
getCurrentUser,
|
||||
isAuthenticated,
|
||||
loadAuthFromCookies,
|
||||
mapRecordToUser,
|
||||
} from "./pocketbase";
|
||||
|
||||
describe("isAuthenticated", () => {
|
||||
@@ -221,3 +223,76 @@ describe("createPocketBaseClient", () => {
|
||||
expect(client.authStore).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("mapRecordToUser intensity goal defaults", () => {
|
||||
const createMockRecord = (overrides: Record<string, unknown> = {}) => ({
|
||||
id: "user123",
|
||||
email: "test@example.com",
|
||||
garminConnected: false,
|
||||
garminOauth1Token: "",
|
||||
garminOauth2Token: "",
|
||||
garminTokenExpiresAt: "",
|
||||
garminRefreshTokenExpiresAt: "",
|
||||
calendarToken: "token",
|
||||
lastPeriodDate: "2025-01-01",
|
||||
cycleLength: 28,
|
||||
notificationTime: "08:00",
|
||||
timezone: "UTC",
|
||||
activeOverrides: [],
|
||||
created: "2024-01-01T00:00:00Z",
|
||||
updated: "2024-01-01T00:00:00Z",
|
||||
...overrides,
|
||||
});
|
||||
|
||||
it("uses default when intensityGoalMenstrual is 0", () => {
|
||||
const record = createMockRecord({ intensityGoalMenstrual: 0 });
|
||||
// biome-ignore lint/suspicious/noExplicitAny: test mock
|
||||
const user = mapRecordToUser(record as any);
|
||||
expect(user.intensityGoalMenstrual).toBe(DEFAULT_INTENSITY_GOALS.menstrual);
|
||||
});
|
||||
|
||||
it("uses default when intensityGoalFollicular is 0", () => {
|
||||
const record = createMockRecord({ intensityGoalFollicular: 0 });
|
||||
// biome-ignore lint/suspicious/noExplicitAny: test mock
|
||||
const user = mapRecordToUser(record as any);
|
||||
expect(user.intensityGoalFollicular).toBe(
|
||||
DEFAULT_INTENSITY_GOALS.follicular,
|
||||
);
|
||||
});
|
||||
|
||||
it("uses default when intensityGoalOvulation is 0", () => {
|
||||
const record = createMockRecord({ intensityGoalOvulation: 0 });
|
||||
// biome-ignore lint/suspicious/noExplicitAny: test mock
|
||||
const user = mapRecordToUser(record as any);
|
||||
expect(user.intensityGoalOvulation).toBe(DEFAULT_INTENSITY_GOALS.ovulation);
|
||||
});
|
||||
|
||||
it("uses default when intensityGoalEarlyLuteal is 0", () => {
|
||||
const record = createMockRecord({ intensityGoalEarlyLuteal: 0 });
|
||||
// biome-ignore lint/suspicious/noExplicitAny: test mock
|
||||
const user = mapRecordToUser(record as any);
|
||||
expect(user.intensityGoalEarlyLuteal).toBe(
|
||||
DEFAULT_INTENSITY_GOALS.earlyLuteal,
|
||||
);
|
||||
});
|
||||
|
||||
it("uses default when intensityGoalLateLuteal is 0", () => {
|
||||
const record = createMockRecord({ intensityGoalLateLuteal: 0 });
|
||||
// biome-ignore lint/suspicious/noExplicitAny: test mock
|
||||
const user = mapRecordToUser(record as any);
|
||||
expect(user.intensityGoalLateLuteal).toBe(
|
||||
DEFAULT_INTENSITY_GOALS.lateLuteal,
|
||||
);
|
||||
});
|
||||
|
||||
it("preserves non-zero intensity goal values", () => {
|
||||
const record = createMockRecord({
|
||||
intensityGoalMenstrual: 100,
|
||||
intensityGoalFollicular: 200,
|
||||
});
|
||||
// biome-ignore lint/suspicious/noExplicitAny: test mock
|
||||
const user = mapRecordToUser(record as any);
|
||||
expect(user.intensityGoalMenstrual).toBe(100);
|
||||
expect(user.intensityGoalFollicular).toBe(200);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -110,20 +110,21 @@ export function mapRecordToUser(record: RecordModel): User {
|
||||
lastPeriodDate: parseDate(record.lastPeriodDate),
|
||||
cycleLength: record.cycleLength as number,
|
||||
// Intensity goals with defaults for existing users
|
||||
// Using || instead of ?? because PocketBase defaults number fields to 0
|
||||
intensityGoalMenstrual:
|
||||
(record.intensityGoalMenstrual as number) ??
|
||||
(record.intensityGoalMenstrual as number) ||
|
||||
DEFAULT_INTENSITY_GOALS.menstrual,
|
||||
intensityGoalFollicular:
|
||||
(record.intensityGoalFollicular as number) ??
|
||||
(record.intensityGoalFollicular as number) ||
|
||||
DEFAULT_INTENSITY_GOALS.follicular,
|
||||
intensityGoalOvulation:
|
||||
(record.intensityGoalOvulation as number) ??
|
||||
(record.intensityGoalOvulation as number) ||
|
||||
DEFAULT_INTENSITY_GOALS.ovulation,
|
||||
intensityGoalEarlyLuteal:
|
||||
(record.intensityGoalEarlyLuteal as number) ??
|
||||
(record.intensityGoalEarlyLuteal as number) ||
|
||||
DEFAULT_INTENSITY_GOALS.earlyLuteal,
|
||||
intensityGoalLateLuteal:
|
||||
(record.intensityGoalLateLuteal as number) ??
|
||||
(record.intensityGoalLateLuteal as number) ||
|
||||
DEFAULT_INTENSITY_GOALS.lateLuteal,
|
||||
notificationTime: record.notificationTime as string,
|
||||
timezone: record.timezone as string,
|
||||
|
||||
Reference in New Issue
Block a user