Skip to content

Commit 6fdc6be

Browse files
committed
fix(home): hold the favourites section until the featured ranking loads
The catalog resolves at once from the local fallback, so "Tus playas favoritas" was painted alone above the spinner, with bare name/municipio rows, and then re-rendered with conditions once /featured arrived. Gate the section on !featuredLoading like every other block of the page. It still renders when the ranking fails — only the timing changes, not the independence from the ranking's fate. Adds a characterization case: favourites absent while /featured is pending, present after it rejects. Claude-Session: https://claude.ai/code/session_01CZeTJqzoJxUKi7uWcVDnoj
1 parent ecdb690 commit 6fdc6be

2 files changed

Lines changed: 38 additions & 2 deletions

File tree

frontend/src/pages/HomePage.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -472,8 +472,10 @@ const HomePage: React.FC = () => {
472472
/>
473473

474474
<div className="hp-body">
475-
{/* Favorites first — independent of the featured ranking's fate. */}
476-
{favoritasEnHome.length > 0 && (
475+
{/* Favorites first — independent of the featured ranking's fate
476+
(they still show if it fails), but not of its timing: painted
477+
alone above the spinner they looked like the whole page. */}
478+
{!featuredLoading && favoritasEnHome.length > 0 && (
477479
<section className="hp-section hp-section--favoritas">
478480
<h2 className="section-kicker">{t('home.favoritas')}</h2>
479481
<div className="hp-alt-list">

frontend/src/test/characterization/homePage.states.test.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import React from 'react';
1919
import { fireEvent, screen } from '@testing-library/react';
2020
import HomePage from '../../pages/HomePage';
21+
import { recargarFavoritas } from '../../modules/favorites';
2122
import { renderWithProviders } from '../render';
2223
import { installFetchMock, restoreFetch, route, deferred, RouteSpec } from '../http/fakeFetch';
2324
import { beachesResponse } from '../fixtures/beaches';
@@ -35,6 +36,39 @@ afterEach(() => {
3536
});
3637

3738
describe('HomePage — estados', () => {
39+
it('no pinta las favoritas hasta que /featured termina, y sí cuando falla', async () => {
40+
// Seeded straight into storage: the catalog arrives at once (local
41+
// fallback) and used to paint this section alone above the spinner.
42+
localStorage.setItem(
43+
'playas:favoritas',
44+
JSON.stringify({ version: 1, beachCodes: [beachesResponse[0].codigo] }),
45+
);
46+
recargarFavoritas();
47+
48+
const pending = deferred<RouteSpec>();
49+
installFetchMock([
50+
route(FEATURED, () => pending.promise),
51+
route(BEACHES, { json: beachesResponse }),
52+
]);
53+
54+
renderWithProviders(<HomePage />, { route: '/' });
55+
56+
expect(await screen.findByText('7 playas')).toBeInTheDocument();
57+
expect(screen.getByText('Buscando las mejores playas cerca de ti...')).toBeInTheDocument();
58+
expect(screen.queryByText('Tus playas favoritas')).not.toBeInTheDocument();
59+
60+
// Rejected, not resolved, so the cache stays empty for the next cases.
61+
// The section still shows on error: it depends on the ranking's timing,
62+
// not on its fate.
63+
pending.reject(new Error('backend caído'));
64+
65+
expect(await screen.findByText('Tus playas favoritas')).toBeInTheDocument();
66+
expect(screen.getByText('No se pudieron cargar las condiciones actuales')).toBeInTheDocument();
67+
68+
localStorage.removeItem('playas:favoritas');
69+
recargarFavoritas();
70+
});
71+
3872
it('muestra el mensaje de búsqueda y da paso al error si falla', async () => {
3973
const pending = deferred<RouteSpec>();
4074
installFetchMock([

0 commit comments

Comments
 (0)