diff --git a/packages/api/mocks/RedirectQuery.ts b/packages/api/mocks/RedirectQuery.ts new file mode 100644 index 0000000000..df18d8a860 --- /dev/null +++ b/packages/api/mocks/RedirectQuery.ts @@ -0,0 +1,40 @@ +export const RedirectQueryTermTech = `query RedirectSearch { + redirect(term: "tech") { + url + } + } + ` + +export const redirectTermTechFetch = { + info: 'https://storeframework.vtexcommercestable.com.br/api/io/_v/api/intelligent-search/product_search/trade-policy/1?page=2&count=1&query=tech&sort=&fuzzy=auto&locale=en-US&hideUnavailableItems=false', + init: undefined, + result: { + products: [], + recordsFiltered: 0, + fuzzy: 'auto', + operator: 'and', + redirect: '/technology', + translated: false, + pagination: { + count: 1, + current: { + index: 0, + }, + before: [], + after: [], + perPage: 0, + next: { + index: 0, + }, + previous: { + index: 0, + }, + first: { + index: 0, + }, + last: { + index: 0, + }, + }, + }, +} diff --git a/packages/api/src/__generated__/schema.ts b/packages/api/src/__generated__/schema.ts index 58217a7527..fd514ce5de 100644 --- a/packages/api/src/__generated__/schema.ts +++ b/packages/api/src/__generated__/schema.ts @@ -393,6 +393,8 @@ export type Query = { collection: StoreCollection; /** Returns the details of a product based on the specified locator. */ product: StoreProduct; + /** Returns if there's a redirect for a search. */ + redirect?: Maybe; /** Returns the result of a product, facet, or suggestion search. */ search: StoreSearchResult; /** Returns information about shipping simulation. */ @@ -422,6 +424,12 @@ export type QueryProductArgs = { }; +export type QueryRedirectArgs = { + selectedFacets?: Maybe>; + term?: Maybe; +}; + + export type QuerySearchArgs = { after?: Maybe; first: Scalars['Int']; @@ -896,6 +904,16 @@ export type StorePropertyValue = { valueReference: Scalars['String']; }; +/** + * Redirect informations, including url returned by the query. + * https://schema.org/Thing + */ +export type StoreRedirect = { + __typename?: 'StoreRedirect'; + /** URL to redirect */ + url?: Maybe; +}; + /** Information of a given review. */ export type StoreReview = { __typename?: 'StoreReview'; diff --git a/packages/api/src/platforms/vtex/resolvers/query.ts b/packages/api/src/platforms/vtex/resolvers/query.ts index 7828116dd2..a2caf44a6a 100644 --- a/packages/api/src/platforms/vtex/resolvers/query.ts +++ b/packages/api/src/platforms/vtex/resolvers/query.ts @@ -19,6 +19,7 @@ import type { QueryProductArgs, QuerySearchArgs, QueryShippingArgs, + QueryRedirectArgs } from "../../../__generated__/schema" import type { CategoryTree } from "../clients/commerce/types/CategoryTree" import type { Context } from "../index" @@ -142,9 +143,8 @@ export const Query = { productId: crossSelling.value, }) - query = `product:${ - products.map((x) => x.productId).slice(0, first).join(";") - }` + query = `product:${products.map((x) => x.productId).slice(0, first).join(";") + }` } const after = maybeAfter ? Number(maybeAfter) : 0 @@ -273,4 +273,26 @@ export const Query = { address, } }, + redirect: async ( + _: unknown, + { term, selectedFacets }: QueryRedirectArgs, + ctx: Context + ) => { + // Currently the search redirection can be done through a search term or filter (facet) so we limit the redirect query to always have one of these values otherwise we do not execute it. + // https://help.vtex.com/en/tracks/vtex-intelligent-search--19wrbB7nEQcmwzDPl1l4Cb/4Gd2wLQFbCwTsh8RUDwSoL?&utm_source=autocomplete + if (!term && (!selectedFacets || !selectedFacets.length)) { + return null + } + + const { redirect } = await ctx.clients.search.products({ + page: 1, + count: 1, + query: term ?? undefined, + selectedFacets: selectedFacets?.flatMap(transformSelectedFacet) ?? [], + }) + + return { + url: redirect + } + }, } diff --git a/packages/api/src/typeDefs/query.graphql b/packages/api/src/typeDefs/query.graphql index 82199df676..ed026c2b24 100644 --- a/packages/api/src/typeDefs/query.graphql +++ b/packages/api/src/typeDefs/query.graphql @@ -282,4 +282,30 @@ type Query { country: String! ): ShippingData @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600) + + """ + Returns if there's a redirect for a search. + """ + redirect( + """ + Search term. + """ + term: String + """ + Array of selected search facets. + """ + selectedFacets: [IStoreSelectedFacet!] + ): StoreRedirect + @cacheControl(scope: "public", sMaxAge: 120, staleWhileRevalidate: 3600) +} + +""" +Redirect informations, including url returned by the query. +https://schema.org/Thing +""" +type StoreRedirect { + """ + URL to redirect + """ + url: String } diff --git a/packages/api/test/__snapshots__/queries.test.ts.snap b/packages/api/test/__snapshots__/queries.test.ts.snap index 9e6a84a3ef..490e38c701 100644 --- a/packages/api/test/__snapshots__/queries.test.ts.snap +++ b/packages/api/test/__snapshots__/queries.test.ts.snap @@ -1167,3 +1167,13 @@ Object { }, } `; + +exports[`\`redirect\` query 1`] = ` +Object { + "data": Object { + "redirect": Object { + "url": "/technology", + }, + }, +} +`; \ No newline at end of file diff --git a/packages/api/test/queries.test.ts b/packages/api/test/queries.test.ts index 30ac9228da..7103983200 100644 --- a/packages/api/test/queries.test.ts +++ b/packages/api/test/queries.test.ts @@ -34,6 +34,10 @@ import { addressFetch, ShippingSimulationQueryResult, } from '../mocks/ShippingQuery' +import { + RedirectQueryTermTech, + redirectTermTechFetch, +} from '../mocks/RedirectQuery' const apiOptions = { platform: 'vtex', @@ -236,3 +240,24 @@ test('`shipping` query', async () => { expect(response).toMatchSnapshot() }) + +test('`redirect` query', async () => { + const fetchAPICalls = [redirectTermTechFetch] + + mockedFetch.mockImplementation((info, init) => + pickFetchAPICallResult(info, init, fetchAPICalls) + ) + + const response = await run(RedirectQueryTermTech) + + expect(mockedFetch).toHaveBeenCalledTimes(1) + + fetchAPICalls.forEach((fetchAPICall) => { + expect(mockedFetch).toHaveBeenCalledWith( + fetchAPICall.info, + fetchAPICall.init + ) + }) + + expect(response).toMatchSnapshot() +}) diff --git a/packages/api/test/schema.test.ts b/packages/api/test/schema.test.ts index 113f4f9c24..08ca69facb 100644 --- a/packages/api/test/schema.test.ts +++ b/packages/api/test/schema.test.ts @@ -65,6 +65,7 @@ const QUERIES = [ 'allProducts', 'allCollections', 'shipping', + 'redirect', ] const MUTATIONS = ['validateCart', 'validateSession', 'subscribeToNewsletter']