diff --git a/README.md b/README.md index c648c27ff..4ab6d02de 100644 --- a/README.md +++ b/README.md @@ -418,6 +418,14 @@ client.multiSearch(queries?: MultiSearchParams, config?: Partial): Prom `multiSearch` uses the `POST` method when performing its request to Meilisearch. +### Search For Facet Values + +#### [Search for facet values](#) + +```ts +client.index('myIndex').searchForFacetValues(params: SearchForFacetValuesParams, config?: Partial): Promise +``` + ### Documents #### [Add or replace multiple documents](https://www.meilisearch.com/docs/reference/api/documents#add-or-replace-documents) diff --git a/src/indexes.ts b/src/indexes.ts index a5145253e..ea732da5b 100644 --- a/src/indexes.ts +++ b/src/indexes.ts @@ -45,6 +45,8 @@ import { ContentType, DocumentsIds, DocumentsDeletionQuery, + SearchForFacetValuesParams, + SearchForFacetValuesResponse, } from './types' import { removeUndefinedFromObject } from './utils' import { HttpRequests } from './http-requests' @@ -137,6 +139,8 @@ class Index = Record> { attributesToRetrieve: options?.attributesToRetrieve?.join(','), attributesToCrop: options?.attributesToCrop?.join(','), attributesToHighlight: options?.attributesToHighlight?.join(','), + vector: options?.vector?.join(','), + attributesToSearchOn: options?.attributesToSearchOn?.join(','), } return await this.httpRequest.get>( @@ -146,6 +150,27 @@ class Index = Record> { ) } + /** + * Search for facet values + * + * @param params - Parameters used to search on the facets + * @param config - Additional request configuration options + * @returns Promise containing the search response + */ + async searchForFacetValues( + params: SearchForFacetValuesParams, + config?: Partial + ): Promise { + const url = `indexes/${this.uid}/facet-search` + + return await this.httpRequest.post( + url, + removeUndefinedFromObject(params), + undefined, + config + ) + } + /// /// INDEX /// diff --git a/src/types/types.ts b/src/types/types.ts index 15842c68b..99af63fa4 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -78,6 +78,22 @@ export type Crop = { cropMarker?: string } +// `facetName` becomes mandatory when using `searchForFacetValues` +export type SearchForFacetValuesParams = Omit & { + facetName: string +} + +export type FacetHit = { + value: string + count: number +} + +export type SearchForFacetValuesResponse = { + facetHits: FacetHit[] + facetQuery: string | null + processingTimeMs: number +} + export type SearchParams = Query & Pagination & Highlight & @@ -90,6 +106,12 @@ export type SearchParams = Query & matchingStrategy?: MatchingStrategies hitsPerPage?: number page?: number + facetName?: string + facetQuery?: string + vector?: number[] | null + showRankingScore?: boolean + showRankingScoreDetails?: boolean + attributesToSearchOn?: string[] | null } // Search parameters for searches made with the GET method @@ -105,6 +127,8 @@ export type SearchRequestGET = Pagination & attributesToHighlight?: string attributesToCrop?: string showMatchesPosition?: boolean + vector?: string | null + attributesToSearchOn?: string | null } export type MultiSearchQuery = SearchParams & { indexUid: string } @@ -126,6 +150,39 @@ export type MatchesPosition = Partial< export type Hit> = T & { _formatted?: Partial _matchesPosition?: MatchesPosition + _rankingScore?: number + _rankingScoreDetails?: RakingScoreDetails +} + +export type RakingScoreDetails = { + words?: { + order: number + matchingWords: number + maxMatchingWords: number + score: number + } + typo?: { + order: number + typoCount: number + maxTypoCount: number + score: number + } + proximity?: { + order: number + score: number + } + attribute?: { + order: number + attributes_ranking_order: number + attributes_query_word_order: number + score: number + } + exactness?: { + order: number + matchType: string + score: number + } + [key: string]: Record | undefined } export type Hits> = Array> @@ -139,9 +196,10 @@ export type SearchResponse< > = { hits: Hits processingTimeMs: number - facetDistribution?: FacetDistribution query: string + facetDistribution?: FacetDistribution facetStats?: FacetStats + vector?: number[] } & (undefined extends S ? Partial : true extends IsFinitePagination> @@ -255,9 +313,13 @@ export type TypoTolerance = { } } | null +export type FacetOrder = 'alpha' | 'count' + export type Faceting = { maxValuesPerFacet?: number | null + sortFacetValuesBy?: Record | null } + export type PaginationSettings = { maxTotalHits?: number | null } @@ -399,6 +461,7 @@ type CursorResults = { limit: number from: number next: number + total: number } export type TasksResults = CursorResults @@ -556,12 +619,15 @@ export const enum ErrorStatusCode { /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_offset */ INVALID_DOCUMENT_OFFSET = 'invalid_document_offset', - /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_offset */ + /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_filter */ INVALID_DOCUMENT_FILTER = 'invalid_document_filter', - /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_offset */ + /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_document_filter */ MISSING_DOCUMENT_FILTER = 'missing_document_filter', + /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_document_vectors_field */ + INVALID_DOCUMENT_VECTORS_FIELD = 'invalid_document_vectors_field', + /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#payload_too_large */ PAYLOAD_TOO_LARGE = 'payload_too_large', @@ -637,6 +703,12 @@ export const enum ErrorStatusCode { /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_matching_strategy */ INVALID_SEARCH_MATCHING_STRATEGY = 'invalid_search_matching_strategy', + /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_vector */ + INVALID_SEARCH_VECTOR = 'invalid_search_vector', + + /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_attributes_to_search_on */ + INVALID_SEARCH_ATTRIBUTES_TO_SEARCH_ON = 'invalid_search_attributes_to_search_on', + /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#bad_request */ BAD_REQUEST = 'bad_request', @@ -816,6 +888,15 @@ export const enum ErrorStatusCode { /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_api_key_offset */ INVALID_API_KEY_OFFSET = 'invalid_api_key_offset', + + /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_facet_search_facet_name */ + INVALID_FACET_SEARCH_FACET_NAME = 'invalid_facet_search_facet_name', + + /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#missing_facet_search_facet_name */ + MISSING_FACET_SEARCH_FACET_NAME = 'missing_facet_search_facet_name', + + /** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_facet_search_facet_query */ + INVALID_FACET_SEARCH_FACET_QUERY = 'invalid_facet_search_facet_query', } export type TokenIndexRules = { diff --git a/tests/__snapshots__/facet_search.test.ts.snap b/tests/__snapshots__/facet_search.test.ts.snap new file mode 100644 index 000000000..17c3d1bf0 --- /dev/null +++ b/tests/__snapshots__/facet_search.test.ts.snap @@ -0,0 +1,205 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test on POST search Admin key: basic facet value search 1`] = ` +Object { + "facetHits": Array [ + Object { + "count": 1, + "value": "action", + }, + Object { + "count": 2, + "value": "adventure", + }, + ], + "facetQuery": "a", + "processingTimeMs": 0, +} +`; + +exports[`Test on POST search Admin key: facet value search with filter 1`] = ` +Object { + "facetHits": Array [ + Object { + "count": 1, + "value": "action", + }, + ], + "facetQuery": "a", + "processingTimeMs": 0, +} +`; + +exports[`Test on POST search Admin key: facet value search with no facet query 1`] = ` +Object { + "facetHits": Array [ + Object { + "count": 1, + "value": "action", + }, + Object { + "count": 2, + "value": "adventure", + }, + Object { + "count": 1, + "value": "comedy", + }, + Object { + "count": 2, + "value": "romance", + }, + ], + "facetQuery": null, + "processingTimeMs": 0, +} +`; + +exports[`Test on POST search Admin key: facet value search with search query 1`] = ` +Object { + "facetHits": Array [ + Object { + "count": 1, + "value": "adventure", + }, + ], + "facetQuery": "a", + "processingTimeMs": 0, +} +`; + +exports[`Test on POST search Master key: basic facet value search 1`] = ` +Object { + "facetHits": Array [ + Object { + "count": 1, + "value": "action", + }, + Object { + "count": 2, + "value": "adventure", + }, + ], + "facetQuery": "a", + "processingTimeMs": 0, +} +`; + +exports[`Test on POST search Master key: facet value search with filter 1`] = ` +Object { + "facetHits": Array [ + Object { + "count": 1, + "value": "action", + }, + ], + "facetQuery": "a", + "processingTimeMs": 0, +} +`; + +exports[`Test on POST search Master key: facet value search with no facet query 1`] = ` +Object { + "facetHits": Array [ + Object { + "count": 1, + "value": "action", + }, + Object { + "count": 2, + "value": "adventure", + }, + Object { + "count": 1, + "value": "comedy", + }, + Object { + "count": 2, + "value": "romance", + }, + ], + "facetQuery": null, + "processingTimeMs": 0, +} +`; + +exports[`Test on POST search Master key: facet value search with search query 1`] = ` +Object { + "facetHits": Array [ + Object { + "count": 1, + "value": "adventure", + }, + ], + "facetQuery": "a", + "processingTimeMs": 0, +} +`; + +exports[`Test on POST search Search key: basic facet value search 1`] = ` +Object { + "facetHits": Array [ + Object { + "count": 1, + "value": "action", + }, + Object { + "count": 2, + "value": "adventure", + }, + ], + "facetQuery": "a", + "processingTimeMs": 0, +} +`; + +exports[`Test on POST search Search key: facet value search with filter 1`] = ` +Object { + "facetHits": Array [ + Object { + "count": 1, + "value": "action", + }, + ], + "facetQuery": "a", + "processingTimeMs": 0, +} +`; + +exports[`Test on POST search Search key: facet value search with no facet query 1`] = ` +Object { + "facetHits": Array [ + Object { + "count": 1, + "value": "action", + }, + Object { + "count": 2, + "value": "adventure", + }, + Object { + "count": 1, + "value": "comedy", + }, + Object { + "count": 2, + "value": "romance", + }, + ], + "facetQuery": null, + "processingTimeMs": 0, +} +`; + +exports[`Test on POST search Search key: facet value search with search query 1`] = ` +Object { + "facetHits": Array [ + Object { + "count": 1, + "value": "adventure", + }, + ], + "facetQuery": "a", + "processingTimeMs": 0, +} +`; diff --git a/tests/__snapshots__/faceting.test.ts.snap b/tests/__snapshots__/faceting.test.ts.snap new file mode 100644 index 000000000..6c0e9262b --- /dev/null +++ b/tests/__snapshots__/faceting.test.ts.snap @@ -0,0 +1,75 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test on faceting Admin key: Get default faceting object 1`] = ` +Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, +} +`; + +exports[`Test on faceting Admin key: Reset faceting 1`] = ` +Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, +} +`; + +exports[`Test on faceting Admin key: Update faceting at null 1`] = ` +Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, +} +`; + +exports[`Test on faceting Admin key: Update faceting settings 1`] = ` +Object { + "maxValuesPerFacet": 12, + "sortFacetValuesBy": Object { + "*": "alpha", + "test": "count", + }, +} +`; + +exports[`Test on faceting Master key: Get default faceting object 1`] = ` +Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, +} +`; + +exports[`Test on faceting Master key: Reset faceting 1`] = ` +Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, +} +`; + +exports[`Test on faceting Master key: Update faceting at null 1`] = ` +Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, +} +`; + +exports[`Test on faceting Master key: Update faceting settings 1`] = ` +Object { + "maxValuesPerFacet": 12, + "sortFacetValuesBy": Object { + "*": "alpha", + "test": "count", + }, +} +`; diff --git a/tests/__snapshots__/get_search.test.ts.snap b/tests/__snapshots__/get_search.test.ts.snap new file mode 100644 index 000000000..1017d2302 --- /dev/null +++ b/tests/__snapshots__/get_search.test.ts.snap @@ -0,0 +1,73 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test on GET search Admin key: search on attributesToSearchOn set to null 1`] = ` +Object { + "estimatedTotalHits": 2, + "hits": Array [ + Object { + "comment": "A french book about a prince that walks on little cute planets", + "genre": "adventure", + "id": 456, + "title": "Le Petit Prince", + }, + Object { + "comment": "The best book", + "genre": "fantasy", + "id": 4, + "title": "Harry Potter and the Half-Blood Prince", + }, + ], + "limit": 20, + "offset": 0, + "processingTimeMs": 0, + "query": "prince", +} +`; + +exports[`Test on GET search Master key: search on attributesToSearchOn set to null 1`] = ` +Object { + "estimatedTotalHits": 2, + "hits": Array [ + Object { + "comment": "A french book about a prince that walks on little cute planets", + "genre": "adventure", + "id": 456, + "title": "Le Petit Prince", + }, + Object { + "comment": "The best book", + "genre": "fantasy", + "id": 4, + "title": "Harry Potter and the Half-Blood Prince", + }, + ], + "limit": 20, + "offset": 0, + "processingTimeMs": 0, + "query": "prince", +} +`; + +exports[`Test on GET search Search key: search on attributesToSearchOn set to null 1`] = ` +Object { + "estimatedTotalHits": 2, + "hits": Array [ + Object { + "comment": "A french book about a prince that walks on little cute planets", + "genre": "adventure", + "id": 456, + "title": "Le Petit Prince", + }, + Object { + "comment": "The best book", + "genre": "fantasy", + "id": 4, + "title": "Harry Potter and the Half-Blood Prince", + }, + ], + "limit": 20, + "offset": 0, + "processingTimeMs": 0, + "query": "prince", +} +`; diff --git a/tests/__snapshots__/search.test.ts.snap b/tests/__snapshots__/search.test.ts.snap new file mode 100644 index 000000000..340d04d11 --- /dev/null +++ b/tests/__snapshots__/search.test.ts.snap @@ -0,0 +1,79 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test on POST search Admin key: search on attributesToSearchOn set to null 1`] = ` +Object { + "estimatedTotalHits": 2, + "hits": Array [ + Object { + "comment": "A french book about a prince that walks on little cute planets", + "genre": "adventure", + "id": 456, + "isNull": null, + "isTrue": true, + "title": "Le Petit Prince", + }, + Object { + "comment": "The best book", + "genre": "fantasy", + "id": 4, + "title": "Harry Potter and the Half-Blood Prince", + }, + ], + "limit": 20, + "offset": 0, + "processingTimeMs": 0, + "query": "prince", +} +`; + +exports[`Test on POST search Master key: search on attributesToSearchOn set to null 1`] = ` +Object { + "estimatedTotalHits": 2, + "hits": Array [ + Object { + "comment": "A french book about a prince that walks on little cute planets", + "genre": "adventure", + "id": 456, + "isNull": null, + "isTrue": true, + "title": "Le Petit Prince", + }, + Object { + "comment": "The best book", + "genre": "fantasy", + "id": 4, + "title": "Harry Potter and the Half-Blood Prince", + }, + ], + "limit": 20, + "offset": 0, + "processingTimeMs": 0, + "query": "prince", +} +`; + +exports[`Test on POST search Search key: search on attributesToSearchOn set to null 1`] = ` +Object { + "estimatedTotalHits": 2, + "hits": Array [ + Object { + "comment": "A french book about a prince that walks on little cute planets", + "genre": "adventure", + "id": 456, + "isNull": null, + "isTrue": true, + "title": "Le Petit Prince", + }, + Object { + "comment": "The best book", + "genre": "fantasy", + "id": 4, + "title": "Harry Potter and the Half-Blood Prince", + }, + ], + "limit": 20, + "offset": 0, + "processingTimeMs": 0, + "query": "prince", +} +`; diff --git a/tests/__snapshots__/settings.test.ts.snap b/tests/__snapshots__/settings.test.ts.snap new file mode 100644 index 000000000..fdc4721df --- /dev/null +++ b/tests/__snapshots__/settings.test.ts.snap @@ -0,0 +1,773 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test on settings Admin key: Get default settings of an index 1`] = ` +Object { + "displayedAttributes": Array [ + "*", + ], + "distinctAttribute": null, + "faceting": Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "words", + "typo", + "proximity", + "attribute", + "sort", + "exactness", + ], + "searchableAttributes": Array [ + "*", + ], + "sortableAttributes": Array [], + "stopWords": Array [], + "synonyms": Object {}, + "typoTolerance": Object { + "disableOnAttributes": Array [], + "disableOnWords": Array [], + "enabled": true, + "minWordSizeForTypos": Object { + "oneTypo": 5, + "twoTypos": 9, + }, + }, +} +`; + +exports[`Test on settings Admin key: Get default settings of empty index with primary key 1`] = ` +Object { + "displayedAttributes": Array [ + "*", + ], + "distinctAttribute": null, + "faceting": Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "words", + "typo", + "proximity", + "attribute", + "sort", + "exactness", + ], + "searchableAttributes": Array [ + "*", + ], + "sortableAttributes": Array [], + "stopWords": Array [], + "synonyms": Object {}, + "typoTolerance": Object { + "disableOnAttributes": Array [], + "disableOnWords": Array [], + "enabled": true, + "minWordSizeForTypos": Object { + "oneTypo": 5, + "twoTypos": 9, + }, + }, +} +`; + +exports[`Test on settings Admin key: Reset settings 1`] = ` +Object { + "displayedAttributes": Array [ + "*", + ], + "distinctAttribute": null, + "faceting": Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "words", + "typo", + "proximity", + "attribute", + "sort", + "exactness", + ], + "searchableAttributes": Array [ + "*", + ], + "sortableAttributes": Array [], + "stopWords": Array [], + "synonyms": Object {}, + "typoTolerance": Object { + "disableOnAttributes": Array [], + "disableOnWords": Array [], + "enabled": true, + "minWordSizeForTypos": Object { + "oneTypo": 5, + "twoTypos": 9, + }, + }, +} +`; + +exports[`Test on settings Admin key: Reset settings of empty index 1`] = ` +Object { + "displayedAttributes": Array [ + "*", + ], + "distinctAttribute": null, + "faceting": Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "words", + "typo", + "proximity", + "attribute", + "sort", + "exactness", + ], + "searchableAttributes": Array [ + "*", + ], + "sortableAttributes": Array [], + "stopWords": Array [], + "synonyms": Object {}, + "typoTolerance": Object { + "disableOnAttributes": Array [], + "disableOnWords": Array [], + "enabled": true, + "minWordSizeForTypos": Object { + "oneTypo": 5, + "twoTypos": 9, + }, + }, +} +`; + +exports[`Test on settings Admin key: Update searchableAttributes settings on empty index 1`] = ` +Object { + "displayedAttributes": Array [ + "*", + ], + "distinctAttribute": null, + "faceting": Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "words", + "typo", + "proximity", + "attribute", + "sort", + "exactness", + ], + "searchableAttributes": Array [ + "title", + ], + "sortableAttributes": Array [], + "stopWords": Array [], + "synonyms": Object {}, + "typoTolerance": Object { + "disableOnAttributes": Array [], + "disableOnWords": Array [], + "enabled": true, + "minWordSizeForTypos": Object { + "oneTypo": 5, + "twoTypos": 9, + }, + }, +} +`; + +exports[`Test on settings Admin key: Update searchableAttributes settings on empty index with a primary key 1`] = ` +Object { + "displayedAttributes": Array [ + "*", + ], + "distinctAttribute": null, + "faceting": Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "words", + "typo", + "proximity", + "attribute", + "sort", + "exactness", + ], + "searchableAttributes": Array [ + "title", + ], + "sortableAttributes": Array [], + "stopWords": Array [], + "synonyms": Object {}, + "typoTolerance": Object { + "disableOnAttributes": Array [], + "disableOnWords": Array [], + "enabled": true, + "minWordSizeForTypos": Object { + "oneTypo": 5, + "twoTypos": 9, + }, + }, +} +`; + +exports[`Test on settings Admin key: Update settings 1`] = ` +Object { + "displayedAttributes": Array [ + "title", + ], + "distinctAttribute": "title", + "faceting": Object { + "maxValuesPerFacet": 50, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [ + "title", + ], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "id:asc", + "typo", + ], + "searchableAttributes": Array [ + "title", + ], + "sortableAttributes": Array [ + "title", + ], + "stopWords": Array [ + "the", + ], + "synonyms": Object { + "harry": Array [ + "potter", + ], + }, + "typoTolerance": Object { + "disableOnAttributes": Array [ + "comment", + ], + "disableOnWords": Array [ + "prince", + ], + "enabled": false, + "minWordSizeForTypos": Object { + "oneTypo": 1, + "twoTypos": 100, + }, + }, +} +`; + +exports[`Test on settings Admin key: Update settings on empty index with primary key 1`] = ` +Object { + "displayedAttributes": Array [ + "*", + ], + "distinctAttribute": "title", + "faceting": Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "title:asc", + "typo", + ], + "searchableAttributes": Array [ + "*", + ], + "sortableAttributes": Array [], + "stopWords": Array [ + "the", + ], + "synonyms": Object {}, + "typoTolerance": Object { + "disableOnAttributes": Array [], + "disableOnWords": Array [], + "enabled": true, + "minWordSizeForTypos": Object { + "oneTypo": 5, + "twoTypos": 9, + }, + }, +} +`; + +exports[`Test on settings Admin key: Update settings with all null values 1`] = ` +Object { + "displayedAttributes": Array [ + "*", + ], + "distinctAttribute": null, + "faceting": Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "words", + "typo", + "proximity", + "attribute", + "sort", + "exactness", + ], + "searchableAttributes": Array [ + "*", + ], + "sortableAttributes": Array [], + "stopWords": Array [], + "synonyms": Object {}, + "typoTolerance": Object { + "disableOnAttributes": Array [], + "disableOnWords": Array [], + "enabled": true, + "minWordSizeForTypos": Object { + "oneTypo": 5, + "twoTypos": 9, + }, + }, +} +`; + +exports[`Test on settings Master key: Get default settings of an index 1`] = ` +Object { + "displayedAttributes": Array [ + "*", + ], + "distinctAttribute": null, + "faceting": Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "words", + "typo", + "proximity", + "attribute", + "sort", + "exactness", + ], + "searchableAttributes": Array [ + "*", + ], + "sortableAttributes": Array [], + "stopWords": Array [], + "synonyms": Object {}, + "typoTolerance": Object { + "disableOnAttributes": Array [], + "disableOnWords": Array [], + "enabled": true, + "minWordSizeForTypos": Object { + "oneTypo": 5, + "twoTypos": 9, + }, + }, +} +`; + +exports[`Test on settings Master key: Get default settings of empty index with primary key 1`] = ` +Object { + "displayedAttributes": Array [ + "*", + ], + "distinctAttribute": null, + "faceting": Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "words", + "typo", + "proximity", + "attribute", + "sort", + "exactness", + ], + "searchableAttributes": Array [ + "*", + ], + "sortableAttributes": Array [], + "stopWords": Array [], + "synonyms": Object {}, + "typoTolerance": Object { + "disableOnAttributes": Array [], + "disableOnWords": Array [], + "enabled": true, + "minWordSizeForTypos": Object { + "oneTypo": 5, + "twoTypos": 9, + }, + }, +} +`; + +exports[`Test on settings Master key: Reset settings 1`] = ` +Object { + "displayedAttributes": Array [ + "*", + ], + "distinctAttribute": null, + "faceting": Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "words", + "typo", + "proximity", + "attribute", + "sort", + "exactness", + ], + "searchableAttributes": Array [ + "*", + ], + "sortableAttributes": Array [], + "stopWords": Array [], + "synonyms": Object {}, + "typoTolerance": Object { + "disableOnAttributes": Array [], + "disableOnWords": Array [], + "enabled": true, + "minWordSizeForTypos": Object { + "oneTypo": 5, + "twoTypos": 9, + }, + }, +} +`; + +exports[`Test on settings Master key: Reset settings of empty index 1`] = ` +Object { + "displayedAttributes": Array [ + "*", + ], + "distinctAttribute": null, + "faceting": Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "words", + "typo", + "proximity", + "attribute", + "sort", + "exactness", + ], + "searchableAttributes": Array [ + "*", + ], + "sortableAttributes": Array [], + "stopWords": Array [], + "synonyms": Object {}, + "typoTolerance": Object { + "disableOnAttributes": Array [], + "disableOnWords": Array [], + "enabled": true, + "minWordSizeForTypos": Object { + "oneTypo": 5, + "twoTypos": 9, + }, + }, +} +`; + +exports[`Test on settings Master key: Update searchableAttributes settings on empty index 1`] = ` +Object { + "displayedAttributes": Array [ + "*", + ], + "distinctAttribute": null, + "faceting": Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "words", + "typo", + "proximity", + "attribute", + "sort", + "exactness", + ], + "searchableAttributes": Array [ + "title", + ], + "sortableAttributes": Array [], + "stopWords": Array [], + "synonyms": Object {}, + "typoTolerance": Object { + "disableOnAttributes": Array [], + "disableOnWords": Array [], + "enabled": true, + "minWordSizeForTypos": Object { + "oneTypo": 5, + "twoTypos": 9, + }, + }, +} +`; + +exports[`Test on settings Master key: Update searchableAttributes settings on empty index with a primary key 1`] = ` +Object { + "displayedAttributes": Array [ + "*", + ], + "distinctAttribute": null, + "faceting": Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "words", + "typo", + "proximity", + "attribute", + "sort", + "exactness", + ], + "searchableAttributes": Array [ + "title", + ], + "sortableAttributes": Array [], + "stopWords": Array [], + "synonyms": Object {}, + "typoTolerance": Object { + "disableOnAttributes": Array [], + "disableOnWords": Array [], + "enabled": true, + "minWordSizeForTypos": Object { + "oneTypo": 5, + "twoTypos": 9, + }, + }, +} +`; + +exports[`Test on settings Master key: Update settings 1`] = ` +Object { + "displayedAttributes": Array [ + "title", + ], + "distinctAttribute": "title", + "faceting": Object { + "maxValuesPerFacet": 50, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [ + "title", + ], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "id:asc", + "typo", + ], + "searchableAttributes": Array [ + "title", + ], + "sortableAttributes": Array [ + "title", + ], + "stopWords": Array [ + "the", + ], + "synonyms": Object { + "harry": Array [ + "potter", + ], + }, + "typoTolerance": Object { + "disableOnAttributes": Array [ + "comment", + ], + "disableOnWords": Array [ + "prince", + ], + "enabled": false, + "minWordSizeForTypos": Object { + "oneTypo": 1, + "twoTypos": 100, + }, + }, +} +`; + +exports[`Test on settings Master key: Update settings on empty index with primary key 1`] = ` +Object { + "displayedAttributes": Array [ + "*", + ], + "distinctAttribute": "title", + "faceting": Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "title:asc", + "typo", + ], + "searchableAttributes": Array [ + "*", + ], + "sortableAttributes": Array [], + "stopWords": Array [ + "the", + ], + "synonyms": Object {}, + "typoTolerance": Object { + "disableOnAttributes": Array [], + "disableOnWords": Array [], + "enabled": true, + "minWordSizeForTypos": Object { + "oneTypo": 5, + "twoTypos": 9, + }, + }, +} +`; + +exports[`Test on settings Master key: Update settings with all null values 1`] = ` +Object { + "displayedAttributes": Array [ + "*", + ], + "distinctAttribute": null, + "faceting": Object { + "maxValuesPerFacet": 100, + "sortFacetValuesBy": Object { + "*": "alpha", + }, + }, + "filterableAttributes": Array [], + "pagination": Object { + "maxTotalHits": 1000, + }, + "rankingRules": Array [ + "words", + "typo", + "proximity", + "attribute", + "sort", + "exactness", + ], + "searchableAttributes": Array [ + "*", + ], + "sortableAttributes": Array [], + "stopWords": Array [], + "synonyms": Object {}, + "typoTolerance": Object { + "disableOnAttributes": Array [], + "disableOnWords": Array [], + "enabled": true, + "minWordSizeForTypos": Object { + "oneTypo": 5, + "twoTypos": 9, + }, + }, +} +`; diff --git a/tests/facet_search.test.ts b/tests/facet_search.test.ts new file mode 100644 index 000000000..e20866b1f --- /dev/null +++ b/tests/facet_search.test.ts @@ -0,0 +1,106 @@ +import { + clearAllIndexes, + config, + getClient, +} from './utils/meilisearch-test-utils' + +const index = { + uid: 'movies_test', +} + +const dataset = [ + { + id: 123, + title: 'Pride and Prejudice', + genres: ['romance', 'action'], + }, + { + id: 456, + title: 'Le Petit Prince', + genres: ['adventure', 'comedy'], + }, + { + id: 2, + title: 'Le Rouge et le Noir', + genres: 'romance', + }, + { + id: 1, + title: 'Alice In Wonderland', + genres: ['adventure'], + }, +] + +describe.each([ + { permission: 'Master' }, + { permission: 'Admin' }, + { permission: 'Search' }, +])('Test on POST search', ({ permission }) => { + beforeAll(async () => { + await clearAllIndexes(config) + const client = await getClient('Master') + const newFilterableAttributes = ['genres', 'title'] + await client.createIndex(index.uid) + await client.index(index.uid).updateSettings({ + filterableAttributes: newFilterableAttributes, + }) + const { taskUid } = await client.index(index.uid).addDocuments(dataset) + await client.waitForTask(taskUid) + }) + + test(`${permission} key: basic facet value search`, async () => { + const client = await getClient(permission) + + const params = { + facetQuery: 'a', + facetName: 'genres', + } + const response = await client.index(index.uid).searchForFacetValues(params) + + expect(response).toMatchSnapshot() + }) + + test(`${permission} key: facet value search with no facet query`, async () => { + const client = await getClient(permission) + + const params = { + facetName: 'genres', + } + const response = await client.index(index.uid).searchForFacetValues(params) + + expect(response).toMatchSnapshot() + }) + + test(`${permission} key: facet value search with filter`, async () => { + const client = await getClient(permission) + + const params = { + facetName: 'genres', + facetQuery: 'a', + filter: ['genres = action'], + } + + const response = await client.index(index.uid).searchForFacetValues(params) + + expect(response).toMatchSnapshot() + }) + + test(`${permission} key: facet value search with search query`, async () => { + const client = await getClient(permission) + + const params = { + facetName: 'genres', + facetQuery: 'a', + q: 'Alice', + } + const response = await client.index(index.uid).searchForFacetValues(params) + + expect(response).toMatchSnapshot() + }) +}) + +jest.setTimeout(100 * 1000) + +afterAll(() => { + return clearAllIndexes(config) +}) diff --git a/tests/faceting.test.ts b/tests/faceting.test.ts index e8bbe61fe..64457f55b 100644 --- a/tests/faceting.test.ts +++ b/tests/faceting.test.ts @@ -38,18 +38,21 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( const response = await client.index(index.uid).getFaceting() - expect(response).toEqual({ maxValuesPerFacet: 100 }) + expect(response).toMatchSnapshot() }) test(`${permission} key: Update faceting settings`, async () => { const client = await getClient(permission) - const newFaceting = { maxValuesPerFacet: 12 } + const newFaceting = { + maxValuesPerFacet: 12, + sortFacetValuesBy: { test: 'count' as 'count' }, + } const task = await client.index(index.uid).updateFaceting(newFaceting) await client.index(index.uid).waitForTask(task.taskUid) const response = await client.index(index.uid).getFaceting() - expect(response).toEqual(newFaceting) + expect(response).toMatchSnapshot() }) test(`${permission} key: Update faceting at null`, async () => { @@ -61,7 +64,7 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( const response = await client.index(index.uid).getFaceting() - expect(response).toEqual({ maxValuesPerFacet: 100 }) + expect(response).toMatchSnapshot() }) test(`${permission} key: Reset faceting`, async () => { @@ -80,7 +83,7 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( const response = await client.index(index.uid).getFaceting() - expect(response).toEqual({ maxValuesPerFacet: 100 }) + expect(response).toMatchSnapshot() }) } ) diff --git a/tests/get_search.test.ts b/tests/get_search.test.ts index 33c19a79e..5a2beac45 100644 --- a/tests/get_search.test.ts +++ b/tests/get_search.test.ts @@ -6,6 +6,8 @@ import { BAD_HOST, MeiliSearch, getClient, + HOST, + getKey, } from './utils/meilisearch-test-utils' const index = { @@ -139,6 +141,26 @@ describe.each([ ) }) + test(`${permission} key: search on attributesToSearchOn`, async () => { + const client = await getClient(permission) + + const response = await client.index(index.uid).searchGet('prince', { + attributesToSearchOn: ['id'], + }) + + expect(response.hits.length).toEqual(0) + }) + + test(`${permission} key: search on attributesToSearchOn set to null`, async () => { + const client = await getClient(permission) + + const response = await client.index(index.uid).searchGet('prince', { + attributesToSearchOn: null, + }) + + expect(response).toMatchSnapshot() + }) + test(`${permission} key: search with options`, async () => { const client = await getClient(permission) const response = await client @@ -423,6 +445,25 @@ describe.each([ 'The filter query parameter should be in string format when using searchGet' ) }) + test.skip(`${permission} key: search with vectors`, async () => { + const client = await getClient(permission) + const key = await getKey(permission) + + await fetch(`${HOST}/experimental-features`, { + body: JSON.stringify({ vectorStore: true }), + headers: { + Authorization: `Bearer ${key}`, + 'Content-Type': 'application/json', + }, + method: 'PATCH', + }) + + const response = await client + .index(emptyIndex.uid) + .searchGet('', { vector: [1] }) + + expect(response.vector).toEqual([1]) + }) test(`${permission} key: Try to search on deleted index and fail`, async () => { const client = await getClient(permission) diff --git a/tests/search.test.ts b/tests/search.test.ts index 7edd89360..222f36323 100644 --- a/tests/search.test.ts +++ b/tests/search.test.ts @@ -8,8 +8,14 @@ import { MeiliSearch, getClient, datasetWithNests, + HOST, + getKey, } from './utils/meilisearch-test-utils' +if (typeof fetch === 'undefined') { + require('cross-fetch/polyfill') +} + const index = { uid: 'movies_test', } @@ -251,6 +257,51 @@ describe.each([ expect(hit.id).toEqual(1) }) + test(`${permission} key: search with _showRankingScore enabled`, async () => { + const client = await getClient(permission) + + const response = await client.index(index.uid).search('prince', { + showRankingScore: true, + }) + + const hit = response.hits[0] + + expect(response).toHaveProperty('hits', expect.any(Array)) + expect(response).toHaveProperty('query', 'prince') + expect(hit).toHaveProperty('_rankingScore') + }) + + test(`${permission} key: search with showRankingScoreDetails enabled`, async () => { + const client = await getClient(permission) + const key = await getKey(permission) + + await fetch(`${HOST}/experimental-features`, { + body: JSON.stringify({ scoreDetails: true }), + headers: { + Authorization: `Bearer ${key}`, + 'Content-Type': 'application/json', + }, + method: 'PATCH', + }) + + const response = await client.index(index.uid).search('prince', { + showRankingScoreDetails: true, + }) + + const hit = response.hits[0] + + expect(response).toHaveProperty('hits', expect.any(Array)) + expect(response).toHaveProperty('query', 'prince') + expect(hit).toHaveProperty('_rankingScoreDetails') + expect(Object.keys(hit._rankingScoreDetails || {})).toEqual([ + 'words', + 'typo', + 'proximity', + 'attribute', + 'exactness', + ]) + }) + test(`${permission} key: search with array options`, async () => { const client = await getClient(permission) @@ -266,6 +317,26 @@ describe.each([ ) }) + test(`${permission} key: search on attributesToSearchOn`, async () => { + const client = await getClient(permission) + + const response = await client.index(index.uid).search('prince', { + attributesToSearchOn: ['id'], + }) + + expect(response.hits.length).toEqual(0) + }) + + test(`${permission} key: search on attributesToSearchOn set to null`, async () => { + const client = await getClient(permission) + + const response = await client.index(index.uid).search('prince', { + attributesToSearchOn: null, + }) + + expect(response).toMatchSnapshot() + }) + test(`${permission} key: search with array options`, async () => { const client = await getClient(permission) @@ -767,6 +838,26 @@ describe.each([ expect(response.hits.length).toEqual(0) }) + test(`${permission} key: search with vectors`, async () => { + const client = await getClient(permission) + const key = await getKey(permission) + + await fetch(`${HOST}/experimental-features`, { + body: JSON.stringify({ vectorStore: true }), + headers: { + Authorization: `Bearer ${key}`, + 'Content-Type': 'application/json', + }, + method: 'PATCH', + }) + + const response = await client + .index(emptyIndex.uid) + .search('', { vector: [1] }) + + expect(response.vector).toEqual([1]) + }) + test(`${permission} key: Try to search on deleted index and fail`, async () => { const client = await getClient(permission) const masterClient = await getClient('Master') diff --git a/tests/settings.test.ts b/tests/settings.test.ts index 97864fdd4..d4b6cfd69 100644 --- a/tests/settings.test.ts +++ b/tests/settings.test.ts @@ -1,4 +1,4 @@ -import { ErrorStatusCode } from '../src/types' +import { ErrorStatusCode, Settings } from '../src/types' import { clearAllIndexes, config, @@ -16,48 +16,6 @@ const indexAndPK = { primaryKey: 'id', } -const defaultRankingRules = [ - 'words', - 'typo', - 'proximity', - 'attribute', - 'sort', - 'exactness', -] - -const defaultSettings = { - filterableAttributes: [], - sortableAttributes: [], - distinctAttribute: null, - searchableAttributes: ['*'], - displayedAttributes: ['*'], - rankingRules: [ - 'words', - 'typo', - 'proximity', - 'attribute', - 'sort', - 'exactness', - ], - stopWords: [], - synonyms: {}, - typoTolerance: { - enabled: true, - minWordSizeForTypos: { - oneTypo: 5, - twoTypos: 9, - }, - disableOnWords: [], - disableOnAttributes: [], - }, - pagination: { - maxTotalHits: 1000, - }, - faceting: { - maxValuesPerFacet: 100, - }, -} - jest.setTimeout(100 * 1000) afterAll(() => { @@ -88,15 +46,7 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( const response = await client.index(index.uid).getSettings() - expect(response).toHaveProperty('rankingRules', defaultRankingRules) - expect(response).toHaveProperty('distinctAttribute', null) - expect(response).toHaveProperty('searchableAttributes', ['*']) - expect(response).toHaveProperty('displayedAttributes', ['*']) - expect(response).toHaveProperty('sortableAttributes', []) - expect(response).toHaveProperty('stopWords', []) - expect(response).toHaveProperty('synonyms', {}) - expect(response).toHaveProperty('faceting', { maxValuesPerFacet: 100 }) - expect(response).toHaveProperty('pagination', { maxTotalHits: 1000 }) + expect(response).toMatchSnapshot() }) test(`${permission} key: Get default settings of empty index with primary key`, async () => { @@ -104,20 +54,12 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( const response = await client.index(indexAndPK.uid).getSettings() - expect(response).toHaveProperty('rankingRules', defaultRankingRules) - expect(response).toHaveProperty('distinctAttribute', null) - expect(response).toHaveProperty('searchableAttributes', ['*']) - expect(response).toHaveProperty('displayedAttributes', ['*']) - expect(response).toHaveProperty('sortableAttributes', []) - expect(response).toHaveProperty('stopWords', []) - expect(response).toHaveProperty('synonyms', {}) - expect(response).toHaveProperty('faceting', { maxValuesPerFacet: 100 }) - expect(response).toHaveProperty('pagination', { maxTotalHits: 1000 }) + expect(response).toMatchSnapshot() }) test(`${permission} key: Update settings`, async () => { const client = await getClient(permission) - const newSettings = { + const newSettings: Settings = { filterableAttributes: ['title'], sortableAttributes: ['title'], distinctAttribute: 'title', @@ -140,6 +82,9 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( }, faceting: { maxValuesPerFacet: 50, + sortFacetValuesBy: { + '*': 'alpha', + }, }, } // Add the settings @@ -150,7 +95,7 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( const response = await client.index(index.uid).getSettings() // tests - expect(response).toEqual(newSettings) + expect(response).toMatchSnapshot() }) test(`${permission} key: Update settings with all null values`, async () => { @@ -175,6 +120,7 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( }, faceting: { maxValuesPerFacet: null, + sortFacetValuesBy: null, }, pagination: { maxTotalHits: null, @@ -188,7 +134,7 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( const response = await client.index(index.uid).getSettings() // tests - expect(response).toEqual(defaultSettings) + expect(response).toMatchSnapshot() }) test(`${permission} key: Update settings on empty index with primary key`, async () => { @@ -205,17 +151,7 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( const response = await client.index(indexAndPK.uid).getSettings() - expect(response).toHaveProperty('rankingRules', newSettings.rankingRules) - expect(response).toHaveProperty( - 'distinctAttribute', - newSettings.distinctAttribute - ) - expect(response).toHaveProperty('searchableAttributes', ['*']) - expect(response).toHaveProperty('displayedAttributes', ['*']) - expect(response).toHaveProperty('stopWords', newSettings.stopWords) - expect(response).toHaveProperty('synonyms', {}) - expect(response).toHaveProperty('faceting', { maxValuesPerFacet: 100 }) - expect(response).toHaveProperty('pagination', { maxTotalHits: 1000 }) + expect(response).toMatchSnapshot() }) test(`${permission} key: Reset settings`, async () => { @@ -225,15 +161,7 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( const response = await client.index(index.uid).getSettings() - expect(response).toHaveProperty('rankingRules', defaultRankingRules) - expect(response).toHaveProperty('distinctAttribute', null) - expect(response).toHaveProperty('searchableAttributes', ['*']) - expect(response).toHaveProperty('displayedAttributes', ['*']) - expect(response).toHaveProperty('sortableAttributes', []) - expect(response).toHaveProperty('stopWords', []) - expect(response).toHaveProperty('synonyms', {}) - expect(response).toHaveProperty('faceting', { maxValuesPerFacet: 100 }) - expect(response).toHaveProperty('pagination', { maxTotalHits: 1000 }) + expect(response).toMatchSnapshot() }) test(`${permission} key: Reset settings of empty index`, async () => { @@ -243,14 +171,7 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( const response = await client.index(indexAndPK.uid).getSettings() - expect(response).toHaveProperty('rankingRules', defaultRankingRules) - expect(response).toHaveProperty('distinctAttribute', null) - expect(response).toHaveProperty('searchableAttributes', ['*']) - expect(response).toHaveProperty('displayedAttributes', ['*']) - expect(response).toHaveProperty('stopWords', []) - expect(response).toHaveProperty('synonyms', {}) - expect(response).toHaveProperty('faceting', { maxValuesPerFacet: 100 }) - expect(response).toHaveProperty('pagination', { maxTotalHits: 1000 }) + expect(response).toMatchSnapshot() }) test(`${permission} key: Update searchableAttributes settings on empty index`, async () => { @@ -263,20 +184,7 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( const response = await client.index(index.uid).getSettings() - expect(response).toHaveProperty('rankingRules', defaultRankingRules) - expect(response).toHaveProperty( - 'distinctAttribute', - defaultSettings.distinctAttribute - ) - expect(response).toHaveProperty( - 'searchableAttributes', - newSettings.searchableAttributes - ) - expect(response).toHaveProperty('displayedAttributes', expect.any(Array)) - expect(response).toHaveProperty('stopWords', defaultSettings.stopWords) - expect(response).toHaveProperty('synonyms', {}) - expect(response).toHaveProperty('faceting', { maxValuesPerFacet: 100 }) - expect(response).toHaveProperty('pagination', { maxTotalHits: 1000 }) + expect(response).toMatchSnapshot() }) test(`${permission} key: Update searchableAttributes settings on empty index with a primary key`, async () => { @@ -294,25 +202,7 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( // Fetch settings const response = await client.index(indexAndPK.uid).getSettings() - // Compare searchableAttributes - expect(response).toHaveProperty( - 'searchableAttributes', - newSettings.searchableAttributes - ) - expect(response).toHaveProperty('rankingRules', defaultRankingRules) - expect(response).toHaveProperty( - 'distinctAttribute', - defaultSettings.distinctAttribute - ) - expect(response).toHaveProperty( - 'searchableAttributes', - newSettings.searchableAttributes - ) - expect(response).toHaveProperty('displayedAttributes', expect.any(Array)) - expect(response).toHaveProperty('stopWords', defaultSettings.stopWords) - expect(response).toHaveProperty('synonyms', {}) - expect(response).toHaveProperty('faceting', { maxValuesPerFacet: 100 }) - expect(response).toHaveProperty('pagination', { maxTotalHits: 1000 }) + expect(response).toMatchSnapshot() }) } ) diff --git a/tests/task.test.ts b/tests/task.test.ts index a2eb4057c..050003b2c 100644 --- a/tests/task.test.ts +++ b/tests/task.test.ts @@ -95,6 +95,7 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( const tasks = await client.getTasks() expect(tasks.results).toBeInstanceOf(Array) + expect(tasks.total).toBeDefined() expect(tasks.results[0].uid).toEqual(enqueuedTask.taskUid) })