Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(PC-32374)[PRO] refactor: Add commons directory and add folders inside #14586

Merged
merged 2 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions pro/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module.exports = {
'**/*.svg',
'**/*.scss',
'**/*.md',
'**/*.mdx',
'**/*.jpg',
'**/*.png',
'src/index.html',
Expand Down
8 changes: 4 additions & 4 deletions pro/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ const config: StorybookConfig = {
staticDirs: ['../src/public'],
framework: {
name: '@storybook/react-vite',
options: {}
options: {},
},
async viteFinal(config) {
if (config.build) {
// Make sure that the <use> content in svgs is not inlined which is forbidden by some browsers
config.build.assetsInlineLimit = 0;
config.build.assetsInlineLimit = 0
}
return config;
return config
},
docs: {
defaultName: 'Documentation'
defaultName: 'Documentation',
},
}

Expand Down
2 changes: 1 addition & 1 deletion pro/.storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ export const parameters = {
},
}

export const tags = [ 'autodocs' ]
export const tags = ['autodocs']
4 changes: 1 addition & 3 deletions pro/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ Sur linux + chrome / chromium l’application peut se charger indéfiniment un w
- Injection des données de test `pc sandbox -n e2e`
- Lancement des tests depuis la ligne de commande `yarn test:e2e`

Note, si vous lancez les tests e2e hors Docker et sous OSX, Cypress tentera de contacter le backoffice sur
le localhost ipv6. Comme, par défaut, le backend écoute sur les ports en ipv4, il faudra lancer le backend
avec:
Note, si vous lancez les tests e2e hors Docker et sous OSX, Cypress tentera de contacter le backoffice sur le localhost ipv6. Comme, par défaut, le backend écoute sur les ports en ipv4, il faudra lancer le backend avec:

