From c9fa405f63b8bfa8f00ba112766fc2ab4920d6b5 Mon Sep 17 00:00:00 2001 From: Alexia Toulmet Date: Wed, 9 Aug 2023 14:55:20 +0200 Subject: [PATCH] proto-beta: Tokenizer customization --- .prettierignore | 1 + README.md | 61 ++++++++++ src/indexes.ts | 130 +++++++++++++++++++++ src/types/types.ts | 6 + tests/__snapshots__/settings.test.ts.snap | 76 ++++++++++++ tests/dictionary.test.ts | 124 ++++++++++++++++++++ tests/non_separator_tokens.test.ts | 134 ++++++++++++++++++++++ tests/separator_tokens.test.ts | 134 ++++++++++++++++++++++ tests/settings.test.ts | 6 + 9 files changed, 672 insertions(+) create mode 100644 tests/dictionary.test.ts create mode 100644 tests/non_separator_tokens.test.ts create mode 100644 tests/separator_tokens.test.ts diff --git a/.prettierignore b/.prettierignore index f06235c46..25fb9870e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,2 +1,3 @@ node_modules dist +*.md diff --git a/README.md b/README.md index 9f9166493..b8a14e831 100644 --- a/README.md +++ b/README.md @@ -900,6 +900,67 @@ client.index('myIndex').updateTypoTolerance(typoTolerance: TypoTolerance | null) client.index('myIndex').resetTypoTolerance(): Promise ``` + +### Separator tokens + +#### Get separator tokens + +```ts +client.index('myIndex').getSeparatorTokens(): Promise +``` + +#### Update separator tokens + +```ts +client.index('myIndex').updateSeparatorTokens(separatorTokens: SeparatorTokens | null): Promise +``` + +#### Reset separator tokens + +```ts +client.index('myIndex').resetSeparatorTokens(): Promise +``` + +### Non Separator tokens + +#### Get non separator tokens + +```ts +client.index('myIndex').getNonSeparatorTokens(): Promise +``` + +#### Update non separator tokens + +```ts +client.index('myIndex').updateNonSeparatorTokens(nonSeparatorTokens: NonSeparatorTokens | null): Promise +``` + +#### Reset non separator tokens + +```ts +client.index('myIndex').resetNonSeparatorTokens(): Promise +``` + +### Dictionary + +#### Get dictionary + +```ts +client.index('myIndex').getDictionary(): Promise +``` + +#### Update dictionary + +```ts +client.index('myIndex').updateDictionary(dictionary: Dictionary | null): Promise +``` + +#### Reset dictionary + +```ts +client.index('myIndex').resetDictionary(): Promise +``` + ### Keys #### [Get keys](https://www.meilisearch.com/docs/reference/api/keys#get-all-keys) diff --git a/src/indexes.ts b/src/indexes.ts index ea732da5b..39b338a7e 100644 --- a/src/indexes.ts +++ b/src/indexes.ts @@ -47,6 +47,9 @@ import { DocumentsDeletionQuery, SearchForFacetValuesParams, SearchForFacetValuesResponse, + SeparatorTokens, + NonSeparatorTokens, + Dictionary, } from './types' import { removeUndefinedFromObject } from './utils' import { HttpRequests } from './http-requests' @@ -1117,6 +1120,133 @@ class Index = Record> { return new EnqueuedTask(task) } + + /// + /// SEPARATOR TOKENS + /// + + /** + * Get the list of all separator tokens. + * + * @returns Promise containing array of separator tokens + */ + async getSeparatorTokens(): Promise { + const url = `indexes/${this.uid}/settings/separator-tokens` + return await this.httpRequest.get(url) + } + + /** + * Update the list of separator tokens. Overwrite the old list. + * + * @param separatorTokens - Array that contains separator tokens. + * @returns Promise containing an EnqueuedTask or null + */ + async updateSeparatorTokens( + separatorTokens: SeparatorTokens + ): Promise { + const url = `indexes/${this.uid}/settings/separator-tokens` + const task = await this.httpRequest.put(url, separatorTokens) + + return new EnqueuedTask(task) + } + + /** + * Reset the separator tokens list to its default value + * + * @returns Promise containing an EnqueuedTask + */ + async resetSeparatorTokens(): Promise { + const url = `indexes/${this.uid}/settings/separator-tokens` + const task = await this.httpRequest.delete(url) + + task.enqueuedAt = new Date(task.enqueuedAt) + + return task + } + + /// + /// NON-SEPARATOR TOKENS + /// + + /** + * Get the list of all non-separator tokens. + * + * @returns Promise containing array of non-separator tokens + */ + async getNonSeparatorTokens(): Promise { + const url = `indexes/${this.uid}/settings/non-separator-tokens` + return await this.httpRequest.get(url) + } + + /** + * Update the list of non-separator tokens. Overwrite the old list. + * + * @param nonSeparatorTokens - Array that contains non-separator tokens. + * @returns Promise containing an EnqueuedTask or null + */ + async updateNonSeparatorTokens( + nonSeparatorTokens: NonSeparatorTokens + ): Promise { + const url = `indexes/${this.uid}/settings/non-separator-tokens` + const task = await this.httpRequest.put(url, nonSeparatorTokens) + + return new EnqueuedTask(task) + } + + /** + * Reset the non-separator tokens list to its default value + * + * @returns Promise containing an EnqueuedTask + */ + async resetNonSeparatorTokens(): Promise { + const url = `indexes/${this.uid}/settings/non-separator-tokens` + const task = await this.httpRequest.delete(url) + + task.enqueuedAt = new Date(task.enqueuedAt) + + return task + } + + /// + /// DICTIONARY + /// + + /** + * Get the dictionary settings of a Meilisearch index. + * + * @returns Promise containing the dictionary settings + */ + async getDictionary(): Promise { + const url = `indexes/${this.uid}/settings/dictionary` + return await this.httpRequest.get(url) + } + + /** + * Update the the dictionary settings. Overwrite the old settings. + * + * @param dictionary - Array that contains the new dictionary settings. + * @returns Promise containing an EnqueuedTask or null + */ + async updateDictionary(dictionary: Dictionary): Promise { + const url = `indexes/${this.uid}/settings/dictionary` + const task = await this.httpRequest.put(url, dictionary) + + return new EnqueuedTask(task) + } + + /** + * Reset the dictionary settings to its default value + * + * @returns Promise containing an EnqueuedTask + */ + async resetDictionary(): Promise { + const url = `indexes/${this.uid}/settings/dictionary` + const task = await this.httpRequest.delete(url) + + task.enqueuedAt = new Date(task.enqueuedAt) + + return task + } } export { Index } diff --git a/src/types/types.ts b/src/types/types.ts index 0d9139439..be1a6b8fc 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -312,6 +312,9 @@ export type TypoTolerance = { twoTypos?: number | null } } | null +export type SeparatorTokens = string[] | null +export type NonSeparatorTokens = string[] | null +export type Dictionary = string[] | null export type FacetOrder = 'alpha' | 'count' @@ -336,6 +339,9 @@ export type Settings = { typoTolerance?: TypoTolerance faceting?: Faceting pagination?: PaginationSettings + separatorTokens?: SeparatorTokens + nonSeparatorTokens?: NonSeparatorTokens + dictionary?: Dictionary } /* diff --git a/tests/__snapshots__/settings.test.ts.snap b/tests/__snapshots__/settings.test.ts.snap index fdc4721df..158884d15 100644 --- a/tests/__snapshots__/settings.test.ts.snap +++ b/tests/__snapshots__/settings.test.ts.snap @@ -2,6 +2,7 @@ exports[`Test on settings Admin key: Get default settings of an index 1`] = ` Object { + "dictionary": Array [], "displayedAttributes": Array [ "*", ], @@ -13,6 +14,7 @@ Object { }, }, "filterableAttributes": Array [], + "nonSeparatorTokens": Array [], "pagination": Object { "maxTotalHits": 1000, }, @@ -27,6 +29,7 @@ Object { "searchableAttributes": Array [ "*", ], + "separatorTokens": Array [], "sortableAttributes": Array [], "stopWords": Array [], "synonyms": Object {}, @@ -44,6 +47,7 @@ Object { exports[`Test on settings Admin key: Get default settings of empty index with primary key 1`] = ` Object { + "dictionary": Array [], "displayedAttributes": Array [ "*", ], @@ -55,6 +59,7 @@ Object { }, }, "filterableAttributes": Array [], + "nonSeparatorTokens": Array [], "pagination": Object { "maxTotalHits": 1000, }, @@ -69,6 +74,7 @@ Object { "searchableAttributes": Array [ "*", ], + "separatorTokens": Array [], "sortableAttributes": Array [], "stopWords": Array [], "synonyms": Object {}, @@ -86,6 +92,7 @@ Object { exports[`Test on settings Admin key: Reset settings 1`] = ` Object { + "dictionary": Array [], "displayedAttributes": Array [ "*", ], @@ -97,6 +104,7 @@ Object { }, }, "filterableAttributes": Array [], + "nonSeparatorTokens": Array [], "pagination": Object { "maxTotalHits": 1000, }, @@ -111,6 +119,7 @@ Object { "searchableAttributes": Array [ "*", ], + "separatorTokens": Array [], "sortableAttributes": Array [], "stopWords": Array [], "synonyms": Object {}, @@ -128,6 +137,7 @@ Object { exports[`Test on settings Admin key: Reset settings of empty index 1`] = ` Object { + "dictionary": Array [], "displayedAttributes": Array [ "*", ], @@ -139,6 +149,7 @@ Object { }, }, "filterableAttributes": Array [], + "nonSeparatorTokens": Array [], "pagination": Object { "maxTotalHits": 1000, }, @@ -153,6 +164,7 @@ Object { "searchableAttributes": Array [ "*", ], + "separatorTokens": Array [], "sortableAttributes": Array [], "stopWords": Array [], "synonyms": Object {}, @@ -170,6 +182,7 @@ Object { exports[`Test on settings Admin key: Update searchableAttributes settings on empty index 1`] = ` Object { + "dictionary": Array [], "displayedAttributes": Array [ "*", ], @@ -181,6 +194,7 @@ Object { }, }, "filterableAttributes": Array [], + "nonSeparatorTokens": Array [], "pagination": Object { "maxTotalHits": 1000, }, @@ -195,6 +209,7 @@ Object { "searchableAttributes": Array [ "title", ], + "separatorTokens": Array [], "sortableAttributes": Array [], "stopWords": Array [], "synonyms": Object {}, @@ -212,6 +227,7 @@ Object { exports[`Test on settings Admin key: Update searchableAttributes settings on empty index with a primary key 1`] = ` Object { + "dictionary": Array [], "displayedAttributes": Array [ "*", ], @@ -223,6 +239,7 @@ Object { }, }, "filterableAttributes": Array [], + "nonSeparatorTokens": Array [], "pagination": Object { "maxTotalHits": 1000, }, @@ -237,6 +254,7 @@ Object { "searchableAttributes": Array [ "title", ], + "separatorTokens": Array [], "sortableAttributes": Array [], "stopWords": Array [], "synonyms": Object {}, @@ -254,6 +272,10 @@ Object { exports[`Test on settings Admin key: Update settings 1`] = ` Object { + "dictionary": Array [ + "J. K.", + "J. R. R.", + ], "displayedAttributes": Array [ "title", ], @@ -267,6 +289,11 @@ Object { "filterableAttributes": Array [ "title", ], + "nonSeparatorTokens": Array [ + "&sep", + "/", + "|", + ], "pagination": Object { "maxTotalHits": 1000, }, @@ -277,6 +304,11 @@ Object { "searchableAttributes": Array [ "title", ], + "separatorTokens": Array [ + "&sep", + "/", + "|", + ], "sortableAttributes": Array [ "title", ], @@ -306,6 +338,7 @@ Object { exports[`Test on settings Admin key: Update settings on empty index with primary key 1`] = ` Object { + "dictionary": Array [], "displayedAttributes": Array [ "*", ], @@ -317,6 +350,7 @@ Object { }, }, "filterableAttributes": Array [], + "nonSeparatorTokens": Array [], "pagination": Object { "maxTotalHits": 1000, }, @@ -327,6 +361,7 @@ Object { "searchableAttributes": Array [ "*", ], + "separatorTokens": Array [], "sortableAttributes": Array [], "stopWords": Array [ "the", @@ -346,6 +381,7 @@ Object { exports[`Test on settings Admin key: Update settings with all null values 1`] = ` Object { + "dictionary": Array [], "displayedAttributes": Array [ "*", ], @@ -357,6 +393,7 @@ Object { }, }, "filterableAttributes": Array [], + "nonSeparatorTokens": Array [], "pagination": Object { "maxTotalHits": 1000, }, @@ -371,6 +408,7 @@ Object { "searchableAttributes": Array [ "*", ], + "separatorTokens": Array [], "sortableAttributes": Array [], "stopWords": Array [], "synonyms": Object {}, @@ -388,6 +426,7 @@ Object { exports[`Test on settings Master key: Get default settings of an index 1`] = ` Object { + "dictionary": Array [], "displayedAttributes": Array [ "*", ], @@ -399,6 +438,7 @@ Object { }, }, "filterableAttributes": Array [], + "nonSeparatorTokens": Array [], "pagination": Object { "maxTotalHits": 1000, }, @@ -413,6 +453,7 @@ Object { "searchableAttributes": Array [ "*", ], + "separatorTokens": Array [], "sortableAttributes": Array [], "stopWords": Array [], "synonyms": Object {}, @@ -430,6 +471,7 @@ Object { exports[`Test on settings Master key: Get default settings of empty index with primary key 1`] = ` Object { + "dictionary": Array [], "displayedAttributes": Array [ "*", ], @@ -441,6 +483,7 @@ Object { }, }, "filterableAttributes": Array [], + "nonSeparatorTokens": Array [], "pagination": Object { "maxTotalHits": 1000, }, @@ -455,6 +498,7 @@ Object { "searchableAttributes": Array [ "*", ], + "separatorTokens": Array [], "sortableAttributes": Array [], "stopWords": Array [], "synonyms": Object {}, @@ -472,6 +516,7 @@ Object { exports[`Test on settings Master key: Reset settings 1`] = ` Object { + "dictionary": Array [], "displayedAttributes": Array [ "*", ], @@ -483,6 +528,7 @@ Object { }, }, "filterableAttributes": Array [], + "nonSeparatorTokens": Array [], "pagination": Object { "maxTotalHits": 1000, }, @@ -497,6 +543,7 @@ Object { "searchableAttributes": Array [ "*", ], + "separatorTokens": Array [], "sortableAttributes": Array [], "stopWords": Array [], "synonyms": Object {}, @@ -514,6 +561,7 @@ Object { exports[`Test on settings Master key: Reset settings of empty index 1`] = ` Object { + "dictionary": Array [], "displayedAttributes": Array [ "*", ], @@ -525,6 +573,7 @@ Object { }, }, "filterableAttributes": Array [], + "nonSeparatorTokens": Array [], "pagination": Object { "maxTotalHits": 1000, }, @@ -539,6 +588,7 @@ Object { "searchableAttributes": Array [ "*", ], + "separatorTokens": Array [], "sortableAttributes": Array [], "stopWords": Array [], "synonyms": Object {}, @@ -556,6 +606,7 @@ Object { exports[`Test on settings Master key: Update searchableAttributes settings on empty index 1`] = ` Object { + "dictionary": Array [], "displayedAttributes": Array [ "*", ], @@ -567,6 +618,7 @@ Object { }, }, "filterableAttributes": Array [], + "nonSeparatorTokens": Array [], "pagination": Object { "maxTotalHits": 1000, }, @@ -581,6 +633,7 @@ Object { "searchableAttributes": Array [ "title", ], + "separatorTokens": Array [], "sortableAttributes": Array [], "stopWords": Array [], "synonyms": Object {}, @@ -598,6 +651,7 @@ Object { exports[`Test on settings Master key: Update searchableAttributes settings on empty index with a primary key 1`] = ` Object { + "dictionary": Array [], "displayedAttributes": Array [ "*", ], @@ -609,6 +663,7 @@ Object { }, }, "filterableAttributes": Array [], + "nonSeparatorTokens": Array [], "pagination": Object { "maxTotalHits": 1000, }, @@ -623,6 +678,7 @@ Object { "searchableAttributes": Array [ "title", ], + "separatorTokens": Array [], "sortableAttributes": Array [], "stopWords": Array [], "synonyms": Object {}, @@ -640,6 +696,10 @@ Object { exports[`Test on settings Master key: Update settings 1`] = ` Object { + "dictionary": Array [ + "J. K.", + "J. R. R.", + ], "displayedAttributes": Array [ "title", ], @@ -653,6 +713,11 @@ Object { "filterableAttributes": Array [ "title", ], + "nonSeparatorTokens": Array [ + "&sep", + "/", + "|", + ], "pagination": Object { "maxTotalHits": 1000, }, @@ -663,6 +728,11 @@ Object { "searchableAttributes": Array [ "title", ], + "separatorTokens": Array [ + "&sep", + "/", + "|", + ], "sortableAttributes": Array [ "title", ], @@ -692,6 +762,7 @@ Object { exports[`Test on settings Master key: Update settings on empty index with primary key 1`] = ` Object { + "dictionary": Array [], "displayedAttributes": Array [ "*", ], @@ -703,6 +774,7 @@ Object { }, }, "filterableAttributes": Array [], + "nonSeparatorTokens": Array [], "pagination": Object { "maxTotalHits": 1000, }, @@ -713,6 +785,7 @@ Object { "searchableAttributes": Array [ "*", ], + "separatorTokens": Array [], "sortableAttributes": Array [], "stopWords": Array [ "the", @@ -732,6 +805,7 @@ Object { exports[`Test on settings Master key: Update settings with all null values 1`] = ` Object { + "dictionary": Array [], "displayedAttributes": Array [ "*", ], @@ -743,6 +817,7 @@ Object { }, }, "filterableAttributes": Array [], + "nonSeparatorTokens": Array [], "pagination": Object { "maxTotalHits": 1000, }, @@ -757,6 +832,7 @@ Object { "searchableAttributes": Array [ "*", ], + "separatorTokens": Array [], "sortableAttributes": Array [], "stopWords": Array [], "synonyms": Object {}, diff --git a/tests/dictionary.test.ts b/tests/dictionary.test.ts new file mode 100644 index 000000000..a2f2e3a9f --- /dev/null +++ b/tests/dictionary.test.ts @@ -0,0 +1,124 @@ +import { EnqueuedTask } from '../src/enqueued-task' +import { + clearAllIndexes, + config, + BAD_HOST, + MeiliSearch, + getClient, + dataset, +} from './utils/meilisearch-test-utils' + +const index = { + uid: 'movies_test', +} + +jest.setTimeout(100 * 1000) + +afterAll(() => { + return clearAllIndexes(config) +}) + +describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( + 'Test on dictionary', + ({ permission }) => { + beforeEach(async () => { + const client = await getClient('Master') + const { taskUid } = await client.index(index.uid).addDocuments(dataset) + await client.waitForTask(taskUid) + }) + + test(`${permission} key: Get default dictionary`, async () => { + const client = await getClient(permission) + const response: string[] = await client.index(index.uid).getDictionary() + + expect(response).toEqual([]) + }) + + test(`${permission} key: Update dictionary`, async () => { + const client = await getClient(permission) + const newDictionary = ['J. K.', 'J. R. R.'] + const task: EnqueuedTask = await client + .index(index.uid) + .updateDictionary(newDictionary) + await client.index(index.uid).waitForTask(task.taskUid) + + const response: string[] = await client.index(index.uid).getDictionary() + + expect(response).toEqual(newDictionary) + }) + + test(`${permission} key: Update dictionary with null value`, async () => { + const client = await getClient(permission) + const newDictionary = null + const task: EnqueuedTask = await client + .index(index.uid) + .updateDictionary(newDictionary) + await client.index(index.uid).waitForTask(task.taskUid) + + const response: string[] = await client.index(index.uid).getDictionary() + + expect(response).toEqual([]) + }) + + test(`${permission} key: Reset dictionary`, async () => { + const client = await getClient(permission) + const task: EnqueuedTask = await client.index(index.uid).resetDictionary() + await client.index(index.uid).waitForTask(task.taskUid) + + const response: string[] = await client.index(index.uid).getDictionary() + + expect(response).toEqual([]) + }) + } +) + +describe.each([ + { host: BAD_HOST, trailing: false }, + { host: `${BAD_HOST}/api`, trailing: false }, + { host: `${BAD_HOST}/trailing/`, trailing: true }, +])('Tests on url construction', ({ host, trailing }) => { + test(`Test getDictionary route`, async () => { + const route = `indexes/${index.uid}/settings/dictionary` + const client = new MeiliSearch({ host }) + const strippedHost = trailing ? host.slice(0, -1) : host + await expect( + client.index(index.uid).getDictionary() + ).rejects.toHaveProperty( + 'message', + `request to ${strippedHost}/${route} failed, reason: connect ECONNREFUSED ${BAD_HOST.replace( + 'http://', + '' + )}` + ) + }) + + test(`Test updateDictionary route`, async () => { + const route = `indexes/${index.uid}/settings/dictionary` + const client = new MeiliSearch({ host }) + const strippedHost = trailing ? host.slice(0, -1) : host + await expect( + client.index(index.uid).updateDictionary([]) + ).rejects.toHaveProperty( + 'message', + `request to ${strippedHost}/${route} failed, reason: connect ECONNREFUSED ${BAD_HOST.replace( + 'http://', + '' + )}` + ) + }) + + test(`Test resetDictionary route`, async () => { + const route = `indexes/${index.uid}/settings/dictionary` + const client = new MeiliSearch({ host }) + const strippedHost = trailing ? host.slice(0, -1) : host + await expect( + client.index(index.uid).resetDictionary() + ).rejects.toHaveProperty( + 'message', + `request to ${strippedHost}/${route} failed, reason: connect ECONNREFUSED ${BAD_HOST.replace( + 'http://', + '' + )}` + ) + }) +}) diff --git a/tests/non_separator_tokens.test.ts b/tests/non_separator_tokens.test.ts new file mode 100644 index 000000000..0037c2f30 --- /dev/null +++ b/tests/non_separator_tokens.test.ts @@ -0,0 +1,134 @@ +import { EnqueuedTask } from '../src/enqueued-task' +import { + clearAllIndexes, + config, + BAD_HOST, + MeiliSearch, + getClient, + dataset, +} from './utils/meilisearch-test-utils' + +const index = { + uid: 'movies_test', +} + +jest.setTimeout(100 * 1000) + +afterAll(() => { + return clearAllIndexes(config) +}) + +describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( + 'Test on non separator tokens', + ({ permission }) => { + beforeEach(async () => { + const client = await getClient('Master') + const { taskUid } = await client.index(index.uid).addDocuments(dataset) + await client.waitForTask(taskUid) + }) + + test(`${permission} key: Get default non separator tokens`, async () => { + const client = await getClient(permission) + const response: string[] = await client + .index(index.uid) + .getNonSeparatorTokens() + + expect(response).toEqual([]) + }) + + test(`${permission} key: Update non separator tokens`, async () => { + const client = await getClient(permission) + const newNonSeparatorTokens = ['&sep', '/', '|'] + const task: EnqueuedTask = await client + .index(index.uid) + .updateNonSeparatorTokens(newNonSeparatorTokens) + await client.index(index.uid).waitForTask(task.taskUid) + + const response: string[] = await client + .index(index.uid) + .getNonSeparatorTokens() + + expect(response).toEqual(newNonSeparatorTokens) + }) + + test(`${permission} key: Update non separator tokens with null value`, async () => { + const client = await getClient(permission) + const newNonSeparatorTokens = null + const task: EnqueuedTask = await client + .index(index.uid) + .updateNonSeparatorTokens(newNonSeparatorTokens) + await client.index(index.uid).waitForTask(task.taskUid) + + const response: string[] = await client + .index(index.uid) + .getNonSeparatorTokens() + + expect(response).toEqual([]) + }) + + test(`${permission} key: Reset NonSeparator tokens`, async () => { + const client = await getClient(permission) + const task: EnqueuedTask = await client + .index(index.uid) + .resetNonSeparatorTokens() + await client.index(index.uid).waitForTask(task.taskUid) + + const response: string[] = await client + .index(index.uid) + .getNonSeparatorTokens() + + expect(response).toEqual([]) + }) + } +) + +describe.each([ + { host: BAD_HOST, trailing: false }, + { host: `${BAD_HOST}/api`, trailing: false }, + { host: `${BAD_HOST}/trailing/`, trailing: true }, +])('Tests on url construction', ({ host, trailing }) => { + test(`Test getNonSeparatorTokens route`, async () => { + const route = `indexes/${index.uid}/settings/non-separator-tokens` + const client = new MeiliSearch({ host }) + const strippedHost = trailing ? host.slice(0, -1) : host + await expect( + client.index(index.uid).getNonSeparatorTokens() + ).rejects.toHaveProperty( + 'message', + `request to ${strippedHost}/${route} failed, reason: connect ECONNREFUSED ${BAD_HOST.replace( + 'http://', + '' + )}` + ) + }) + + test(`Test updateNonSeparatorTokens route`, async () => { + const route = `indexes/${index.uid}/settings/non-separator-tokens` + const client = new MeiliSearch({ host }) + const strippedHost = trailing ? host.slice(0, -1) : host + await expect( + client.index(index.uid).updateNonSeparatorTokens([]) + ).rejects.toHaveProperty( + 'message', + `request to ${strippedHost}/${route} failed, reason: connect ECONNREFUSED ${BAD_HOST.replace( + 'http://', + '' + )}` + ) + }) + + test(`Test resetNonSeparatorTokens route`, async () => { + const route = `indexes/${index.uid}/settings/non-separator-tokens` + const client = new MeiliSearch({ host }) + const strippedHost = trailing ? host.slice(0, -1) : host + await expect( + client.index(index.uid).resetNonSeparatorTokens() + ).rejects.toHaveProperty( + 'message', + `request to ${strippedHost}/${route} failed, reason: connect ECONNREFUSED ${BAD_HOST.replace( + 'http://', + '' + )}` + ) + }) +}) diff --git a/tests/separator_tokens.test.ts b/tests/separator_tokens.test.ts new file mode 100644 index 000000000..ebb0f455b --- /dev/null +++ b/tests/separator_tokens.test.ts @@ -0,0 +1,134 @@ +import { EnqueuedTask } from '../src/enqueued-task' +import { + clearAllIndexes, + config, + BAD_HOST, + MeiliSearch, + getClient, + dataset, +} from './utils/meilisearch-test-utils' + +const index = { + uid: 'movies_test', +} + +jest.setTimeout(100 * 1000) + +afterAll(() => { + return clearAllIndexes(config) +}) + +describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( + 'Test on separator tokens', + ({ permission }) => { + beforeEach(async () => { + const client = await getClient('Master') + const { taskUid } = await client.index(index.uid).addDocuments(dataset) + await client.waitForTask(taskUid) + }) + + test(`${permission} key: Get default separator tokens`, async () => { + const client = await getClient(permission) + const response: string[] = await client + .index(index.uid) + .getSeparatorTokens() + + expect(response).toEqual([]) + }) + + test(`${permission} key: Update separator tokens`, async () => { + const client = await getClient(permission) + const newSeparatorTokens = ['&sep', '/', '|'] + const task: EnqueuedTask = await client + .index(index.uid) + .updateSeparatorTokens(newSeparatorTokens) + await client.index(index.uid).waitForTask(task.taskUid) + + const response: string[] = await client + .index(index.uid) + .getSeparatorTokens() + + expect(response).toEqual(newSeparatorTokens) + }) + + test(`${permission} key: Update separator tokens with null value`, async () => { + const client = await getClient(permission) + const newSeparatorTokens = null + const task: EnqueuedTask = await client + .index(index.uid) + .updateSeparatorTokens(newSeparatorTokens) + await client.index(index.uid).waitForTask(task.taskUid) + + const response: string[] = await client + .index(index.uid) + .getSeparatorTokens() + + expect(response).toEqual([]) + }) + + test(`${permission} key: Reset separator tokens`, async () => { + const client = await getClient(permission) + const task: EnqueuedTask = await client + .index(index.uid) + .resetSeparatorTokens() + await client.index(index.uid).waitForTask(task.taskUid) + + const response: string[] = await client + .index(index.uid) + .getSeparatorTokens() + + expect(response).toEqual([]) + }) + } +) + +describe.each([ + { host: BAD_HOST, trailing: false }, + { host: `${BAD_HOST}/api`, trailing: false }, + { host: `${BAD_HOST}/trailing/`, trailing: true }, +])('Tests on url construction', ({ host, trailing }) => { + test(`Test getSeparatorTokens route`, async () => { + const route = `indexes/${index.uid}/settings/separator-tokens` + const client = new MeiliSearch({ host }) + const strippedHost = trailing ? host.slice(0, -1) : host + await expect( + client.index(index.uid).getSeparatorTokens() + ).rejects.toHaveProperty( + 'message', + `request to ${strippedHost}/${route} failed, reason: connect ECONNREFUSED ${BAD_HOST.replace( + 'http://', + '' + )}` + ) + }) + + test(`Test updateSeparatorTokens route`, async () => { + const route = `indexes/${index.uid}/settings/separator-tokens` + const client = new MeiliSearch({ host }) + const strippedHost = trailing ? host.slice(0, -1) : host + await expect( + client.index(index.uid).updateSeparatorTokens([]) + ).rejects.toHaveProperty( + 'message', + `request to ${strippedHost}/${route} failed, reason: connect ECONNREFUSED ${BAD_HOST.replace( + 'http://', + '' + )}` + ) + }) + + test(`Test resetSeparatorTokens route`, async () => { + const route = `indexes/${index.uid}/settings/separator-tokens` + const client = new MeiliSearch({ host }) + const strippedHost = trailing ? host.slice(0, -1) : host + await expect( + client.index(index.uid).resetSeparatorTokens() + ).rejects.toHaveProperty( + 'message', + `request to ${strippedHost}/${route} failed, reason: connect ECONNREFUSED ${BAD_HOST.replace( + 'http://', + '' + )}` + ) + }) +}) diff --git a/tests/settings.test.ts b/tests/settings.test.ts index d4b6cfd69..e59a4f5a5 100644 --- a/tests/settings.test.ts +++ b/tests/settings.test.ts @@ -86,6 +86,9 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( '*': 'alpha', }, }, + separatorTokens: ['&sep', '/', '|'], + nonSeparatorTokens: ['&sep', '/', '|'], + dictionary: ['J. K.', 'J. R. R.'], } // Add the settings const task = await client.index(index.uid).updateSettings(newSettings) @@ -125,6 +128,9 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])( pagination: { maxTotalHits: null, }, + separatorTokens: null, + nonSeparatorTokens: null, + dictionary: null, } // Add the settings const task = await client.index(index.uid).updateSettings(newSettings)