From 0d8ae6e44cd6e84e907d3e4f2a97dadfdb728589 Mon Sep 17 00:00:00 2001 From: Pierre Millot Date: Fri, 30 Aug 2024 01:40:07 +0200 Subject: [PATCH] fix(cts): add the remaining helpers tests --- scripts/buildClients.ts | 3 + scripts/cts/runCts.ts | 2 +- scripts/cts/testServer/index.ts | 2 +- .../{waitForApiKey.ts => waitFor.ts} | 14 +- .../search/common/schemas/GetTaskResponse.yml | 8 + specs/search/helpers/browseObjects.yml | 31 + specs/search/helpers/waitForAppTask.yml | 23 + specs/search/helpers/waitForTask.yml | 34 ++ specs/search/paths/advanced/getAppTask.yml | 9 +- specs/search/paths/advanced/getTask.yml | 9 +- specs/search/spec.yml | 9 + templates/go/search_helpers.mustache | 6 +- templates/java/api_helpers.mustache | 32 +- tests/CTS/client/search/browseObjects.json | 33 ++ tests/CTS/client/search/deleteObjects.json | 44 ++ .../client/search/generateSecuredApiKey.json | 61 ++ tests/CTS/client/search/helpers.json | 556 ------------------ .../client/search/partialUpdateObjects.json | 100 ++++ .../CTS/client/search/replaceAllObjects.json | 116 ++++ tests/CTS/client/search/saveObjects.json | 100 ++++ tests/CTS/client/search/waitForApiKey.json | 145 +++++ tests/CTS/client/search/waitForAppTask.json | 34 ++ tests/CTS/client/search/waitForTask.json | 35 ++ 23 files changed, 812 insertions(+), 594 deletions(-) rename scripts/cts/testServer/{waitForApiKey.ts => waitFor.ts} (91%) create mode 100644 specs/search/common/schemas/GetTaskResponse.yml create mode 100644 specs/search/helpers/browseObjects.yml create mode 100644 specs/search/helpers/waitForAppTask.yml create mode 100644 specs/search/helpers/waitForTask.yml create mode 100644 tests/CTS/client/search/browseObjects.json create mode 100644 tests/CTS/client/search/deleteObjects.json create mode 100644 tests/CTS/client/search/generateSecuredApiKey.json delete mode 100644 tests/CTS/client/search/helpers.json create mode 100644 tests/CTS/client/search/partialUpdateObjects.json create mode 100644 tests/CTS/client/search/replaceAllObjects.json create mode 100644 tests/CTS/client/search/saveObjects.json create mode 100644 tests/CTS/client/search/waitForApiKey.json create mode 100644 tests/CTS/client/search/waitForAppTask.json create mode 100644 tests/CTS/client/search/waitForTask.json diff --git a/scripts/buildClients.ts b/scripts/buildClients.ts index e2f328f45e4..e27850a342b 100644 --- a/scripts/buildClients.ts +++ b/scripts/buildClients.ts @@ -15,6 +15,9 @@ async function buildLanguage(language: Language, gens: Generator[], buildType: B case 'csharp': await run('dotnet build --configuration Release', { cwd, language }); break; + case 'go': + await run('go build ./...', { cwd, language }); + break; case 'javascript': await run('YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install', { cwd }); if (buildType === 'client') { diff --git a/scripts/cts/runCts.ts b/scripts/cts/runCts.ts index b57bb189b91..1929ed1999c 100644 --- a/scripts/cts/runCts.ts +++ b/scripts/cts/runCts.ts @@ -10,7 +10,7 @@ import { printBenchmarkReport } from './testServer/benchmark.js'; import { assertChunkWrapperValid } from './testServer/chunkWrapper.js'; import { assertValidReplaceAllObjects } from './testServer/replaceAllObjects.js'; import { assertValidTimeouts } from './testServer/timeout.js'; -import { assertValidWaitForApiKey } from './testServer/waitForApiKey.js'; +import { assertValidWaitForApiKey } from './testServer/waitFor.js'; export type CTSType = 'benchmark' | 'client' | 'e2e' | 'requests'; diff --git a/scripts/cts/testServer/index.ts b/scripts/cts/testServer/index.ts index 8f6333ee646..c44dfb0adbb 100644 --- a/scripts/cts/testServer/index.ts +++ b/scripts/cts/testServer/index.ts @@ -12,7 +12,7 @@ import { gzipServer } from './gzip'; import { replaceAllObjectsServer } from './replaceAllObjects'; import { timeoutServer } from './timeout'; import { timeoutServerBis } from './timeoutBis'; -import { waitForApiKeyServer } from './waitForApiKey'; +import { waitForApiKeyServer } from './waitFor'; export async function startTestServer(suites: Record): Promise<() => Promise> { const toStart: Array> = []; diff --git a/scripts/cts/testServer/waitForApiKey.ts b/scripts/cts/testServer/waitFor.ts similarity index 91% rename from scripts/cts/testServer/waitForApiKey.ts rename to scripts/cts/testServer/waitFor.ts index 7a31c3fe116..3222c1df664 100644 --- a/scripts/cts/testServer/waitForApiKey.ts +++ b/scripts/cts/testServer/waitFor.ts @@ -113,8 +113,20 @@ function addRoutes(app: Express): void { throw new Error(`Invalid API key ${req.params.key}`); } }); + + app.get('/1/indexes/:indexName/task/:taskID', (req, res) => { + res.status(200).json({ + status: 'published', + }); + }); + + app.get('/1/task/:taskID', (req, res) => { + res.status(200).json({ + status: 'published', + }); + }); } export function waitForApiKeyServer(): Promise { - return setupServer('waitForApiKey', 6681, addRoutes); + return setupServer('waitFor', 6681, addRoutes); } diff --git a/specs/search/common/schemas/GetTaskResponse.yml b/specs/search/common/schemas/GetTaskResponse.yml new file mode 100644 index 00000000000..7b4213b832a --- /dev/null +++ b/specs/search/common/schemas/GetTaskResponse.yml @@ -0,0 +1,8 @@ +title: getTaskResponse +type: object +additionalProperties: false +properties: + status: + $ref: '../../../common/responses/common.yml#/taskStatus' +required: + - status diff --git a/specs/search/helpers/browseObjects.yml b/specs/search/helpers/browseObjects.yml new file mode 100644 index 00000000000..a44ddfe6bde --- /dev/null +++ b/specs/search/helpers/browseObjects.yml @@ -0,0 +1,31 @@ +method: + get: + x-helper: true + tags: + - Records + operationId: browseObjects + summary: Get all records from an index + description: | + You can use the browse method to get records from an index—for example, to export your index as a backup. To export all records, use an empty query. + + Use browse instead of search when exporting records from your index, when ranking, or analytics, isn't important. The Analytics API doesn't collect data when using browse. + + Don't use this method for building a search UI. Use search instead. + parameters: + - in: query + name: indexName + description: The name of the index on which the operation was performed. + required: true + schema: + type: string + - in: query + name: browseParams + description: Browse parameters. + required: true + schema: + $ref: '../common/schemas/BrowseParams.yml#/browseParamsObject' + responses: + '204': + description: No content. + '400': + $ref: '../../common/responses/IndexNotFound.yml' diff --git a/specs/search/helpers/waitForAppTask.yml b/specs/search/helpers/waitForAppTask.yml new file mode 100644 index 00000000000..ea177c3cfce --- /dev/null +++ b/specs/search/helpers/waitForAppTask.yml @@ -0,0 +1,23 @@ +method: + get: + x-helper: true + operationId: waitForAppTask + summary: Wait for application-level operation to complete + description: Wait for a application-level task to complete. + parameters: + - in: query + name: taskID + description: The taskID returned by the operation. + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '../common/schemas/GetTaskResponse.yml' + '400': + $ref: '../../common/responses/IndexNotFound.yml' diff --git a/specs/search/helpers/waitForTask.yml b/specs/search/helpers/waitForTask.yml new file mode 100644 index 00000000000..99ef8c6d25f --- /dev/null +++ b/specs/search/helpers/waitForTask.yml @@ -0,0 +1,34 @@ +method: + get: + x-helper: true + tags: + - Records + operationId: waitForTask + summary: Wait for operation to complete + description: | + Wait for a task to complete to ensure synchronized index updates. + + All Algolia write operations are asynchronous. When you make a request for a write operation, for example, to add or update records in your index, Algolia creates a task on a queue and returns a taskID. The task itself runs separately, depending on the server load. + parameters: + - in: query + name: indexName + description: The name of the index on which the operation was performed. + required: true + schema: + type: string + - in: query + name: taskID + description: The taskID returned by the operation. + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '../common/schemas/GetTaskResponse.yml' + '400': + $ref: '../../common/responses/IndexNotFound.yml' diff --git a/specs/search/paths/advanced/getAppTask.yml b/specs/search/paths/advanced/getAppTask.yml index b9bbe111d55..92d35841723 100644 --- a/specs/search/paths/advanced/getAppTask.yml +++ b/specs/search/paths/advanced/getAppTask.yml @@ -22,14 +22,7 @@ get: content: application/json: schema: - title: getTaskResponse - type: object - additionalProperties: false - properties: - status: - $ref: '../../../common/responses/common.yml#/taskStatus' - required: - - status + $ref: '../../common/schemas/GetTaskResponse.yml' '400': $ref: '../../../common/responses/BadRequest.yml' '402': diff --git a/specs/search/paths/advanced/getTask.yml b/specs/search/paths/advanced/getTask.yml index 255ddeaabad..05feacb4bcf 100644 --- a/specs/search/paths/advanced/getTask.yml +++ b/specs/search/paths/advanced/getTask.yml @@ -29,14 +29,7 @@ get: content: application/json: schema: - title: getTaskResponse - type: object - additionalProperties: false - properties: - status: - $ref: '../../../common/responses/common.yml#/taskStatus' - required: - - status + $ref: '../../common/schemas/GetTaskResponse.yml' '400': $ref: '../../../common/responses/BadRequest.yml' '402': diff --git a/specs/search/spec.yml b/specs/search/spec.yml index 801722c8f5d..fb72c592074 100644 --- a/specs/search/spec.yml +++ b/specs/search/spec.yml @@ -361,6 +361,15 @@ paths: /waitForApiKey: $ref: 'helpers/waitForApiKey.yml#/method' + /waitForTask: + $ref: 'helpers/waitForTask.yml#/method' + + /waitForAppTask: + $ref: 'helpers/waitForAppTask.yml#/method' + + /browseObjects: + $ref: 'helpers/browseObjects.yml#/method' + /generateSecuredApiKey: $ref: 'helpers/generateSecuredApiKey.yml#/method' diff --git a/templates/go/search_helpers.mustache b/templates/go/search_helpers.mustache index e7d684f9a7c..65d96e87673 100644 --- a/templates/go/search_helpers.mustache +++ b/templates/go/search_helpers.mustache @@ -108,7 +108,7 @@ func (c *APIClient) WaitForTask( taskID int64, opts ...IterableOption, ) (*GetTaskResponse, error) { - // provide a defalut timeout function + // provide a default timeout function opts = append([]IterableOption{WithTimeout(func(count int) time.Duration { return time.Duration(min(200*count, 5000)) * time.Millisecond }), WithMaxRetries(50)}, opts...) @@ -142,7 +142,7 @@ func (c *APIClient) WaitForAppTask( taskID int64, opts ...IterableOption, ) (*GetTaskResponse, error) { - // provide a defalut timeout function + // provide a default timeout function opts = append([]IterableOption{WithTimeout(func(count int) time.Duration { return time.Duration(min(200*count, 5000)) * time.Millisecond }), WithMaxRetries(50)}, opts...) @@ -276,7 +276,7 @@ func (c *APIClient) WaitForApiKey( } - // provide a defalut timeout function + // provide a default timeout function opts = append([]WaitForApiKeyOption{WithTimeout(func(count int) time.Duration { return time.Duration(min(200*count, 5000)) * time.Millisecond }), WithMaxRetries(50)}, opts...) diff --git a/templates/java/api_helpers.mustache b/templates/java/api_helpers.mustache index 802b4d16cc3..a04a651067f 100644 --- a/templates/java/api_helpers.mustache +++ b/templates/java/api_helpers.mustache @@ -8,8 +8,8 @@ * @param timeout The function to decide how long to wait between retries. min(retries * 200, 5000) by default. (optional) * @param requestOptions The requestOptions to send along with the query, they will be merged with the transporter requestOptions. (optional) */ -public void waitForTask(String indexName, Long taskID, int maxRetries, IntUnaryOperator timeout, RequestOptions requestOptions) { - TaskUtils.retryUntil( +public GetTaskResponse waitForTask(String indexName, Long taskID, int maxRetries, IntUnaryOperator timeout, RequestOptions requestOptions) { + return TaskUtils.retryUntil( () -> this.getTask(indexName, taskID, requestOptions), (GetTaskResponse task) -> task.getStatus() == TaskStatus.PUBLISHED, maxRetries, @@ -24,8 +24,8 @@ public void waitForTask(String indexName, Long taskID, int maxRetries, IntUnaryO * @param taskID The `taskID` returned in the method response. * @param requestOptions The requestOptions to send along with the query, they will be merged with the transporter requestOptions. (optional) */ -public void waitForTask(String indexName, Long taskID, RequestOptions requestOptions) { - this.waitForTask(indexName, taskID, TaskUtils.DEFAULT_MAX_RETRIES, TaskUtils.DEFAULT_TIMEOUT, requestOptions); +public GetTaskResponse waitForTask(String indexName, Long taskID, RequestOptions requestOptions) { + return this.waitForTask(indexName, taskID, TaskUtils.DEFAULT_MAX_RETRIES, TaskUtils.DEFAULT_TIMEOUT, requestOptions); } /** @@ -36,8 +36,8 @@ public void waitForTask(String indexName, Long taskID, RequestOptions requestOpt * @param maxRetries The maximum number of retry. 50 by default. (optional) * @param timeout The function to decide how long to wait between retries. min(retries * 200, 5000) by default. (optional) */ -public void waitForTask(String indexName, Long taskID, int maxRetries, IntUnaryOperator timeout) { - this.waitForTask(indexName, taskID, maxRetries, timeout, null); +public GetTaskResponse waitForTask(String indexName, Long taskID, int maxRetries, IntUnaryOperator timeout) { + return this.waitForTask(indexName, taskID, maxRetries, timeout, null); } /** @@ -46,8 +46,8 @@ public void waitForTask(String indexName, Long taskID, int maxRetries, IntUnaryO * @param indexName The `indexName` where the operation was performed. * @param taskID The `taskID` returned in the method response. */ -public void waitForTask(String indexName, Long taskID) { - this.waitForTask(indexName, taskID, TaskUtils.DEFAULT_MAX_RETRIES, TaskUtils.DEFAULT_TIMEOUT, null); +public GetTaskResponse waitForTask(String indexName, Long taskID) { + return this.waitForTask(indexName, taskID, TaskUtils.DEFAULT_MAX_RETRIES, TaskUtils.DEFAULT_TIMEOUT, null); } /** @@ -60,8 +60,8 @@ public void waitForTask(String indexName, Long taskID) { * @param requestOptions The requestOptions to send along with the query, they will be merged with * the transporter requestOptions. (optional) */ -public void waitForAppTask(Long taskID, int maxRetries, IntUnaryOperator timeout, RequestOptions requestOptions) { -TaskUtils.retryUntil( +public GetTaskResponse waitForAppTask(Long taskID, int maxRetries, IntUnaryOperator timeout, RequestOptions requestOptions) { +return TaskUtils.retryUntil( () -> this.getAppTask(taskID, requestOptions), (GetTaskResponse task) -> task.getStatus() == TaskStatus.PUBLISHED, maxRetries, @@ -76,8 +76,8 @@ TaskUtils.retryUntil( * @param requestOptions The requestOptions to send along with the query, they will be merged with * the transporter requestOptions. (optional) */ -public void waitForAppTask(Long taskID, RequestOptions requestOptions) { -this.waitForAppTask(taskID, TaskUtils.DEFAULT_MAX_RETRIES, TaskUtils.DEFAULT_TIMEOUT, requestOptions); +public GetTaskResponse waitForAppTask(Long taskID, RequestOptions requestOptions) { + return this.waitForAppTask(taskID, TaskUtils.DEFAULT_MAX_RETRIES, TaskUtils.DEFAULT_TIMEOUT, requestOptions); } /** @@ -88,8 +88,8 @@ this.waitForAppTask(taskID, TaskUtils.DEFAULT_MAX_RETRIES, TaskUtils.DEFAULT_TIM * @param timeout The function to decide how long to wait between retries. min(retries * 200, * 5000) by default. (optional) */ -public void waitForAppTask(Long taskID, int maxRetries, IntUnaryOperator timeout) { -this.waitForAppTask(taskID, maxRetries, timeout, null); +public GetTaskResponse waitForAppTask(Long taskID, int maxRetries, IntUnaryOperator timeout) { + return this.waitForAppTask(taskID, maxRetries, timeout, null); } /** @@ -97,8 +97,8 @@ this.waitForAppTask(taskID, maxRetries, timeout, null); * * @param taskID The `taskID` returned in the method response. */ -public void waitForAppTask(Long taskID) { -this.waitForAppTask(taskID, TaskUtils.DEFAULT_MAX_RETRIES, TaskUtils.DEFAULT_TIMEOUT, null); +public GetTaskResponse waitForAppTask(Long taskID) { + return this.waitForAppTask(taskID, TaskUtils.DEFAULT_MAX_RETRIES, TaskUtils.DEFAULT_TIMEOUT, null); } /** diff --git a/tests/CTS/client/search/browseObjects.json b/tests/CTS/client/search/browseObjects.json new file mode 100644 index 00000000000..c93255fdb2f --- /dev/null +++ b/tests/CTS/client/search/browseObjects.json @@ -0,0 +1,33 @@ +[ + { + "autoCreateClient": false, + "steps": [ + { + "type": "createClient", + "parameters": { + "appId": "test-app-id", + "apiKey": "test-api-key", + "customHosts": [ + { + "host": "${{localhost}}", + "port": 6681 + } + ] + } + }, + { + "type": "method", + "method": "browseObjects", + "parameters": { + "indexName": "browse-objects-${{language}}", + "browseParams": { + "query": "batman", + "facets": [ + "year" + ] + } + } + } + ] + } +] diff --git a/tests/CTS/client/search/deleteObjects.json b/tests/CTS/client/search/deleteObjects.json new file mode 100644 index 00000000000..5a807fcdc69 --- /dev/null +++ b/tests/CTS/client/search/deleteObjects.json @@ -0,0 +1,44 @@ +[ + { + "testName": "call deleteObjects without error", + "autoCreateClient": false, + "steps": [ + { + "type": "createClient", + "parameters": { + "appId": "test-app-id", + "apiKey": "test-api-key", + "customHosts": [ + { + "host": "${{localhost}}", + "port": 6680 + } + ] + } + }, + { + "type": "method", + "method": "deleteObjects", + "parameters": { + "indexName": "cts_e2e_deleteObjects_${{language}}", + "objectIDs": [ + "1", + "2" + ] + }, + "expected": { + "type": "response", + "match": [ + { + "taskID": 666, + "objectIDs": [ + "1", + "2" + ] + } + ] + } + } + ] + } +] diff --git a/tests/CTS/client/search/generateSecuredApiKey.json b/tests/CTS/client/search/generateSecuredApiKey.json new file mode 100644 index 00000000000..046c0e13c13 --- /dev/null +++ b/tests/CTS/client/search/generateSecuredApiKey.json @@ -0,0 +1,61 @@ +[ + { + "testName": "generate secured api key basic", + "steps": [ + { + "type": "method", + "method": "generateSecuredApiKey", + "parameters": { + "parentApiKey": "2640659426d5107b6e47d75db9cbaef8", + "restrictions": { + "validUntil": 2524604400, + "restrictIndices": [ + "Movies" + ] + } + }, + "expected": { + "type": "response", + "match": "NjFhZmE0OGEyMTI3OThiODc0OTlkOGM0YjcxYzljY2M2NmU2NDE5ZWY0NDZjMWJhNjA2NzBkMjAwOTI2YWQyZnJlc3RyaWN0SW5kaWNlcz1Nb3ZpZXMmdmFsaWRVbnRpbD0yNTI0NjA0NDAw" + } + } + ] + }, + { + "testName": "generate secured api key with searchParams", + "steps": [ + { + "type": "method", + "method": "generateSecuredApiKey", + "parameters": { + "parentApiKey": "2640659426d5107b6e47d75db9cbaef8", + "restrictions": { + "validUntil": 2524604400, + "restrictIndices": [ + "Movies", + "cts_e2e_settings" + ], + "restrictSources": "192.168.1.0/24", + "filters": "category:Book OR category:Ebook AND _tags:published", + "userToken": "user123", + "searchParams": { + "query": "batman", + "typoTolerance": "strict", + "aroundRadius": "all", + "mode": "neuralSearch", + "hitsPerPage": 10, + "optionalWords": [ + "one", + "two" + ] + } + } + }, + "expected": { + "type": "response", + "match": "MzAxMDUwYjYyODMxODQ3ZWM1ZDYzNTkxZmNjNDg2OGZjMjAzYjQyOTZhMGQ1NDJhMDFiNGMzYTYzODRhNmMxZWFyb3VuZFJhZGl1cz1hbGwmZmlsdGVycz1jYXRlZ29yeSUzQUJvb2slMjBPUiUyMGNhdGVnb3J5JTNBRWJvb2slMjBBTkQlMjBfdGFncyUzQXB1Ymxpc2hlZCZoaXRzUGVyUGFnZT0xMCZtb2RlPW5ldXJhbFNlYXJjaCZvcHRpb25hbFdvcmRzPW9uZSUyQ3R3byZxdWVyeT1iYXRtYW4mcmVzdHJpY3RJbmRpY2VzPU1vdmllcyUyQ2N0c19lMmVfc2V0dGluZ3MmcmVzdHJpY3RTb3VyY2VzPTE5Mi4xNjguMS4wJTJGMjQmdHlwb1RvbGVyYW5jZT1zdHJpY3QmdXNlclRva2VuPXVzZXIxMjMmdmFsaWRVbnRpbD0yNTI0NjA0NDAw" + } + } + ] + } +] diff --git a/tests/CTS/client/search/helpers.json b/tests/CTS/client/search/helpers.json deleted file mode 100644 index c65f4a713d3..00000000000 --- a/tests/CTS/client/search/helpers.json +++ /dev/null @@ -1,556 +0,0 @@ -[ - { - "testName": "generate secured api key basic", - "steps": [ - { - "type": "method", - "method": "generateSecuredApiKey", - "parameters": { - "parentApiKey": "2640659426d5107b6e47d75db9cbaef8", - "restrictions": { - "validUntil": 2524604400, - "restrictIndices": [ - "Movies" - ] - } - }, - "expected": { - "type": "response", - "match": "NjFhZmE0OGEyMTI3OThiODc0OTlkOGM0YjcxYzljY2M2NmU2NDE5ZWY0NDZjMWJhNjA2NzBkMjAwOTI2YWQyZnJlc3RyaWN0SW5kaWNlcz1Nb3ZpZXMmdmFsaWRVbnRpbD0yNTI0NjA0NDAw" - } - } - ] - }, - { - "testName": "generate secured api key with searchParams", - "steps": [ - { - "type": "method", - "method": "generateSecuredApiKey", - "parameters": { - "parentApiKey": "2640659426d5107b6e47d75db9cbaef8", - "restrictions": { - "validUntil": 2524604400, - "restrictIndices": [ - "Movies", - "cts_e2e_settings" - ], - "restrictSources": "192.168.1.0/24", - "filters": "category:Book OR category:Ebook AND _tags:published", - "userToken": "user123", - "searchParams": { - "query": "batman", - "typoTolerance": "strict", - "aroundRadius": "all", - "mode": "neuralSearch", - "hitsPerPage": 10, - "optionalWords": [ - "one", - "two" - ] - } - } - }, - "expected": { - "type": "response", - "match": "MzAxMDUwYjYyODMxODQ3ZWM1ZDYzNTkxZmNjNDg2OGZjMjAzYjQyOTZhMGQ1NDJhMDFiNGMzYTYzODRhNmMxZWFyb3VuZFJhZGl1cz1hbGwmZmlsdGVycz1jYXRlZ29yeSUzQUJvb2slMjBPUiUyMGNhdGVnb3J5JTNBRWJvb2slMjBBTkQlMjBfdGFncyUzQXB1Ymxpc2hlZCZoaXRzUGVyUGFnZT0xMCZtb2RlPW5ldXJhbFNlYXJjaCZvcHRpb25hbFdvcmRzPW9uZSUyQ3R3byZxdWVyeT1iYXRtYW4mcmVzdHJpY3RJbmRpY2VzPU1vdmllcyUyQ2N0c19lMmVfc2V0dGluZ3MmcmVzdHJpY3RTb3VyY2VzPTE5Mi4xNjguMS4wJTJGMjQmdHlwb1RvbGVyYW5jZT1zdHJpY3QmdXNlclRva2VuPXVzZXIxMjMmdmFsaWRVbnRpbD0yNTI0NjA0NDAw" - } - } - ] - }, - { - "testName": "call replaceAllObjects without error", - "autoCreateClient": false, - "steps": [ - { - "type": "createClient", - "parameters": { - "appId": "test-app-id", - "apiKey": "test-api-key", - "customHosts": [ - { - "host": "${{localhost}}", - "port": 6679 - } - ] - } - }, - { - "type": "method", - "method": "replaceAllObjects", - "parameters": { - "indexName": "cts_e2e_replace_all_objects_${{language}}", - "objects": [ - { - "objectID": "1", - "name": "Adam" - }, - { - "objectID": "2", - "name": "Benoit" - }, - { - "objectID": "3", - "name": "Cyril" - }, - { - "objectID": "4", - "name": "David" - }, - { - "objectID": "5", - "name": "Eva" - }, - { - "objectID": "6", - "name": "Fiona" - }, - { - "objectID": "7", - "name": "Gael" - }, - { - "objectID": "8", - "name": "Hugo" - }, - { - "objectID": "9", - "name": "Igor" - }, - { - "objectID": "10", - "name": "Julia" - } - ], - "batchSize": 3 - }, - "expected": { - "type": "response", - "match": { - "copyOperationResponse": { - "taskID": 125, - "updatedAt": "2021-01-01T00:00:00.000Z" - }, - "batchResponses": [ - { - "taskID": 127, - "objectIDs": [ - "1", - "2", - "3" - ] - }, - { - "taskID": 130, - "objectIDs": [ - "4", - "5", - "6" - ] - }, - { - "taskID": 133, - "objectIDs": [ - "7", - "8", - "9" - ] - }, - { - "taskID": 134, - "objectIDs": [ - "10" - ] - } - ], - "moveOperationResponse": { - "taskID": 777, - "updatedAt": "2021-01-01T00:00:00.000Z" - } - } - } - } - ] - }, - { - "testName": "call saveObjects without error", - "autoCreateClient": false, - "steps": [ - { - "type": "createClient", - "parameters": { - "appId": "test-app-id", - "apiKey": "test-api-key", - "customHosts": [ - { - "host": "${{localhost}}", - "port": 6680 - } - ] - } - }, - { - "type": "method", - "method": "saveObjects", - "parameters": { - "indexName": "cts_e2e_saveObjects_${{language}}", - "objects": [ - { - "objectID": "1", - "name": "Adam" - }, - { - "objectID": "2", - "name": "Benoit" - } - ] - }, - "expected": { - "type": "response", - "match": [ - { - "taskID": 333, - "objectIDs": [ - "1", - "2" - ] - } - ] - } - } - ] - }, - { - "testName": "saveObjects should report errors", - "autoCreateClient": false, - "steps": [ - { - "type": "createClient", - "parameters": { - "appId": "test-app-id", - "apiKey": "wrong-api-key", - "customHosts": [ - { - "host": "${{localhost}}", - "port": 6680 - } - ] - } - }, - { - "type": "method", - "method": "saveObjects", - "parameters": { - "indexName": "cts_e2e_saveObjects_${{language}}", - "objects": [ - { - "objectID": "1", - "name": "Adam" - }, - { - "objectID": "2", - "name": "Benoit" - } - ] - }, - "expected": { - "error": { - "csharp": "{\\\"message\\\":\\\"Invalid Application-ID or API key\\\",\\\"status\\\":403}", - "go": "API error [403] {\\\"message\\\":\\\"Invalid Application-ID or API key\\\",\\\"status\\\":403}", - "java": "Status Code: 403 - {\\\"message\\\":\\\"Invalid Application-ID or API key\\\",\\\"status\\\":403}", - "javascript": "Invalid Application-ID or API key", - "kotlin": "Client request(POST http://${{localhost}}:6680/1/indexes/cts_e2e_saveObjects_kotlin/batch) invalid: 403 Forbidden. Text: \\\"{\\\"message\\\":\\\"Invalid Application-ID or API key\\\",\\\"status\\\":403}\\\"", - "php": "Invalid Application-ID or API key", - "python": "Invalid Application-ID or API key", - "ruby": "Invalid Application-ID or API key", - "scala": "Invalid Application-ID or API key", - "swift": "HTTP error: Status code: 403 Message: Invalid Application-ID or API key" - } - } - } - ] - }, - { - "testName": "call partialUpdateObjects with createIfNotExists=true", - "autoCreateClient": false, - "steps": [ - { - "type": "createClient", - "parameters": { - "appId": "test-app-id", - "apiKey": "test-api-key", - "customHosts": [ - { - "host": "${{localhost}}", - "port": 6680 - } - ] - } - }, - { - "type": "method", - "method": "partialUpdateObjects", - "parameters": { - "indexName": "cts_e2e_partialUpdateObjects_${{language}}", - "objects": [ - { - "objectID": "1", - "name": "Adam" - }, - { - "objectID": "2", - "name": "Benoit" - } - ], - "createIfNotExists": true - }, - "expected": { - "type": "response", - "match": [ - { - "taskID": 444, - "objectIDs": [ - "1", - "2" - ] - } - ] - } - } - ] - }, - { - "testName": "call partialUpdateObjects with createIfNotExists=false", - "autoCreateClient": false, - "steps": [ - { - "type": "createClient", - "parameters": { - "appId": "test-app-id", - "apiKey": "test-api-key", - "customHosts": [ - { - "host": "${{localhost}}", - "port": 6680 - } - ] - } - }, - { - "type": "method", - "method": "partialUpdateObjects", - "parameters": { - "indexName": "cts_e2e_partialUpdateObjects_${{language}}", - "objects": [ - { - "objectID": "3", - "name": "Cyril" - }, - { - "objectID": "4", - "name": "David" - } - ], - "createIfNotExists": false - }, - "expected": { - "type": "response", - "match": [ - { - "taskID": 555, - "objectIDs": [ - "3", - "4" - ] - } - ] - } - } - ] - }, - { - "testName": "call deleteObjects without error", - "autoCreateClient": false, - "steps": [ - { - "type": "createClient", - "parameters": { - "appId": "test-app-id", - "apiKey": "test-api-key", - "customHosts": [ - { - "host": "${{localhost}}", - "port": 6680 - } - ] - } - }, - { - "type": "method", - "method": "deleteObjects", - "parameters": { - "indexName": "cts_e2e_deleteObjects_${{language}}", - "objectIDs": [ - "1", - "2" - ] - }, - "expected": { - "type": "response", - "match": [ - { - "taskID": 666, - "objectIDs": [ - "1", - "2" - ] - } - ] - } - } - ] - }, - { - "testName": "wait for api key helper - add", - "autoCreateClient": false, - "steps": [ - { - "type": "createClient", - "parameters": { - "appId": "test-app-id", - "apiKey": "test-api-key", - "customHosts": [ - { - "host": "${{localhost}}", - "port": 6681 - } - ] - } - }, - { - "type": "method", - "method": "waitForApiKey", - "parameters": { - "key": "api-key-add-operation-test-${{language}}", - "operation": "add" - }, - "expected": { - "type": "response", - "match": { - "value": "api-key-add-operation-test-${{language}}", - "description": "my new api key", - "acl": [ - "search", - "addObject" - ], - "validity": 300, - "maxQueriesPerIPPerHour": 100, - "maxHitsPerQuery": 20, - "createdAt": 1720094400 - } - } - } - ] - }, - { - "testName": "wait for api key - update", - "autoCreateClient": false, - "steps": [ - { - "type": "createClient", - "parameters": { - "appId": "test-app-id", - "apiKey": "test-api-key", - "customHosts": [ - { - "host": "${{localhost}}", - "port": 6681 - } - ] - } - }, - { - "type": "method", - "method": "waitForApiKey", - "parameters": { - "key": "api-key-update-operation-test-${{language}}", - "operation": "update", - "apiKey": { - "description": "my updated api key", - "acl": [ - "search", - "addObject", - "deleteObject" - ], - "indexes": [ - "Movies", - "Books" - ], - "referers": [ - "*google.com", - "*algolia.com" - ], - "validity": 305, - "maxQueriesPerIPPerHour": 95, - "maxHitsPerQuery": 20 - } - }, - "expected": { - "type": "response", - "match": { - "value": "api-key-update-operation-test-${{language}}", - "description": "my updated api key", - "acl": [ - "search", - "addObject", - "deleteObject" - ], - "indexes": [ - "Movies", - "Books" - ], - "referers": [ - "*google.com", - "*algolia.com" - ], - "validity": 305, - "maxQueriesPerIPPerHour": 95, - "maxHitsPerQuery": 20, - "createdAt": 1720094400 - } - } - } - ] - }, - { - "testName": "wait for api key - delete", - "autoCreateClient": false, - "steps": [ - { - "type": "createClient", - "parameters": { - "appId": "test-app-id", - "apiKey": "test-api-key", - "customHosts": [ - { - "host": "${{localhost}}", - "port": 6681 - } - ] - } - }, - { - "type": "method", - "method": "waitForApiKey", - "parameters": { - "key": "api-key-delete-operation-test-${{language}}", - "operation": "delete" - }, - "expected": { - "type": "response", - "match": null - } - } - ] - } -] diff --git a/tests/CTS/client/search/partialUpdateObjects.json b/tests/CTS/client/search/partialUpdateObjects.json new file mode 100644 index 00000000000..56f9a5d9887 --- /dev/null +++ b/tests/CTS/client/search/partialUpdateObjects.json @@ -0,0 +1,100 @@ +[ + { + "testName": "call partialUpdateObjects with createIfNotExists=true", + "autoCreateClient": false, + "steps": [ + { + "type": "createClient", + "parameters": { + "appId": "test-app-id", + "apiKey": "test-api-key", + "customHosts": [ + { + "host": "${{localhost}}", + "port": 6680 + } + ] + } + }, + { + "type": "method", + "method": "partialUpdateObjects", + "parameters": { + "indexName": "cts_e2e_partialUpdateObjects_${{language}}", + "objects": [ + { + "objectID": "1", + "name": "Adam" + }, + { + "objectID": "2", + "name": "Benoit" + } + ], + "createIfNotExists": true + }, + "expected": { + "type": "response", + "match": [ + { + "taskID": 444, + "objectIDs": [ + "1", + "2" + ] + } + ] + } + } + ] + }, + { + "testName": "call partialUpdateObjects with createIfNotExists=false", + "autoCreateClient": false, + "steps": [ + { + "type": "createClient", + "parameters": { + "appId": "test-app-id", + "apiKey": "test-api-key", + "customHosts": [ + { + "host": "${{localhost}}", + "port": 6680 + } + ] + } + }, + { + "type": "method", + "method": "partialUpdateObjects", + "parameters": { + "indexName": "cts_e2e_partialUpdateObjects_${{language}}", + "objects": [ + { + "objectID": "3", + "name": "Cyril" + }, + { + "objectID": "4", + "name": "David" + } + ], + "createIfNotExists": false + }, + "expected": { + "type": "response", + "match": [ + { + "taskID": 555, + "objectIDs": [ + "3", + "4" + ] + } + ] + } + } + ] + } +] diff --git a/tests/CTS/client/search/replaceAllObjects.json b/tests/CTS/client/search/replaceAllObjects.json new file mode 100644 index 00000000000..e2dff2b0979 --- /dev/null +++ b/tests/CTS/client/search/replaceAllObjects.json @@ -0,0 +1,116 @@ +[ + { + "testName": "call replaceAllObjects without error", + "autoCreateClient": false, + "steps": [ + { + "type": "createClient", + "parameters": { + "appId": "test-app-id", + "apiKey": "test-api-key", + "customHosts": [ + { + "host": "${{localhost}}", + "port": 6679 + } + ] + } + }, + { + "type": "method", + "method": "replaceAllObjects", + "parameters": { + "indexName": "cts_e2e_replace_all_objects_${{language}}", + "objects": [ + { + "objectID": "1", + "name": "Adam" + }, + { + "objectID": "2", + "name": "Benoit" + }, + { + "objectID": "3", + "name": "Cyril" + }, + { + "objectID": "4", + "name": "David" + }, + { + "objectID": "5", + "name": "Eva" + }, + { + "objectID": "6", + "name": "Fiona" + }, + { + "objectID": "7", + "name": "Gael" + }, + { + "objectID": "8", + "name": "Hugo" + }, + { + "objectID": "9", + "name": "Igor" + }, + { + "objectID": "10", + "name": "Julia" + } + ], + "batchSize": 3 + }, + "expected": { + "type": "response", + "match": { + "copyOperationResponse": { + "taskID": 125, + "updatedAt": "2021-01-01T00:00:00.000Z" + }, + "batchResponses": [ + { + "taskID": 127, + "objectIDs": [ + "1", + "2", + "3" + ] + }, + { + "taskID": 130, + "objectIDs": [ + "4", + "5", + "6" + ] + }, + { + "taskID": 133, + "objectIDs": [ + "7", + "8", + "9" + ] + }, + { + "taskID": 134, + "objectIDs": [ + "10" + ] + } + ], + "moveOperationResponse": { + "taskID": 777, + "updatedAt": "2021-01-01T00:00:00.000Z" + } + } + } + } + ] + } +] diff --git a/tests/CTS/client/search/saveObjects.json b/tests/CTS/client/search/saveObjects.json new file mode 100644 index 00000000000..6c44b57aa4c --- /dev/null +++ b/tests/CTS/client/search/saveObjects.json @@ -0,0 +1,100 @@ +[ + { + "testName": "call saveObjects without error", + "autoCreateClient": false, + "steps": [ + { + "type": "createClient", + "parameters": { + "appId": "test-app-id", + "apiKey": "test-api-key", + "customHosts": [ + { + "host": "${{localhost}}", + "port": 6680 + } + ] + } + }, + { + "type": "method", + "method": "saveObjects", + "parameters": { + "indexName": "cts_e2e_saveObjects_${{language}}", + "objects": [ + { + "objectID": "1", + "name": "Adam" + }, + { + "objectID": "2", + "name": "Benoit" + } + ] + }, + "expected": { + "type": "response", + "match": [ + { + "taskID": 333, + "objectIDs": [ + "1", + "2" + ] + } + ] + } + } + ] + }, + { + "testName": "saveObjects should report errors", + "autoCreateClient": false, + "steps": [ + { + "type": "createClient", + "parameters": { + "appId": "test-app-id", + "apiKey": "wrong-api-key", + "customHosts": [ + { + "host": "${{localhost}}", + "port": 6680 + } + ] + } + }, + { + "type": "method", + "method": "saveObjects", + "parameters": { + "indexName": "cts_e2e_saveObjects_${{language}}", + "objects": [ + { + "objectID": "1", + "name": "Adam" + }, + { + "objectID": "2", + "name": "Benoit" + } + ] + }, + "expected": { + "error": { + "csharp": "{\\\"message\\\":\\\"Invalid Application-ID or API key\\\",\\\"status\\\":403}", + "go": "API error [403] {\\\"message\\\":\\\"Invalid Application-ID or API key\\\",\\\"status\\\":403}", + "java": "Status Code: 403 - {\\\"message\\\":\\\"Invalid Application-ID or API key\\\",\\\"status\\\":403}", + "javascript": "Invalid Application-ID or API key", + "kotlin": "Client request(POST http://${{localhost}}:6680/1/indexes/cts_e2e_saveObjects_kotlin/batch) invalid: 403 Forbidden. Text: \\\"{\\\"message\\\":\\\"Invalid Application-ID or API key\\\",\\\"status\\\":403}\\\"", + "php": "Invalid Application-ID or API key", + "python": "Invalid Application-ID or API key", + "ruby": "Invalid Application-ID or API key", + "scala": "Invalid Application-ID or API key", + "swift": "HTTP error: Status code: 403 Message: Invalid Application-ID or API key" + } + } + } + ] + } +] diff --git a/tests/CTS/client/search/waitForApiKey.json b/tests/CTS/client/search/waitForApiKey.json new file mode 100644 index 00000000000..9d3339cdf90 --- /dev/null +++ b/tests/CTS/client/search/waitForApiKey.json @@ -0,0 +1,145 @@ +[ + { + "testName": "wait for api key helper - add", + "autoCreateClient": false, + "steps": [ + { + "type": "createClient", + "parameters": { + "appId": "test-app-id", + "apiKey": "test-api-key", + "customHosts": [ + { + "host": "${{localhost}}", + "port": 6681 + } + ] + } + }, + { + "type": "method", + "method": "waitForApiKey", + "parameters": { + "key": "api-key-add-operation-test-${{language}}", + "operation": "add" + }, + "expected": { + "type": "response", + "match": { + "value": "api-key-add-operation-test-${{language}}", + "description": "my new api key", + "acl": [ + "search", + "addObject" + ], + "validity": 300, + "maxQueriesPerIPPerHour": 100, + "maxHitsPerQuery": 20, + "createdAt": 1720094400 + } + } + } + ] + }, + { + "testName": "wait for api key - update", + "autoCreateClient": false, + "steps": [ + { + "type": "createClient", + "parameters": { + "appId": "test-app-id", + "apiKey": "test-api-key", + "customHosts": [ + { + "host": "${{localhost}}", + "port": 6681 + } + ] + } + }, + { + "type": "method", + "method": "waitForApiKey", + "parameters": { + "key": "api-key-update-operation-test-${{language}}", + "operation": "update", + "apiKey": { + "description": "my updated api key", + "acl": [ + "search", + "addObject", + "deleteObject" + ], + "indexes": [ + "Movies", + "Books" + ], + "referers": [ + "*google.com", + "*algolia.com" + ], + "validity": 305, + "maxQueriesPerIPPerHour": 95, + "maxHitsPerQuery": 20 + } + }, + "expected": { + "type": "response", + "match": { + "value": "api-key-update-operation-test-${{language}}", + "description": "my updated api key", + "acl": [ + "search", + "addObject", + "deleteObject" + ], + "indexes": [ + "Movies", + "Books" + ], + "referers": [ + "*google.com", + "*algolia.com" + ], + "validity": 305, + "maxQueriesPerIPPerHour": 95, + "maxHitsPerQuery": 20, + "createdAt": 1720094400 + } + } + } + ] + }, + { + "testName": "wait for api key - delete", + "autoCreateClient": false, + "steps": [ + { + "type": "createClient", + "parameters": { + "appId": "test-app-id", + "apiKey": "test-api-key", + "customHosts": [ + { + "host": "${{localhost}}", + "port": 6681 + } + ] + } + }, + { + "type": "method", + "method": "waitForApiKey", + "parameters": { + "key": "api-key-delete-operation-test-${{language}}", + "operation": "delete" + }, + "expected": { + "type": "response", + "match": null + } + } + ] + } +] diff --git a/tests/CTS/client/search/waitForAppTask.json b/tests/CTS/client/search/waitForAppTask.json new file mode 100644 index 00000000000..c9bba741170 --- /dev/null +++ b/tests/CTS/client/search/waitForAppTask.json @@ -0,0 +1,34 @@ +[ + { + "testName": "wait for an application-level task", + "autoCreateClient": false, + "steps": [ + { + "type": "createClient", + "parameters": { + "appId": "test-app-id", + "apiKey": "test-api-key", + "customHosts": [ + { + "host": "${{localhost}}", + "port": 6681 + } + ] + } + }, + { + "type": "method", + "method": "waitForAppTask", + "parameters": { + "taskID": 123 + }, + "expected": { + "type": "response", + "match": { + "status": "published" + } + } + } + ] + } +] diff --git a/tests/CTS/client/search/waitForTask.json b/tests/CTS/client/search/waitForTask.json new file mode 100644 index 00000000000..08af95e1058 --- /dev/null +++ b/tests/CTS/client/search/waitForTask.json @@ -0,0 +1,35 @@ +[ + { + "testName": "wait for task", + "autoCreateClient": false, + "steps": [ + { + "type": "createClient", + "parameters": { + "appId": "test-app-id", + "apiKey": "test-api-key", + "customHosts": [ + { + "host": "${{localhost}}", + "port": 6681 + } + ] + } + }, + { + "type": "method", + "method": "waitForTask", + "parameters": { + "indexName": "wait-task-${{language}}", + "taskID": 123 + }, + "expected": { + "type": "response", + "match": { + "status": "published" + } + } + } + ] + } +]