mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 05:12:14 +00:00
Bail the rhythm cards on a failed shared read
With the error notice hoisted to the page, the three cards fell through to their skeleton on a failed read — a spinner that can never resolve. Return null instead, so a card rendered outside the page's gate is still honest about having nothing to show.
This commit is contained in:
1 parent
59ffa02b0c
commit
943c6ad01f
5 files changed
+38
-9
No files matched your search
@@ -65,14 +65,18 @@ beforeEach(() => {
|
||||
});
|
||||
|
||||
describe("<ChronotypeSection>", () => {
|
||||
it("renders the quiet inline notice on a query error", () => {
|
||||
it("renders nothing on a query error — the page owns the one notice", () => {
|
||||
// All three rhythm cards resolve the same query, so a per-card notice
|
||||
// printed the identical sentence three times. /insights/sleep now renders
|
||||
// a single QueryErrorCard with a retry in place of the row. The card must
|
||||
// still not fall through to its skeleton, which would spin forever.
|
||||
rhythmMock.mockReturnValue({
|
||||
data: undefined,
|
||||
isLoading: false,
|
||||
isError: true,
|
||||
});
|
||||
const html = render(<ChronotypeSection enabled />);
|
||||
expect(html).toContain('data-slot="chronotype-error"');
|
||||
expect(html).toBe("");
|
||||
expect(html).not.toContain('data-slot="chronotype-loading"');
|
||||
});
|
||||
|
||||
|
||||
@@ -73,16 +73,17 @@ beforeEach(() => {
|
||||
});
|
||||
|
||||
describe("<SleepRhythmSection>", () => {
|
||||
it("renders the quiet inline notice on a query error, not an infinite skeleton", () => {
|
||||
it("renders nothing on a query error, and never an infinite skeleton", () => {
|
||||
// The shared-read notice moved to /insights/sleep so one failure prints
|
||||
// one message instead of three. The card must still bail rather than
|
||||
// fall through to a skeleton that can never resolve.
|
||||
rhythmMock.mockReturnValue({
|
||||
data: undefined,
|
||||
isLoading: false,
|
||||
isError: true,
|
||||
});
|
||||
const html = render(<SleepRhythmSection enabled />);
|
||||
expect(html).toContain('data-slot="sleep-rhythm-error"');
|
||||
expect(html).toContain("Your sleep rhythm");
|
||||
// No skeletons while errored.
|
||||
expect(html).toBe("");
|
||||
expect(html).not.toContain('data-slot="sleep-rhythm-loading"');
|
||||
});
|
||||
|
||||
|
||||
@@ -20,10 +20,18 @@ import { AverageSleepCard } from "./average-sleep-card";
|
||||
*/
|
||||
export function AverageSleepSection({ enabled }: { enabled: boolean }) {
|
||||
const { isAuthenticated } = useAuth();
|
||||
const { data, isLoading } = useSleepRhythm(isAuthenticated && enabled);
|
||||
const { data, isLoading, isError } = useSleepRhythm(
|
||||
isAuthenticated && enabled,
|
||||
);
|
||||
|
||||
if (!enabled) return null;
|
||||
|
||||
// The page owns the single error notice for this shared read (all three
|
||||
// cards resolve the same query, so a per-card notice printed it three
|
||||
// times). Bail out here rather than falling through to the skeleton below,
|
||||
// which would otherwise spin forever on a failed read.
|
||||
if (isError) return null;
|
||||
|
||||
if (isLoading || !data) {
|
||||
return (
|
||||
<Skeleton
|
||||
|
||||
@@ -25,10 +25,18 @@ import { ChronotypeCard } from "./chronotype-card";
|
||||
*/
|
||||
export function ChronotypeSection({ enabled }: { enabled: boolean }) {
|
||||
const { isAuthenticated } = useAuth();
|
||||
const { data, isLoading } = useSleepRhythm(isAuthenticated && enabled);
|
||||
const { data, isLoading, isError } = useSleepRhythm(
|
||||
isAuthenticated && enabled,
|
||||
);
|
||||
|
||||
if (!enabled) return null;
|
||||
|
||||
// The page owns the single error notice for this shared read (all three
|
||||
// cards resolve the same query, so a per-card notice printed it three
|
||||
// times). Bail out here rather than falling through to the skeleton below,
|
||||
// which would otherwise spin forever on a failed read.
|
||||
if (isError) return null;
|
||||
|
||||
if (isLoading || !data) {
|
||||
return (
|
||||
<Skeleton
|
||||
|
||||
@@ -26,10 +26,18 @@ import { SleepDebtCard } from "./sleep-debt-card";
|
||||
*/
|
||||
export function SleepRhythmSection({ enabled }: { enabled: boolean }) {
|
||||
const { isAuthenticated } = useAuth();
|
||||
const { data, isLoading } = useSleepRhythm(isAuthenticated && enabled);
|
||||
const { data, isLoading, isError } = useSleepRhythm(
|
||||
isAuthenticated && enabled,
|
||||
);
|
||||
|
||||
if (!enabled) return null;
|
||||
|
||||
// The page owns the single error notice for this shared read (all three
|
||||
// cards resolve the same query, so a per-card notice printed it three
|
||||
// times). Bail out here rather than falling through to the skeleton below,
|
||||
// which would otherwise spin forever on a failed read.
|
||||
if (isError) return null;
|
||||
|
||||
if (isLoading || !data) {
|
||||
return (
|
||||
<div className="space-y-4" data-slot="sleep-rhythm-loading">
|
||||
|
||||
Reference in new issue
Block a user