```bash
$ FLASK_IP="::1" python src/pcapi/app.py
Expand Down
52 changes: 23 additions & 29 deletions pro/cypress/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,41 @@

features (Gherkin) -> step-definitions (TS) (et c'est tout !)

- [Gherkin](#writing-your-first-scenario-with-gherkin) : c'est le fichier `.feature`. C'est ici que vous décrivez le cas d'usage fonctionnel comme si vous étiez un utilisateur sans connaissance technique. Tout le monde dans l'entreprise devrait être capable de comprendre et de reproduire le cas de test. Ici, vous éviterez de parler de la façon dont le test est implémenté, par exemple "l'utlisateur se connecte" plutôt que "l'utilisateur remplit le champ ..."
- [Step definition](#step-definition) : ici vous collez à l'interface et décrivez chaque interaction. Chaque personne qui lit le code devrait être capable de reproduire le cas de test comme si c'était un script. Pour faciliter la lecture du code, on a utilisé Testing Library (voir plus bas).
- [Gherkin](#writing-your-first-scenario-with-gherkin) : c'est le fichier `.feature`. C'est ici que vous décrivez le cas d'usage fonctionnel comme si vous étiez un utilisateur sans connaissance technique. Tout le monde dans l'entreprise devrait être capable de comprendre et de reproduire le cas de test. Ici, vous éviterez de parler de la façon dont le test est implémenté, par exemple "l'utlisateur se connecte" plutôt que "l'utilisateur remplit le champ ..."
- [Step definition](#step-definition) : ici vous collez à l'interface et décrivez chaque interaction. Chaque personne qui lit le code devrait être capable de reproduire le cas de test comme si c'était un script. Pour faciliter la lecture du code, on a utilisé Testing Library (voir plus bas).

## Les fichiers .feature

Gherkin est un langage non technique et compréhensible par les humains pour écrire un scénario de test. Il est interprété par Cucumber pour faire le lien avec les step definitions dans Typescript. Regardez ce que vous pouvez faire avec Gherkin dans cette [documentation](https://cucumber.io/docs/gherkin/reference/), il faut absolument savoir comment utiliser ces mots clé avant d'écrire votre premier scénario :

- Feature
- Background
- Scenario
- Scenario Outline and Examples
- Step Arguments (doc string, data tables, etc.) et les Expressions Cucumber inclus dans cette [documentation dédiée](https://github.com/cucumber/cucumber-expressions#readme)
- Feature
- Background
- Scenario
- Scenario Outline and Examples
- Step Arguments (doc string, data tables, etc.) et les Expressions Cucumber inclus dans cette [documentation dédiée](https://github.com/cucumber/cucumber-expressions#readme)

TODO: parler des tags?

### Comment nommer votre Feature et Scenario

La "feature" doit décrire où vous êtes dans l'application et l'objectif d'un point de vue utilisateur. On reprend souvent juste en dessous le modèle "En tant que ... j'aimerais ... afin de...", sur trois lignes distinctes.
Le scénario devrait entrer plus dans les détails et décrire brièvement ce qu'il vérifie. Le titre du scénario doit être unique.
La "feature" doit décrire où vous êtes dans l'application et l'objectif d'un point de vue utilisateur. On reprend souvent juste en dessous le modèle "En tant que ... j'aimerais ... afin de...", sur trois lignes distinctes. Le scénario devrait entrer plus dans les détails et décrire brièvement ce qu'il vérifie. Le titre du scénario doit être unique.

_Ex:_
Feature: Create and update venue
Scenario: A pro user can add a venue without SIRET
Scenario: A pro user can add a venue with SIRET
Scenario: It should update a venue
_Ex:_ Feature: Create and update venue Scenario: A pro user can add a venue without SIRET Scenario: A pro user can add a venue with SIRET Scenario: It should update a venue

Utilisez `Given`, `When`, `Then`, `And`, `But` dans le bon ordre pour rendre vos scénarios faciles à lire :

- `Given` donne les préconditions : que doit-on faire pour arriver à notre objet de test
- `When` décrit les actions : dans le contexte de ma fonctionalité, quelles sont les étapes à réaliser pour atteindre mon résultat
- `Then` attend un résultat et fait une assertion
- `And`, `But` lie des étapes, ce sont des alias des trois mots clés précédents
- `Given` donne les préconditions : que doit-on faire pour arriver à notre objet de test
- `When` décrit les actions : dans le contexte de ma fonctionalité, quelles sont les étapes à réaliser pour atteindre mon résultat
- `Then` attend un résultat et fait une assertion
- `And`, `But` lie des étapes, ce sont des alias des trois mots clés précédents

**Réutilisez** des étapes: quand vous tapez un mot, votre IDE devrait vous donner des indices sur des steps proches ou existantes (il faut parfois installer un plugin gherkin ou cucumber).
Vous pouvez aussi utiliser les paramètres de steps pour appeler la même step mais avec des données différentes.
**Réutilisez** des étapes: quand vous tapez un mot, votre IDE devrait vous donner des indices sur des steps proches ou existantes (il faut parfois installer un plugin gherkin ou cucumber). Vous pouvez aussi utiliser les paramètres de steps pour appeler la même step mais avec des données différentes.

Pour les nouvelles steps, veuillez suivre les règles suivantes :

- commencer en minuscule
- décrire qui fait quoi: `EXEMPLE` (si possible, utiliser "the user" ou un rôle spécifique suivi d'un verbe d'action)
- décrire ce qui doit être vérifié: `EXEMPLE`
- commencer en minuscule
- décrire qui fait quoi: `EXEMPLE` (si possible, utiliser "the user" ou un rôle spécifique suivi d'un verbe d'action)
- décrire ce qui doit être vérifié: `EXEMPLE`

:information_source: Les bonnes pratiques de gherkin recommandent de n'utiliser pas plus de **un** couple de `When`/`Then` dans un test, même si c'est difficile à mettre en place dans une configuration end-to-end.

Expand All @@ -65,9 +59,9 @@ Feature: Create and update venue
And I validate venue step
And I skip offer creation
Then I should see my venue without Siret resume

[...]
```
```

## Step definition

Expand Down Expand Up @@ -96,12 +90,12 @@ Then('Paramètres généraux data should be updated', () => {

Les mauvaises implémentations de codes d'attentes sont les principales sources d'instabilité (flakiness) dans les tests E2E, soyez vigilants ! Les mauvaises pratiques sont :

- [les tests conditionnels sur un DOM instable](https://docs.cypress.io/guides/core-concepts/conditional-testing)
- attendre qu'un élément disparaisse en utilisant "cet élément ne devrait pas être visible" alors que l'élément n'est pas encore apparu : le test passe mais trop tôt, c'est un faux positif.
- utiliser `cy.wait(1000)` pour un élément qui doit apparaitre : vous ne savez pas vraiment quand l'élément va arriver, donc ça va échouer si l'app est un peut trop lente ou alors vous allez attendre plus longtemps que néccessaire et ralentir l'exécution des tests.
- [les tests conditionnels sur un DOM instable](https://docs.cypress.io/guides/core-concepts/conditional-testing)
- attendre qu'un élément disparaisse en utilisant "cet élément ne devrait pas être visible" alors que l'élément n'est pas encore apparu : le test passe mais trop tôt, c'est un faux positif.
- utiliser `cy.wait(1000)` pour un élément qui doit apparaitre : vous ne savez pas vraiment quand l'élément va arriver, donc ça va échouer si l'app est un peut trop lente ou alors vous allez attendre plus longtemps que néccessaire et ralentir l'exécution des tests.

**à la place :**

1. utilisez les `intercept` fournis par Cypress pour attendre les retours du serveur avant d'interagir avec les éléments de l'UI.
2. n'attendez pas des éléments instables comme les animations, essayez de penser à d'autres moyens d'attendre que l'app atteigne un certain état.
3. définissez des constantes de timeouts avec un bon nommage dans `support/timeouts.ts`, en mettant des timeouts courts pour que les tests ne tournent pas trop longtemps dans le cas où l'élément attendu n'apparait pas à cause d'un bug (note: cette règle n'est pas encore en place dans le projet).
3. définissez des constantes de timeouts avec un bon nommage dans `support/timeouts.ts`, en mettant des timeouts courts pour que les tests ne tournent pas trop longtemps dans le cas où l'élément attendu n'apparait pas à cause d'un bug (note: cette règle n'est pas encore en place dans le projet).
6 changes: 2 additions & 4 deletions pro/cypress/e2e/features/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ Comme dit dans le titre, ne réécrivez pas un test (ou une assertion) qui exist

### Nommez vos features et scénarios de manière à ce qu'on sache exactement ce qu'ils vont faire

En lisant votre feature et votre scénario on devrait savoir immédiatement ce que ça teste.
Pour trouver l'inspiration, on pourra par exemple utiliser une tournure à la Friends : "Celui où..."
En lisant votre feature et votre scénario on devrait savoir immédiatement ce que ça teste. Pour trouver l'inspiration, on pourra par exemple utiliser une tournure à la Friends : "Celui où..."

### Faites le plus court possible

Expand All @@ -37,11 +36,10 @@ votre scénario ne devrait pas parler de l'interface (boutons, liens, etc.). Vou

_Ex:_ `I click on "Plus Tard" link in confirmation popin`_, devrait plutôt ressembler à :_ `I skip offer creation`


## Gardez le projet propre

### La règle du boy scout

On doit laisser le code plus propre qu'on ne l'a trouvé. Cela veut dire que si vous trouvez quelque chose qui devrait être corrigé, corrigez le.

_Ex: variable mal nommée, typo, etc..._
_Ex: variable mal nommée, typo, etc..._
70 changes: 35 additions & 35 deletions pro/cypress/old_cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,46 @@ import { defineConfig } from 'cypress'
import cypressFailFast = require('cypress-fail-fast/plugin')

async function setupNodeEvents(
on: Cypress.PluginEvents,
config: Cypress.PluginConfigOptions
on: Cypress.PluginEvents,
config: Cypress.PluginConfigOptions
): Promise<Cypress.PluginConfigOptions> {
// This is required for the preprocessor to be able to generate JSON reports after each run, and more,
await addCucumberPreprocessorPlugin(on, config)
// This is required for the preprocessor to be able to generate JSON reports after each run, and more,
await addCucumberPreprocessorPlugin(on, config)

on(
'file:preprocessor',
createBundler({
plugins: [createEsbuildPlugin(config)],
})
)
cypressFailFast(on, config)
// Make sure to return the config object as it might have been modified by the plugin.
return config
on(
'file:preprocessor',
createBundler({
plugins: [createEsbuildPlugin(config)],
})
)
cypressFailFast(on, config)
// Make sure to return the config object as it might have been modified by the plugin.
return config
}

// ts-unused-exports:disable-next-line
export default defineConfig({
e2e: {
specPattern: '**/*.feature',
setupNodeEvents,
e2e: {
specPattern: '**/*.feature',
setupNodeEvents,

baseUrl: 'http://localhost:3001',
experimentalRunAllSpecs: true, // Run all specs test in UI mode
},
retries: {
runMode: 2,
openMode: 0,
},
viewportHeight: 1080,
viewportWidth: 1920,
defaultCommandTimeout: 30000,
requestTimeout: 30000,
video: true,
videoCompression: true,
watchForFileChanges: false,
env: {
FAIL_FAST_STRATEGY: 'run',
FAIL_FAST_ENABLED: true,
FAIL_FAST_BAIL: 3,
},
baseUrl: 'http://localhost:3001',
experimentalRunAllSpecs: true, // Run all specs test in UI mode
},
retries: {
runMode: 2,
openMode: 0,
},
viewportHeight: 1080,
viewportWidth: 1920,
defaultCommandTimeout: 30000,
requestTimeout: 30000,
video: true,
videoCompression: true,
watchForFileChanges: false,
env: {
FAIL_FAST_STRATEGY: 'run',
FAIL_FAST_ENABLED: true,
FAIL_FAST_BAIL: 3,
},
})
2 changes: 1 addition & 1 deletion pro/scripts/customRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import { URL_FOR_MAINTENANCE } from 'utils/config'
import { URL_FOR_MAINTENANCE } from 'commons/utils/config'
import { ApiError } from './ApiError'
import type { ApiRequestOptions } from './ApiRequestOptions'
import type { ApiResult } from './ApiResult'
Expand Down
4 changes: 2 additions & 2 deletions pro/src/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React from 'react'
import { Provider } from 'react-redux'

import { AppRouter } from 'app/AppRouter/AppRouter'
import { createStore } from 'store/store'
import { StoreProvider } from 'store/StoreProvider/StoreProvider'
import { createStore } from 'commons/store/store'
import { StoreProvider } from 'commons/store/StoreProvider/StoreProvider'

interface RootProps {
isAdageIframe: boolean
Expand Down
2 changes: 1 addition & 1 deletion pro/src/apiClient/__specs__/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import createFetchMock from 'vitest-fetch-mock'

import { api, apiContremarque } from 'apiClient/api'
import { URL_FOR_MAINTENANCE } from 'utils/config'
import { URL_FOR_MAINTENANCE } from 'commons/utils/config'

const fetchMock = createFetchMock(vi)
fetchMock.enableMocks()
Expand Down
2 changes: 1 addition & 1 deletion pro/src/apiClient/adage/core/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import { URL_FOR_MAINTENANCE } from 'utils/config'
import { URL_FOR_MAINTENANCE } from 'commons/utils/config'
import { ApiError } from './ApiError'
import type { ApiRequestOptions } from './ApiRequestOptions'
import type { ApiResult } from './ApiResult'
Expand Down
2 changes: 1 addition & 1 deletion pro/src/apiClient/api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { API_URL } from 'utils/config'
import { API_URL } from 'commons/utils/config'

import { AppClientAdage } from './adage/AppClientAdage'
import { AppClient, OpenAPIConfig } from './v1'
Expand Down
2 changes: 1 addition & 1 deletion pro/src/apiClient/v1/core/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import { URL_FOR_MAINTENANCE } from 'utils/config'
import { URL_FOR_MAINTENANCE } from 'commons/utils/config'
import { ApiError } from './ApiError'
import type { ApiRequestOptions } from './ApiRequestOptions'
import type { ApiResult } from './ApiResult'
Expand Down
2 changes: 1 addition & 1 deletion pro/src/apiClient/v2/core/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import { URL_FOR_MAINTENANCE } from 'utils/config'
import { URL_FOR_MAINTENANCE } from 'commons/utils/config'
import { ApiError } from './ApiError'
import type { ApiRequestOptions } from './ApiRequestOptions'
import type { ApiResult } from './ApiResult'
Expand Down
14 changes: 7 additions & 7 deletions pro/src/app/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@
import { isErrorAPIError } from 'apiClient/helpers'
import { useLogExtraProData } from 'app/App/hook/useLogExtraProData'
import { findCurrentRoute } from 'app/AppRouter/findCurrentRoute'
import { Notification } from 'components/Notification/Notification'
import {
GET_DATA_ERROR_MESSAGE,
SAVED_OFFERER_ID_KEY,
} from 'core/shared/constants'
import { useIsNewInterfaceActive } from 'hooks/useIsNewInterfaceActive'
import { useNotification } from 'hooks/useNotification'
} from 'commons/core/shared/constants'
import { useIsNewInterfaceActive } from 'commons/hooks/useIsNewInterfaceActive'
import { useNotification } from 'commons/hooks/useNotification'
import { updateSelectedOffererId, updateUser } from 'commons/store/user/reducer'
import { selectCurrentUser } from 'commons/store/user/selectors'
import { localStorageAvailable } from 'commons/utils/localStorageAvailable'
import { Notification } from 'components/Notification/Notification'
import { SAVED_VENUE_ID_KEY } from 'pages/Home/Offerers/PartnerPages'
import { updateSelectedOffererId, updateUser } from 'store/user/reducer'
import { selectCurrentUser } from 'store/user/selectors'
import { localStorageAvailable } from 'utils/localStorageAvailable'

import { useBeamer } from './analytics/beamer'
import { useFirebase } from './analytics/firebase'
Expand Down Expand Up @@ -82,7 +82,7 @@
dispatch(updateUser(null))
dispatch(updateSelectedOffererId(null))
}
}, [location])

Check warning on line 85 in pro/src/app/App/App.tsx

View workflow job for this annotation

GitHub Actions / Tests pro / Type check / Quality check / Style quality check

React Hook useEffect has a missing dependency: 'dispatch'. Either include it or remove the dependency array

const currentRoute = findCurrentRoute(location)
if (!currentRoute?.meta?.public && currentUser === null) {
Expand Down
6 changes: 3 additions & 3 deletions pro/src/app/App/analytics/__specs__/firebase.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { waitFor } from '@testing-library/react'
import React from 'react'
import { expect, vi } from 'vitest'

import { firebaseConfig } from 'config/firebase'
import { renderWithProviders } from 'utils/renderWithProviders'
import { sharedCurrentUserFactory } from 'utils/storeFactories'
import { firebaseConfig } from 'commons/config/firebase'
import { renderWithProviders } from 'commons/utils/renderWithProviders'
import { sharedCurrentUserFactory } from 'commons/utils/storeFactories'

import { destroyFirebase, useFirebase } from '../firebase'

Expand Down
4 changes: 2 additions & 2 deletions pro/src/app/App/analytics/beamer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { useEffect } from 'react'
import { useSelector } from 'react-redux'
import { useLocation } from 'react-router-dom'

import { useActiveFeature } from 'hooks/useActiveFeature'
import { selectCurrentUser } from 'store/user/selectors'
import { useActiveFeature } from 'commons/hooks/useActiveFeature'
import { selectCurrentUser } from 'commons/store/user/selectors'

export const useBeamer = (consentedToBeamer: boolean) => {
const isBeamerEnabled = useActiveFeature('ENABLE_BEAMER')
Expand Down
9 changes: 6 additions & 3 deletions pro/src/app/App/analytics/firebase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ import {
import { useCallback, useEffect, useState } from 'react'
import { useSelector } from 'react-redux'

import { firebaseConfig } from 'config/firebase'
import { useUtmQueryParams } from 'hooks/useUtmQueryParams'
import { selectCurrentOffererId, selectCurrentUser } from 'store/user/selectors'
import { firebaseConfig } from 'commons/config/firebase'
import { useUtmQueryParams } from 'commons/hooks/useUtmQueryParams'
import {
selectCurrentOffererId,
selectCurrentUser,
} from 'commons/store/user/selectors'

let firebaseApp: firebase.FirebaseApp | undefined
let firebaseRemoteConfig: RemoteConfig | undefined
Expand Down
4 changes: 2 additions & 2 deletions pro/src/app/App/analytics/orejime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { useEffect, useState } from 'react'
import { useLocation } from 'react-router-dom'
import { v4 as uuidv4 } from 'uuid'

import { localStorageAvailable } from 'utils/localStorageAvailable'
import { sendSentryCustomError } from 'utils/sendSentryCustomError'
import { localStorageAvailable } from 'commons/utils/localStorageAvailable'
import { sendSentryCustomError } from 'commons/utils/sendSentryCustomError'

import {
Consents,
Expand Down
4 changes: 2 additions & 2 deletions pro/src/app/App/analytics/orejimeConfig.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { api } from 'apiClient/api'
import { toISOStringWithoutMilliseconds } from 'utils/date'
import { localStorageAvailable } from 'utils/localStorageAvailable'
import { toISOStringWithoutMilliseconds } from 'commons/utils/date'
import { localStorageAvailable } from 'commons/utils/localStorageAvailable'

export enum Consents {
FIREBASE = 'firebase',
Expand Down
Loading
Loading