Repository: pass-culture/pass-culture-app-native
Pull request #8106: (PC-36045) refactor(Offer): querify query functions
Author: login: xlecunff-pass
Created: 2025-05-07T13:24:57Z | Merged: 2025-05-12T14:02:12Z

Link to JIRA ticket: https://passculture.atlassian.net/browse/PC-36045

## Flakiness

If I had to re-run tests in the CI due to flakiness, I add the incident [on Notion][2]

## Checklist

I have:

- [ ] Made sure my feature is working on web.
- [ ] Made sure my feature is working on mobile (depending on relevance : real or virtual devices)
- [ ] Written **unit tests** native (and web when implementation is different) for my feature.
- [ ] Added a **screenshot** for UI tickets or deleted the screenshot section if no UI change
- [ ] If my PR is a bugfix, I add the link of the "résolution de problème sur le bug" [on Notion][1]
- [ ] I am aware of all the best practices and respected them.

## Screenshots

**delete** _if no UI change_

| Platform         | Mockup/Before | After |
| :--------------- | :-----------: | :---: |
| iOS              |               |       |
| Android          |               |       |
| Phone - Chrome   |               |       |
| Desktop - Chrome |               |       |

[1]: https://www.notion.so/passcultureapp/R-solution-de-probl-mes-sur-les-bugs-5dd6df8f6a754e6887066cf613467d0a
[2]: https://www.notion.so/passcultureapp/cb45383351b44723a6f2d9e1481ad6bb?v=10fe47258701423985aa7d25bb04cfee&pvs=4

## Best Practices

<details>
  <summary>Click to expand</summary>

These rules apply to files that you make changes to.
If you can't respect one of these rules, be sure to explain why with a comment.
If you consider correcting the issue is too time consuming/complex: create a ticket. Link the ticket in the code.

- In the production code: remove type assertions with `as` (type assertions are removed at compile-time, there is no runtime checking associated with a type assertion. There won’t be an exception or `null` generated if the type assertion is wrong). In certain cases `as const` is acceptable (for example when defining readonly arrays/objects). Using `as` in tests is tolerable.
- Remove bypass type checking with `any` (when you want to accept anything because you will be blindly passing it through without interacting with it, you can use `unknown`). Using `any` in tests is tolerable.
- Remove non-null assertion operators (just like other type assertions, this doesn’t change the runtime behavior of your code, so it’s important to only use `!` when you know that the value can’t be `null` or `undefined`).
- Remove all `@ts-expect-error` and `@eslint-disable`.
- Remove all warnings, and errors that we are used to ignore (`yarn test:lint`, `yarn test:types`, `yarn start:web`...).
- Use `gap` (`ViewGap`) instead of `<Spacer.Column />`, `<Spacer.Row />` or `<Spacer.Flex />`.
- Don't add new "alias hooks" (hooks created to group other hooks together). When adding new logic, this hook will progressively become more complex and harder to maintain.
- Remove logic from components that should be dumb.
- undefined != null : undefined should be used for optionals and null when no value

### Request specific:

- A request must use `react-query`
- A hook that use `react-query` must:
  - folder
    - when used in one feature
      - be in `src/<feature>/queries/`
    - when used by several features
      - be in `src/queries/<the main feature related to the query>/`
  - file
    - when use `useQuery` or hook related (like `useInfiniteQuery`)
      - named `use<the content retrieved by the query>Query.ts`
      - returns the type `UseQueryResult<the content retrieved by the query>`
    - when use `useMutation`
      - named `use<the content mutated by the query>Mutation.ts`
      - returns the type `UseMutationResult<the content mutated by the query>`

### Test specific:

- Avoid mocking internal parts of our code. Ideally, mock only external calls.
- When you see a local variable that is over-written in every test, mock it.
- Prefer `user` to `fireEvent`.
- When mocking feature flags, use `setFeatureFlags`. If not possible, mention which one(s) you want to mock in a comment (example: `jest.spyOn(useFeatureFlagAPI, 'useFeatureFlag').mockReturnValue(true) // WIP_NEW_OFFER_TILE in renderPassPlaylist.tsx` )
- In component tests, replace `await act(async () => {})` and `await waitFor(/* ... */)` by `await screen.findBySomething()`.
- In hooks tests, use `act` by default and `waitFor` as a last resort.
- Make a snapshot test for pages and modals ONLY.
- Make a web specific snapshot when your web page/modal is specific to the web.
- Make an a11y test for web pages.

### Advice:

- Use TDD
- Use Storybook
- Use pair programming/mobs

</details>



Diff:
diff --git a/src/features/artist/components/ArtistBody/ArtistBody.native.test.tsx b/src/features/artist/components/ArtistBody/ArtistBody.native.test.tsx
index 52813ea1e967..65c78652e783 100644
--- a/src/features/artist/components/ArtistBody/ArtistBody.native.test.tsx
+++ b/src/features/artist/components/ArtistBody/ArtistBody.native.test.tsx
@@ -5,7 +5,7 @@ import { SubcategoryIdEnum } from 'api/gen'
 import { ArtistBody } from 'features/artist/components/ArtistBody/ArtistBody'
 import { mockOffer } from 'features/bookOffer/fixtures/offer'
 import * as useGoBack from 'features/navigation/useGoBack'
-import * as useArtistResults from 'features/offer/helpers/useArtistResults/useArtistResults'
+import * as useArtistResultsAPI from 'features/offer/queries/useArtistResultsQuery'
 import { mockedAlgoliaOffersWithSameArtistResponse } from 'libs/algolia/fixtures/algoliaFixtures'
 import { setFeatureFlags } from 'libs/firebase/firestore/featureFlags/tests/setFeatureFlags'
 import { reactQueryProviderHOC } from 'tests/reactQueryProviderHOC'
@@ -41,7 +41,7 @@ useRoute.mockReturnValue({
   },
 })
 
