Mise en place StoryBook

Voir plus Lancer la commande suivante

npx -p @storybook/cli sb init --type react

il faut ensuite configurer storyBook pour lui dire d'aller chercher les story dans le dossier component.

on ouvre donc le fichier ./storybook/config.js

et on modifie

configure(require.context('../stories', true, /\.stories\.js$/), module);

par

configure(require.context('../src/components', true, /\.stories\.js$/), module);

les composants dans le dossier components sont maintenant visible dans notre storybook.

Travailler avec Styled Components

Nos composant utilisent un ThemeProvider, il faut émuler ce comportement au sein de son storyBook.

pour cela il faut créer un composant perso appelé ThemeDecorator

dans ./storybook créer themeDecorator.js

import React from "react"
import { ThemeProvider } from "styled-components"

import theme from '../src/config/theme'

const ThemeDecorator = storyFn => (
  <ThemeProvider theme={theme}>{storyFn()}</ThemeProvider>
)

export default ThemeDecorator

on utilisera ce ThemeDecorator dans ./storybook/config.js

import { configure, addDecorator } from "@storybook/react"
import themeDecorator from "./themeDecorator"

on appliquera ensuite notre decorator.

addDecorator(themeDecorator);

Votre StoryBook est desormais pret a être utiliser avec styled component

pour creer ses stories voir la doc de storybook

Mise en place Router

Lancer la commande

yarn add react-router-dom

creer un fichier routes.js dans le dossier config

pour notre exemple creer un fichier ranking.js dans screens

(il nous faut au moins 2 screens pour le router)

On créera ensuite le fichier routes.js dans config

import React from 'react';

import {
  Route,
  BrowserRouter as Router,
  Redirect,
  Switch
} from 'react-router-dom';
import PrivateRoute from '../utils/privateRoute';

import App from '../screens/app';
import Ranking from '../screens/ranking';

export default class Routes extends React.Component {
  render() {
    return (
      <Router>
        <Switch>
          <Route exact path="/" component={App}></Route>
          <PrivateRoute
            path="/ranking"
            component={Ranking}
          ></PrivateRoute>
          <Redirect to="/" />
        </Switch>
      </Router>
    );
  }
}

Pour faire fonctionner le routeur on aura besoin de deux fichier : isUserConnected.js et privateRoute.js dans le dossier utils

isUserConnected

const isUserConnected = () => {
  const isConnected = localStorage.getItem('token');
  return !!isConnected;
};

export default isUserConnected;

privateRoute.js

import React from 'react';
import PropTypes from 'prop-types';
import isUserConnected from './isUserConnected';
import { Redirect, Route } from 'react-router-dom';

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route
    {...rest}
    render={props =>
      isUserConnected() === true ? (
        <Component {...props} />
      ) : (
        <Redirect
          to={{
            pathname: '/',
            state: { from: props.location }
          }}
        />
      )
    }
  />
);

PrivateRoute.propTypes = {
  component: PropTypes.any,
  location: PropTypes.any
};

// To give an accurate explanation, let's break down the { component: Component, ...rest } expression into two separate operations:

// Operation 1: Find the component property defined on props (Note: lowercase component) and assign it to a new location in state we call Component (Note: capital Component).
// Operation 2: Then, take all remaining properties defined on the props object and collect them inside an argument called rest.

export default PrivateRoute;

le Routeur est deseormais fonctionnel on l'importera dans index.js a la racine du projet

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import * as serviceWorker from './serviceWorker';
import {ThemeProvider} from 'styled-components';

import Routes from './config/routes';

import theme from './config/theme';

class Index extends React.Component{
  render(){
    return(
    <ThemeProvider theme={theme}>
       <Routes /> 
    </ThemeProvider>
    );
  }
}

ReactDOM.render(<Index></Index>, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

// faire la mise en place de la connexion en live

Mise en place des tests unitaires

yarn add enzyme enzyme-adapter-react-16 enzyme-to-json

pour faire fonctionner enzyme il faut creer ce fichier de parametre a la racine de ./src

setupTests.js

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({ adapter: new Adapter() });

ajouter dans package.json

  "jest": {
    "collectCoverageFrom": [
      "app/**/*js"
    ],
    "snapshotSerializers": [
      "enzyme-to-json/serializer"
    ]
  }

Enzyme nous permet de faire du shallow rendering (render sans les composants enfant)

pour faciliter la lecture des snapshot, on installe enzyme-to-json puis on le parametre dans le package.json

on peux desormais tester les composant classique, pour faciliter les test des styled-components il faut installer le package suivant

yarn add jest-styled-components --dev

ce composant règle certain soucis qui fausse le resultat des snapshot.