Skip to content

Commit

Permalink
fix(multiple): le bouton retour apparait tout le temps (#2324)
Browse files Browse the repository at this point in the history
* fix(multiple): le bouton retour apparait tout le temps

* fix: retour review
  • Loading branch information
Naorid committed Nov 27, 2023
1 parent 952ac49 commit 2807cca
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 34 deletions.
46 changes: 46 additions & 0 deletions src/client/components/features/ButtonRetour/BackButton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* @jest-environment jsdom
*/

import { render, screen } from '@testing-library/react';

import { BackButton } from '~/client/components/features/ButtonRetour/BackButton';
import { mockUseRouter } from '~/client/components/useRouter.mock';
import { mockSessionStorage } from '~/client/components/window.mock';

describe('BackButton', () => {
beforeEach(() => {
jest.resetAllMocks();
});

describe('Lorsque la variable PREVIOUS_PAGE est définie dans le sessionStorage', () => {
it('affiche le bouton de retour', () => {
// Given
mockUseRouter({});
mockSessionStorage({
getItem: jest.fn().mockReturnValue('/page-1'),
});

// When
render(<BackButton />);

// Then
expect(screen.getByRole('button', { name: 'Retour vers la page précédente' })).toBeInTheDocument();
});
});
describe('Lorsque la variable PREVIOUS_PAGE n’est pas définie dans le sessionStorage', () => {
it('n’affiche pas le bouton de retour', () => {
// Given
mockUseRouter({});
mockSessionStorage({
getItem: jest.fn().mockReturnValue(null),
});

// When
render(<BackButton />);

// Then
expect(screen.queryByRole('button', { name: 'Retour vers la page précédente' })).not.toBeInTheDocument();
});
});
});
18 changes: 6 additions & 12 deletions src/client/components/features/ButtonRetour/BackButton.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,28 @@
import { useRouter } from 'next/router';
import React, { useEffect, useMemo } from 'react';
import React, { useEffect, useState } from 'react';

import { Container } from '~/client/components/layouts/Container/Container';
import {
ButtonComponent,
} from '~/client/components/ui/Button/ButtonComponent';
import { Icon } from '~/client/components/ui/Icon/Icon';
import { REFERRER } from '~/client/hooks/useReferrer';
import { PREVIOUS_PAGE } from '~/client/hooks/useDisplayBackButton';

type BackButtonProps = Omit<React.ComponentPropsWithoutRef<typeof ButtonComponent>,'label'> & {
label?: string
}

export function BackButton({ className, label= 'Retour', ...rest }: BackButtonProps) {

const router = useRouter();

const referrer = useMemo( () => {
return sessionStorage.getItem(REFERRER);
}, []);

const [displayBackButton, setDisplayBackButton] = useState(false);
useEffect(() => {
return () => {
sessionStorage.removeItem(REFERRER);
};
const previousPage = sessionStorage.getItem(PREVIOUS_PAGE);
setDisplayBackButton(!!previousPage);
}, []);

if (referrer === null) return null;

return (
displayBackButton &&
<div className={className}>
<Container>
<ButtonComponent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,22 @@ import {

import { ConsulterAnnonce } from '~/client/components/features/Logement/Consulter/ConsulterAnnonce';
import { mockUseRouter } from '~/client/components/useRouter.mock';
import { mockSessionStorage, mockSmallScreen } from '~/client/components/window.mock';
import { mockSmallScreen } from '~/client/components/window.mock';
import { LocaleProvider } from '~/client/context/locale.context';
import { anAnnonceDeLogement } from '~/server/cms/domain/annonceDeLogement.fixture';
import { AnnonceDeLogement } from '~/server/cms/domain/annonceDeLogement.type';

describe('<ConsulterAnnonce />', () => {
beforeEach(() => {
jest.resetAllMocks();
mockSmallScreen();
mockSessionStorage({
setItem: jest.fn().mockReturnValue('/annonces'),
});
const routerReload = jest.fn();
mockUseRouter({ reload: routerReload });
});

it('affiche le le bouton retour vers la liste des annonces', () => {
jest.spyOn(Object.getPrototypeOf(sessionStorage), 'getItem').mockReturnValue('/');

const annonceDeLogement = anAnnonceDeLogement();
annonceDeLogement.titre = 'Super T3 dans le centre de Paris';

Expand Down
54 changes: 54 additions & 0 deletions src/client/hooks/useDisplayBackButton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* @jest-environment jsdom
*/

import { render } from '@testing-library/react';

import { mockUseRouter } from '~/client/components/useRouter.mock';
import useDisplayBackButton from '~/client/hooks/useDisplayBackButton';

function TestComponent() {
useDisplayBackButton();
return <></>;
}

describe('useDisplayBackButton', () => {
beforeEach(() => {
sessionStorage.clear();
jest.resetAllMocks();
});
describe('quand la page actuel est la première sur laquelle on navigue', () => {
it('stocke le pathname de la page dans sessionStorage', () => {
// Given
mockUseRouter({
pathname: '/',
});
const setItem = jest.spyOn(Object.getPrototypeOf(sessionStorage), 'setItem');
jest.spyOn(Object.getPrototypeOf(sessionStorage), 'getItem').mockReturnValue(null);

// When
render(<TestComponent />);

// Then
expect(setItem).toHaveBeenCalledWith('current-page', '/');
});
});

describe('quand la page actuel n’est pas la première sur laquelle on navigue', () => {
it('stocke le pathname de la page dans sessionStorage', () => {
// Given
mockUseRouter({
pathname: '/other-page',
});
const setItem = jest.spyOn(Object.getPrototypeOf(sessionStorage), 'setItem');
jest.spyOn(Object.getPrototypeOf(sessionStorage), 'getItem').mockReturnValue('/');

// When
render(<TestComponent />);

// Then
expect(setItem).toHaveBeenCalledWith('previous-page', '/');
expect(setItem).toHaveBeenLastCalledWith('current-page', '/other-page');
});
});
});
19 changes: 19 additions & 0 deletions src/client/hooks/useDisplayBackButton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useRouter } from 'next/router';
import { useLayoutEffect } from 'react';

const CURRENT_PAGE = 'current-page';
export const PREVIOUS_PAGE = 'previous-page';

function useDisplayBackButton(): void {
const router = useRouter();

useLayoutEffect(() => {
const currentPage = sessionStorage.getItem(CURRENT_PAGE);
if (currentPage && currentPage !== router.pathname) {
sessionStorage.setItem(PREVIOUS_PAGE, currentPage);
}
sessionStorage.setItem(CURRENT_PAGE, router.pathname);
}, [router.pathname]);
}

export default useDisplayBackButton;
15 changes: 0 additions & 15 deletions src/client/hooks/useReferrer.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/client/hooks/useSessionStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ function useSessionStorage<T>(key: string): {get: () => T | null, set: (value: T
remove: () => setDefaultValue(null),
set: setDefaultValue,
};
};
}

export default useSessionStorage;
5 changes: 3 additions & 2 deletions src/pages/_app.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import React, { ReactElement, ReactNode, useEffect, useMemo } from 'react';
import { Layout } from '~/client/components/layouts/Layout';
import { DependenciesProvider } from '~/client/context/dependenciesContainer.context';
import dependenciesContainer from '~/client/dependencies.container';
import useReferrer from '~/client/hooks/useReferrer';
import useDisplayBackButton from '~/client/hooks/useDisplayBackButton';
import useSessionId from '~/client/hooks/useSessionId';

export type NextPageWithLayout<P = object> = NextPage<P, P> & {
Expand All @@ -24,7 +24,8 @@ export default function App({ Component, pageProps }: AppPropsWithLayout) {
const sessionId = useSessionId();
const dependenciesContainerInstance = useMemo(() => sessionId && dependenciesContainer(sessionId), [sessionId]);
const router = useRouter();
useReferrer();

useDisplayBackButton();

useEffect(() => {
const [/* full path */, targetId] = router.asPath.match(/^[^#]*#(.+)$/) ?? [];
Expand Down

0 comments on commit 2807cca

Please sign in to comment.