-const spyUseArtistResults = jest.spyOn(useArtistResults, 'useArtistResults')
+const spyUseArtistResults = jest.spyOn(useArtistResultsAPI, 'useArtistResultsQuery')
 
 const mockArtist = {
   id: '1',
diff --git a/src/features/artist/pages/Artist.native.test.tsx b/src/features/artist/pages/Artist.native.test.tsx
index 2ff0fb1c9632..108a98ef745c 100644
--- a/src/features/artist/pages/Artist.native.test.tsx
+++ b/src/features/artist/pages/Artist.native.test.tsx
@@ -3,7 +3,7 @@ import React from 'react'
 import { useRoute } from '__mocks__/@react-navigation/native'
 import { Artist } from 'features/artist/pages/Artist'
 import * as useGoBack from 'features/navigation/useGoBack'
-import * as useArtistResults from 'features/offer/helpers/useArtistResults/useArtistResults'
+import * as useArtistResultsAPI from 'features/offer/queries/useArtistResultsQuery'
 import { mockedAlgoliaOffersWithSameArtistResponse } from 'libs/algolia/fixtures/algoliaFixtures'
 import { setFeatureFlags } from 'libs/firebase/firestore/featureFlags/tests/setFeatureFlags'
 import { RemoteStoreFeatureFlags } from 'libs/firebase/firestore/types'
@@ -15,7 +15,7 @@ jest.spyOn(useGoBack, 'useGoBack').mockReturnValue({
   canGoBack: jest.fn(() => true),
 })
 
-const spyUseArtistResults = jest.spyOn(useArtistResults, 'useArtistResults')
+const spyUseArtistResults = jest.spyOn(useArtistResultsAPI, 'useArtistResultsQuery')
 
 jest.unmock('react-native/Libraries/Animated/createAnimatedComponent')
 
diff --git a/src/features/artist/pages/Artist.tsx b/src/features/artist/pages/Artist.tsx
index c79972d83595..1bb015c32b94 100644
--- a/src/features/artist/pages/Artist.tsx
+++ b/src/features/artist/pages/Artist.tsx
@@ -4,7 +4,7 @@ import React, { FunctionComponent, useMemo } from 'react'
 import { ArtistBody } from 'features/artist/components/ArtistBody/ArtistBody'
 import { ArtistType } from 'features/artist/types'
 import { UseRouteType } from 'features/navigation/RootNavigator/types'
-import { useArtistResults } from 'features/offer/helpers/useArtistResults/useArtistResults'
+import { useArtistResultsQuery } from 'features/offer/queries/useArtistResultsQuery'
 import { useFeatureFlag } from 'libs/firebase/firestore/featureFlags/useFeatureFlag'
 import { RemoteStoreFeatureFlags } from 'libs/firebase/firestore/types'
 
@@ -12,7 +12,7 @@ export const Artist: FunctionComponent = () => {
   const enableArtistPage = useFeatureFlag(RemoteStoreFeatureFlags.WIP_ARTIST_PAGE)
   const { params } = useRoute<UseRouteType<'Artist'>>()
 
-  const { artistPlaylist, artistTopOffers } = useArtistResults({
+  const { artistPlaylist, artistTopOffers } = useArtistResultsQuery({
     artistId: params.id,
   })
 
diff --git a/src/features/home/api/useAlgoliaRecommendedOffers.ts b/src/features/home/api/useAlgoliaRecommendedOffers.ts
index 140c4d08dd02..ad7c35fce8cc 100644
--- a/src/features/home/api/useAlgoliaRecommendedOffers.ts
+++ b/src/features/home/api/useAlgoliaRecommendedOffers.ts
@@ -1,5 +1,5 @@
-import { useAlgoliaSimilarOffers } from 'features/offer/api/useAlgoliaSimilarOffers'
 import { QueryKeys } from 'libs/queryKeys'
+import { useAlgoliaSimilarOffersQuery } from 'queries/offer/useAlgoliaSimilarOffersQuery'
 import { Offer } from 'shared/offer/types'
 
 export const useAlgoliaRecommendedOffers = (
@@ -7,7 +7,7 @@ export const useAlgoliaRecommendedOffers = (
   moduleId: string,
   shouldPreserveIdsOrder?: boolean
 ): Offer[] | undefined => {
-  return useAlgoliaSimilarOffers(ids, shouldPreserveIdsOrder, [
+  return useAlgoliaSimilarOffersQuery(ids, shouldPreserveIdsOrder, [
     QueryKeys.RECOMMENDATION_HITS,
     moduleId,
     ids,
diff --git a/src/features/offer/components/MoviesScreeningCalendar/VenueCalendar.tsx b/src/features/offer/components/MoviesScreeningCalendar/VenueCalendar.tsx
index 411c5af269bb..64e12c2bd19e 100644
--- a/src/features/offer/components/MoviesScreeningCalendar/VenueCalendar.tsx
+++ b/src/features/offer/components/MoviesScreeningCalendar/VenueCalendar.tsx
@@ -2,13 +2,13 @@ import React, { FunctionComponent, useCallback } from 'react'
 import { View } from 'react-native'
 import styled from 'styled-components/native'
 
-import { useOffersStocks } from 'features/offer/api/useOffersStocks'
 import { getVenueMovieOffers } from 'features/offer/components/MoviesScreeningCalendar/hook/getVenueMovieOffers'
 import {
   useDisplayCalendar,
   useMovieCalendar,
 } from 'features/offer/components/MoviesScreeningCalendar/MovieCalendarContext'
 import { MovieOfferTile } from 'features/offer/components/MoviesScreeningCalendar/MovieOfferTile'
+import { useOffersStocksQuery } from 'features/offer/queries/useOffersStocksQuery'
 import { VenueOffers } from 'features/venue/types'
 import { Spacer } from 'ui/theme'
 
@@ -18,7 +18,7 @@ type Props = {
 }
 
 export const VenueCalendar: FunctionComponent<Props> = ({ venueOffers, offerIds }) => {
-  const { data: offersWithStocks } = useOffersStocks({ offerIds })
+  const { data: offersWithStocks } = useOffersStocksQuery({ offerIds })
 
   const { selectedDate } = useMovieCalendar()
 
diff --git a/src/features/offer/components/OfferBody/OfferBody.native.test.tsx b/src/features/offer/components/OfferBody/OfferBody.native.test.tsx
index 742be975a7bf..72d247bc930f 100644
--- a/src/features/offer/components/OfferBody/OfferBody.native.test.tsx
+++ b/src/features/offer/components/OfferBody/OfferBody.native.test.tsx
@@ -14,7 +14,7 @@ import {
 import { OfferBody } from 'features/offer/components/OfferBody/OfferBody'
 import { mockSubcategory, mockSubcategoryBook } from 'features/offer/fixtures/mockSubcategory'
 import { offerResponseSnap } from 'features/offer/fixtures/offerResponse'
-import * as useArtistResults from 'features/offer/helpers/useArtistResults/useArtistResults'
+import * as useArtistResultsAPI from 'features/offer/queries/useArtistResultsQuery'
 import { mockedAlgoliaOffersWithSameArtistResponse } from 'libs/algolia/fixtures/algoliaFixtures'
 import { analytics } from 'libs/analytics/provider'
 import { setFeatureFlags } from 'libs/firebase/firestore/featureFlags/tests/setFeatureFlags'
@@ -61,7 +61,7 @@ jest.mock('react-native/Libraries/Animated/createAnimatedComponent', () => {
 })
 
 const useArtistResultsSpy = jest
-  .spyOn(useArtistResults, 'useArtistResults')
+  .spyOn(useArtistResultsAPI, 'useArtistResultsQuery')
   .mockImplementation()
   .mockReturnValue({
     artistPlaylist: mockedAlgoliaOffersWithSameArtistResponse,
diff --git a/src/features/offer/components/OfferBody/OfferBody.tsx b/src/features/offer/components/OfferBody/OfferBody.tsx
index 588573d99788..508d4aea526d 100644
--- a/src/features/offer/components/OfferBody/OfferBody.tsx
+++ b/src/features/offer/components/OfferBody/OfferBody.tsx
@@ -17,8 +17,8 @@ import { OfferVenueButton } from 'features/offer/components/OfferVenueButton/Off
 import { getOfferMetadata } from 'features/offer/helpers/getOfferMetadata/getOfferMetadata'
 import { getOfferPrices } from 'features/offer/helpers/getOfferPrice/getOfferPrice'
 import { getOfferTags } from 'features/offer/helpers/getOfferTags/getOfferTags'
-import { useArtistResults } from 'features/offer/helpers/useArtistResults/useArtistResults'
 import { useOfferSummaryInfoList } from 'features/offer/helpers/useOfferSummaryInfoList/useOfferSummaryInfoList'
+import { useArtistResultsQuery } from 'features/offer/queries/useArtistResultsQuery'
 import { analytics } from 'libs/analytics/provider'
 import { useFeatureFlag } from 'libs/firebase/firestore/featureFlags/useFeatureFlag'
 import { RemoteStoreFeatureFlags } from 'libs/firebase/firestore/types'
@@ -81,7 +81,7 @@ export const OfferBody: FunctionComponent<Props> = ({
     { fractionDigits: 2 }
   )
 
-  const { artistPlaylist: artistOffers } = useArtistResults({
+  const { artistPlaylist: artistOffers } = useArtistResultsQuery({
     artistId: artists.length > 0 ? artists[0]?.id : undefined,
     subcategoryId: offer.subcategoryId,
   })
diff --git a/src/features/offer/components/OfferCine/OfferCineContent.native.test.tsx b/src/features/offer/components/OfferCine/OfferCineContent.native.test.tsx
index 8de4570af2bc..5f1f42bc0d4d 100644
--- a/src/features/offer/components/OfferCine/OfferCineContent.native.test.tsx
+++ b/src/features/offer/components/OfferCine/OfferCineContent.native.test.tsx
@@ -31,12 +31,9 @@ const defaultOffersStocksFromOfferQuery = {
   data: mockBuilder.offerResponseV2({}),
 }
 const mockuseOffersStocksFromOfferQuery = jest.fn(() => defaultOffersStocksFromOfferQuery)
-jest.mock(
-  'features/offer/helpers/useOffersStocksFromOfferQuery/useOffersStocksFromOfferQuery',
-  () => ({
-    useOffersStocksFromOfferQuery: () => mockuseOffersStocksFromOfferQuery(),
-  })
-)
+jest.mock('features/offer/queries/useOffersStocksFromOfferQuery', () => ({
+  useOffersStocksFromOfferQuery: () => mockuseOffersStocksFromOfferQuery(),
+}))
 
 jest.mock('features/offer/helpers/useGetVenueByDay/useGetVenuesByDay', () => ({
   useGetVenuesByDay: () => ({
diff --git a/src/features/offer/components/OfferCine/OfferCineContent.tsx b/src/features/offer/components/OfferCine/OfferCineContent.tsx
index 34463f9fb996..6e076f66d707 100644
--- a/src/features/offer/components/OfferCine/OfferCineContent.tsx
+++ b/src/features/offer/components/OfferCine/OfferCineContent.tsx
@@ -16,7 +16,7 @@ import {
   useGetVenuesByDay,
 } from 'features/offer/helpers/useGetVenueByDay/useGetVenuesByDay'
 import { useListExpander } from 'features/offer/helpers/useListExpander/useListExpander'
-import { useOffersStocksFromOfferQuery } from 'features/offer/helpers/useOffersStocksFromOfferQuery/useOffersStocksFromOfferQuery'
+import { useOffersStocksFromOfferQuery } from 'features/offer/queries/useOffersStocksFromOfferQuery'
 import { ButtonSecondary } from 'ui/components/buttons/ButtonSecondary'
 import { PlainMore } from 'ui/svg/icons/PlainMore'
 import { Typo, getSpacing } from 'ui/theme'
diff --git a/src/features/offer/components/OfferContent/OfferContent.native.test.tsx b/src/features/offer/components/OfferContent/OfferContent.native.test.tsx
index 68420eb96ac3..9d8f0272422d 100644
--- a/src/features/offer/components/OfferContent/OfferContent.native.test.tsx
+++ b/src/features/offer/components/OfferContent/OfferContent.native.test.tsx
@@ -21,12 +21,12 @@ import { favoriteResponseSnap } from 'features/favorites/fixtures/favoriteRespon
 import * as useFavorite from 'features/favorites/hooks/useFavorite'
 import * as useGoBack from 'features/navigation/useGoBack'
 import { chroniclePreviewToChronicalCardData } from 'features/offer/adapters/chroniclePreviewToChronicleCardData'
-import * as useSimilarOffers from 'features/offer/api/useSimilarOffers'
 import { CineContentCTAID } from 'features/offer/components/OfferCine/CineContentCTA'
 import { PlaylistType } from 'features/offer/enums'
 import { mockSubcategory } from 'features/offer/fixtures/mockSubcategory'
 import { offerResponseSnap } from 'features/offer/fixtures/offerResponse'
-import * as useArtistResults from 'features/offer/helpers/useArtistResults/useArtistResults'
+import * as useArtistResultsAPI from 'features/offer/queries/useArtistResultsQuery'
+import * as useSimilarOffersAPI from 'features/offer/queries/useSimilarOffersQuery'
 import { beneficiaryUser } from 'fixtures/user'
 import {
   mockedAlgoliaOffersWithSameArtistResponse,
@@ -104,10 +104,10 @@ const apiRecoParams: RecommendationApiParams = {
 }
 
 const useSimilarOffersSpy = jest
-  .spyOn(useSimilarOffers, 'useSimilarOffers')
+  .spyOn(useSimilarOffersAPI, 'useSimilarOffersQuery')
   .mockReturnValue({ similarOffers: undefined, apiRecoParams: undefined })
 
-jest.spyOn(useArtistResults, 'useArtistResults').mockReturnValue({
+jest.spyOn(useArtistResultsAPI, 'useArtistResultsQuery').mockReturnValue({
   artistPlaylist: mockedAlgoliaOffersWithSameArtistResponse,
   artistTopOffers: mockedAlgoliaOffersWithSameArtistResponse.slice(0, 4),
 })
diff --git a/src/features/offer/components/OfferContent/OfferContent.web.test.tsx b/src/features/offer/components/OfferContent/OfferContent.web.test.tsx
index 51241472a722..5483cd54fdc2 100644
--- a/src/features/offer/components/OfferContent/OfferContent.web.test.tsx
+++ b/src/features/offer/components/OfferContent/OfferContent.web.test.tsx
@@ -2,9 +2,9 @@ import React, { ComponentProps } from 'react'
 import * as ReactQueryAPI from 'react-query'
 
 import { OfferResponseV2, SubcategoriesResponseModelv2 } from 'api/gen'
-import * as useSimilarOffers from 'features/offer/api/useSimilarOffers'
 import { mockSubcategory } from 'features/offer/fixtures/mockSubcategory'
 import { offerResponseSnap } from 'features/offer/fixtures/offerResponse'
+import * as useSimilarOffersAPI from 'features/offer/queries/useSimilarOffersQuery'
 import { setFeatureFlags } from 'libs/firebase/firestore/featureFlags/tests/setFeatureFlags'
 import { RemoteStoreFeatureFlags } from 'libs/firebase/firestore/types'
 import { Position } from 'libs/location'
@@ -52,7 +52,7 @@ useQueryClientSpy.mockReturnValue({
 } as unknown as ReactQueryAPI.QueryClient)
 
 jest
-  .spyOn(useSimilarOffers, 'useSimilarOffers')
+  .spyOn(useSimilarOffersAPI, 'useSimilarOffersQuery')
   .mockReturnValue({ similarOffers: undefined, apiRecoParams: undefined })
 
 jest.mock('features/auth/context/AuthContext')
diff --git a/src/features/offer/helpers/useOfferPlaylist/useOfferPlaylist.test.ts b/src/features/offer/helpers/useOfferPlaylist/useOfferPlaylist.test.ts
index ab01671d6543..9058e3bbbc29 100644
--- a/src/features/offer/helpers/useOfferPlaylist/useOfferPlaylist.test.ts
+++ b/src/features/offer/helpers/useOfferPlaylist/useOfferPlaylist.test.ts
@@ -1,7 +1,7 @@
 import { RecommendationApiParams, SearchGroupNameEnumv2 } from 'api/gen'
-import * as useSimilarOffers from 'features/offer/api/useSimilarOffers'
 import { offerResponseSnap } from 'features/offer/fixtures/offerResponse'
 import { useOfferPlaylist } from 'features/offer/helpers/useOfferPlaylist/useOfferPlaylist'
+import * as useSimilarOffersAPI from 'features/offer/queries/useSimilarOffersQuery'
 import { moreHitsForSimilarOffersPlaylist } from 'libs/algolia/fixtures/algoliaFixtures'
 import { Position } from 'libs/location'
 import { searchGroupsDataTest } from 'libs/subcategories/fixtures/subcategoriesResponse'
@@ -22,7 +22,7 @@ const offerSearchGroup = SearchGroupNameEnumv2.CINEMA
 const searchGroupList = searchGroupsDataTest
 
 const useSimilarOffersSpy = jest
-  .spyOn(useSimilarOffers, 'useSimilarOffers')
+  .spyOn(useSimilarOffersAPI, 'useSimilarOffersQuery')
   .mockImplementation()
   .mockReturnValue({ similarOffers: moreHitsForSimilarOffersPlaylist, apiRecoParams })
 
diff --git a/src/features/offer/helpers/useOfferPlaylist/useOfferPlaylist.ts b/src/features/offer/helpers/useOfferPlaylist/useOfferPlaylist.ts
index 7cf5a4ca7a15..f38e1f2bc308 100644
--- a/src/features/offer/helpers/useOfferPlaylist/useOfferPlaylist.ts
+++ b/src/features/offer/helpers/useOfferPlaylist/useOfferPlaylist.ts
@@ -7,7 +7,7 @@ import {
   SearchGroupNameEnumv2,
   SearchGroupResponseModelv2,
 } from 'api/gen'
-import { useSimilarOffers } from 'features/offer/api/useSimilarOffers'
+import { useSimilarOffersQuery } from 'features/offer/queries/useSimilarOffersQuery'
 import { Position, useLocation } from 'libs/location'
 import { Offer } from 'shared/offer/types'
 
@@ -44,7 +44,7 @@ export const useOfferPlaylist = ({
   const position = userLocation ? roundedPosition : undefined
 
   const { similarOffers: sameCategorySimilarOffers, apiRecoParams: apiRecoParamsSameCategory } =
-    useSimilarOffers({
+    useSimilarOffersQuery({
       offerId: offer.id,
       shouldFetch: isFocused,
       position,
@@ -54,7 +54,7 @@ export const useOfferPlaylist = ({
   const {
     similarOffers: otherCategoriesSimilarOffers,
     apiRecoParams: apiRecoParamsOtherCategories,
-  } = useSimilarOffers({
+  } = useSimilarOffersQuery({
     offerId: offer.id,
     shouldFetch: isFocused,
     position,
diff --git a/src/features/offer/pages/Offer/Offer.native.test.tsx b/src/features/offer/pages/Offer/Offer.native.test.tsx
index 87666192412d..735766ed7437 100644
--- a/src/features/offer/pages/Offer/Offer.native.test.tsx
+++ b/src/features/offer/pages/Offer/Offer.native.test.tsx
@@ -5,9 +5,9 @@ import {
   SubcategoriesResponseModelv2,
 } from 'api/gen'
 import { bookingsSnap } from 'features/bookings/fixtures/bookingsSnap'
-import * as useSimilarOffers from 'features/offer/api/useSimilarOffers'
 import { offerResponseSnap } from 'features/offer/fixtures/offerResponse'
-import * as useArtistResults from 'features/offer/helpers/useArtistResults/useArtistResults'
+import * as useArtistResultsAPI from 'features/offer/queries/useArtistResultsQuery'
+import * as useSimilarOffersAPI from 'features/offer/queries/useSimilarOffersQuery'
 import { renderOfferPage } from 'features/offer/tests/renderOfferPageTestUtil'
 import { mockedAlgoliaOffersWithSameArtistResponse } from 'libs/algolia/fixtures/algoliaFixtures'
 import { setFeatureFlags } from 'libs/firebase/firestore/featureFlags/tests/setFeatureFlags'
@@ -22,12 +22,12 @@ jest.unmock('react-native/Libraries/Animated/createAnimatedComponent')
 jest.mock('libs/jwt/jwt')
 
 jest
-  .spyOn(useSimilarOffers, 'useSimilarOffers')
+  .spyOn(useSimilarOffersAPI, 'useSimilarOffersQuery')
   .mockImplementation()
   .mockReturnValue({ similarOffers: undefined, apiRecoParams: undefined })
 
 jest
-  .spyOn(useArtistResults, 'useArtistResults')
+  .spyOn(useArtistResultsAPI, 'useArtistResultsQuery')
   .mockImplementation()
   .mockReturnValue({
     artistPlaylist: mockedAlgoliaOffersWithSameArtistResponse,
diff --git a/src/features/offer/pages/Offer/Offer.perf.test.tsx b/src/features/offer/pages/Offer/Offer.perf.test.tsx
index 45c29bee7107..41255900e8fd 100644
--- a/src/features/offer/pages/Offer/Offer.perf.test.tsx
+++ b/src/features/offer/pages/Offer/Offer.perf.test.tsx
@@ -9,8 +9,8 @@ import {
 } from 'api/gen'
 import { offerResponseSnap } from 'features/offer/fixtures/offerResponse'
 import * as GetInstalledAppsAPI from 'features/offer/helpers/getInstalledApps/getInstalledApps'
-import * as useArtistResults from 'features/offer/helpers/useArtistResults/useArtistResults'
 import { Offer } from 'features/offer/pages/Offer/Offer'
+import * as useArtistResultsAPI from 'features/offer/queries/useArtistResultsQuery'
 import {
   mockedAlgoliaOffersWithSameArtistResponse,
   mockedAlgoliaResponse,
@@ -31,7 +31,7 @@ jest.mock('react-native/Libraries/Alert/Alert', () => ({
 }))
 
 jest
-  .spyOn(useArtistResults, 'useArtistResults')
+  .spyOn(useArtistResultsAPI, 'useArtistResultsQuery')
   .mockImplementation()
   .mockReturnValue({
     artistPlaylist: mockedAlgoliaOffersWithSameArtistResponse,
diff --git a/src/features/offer/helpers/useArtistResults/useArtistResults.native.test.ts b/src/features/offer/queries/useArtistResultsQuery.native.test.ts
similarity index 90%
rename from src/features/offer/helpers/useArtistResults/useArtistResults.native.test.ts
rename to src/features/offer/queries/useArtistResultsQuery.native.test.ts
index 14c2097eb5ed..ab9a414e7240 100644
--- a/src/features/offer/helpers/useArtistResults/useArtistResults.native.test.ts
+++ b/src/features/offer/queries/useArtistResultsQuery.native.test.ts
@@ -1,5 +1,5 @@
 import { SubcategoryIdEnum } from 'api/gen'
-import { useArtistResults } from 'features/offer/helpers/useArtistResults/useArtistResults'
+import { useArtistResultsQuery } from 'features/offer/queries/useArtistResultsQuery'
 import { mockedAlgoliaOffersWithSameArtistResponse } from 'libs/algolia/fixtures/algoliaFixtures'
 import * as useRemoteConfigQuery from 'libs/firebase/remoteConfig/queries/useRemoteConfigQuery'
 import { DEFAULT_REMOTE_CONFIG } from 'libs/firebase/remoteConfig/remoteConfig.constants'
@@ -7,7 +7,7 @@ import { Position } from 'libs/location/types'
 import { reactQueryProviderHOC } from 'tests/reactQueryProviderHOC'
 import { renderHook, waitFor } from 'tests/utils'
 
-import * as fetchOffersByArtist from '../../api/fetchOffersByArtist/fetchOffersByArtist'
+import * as fetchOffersByArtist from '../api/fetchOffersByArtist/fetchOffersByArtist'
 
 jest.mock('libs/react-query/usePersistQuery', () => ({
   usePersistQuery: jest.requireActual('react-query').useQuery,
@@ -29,7 +29,7 @@ jest.mock('libs/location/LocationWrapper', () => ({
 
 const useRemoteConfigSpy = jest.spyOn(useRemoteConfigQuery, 'useRemoteConfigQuery')
 
-describe('useArtistResults', () => {
+describe('useArtistResultsQuery', () => {
   beforeAll(() => {
     useRemoteConfigSpy.mockReturnValue({
       ...DEFAULT_REMOTE_CONFIG,
@@ -40,7 +40,7 @@ describe('useArtistResults', () => {
   it('should fetch same artist playlist when artistId and subcategory compatible with artist page defined', async () => {
     renderHook(
       () =>
-        useArtistResults({
+        useArtistResultsQuery({
           artistId: '1',
           subcategoryId: SubcategoryIdEnum.LIVRE_PAPIER,
         }),
@@ -60,7 +60,7 @@ describe('useArtistResults', () => {
   it('should fetch same artist playlist when artistId defined and subcategory not defined', async () => {
     renderHook(
       () =>
-        useArtistResults({
+        useArtistResultsQuery({
           artistId: '1',
         }),
       {
@@ -79,7 +79,7 @@ describe('useArtistResults', () => {
   it('should not fetch same artist playlist when subcategory compatible with artist page defined and artistId not defined', async () => {
     renderHook(
       () =>
-        useArtistResults({
+        useArtistResultsQuery({
           subcategoryId: SubcategoryIdEnum.LIVRE_PAPIER,
         }),
       {
@@ -91,7 +91,7 @@ describe('useArtistResults', () => {
   })
 
   it('should not fetch same artist playlist when subcategory compatible with artist page and artistId not defined', async () => {
-    renderHook(() => useArtistResults({}), {
+    renderHook(() => useArtistResultsQuery({}), {
       wrapper: ({ children }) => reactQueryProviderHOC(children),
     })
 
@@ -103,7 +103,7 @@ describe('useArtistResults', () => {
 
     const { result } = renderHook(
       () =>
-        useArtistResults({
+        useArtistResultsQuery({
           artistId: '1',
           subcategoryId: SubcategoryIdEnum.LIVRE_PAPIER,
         }),
@@ -122,7 +122,7 @@ describe('useArtistResults', () => {
 
     const { result } = renderHook(
       () =>
-        useArtistResults({
+        useArtistResultsQuery({
           artistId: '1',
           subcategoryId: SubcategoryIdEnum.LIVRE_PAPIER,
         }),
diff --git a/src/features/offer/helpers/useArtistResults/useArtistResults.tsx b/src/features/offer/queries/useArtistResultsQuery.ts
similarity index 96%
rename from src/features/offer/helpers/useArtistResults/useArtistResults.tsx
rename to src/features/offer/queries/useArtistResultsQuery.ts
index 4fa771274b7b..cee20f18952e 100644
--- a/src/features/offer/helpers/useArtistResults/useArtistResults.tsx
+++ b/src/features/offer/queries/useArtistResultsQuery.ts
@@ -16,7 +16,7 @@ type UseArtistResultsProps = {
   artistId?: string
 }
 
-export const useArtistResults = ({ artistId, subcategoryId }: UseArtistResultsProps) => {
+export const useArtistResultsQuery = ({ artistId, subcategoryId }: UseArtistResultsProps) => {
   const transformHits = useTransformOfferHits()
   const { userLocation } = useLocation()
   const { artistPageSubcategories } = useRemoteConfigQuery()
diff --git a/src/features/offer/api/useFetchOffers.ts b/src/features/offer/queries/useFetchOffersQuery.ts
similarity index 76%
rename from src/features/offer/api/useFetchOffers.ts
rename to src/features/offer/queries/useFetchOffersQuery.ts
index 5bf88b9d5c7c..615ef8bb6eb0 100644
--- a/src/features/offer/api/useFetchOffers.ts
+++ b/src/features/offer/queries/useFetchOffersQuery.ts
@@ -3,7 +3,7 @@ import { useQuery } from 'react-query'
 import { fetchOffers } from 'libs/algolia/fetchAlgolia/fetchOffers'
 import { QueryKeys } from 'libs/queryKeys'
 
-export const useFetchOffers = (...params: Parameters<typeof fetchOffers>) => {
+export const useFetchOffersQuery = (...params: Parameters<typeof fetchOffers>) => {
   return useQuery({
     queryKey: [QueryKeys.SEARCH_RESULTS, params],
     queryFn: () => fetchOffers(...params),
diff --git a/src/features/offer/helpers/useOffersStocksFromOfferQuery/useOffersStocksFromOfferQuery.native.test.ts b/src/features/offer/queries/useOffersStocksFromOfferQuery.native.test.ts
similarity index 96%
rename from src/features/offer/helpers/useOffersStocksFromOfferQuery/useOffersStocksFromOfferQuery.native.test.ts
rename to src/features/offer/queries/useOffersStocksFromOfferQuery.native.test.ts
index adfcc2cc3c87..4607c9e86199 100644
--- a/src/features/offer/helpers/useOffersStocksFromOfferQuery/useOffersStocksFromOfferQuery.native.test.ts
+++ b/src/features/offer/queries/useOffersStocksFromOfferQuery.native.test.ts
@@ -1,7 +1,7 @@
 import mockdate from 'mockdate'
 
 import * as getStocksByOfferIdsModule from 'features/offer/api/getStocksByOfferIds'
-import { useOffersStocksFromOfferQuery } from 'features/offer/helpers/useOffersStocksFromOfferQuery/useOffersStocksFromOfferQuery'
+import { useOffersStocksFromOfferQuery } from 'features/offer/queries/useOffersStocksFromOfferQuery'
 import * as fetchAlgoliaOffer from 'libs/algolia/fetchAlgolia/fetchOffers'
 import { LocationMode, Position } from 'libs/location/types'
 import { dateBuilder, mockBuilder } from 'tests/mockBuilder'
diff --git a/src/features/offer/helpers/useOffersStocksFromOfferQuery/useOffersStocksFromOfferQuery.ts b/src/features/offer/queries/useOffersStocksFromOfferQuery.ts
similarity index 86%
rename from src/features/offer/helpers/useOffersStocksFromOfferQuery/useOffersStocksFromOfferQuery.ts
rename to src/features/offer/queries/useOffersStocksFromOfferQuery.ts
index 599af30aacf3..f7164e8f4fe8 100644
--- a/src/features/offer/helpers/useOffersStocksFromOfferQuery/useOffersStocksFromOfferQuery.ts
+++ b/src/features/offer/queries/useOffersStocksFromOfferQuery.ts
@@ -1,9 +1,9 @@
 import { Hit } from '@algolia/client-search'
 
 import { OfferResponseV2 } from 'api/gen'
-import { useFetchOffers } from 'features/offer/api/useFetchOffers'
-import { useOffersStocks } from 'features/offer/api/useOffersStocks'
 import { useUserLocation } from 'features/offer/helpers/useUserLocation/useUserLocation'
+import { useFetchOffersQuery } from 'features/offer/queries/useFetchOffersQuery'
+import { useOffersStocksQuery } from 'features/offer/queries/useOffersStocksQuery'
 import { useIsUserUnderage } from 'features/profile/helpers/useIsUserUnderage'
 import { initialSearchState } from 'features/search/context/reducer'
 import { SearchQueryParameters } from 'libs/algolia/types'
@@ -31,7 +31,7 @@ export const useOffersStocksFromOfferQuery = (
     searchQueryParameters = { ...searchQueryParameters, objectIds: [offer.id.toString()] }
   }
 
-  const { data } = useFetchOffers({
+  const { data } = useFetchOffersQuery({
     parameters: searchQueryParameters,
     buildLocationParameterParams: {
       userLocation,
@@ -44,7 +44,7 @@ export const useOffersStocksFromOfferQuery = (
 
   const offerIds = extractOfferIdsFromHits(data?.hits)
 
-  const offersStocks = useOffersStocks({ offerIds })
+  const offersStocks = useOffersStocksQuery({ offerIds })
 
   return { ...offersStocks, data: offersStocks.data ?? { offers: [] } }
 }
diff --git a/src/features/offer/api/useOffersStocks.native.test.ts b/src/features/offer/queries/useOffersStocksQuery.native.test.ts
similarity index 79%
rename from src/features/offer/api/useOffersStocks.native.test.ts
rename to src/features/offer/queries/useOffersStocksQuery.native.test.ts
index cee1ce825838..9c6fd2e07ac1 100644
--- a/src/features/offer/api/useOffersStocks.native.test.ts
+++ b/src/features/offer/queries/useOffersStocksQuery.native.test.ts
@@ -1,6 +1,6 @@
 import { OffersStocksResponseV2 } from 'api/gen'
-import { useOffersStocks } from 'features/offer/api/useOffersStocks'
 import { offersStocksResponseSnap } from 'features/offer/fixtures/offersStocksResponse'
+import { useOffersStocksQuery } from 'features/offer/queries/useOffersStocksQuery'
 import { mockServer } from 'tests/mswServer'
 import { reactQueryProviderHOC } from 'tests/reactQueryProviderHOC'
 import { act, renderHook } from 'tests/utils'
@@ -8,14 +8,14 @@ import { act, renderHook } from 'tests/utils'
 jest.mock('libs/network/NetInfoWrapper')
 jest.mock('libs/firebase/analytics/analytics')
 
-describe('useOffersStocks', () => {
+describe('useOffersStocksQuery', () => {
   beforeEach(() => {
     mockServer.postApi<OffersStocksResponseV2>(`/v2/offers/stocks`, offersStocksResponseSnap)
   })
 
   it('should call API', async () => {
     const { result } = renderHook(
-      () => useOffersStocks({ offerIds: [offersStocksResponseSnap.offers[0].id] }),
+      () => useOffersStocksQuery({ offerIds: [offersStocksResponseSnap.offers[0].id] }),
       {
         wrapper: ({ children }) => reactQueryProviderHOC(children),
       }
diff --git a/src/features/offer/api/useOffersStocks.ts b/src/features/offer/queries/useOffersStocksQuery.ts
similarity index 85%
rename from src/features/offer/api/useOffersStocks.ts
rename to src/features/offer/queries/useOffersStocksQuery.ts
index 527619163cdb..89ebaf5ee27c 100644
--- a/src/features/offer/api/useOffersStocks.ts
+++ b/src/features/offer/queries/useOffersStocksQuery.ts
@@ -5,7 +5,7 @@ import { getStocksByOfferIds } from 'features/offer/api/getStocksByOfferIds'
 import { useLogTypeFromRemoteConfig } from 'libs/hooks/useLogTypeFromRemoteConfig'
 import { QueryKeys } from 'libs/queryKeys'
 
-export const useOffersStocks = ({ offerIds }: { offerIds: number[] }) => {
+export const useOffersStocksQuery = ({ offerIds }: { offerIds: number[] }) => {
   const { logType } = useLogTypeFromRemoteConfig()
 
   return useQuery<OffersStocksResponseV2>([QueryKeys.OFFER, offerIds], () =>
diff --git a/src/features/offer/api/useSimilarOffers.native.test.ts b/src/features/offer/queries/useSimilarOffersQuery.native.test.ts
similarity index 93%
rename from src/features/offer/api/useSimilarOffers.native.test.ts
rename to src/features/offer/queries/useSimilarOffersQuery.native.test.ts
index b3077d14c427..4184cba08f86 100644
--- a/src/features/offer/api/useSimilarOffers.native.test.ts
+++ b/src/features/offer/queries/useSimilarOffersQuery.native.test.ts
@@ -1,13 +1,13 @@
 import { onlineManager } from 'react-query'
 
 import { SearchGroupNameEnumv2, SimilarOffersResponse } from 'api/gen'
-import * as useAlgoliaSimilarOffers from 'features/offer/api/useAlgoliaSimilarOffers'
-import { getCategories, useSimilarOffers } from 'features/offer/api/useSimilarOffers'
+import { getCategories, useSimilarOffersQuery } from 'features/offer/queries/useSimilarOffersQuery'
 import { env } from 'libs/environment/fixtures'
 import { EmptyResponse } from 'libs/fetch'
 import { eventMonitoring } from 'libs/monitoring/services'
 import * as PackageJson from 'libs/packageJson'
 import { searchGroupsDataTest } from 'libs/subcategories/fixtures/subcategoriesResponse'
+import * as useAlgoliaSimilarOffersAPI from 'queries/offer/useAlgoliaSimilarOffersQuery'
 import { mockServer } from 'tests/mswServer'
 import { reactQueryProviderHOC } from 'tests/reactQueryProviderHOC'
 import { renderHook, waitFor } from 'tests/utils'
@@ -22,14 +22,12 @@ const position = {
 jest.mock('features/auth/context/AuthContext')
 jest.mock('libs/subcategories/useSubcategories')
 
-const algoliaSpy = jest
-  .spyOn(useAlgoliaSimilarOffers, 'useAlgoliaSimilarOffers')
-  .mockImplementation()
+const algoliaSpy = jest.spyOn(useAlgoliaSimilarOffersAPI, 'useAlgoliaSimilarOffersQuery')
 const fetchApiRecoSpy = jest.spyOn(global, 'fetch')
 
 jest.spyOn(PackageJson, 'getAppVersion').mockReturnValue('1.10.5')
 
-describe('useSimilarOffers', () => {
+describe('useSimilarOffersQuery', () => {
   describe('When success API response', () => {
     beforeEach(() => {
       mockServer.getApi<SimilarOffersResponse>(`/v1/recommendation/similar_offers/${mockOfferId}`, {
@@ -41,7 +39,7 @@ describe('useSimilarOffers', () => {
     it('should call Algolia hook with category included', async () => {
       renderHook(
         () =>
-          useSimilarOffers({
+          useSimilarOffersQuery({
             offerId: mockOfferId,
             shouldFetch: true,
             position,
@@ -59,7 +57,7 @@ describe('useSimilarOffers', () => {
     it('should call Algolia hook with category excluded', async () => {
       renderHook(
         () =>
-          useSimilarOffers({
+          useSimilarOffersQuery({
             offerId: mockOfferId,
             shouldFetch: true,
             position,
@@ -77,7 +75,7 @@ describe('useSimilarOffers', () => {
     it('should call similar offers API when offer id provided and user share his position', async () => {
       renderHook(
         () =>
-          useSimilarOffers({
+          useSimilarOffersQuery({
             offerId: mockOfferId,
             shouldFetch: true,
             categoryIncluded: SearchGroupNameEnumv2.CINEMA,
@@ -111,7 +109,7 @@ describe('useSimilarOffers', () => {
     it('should call similar offers API when offer id provided and user not share his position', async () => {
       renderHook(
         () =>
-          useSimilarOffers({
+          useSimilarOffersQuery({
             offerId: mockOfferId,
             shouldFetch: true,
             categoryIncluded: SearchGroupNameEnumv2.CINEMA,
@@ -145,7 +143,7 @@ describe('useSimilarOffers', () => {
     it('should not call similar offers API when offer id provided, user share his position and shouldFetch is false', () => {
       renderHook(
         () =>
-          useSimilarOffers({
+          useSimilarOffersQuery({
             offerId: mockOfferId,
             shouldFetch: false,
             categoryIncluded: SearchGroupNameEnumv2.CINEMA,
@@ -167,7 +165,7 @@ describe('useSimilarOffers', () => {
       })
       const { result } = renderHook(
         () =>
-          useSimilarOffers({
+          useSimilarOffersQuery({
             offerId: mockOfferId,
             shouldFetch: true,
             categoryIncluded: SearchGroupNameEnumv2.CINEMA,
@@ -190,7 +188,7 @@ describe('useSimilarOffers', () => {
     })
     renderHook(
       () =>
-        useSimilarOffers({
+        useSimilarOffersQuery({
           offerId: mockOfferId,
           shouldFetch: true,
           categoryIncluded: SearchGroupNameEnumv2.CINEMA,
@@ -232,7 +230,7 @@ describe('useSimilarOffers', () => {
       })
       renderHook(
         () =>
-          useSimilarOffers({
+          useSimilarOffersQuery({
             offerId: mockOfferId,
             shouldFetch: true,
             categoryIncluded: SearchGroupNameEnumv2.CINEMA,
@@ -254,7 +252,7 @@ describe('useSimilarOffers', () => {
 
     renderHook(
       () =>
-        useSimilarOffers({
+        useSimilarOffersQuery({
           offerId: mockOfferId,
           shouldFetch: true,
           categoryIncluded: SearchGroupNameEnumv2.CINEMA,
diff --git a/src/features/offer/api/useSimilarOffers.ts b/src/features/offer/queries/useSimilarOffersQuery.ts
similarity index 93%
rename from src/features/offer/api/useSimilarOffers.ts
rename to src/features/offer/queries/useSimilarOffersQuery.ts
index c426ce338e1f..0efe00977a3e 100644
--- a/src/features/offer/api/useSimilarOffers.ts
+++ b/src/features/offer/queries/useSimilarOffersQuery.ts
@@ -5,10 +5,10 @@ import { api } from 'api/api'
 import { ApiError } from 'api/ApiError'
 import { isAPIExceptionNotCaptured } from 'api/apiHelpers'
 import { SearchGroupNameEnumv2, SearchGroupResponseModelv2 } from 'api/gen'
-import { useAlgoliaSimilarOffers } from 'features/offer/api/useAlgoliaSimilarOffers'
 import { Position } from 'libs/location'
 import { eventMonitoring } from 'libs/monitoring/services'
 import { QueryKeys } from 'libs/queryKeys'
+import { useAlgoliaSimilarOffersQuery } from 'queries/offer/useAlgoliaSimilarOffersQuery'
 
 type WithIncludeCategoryProps = {
   categoryIncluded: SearchGroupNameEnumv2
@@ -48,7 +48,7 @@ export const getCategories = (
   return []
 }
 
-export const useSimilarOffers = ({
+export const useSimilarOffersQuery = ({
   offerId,
   shouldFetch,
   position,
@@ -104,7 +104,7 @@ export const useSimilarOffers = ({
   )
 
   return {
-    similarOffers: useAlgoliaSimilarOffers(apiRecoResponse?.results ?? [], true),
+    similarOffers: useAlgoliaSimilarOffersQuery(apiRecoResponse?.results ?? [], true),
     apiRecoParams: apiRecoResponse?.params,
   }
 }
diff --git a/src/features/offer/api/useAlgoliaSimilarOffers.native.test.ts b/src/queries/offer/useAlgoliaSimilarOffersQuery.native.test.ts
similarity index 83%
rename from src/features/offer/api/useAlgoliaSimilarOffers.native.test.ts
rename to src/queries/offer/useAlgoliaSimilarOffersQuery.native.test.ts
index 81469d61c2eb..84abc597a806 100644
--- a/src/features/offer/api/useAlgoliaSimilarOffers.native.test.ts
+++ b/src/queries/offer/useAlgoliaSimilarOffersQuery.native.test.ts
@@ -1,7 +1,7 @@
-import { useAlgoliaSimilarOffers } from 'features/offer/api/useAlgoliaSimilarOffers'
 import * as fetchOffersByIdsAPI from 'libs/algolia/fetchAlgolia/fetchOffersByIds'
 import * as filterOfferHitWithImageAPI from 'libs/algolia/fetchAlgolia/transformOfferHit'
 import { mockedAlgoliaResponse } from 'libs/algolia/fixtures/algoliaFixtures'
+import { useAlgoliaSimilarOffersQuery } from 'queries/offer/useAlgoliaSimilarOffersQuery'
 import * as getSimilarOrRecoOffersInOrder from 'shared/offer/getSimilarOrRecoOffersInOrder'
 import { reactQueryProviderHOC } from 'tests/reactQueryProviderHOC'
 import { act, renderHook, waitFor } from 'tests/utils'
@@ -15,7 +15,7 @@ const getSimilarOffersInOrderSpy = jest.spyOn(
 
 const ids = ['102280', '102272', '102249', '102310']
 
-describe('useAlgoliaSimilarOffers', () => {
+describe('useAlgoliaSimilarOffersQuery', () => {
   const mockFetchAlgoliaHits = jest.fn().mockResolvedValue(mockedAlgoliaResponse.hits)
   const fetchAlgoliaHitsSpy = jest
     .spyOn(fetchOffersByIdsAPI, 'fetchOffersByIds')
@@ -26,7 +26,7 @@ describe('useAlgoliaSimilarOffers', () => {
     .mockImplementation(jest.fn())
 
   it('should fetch algolia when ids are provided', async () => {
-    renderHook(() => useAlgoliaSimilarOffers(ids), {
+    renderHook(() => useAlgoliaSimilarOffersQuery(ids), {
       wrapper: ({ children }) => reactQueryProviderHOC(children),
     })
     await waitFor(() => {
@@ -35,7 +35,7 @@ describe('useAlgoliaSimilarOffers', () => {
   })
 
   it('should filter algolia hits', async () => {
-    renderHook(() => useAlgoliaSimilarOffers(ids), {
+    renderHook(() => useAlgoliaSimilarOffersQuery(ids), {
       wrapper: ({ children }) => reactQueryProviderHOC(children),
     })
     await waitFor(() => {
@@ -45,7 +45,7 @@ describe('useAlgoliaSimilarOffers', () => {
 
   it('should return undefined when algolia does not return any hit', async () => {
     jest.spyOn(fetchOffersByIdsAPI, 'fetchOffersByIds').mockResolvedValueOnce([])
-    const { result } = renderHook(() => useAlgoliaSimilarOffers(ids), {
+    const { result } = renderHook(() => useAlgoliaSimilarOffersQuery(ids), {
       wrapper: ({ children }) => reactQueryProviderHOC(children),
     })
     await waitFor(() => {
@@ -55,7 +55,7 @@ describe('useAlgoliaSimilarOffers', () => {
   })
 
   it('should return undefined when ids are not provided', async () => {
-    const { result } = renderHook(() => useAlgoliaSimilarOffers([]), {
+    const { result } = renderHook(() => useAlgoliaSimilarOffersQuery([]), {
       wrapper: ({ children }) => reactQueryProviderHOC(children),
     })
 
@@ -63,7 +63,7 @@ describe('useAlgoliaSimilarOffers', () => {
   })
 
   it('should call function to preserve ids offer order when shouldPreserveIdsOrder is true', async () => {
-    renderHook(() => useAlgoliaSimilarOffers(ids, true), {
+    renderHook(() => useAlgoliaSimilarOffersQuery(ids, true), {
       wrapper: ({ children }) => reactQueryProviderHOC(children),
     })
     await act(async () => {})
@@ -72,7 +72,7 @@ describe('useAlgoliaSimilarOffers', () => {
   })
 
   it('should not call function to preserve ids offer order when shouldPreserveIdsOrder is undefined', async () => {
-    renderHook(() => useAlgoliaSimilarOffers(ids), {
+    renderHook(() => useAlgoliaSimilarOffersQuery(ids), {
       wrapper: ({ children }) => reactQueryProviderHOC(children),
     })
     await act(async () => {})
@@ -81,7 +81,7 @@ describe('useAlgoliaSimilarOffers', () => {
   })
 
   it('should not call function to preserve ids offer order when shouldPreserveIdsOrder is false', async () => {
-    renderHook(() => useAlgoliaSimilarOffers(ids, false), {
+    renderHook(() => useAlgoliaSimilarOffersQuery(ids, false), {
       wrapper: ({ children }) => reactQueryProviderHOC(children),
     })
     await act(async () => {})
diff --git a/src/features/offer/api/useAlgoliaSimilarOffers.ts b/src/queries/offer/useAlgoliaSimilarOffersQuery.ts
similarity index 96%
rename from src/features/offer/api/useAlgoliaSimilarOffers.ts
rename to src/queries/offer/useAlgoliaSimilarOffersQuery.ts
index cfd075730992..9bd4d3ab5411 100644
--- a/src/features/offer/api/useAlgoliaSimilarOffers.ts
+++ b/src/queries/offer/useAlgoliaSimilarOffersQuery.ts
@@ -12,7 +12,7 @@ import { QueryKeys } from 'libs/queryKeys'
 import { getSimilarOrRecoOffersInOrder } from 'shared/offer/getSimilarOrRecoOffersInOrder'
 import { Offer } from 'shared/offer/types'
 
-export const useAlgoliaSimilarOffers = (
+export const useAlgoliaSimilarOffersQuery = (
   ids: string[],
   shouldPreserveIdsOrder?: boolean,
   queryKey?: UseQueryOptions['queryKey']


Reviews:
user: login: mmeissonnier-pass
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T08:45:01Z
user: login: mmeissonnier-pass
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T08:50:05Z
user: login: bebstein-pass
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T09:03:59Z
user: login: bebstein-pass
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T13:08:26Z
user: login: bebstein-pass
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T13:13:07Z
user: login: xlecunff-pass
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T13:23:18Z
user: login: bebstein-pass
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T13:26:30Z
user: login: bebstein-pass
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T13:28:30Z
user: login: xlecunff-pass
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T13:29:10Z

Review comments:
diff_hunk: @@ -7,7 +7,7 @@ export const useAlgoliaRecommendedOffers = (
   moduleId: string,
   shouldPreserveIdsOrder?: boolean
 ): Offer[] | undefined => {
-  return useAlgoliaSimilarOffers(ids, shouldPreserveIdsOrder, [
+  return useAlgoliaSimilarOffersQuery(ids, shouldPreserveIdsOrder, [
path: src/features/home/api/useAlgoliaRecommendedOffers.ts
user: login: mmeissonnier-pass
body: Etant donné que cette query est utilisée dans 2 features (home et offer), ne devrait-elle pas plutôt se trouver dans le dossier `src/queries` ?
created_at: 2025-05-12T08:49:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -41,7 +41,7 @@ useRoute.mockReturnValue({
   },
 })
 
-const spyUseArtistResults = jest.spyOn(useArtistResults, 'useArtistResults')
+const spyUseArtistResults = jest.spyOn(useArtistResults, 'useArtistResultsQuery')
path: src/features/artist/components/ArtistBody/ArtistBody.native.test.tsx
user: login: bebstein-pass
body: ```suggestion
const spyUseArtistResults = jest.spyOn(useArtistResultsAPI, 'useArtistResultsQuery')
```
created_at: 2025-05-12T08:59:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -41,7 +41,7 @@ useRoute.mockReturnValue({
   },
 })
 
-const spyUseArtistResults = jest.spyOn(useArtistResults, 'useArtistResults')
+const spyUseArtistResults = jest.spyOn(useArtistResults, 'useArtistResultsQuery')
path: src/features/artist/components/ArtistBody/ArtistBody.native.test.tsx
user: login: bebstein-pass
body: ce commentaire est aussi pour les autres fichiers
created_at: 2025-05-12T13:08:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,13 +1,13 @@
 import { onlineManager } from 'react-query'
 
 import { SearchGroupNameEnumv2, SimilarOffersResponse } from 'api/gen'
-import * as useAlgoliaSimilarOffers from 'features/offer/api/useAlgoliaSimilarOffers'
-import { getCategories, useSimilarOffers } from 'features/offer/api/useSimilarOffers'
+import { getCategories, useSimilarOffersQuery } from 'features/offer/queries/useSimilarOffersQuery'
 import { env } from 'libs/environment/fixtures'
 import { EmptyResponse } from 'libs/fetch'
 import { eventMonitoring } from 'libs/monitoring/services'
 import * as PackageJson from 'libs/packageJson'
 import { searchGroupsDataTest } from 'libs/subcategories/fixtures/subcategoriesResponse'
+import * as useAlgoliaSimilarOffers from 'queries/offer/useAlgoliaSimilarOffersQuery'
path: src/features/offer/queries/useSimilarOffersQuery.native.test.ts
user: login: bebstein-pass
body: ```suggestion
import * as useAlgoliaSimilarOffersAPI from 'queries/offer/useAlgoliaSimilarOffersQuery'
```
created_at: 2025-05-12T13:10:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -23,13 +23,13 @@ jest.mock('features/auth/context/AuthContext')
 jest.mock('libs/subcategories/useSubcategories')
 
 const algoliaSpy = jest
-  .spyOn(useAlgoliaSimilarOffers, 'useAlgoliaSimilarOffers')
+  .spyOn(useAlgoliaSimilarOffers, 'useAlgoliaSimilarOffersQuery')
   .mockImplementation()
path: src/features/offer/queries/useSimilarOffersQuery.native.test.ts
user: login: bebstein-pass
body: je trouve cette ligne très bizarre

je peux comprendre que dans certain cas, on veut spy des trucs

soit `.mockImplementation()` ne fait rien, dans ce cas, on peut l'enlever

soit ça mock avec un comportement par défaut (quelque chose comme `() => {}`) et dans ce cas, on teste un mock
created_at: 2025-05-12T13:12:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,13 +1,13 @@
 import { onlineManager } from 'react-query'
 
 import { SearchGroupNameEnumv2, SimilarOffersResponse } from 'api/gen'
-import * as useAlgoliaSimilarOffers from 'features/offer/api/useAlgoliaSimilarOffers'
-import { getCategories, useSimilarOffers } from 'features/offer/api/useSimilarOffers'
+import { getCategories, useSimilarOffersQuery } from 'features/offer/queries/useSimilarOffersQuery'
 import { env } from 'libs/environment/fixtures'
 import { EmptyResponse } from 'libs/fetch'
 import { eventMonitoring } from 'libs/monitoring/services'
 import * as PackageJson from 'libs/packageJson'
 import { searchGroupsDataTest } from 'libs/subcategories/fixtures/subcategoriesResponse'
+import * as useAlgoliaSimilarOffers from 'queries/offer/useAlgoliaSimilarOffersQuery'
path: src/features/offer/queries/useSimilarOffersQuery.native.test.ts
user: login: xlecunff-pass
body: On peut faire une règle ESlint pour renforcer ce comportement, car ça peut très rapidement nous échapper
created_at: 2025-05-12T13:23:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,13 +1,13 @@
 import { onlineManager } from 'react-query'
 
 import { SearchGroupNameEnumv2, SimilarOffersResponse } from 'api/gen'
-import * as useAlgoliaSimilarOffers from 'features/offer/api/useAlgoliaSimilarOffers'
-import { getCategories, useSimilarOffers } from 'features/offer/api/useSimilarOffers'
+import { getCategories, useSimilarOffersQuery } from 'features/offer/queries/useSimilarOffersQuery'
 import { env } from 'libs/environment/fixtures'
 import { EmptyResponse } from 'libs/fetch'
 import { eventMonitoring } from 'libs/monitoring/services'
 import * as PackageJson from 'libs/packageJson'
 import { searchGroupsDataTest } from 'libs/subcategories/fixtures/subcategoriesResponse'
+import * as useAlgoliaSimilarOffers from 'queries/offer/useAlgoliaSimilarOffersQuery'
path: src/features/offer/queries/useSimilarOffersQuery.native.test.ts
user: login: bebstein-pass
body: Bonne idée
created_at: 2025-05-12T13:26:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,13 +1,13 @@
 import { onlineManager } from 'react-query'
 
 import { SearchGroupNameEnumv2, SimilarOffersResponse } from 'api/gen'
-import * as useAlgoliaSimilarOffers from 'features/offer/api/useAlgoliaSimilarOffers'
-import { getCategories, useSimilarOffers } from 'features/offer/api/useSimilarOffers'
+import { getCategories, useSimilarOffersQuery } from 'features/offer/queries/useSimilarOffersQuery'
 import { env } from 'libs/environment/fixtures'
 import { EmptyResponse } from 'libs/fetch'
 import { eventMonitoring } from 'libs/monitoring/services'
 import * as PackageJson from 'libs/packageJson'
 import { searchGroupsDataTest } from 'libs/subcategories/fixtures/subcategoriesResponse'
+import * as useAlgoliaSimilarOffers from 'queries/offer/useAlgoliaSimilarOffersQuery'
path: src/features/offer/queries/useSimilarOffersQuery.native.test.ts
user: login: bebstein-pass
body: https://passculture.atlassian.net/browse/PC-36069
created_at: 2025-05-12T13:28:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -23,13 +23,13 @@ jest.mock('features/auth/context/AuthContext')
 jest.mock('libs/subcategories/useSubcategories')
 
 const algoliaSpy = jest
-  .spyOn(useAlgoliaSimilarOffers, 'useAlgoliaSimilarOffers')
+  .spyOn(useAlgoliaSimilarOffers, 'useAlgoliaSimilarOffersQuery')
   .mockImplementation()
path: src/features/offer/queries/useSimilarOffersQuery.native.test.ts
user: login: xlecunff-pass
body: Bien vu! Les tests passent sans 🎉
created_at: 2025-05-12T13:29:10Z
author_association: CONTRIBUTOR

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-05-12T13:36:50Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=pass-culture_pass-culture-app-native-proxy&pullRequest=8106) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=pass-culture_pass-culture-app-native-proxy&pullRequest=8106&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=pass-culture_pass-culture-app-native-proxy&pullRequest=8106&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=pass-culture_pass-culture-app-native-proxy&pullRequest=8106&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=pass-culture_pass-culture-app-native-proxy&pullRequest=8106&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=pass-culture_pass-culture-app-native-proxy&pullRequest=8106&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=pass-culture_pass-culture-app-native-proxy&pullRequest=8106)


author_association: NONE
user: login: sonarqubecloud[bot]
created_at: 2025-05-12T13:43:23Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=pass-culture_pass-culture-app-native&pullRequest=8106) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=pass-culture_pass-culture-app-native&pullRequest=8106&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=pass-culture_pass-culture-app-native&pullRequest=8106&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=pass-culture_pass-culture-app-native&pullRequest=8106&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [92.8% Coverage on New Code](https://sonarcloud.io/component_measures?id=pass-culture_pass-culture-app-native&pullRequest=8106&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=pass-culture_pass-culture-app-native&pullRequest=8106&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=pass-culture_pass-culture-app-native&pullRequest=8106)


author_association: NONE